1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/webrtc/trunk/build/android/device_status_check.py Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,170 @@ 1.4 +#!/usr/bin/env python 1.5 +# 1.6 +# Copyright (c) 2012 The Chromium Authors. All rights reserved. 1.7 +# Use of this source code is governed by a BSD-style license that can be 1.8 +# found in the LICENSE file. 1.9 + 1.10 +"""A class to keep track of devices across builds and report state.""" 1.11 +import logging 1.12 +import optparse 1.13 +import os 1.14 +import smtplib 1.15 +import sys 1.16 + 1.17 +from pylib import buildbot_report 1.18 +from pylib.android_commands import GetAttachedDevices 1.19 +from pylib.cmd_helper import GetCmdOutput 1.20 + 1.21 + 1.22 +def DeviceInfo(serial): 1.23 + """Gathers info on a device via various adb calls. 1.24 + 1.25 + Args: 1.26 + serial: The serial of the attached device to construct info about. 1.27 + 1.28 + Returns: 1.29 + Tuple of device type, build id and report as a string. 1.30 + """ 1.31 + 1.32 + def AdbShellCmd(cmd): 1.33 + return GetCmdOutput('adb -s %s shell %s' % (serial, cmd), 1.34 + shell=True).strip() 1.35 + 1.36 + device_type = AdbShellCmd('getprop ro.build.product') 1.37 + device_build = AdbShellCmd('getprop ro.build.id') 1.38 + 1.39 + report = ['Device %s (%s)' % (serial, device_type), 1.40 + ' Build: %s (%s)' % (device_build, 1.41 + AdbShellCmd('getprop ro.build.fingerprint')), 1.42 + ' Battery: %s%%' % AdbShellCmd('dumpsys battery | grep level ' 1.43 + "| awk '{print $2}'"), 1.44 + ' Battery temp: %s' % AdbShellCmd('dumpsys battery' 1.45 + '| grep temp ' 1.46 + "| awk '{print $2}'"), 1.47 + ' IMEI slice: %s' % AdbShellCmd('dumpsys iphonesubinfo ' 1.48 + '| grep Device' 1.49 + "| awk '{print $4}'")[-6:], 1.50 + ' Wifi IP: %s' % AdbShellCmd('getprop dhcp.wlan0.ipaddress'), 1.51 + ''] 1.52 + 1.53 + return device_type, device_build, '\n'.join(report) 1.54 + 1.55 + 1.56 +def CheckForMissingDevices(options, adb_online_devs): 1.57 + """Uses file of previous online devices to detect broken phones. 1.58 + 1.59 + Args: 1.60 + options: out_dir parameter of options argument is used as the base 1.61 + directory to load and update the cache file. 1.62 + adb_online_devs: A list of serial numbers of the currently visible 1.63 + and online attached devices. 1.64 + """ 1.65 + # TODO(navabi): remove this once the bug that causes different number 1.66 + # of devices to be detected between calls is fixed. 1.67 + logger = logging.getLogger() 1.68 + logger.setLevel(logging.INFO) 1.69 + 1.70 + out_dir = os.path.abspath(options.out_dir) 1.71 + 1.72 + def ReadDeviceList(file_name): 1.73 + devices_path = os.path.join(out_dir, file_name) 1.74 + devices = [] 1.75 + try: 1.76 + with open(devices_path) as f: 1.77 + devices = f.read().splitlines() 1.78 + except IOError: 1.79 + # Ignore error, file might not exist 1.80 + pass 1.81 + return devices 1.82 + 1.83 + def WriteDeviceList(file_name, device_list): 1.84 + path = os.path.join(out_dir, file_name) 1.85 + if not os.path.exists(out_dir): 1.86 + os.makedirs(out_dir) 1.87 + with open(path, 'w') as f: 1.88 + # Write devices currently visible plus devices previously seen. 1.89 + f.write('\n'.join(set(device_list))) 1.90 + 1.91 + last_devices_path = os.path.join(out_dir, '.last_devices') 1.92 + last_devices = ReadDeviceList('.last_devices') 1.93 + 1.94 + missing_devs = list(set(last_devices) - set(adb_online_devs)) 1.95 + if missing_devs: 1.96 + from_address = 'buildbot@chromium.org' 1.97 + to_address = 'chromium-android-device-alerts@google.com' 1.98 + bot_name = os.environ['BUILDBOT_BUILDERNAME'] 1.99 + slave_name = os.environ['BUILDBOT_SLAVENAME'] 1.100 + num_online_devs = len(adb_online_devs) 1.101 + subject = 'Devices offline on %s, %s (%d remaining).' % (slave_name, 1.102 + bot_name, 1.103 + num_online_devs) 1.104 + buildbot_report.PrintWarning() 1.105 + devices_missing_msg = '%d devices not detected.' % len(missing_devs) 1.106 + buildbot_report.PrintSummaryText(devices_missing_msg) 1.107 + 1.108 + # TODO(navabi): Debug by printing both output from GetCmdOutput and 1.109 + # GetAttachedDevices to compare results. 1.110 + body = '\n'.join( 1.111 + ['Current online devices: %s' % adb_online_devs, 1.112 + '%s are no longer visible. Were they removed?\n' % missing_devs, 1.113 + 'SHERIFF: See go/chrome_device_monitor', 1.114 + 'Cache file: %s\n\n' % last_devices_path, 1.115 + 'adb devices: %s' % GetCmdOutput(['adb', 'devices']), 1.116 + 'adb devices(GetAttachedDevices): %s' % GetAttachedDevices()]) 1.117 + 1.118 + print body 1.119 + 1.120 + # Only send email if the first time a particular device goes offline 1.121 + last_missing = ReadDeviceList('.last_missing') 1.122 + new_missing_devs = set(missing_devs) - set(last_missing) 1.123 + 1.124 + if new_missing_devs: 1.125 + msg_body = '\r\n'.join( 1.126 + ['From: %s' % from_address, 1.127 + 'To: %s' % to_address, 1.128 + 'Subject: %s' % subject, 1.129 + '', body]) 1.130 + try: 1.131 + server = smtplib.SMTP('localhost') 1.132 + server.sendmail(from_address, [to_address], msg_body) 1.133 + server.quit() 1.134 + except Exception as e: 1.135 + print 'Failed to send alert email. Error: %s' % e 1.136 + else: 1.137 + new_devs = set(adb_online_devs) - set(last_devices) 1.138 + if new_devs and os.path.exists(last_devices_path): 1.139 + buildbot_report.PrintWarning() 1.140 + buildbot_report.PrintSummaryText( 1.141 + '%d new devices detected' % len(new_devs)) 1.142 + print ('New devices detected %s. And now back to your ' 1.143 + 'regularly scheduled program.' % list(new_devs)) 1.144 + WriteDeviceList('.last_devices', (adb_online_devs + last_devices)) 1.145 + WriteDeviceList('.last_missing', missing_devs) 1.146 + 1.147 + 1.148 +def main(): 1.149 + parser = optparse.OptionParser() 1.150 + parser.add_option('', '--out-dir', 1.151 + help='Directory where the device path is stored', 1.152 + default=os.path.join(os.path.dirname(__file__), '..', 1.153 + '..', 'out')) 1.154 + 1.155 + options, args = parser.parse_args() 1.156 + if args: 1.157 + parser.error('Unknown options %s' % args) 1.158 + buildbot_report.PrintNamedStep('Device Status Check') 1.159 + devices = GetAttachedDevices() 1.160 + types, builds, reports = [], [], [] 1.161 + if devices: 1.162 + types, builds, reports = zip(*[DeviceInfo(dev) for dev in devices]) 1.163 + 1.164 + unique_types = list(set(types)) 1.165 + unique_builds = list(set(builds)) 1.166 + 1.167 + buildbot_report.PrintMsg('Online devices: %d. Device types %s, builds %s' 1.168 + % (len(devices), unique_types, unique_builds)) 1.169 + print '\n'.join(reports) 1.170 + CheckForMissingDevices(options, devices) 1.171 + 1.172 +if __name__ == '__main__': 1.173 + sys.exit(main())