Home | History | Annotate | Download | only in platform
      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