device_utils.py revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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""" 6Provides a variety of device interactions based on adb. 7 8Eventually, this will be based on adb_wrapper. 9""" 10# pylint: disable=W0613 11 12import time 13 14import pylib.android_commands 15from pylib.device import adb_wrapper 16from pylib.device import decorators 17from pylib.device import device_errors 18from pylib.utils import parallelizer 19 20_DEFAULT_TIMEOUT = 30 21_DEFAULT_RETRIES = 3 22 23 24@decorators.WithExplicitTimeoutAndRetries( 25 _DEFAULT_TIMEOUT, _DEFAULT_RETRIES) 26def GetAVDs(): 27 """ Returns a list of Android Virtual Devices. 28 29 Returns: 30 A list containing the configured AVDs. 31 """ 32 return pylib.android_commands.GetAVDs() 33 34 35@decorators.WithExplicitTimeoutAndRetries( 36 _DEFAULT_TIMEOUT, _DEFAULT_RETRIES) 37def RestartServer(): 38 """ Restarts the adb server. 39 40 Raises: 41 CommandFailedError if we fail to kill or restart the server. 42 """ 43 pylib.android_commands.AndroidCommands().RestartAdbServer() 44 45 46class DeviceUtils(object): 47 48 def __init__(self, device, default_timeout=_DEFAULT_TIMEOUT, 49 default_retries=_DEFAULT_RETRIES): 50 """ DeviceUtils constructor. 51 52 Args: 53 device: Either a device serial, an existing AdbWrapper instance, an 54 an existing AndroidCommands instance, or nothing. 55 default_timeout: An integer containing the default number of seconds to 56 wait for an operation to complete if no explicit value 57 is provided. 58 default_retries: An integer containing the default number or times an 59 operation should be retried on failure if no explicit 60 value is provided. 61 """ 62 self.old_interface = None 63 if isinstance(device, basestring): 64 self.old_interface = pylib.android_commands.AndroidCommands(device) 65 elif isinstance(device, adb_wrapper.AdbWrapper): 66 self.old_interface = pylib.android_commands.AndroidCommands(str(device)) 67 elif isinstance(device, pylib.android_commands.AndroidCommands): 68 self.old_interface = device 69 elif not device: 70 self.old_interface = pylib.android_commands.AndroidCommands() 71 else: 72 raise ValueError('Unsupported type passed for argument "device"') 73 self._default_timeout = default_timeout 74 self._default_retries = default_retries 75 assert(hasattr(self, decorators.DEFAULT_TIMEOUT_ATTR)) 76 assert(hasattr(self, decorators.DEFAULT_RETRIES_ATTR)) 77 78 @decorators.WithTimeoutAndRetriesFromInstance() 79 def IsOnline(self, timeout=None, retries=None): 80 """ Checks whether the device is online. 81 82 Args: 83 timeout: An integer containing the number of seconds to wait for the 84 operation to complete. 85 retries: An integer containing the number of times the operation should 86 be retried if it fails. 87 Returns: 88 True if the device is online, False otherwise. 89 """ 90 return self.old_interface.IsOnline() 91 92 @decorators.WithTimeoutAndRetriesFromInstance() 93 def HasRoot(self, timeout=None, retries=None): 94 """ Checks whether or not adbd has root privileges. 95 96 Args: 97 timeout: Same as for |IsOnline|. 98 retries: Same as for |IsOnline|. 99 Returns: 100 True if adbd has root privileges, False otherwise. 101 """ 102 return self.old_interface.IsRootEnabled() 103 104 @decorators.WithTimeoutAndRetriesFromInstance() 105 def EnableRoot(self, timeout=None, retries=None): 106 """ Restarts adbd with root privileges. 107 108 Args: 109 timeout: Same as for |IsOnline|. 110 retries: Same as for |IsOnline|. 111 Raises: 112 CommandFailedError if root could not be enabled. 113 """ 114 if not self.old_interface.EnableAdbRoot(): 115 raise device_errors.CommandFailedError( 116 'adb root', 'Could not enable root.') 117 118 @decorators.WithTimeoutAndRetriesFromInstance() 119 def GetExternalStoragePath(self, timeout=None, retries=None): 120 """ Get the device's path to its SD card. 121 122 Args: 123 timeout: Same as for |IsOnline|. 124 retries: Same as for |IsOnline|. 125 Returns: 126 The device's path to its SD card. 127 """ 128 try: 129 return self.old_interface.GetExternalStorage() 130 except AssertionError as e: 131 raise device_errors.CommandFailedError(str(e)) 132 133 @decorators.WithTimeoutAndRetriesFromInstance() 134 def WaitUntilFullyBooted(self, wifi=False, timeout=None, retries=None): 135 """ Wait for the device to fully boot. 136 137 This means waiting for the device to boot, the package manager to be 138 available, and the SD card to be ready. It can optionally mean waiting 139 for wifi to come up, too. 140 141 Args: 142 wifi: A boolean indicating if we should wait for wifi to come up or not. 143 timeout: Same as for |IsOnline|. 144 retries: Same as for |IsOnline|. 145 Raises: 146 CommandTimeoutError if one of the component waits times out. 147 DeviceUnreachableError if the device becomes unresponsive. 148 """ 149 self.old_interface.WaitForSystemBootCompleted(timeout) 150 self.old_interface.WaitForDevicePm() 151 self.old_interface.WaitForSdCardReady(timeout) 152 if wifi: 153 while not 'Wi-Fi is enabled' in ( 154 self.old_interface.RunShellCommand('dumpsys wifi')): 155 time.sleep(0.1) 156 157 def __str__(self): 158 """Returns the device serial.""" 159 return self.old_interface.GetDevice() 160 161 @staticmethod 162 def parallel(devices=None, async=False): 163 """ Creates a Parallelizer to operate over the provided list of devices. 164 165 If |devices| is either |None| or an empty list, the Parallelizer will 166 operate over all attached devices. 167 168 Args: 169 devices: A list of either DeviceUtils instances or objects from 170 from which DeviceUtils instances can be constructed. If None, 171 all attached devices will be used. 172 async: If true, returns a Parallelizer that runs operations 173 asynchronously. 174 Returns: 175 A Parallelizer operating over |devices|. 176 """ 177 if not devices or len(devices) == 0: 178 devices = pylib.android_commands.GetAttachedDevices() 179 parallelizer_type = (parallelizer.Parallelizer if async 180 else parallelizer.SyncParallelizer) 181 return parallelizer_type([ 182 d if isinstance(d, DeviceUtils) else DeviceUtils(d) 183 for d in devices]) 184 185