| Index: build/android/pylib/device/device_utils.py
|
| diff --git a/build/android/pylib/device/device_utils.py b/build/android/pylib/device/device_utils.py
|
| index 4adde1d47b273da180277eb0fcb8906c94e92fb6..97019236374fd8adaa3a8b021b97fd3f25a8f5ea 100644
|
| --- a/build/android/pylib/device/device_utils.py
|
| +++ b/build/android/pylib/device/device_utils.py
|
| @@ -2,8 +2,7 @@
|
| # Use of this source code is governed by a BSD-style license that can be
|
| # found in the LICENSE file.
|
|
|
| -"""
|
| -Provides a variety of device interactions based on adb.
|
| +"""Provides a variety of device interactions based on adb.
|
|
|
| Eventually, this will be based on adb_wrapper.
|
| """
|
| @@ -15,6 +14,7 @@ import pylib.android_commands
|
| from pylib.device import adb_wrapper
|
| from pylib.device import decorators
|
| from pylib.device import device_errors
|
| +from pylib.utils import apk_helper
|
| from pylib.utils import parallelizer
|
|
|
| _DEFAULT_TIMEOUT = 30
|
| @@ -24,7 +24,7 @@ _DEFAULT_RETRIES = 3
|
| @decorators.WithExplicitTimeoutAndRetries(
|
| _DEFAULT_TIMEOUT, _DEFAULT_RETRIES)
|
| def GetAVDs():
|
| - """ Returns a list of Android Virtual Devices.
|
| + """Returns a list of Android Virtual Devices.
|
|
|
| Returns:
|
| A list containing the configured AVDs.
|
| @@ -35,7 +35,7 @@ def GetAVDs():
|
| @decorators.WithExplicitTimeoutAndRetries(
|
| _DEFAULT_TIMEOUT, _DEFAULT_RETRIES)
|
| def RestartServer():
|
| - """ Restarts the adb server.
|
| + """Restarts the adb server.
|
|
|
| Raises:
|
| CommandFailedError if we fail to kill or restart the server.
|
| @@ -47,7 +47,7 @@ class DeviceUtils(object):
|
|
|
| def __init__(self, device, default_timeout=_DEFAULT_TIMEOUT,
|
| default_retries=_DEFAULT_RETRIES):
|
| - """ DeviceUtils constructor.
|
| + """DeviceUtils constructor.
|
|
|
| Args:
|
| device: Either a device serial, an existing AdbWrapper instance, an
|
| @@ -77,7 +77,7 @@ class DeviceUtils(object):
|
|
|
| @decorators.WithTimeoutAndRetriesFromInstance()
|
| def IsOnline(self, timeout=None, retries=None):
|
| - """ Checks whether the device is online.
|
| + """Checks whether the device is online.
|
|
|
| Args:
|
| timeout: An integer containing the number of seconds to wait for the
|
| @@ -91,7 +91,7 @@ class DeviceUtils(object):
|
|
|
| @decorators.WithTimeoutAndRetriesFromInstance()
|
| def HasRoot(self, timeout=None, retries=None):
|
| - """ Checks whether or not adbd has root privileges.
|
| + """Checks whether or not adbd has root privileges.
|
|
|
| Args:
|
| timeout: Same as for |IsOnline|.
|
| @@ -103,7 +103,7 @@ class DeviceUtils(object):
|
|
|
| @decorators.WithTimeoutAndRetriesFromInstance()
|
| def EnableRoot(self, timeout=None, retries=None):
|
| - """ Restarts adbd with root privileges.
|
| + """Restarts adbd with root privileges.
|
|
|
| Args:
|
| timeout: Same as for |IsOnline|.
|
| @@ -113,11 +113,11 @@ class DeviceUtils(object):
|
| """
|
| if not self.old_interface.EnableAdbRoot():
|
| raise device_errors.CommandFailedError(
|
| - 'adb root', 'Could not enable root.')
|
| + ['adb', 'root'], 'Could not enable root.')
|
|
|
| @decorators.WithTimeoutAndRetriesFromInstance()
|
| def GetExternalStoragePath(self, timeout=None, retries=None):
|
| - """ Get the device's path to its SD card.
|
| + """Get the device's path to its SD card.
|
|
|
| Args:
|
| timeout: Same as for |IsOnline|.
|
| @@ -128,11 +128,12 @@ class DeviceUtils(object):
|
| try:
|
| return self.old_interface.GetExternalStorage()
|
| except AssertionError as e:
|
| - raise device_errors.CommandFailedError(str(e))
|
| + raise device_errors.CommandFailedError(
|
| + ['adb', 'shell', 'echo', '$EXTERNAL_STORAGE'], str(e))
|
|
|
| @decorators.WithTimeoutAndRetriesFromInstance()
|
| def WaitUntilFullyBooted(self, wifi=False, timeout=None, retries=None):
|
| - """ Wait for the device to fully boot.
|
| + """Wait for the device to fully boot.
|
|
|
| This means waiting for the device to boot, the package manager to be
|
| available, and the SD card to be ready. It can optionally mean waiting
|
| @@ -146,6 +147,25 @@ class DeviceUtils(object):
|
| CommandTimeoutError if one of the component waits times out.
|
| DeviceUnreachableError if the device becomes unresponsive.
|
| """
|
| + self._WaitUntilFullyBootedImpl(wifi=wifi, timeout=timeout)
|
| +
|
| + def _WaitUntilFullyBootedImpl(self, wifi=False, timeout=None):
|
| + """ Implementation of WaitUntilFullyBooted.
|
| +
|
| + This is split from WaitUntilFullyBooted to allow other DeviceUtils methods
|
| + to call WaitUntilFullyBooted without spawning a new timeout thread.
|
| +
|
| + TODO(jbudorick) Remove the timeout parameter once this is no longer
|
| + implemented via AndroidCommands.
|
| +
|
| + Args:
|
| + wifi: Same as for |WaitUntilFullyBooted|.
|
| + timeout: Same as for |IsOnline|.
|
| + Raises:
|
| + Same as for |WaitUntilFullyBooted|.
|
| + """
|
| + if timeout is None:
|
| + timeout = self._default_timeout
|
| self.old_interface.WaitForSystemBootCompleted(timeout)
|
| self.old_interface.WaitForDevicePm()
|
| self.old_interface.WaitForSdCardReady(timeout)
|
| @@ -154,13 +174,71 @@ class DeviceUtils(object):
|
| self.old_interface.RunShellCommand('dumpsys wifi')):
|
| time.sleep(0.1)
|
|
|
| + @decorators.WithTimeoutAndRetriesDefaults(
|
| + 10 * _DEFAULT_TIMEOUT, _DEFAULT_RETRIES)
|
| + def Reboot(self, block=True, timeout=None, retries=None):
|
| + """Reboot the device.
|
| +
|
| + Args:
|
| + block: A boolean indicating if we should wait for the reboot to complete.
|
| + timeout: Same as for |IsOnline|.
|
| + retries: Same as for |IsOnline|.
|
| + """
|
| + self.old_interface.Reboot()
|
| + if block:
|
| + self._WaitUntilFullyBootedImpl(timeout=timeout)
|
| +
|
| + @decorators.WithTimeoutAndRetriesDefaults(
|
| + 4 * _DEFAULT_TIMEOUT, _DEFAULT_RETRIES)
|
| + def Install(self, apk_path, reinstall=False, timeout=None, retries=None):
|
| + """Install an APK.
|
| +
|
| + Noop if an identical APK is already installed.
|
| +
|
| + Args:
|
| + apk_path: A string containing the path to the APK to install.
|
| + reinstall: A boolean indicating if we should keep any existing app data.
|
| + timeout: Same as for |IsOnline|.
|
| + retries: Same as for |IsOnline|.
|
| + Raises:
|
| + CommandFailedError if the installation fails.
|
| + CommandTimeoutError if the installation times out.
|
| + """
|
| + package_name = apk_helper.GetPackageName(apk_path)
|
| + device_path = self.old_interface.GetApplicationPath(package_name)
|
| + if device_path is not None:
|
| + files_changed = self.old_interface.GetFilesChanged(
|
| + apk_path, device_path, ignore_filenames=True)
|
| + if len(files_changed) > 0:
|
| + should_install = True
|
| + if not reinstall:
|
| + out = self.old_interface.Uninstall(package_name)
|
| + for line in out.splitlines():
|
| + if 'Failure' in line:
|
| + raise device_errors.CommandFailedError(
|
| + ['adb', 'uninstall', package_name], line.strip())
|
| + else:
|
| + should_install = False
|
| + else:
|
| + should_install = True
|
| + if should_install:
|
| + try:
|
| + out = self.old_interface.Install(apk_path, reinstall=reinstall)
|
| + for line in out.splitlines():
|
| + if 'Failure' in line:
|
| + raise device_errors.CommandFailedError(
|
| + ['adb', 'install', apk_path], line.strip())
|
| + except AssertionError as e:
|
| + raise device_errors.CommandFailedError(
|
| + ['adb', 'install', apk_path], str(e))
|
| +
|
| def __str__(self):
|
| """Returns the device serial."""
|
| return self.old_interface.GetDevice()
|
|
|
| @staticmethod
|
| def parallel(devices=None, async=False):
|
| - """ Creates a Parallelizer to operate over the provided list of devices.
|
| + """Creates a Parallelizer to operate over the provided list of devices.
|
|
|
| If |devices| is either |None| or an empty list, the Parallelizer will
|
| operate over all attached devices.
|
|
|