blob: 47b1dc3f8e309676682a5717ebacd12fca2682a2 [file] [log] [blame]
Justin Klaassende05df42016-11-22 15:38:08 -08001#!/usr/bin/env python
2#
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
5# found in the LICENSE file.
6
7"""Provisions Android devices with settings required for bots.
8
9Usage:
10 ./provision_devices.py [-d <device serial number>]
11"""
12
13import argparse
14import datetime
15import json
16import logging
17import os
18import posixpath
19import re
20import sys
21import time
22
23# Import _strptime before threaded code. datetime.datetime.strptime is
24# threadsafe except for the initial import of the _strptime module.
25# See crbug.com/584730 and https://bugs.python.org/issue7980.
26import _strptime # pylint: disable=unused-import
27
28if __name__ == '__main__':
29 sys.path.append(
30 os.path.abspath(os.path.join(os.path.dirname(__file__),
31 '..', '..', '..')))
32
Justin Klaassende05df42016-11-22 15:38:08 -080033from devil.android import battery_utils
34from devil.android import device_blacklist
35from devil.android import device_errors
36from devil.android import device_temp_file
37from devil.android import device_utils
38from devil.android import settings
Justin Klaassende05df42016-11-22 15:38:08 -080039from devil.android.sdk import adb_wrapper
Justin Klaassen2091a4f2017-01-23 07:38:46 -080040from devil.android.sdk import intent
Justin Klaassende05df42016-11-22 15:38:08 -080041from devil.android.sdk import keyevent
Oussama Ben Abdelbakidcd74cf2020-08-10 14:00:36 -040042from devil.android.sdk import shared_prefs
Justin Klaassende05df42016-11-22 15:38:08 -080043from devil.android.sdk import version_codes
44from devil.android.tools import script_common
45from devil.constants import exit_codes
Justin Klaassen6129c132018-04-04 00:14:34 -040046from devil.utils import logging_common
Justin Klaassende05df42016-11-22 15:38:08 -080047from devil.utils import timeout_retry
48
Justin Klaassen82688992016-11-22 19:09:02 -080049logger = logging.getLogger(__name__)
50
Justin Klaassene2b3d3c2017-04-06 14:06:09 -040051_SYSTEM_APP_DIRECTORIES = ['/system/app/', '/system/priv-app/']
52_SYSTEM_WEBVIEW_NAMES = ['webview', 'WebViewGoogle']
Justin Klaassende05df42016-11-22 15:38:08 -080053_CHROME_PACKAGE_REGEX = re.compile('.*chrom.*')
54_TOMBSTONE_REGEX = re.compile('tombstone.*')
Oussama Ben Abdelbakidcd74cf2020-08-10 14:00:36 -040055_STANDALONE_VR_DEVICES = [
56 'vega', # Lenovo Mirage Solo
57]
Justin Klaassende05df42016-11-22 15:38:08 -080058
59
60class _DEFAULT_TIMEOUTS(object):
61 # L can take a while to reboot after a wipe.
62 LOLLIPOP = 600
63 PRE_LOLLIPOP = 180
64
65 HELP_TEXT = '{}s on L, {}s on pre-L'.format(LOLLIPOP, PRE_LOLLIPOP)
66
67
68class ProvisionStep(object):
69
70 def __init__(self, cmd, reboot=False):
71 self.cmd = cmd
72 self.reboot = reboot
73
74
75def ProvisionDevices(
76 devices,
77 blacklist_file,
78 adb_key_files=None,
79 disable_location=False,
80 disable_mock_location=False,
81 disable_network=False,
82 disable_system_chrome=False,
83 emulators=False,
84 enable_java_debug=False,
85 max_battery_temp=None,
86 min_battery_level=None,
87 output_device_blacklist=None,
88 reboot_timeout=None,
89 remove_system_webview=False,
Justin Klaassene2b3d3c2017-04-06 14:06:09 -040090 system_app_remove_list=None,
Justin Klaassenff093d52017-08-07 14:19:47 -040091 system_package_remove_list=None,
Justin Klaassende05df42016-11-22 15:38:08 -080092 wipe=True):
93 blacklist = (device_blacklist.Blacklist(blacklist_file)
94 if blacklist_file
95 else None)
Justin Klaassene2b3d3c2017-04-06 14:06:09 -040096 system_app_remove_list = system_app_remove_list or []
Justin Klaassenff093d52017-08-07 14:19:47 -040097 system_package_remove_list = system_package_remove_list or []
Justin Klaassen2091a4f2017-01-23 07:38:46 -080098 try:
99 devices = script_common.GetDevices(devices, blacklist)
100 except device_errors.NoDevicesError:
101 logging.error('No available devices to provision.')
102 if blacklist:
103 logging.error('Local device blacklist: %s', blacklist.Read())
104 raise
Justin Klaassende05df42016-11-22 15:38:08 -0800105 devices = [d for d in devices
106 if not emulators or d.adb.is_emulator]
107 parallel_devices = device_utils.DeviceUtils.parallel(devices)
108
109 steps = []
110 if wipe:
111 steps += [ProvisionStep(lambda d: Wipe(d, adb_key_files), reboot=True)]
112 steps += [ProvisionStep(
113 lambda d: SetProperties(d, enable_java_debug, disable_location,
114 disable_mock_location),
115 reboot=not emulators)]
116
117 if disable_network:
118 steps.append(ProvisionStep(DisableNetwork))
119
120 if disable_system_chrome:
121 steps.append(ProvisionStep(DisableSystemChrome))
122
123 if max_battery_temp:
124 steps.append(ProvisionStep(
Justin Klaassenff093d52017-08-07 14:19:47 -0400125 lambda d: WaitForBatteryTemperature(d, max_battery_temp)))
Justin Klaassende05df42016-11-22 15:38:08 -0800126
127 if min_battery_level:
128 steps.append(ProvisionStep(
129 lambda d: WaitForCharge(d, min_battery_level)))
130
131 if remove_system_webview:
Justin Klaassene2b3d3c2017-04-06 14:06:09 -0400132 system_app_remove_list.extend(_SYSTEM_WEBVIEW_NAMES)
133
Justin Klaassenff093d52017-08-07 14:19:47 -0400134 if system_app_remove_list or system_package_remove_list:
Justin Klaassene2b3d3c2017-04-06 14:06:09 -0400135 steps.append(ProvisionStep(
Justin Klaassenff093d52017-08-07 14:19:47 -0400136 lambda d: RemoveSystemApps(
137 d, system_app_remove_list, system_package_remove_list)))
Justin Klaassende05df42016-11-22 15:38:08 -0800138
139 steps.append(ProvisionStep(SetDate))
140 steps.append(ProvisionStep(CheckExternalStorage))
Oussama Ben Abdelbakidcd74cf2020-08-10 14:00:36 -0400141 steps.append(ProvisionStep(StandaloneVrDeviceSetup))
Justin Klaassende05df42016-11-22 15:38:08 -0800142
143 parallel_devices.pMap(ProvisionDevice, steps, blacklist, reboot_timeout)
144
145 blacklisted_devices = blacklist.Read() if blacklist else []
146 if output_device_blacklist:
147 with open(output_device_blacklist, 'w') as f:
148 json.dump(blacklisted_devices, f)
149 if all(d in blacklisted_devices for d in devices):
150 raise device_errors.NoDevicesError
151 return 0
152
153
154def ProvisionDevice(device, steps, blacklist, reboot_timeout=None):
155 try:
156 if not reboot_timeout:
157 if device.build_version_sdk >= version_codes.LOLLIPOP:
158 reboot_timeout = _DEFAULT_TIMEOUTS.LOLLIPOP
159 else:
160 reboot_timeout = _DEFAULT_TIMEOUTS.PRE_LOLLIPOP
161
162 for step in steps:
163 try:
164 device.WaitUntilFullyBooted(timeout=reboot_timeout, retries=0)
165 except device_errors.CommandTimeoutError:
Justin Klaassen82688992016-11-22 19:09:02 -0800166 logger.error('Device did not finish booting. Will try to reboot.')
Justin Klaassende05df42016-11-22 15:38:08 -0800167 device.Reboot(timeout=reboot_timeout)
168 step.cmd(device)
169 if step.reboot:
170 device.Reboot(False, retries=0)
171 device.adb.WaitForDevice()
172
173 except device_errors.CommandTimeoutError:
Justin Klaassen82688992016-11-22 19:09:02 -0800174 logger.exception('Timed out waiting for device %s. Adding to blacklist.',
175 str(device))
Justin Klaassende05df42016-11-22 15:38:08 -0800176 if blacklist:
177 blacklist.Extend([str(device)], reason='provision_timeout')
178
Justin Klaassenff093d52017-08-07 14:19:47 -0400179 except (device_errors.CommandFailedError,
180 device_errors.DeviceUnreachableError):
Justin Klaassen82688992016-11-22 19:09:02 -0800181 logger.exception('Failed to provision device %s. Adding to blacklist.',
182 str(device))
Justin Klaassende05df42016-11-22 15:38:08 -0800183 if blacklist:
184 blacklist.Extend([str(device)], reason='provision_failure')
185
186
187def Wipe(device, adb_key_files=None):
188 if (device.IsUserBuild() or
189 device.build_version_sdk >= version_codes.MARSHMALLOW):
190 WipeChromeData(device)
191
Justin Klaassenff093d52017-08-07 14:19:47 -0400192 package = 'com.google.android.gms'
193 if device.GetApplicationPaths(package):
194 version_name = device.GetApplicationVersion(package)
195 logger.info('Version name for %s is %s', package, version_name)
196 else:
197 logger.info('Package %s is not installed', package)
Justin Klaassende05df42016-11-22 15:38:08 -0800198 else:
199 WipeDevice(device, adb_key_files)
200
201
202def WipeChromeData(device):
203 """Wipes chrome specific data from device
204
205 (1) uninstall any app whose name matches *chrom*, except
206 com.android.chrome, which is the chrome stable package. Doing so also
207 removes the corresponding dirs under /data/data/ and /data/app/
208 (2) remove any dir under /data/app-lib/ whose name matches *chrom*
209 (3) remove any files under /data/tombstones/ whose name matches "tombstone*"
210 (4) remove /data/local.prop if there is any
211 (5) remove /data/local/chrome-command-line if there is any
212 (6) remove anything under /data/local/.config/ if the dir exists
213 (this is telemetry related)
214 (7) remove anything under /data/local/tmp/
215
216 Arguments:
217 device: the device to wipe
218 """
219 try:
220 if device.IsUserBuild():
Justin Klaassenff093d52017-08-07 14:19:47 -0400221 _UninstallIfMatch(device, _CHROME_PACKAGE_REGEX)
Justin Klaassende05df42016-11-22 15:38:08 -0800222 device.RunShellCommand('rm -rf %s/*' % device.GetExternalStoragePath(),
Justin Klaassene2b3d3c2017-04-06 14:06:09 -0400223 shell=True, check_return=True)
224 device.RunShellCommand('rm -rf /data/local/tmp/*',
225 shell=True, check_return=True)
Justin Klaassende05df42016-11-22 15:38:08 -0800226 else:
227 device.EnableRoot()
Justin Klaassenff093d52017-08-07 14:19:47 -0400228 _UninstallIfMatch(device, _CHROME_PACKAGE_REGEX)
Justin Klaassende05df42016-11-22 15:38:08 -0800229 _WipeUnderDirIfMatch(device, '/data/app-lib/', _CHROME_PACKAGE_REGEX)
230 _WipeUnderDirIfMatch(device, '/data/tombstones/', _TOMBSTONE_REGEX)
231
232 _WipeFileOrDir(device, '/data/local.prop')
233 _WipeFileOrDir(device, '/data/local/chrome-command-line')
234 _WipeFileOrDir(device, '/data/local/.config/')
235 _WipeFileOrDir(device, '/data/local/tmp/')
236 device.RunShellCommand('rm -rf %s/*' % device.GetExternalStoragePath(),
Justin Klaassene2b3d3c2017-04-06 14:06:09 -0400237 shell=True, check_return=True)
Justin Klaassende05df42016-11-22 15:38:08 -0800238 except device_errors.CommandFailedError:
Justin Klaassen82688992016-11-22 19:09:02 -0800239 logger.exception('Possible failure while wiping the device. '
240 'Attempting to continue.')
Justin Klaassende05df42016-11-22 15:38:08 -0800241
242
Justin Klaassenff093d52017-08-07 14:19:47 -0400243def _UninstallIfMatch(device, pattern):
Justin Klaassene2b3d3c2017-04-06 14:06:09 -0400244 installed_packages = device.RunShellCommand(
245 ['pm', 'list', 'packages'], check_return=True)
Justin Klaassende05df42016-11-22 15:38:08 -0800246 installed_system_packages = [
Justin Klaassene2b3d3c2017-04-06 14:06:09 -0400247 pkg.split(':')[1] for pkg in device.RunShellCommand(
248 ['pm', 'list', 'packages', '-s'], check_return=True)]
Justin Klaassende05df42016-11-22 15:38:08 -0800249 for package_output in installed_packages:
250 package = package_output.split(":")[1]
Justin Klaassenff093d52017-08-07 14:19:47 -0400251 if pattern.match(package) and package not in installed_system_packages:
252 device.Uninstall(package)
Justin Klaassende05df42016-11-22 15:38:08 -0800253
254
255def _WipeUnderDirIfMatch(device, path, pattern):
256 for filename in device.ListDirectory(path):
257 if pattern.match(filename):
258 _WipeFileOrDir(device, posixpath.join(path, filename))
259
260
261def _WipeFileOrDir(device, path):
262 if device.PathExists(path):
263 device.RunShellCommand(['rm', '-rf', path], check_return=True)
264
265
266def WipeDevice(device, adb_key_files):
267 """Wipes data from device, keeping only the adb_keys for authorization.
268
269 After wiping data on a device that has been authorized, adb can still
270 communicate with the device, but after reboot the device will need to be
271 re-authorized because the adb keys file is stored in /data/misc/adb/.
272 Thus, adb_keys file is rewritten so the device does not need to be
273 re-authorized.
274
275 Arguments:
276 device: the device to wipe
277 """
278 try:
279 device.EnableRoot()
280 device_authorized = device.FileExists(adb_wrapper.ADB_KEYS_FILE)
281 if device_authorized:
282 adb_keys = device.ReadFile(adb_wrapper.ADB_KEYS_FILE,
283 as_root=True).splitlines()
284 device.RunShellCommand(['wipe', 'data'],
285 as_root=True, check_return=True)
286 device.adb.WaitForDevice()
287
288 if device_authorized:
289 adb_keys_set = set(adb_keys)
290 for adb_key_file in adb_key_files or []:
291 try:
292 with open(adb_key_file, 'r') as f:
293 adb_public_keys = f.readlines()
294 adb_keys_set.update(adb_public_keys)
295 except IOError:
Justin Klaassen82688992016-11-22 19:09:02 -0800296 logger.warning('Unable to find adb keys file %s.', adb_key_file)
Justin Klaassende05df42016-11-22 15:38:08 -0800297 _WriteAdbKeysFile(device, '\n'.join(adb_keys_set))
298 except device_errors.CommandFailedError:
Justin Klaassen82688992016-11-22 19:09:02 -0800299 logger.exception('Possible failure while wiping the device. '
300 'Attempting to continue.')
Justin Klaassende05df42016-11-22 15:38:08 -0800301
302
303def _WriteAdbKeysFile(device, adb_keys_string):
304 dir_path = posixpath.dirname(adb_wrapper.ADB_KEYS_FILE)
305 device.RunShellCommand(['mkdir', '-p', dir_path],
306 as_root=True, check_return=True)
307 device.RunShellCommand(['restorecon', dir_path],
308 as_root=True, check_return=True)
309 device.WriteFile(adb_wrapper.ADB_KEYS_FILE, adb_keys_string, as_root=True)
310 device.RunShellCommand(['restorecon', adb_wrapper.ADB_KEYS_FILE],
311 as_root=True, check_return=True)
312
313
314def SetProperties(device, enable_java_debug, disable_location,
315 disable_mock_location):
316 try:
317 device.EnableRoot()
318 except device_errors.CommandFailedError as e:
Justin Klaassen82688992016-11-22 19:09:02 -0800319 logger.warning(str(e))
Justin Klaassende05df42016-11-22 15:38:08 -0800320
321 if not device.IsUserBuild():
322 _ConfigureLocalProperties(device, enable_java_debug)
323 else:
Justin Klaassen82688992016-11-22 19:09:02 -0800324 logger.warning('Cannot configure properties in user builds.')
Justin Klaassende05df42016-11-22 15:38:08 -0800325 settings.ConfigureContentSettings(
326 device, settings.DETERMINISTIC_DEVICE_SETTINGS)
327 if disable_location:
328 settings.ConfigureContentSettings(
329 device, settings.DISABLE_LOCATION_SETTINGS)
330 else:
331 settings.ConfigureContentSettings(
332 device, settings.ENABLE_LOCATION_SETTINGS)
333
334 if disable_mock_location:
335 settings.ConfigureContentSettings(
336 device, settings.DISABLE_MOCK_LOCATION_SETTINGS)
337 else:
338 settings.ConfigureContentSettings(
339 device, settings.ENABLE_MOCK_LOCATION_SETTINGS)
340
341 settings.SetLockScreenSettings(device)
342
343 # Some device types can momentarily disappear after setting properties.
344 device.adb.WaitForDevice()
345
346
347def DisableNetwork(device):
348 settings.ConfigureContentSettings(
349 device, settings.NETWORK_DISABLED_SETTINGS)
350 if device.build_version_sdk >= version_codes.MARSHMALLOW:
351 # Ensure that NFC is also switched off.
352 device.RunShellCommand(['svc', 'nfc', 'disable'],
353 as_root=True, check_return=True)
354
355
356def DisableSystemChrome(device):
357 # The system chrome version on the device interferes with some tests.
358 device.RunShellCommand(['pm', 'disable', 'com.android.chrome'],
Justin Klaassenff093d52017-08-07 14:19:47 -0400359 as_root=True, check_return=True)
Justin Klaassende05df42016-11-22 15:38:08 -0800360
361
Justin Klaassenff093d52017-08-07 14:19:47 -0400362def _FindSystemPackagePaths(device, system_package_list):
Justin Klaassene2b3d3c2017-04-06 14:06:09 -0400363 found_paths = []
Justin Klaassenff093d52017-08-07 14:19:47 -0400364 for system_package in system_package_list:
365 found_paths.extend(device.GetApplicationPaths(system_package))
366 return [p for p in found_paths if p.startswith('/system/')]
Justin Klaassende05df42016-11-22 15:38:08 -0800367
Justin Klaassenff093d52017-08-07 14:19:47 -0400368
369def _FindSystemAppPaths(device, system_app_list):
370 found_paths = []
371 for system_app in system_app_list:
372 for directory in _SYSTEM_APP_DIRECTORIES:
373 path = os.path.join(directory, system_app)
374 if device.PathExists(path):
375 found_paths.append(path)
376 return found_paths
377
378
379def RemoveSystemApps(
380 device, system_app_remove_list, system_package_remove_list):
Justin Klaassene2b3d3c2017-04-06 14:06:09 -0400381 """Attempts to remove the provided system apps from the given device.
382
383 Arguments:
384 device: The device to remove the system apps from.
385 system_app_remove_list: A list of app names to remove, e.g.
386 ['WebViewGoogle', 'GoogleVrCore']
Justin Klaassenff093d52017-08-07 14:19:47 -0400387 system_package_remove_list: A list of app packages to remove, e.g.
388 ['com.google.android.webview']
Justin Klaassene2b3d3c2017-04-06 14:06:09 -0400389 """
390 device.EnableRoot()
391 if device.HasRoot():
Justin Klaassenff093d52017-08-07 14:19:47 -0400392 system_app_paths = (
393 _FindSystemAppPaths(device, system_app_remove_list) +
394 _FindSystemPackagePaths(device, system_package_remove_list))
395 if system_app_paths:
396 # Disable Marshmallow's Verity security feature
397 if device.build_version_sdk >= version_codes.MARSHMALLOW:
398 logger.info('Disabling Verity on %s', device.serial)
399 device.adb.DisableVerity()
400 device.Reboot()
401 device.WaitUntilFullyBooted()
402 device.EnableRoot()
Justin Klaassene2b3d3c2017-04-06 14:06:09 -0400403
Justin Klaassenff093d52017-08-07 14:19:47 -0400404 device.adb.Remount()
405 device.RunShellCommand(['stop'], check_return=True)
406 device.RemovePath(system_app_paths, force=True, recursive=True)
407 device.RunShellCommand(['start'], check_return=True)
Justin Klaassende05df42016-11-22 15:38:08 -0800408 else:
Justin Klaassene2b3d3c2017-04-06 14:06:09 -0400409 raise device_errors.CommandFailedError(
410 'Failed to remove system apps from non-rooted device', str(device))
Justin Klaassende05df42016-11-22 15:38:08 -0800411
412
413def _ConfigureLocalProperties(device, java_debug=True):
414 """Set standard readonly testing device properties prior to reboot."""
415 local_props = [
416 'persist.sys.usb.config=adb',
417 'ro.monkey=1',
418 'ro.test_harness=1',
419 'ro.audio.silent=1',
420 'ro.setupwizard.mode=DISABLED',
421 ]
422 if java_debug:
423 local_props.append(
424 '%s=all' % device_utils.DeviceUtils.JAVA_ASSERT_PROPERTY)
425 local_props.append('debug.checkjni=1')
426 try:
427 device.WriteFile(
428 device.LOCAL_PROPERTIES_PATH,
429 '\n'.join(local_props), as_root=True)
430 # Android will not respect the local props file if it is world writable.
431 device.RunShellCommand(
432 ['chmod', '644', device.LOCAL_PROPERTIES_PATH],
433 as_root=True, check_return=True)
434 except device_errors.CommandFailedError:
Justin Klaassen82688992016-11-22 19:09:02 -0800435 logger.exception('Failed to configure local properties.')
Justin Klaassende05df42016-11-22 15:38:08 -0800436
437
438def FinishProvisioning(device):
439 # The lockscreen can't be disabled on user builds, so send a keyevent
440 # to unlock it.
441 if device.IsUserBuild():
442 device.SendKeyEvent(keyevent.KEYCODE_MENU)
443
444
445def WaitForCharge(device, min_battery_level):
446 battery = battery_utils.BatteryUtils(device)
447 try:
448 battery.ChargeDeviceToLevel(min_battery_level)
449 except device_errors.DeviceChargingError:
450 device.Reboot()
451 battery.ChargeDeviceToLevel(min_battery_level)
452
453
Justin Klaassenff093d52017-08-07 14:19:47 -0400454def WaitForBatteryTemperature(device, max_battery_temp):
Justin Klaassende05df42016-11-22 15:38:08 -0800455 try:
456 battery = battery_utils.BatteryUtils(device)
457 battery.LetBatteryCoolToTemperature(max_battery_temp)
458 except device_errors.CommandFailedError:
Justin Klaassen82688992016-11-22 19:09:02 -0800459 logger.exception('Unable to let battery cool to specified temperature.')
Justin Klaassende05df42016-11-22 15:38:08 -0800460
461
462def SetDate(device):
463 def _set_and_verify_date():
464 if device.build_version_sdk >= version_codes.MARSHMALLOW:
465 date_format = '%m%d%H%M%Y.%S'
466 set_date_command = ['date', '-u']
467 get_date_command = ['date', '-u']
468 else:
469 date_format = '%Y%m%d.%H%M%S'
470 set_date_command = ['date', '-s']
471 get_date_command = ['date']
472
473 # TODO(jbudorick): This is wrong on pre-M devices -- get/set are
474 # dealing in local time, but we're setting based on GMT.
475 strgmtime = time.strftime(date_format, time.gmtime())
476 set_date_command.append(strgmtime)
477 device.RunShellCommand(set_date_command, as_root=True, check_return=True)
478
479 get_date_command.append('+"%Y%m%d.%H%M%S"')
480 device_time = device.RunShellCommand(
Justin Klaassene2b3d3c2017-04-06 14:06:09 -0400481 get_date_command, check_return=True,
482 as_root=True, single_line=True).replace('"', '')
Justin Klaassende05df42016-11-22 15:38:08 -0800483 device_time = datetime.datetime.strptime(device_time, "%Y%m%d.%H%M%S")
484 correct_time = datetime.datetime.strptime(strgmtime, date_format)
485 tdelta = (correct_time - device_time).seconds
486 if tdelta <= 1:
Justin Klaassen82688992016-11-22 19:09:02 -0800487 logger.info('Date/time successfully set on %s', device)
Justin Klaassende05df42016-11-22 15:38:08 -0800488 return True
489 else:
Justin Klaassen82688992016-11-22 19:09:02 -0800490 logger.error('Date mismatch. Device: %s Correct: %s',
491 device_time.isoformat(), correct_time.isoformat())
Justin Klaassende05df42016-11-22 15:38:08 -0800492 return False
493
494 # Sometimes the date is not set correctly on the devices. Retry on failure.
495 if device.IsUserBuild():
496 # TODO(bpastene): Figure out how to set the date & time on user builds.
497 pass
498 else:
499 if not timeout_retry.WaitFor(
500 _set_and_verify_date, wait_period=1, max_tries=2):
501 raise device_errors.CommandFailedError(
502 'Failed to set date & time.', device_serial=str(device))
Justin Klaassene2b3d3c2017-04-06 14:06:09 -0400503 device.EnableRoot()
Justin Klaassenff093d52017-08-07 14:19:47 -0400504 # The following intent can take a bit to complete when ran shortly after
505 # device boot-up.
Justin Klaassen2091a4f2017-01-23 07:38:46 -0800506 device.BroadcastIntent(
Justin Klaassenff093d52017-08-07 14:19:47 -0400507 intent.Intent(action='android.intent.action.TIME_SET'),
508 timeout=180)
Justin Klaassende05df42016-11-22 15:38:08 -0800509
510
511def LogDeviceProperties(device):
Justin Klaassene2b3d3c2017-04-06 14:06:09 -0400512 props = device.RunShellCommand(['getprop'], check_return=True)
Justin Klaassende05df42016-11-22 15:38:08 -0800513 for prop in props:
Justin Klaassen82688992016-11-22 19:09:02 -0800514 logger.info(' %s', prop)
Justin Klaassende05df42016-11-22 15:38:08 -0800515
516
Oussama Ben Abdelbakidcd74cf2020-08-10 14:00:36 -0400517# TODO(jbudorick): Relocate this either to device_utils or a separate
518# and more intentionally reusable layer on top of device_utils.
Justin Klaassende05df42016-11-22 15:38:08 -0800519def CheckExternalStorage(device):
520 """Checks that storage is writable and if not makes it writable.
521
522 Arguments:
523 device: The device to check.
524 """
525 try:
526 with device_temp_file.DeviceTempFile(
527 device.adb, suffix='.sh', dir=device.GetExternalStoragePath()) as f:
528 device.WriteFile(f.name, 'test')
529 except device_errors.CommandFailedError:
Justin Klaassen82688992016-11-22 19:09:02 -0800530 logger.info('External storage not writable. Remounting / as RW')
Justin Klaassende05df42016-11-22 15:38:08 -0800531 device.RunShellCommand(['mount', '-o', 'remount,rw', '/'],
532 check_return=True, as_root=True)
533 device.EnableRoot()
534 with device_temp_file.DeviceTempFile(
535 device.adb, suffix='.sh', dir=device.GetExternalStoragePath()) as f:
536 device.WriteFile(f.name, 'test')
537
538
Oussama Ben Abdelbakidcd74cf2020-08-10 14:00:36 -0400539def StandaloneVrDeviceSetup(device):
540 """Performs any additional setup necessary for standalone Android VR devices.
541
542 Arguments:
543 device: The device to check.
544 """
545 if device.product_name not in _STANDALONE_VR_DEVICES:
546 return
547
548 # Modify VrCore's settings so that any first time setup, etc. is skipped.
549 shared_pref = shared_prefs.SharedPrefs(device, 'com.google.vr.vrcore',
550 'VrCoreSettings.xml', use_encrypted_path=True)
551 shared_pref.Load()
552 # Skip first time setup.
553 shared_pref.SetBoolean('DaydreamSetupComplete', True)
554 # Disable the automatic prompt that shows anytime the device detects that a
555 # controller isn't connected.
556 shared_pref.SetBoolean('gConfigFlags:controller_recovery_enabled', False)
557 # Use an automated controller instead of a real one so we get past the
558 # controller pairing screen that's shown on startup.
559 shared_pref.SetBoolean('UseAutomatedController', True)
560 shared_pref.Commit()
561
562
Justin Klaassende05df42016-11-22 15:38:08 -0800563def main(raw_args):
564 # Recommended options on perf bots:
565 # --disable-network
566 # TODO(tonyg): We eventually want network on. However, currently radios
567 # can cause perfbots to drain faster than they charge.
568 # --min-battery-level 95
569 # Some perf bots run benchmarks with USB charging disabled which leads
570 # to gradual draining of the battery. We must wait for a full charge
571 # before starting a run in order to keep the devices online.
572
573 parser = argparse.ArgumentParser(
574 description='Provision Android devices with settings required for bots.')
Justin Klaassen6129c132018-04-04 00:14:34 -0400575 logging_common.AddLoggingArguments(parser)
576 script_common.AddDeviceArguments(parser)
577 script_common.AddEnvironmentArguments(parser)
Justin Klaassende05df42016-11-22 15:38:08 -0800578 parser.add_argument(
Justin Klaassen2091a4f2017-01-23 07:38:46 -0800579 '--adb-key-files', type=str, nargs='+',
580 help='list of adb keys to push to device')
Justin Klaassende05df42016-11-22 15:38:08 -0800581 parser.add_argument(
Justin Klaassende05df42016-11-22 15:38:08 -0800582 '--disable-location', action='store_true',
583 help='disable Google location services on devices')
584 parser.add_argument(
585 '--disable-mock-location', action='store_true', default=False,
586 help='Set ALLOW_MOCK_LOCATION to false')
587 parser.add_argument(
588 '--disable-network', action='store_true',
589 help='disable network access on devices')
590 parser.add_argument(
591 '--disable-java-debug', action='store_false',
592 dest='enable_java_debug', default=True,
593 help='disable Java property asserts and JNI checking')
594 parser.add_argument(
595 '--disable-system-chrome', action='store_true',
Justin Klaassenff093d52017-08-07 14:19:47 -0400596 help='DEPRECATED: use --remove-system-packages com.android.google '
597 'Disable the system chrome from devices.')
Justin Klaassende05df42016-11-22 15:38:08 -0800598 parser.add_argument(
Justin Klaassen2091a4f2017-01-23 07:38:46 -0800599 '--emulators', action='store_true',
Justin Klaassene2b3d3c2017-04-06 14:06:09 -0400600 help='provision only emulators and ignore usb devices '
601 '(this will not wipe emulators)')
Justin Klaassende05df42016-11-22 15:38:08 -0800602 parser.add_argument(
603 '--max-battery-temp', type=int, metavar='NUM',
604 help='Wait for the battery to have this temp or lower.')
605 parser.add_argument(
Justin Klaassen2091a4f2017-01-23 07:38:46 -0800606 '--min-battery-level', type=int, metavar='NUM',
607 help='wait for the device to reach this minimum battery'
608 ' level before trying to continue')
609 parser.add_argument(
Justin Klaassende05df42016-11-22 15:38:08 -0800610 '--output-device-blacklist',
611 help='Json file to output the device blacklist.')
612 parser.add_argument(
Justin Klaassen2091a4f2017-01-23 07:38:46 -0800613 '--reboot-timeout', metavar='SECS', type=int,
614 help='when wiping the device, max number of seconds to'
615 ' wait after each reboot '
616 '(default: %s)' % _DEFAULT_TIMEOUTS.HELP_TEXT)
617 parser.add_argument(
Justin Klaassene2b3d3c2017-04-06 14:06:09 -0400618 '--remove-system-apps', nargs='*', dest='system_app_remove_list',
Justin Klaassenff093d52017-08-07 14:19:47 -0400619 help='DEPRECATED: use --remove-system-packages instead. '
620 'The names of system apps to remove. ')
621 parser.add_argument(
622 '--remove-system-packages', nargs='*', dest='system_package_remove_list',
623 help='The names of system packages to remove.')
Justin Klaassene2b3d3c2017-04-06 14:06:09 -0400624 parser.add_argument(
Justin Klaassen2091a4f2017-01-23 07:38:46 -0800625 '--remove-system-webview', action='store_true',
Justin Klaassenff093d52017-08-07 14:19:47 -0400626 help='DEPRECATED: use --remove-system-packages '
627 'com.google.android.webview com.android.webview '
628 'Remove the system webview from devices.')
Justin Klaassen2091a4f2017-01-23 07:38:46 -0800629 parser.add_argument(
630 '--skip-wipe', action='store_true', default=False,
Justin Klaassene2b3d3c2017-04-06 14:06:09 -0400631 help='do not wipe device data during provisioning')
Justin Klaassen2091a4f2017-01-23 07:38:46 -0800632
633 # No-op arguments for compatibility with build/android/provision_devices.py.
634 # TODO(jbudorick): Remove these once all callers have stopped using them.
635 parser.add_argument(
636 '--chrome-specific-wipe', action='store_true',
637 help=argparse.SUPPRESS)
638 parser.add_argument(
639 '--phase', action='append',
640 help=argparse.SUPPRESS)
641 parser.add_argument(
642 '-r', '--auto-reconnect', action='store_true',
643 help=argparse.SUPPRESS)
644 parser.add_argument(
645 '-t', '--target',
646 help=argparse.SUPPRESS)
647
Justin Klaassende05df42016-11-22 15:38:08 -0800648 args = parser.parse_args(raw_args)
649
Justin Klaassen6129c132018-04-04 00:14:34 -0400650 logging_common.InitializeLogging(args)
651 script_common.InitializeEnvironment(args)
Justin Klaassende05df42016-11-22 15:38:08 -0800652
653 try:
654 return ProvisionDevices(
655 args.devices,
656 args.blacklist_file,
657 adb_key_files=args.adb_key_files,
658 disable_location=args.disable_location,
659 disable_mock_location=args.disable_mock_location,
660 disable_network=args.disable_network,
661 disable_system_chrome=args.disable_system_chrome,
662 emulators=args.emulators,
663 enable_java_debug=args.enable_java_debug,
664 max_battery_temp=args.max_battery_temp,
665 min_battery_level=args.min_battery_level,
666 output_device_blacklist=args.output_device_blacklist,
667 reboot_timeout=args.reboot_timeout,
668 remove_system_webview=args.remove_system_webview,
Justin Klaassene2b3d3c2017-04-06 14:06:09 -0400669 system_app_remove_list=args.system_app_remove_list,
Justin Klaassenff093d52017-08-07 14:19:47 -0400670 system_package_remove_list=args.system_package_remove_list,
Justin Klaassene2b3d3c2017-04-06 14:06:09 -0400671 wipe=not args.skip_wipe and not args.emulators)
Justin Klaassende05df42016-11-22 15:38:08 -0800672 except (device_errors.DeviceUnreachableError, device_errors.NoDevicesError):
Justin Klaassen2091a4f2017-01-23 07:38:46 -0800673 logging.exception('Unable to provision local devices.')
Justin Klaassende05df42016-11-22 15:38:08 -0800674 return exit_codes.INFRA
675
676
677if __name__ == '__main__':
678 sys.exit(main(sys.argv[1:]))