Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(203)

Side by Side Diff: build/android/provision_devices.py

Issue 869563002: [Android] Expose provisioning settings as command line options (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: java debug enable = not disable Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 logging 14 import logging
14 import optparse
15 import os 15 import os
16 import re 16 import re
17 import subprocess 17 import subprocess
18 import sys 18 import sys
19 import time 19 import time
20 20
21 from pylib import android_commands 21 from pylib import android_commands
22 from pylib import constants 22 from pylib import constants
23 from pylib import device_settings 23 from pylib import device_settings
24 from pylib.device import device_blacklist 24 from pylib.device import device_blacklist
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
72 logging.info(' Pushing adb_reboot ...') 72 logging.info(' Pushing adb_reboot ...')
73 adb_reboot = os.path.join(constants.DIR_SOURCE_ROOT, 73 adb_reboot = os.path.join(constants.DIR_SOURCE_ROOT,
74 'out/%s/adb_reboot' % target) 74 'out/%s/adb_reboot' % target)
75 device.PushChangedFiles([(adb_reboot, '/data/local/tmp/')]) 75 device.PushChangedFiles([(adb_reboot, '/data/local/tmp/')])
76 # Launch adb_reboot 76 # Launch adb_reboot
77 logging.info(' Launching adb_reboot ...') 77 logging.info(' Launching adb_reboot ...')
78 device.old_interface.GetAndroidToolStatusAndOutput( 78 device.old_interface.GetAndroidToolStatusAndOutput(
79 '/data/local/tmp/adb_reboot') 79 '/data/local/tmp/adb_reboot')
80 80
81 81
82 def _ConfigureLocalProperties(device, is_perf): 82 def _ConfigureLocalProperties(device, java_debug=True):
83 """Set standard readonly testing device properties prior to reboot.""" 83 """Set standard readonly testing device properties prior to reboot."""
84 local_props = [ 84 local_props = [
85 'persist.sys.usb.config=adb', 85 'persist.sys.usb.config=adb',
86 'ro.monkey=1', 86 'ro.monkey=1',
87 'ro.test_harness=1', 87 'ro.test_harness=1',
88 'ro.audio.silent=1', 88 'ro.audio.silent=1',
89 'ro.setupwizard.mode=DISABLED', 89 'ro.setupwizard.mode=DISABLED',
90 ] 90 ]
91 if not is_perf: 91 if java_debug:
92 local_props.append('%s=all' % android_commands.JAVA_ASSERT_PROPERTY) 92 local_props.append('%s=all' % android_commands.JAVA_ASSERT_PROPERTY)
93 local_props.append('debug.checkjni=1') 93 local_props.append('debug.checkjni=1')
94 try: 94 try:
95 device.WriteFile( 95 device.WriteFile(
96 constants.DEVICE_LOCAL_PROPERTIES_PATH, 96 constants.DEVICE_LOCAL_PROPERTIES_PATH,
97 '\n'.join(local_props), as_root=True) 97 '\n'.join(local_props), as_root=True)
98 # Android will not respect the local props file if it is world writable. 98 # Android will not respect the local props file if it is world writable.
99 device.RunShellCommand( 99 device.RunShellCommand(
100 'chmod 644 %s' % constants.DEVICE_LOCAL_PROPERTIES_PATH, 100 ['chmod', '644', constants.DEVICE_LOCAL_PROPERTIES_PATH],
101 as_root=True) 101 as_root=True)
102 except device_errors.CommandFailedError as e: 102 except device_errors.CommandFailedError as e:
103 logging.warning(str(e)) 103 logging.warning(str(e))
104 104
105 # LOCAL_PROPERTIES_PATH = '/data/local.prop' 105 # LOCAL_PROPERTIES_PATH = '/data/local.prop'
106 106
107 107
108 def WipeDeviceData(device): 108 def WipeDeviceData(device):
109 """Wipes data from device, keeping only the adb_keys for authorization. 109 """Wipes data from device, keeping only the adb_keys for authorization.
110 110
(...skipping 18 matching lines...) Expand all
129 device.RunShellCommand('restorecon %s' % dir_path, as_root=True) 129 device.RunShellCommand('restorecon %s' % dir_path, as_root=True)
130 device.RunShellCommand('echo %s > %s' % 130 device.RunShellCommand('echo %s > %s' %
131 (adb_keys[0], constants.ADB_KEYS_FILE), as_root=True) 131 (adb_keys[0], constants.ADB_KEYS_FILE), as_root=True)
132 for adb_key in adb_keys[1:]: 132 for adb_key in adb_keys[1:]:
133 device.RunShellCommand( 133 device.RunShellCommand(
134 'echo %s >> %s' % (adb_key, constants.ADB_KEYS_FILE), as_root=True) 134 'echo %s >> %s' % (adb_key, constants.ADB_KEYS_FILE), as_root=True)
135 device.RunShellCommand('restorecon %s' % constants.ADB_KEYS_FILE, 135 device.RunShellCommand('restorecon %s' % constants.ADB_KEYS_FILE,
136 as_root=True) 136 as_root=True)
137 137
138 138
139 def WipeDeviceIfPossible(device): 139 def WipeDeviceIfPossible(device, timeout):
140 try: 140 try:
141 device.EnableRoot() 141 device.EnableRoot()
142 WipeDeviceData(device) 142 WipeDeviceData(device)
143 # TODO(jbudorick): Tune the timeout per OS version. 143 device.Reboot(True, timeout=timeout, retries=0)
144 device.Reboot(True, timeout=600, retries=0)
145 except (errors.DeviceUnresponsiveError, device_errors.CommandFailedError): 144 except (errors.DeviceUnresponsiveError, device_errors.CommandFailedError):
146 pass 145 pass
147 146
148 147
149 def ProvisionDevice(device, options, is_perf): 148 def ProvisionDevice(device, options):
150 try: 149 try:
151 if not options.skip_wipe: 150 if not options.skip_wipe:
152 WipeDeviceIfPossible(device) 151 WipeDeviceIfPossible(device, options.reboot_timeout)
153 try: 152 try:
154 device.EnableRoot() 153 device.EnableRoot()
155 except device_errors.CommandFailedError as e: 154 except device_errors.CommandFailedError as e:
156 logging.warning(str(e)) 155 logging.warning(str(e))
157 _ConfigureLocalProperties(device, is_perf) 156 _ConfigureLocalProperties(device, options.enable_java_debug)
158 device_settings.ConfigureContentSettings( 157 device_settings.ConfigureContentSettings(
159 device, device_settings.DETERMINISTIC_DEVICE_SETTINGS) 158 device, device_settings.DETERMINISTIC_DEVICE_SETTINGS)
160 if options.disable_location: 159 if options.disable_location:
161 device_settings.ConfigureContentSettings( 160 device_settings.ConfigureContentSettings(
162 device, device_settings.DISABLE_LOCATION_SETTINGS) 161 device, device_settings.DISABLE_LOCATION_SETTINGS)
163 else: 162 else:
164 device_settings.ConfigureContentSettings( 163 device_settings.ConfigureContentSettings(
165 device, device_settings.ENABLE_LOCATION_SETTINGS) 164 device, device_settings.ENABLE_LOCATION_SETTINGS)
166 device_settings.SetLockScreenSettings(device) 165 device_settings.SetLockScreenSettings(device)
167 if is_perf: 166 if options.disable_network:
168 # TODO(tonyg): We eventually want network on. However, currently radios
169 # can cause perfbots to drain faster than they charge.
170 device_settings.ConfigureContentSettings( 167 device_settings.ConfigureContentSettings(
171 device, device_settings.NETWORK_DISABLED_SETTINGS) 168 device, device_settings.NETWORK_DISABLED_SETTINGS)
172 # Some perf bots run benchmarks with USB charging disabled which leads 169 if options.wait_for_battery:
173 # to gradual draining of the battery. We must wait for a full charge
174 # before starting a run in order to keep the devices online.
175 try: 170 try:
176 battery_info = device.old_interface.GetBatteryInfo() 171 battery_info = device.old_interface.GetBatteryInfo()
177 except Exception as e: 172 except Exception as e:
178 battery_info = {} 173 battery_info = {}
179 logging.error('Unable to obtain battery info for %s, %s', 174 logging.error('Unable to obtain battery info for %s, %s',
180 str(device), e) 175 str(device), e)
181 176
182 while int(battery_info.get('level', 100)) < options.min_battery_level: 177 while int(battery_info.get('level', 100)) < options.min_battery_level:
183 if not device.old_interface.IsDeviceCharging(): 178 if not device.old_interface.IsDeviceCharging():
184 if device.old_interface.CanControlUsbCharging(): 179 if device.old_interface.CanControlUsbCharging():
185 device.old_interface.EnableUsbCharging() 180 device.old_interface.EnableUsbCharging()
186 else: 181 else:
187 logging.error('Device is not charging') 182 logging.error('Device is not charging')
188 break 183 break
189 logging.info('Waiting for device to charge. Current level=%s', 184 logging.info('Waiting for device to charge. Current level=%s',
190 battery_info.get('level', 0)) 185 battery_info.get('level', 0))
191 time.sleep(60) 186 time.sleep(60)
192 battery_info = device.old_interface.GetBatteryInfo() 187 battery_info = device.old_interface.GetBatteryInfo()
193 if not options.skip_wipe: 188 if not options.skip_wipe:
194 # TODO(jbudorick): Tune the timeout per OS version. 189 device.Reboot(True, timeout=options.reboot_timeout, retries=0)
195 device.Reboot(True, timeout=600, retries=0)
196 device.RunShellCommand('date -s %s' % time.strftime('%Y%m%d.%H%M%S', 190 device.RunShellCommand('date -s %s' % time.strftime('%Y%m%d.%H%M%S',
197 time.gmtime()), 191 time.gmtime()),
198 as_root=True) 192 as_root=True)
199 props = device.RunShellCommand('getprop') 193 props = device.RunShellCommand('getprop')
200 for prop in props: 194 for prop in props:
201 logging.info(' %s' % prop) 195 logging.info(' %s' % prop)
202 if options.auto_reconnect: 196 if options.auto_reconnect:
203 PushAndLaunchAdbReboot(device, options.target) 197 PushAndLaunchAdbReboot(device, options.target)
204 except (errors.WaitForResponseTimedOutError, 198 except (errors.WaitForResponseTimedOutError,
205 device_errors.CommandTimeoutError): 199 device_errors.CommandTimeoutError):
206 logging.info('Timed out waiting for device %s. Adding to blacklist.', 200 logging.info('Timed out waiting for device %s. Adding to blacklist.',
207 str(device)) 201 str(device))
208 # Device black list is reset by bb_device_status_check.py per build. 202 # Device black list is reset by bb_device_status_check.py per build.
209 device_blacklist.ExtendBlacklist([str(device)]) 203 device_blacklist.ExtendBlacklist([str(device)])
210 except device_errors.CommandFailedError: 204 except device_errors.CommandFailedError:
211 logging.exception('Failed to provision device %s. Adding to blacklist.', 205 logging.exception('Failed to provision device %s. Adding to blacklist.',
212 str(device)) 206 str(device))
213 device_blacklist.ExtendBlacklist([str(device)]) 207 device_blacklist.ExtendBlacklist([str(device)])
214 208
215 209
216 def ProvisionDevices(options): 210 def ProvisionDevices(options):
217 is_perf = 'perf' in os.environ.get('BUILDBOT_BUILDERNAME', '').lower()
218 if options.device is not None: 211 if options.device is not None:
219 devices = [options.device] 212 devices = [options.device]
220 else: 213 else:
221 devices = android_commands.GetAttachedDevices() 214 devices = android_commands.GetAttachedDevices()
222 215
223 parallel_devices = device_utils.DeviceUtils.parallel(devices) 216 parallel_devices = device_utils.DeviceUtils.parallel(devices)
224 parallel_devices.pMap(ProvisionDevice, options, is_perf) 217 parallel_devices.pMap(ProvisionDevice, options)
225 if options.auto_reconnect: 218 if options.auto_reconnect:
226 LaunchHostHeartbeat() 219 LaunchHostHeartbeat()
227 blacklist = device_blacklist.ReadBlacklist() 220 blacklist = device_blacklist.ReadBlacklist()
228 if all(d in blacklist for d in devices): 221 if all(d in blacklist for d in devices):
229 raise device_errors.NoDevicesError 222 raise device_errors.NoDevicesError
230 return 0 223 return 0
231 224
232 225
233 def main(argv): 226 def main():
234 custom_handler = logging.StreamHandler(sys.stdout) 227 custom_handler = logging.StreamHandler(sys.stdout)
235 custom_handler.setFormatter(run_tests_helper.CustomFormatter()) 228 custom_handler.setFormatter(run_tests_helper.CustomFormatter())
236 logging.getLogger().addHandler(custom_handler) 229 logging.getLogger().addHandler(custom_handler)
237 logging.getLogger().setLevel(logging.INFO) 230 logging.getLogger().setLevel(logging.INFO)
238 231
239 parser = optparse.OptionParser() 232 # TODO(perezju): This script used to rely on the builder name to determine
240 parser.add_option('--min-battery-level', default=95, type='int', 233 # the desired device configuration for perf bots. To safely phase this out,
241 help="Minimum battery level for performance testing " 234 # we now:
242 "(default: 95).") 235 # - expose these configuration settings as command line options
243 parser.add_option('--skip-wipe', action='store_true', default=False, 236 # - set default values for these options based on the builder name, thus
244 help="Don't wipe device data during provisioning.") 237 # matching the previous behaviour of the script on all bots.
245 parser.add_option('--disable-location', action='store_true', default=False, 238 # - explicitly adding these options on the perf bots will also maintain the
246 help="Disallow Google location services on devices.") 239 # script behaviour, namely:
247 parser.add_option('-d', '--device', 240 # --wait-for-battery --disable-network --disable-java-debug
248 help='The serial number of the device to be provisioned') 241 # - after all perf-bot recipes are updated, we can remove the following
249 parser.add_option('-t', '--target', default='Debug', help='The build target') 242 # builder-name-sniffing code and replace |is_perf| with |False|.
250 parser.add_option( 243 is_perf = 'perf' in os.environ.get('BUILDBOT_BUILDERNAME', '').lower()
251 '-r', '--auto-reconnect', action='store_true',
252 help='Push binary which will reboot the device on adb disconnections.')
253 options, args = parser.parse_args(argv[1:])
254 constants.SetBuildType(options.target)
255 244
256 if args: 245 # Recommended options on perf bots:
257 print >> sys.stderr, 'Unused args %s' % args 246 # --disable-network
258 return 1 247 # TODO(tonyg): We eventually want network on. However, currently radios
248 # can cause perfbots to drain faster than they charge.
249 # --wait-for-battery
250 # Some perf bots run benchmarks with USB charging disabled which leads
251 # to gradual draining of the battery. We must wait for a full charge
252 # before starting a run in order to keep the devices online.
259 253
260 return ProvisionDevices(options) 254 parser = argparse.ArgumentParser(
255 description='Provision Android devices with settings required for bots.')
256 parser.add_argument('-d', '--device', metavar='SERIAL',
257 help='the serial number of the device to be provisioned'
258 ' (the default is to provision all devices attached)')
259 parser.add_argument('--skip-wipe', action='store_true', default=False,
260 help="don't wipe device data during provisioning")
261 parser.add_argument('--reboot-timeout', default=600, type=int,
262 metavar='SECS',
263 help='when wiping the device, max number of seconds to'
264 ' wait after each reboot (default: %(default)s)')
265 parser.add_argument('--wait-for-battery', action='store_true',
266 default=is_perf,
267 help='wait for the battery on the devices to charge')
268 parser.add_argument('--min-battery-level', default=95, type=int,
269 metavar='NUM',
270 help='when waiting for battery, minimum battery level'
271 ' required to continue (default: %(default)s)')
272 parser.add_argument('--disable-location', action='store_true',
273 help='disable Google location services on devices')
274 parser.add_argument('--disable-network', action='store_true',
275 default=is_perf,
276 help='disable network access on devices')
277 parser.add_argument('--disable-java-debug', action='store_false',
278 dest='enable_java_debug', default=not is_perf,
279 help='disable Java property asserts and JNI checking')
280 parser.add_argument('-t', '--target', default='Debug',
281 help='the build target (default: %(default)s)')
282 parser.add_argument('-r', '--auto-reconnect', action='store_true',
283 help='push binary which will reboot the device on adb'
284 ' disconnections')
285 args = parser.parse_args()
286 constants.SetBuildType(args.target)
287
288 return ProvisionDevices(args)
261 289
262 290
263 if __name__ == '__main__': 291 if __name__ == '__main__':
264 sys.exit(main(sys.argv)) 292 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698