1# Copyright 2014 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import logging 6import os 7 8from telemetry.core import util 9from telemetry.internal.platform import cros_device 10from telemetry.internal.platform import device 11from telemetry.internal.platform.profiler import monsoon 12 13from devil.android import device_blacklist 14from devil.android import device_errors 15from devil.android import device_utils 16from devil.android.sdk import adb_wrapper 17 18 19class AndroidDevice(device.Device): 20 """ Class represents information for connecting to an android device. 21 22 Attributes: 23 device_id: the device's serial string created by adb to uniquely 24 identify an emulator/device instance. This string can be found by running 25 'adb devices' command 26 enable_performance_mode: when this is set to True, android platform will be 27 set to high performance mode after browser is started. 28 """ 29 def __init__(self, device_id, enable_performance_mode=True): 30 super(AndroidDevice, self).__init__( 31 name='Android device %s' % device_id, guid=device_id) 32 self._device_id = device_id 33 self._enable_performance_mode = enable_performance_mode 34 35 @classmethod 36 def GetAllConnectedDevices(cls, blacklist): 37 device_serials = GetDeviceSerials(blacklist) 38 return [cls(s) for s in device_serials] 39 40 @property 41 def device_id(self): 42 return self._device_id 43 44 @property 45 def enable_performance_mode(self): 46 return self._enable_performance_mode 47 48 49def _ListSerialsOfHealthyOnlineDevices(blacklist): 50 return [d.adb.GetDeviceSerial() 51 for d in device_utils.DeviceUtils.HealthyDevices(blacklist) 52 if d.IsOnline()] 53 54 55def GetDeviceSerials(blacklist): 56 """Return the list of device serials of healthy devices. 57 58 If a preferred device has been set with ANDROID_SERIAL, it will be first in 59 the returned list. The arguments specify what devices to include in the list. 60 """ 61 62 device_serials = _ListSerialsOfHealthyOnlineDevices(blacklist) 63 64 # The monsoon provides power for the device, so for devices with no 65 # real battery, we need to turn them on after the monsoon enables voltage 66 # output to the device. 67 if not device_serials: 68 try: 69 m = monsoon.Monsoon(wait=False) 70 m.SetUsbPassthrough(1) 71 m.SetVoltage(3.8) 72 m.SetMaxCurrent(8) 73 logging.warn(""" 74Monsoon power monitor detected, but no Android devices. 75 76The Monsoon's power output has been enabled. Please now ensure that: 77 78 1. The Monsoon's front and back USB are connected to the host. 79 2. The device is connected to the Monsoon's main and USB channels. 80 3. The device is turned on. 81 82Waiting for device... 83""") 84 util.WaitFor(_ListSerialsOfHealthyOnlineDevices(blacklist), 600) 85 device_serials = _ListSerialsOfHealthyOnlineDevices(blacklist) 86 except IOError: 87 return [] 88 89 preferred_device = os.environ.get('ANDROID_SERIAL') 90 if preferred_device in device_serials: 91 logging.warn( 92 'ANDROID_SERIAL is defined. Put %s in the first of the' 93 'discovered devices list.' % preferred_device) 94 device_serials.remove(preferred_device) 95 device_serials.insert(0, preferred_device) 96 return device_serials 97 98 99def GetDevice(finder_options): 100 """Return a Platform instance for the device specified by |finder_options|.""" 101 android_platform_options = finder_options.remote_platform_options 102 if not CanDiscoverDevices(): 103 logging.info( 104 'No adb command found. Will not try searching for Android browsers.') 105 return None 106 107 if android_platform_options.android_blacklist_file: 108 blacklist = device_blacklist.Blacklist( 109 android_platform_options.android_blacklist_file) 110 else: 111 blacklist = None 112 113 if (android_platform_options.device 114 and android_platform_options.device in GetDeviceSerials(blacklist)): 115 return AndroidDevice( 116 android_platform_options.device, 117 enable_performance_mode=not finder_options.no_performance_mode) 118 119 devices = AndroidDevice.GetAllConnectedDevices(blacklist) 120 if len(devices) == 0: 121 logging.warn('No android devices found.') 122 return None 123 if len(devices) > 1: 124 logging.warn( 125 'Multiple devices attached. Please specify one of the following:\n' + 126 '\n'.join([' --device=%s' % d.device_id for d in devices])) 127 return None 128 return devices[0] 129 130 131def _HasValidAdb(): 132 """Returns true if adb is present. 133 134 Note that this currently will return True even if the adb that's present 135 cannot run on this system. 136 """ 137 if os.name != 'posix' or cros_device.IsRunningOnCrOS(): 138 return False 139 140 try: 141 adb_path = adb_wrapper.AdbWrapper.GetAdbPath() 142 except device_errors.NoAdbError: 143 return False 144 145 if os.path.isabs(adb_path) and not os.path.exists(adb_path): 146 return False 147 148 return True 149 150 151def CanDiscoverDevices(): 152 """Returns true if devices are discoverable via adb.""" 153 if not _HasValidAdb(): 154 return False 155 156 try: 157 device_utils.DeviceUtils.HealthyDevices(None) 158 return True 159 except (device_errors.CommandFailedError, device_errors.CommandTimeoutError, 160 device_errors.NoAdbError, OSError): 161 return False 162 163 164def FindAllAvailableDevices(options): 165 """Returns a list of available devices. 166 """ 167 # Disable Android device discovery when remote testing a CrOS device 168 if options.cros_remote: 169 return [] 170 171 android_platform_options = options.remote_platform_options 172 devices = [] 173 try: 174 if CanDiscoverDevices(): 175 blacklist = None 176 if android_platform_options.android_blacklist_file: 177 blacklist = device_blacklist.Blacklist( 178 android_platform_options.android_blacklist_file) 179 devices = AndroidDevice.GetAllConnectedDevices(blacklist) 180 finally: 181 if not devices and _HasValidAdb(): 182 try: 183 adb_wrapper.AdbWrapper.KillServer() 184 except device_errors.NoAdbError as e: 185 logging.warning( 186 'adb reported as present, but NoAdbError thrown: %s', str(e)) 187 188 return devices 189