OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # | 2 # |
3 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 """A class to keep track of devices across builds and report state.""" | 7 """A class to keep track of devices across builds and report state.""" |
8 import logging | 8 import logging |
9 import optparse | 9 import optparse |
10 import os | 10 import os |
(...skipping 11 matching lines...) Expand all Loading... | |
22 """Gathers info on a device via various adb calls. | 22 """Gathers info on a device via various adb calls. |
23 | 23 |
24 Args: | 24 Args: |
25 serial: The serial of the attached device to construct info about. | 25 serial: The serial of the attached device to construct info about. |
26 | 26 |
27 Returns: | 27 Returns: |
28 Tuple of device type, build id, report as a string, error messages, and | 28 Tuple of device type, build id, report as a string, error messages, and |
29 boolean indicating whether or not device can be used for testing. | 29 boolean indicating whether or not device can be used for testing. |
30 """ | 30 """ |
31 | 31 |
32 def AdbShellCmd(cmd): | |
33 return GetCmdOutput('adb -s %s shell %s' % (serial, cmd), | |
34 shell=True).strip() | |
35 | |
36 device_adb = android_commands.AndroidCommands(serial) | 32 device_adb = android_commands.AndroidCommands(serial) |
37 | 33 |
38 # TODO(navabi): Replace AdbShellCmd with device_adb. | 34 def AdbShellCommand(cmd): |
39 device_type = AdbShellCmd('getprop ro.build.product') | 35 return '\n'.join(device_adb.RunShellCommand(cmd)) |
40 device_build = AdbShellCmd('getprop ro.build.id') | |
41 device_build_type = AdbShellCmd('getprop ro.build.type') | |
42 device_product_name = AdbShellCmd('getprop ro.product.name') | |
43 | 36 |
44 setup_wizard_disabled = AdbShellCmd( | 37 device_type = AdbShellCommand('getprop ro.build.product') |
38 device_build = AdbShellCommand('getprop ro.build.id') | |
39 device_build_type = AdbShellCommand('getprop ro.build.type') | |
40 device_product_name = AdbShellCommand('getprop ro.product.name') | |
41 | |
42 setup_wizard_disabled = device_adb.RunShellCommand( | |
45 'getprop ro.setupwizard.mode') == 'DISABLED' | 43 'getprop ro.setupwizard.mode') == 'DISABLED' |
46 battery = AdbShellCmd('dumpsys battery') | 44 battery = AdbShellCommand('dumpsys battery') |
47 install_output = GetCmdOutput( | 45 install_output = GetCmdOutput( |
48 ['%s/build/android/adb_install_apk.py' % constants.DIR_SOURCE_ROOT, '--apk', | 46 ['%s/build/android/adb_install_apk.py' % constants.DIR_SOURCE_ROOT, '--apk', |
49 '%s/build/android/CheckInstallApk-debug.apk' % constants.DIR_SOURCE_ROOT]) | 47 '%s/build/android/CheckInstallApk-debug.apk' % constants.DIR_SOURCE_ROOT]) |
50 install_speed_found = re.findall('(\d+) KB/s', install_output) | 48 install_speed_found = re.findall('(\d+) KB/s', install_output) |
51 if install_speed_found: | 49 if install_speed_found: |
52 install_speed = int(install_speed_found[0]) | 50 install_speed = int(install_speed_found[0]) |
53 else: | 51 else: |
54 install_speed = 'Unknown' | 52 install_speed = 'Unknown' |
55 if 'Error' in battery: | 53 if 'Error' in battery: |
56 ac_power = 'Unknown' | 54 ac_power = 'Unknown' |
57 battery_level = 'Unknown' | 55 battery_level = 'Unknown' |
58 battery_temp = 'Unknown' | 56 battery_temp = 'Unknown' |
59 else: | 57 else: |
60 ac_power = re.findall('AC powered: (\w+)', battery)[0] | 58 ac_power = re.findall('AC powered: (\w+)', battery)[0] |
61 battery_level = int(re.findall('level: (\d+)', battery)[0]) | 59 battery_level = int(re.findall('level: (\d+)', battery)[0]) |
62 battery_temp = float(re.findall('temperature: (\d+)', battery)[0]) / 10 | 60 battery_temp = float(re.findall('temperature: (\d+)', battery)[0]) / 10 |
63 report = ['Device %s (%s)' % (serial, device_type), | 61 report = ['Device %s (%s)' % (serial, device_type), |
64 ' Build: %s (%s)' % (device_build, | 62 ' Build: %s (%s)' % |
65 AdbShellCmd('getprop ro.build.fingerprint')), | 63 (device_build, |
64 AdbShellCommand('getprop ro.build.fingerprint')), | |
66 ' Battery: %s%%' % battery_level, | 65 ' Battery: %s%%' % battery_level, |
67 ' Battery temp: %s' % battery_temp, | 66 ' Battery temp: %s' % battery_temp, |
68 ' IMEI slice: %s' % AdbShellCmd('dumpsys iphonesubinfo ' | 67 ' IMEI slice: %s' % AdbShellCommand('dumpsys iphonesubinfo ' |
69 '| grep Device' | 68 '| grep Device' |
70 "| awk '{print $4}'")[-6:], | 69 "| awk '{print $4}'")[-6:], |
71 ' Wifi IP: %s' % AdbShellCmd('getprop dhcp.wlan0.ipaddress'), | 70 ' Wifi IP: %s' % AdbShellCommand('getprop dhcp.wlan0.ipaddress'), |
72 ' Install Speed: %s KB/s' % install_speed, | 71 ' Install Speed: %s KB/s' % install_speed, |
73 ''] | 72 ''] |
74 | 73 |
75 errors = [] | 74 errors = [] |
76 if battery_level < 15: | 75 if battery_level < 15: |
77 errors += ['Device critically low in battery. Turning off device.'] | 76 errors += ['Device critically low in battery. Turning off device.'] |
78 if (not setup_wizard_disabled and device_build_type != 'user' and | 77 if (not setup_wizard_disabled and device_build_type != 'user' and |
79 not options.no_provisioning_check): | 78 not options.no_provisioning_check): |
80 errors += ['Setup wizard not disabled. Was it provisioned correctly?'] | 79 errors += ['Setup wizard not disabled. Was it provisioned correctly?'] |
81 if device_product_name == 'mantaray' and ac_power != 'true': | 80 if device_product_name == 'mantaray' and ac_power != 'true': |
82 errors += ['Mantaray device not connected to AC power.'] | 81 errors += ['Mantaray device not connected to AC power.'] |
83 # TODO(navabi): Insert warning once we have a better handle of what install | 82 # TODO(navabi): Insert warning once we have a better handle of what install |
84 # speeds to expect. The following lines were causing too many alerts. | 83 # speeds to expect. The following lines were causing too many alerts. |
85 # if install_speed < 500: | 84 # if install_speed < 500: |
86 # errors += ['Device install speed too low. Do not use for testing.'] | 85 # errors += ['Device install speed too low. Do not use for testing.'] |
87 | 86 |
88 # Causing the device status check step fail for slow install speed or low | 87 # Causing the device status check step fail for slow install speed or low |
89 # battery currently is too disruptive to the bots (especially try bots). | 88 # battery currently is too disruptive to the bots (especially try bots). |
90 # Turn off devices with low battery and the step does not fail. | 89 # Turn off devices with low battery and the step does not fail. |
91 if battery_level < 15: | 90 if battery_level < 15: |
92 device_adb.EnableAdbRoot() | 91 device_adb.EnableAdbRoot() |
93 AdbShellCmd('reboot -p') | 92 AdbShellCommand('reboot -p') |
94 return device_type, device_build, '\n'.join(report), errors, True | 93 full_report = '\n'.join(report) |
94 return device_type, device_build, battery_level, full_report, errors, True | |
95 | 95 |
96 | 96 |
97 def CheckForMissingDevices(options, adb_online_devs): | 97 def CheckForMissingDevices(options, adb_online_devs): |
98 """Uses file of previous online devices to detect broken phones. | 98 """Uses file of previous online devices to detect broken phones. |
99 | 99 |
100 Args: | 100 Args: |
101 options: out_dir parameter of options argument is used as the base | 101 options: out_dir parameter of options argument is used as the base |
102 directory to load and update the cache file. | 102 directory to load and update the cache file. |
103 adb_online_devs: A list of serial numbers of the currently visible | 103 adb_online_devs: A list of serial numbers of the currently visible |
104 and online attached devices. | 104 and online attached devices. |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
182 | 182 |
183 def main(): | 183 def main(): |
184 parser = optparse.OptionParser() | 184 parser = optparse.OptionParser() |
185 parser.add_option('', '--out-dir', | 185 parser.add_option('', '--out-dir', |
186 help='Directory where the device path is stored', | 186 help='Directory where the device path is stored', |
187 default=os.path.join(os.path.dirname(__file__), '..', | 187 default=os.path.join(os.path.dirname(__file__), '..', |
188 '..', 'out')) | 188 '..', 'out')) |
189 parser.add_option('--no-provisioning-check', | 189 parser.add_option('--no-provisioning-check', |
190 help='Will not check if devices are provisioned properly.') | 190 help='Will not check if devices are provisioned properly.') |
191 | 191 |
192 parser.add_option('--device-status-dashboard', | |
193 help='Output device status data for dashboard.') | |
194 | |
192 options, args = parser.parse_args() | 195 options, args = parser.parse_args() |
193 if args: | 196 if args: |
194 parser.error('Unknown options %s' % args) | 197 parser.error('Unknown options %s' % args) |
195 devices = android_commands.GetAttachedDevices() | 198 devices = android_commands.GetAttachedDevices() |
196 types, builds, reports, errors = [], [], [], [] | 199 offline_devices = android_commands.GetAttachedOfflineDevices() |
200 | |
201 types, builds, batteries, reports, errors = [], [], [], [], [] | |
197 fail_step_lst = [] | 202 fail_step_lst = [] |
198 if devices: | 203 if devices: |
199 types, builds, reports, errors, fail_step_lst = ( | 204 types, builds, batteries, reports, errors, fail_step_lst = ( |
200 zip(*[DeviceInfo(dev, options) for dev in devices])) | 205 zip(*[DeviceInfo(dev, options) for dev in devices])) |
201 | 206 |
207 if options.device_status_dashboard: | |
208 print '<*>RESULT OnlineDevices: OnlineDevices= %s' % len(devices) | |
frankf
2013/07/16 17:51:19
You can probably use pylib/perf_tests_helper.py
navabi
2013/07/16 19:01:16
Done.
| |
209 print 'RESULT OfflineDevices: OfflineDevice= %s' % len(offline_devices) | |
210 for serial, battery in zip(devices, batteries): | |
211 print 'RESULT DeviceBattery: %s= %s' % (serial, battery) | |
212 return 0 | |
frankf
2013/07/16 17:51:19
Why return here?
navabi
2013/07/16 19:01:16
The idea was that this will be a separate step fro
| |
213 | |
202 err_msg = CheckForMissingDevices(options, devices) or [] | 214 err_msg = CheckForMissingDevices(options, devices) or [] |
203 | 215 |
204 unique_types = list(set(types)) | 216 unique_types = list(set(types)) |
205 unique_builds = list(set(builds)) | 217 unique_builds = list(set(builds)) |
206 | 218 |
207 buildbot_report.PrintMsg('Online devices: %d. Device types %s, builds %s' | 219 buildbot_report.PrintMsg('Online devices: %d. Device types %s, builds %s' |
208 % (len(devices), unique_types, unique_builds)) | 220 % (len(devices), unique_types, unique_builds)) |
209 print '\n'.join(reports) | 221 print '\n'.join(reports) |
210 | 222 |
211 for serial, dev_errors in zip(devices, errors): | 223 for serial, dev_errors in zip(devices, errors): |
(...skipping 12 matching lines...) Expand all Loading... | |
224 # devices with critically low battery or install speed. Remove those devices | 236 # devices with critically low battery or install speed. Remove those devices |
225 # from testing, allowing build to continue with good devices. | 237 # from testing, allowing build to continue with good devices. |
226 return 1 | 238 return 1 |
227 | 239 |
228 if not devices: | 240 if not devices: |
229 return 1 | 241 return 1 |
230 | 242 |
231 | 243 |
232 if __name__ == '__main__': | 244 if __name__ == '__main__': |
233 sys.exit(main()) | 245 sys.exit(main()) |
OLD | NEW |