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