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 logging | 13 import logging |
| 14 import optparse | 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_errors | 25 from pylib.device import device_errors |
| 25 from pylib.device import device_utils | 26 from pylib.device import device_utils |
| 26 | 27 |
| 27 sys.path.append(os.path.join(constants.DIR_SOURCE_ROOT, | 28 sys.path.append(os.path.join(constants.DIR_SOURCE_ROOT, |
| 28 'third_party', 'android_testrunner')) | 29 'third_party', 'android_testrunner')) |
| 29 import errors | 30 import errors |
| 30 | 31 |
| 31 def KillHostHeartbeat(): | 32 def KillHostHeartbeat(): |
| 32 ps = subprocess.Popen(['ps', 'aux'], stdout = subprocess.PIPE) | 33 ps = subprocess.Popen(['ps', 'aux'], stdout = subprocess.PIPE) |
| 33 stdout, _ = ps.communicate() | 34 stdout, _ = ps.communicate() |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 147 | 148 |
| 148 if devices_to_reboot: | 149 if devices_to_reboot: |
| 149 try: | 150 try: |
| 150 device_utils.DeviceUtils.parallel(devices_to_reboot).Reboot(True) | 151 device_utils.DeviceUtils.parallel(devices_to_reboot).Reboot(True) |
| 151 except errors.DeviceUnresponsiveError: | 152 except errors.DeviceUnresponsiveError: |
| 152 pass | 153 pass |
| 153 for device_serial in devices_to_reboot: | 154 for device_serial in devices_to_reboot: |
| 154 device.WaitUntilFullyBooted(timeout=90) | 155 device.WaitUntilFullyBooted(timeout=90) |
| 155 | 156 |
| 156 | 157 |
| 158 def ProvisionDevice(device_serial, is_perf, disable_location): | |
| 159 device = device_utils.DeviceUtils(device_serial) | |
| 160 device.old_interface.EnableAdbRoot() | |
| 161 _ConfigureLocalProperties(device, is_perf) | |
| 162 device_settings_map = device_settings.DETERMINISTIC_DEVICE_SETTINGS | |
| 163 if disable_location: | |
| 164 device_settings_map.update(device_settings.DISABLE_LOCATION_SETTING) | |
| 165 else: | |
| 166 device_settings_map.update(device_settings.ENABLE_LOCATION_SETTING) | |
| 167 device_settings.ConfigureContentSettingsDict(device, device_settings_map) | |
| 168 device_settings.SetLockScreenSettings(device) | |
| 169 if is_perf: | |
| 170 # TODO(tonyg): We eventually want network on. However, currently radios | |
| 171 # can cause perfbots to drain faster than they charge. | |
| 172 device_settings.ConfigureContentSettingsDict( | |
| 173 device, device_settings.NETWORK_DISABLED_SETTINGS) | |
| 174 # Some perf bots run benchmarks with USB charging disabled which leads | |
| 175 # to gradual draining of the battery. We must wait for a full charge | |
| 176 # before starting a run in order to keep the devices online. | |
| 177 try: | |
| 178 battery_info = device.old_interface.GetBatteryInfo() | |
| 179 except Exception as e: | |
| 180 battery_info = {} | |
| 181 logging.error('Unable to obtain battery info for %s, %s', | |
| 182 device_serial, e) | |
| 183 | |
| 184 while int(battery_info.get('level', 100)) < 95: | |
| 185 if not device.old_interface.IsDeviceCharging(): | |
| 186 if device.old_interface.CanControlUsbCharging(): | |
| 187 device.old_interface.EnableUsbCharging() | |
| 188 else: | |
| 189 logging.error('Device is not charging') | |
| 190 break | |
| 191 logging.info('Waiting for device to charge. Current level=%s', | |
| 192 battery_info.get('level', 0)) | |
| 193 time.sleep(60) | |
| 194 battery_info = device.old_interface.GetBatteryInfo() | |
| 195 device.RunShellCommand('date -u %f' % time.time(), as_root=True) | |
| 196 | |
| 197 | |
| 157 def ProvisionDevices(options): | 198 def ProvisionDevices(options): |
| 158 is_perf = 'perf' in os.environ.get('BUILDBOT_BUILDERNAME', '').lower() | 199 is_perf = 'perf' in os.environ.get('BUILDBOT_BUILDERNAME', '').lower() |
| 159 # TODO(jbudorick): Parallelize provisioning of all attached devices after | 200 # TODO(jbudorick): Parallelize provisioning of all attached devices after |
| 160 # switching from AndroidCommands. | 201 # switching from AndroidCommands. |
| 161 if options.device is not None: | 202 if options.device is not None: |
| 162 devices = [options.device] | 203 devices = [options.device] |
| 163 else: | 204 else: |
| 164 devices = android_commands.GetAttachedDevices() | 205 devices = android_commands.GetAttachedDevices() |
| 165 | 206 |
| 166 # Wipe devices (unless --skip-wipe was specified) | 207 # Wipe devices (unless --skip-wipe was specified) |
| 167 if not options.skip_wipe: | 208 if not options.skip_wipe: |
| 168 WipeDevicesIfPossible(devices) | 209 WipeDevicesIfPossible(devices) |
| 169 | 210 |
| 211 bad_devices = [] | |
| 170 # Provision devices | 212 # Provision devices |
| 171 for device_serial in devices: | 213 for device_serial in devices: |
| 172 device = device_utils.DeviceUtils(device_serial) | 214 try: |
| 173 device.old_interface.EnableAdbRoot() | 215 ProvisionDevice(device_serial, is_perf, options.disable_location) |
| 174 _ConfigureLocalProperties(device, is_perf) | 216 except errors.WaitForResponseTimedOutError: |
| 175 device_settings_map = device_settings.DETERMINISTIC_DEVICE_SETTINGS | 217 logging.info('Timed out waiting for device %s. Adding to blacklist.', |
| 176 if options.disable_location: | 218 device_serial) |
| 177 device_settings_map.update(device_settings.DISABLE_LOCATION_SETTING) | 219 bad_devices.append(device_serial) |
| 178 else: | 220 # This depends on the call to device_blacklist.ResetBlacklist() in |
| 179 device_settings_map.update(device_settings.ENABLE_LOCATION_SETTING) | 221 # bb_device_status_check.py for device to come back for next build. |
| 180 device_settings.ConfigureContentSettingsDict(device, device_settings_map) | 222 device_blacklist.ExtendBlacklist([device_serial]) |
| 181 device_settings.SetLockScreenSettings(device) | 223 devices = [device for device in devices if device not in bad_devices] |
| 182 if is_perf: | |
| 183 # TODO(tonyg): We eventually want network on. However, currently radios | |
| 184 # can cause perfbots to drain faster than they charge. | |
| 185 device_settings.ConfigureContentSettingsDict( | |
| 186 device, device_settings.NETWORK_DISABLED_SETTINGS) | |
| 187 # Some perf bots run benchmarks with USB charging disabled which leads | |
| 188 # to gradual draining of the battery. We must wait for a full charge | |
| 189 # before starting a run in order to keep the devices online. | |
| 190 try: | |
| 191 battery_info = device.old_interface.GetBatteryInfo() | |
| 192 except Exception as e: | |
| 193 battery_info = {} | |
| 194 logging.error('Unable to obtain battery info for %s, %s', | |
| 195 device_serial, e) | |
| 196 | 224 |
| 197 while int(battery_info.get('level', 100)) < 95: | 225 # If there are no good devices |
| 198 if not device.old_interface.IsDeviceCharging(): | 226 if not devices: |
| 199 if device.old_interface.CanControlUsbCharging(): | 227 raise device_errors.NoDevicesError |
| 200 device.old_interface.EnableUsbCharging() | 228 |
| 201 else: | |
| 202 logging.error('Device is not charging') | |
| 203 break | |
| 204 logging.info('Waiting for device to charge. Current level=%s', | |
| 205 battery_info.get('level', 0)) | |
| 206 time.sleep(60) | |
| 207 battery_info = device.old_interface.GetBatteryInfo() | |
| 208 device.RunShellCommand('date -u %f' % time.time(), as_root=True) | |
| 209 try: | 229 try: |
| 210 device_utils.DeviceUtils.parallel(devices).Reboot(True) | 230 device_utils.DeviceUtils.parallel(devices).Reboot(True) |
| 211 except errors.DeviceUnresponsiveError: | 231 except errors.DeviceUnresponsiveError: |
| 212 pass | 232 pass |
| 213 for device_serial in devices: | 233 for device_serial in devices: |
| 214 device = device_utils.DeviceUtils(device_serial) | 234 device = device_utils.DeviceUtils(device_serial) |
| 215 device.WaitUntilFullyBooted(timeout=90) | 235 device.WaitUntilFullyBooted(timeout=90) |
|
cjhopman
2014/08/06 20:24:54
What happens if we hit this timeout? Does the step
navabi
2014/08/06 21:26:56
Done.
| |
| 216 (_, props) = device.old_interface.GetShellCommandStatusAndOutput('getprop') | 236 (_, props) = device.old_interface.GetShellCommandStatusAndOutput('getprop') |
| 217 for prop in props: | 237 for prop in props: |
| 218 print prop | 238 print prop |
| 219 if options.auto_reconnect: | 239 if options.auto_reconnect: |
| 220 PushAndLaunchAdbReboot(devices, options.target) | 240 PushAndLaunchAdbReboot(devices, options.target) |
| 221 | 241 |
| 222 | 242 |
| 223 def main(argv): | 243 def main(argv): |
| 224 logging.basicConfig(level=logging.INFO) | 244 logging.basicConfig(level=logging.INFO) |
| 225 | 245 |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 239 | 259 |
| 240 if args: | 260 if args: |
| 241 print >> sys.stderr, 'Unused args %s' % args | 261 print >> sys.stderr, 'Unused args %s' % args |
| 242 return 1 | 262 return 1 |
| 243 | 263 |
| 244 ProvisionDevices(options) | 264 ProvisionDevices(options) |
| 245 | 265 |
| 246 | 266 |
| 247 if __name__ == '__main__': | 267 if __name__ == '__main__': |
| 248 sys.exit(main(sys.argv)) | 268 sys.exit(main(sys.argv)) |
| OLD | NEW |