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 random | |
| 19 import re | 20 import re |
| 20 import subprocess | 21 import subprocess |
| 21 import sys | 22 import sys |
| 22 import time | 23 import time |
| 23 | 24 |
| 24 from devil.android import battery_utils | 25 from devil.android import battery_utils |
| 25 from devil.android import device_blacklist | 26 from devil.android import device_blacklist |
| 26 from devil.android import device_errors | 27 from devil.android import device_errors |
| 27 from devil.android import device_utils | 28 from devil.android import device_utils |
| 28 from devil.android.sdk import version_codes | 29 from devil.android.sdk import version_codes |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 92 device.WaitUntilFullyBooted(timeout=reboot_timeout, retries=0) | 93 device.WaitUntilFullyBooted(timeout=reboot_timeout, retries=0) |
| 93 except device_errors.CommandTimeoutError: | 94 except device_errors.CommandTimeoutError: |
| 94 logging.error('Device did not finish booting. Will try to reboot.') | 95 logging.error('Device did not finish booting. Will try to reboot.') |
| 95 device.Reboot(timeout=reboot_timeout) | 96 device.Reboot(timeout=reboot_timeout) |
| 96 phase_func(device, options) | 97 phase_func(device, options) |
| 97 if reboot: | 98 if reboot: |
| 98 device.Reboot(False, retries=0) | 99 device.Reboot(False, retries=0) |
| 99 device.adb.WaitForDevice() | 100 device.adb.WaitForDevice() |
| 100 | 101 |
| 101 try: | 102 try: |
| 103 CheckExternalStorage(device) | |
| 102 if should_run_phase(_PHASES.WIPE): | 104 if should_run_phase(_PHASES.WIPE): |
| 103 if options.chrome_specific_wipe: | 105 if options.chrome_specific_wipe: |
| 104 run_phase(WipeChromeData) | 106 run_phase(WipeChromeData) |
| 105 else: | 107 else: |
| 106 run_phase(WipeDevice) | 108 run_phase(WipeDevice) |
| 107 | 109 |
| 108 if should_run_phase(_PHASES.PROPERTIES): | 110 if should_run_phase(_PHASES.PROPERTIES): |
| 109 run_phase(SetProperties) | 111 run_phase(SetProperties) |
| 110 | 112 |
| 111 if should_run_phase(_PHASES.FINISH): | 113 if should_run_phase(_PHASES.FINISH): |
| 112 run_phase(FinishProvisioning, reboot=False) | 114 run_phase(FinishProvisioning, reboot=False) |
| 113 | 115 |
| 114 if options.chrome_specific_wipe: | 116 if options.chrome_specific_wipe: |
| 115 package = "com.google.android.gms" | 117 package = "com.google.android.gms" |
| 116 version_name = device.GetApplicationVersion(package) | 118 version_name = device.GetApplicationVersion(package) |
| 117 logging.info("Version name for %s is %s", package, version_name) | 119 logging.info("Version name for %s is %s", package, version_name) |
| 118 | 120 |
| 119 except device_errors.CommandTimeoutError: | 121 except device_errors.CommandTimeoutError: |
| 120 logging.exception('Timed out waiting for device %s. Adding to blacklist.', | 122 logging.exception('Timed out waiting for device %s. Adding to blacklist.', |
| 121 str(device)) | 123 str(device)) |
| 122 blacklist.Extend([str(device)]) | 124 blacklist.Extend([str(device)]) |
| 123 | 125 |
| 124 except device_errors.CommandFailedError: | 126 except device_errors.CommandFailedError: |
| 125 logging.exception('Failed to provision device %s. Adding to blacklist.', | 127 logging.exception('Failed to provision device %s. Adding to blacklist.', |
| 126 str(device)) | 128 str(device)) |
| 127 blacklist.Extend([str(device)]) | 129 blacklist.Extend([str(device)]) |
| 128 | 130 |
| 131 def CheckExternalStorage(device): | |
| 132 """Checks that storage is writable and if not makes it writable. | |
| 133 | |
| 134 Arguments: | |
| 135 device: The device to check. | |
| 136 """ | |
| 137 # Write a file with random name to $EXTERNAL_STORAGE to test writability. | |
|
jbudorick
2015/09/28 18:01:17
Use DeviceTempFile with dir=device.GetExternalStor
rnephew (Reviews Here)
2015/09/28 18:34:06
Done.
| |
| 138 file_path = ( | |
| 139 device.GetExternalStoragePath() + '/' + str(random.randint(0, 9999999))) | |
| 140 try: | |
| 141 device.WriteFile(file_path, 'test') | |
| 142 except device_errors.CommandFailedError: | |
| 143 logging.info('External storage not writable. Remounting / as RW') | |
| 144 device.RunShellCommand(['mount', '-o', 'remount,rw', '/'], | |
| 145 check_return=True, as_root=True) | |
| 146 device.WriteFile(file_path, 'test') | |
| 147 finally: | |
| 148 device.RunShellCommand(['rm', file_path], check_return=True) | |
| 129 | 149 |
| 130 def WipeChromeData(device, options): | 150 def WipeChromeData(device, options): |
| 131 """Wipes chrome specific data from device | 151 """Wipes chrome specific data from device |
| 132 | 152 |
| 133 (1) uninstall any app whose name matches *chrom*, except | 153 (1) uninstall any app whose name matches *chrom*, except |
| 134 com.android.chrome, which is the chrome stable package. Doing so also | 154 com.android.chrome, which is the chrome stable package. Doing so also |
| 135 removes the corresponding dirs under /data/data/ and /data/app/ | 155 removes the corresponding dirs under /data/data/ and /data/app/ |
| 136 (2) remove any dir under /data/app-lib/ whose name matches *chrom* | 156 (2) remove any dir under /data/app-lib/ whose name matches *chrom* |
| 137 (3) remove any files under /data/tombstones/ whose name matches "tombstone*" | 157 (3) remove any files under /data/tombstones/ whose name matches "tombstone*" |
| 138 (4) remove /data/local.prop if there is any | 158 (4) remove /data/local.prop if there is any |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 385 | 405 |
| 386 | 406 |
| 387 def _LaunchHostHeartbeat(): | 407 def _LaunchHostHeartbeat(): |
| 388 # Kill if existing host_heartbeat | 408 # Kill if existing host_heartbeat |
| 389 KillHostHeartbeat() | 409 KillHostHeartbeat() |
| 390 # Launch a new host_heartbeat | 410 # Launch a new host_heartbeat |
| 391 logging.info('Spawning host heartbeat...') | 411 logging.info('Spawning host heartbeat...') |
| 392 subprocess.Popen([os.path.join(constants.DIR_SOURCE_ROOT, | 412 subprocess.Popen([os.path.join(constants.DIR_SOURCE_ROOT, |
| 393 'build/android/host_heartbeat.py')]) | 413 'build/android/host_heartbeat.py')]) |
| 394 | 414 |
| 395 | |
| 396 def KillHostHeartbeat(): | 415 def KillHostHeartbeat(): |
| 397 ps = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE) | 416 ps = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE) |
| 398 stdout, _ = ps.communicate() | 417 stdout, _ = ps.communicate() |
| 399 matches = re.findall('\\n.*host_heartbeat.*', stdout) | 418 matches = re.findall('\\n.*host_heartbeat.*', stdout) |
| 400 for match in matches: | 419 for match in matches: |
| 401 logging.info('An instance of host heart beart running... will kill') | 420 logging.info('An instance of host heart beart running... will kill') |
| 402 pid = re.findall(r'(\S+)', match)[1] | 421 pid = re.findall(r'(\S+)', match)[1] |
| 403 subprocess.call(['kill', str(pid)]) | 422 subprocess.call(['kill', str(pid)]) |
| 404 | 423 |
| 405 | |
| 406 def main(): | 424 def main(): |
| 407 # Recommended options on perf bots: | 425 # Recommended options on perf bots: |
| 408 # --disable-network | 426 # --disable-network |
| 409 # TODO(tonyg): We eventually want network on. However, currently radios | 427 # TODO(tonyg): We eventually want network on. However, currently radios |
| 410 # can cause perfbots to drain faster than they charge. | 428 # can cause perfbots to drain faster than they charge. |
| 411 # --min-battery-level 95 | 429 # --min-battery-level 95 |
| 412 # Some perf bots run benchmarks with USB charging disabled which leads | 430 # Some perf bots run benchmarks with USB charging disabled which leads |
| 413 # to gradual draining of the battery. We must wait for a full charge | 431 # to gradual draining of the battery. We must wait for a full charge |
| 414 # before starting a run in order to keep the devices online. | 432 # before starting a run in order to keep the devices online. |
| 415 | 433 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 463 args = parser.parse_args() | 481 args = parser.parse_args() |
| 464 constants.SetBuildType(args.target) | 482 constants.SetBuildType(args.target) |
| 465 | 483 |
| 466 run_tests_helper.SetLogLevel(args.verbose) | 484 run_tests_helper.SetLogLevel(args.verbose) |
| 467 | 485 |
| 468 return ProvisionDevices(args) | 486 return ProvisionDevices(args) |
| 469 | 487 |
| 470 | 488 |
| 471 if __name__ == '__main__': | 489 if __name__ == '__main__': |
| 472 sys.exit(main()) | 490 sys.exit(main()) |
| OLD | NEW |