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 import devil_chromium | 24 import devil_chromium |
25 from devil.android import battery_utils | 25 from devil.android import battery_utils |
26 from devil.android import device_blacklist | 26 from devil.android import device_blacklist |
27 from devil.android import device_errors | 27 from devil.android import device_errors |
28 from devil.android import device_temp_file | 28 from devil.android import device_temp_file |
29 from devil.android import device_utils | 29 from devil.android import device_utils |
| 30 from devil.android.sdk import keyevent |
30 from devil.android.sdk import version_codes | 31 from devil.android.sdk import version_codes |
31 from devil.utils import run_tests_helper | 32 from devil.utils import run_tests_helper |
32 from devil.utils import timeout_retry | 33 from devil.utils import timeout_retry |
33 from pylib import constants | 34 from pylib import constants |
34 from pylib import device_settings | 35 from pylib import device_settings |
35 | 36 |
36 _SYSTEM_WEBVIEW_PATHS = ['/system/app/webview', '/system/app/WebViewGoogle'] | 37 _SYSTEM_WEBVIEW_PATHS = ['/system/app/webview', '/system/app/WebViewGoogle'] |
37 _CHROME_PACKAGE_REGEX = re.compile('.*chrom.*') | 38 _CHROME_PACKAGE_REGEX = re.compile('.*chrom.*') |
38 _TOMBSTONE_REGEX = re.compile('tombstone.*') | 39 _TOMBSTONE_REGEX = re.compile('tombstone.*') |
39 | 40 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 except device_errors.CommandTimeoutError: | 98 except device_errors.CommandTimeoutError: |
98 logging.error('Device did not finish booting. Will try to reboot.') | 99 logging.error('Device did not finish booting. Will try to reboot.') |
99 device.Reboot(timeout=reboot_timeout) | 100 device.Reboot(timeout=reboot_timeout) |
100 phase_func(device, options) | 101 phase_func(device, options) |
101 if reboot: | 102 if reboot: |
102 device.Reboot(False, retries=0) | 103 device.Reboot(False, retries=0) |
103 device.adb.WaitForDevice() | 104 device.adb.WaitForDevice() |
104 | 105 |
105 try: | 106 try: |
106 if should_run_phase(_PHASES.WIPE): | 107 if should_run_phase(_PHASES.WIPE): |
107 if (options.chrome_specific_wipe or device.build_version_sdk >= | 108 if (options.chrome_specific_wipe or device.IsUserBuild() or |
108 version_codes.MARSHMALLOW): | 109 device.build_version_sdk >= version_codes.MARSHMALLOW): |
109 run_phase(WipeChromeData) | 110 run_phase(WipeChromeData) |
110 else: | 111 else: |
111 run_phase(WipeDevice) | 112 run_phase(WipeDevice) |
112 | 113 |
113 if should_run_phase(_PHASES.PROPERTIES): | 114 if should_run_phase(_PHASES.PROPERTIES): |
114 run_phase(SetProperties) | 115 run_phase(SetProperties) |
115 | 116 |
116 if should_run_phase(_PHASES.FINISH): | 117 if should_run_phase(_PHASES.FINISH): |
117 run_phase(FinishProvisioning, reboot=False) | 118 run_phase(FinishProvisioning, reboot=False) |
118 | 119 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 (this is telemetry related) | 169 (this is telemetry related) |
169 (7) remove anything under /data/local/tmp/ | 170 (7) remove anything under /data/local/tmp/ |
170 | 171 |
171 Arguments: | 172 Arguments: |
172 device: the device to wipe | 173 device: the device to wipe |
173 """ | 174 """ |
174 if options.skip_wipe: | 175 if options.skip_wipe: |
175 return | 176 return |
176 | 177 |
177 try: | 178 try: |
178 device.EnableRoot() | 179 if device.IsUserBuild(): |
179 _UninstallIfMatch(device, _CHROME_PACKAGE_REGEX, | 180 _UninstallIfMatch(device, _CHROME_PACKAGE_REGEX, |
180 constants.PACKAGE_INFO['chrome_stable'].package) | 181 constants.PACKAGE_INFO['chrome_stable'].package) |
181 _WipeUnderDirIfMatch(device, '/data/app-lib/', _CHROME_PACKAGE_REGEX) | 182 device.RunShellCommand('rm -rf %s/*' % device.GetExternalStoragePath(), |
182 _WipeUnderDirIfMatch(device, '/data/tombstones/', _TOMBSTONE_REGEX) | 183 check_return=True) |
| 184 device.RunShellCommand('rm -rf /data/local/tmp/*', check_return=True) |
| 185 else: |
| 186 device.EnableRoot() |
| 187 _UninstallIfMatch(device, _CHROME_PACKAGE_REGEX, |
| 188 constants.PACKAGE_INFO['chrome_stable'].package) |
| 189 _WipeUnderDirIfMatch(device, '/data/app-lib/', _CHROME_PACKAGE_REGEX) |
| 190 _WipeUnderDirIfMatch(device, '/data/tombstones/', _TOMBSTONE_REGEX) |
183 | 191 |
184 _WipeFileOrDir(device, '/data/local.prop') | 192 _WipeFileOrDir(device, '/data/local.prop') |
185 _WipeFileOrDir(device, '/data/local/chrome-command-line') | 193 _WipeFileOrDir(device, '/data/local/chrome-command-line') |
186 _WipeFileOrDir(device, '/data/local/.config/') | 194 _WipeFileOrDir(device, '/data/local/.config/') |
187 _WipeFileOrDir(device, '/data/local/tmp/') | 195 _WipeFileOrDir(device, '/data/local/tmp/') |
188 | 196 device.RunShellCommand('rm -rf %s/*' % device.GetExternalStoragePath(), |
189 device.RunShellCommand('rm -rf %s/*' % device.GetExternalStoragePath(), | 197 check_return=True) |
190 check_return=True) | |
191 except device_errors.CommandFailedError: | 198 except device_errors.CommandFailedError: |
192 logging.exception('Possible failure while wiping the device. ' | 199 logging.exception('Possible failure while wiping the device. ' |
193 'Attempting to continue.') | 200 'Attempting to continue.') |
194 | 201 |
195 | 202 |
196 def WipeDevice(device, options): | 203 def WipeDevice(device, options): |
197 """Wipes data from device, keeping only the adb_keys for authorization. | 204 """Wipes data from device, keeping only the adb_keys for authorization. |
198 | 205 |
199 After wiping data on a device that has been authorized, adb can still | 206 After wiping data on a device that has been authorized, adb can still |
200 communicate with the device, but after reboot the device will need to be | 207 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... |
243 device.RunShellCommand(['restorecon', constants.ADB_KEYS_FILE], | 250 device.RunShellCommand(['restorecon', constants.ADB_KEYS_FILE], |
244 as_root=True, check_return=True) | 251 as_root=True, check_return=True) |
245 | 252 |
246 | 253 |
247 def SetProperties(device, options): | 254 def SetProperties(device, options): |
248 try: | 255 try: |
249 device.EnableRoot() | 256 device.EnableRoot() |
250 except device_errors.CommandFailedError as e: | 257 except device_errors.CommandFailedError as e: |
251 logging.warning(str(e)) | 258 logging.warning(str(e)) |
252 | 259 |
253 _ConfigureLocalProperties(device, options.enable_java_debug) | 260 if not device.IsUserBuild(): |
| 261 _ConfigureLocalProperties(device, options.enable_java_debug) |
| 262 else: |
| 263 logging.warning('Cannot configure properties in user builds.') |
254 device_settings.ConfigureContentSettings( | 264 device_settings.ConfigureContentSettings( |
255 device, device_settings.DETERMINISTIC_DEVICE_SETTINGS) | 265 device, device_settings.DETERMINISTIC_DEVICE_SETTINGS) |
256 if options.disable_location: | 266 if options.disable_location: |
257 device_settings.ConfigureContentSettings( | 267 device_settings.ConfigureContentSettings( |
258 device, device_settings.DISABLE_LOCATION_SETTINGS) | 268 device, device_settings.DISABLE_LOCATION_SETTINGS) |
259 else: | 269 else: |
260 device_settings.ConfigureContentSettings( | 270 device_settings.ConfigureContentSettings( |
261 device, device_settings.ENABLE_LOCATION_SETTINGS) | 271 device, device_settings.ENABLE_LOCATION_SETTINGS) |
262 | 272 |
263 if options.disable_mock_location: | 273 if options.disable_mock_location: |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
308 '\n'.join(local_props), as_root=True) | 318 '\n'.join(local_props), as_root=True) |
309 # Android will not respect the local props file if it is world writable. | 319 # Android will not respect the local props file if it is world writable. |
310 device.RunShellCommand( | 320 device.RunShellCommand( |
311 ['chmod', '644', device.LOCAL_PROPERTIES_PATH], | 321 ['chmod', '644', device.LOCAL_PROPERTIES_PATH], |
312 as_root=True, check_return=True) | 322 as_root=True, check_return=True) |
313 except device_errors.CommandFailedError: | 323 except device_errors.CommandFailedError: |
314 logging.exception('Failed to configure local properties.') | 324 logging.exception('Failed to configure local properties.') |
315 | 325 |
316 | 326 |
317 def FinishProvisioning(device, options): | 327 def FinishProvisioning(device, options): |
| 328 # The lockscreen can't be disabled on user builds, so send a keyevent |
| 329 # to unlock it. |
| 330 if device.IsUserBuild(): |
| 331 device.SendKeyEvent(keyevent.KEYCODE_MENU) |
| 332 |
318 if options.min_battery_level is not None: | 333 if options.min_battery_level is not None: |
319 try: | 334 try: |
320 battery = battery_utils.BatteryUtils(device) | 335 battery = battery_utils.BatteryUtils(device) |
321 battery.ChargeDeviceToLevel(options.min_battery_level) | 336 battery.ChargeDeviceToLevel(options.min_battery_level) |
322 except device_errors.CommandFailedError: | 337 except device_errors.CommandFailedError: |
323 logging.exception('Unable to charge device to specified level.') | 338 logging.exception('Unable to charge device to specified level.') |
324 | 339 |
325 if options.max_battery_temp is not None: | 340 if options.max_battery_temp is not None: |
326 try: | 341 try: |
327 battery = battery_utils.BatteryUtils(device) | 342 battery = battery_utils.BatteryUtils(device) |
(...skipping 20 matching lines...) Expand all Loading... |
348 tdelta = (correct_time - device_time).seconds | 363 tdelta = (correct_time - device_time).seconds |
349 if tdelta <= 1: | 364 if tdelta <= 1: |
350 logging.info('Date/time successfully set on %s', device) | 365 logging.info('Date/time successfully set on %s', device) |
351 return True | 366 return True |
352 else: | 367 else: |
353 logging.error('Date mismatch. Device: %s Correct: %s', | 368 logging.error('Date mismatch. Device: %s Correct: %s', |
354 device_time.isoformat(), correct_time.isoformat()) | 369 device_time.isoformat(), correct_time.isoformat()) |
355 return False | 370 return False |
356 | 371 |
357 # Sometimes the date is not set correctly on the devices. Retry on failure. | 372 # Sometimes the date is not set correctly on the devices. Retry on failure. |
358 if not timeout_retry.WaitFor(_set_and_verify_date, wait_period=1, | 373 if device.IsUserBuild(): |
359 max_tries=2): | 374 # TODO(bpastene): Figure out how to set the date & time on user builds. |
360 raise device_errors.CommandFailedError( | 375 pass |
361 'Failed to set date & time.', device_serial=str(device)) | 376 else: |
| 377 if not timeout_retry.WaitFor( |
| 378 _set_and_verify_date, wait_period=1, max_tries=2): |
| 379 raise device_errors.CommandFailedError( |
| 380 'Failed to set date & time.', device_serial=str(device)) |
362 | 381 |
363 props = device.RunShellCommand('getprop', check_return=True) | 382 props = device.RunShellCommand('getprop', check_return=True) |
364 for prop in props: | 383 for prop in props: |
365 logging.info(' %s', prop) | 384 logging.info(' %s', prop) |
366 if options.auto_reconnect: | 385 if options.auto_reconnect: |
367 _PushAndLaunchAdbReboot(device, options.target) | 386 _PushAndLaunchAdbReboot(device, options.target) |
368 | 387 |
369 | 388 |
370 def _UninstallIfMatch(device, pattern, app_to_keep): | 389 def _UninstallIfMatch(device, pattern, app_to_keep): |
371 installed_packages = device.RunShellCommand(['pm', 'list', 'packages']) | 390 installed_packages = device.RunShellCommand(['pm', 'list', 'packages']) |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
492 | 511 |
493 run_tests_helper.SetLogLevel(args.verbose) | 512 run_tests_helper.SetLogLevel(args.verbose) |
494 | 513 |
495 devil_chromium.Initialize() | 514 devil_chromium.Initialize() |
496 | 515 |
497 return ProvisionDevices(args) | 516 return ProvisionDevices(args) |
498 | 517 |
499 | 518 |
500 if __name__ == '__main__': | 519 if __name__ == '__main__': |
501 sys.exit(main()) | 520 sys.exit(main()) |
OLD | NEW |