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