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 |