Index: build/android/buildbot/bb_device_status_check.py |
diff --git a/build/android/buildbot/bb_device_status_check.py b/build/android/buildbot/bb_device_status_check.py |
deleted file mode 100755 |
index 01f2c2e312d61a53ec51b374642b78269b2eeb72..0000000000000000000000000000000000000000 |
--- a/build/android/buildbot/bb_device_status_check.py |
+++ /dev/null |
@@ -1,418 +0,0 @@ |
-#!/usr/bin/env python |
-# |
-# Copyright 2013 The Chromium Authors. All rights reserved. |
-# Use of this source code is governed by a BSD-style license that can be |
-# found in the LICENSE file. |
- |
-"""A class to keep track of devices across builds and report state.""" |
- |
-import argparse |
-import json |
-import logging |
-import os |
-import psutil |
-import re |
-import signal |
-import sys |
- |
-sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) |
-import devil_chromium |
-from devil.android import battery_utils |
-from devil.android import device_blacklist |
-from devil.android import device_errors |
-from devil.android import device_list |
-from devil.android import device_utils |
-from devil.android.sdk import adb_wrapper |
-from devil.constants import exit_codes |
-from devil.utils import lsusb |
-from devil.utils import reset_usb |
-from devil.utils import run_tests_helper |
-from pylib.constants import host_paths |
- |
-_RE_DEVICE_ID = re.compile(r'Device ID = (\d+)') |
- |
- |
-def KillAllAdb(): |
- def GetAllAdb(): |
- for p in psutil.process_iter(): |
- try: |
- if 'adb' in p.name: |
- yield p |
- except (psutil.NoSuchProcess, psutil.AccessDenied): |
- pass |
- |
- for sig in [signal.SIGTERM, signal.SIGQUIT, signal.SIGKILL]: |
- for p in GetAllAdb(): |
- try: |
- logging.info('kill %d %d (%s [%s])', sig, p.pid, p.name, |
- ' '.join(p.cmdline)) |
- p.send_signal(sig) |
- except (psutil.NoSuchProcess, psutil.AccessDenied): |
- pass |
- for p in GetAllAdb(): |
- try: |
- logging.error('Unable to kill %d (%s [%s])', p.pid, p.name, |
- ' '.join(p.cmdline)) |
- except (psutil.NoSuchProcess, psutil.AccessDenied): |
- pass |
- |
- |
-def _IsBlacklisted(serial, blacklist): |
- return blacklist and serial in blacklist.Read() |
- |
- |
-def _BatteryStatus(device, blacklist): |
- battery_info = {} |
- try: |
- battery = battery_utils.BatteryUtils(device) |
- battery_info = battery.GetBatteryInfo(timeout=5) |
- battery_level = int(battery_info.get('level', 100)) |
- |
- if battery_level < 15: |
- logging.error('Critically low battery level (%d)', battery_level) |
- battery = battery_utils.BatteryUtils(device) |
- if not battery.GetCharging(): |
- battery.SetCharging(True) |
- if blacklist: |
- blacklist.Extend([device.adb.GetDeviceSerial()], reason='low_battery') |
- |
- except device_errors.CommandFailedError: |
- logging.exception('Failed to get battery information for %s', |
- str(device)) |
- |
- return battery_info |
- |
- |
-def _IMEISlice(device): |
- imei_slice = '' |
- try: |
- for l in device.RunShellCommand(['dumpsys', 'iphonesubinfo'], |
- check_return=True, timeout=5): |
- m = _RE_DEVICE_ID.match(l) |
- if m: |
- imei_slice = m.group(1)[-6:] |
- except device_errors.CommandFailedError: |
- logging.exception('Failed to get IMEI slice for %s', str(device)) |
- |
- return imei_slice |
- |
- |
-def DeviceStatus(devices, blacklist): |
- """Generates status information for the given devices. |
- |
- Args: |
- devices: The devices to generate status for. |
- blacklist: The current device blacklist. |
- Returns: |
- A dict of the following form: |
- { |
- '<serial>': { |
- 'serial': '<serial>', |
- 'adb_status': str, |
- 'usb_status': bool, |
- 'blacklisted': bool, |
- # only if the device is connected and not blacklisted |
- 'type': ro.build.product, |
- 'build': ro.build.id, |
- 'build_detail': ro.build.fingerprint, |
- 'battery': { |
- ... |
- }, |
- 'imei_slice': str, |
- 'wifi_ip': str, |
- }, |
- ... |
- } |
- """ |
- adb_devices = { |
- a[0].GetDeviceSerial(): a |
- for a in adb_wrapper.AdbWrapper.Devices(desired_state=None, long_list=True) |
- } |
- usb_devices = set(lsusb.get_android_devices()) |
- |
- def blacklisting_device_status(device): |
- serial = device.adb.GetDeviceSerial() |
- adb_status = ( |
- adb_devices[serial][1] if serial in adb_devices |
- else 'missing') |
- usb_status = bool(serial in usb_devices) |
- |
- device_status = { |
- 'serial': serial, |
- 'adb_status': adb_status, |
- 'usb_status': usb_status, |
- } |
- |
- if not _IsBlacklisted(serial, blacklist): |
- if adb_status == 'device': |
- try: |
- build_product = device.build_product |
- build_id = device.build_id |
- build_fingerprint = device.GetProp('ro.build.fingerprint', cache=True) |
- wifi_ip = device.GetProp('dhcp.wlan0.ipaddress') |
- battery_info = _BatteryStatus(device, blacklist) |
- imei_slice = _IMEISlice(device) |
- |
- if (device.product_name == 'mantaray' and |
- battery_info.get('AC powered', None) != 'true'): |
- logging.error('Mantaray device not connected to AC power.') |
- |
- device_status.update({ |
- 'ro.build.product': build_product, |
- 'ro.build.id': build_id, |
- 'ro.build.fingerprint': build_fingerprint, |
- 'battery': battery_info, |
- 'imei_slice': imei_slice, |
- 'wifi_ip': wifi_ip, |
- |
- # TODO(jbudorick): Remove these once no clients depend on them. |
- 'type': build_product, |
- 'build': build_id, |
- 'build_detail': build_fingerprint, |
- }) |
- |
- except device_errors.CommandFailedError: |
- logging.exception('Failure while getting device status for %s.', |
- str(device)) |
- if blacklist: |
- blacklist.Extend([serial], reason='status_check_failure') |
- |
- except device_errors.CommandTimeoutError: |
- logging.exception('Timeout while getting device status for %s.', |
- str(device)) |
- if blacklist: |
- blacklist.Extend([serial], reason='status_check_timeout') |
- |
- elif blacklist: |
- blacklist.Extend([serial], |
- reason=adb_status if usb_status else 'offline') |
- |
- device_status['blacklisted'] = _IsBlacklisted(serial, blacklist) |
- |
- return device_status |
- |
- parallel_devices = device_utils.DeviceUtils.parallel(devices) |
- statuses = parallel_devices.pMap(blacklisting_device_status).pGet(None) |
- return statuses |
- |
- |
-def RecoverDevices(devices, blacklist): |
- """Attempts to recover any inoperable devices in the provided list. |
- |
- Args: |
- devices: The list of devices to attempt to recover. |
- blacklist: The current device blacklist, which will be used then |
- reset. |
- Returns: |
- Nothing. |
- """ |
- |
- statuses = DeviceStatus(devices, blacklist) |
- |
- should_restart_usb = set( |
- status['serial'] for status in statuses |
- if (not status['usb_status'] |
- or status['adb_status'] in ('offline', 'missing'))) |
- should_restart_adb = should_restart_usb.union(set( |
- status['serial'] for status in statuses |
- if status['adb_status'] == 'unauthorized')) |
- should_reboot_device = should_restart_adb.union(set( |
- status['serial'] for status in statuses |
- if status['blacklisted'])) |
- |
- logging.debug('Should restart USB for:') |
- for d in should_restart_usb: |
- logging.debug(' %s', d) |
- logging.debug('Should restart ADB for:') |
- for d in should_restart_adb: |
- logging.debug(' %s', d) |
- logging.debug('Should reboot:') |
- for d in should_reboot_device: |
- logging.debug(' %s', d) |
- |
- if blacklist: |
- blacklist.Reset() |
- |
- if should_restart_adb: |
- KillAllAdb() |
- for serial in should_restart_usb: |
- try: |
- reset_usb.reset_android_usb(serial) |
- except IOError: |
- logging.exception('Unable to reset USB for %s.', serial) |
- if blacklist: |
- blacklist.Extend([serial], reason='usb_failure') |
- except device_errors.DeviceUnreachableError: |
- logging.exception('Unable to reset USB for %s.', serial) |
- if blacklist: |
- blacklist.Extend([serial], reason='offline') |
- |
- def blacklisting_recovery(device): |
- if _IsBlacklisted(device.adb.GetDeviceSerial(), blacklist): |
- logging.debug('%s is blacklisted, skipping recovery.', str(device)) |
- return |
- |
- if str(device) in should_reboot_device: |
- try: |
- device.WaitUntilFullyBooted(retries=0) |
- return |
- except (device_errors.CommandTimeoutError, |
- device_errors.CommandFailedError): |
- logging.exception('Failure while waiting for %s. ' |
- 'Attempting to recover.', str(device)) |
- |
- try: |
- try: |
- device.Reboot(block=False, timeout=5, retries=0) |
- except device_errors.CommandTimeoutError: |
- logging.warning('Timed out while attempting to reboot %s normally.' |
- 'Attempting alternative reboot.', str(device)) |
- # The device drops offline before we can grab the exit code, so |
- # we don't check for status. |
- device.adb.Root() |
- device.adb.Shell('echo b > /proc/sysrq-trigger', expect_status=None, |
- timeout=5, retries=0) |
- except device_errors.CommandFailedError: |
- logging.exception('Failed to reboot %s.', str(device)) |
- if blacklist: |
- blacklist.Extend([device.adb.GetDeviceSerial()], |
- reason='reboot_failure') |
- except device_errors.CommandTimeoutError: |
- logging.exception('Timed out while rebooting %s.', str(device)) |
- if blacklist: |
- blacklist.Extend([device.adb.GetDeviceSerial()], |
- reason='reboot_timeout') |
- |
- try: |
- device.WaitUntilFullyBooted(retries=0) |
- except device_errors.CommandFailedError: |
- logging.exception('Failure while waiting for %s.', str(device)) |
- if blacklist: |
- blacklist.Extend([device.adb.GetDeviceSerial()], |
- reason='reboot_failure') |
- except device_errors.CommandTimeoutError: |
- logging.exception('Timed out while waiting for %s.', str(device)) |
- if blacklist: |
- blacklist.Extend([device.adb.GetDeviceSerial()], |
- reason='reboot_timeout') |
- |
- device_utils.DeviceUtils.parallel(devices).pMap(blacklisting_recovery) |
- |
- |
-def main(): |
- parser = argparse.ArgumentParser() |
- parser.add_argument('--out-dir', |
- help='Directory where the device path is stored', |
- default=os.path.join(host_paths.DIR_SOURCE_ROOT, 'out')) |
- parser.add_argument('--restart-usb', action='store_true', |
- help='DEPRECATED. ' |
- 'This script now always tries to reset USB.') |
- parser.add_argument('--json-output', |
- help='Output JSON information into a specified file.') |
- parser.add_argument('--adb-path', type=os.path.abspath, |
- help='Absolute path to the adb binary to use.') |
- parser.add_argument('--blacklist-file', help='Device blacklist JSON file.') |
- parser.add_argument('--known-devices-file', action='append', default=[], |
- dest='known_devices_files', |
- help='Path to known device lists.') |
- parser.add_argument('-v', '--verbose', action='count', default=1, |
- help='Log more information.') |
- |
- args = parser.parse_args() |
- |
- run_tests_helper.SetLogLevel(args.verbose) |
- |
- devil_chromium.Initialize(adb_path=args.adb_path) |
- |
- blacklist = (device_blacklist.Blacklist(args.blacklist_file) |
- if args.blacklist_file |
- else None) |
- |
- expected_devices = set() |
- try: |
- for path in args.known_devices_files: |
- if os.path.exists(path): |
- expected_devices.update(device_list.GetPersistentDeviceList(path)) |
- except IOError: |
- logging.warning('Problem reading %s, skipping.', path) |
- |
- logging.info('Expected devices:') |
- for device in expected_devices: |
- logging.info(' %s', device) |
- |
- usb_devices = set(lsusb.get_android_devices()) |
- devices = [device_utils.DeviceUtils(s) |
- for s in expected_devices.union(usb_devices)] |
- |
- RecoverDevices(devices, blacklist) |
- statuses = DeviceStatus(devices, blacklist) |
- |
- # Log the state of all devices. |
- for status in statuses: |
- logging.info(status['serial']) |
- adb_status = status.get('adb_status') |
- blacklisted = status.get('blacklisted') |
- logging.info(' USB status: %s', |
- 'online' if status.get('usb_status') else 'offline') |
- logging.info(' ADB status: %s', adb_status) |
- logging.info(' Blacklisted: %s', str(blacklisted)) |
- if adb_status == 'device' and not blacklisted: |
- logging.info(' Device type: %s', status.get('ro.build.product')) |
- logging.info(' OS build: %s', status.get('ro.build.id')) |
- logging.info(' OS build fingerprint: %s', |
- status.get('ro.build.fingerprint')) |
- logging.info(' Battery state:') |
- for k, v in status.get('battery', {}).iteritems(): |
- logging.info(' %s: %s', k, v) |
- logging.info(' IMEI slice: %s', status.get('imei_slice')) |
- logging.info(' WiFi IP: %s', status.get('wifi_ip')) |
- |
- # Update the last devices file(s). |
- for path in args.known_devices_files: |
- device_list.WritePersistentDeviceList( |
- path, [status['serial'] for status in statuses]) |
- |
- # Write device info to file for buildbot info display. |
- if os.path.exists('/home/chrome-bot'): |
- with open('/home/chrome-bot/.adb_device_info', 'w') as f: |
- for status in statuses: |
- try: |
- if status['adb_status'] == 'device': |
- f.write('{serial} {adb_status} {build_product} {build_id} ' |
- '{temperature:.1f}C {level}%\n'.format( |
- serial=status['serial'], |
- adb_status=status['adb_status'], |
- build_product=status['type'], |
- build_id=status['build'], |
- temperature=float(status['battery']['temperature']) / 10, |
- level=status['battery']['level'] |
- )) |
- elif status.get('usb_status', False): |
- f.write('{serial} {adb_status}\n'.format( |
- serial=status['serial'], |
- adb_status=status['adb_status'] |
- )) |
- else: |
- f.write('{serial} offline\n'.format( |
- serial=status['serial'] |
- )) |
- except Exception: # pylint: disable=broad-except |
- pass |
- |
- # Dump the device statuses to JSON. |
- if args.json_output: |
- with open(args.json_output, 'wb') as f: |
- f.write(json.dumps(statuses, indent=4)) |
- |
- live_devices = [status['serial'] for status in statuses |
- if (status['adb_status'] == 'device' |
- and not _IsBlacklisted(status['serial'], blacklist))] |
- |
- # If all devices failed, or if there are no devices, it's an infra error. |
- if not live_devices: |
- logging.error('No available devices.') |
- return 0 if live_devices else exit_codes.INFRA |
- |
- |
-if __name__ == '__main__': |
- sys.exit(main()) |