media/webrtc/trunk/build/android/device_status_check.py

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:ade59c865e9d
1 #!/usr/bin/env python
2 #
3 # Copyright (c) 2012 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 """A class to keep track of devices across builds and report state."""
8 import logging
9 import optparse
10 import os
11 import smtplib
12 import sys
13
14 from pylib import buildbot_report
15 from pylib.android_commands import GetAttachedDevices
16 from pylib.cmd_helper import GetCmdOutput
17
18
19 def DeviceInfo(serial):
20 """Gathers info on a device via various adb calls.
21
22 Args:
23 serial: The serial of the attached device to construct info about.
24
25 Returns:
26 Tuple of device type, build id and report as a string.
27 """
28
29 def AdbShellCmd(cmd):
30 return GetCmdOutput('adb -s %s shell %s' % (serial, cmd),
31 shell=True).strip()
32
33 device_type = AdbShellCmd('getprop ro.build.product')
34 device_build = AdbShellCmd('getprop ro.build.id')
35
36 report = ['Device %s (%s)' % (serial, device_type),
37 ' Build: %s (%s)' % (device_build,
38 AdbShellCmd('getprop ro.build.fingerprint')),
39 ' Battery: %s%%' % AdbShellCmd('dumpsys battery | grep level '
40 "| awk '{print $2}'"),
41 ' Battery temp: %s' % AdbShellCmd('dumpsys battery'
42 '| grep temp '
43 "| awk '{print $2}'"),
44 ' IMEI slice: %s' % AdbShellCmd('dumpsys iphonesubinfo '
45 '| grep Device'
46 "| awk '{print $4}'")[-6:],
47 ' Wifi IP: %s' % AdbShellCmd('getprop dhcp.wlan0.ipaddress'),
48 '']
49
50 return device_type, device_build, '\n'.join(report)
51
52
53 def CheckForMissingDevices(options, adb_online_devs):
54 """Uses file of previous online devices to detect broken phones.
55
56 Args:
57 options: out_dir parameter of options argument is used as the base
58 directory to load and update the cache file.
59 adb_online_devs: A list of serial numbers of the currently visible
60 and online attached devices.
61 """
62 # TODO(navabi): remove this once the bug that causes different number
63 # of devices to be detected between calls is fixed.
64 logger = logging.getLogger()
65 logger.setLevel(logging.INFO)
66
67 out_dir = os.path.abspath(options.out_dir)
68
69 def ReadDeviceList(file_name):
70 devices_path = os.path.join(out_dir, file_name)
71 devices = []
72 try:
73 with open(devices_path) as f:
74 devices = f.read().splitlines()
75 except IOError:
76 # Ignore error, file might not exist
77 pass
78 return devices
79
80 def WriteDeviceList(file_name, device_list):
81 path = os.path.join(out_dir, file_name)
82 if not os.path.exists(out_dir):
83 os.makedirs(out_dir)
84 with open(path, 'w') as f:
85 # Write devices currently visible plus devices previously seen.
86 f.write('\n'.join(set(device_list)))
87
88 last_devices_path = os.path.join(out_dir, '.last_devices')
89 last_devices = ReadDeviceList('.last_devices')
90
91 missing_devs = list(set(last_devices) - set(adb_online_devs))
92 if missing_devs:
93 from_address = 'buildbot@chromium.org'
94 to_address = 'chromium-android-device-alerts@google.com'
95 bot_name = os.environ['BUILDBOT_BUILDERNAME']
96 slave_name = os.environ['BUILDBOT_SLAVENAME']
97 num_online_devs = len(adb_online_devs)
98 subject = 'Devices offline on %s, %s (%d remaining).' % (slave_name,
99 bot_name,
100 num_online_devs)
101 buildbot_report.PrintWarning()
102 devices_missing_msg = '%d devices not detected.' % len(missing_devs)
103 buildbot_report.PrintSummaryText(devices_missing_msg)
104
105 # TODO(navabi): Debug by printing both output from GetCmdOutput and
106 # GetAttachedDevices to compare results.
107 body = '\n'.join(
108 ['Current online devices: %s' % adb_online_devs,
109 '%s are no longer visible. Were they removed?\n' % missing_devs,
110 'SHERIFF: See go/chrome_device_monitor',
111 'Cache file: %s\n\n' % last_devices_path,
112 'adb devices: %s' % GetCmdOutput(['adb', 'devices']),
113 'adb devices(GetAttachedDevices): %s' % GetAttachedDevices()])
114
115 print body
116
117 # Only send email if the first time a particular device goes offline
118 last_missing = ReadDeviceList('.last_missing')
119 new_missing_devs = set(missing_devs) - set(last_missing)
120
121 if new_missing_devs:
122 msg_body = '\r\n'.join(
123 ['From: %s' % from_address,
124 'To: %s' % to_address,
125 'Subject: %s' % subject,
126 '', body])
127 try:
128 server = smtplib.SMTP('localhost')
129 server.sendmail(from_address, [to_address], msg_body)
130 server.quit()
131 except Exception as e:
132 print 'Failed to send alert email. Error: %s' % e
133 else:
134 new_devs = set(adb_online_devs) - set(last_devices)
135 if new_devs and os.path.exists(last_devices_path):
136 buildbot_report.PrintWarning()
137 buildbot_report.PrintSummaryText(
138 '%d new devices detected' % len(new_devs))
139 print ('New devices detected %s. And now back to your '
140 'regularly scheduled program.' % list(new_devs))
141 WriteDeviceList('.last_devices', (adb_online_devs + last_devices))
142 WriteDeviceList('.last_missing', missing_devs)
143
144
145 def main():
146 parser = optparse.OptionParser()
147 parser.add_option('', '--out-dir',
148 help='Directory where the device path is stored',
149 default=os.path.join(os.path.dirname(__file__), '..',
150 '..', 'out'))
151
152 options, args = parser.parse_args()
153 if args:
154 parser.error('Unknown options %s' % args)
155 buildbot_report.PrintNamedStep('Device Status Check')
156 devices = GetAttachedDevices()
157 types, builds, reports = [], [], []
158 if devices:
159 types, builds, reports = zip(*[DeviceInfo(dev) for dev in devices])
160
161 unique_types = list(set(types))
162 unique_builds = list(set(builds))
163
164 buildbot_report.PrintMsg('Online devices: %d. Device types %s, builds %s'
165 % (len(devices), unique_types, unique_builds))
166 print '\n'.join(reports)
167 CheckForMissingDevices(options, devices)
168
169 if __name__ == '__main__':
170 sys.exit(main())

mercurial