| Index: build/android/pylib/device/adb_wrapper.py
|
| diff --git a/build/android/pylib/device/adb_wrapper.py b/build/android/pylib/device/adb_wrapper.py
|
| index c7ea3106bfa8ed3ef1d18384af52c6d0fe92a48a..4981f28df033f82966c76ea6ceb8679bcb05430b 100644
|
| --- a/build/android/pylib/device/adb_wrapper.py
|
| +++ b/build/android/pylib/device/adb_wrapper.py
|
| @@ -9,6 +9,7 @@ should be delegated to a higher level (ex. DeviceUtils).
|
| """
|
|
|
| import errno
|
| +import logging
|
| import os
|
|
|
| from pylib import cmd_helper
|
| @@ -44,43 +45,48 @@ class AdbWrapper(object):
|
| Args:
|
| device_serial: The device serial number as a string.
|
| """
|
| + if not device_serial:
|
| + raise ValueError('A device serial must be specified')
|
| self._device_serial = str(device_serial)
|
|
|
| # pylint: disable=unused-argument
|
| @classmethod
|
| @decorators.WithTimeoutAndRetries
|
| - def _RunAdbCmd(cls, arg_list, timeout=None, retries=None, check_error=True):
|
| - cmd = [constants.GetAdbPath()] + arg_list
|
| - exit_code, output = cmd_helper.GetCmdStatusAndOutputWithTimeout(
|
| - cmd, timeout_retry.CurrentTimeoutThread().GetRemainingTime())
|
| - if exit_code != 0:
|
| + def _RunAdbCmd(cls, args, timeout=None, retries=None, device_serial=None,
|
| + check_error=True):
|
| + cmd = [constants.GetAdbPath()]
|
| + if device_serial is not None:
|
| + cmd.extend(['-s', device_serial])
|
| + cmd.extend(args)
|
| + status, output = cmd_helper.GetCmdStatusAndOutputWithTimeout(
|
| + cmd, timeout_retry.CurrentTimeoutThread().GetRemainingTime())
|
| + if status != 0:
|
| raise device_errors.AdbCommandFailedError(
|
| - cmd, 'returned non-zero exit code %d and output %r' %
|
| - (exit_code, output))
|
| + args, output, status, device_serial)
|
| # This catches some errors, including when the device drops offline;
|
| # unfortunately adb is very inconsistent with error reporting so many
|
| # command failures present differently.
|
| - if check_error and output[:len('error:')] == 'error:':
|
| - raise device_errors.AdbCommandFailedError(arg_list, output)
|
| + if check_error and output.startswith('error:'):
|
| + raise device_errors.AdbCommandFailedError(args, output)
|
| return output
|
| # pylint: enable=unused-argument
|
|
|
| - def _DeviceAdbCmd(self, arg_list, timeout, retries, check_error=True):
|
| + def _RunDeviceAdbCmd(self, args, timeout, retries, check_error=True):
|
| """Runs an adb command on the device associated with this object.
|
|
|
| Args:
|
| - arg_list: A list of arguments to adb.
|
| + args: A list of arguments to adb.
|
| timeout: Timeout in seconds.
|
| retries: Number of retries.
|
| check_error: Check that the command doesn't return an error message. This
|
| - does NOT check the return code of shell commands.
|
| + does NOT check the exit status of shell commands.
|
|
|
| Returns:
|
| The output of the command.
|
| """
|
| - return self._RunAdbCmd(
|
| - ['-s', self._device_serial] + arg_list, timeout=timeout,
|
| - retries=retries, check_error=check_error)
|
| + return self._RunAdbCmd(args, timeout=timeout, retries=retries,
|
| + device_serial=self._device_serial,
|
| + check_error=check_error)
|
|
|
| def __eq__(self, other):
|
| """Consider instances equal if they refer to the same device.
|
| @@ -117,7 +123,7 @@ class AdbWrapper(object):
|
| AdbWrapper instances.
|
| """
|
| output = cls._RunAdbCmd(['devices'], timeout=timeout, retries=retries)
|
| - lines = [line.split() for line in output.split('\n')]
|
| + lines = [line.split() for line in output.splitlines()]
|
| return [AdbWrapper(line[0]) for line in lines
|
| if len(line) == 2 and line[1] == 'device']
|
|
|
| @@ -139,7 +145,7 @@ class AdbWrapper(object):
|
| retries: (optional) Number of retries to attempt.
|
| """
|
| _VerifyLocalFileExists(local)
|
| - self._DeviceAdbCmd(['push', local, remote], timeout, retries)
|
| + self._RunDeviceAdbCmd(['push', local, remote], timeout, retries)
|
|
|
| def Pull(self, remote, local, timeout=60*5, retries=_DEFAULT_RETRIES):
|
| """Pulls a file from the device to the host.
|
| @@ -150,17 +156,17 @@ class AdbWrapper(object):
|
| timeout: (optional) Timeout per try in seconds.
|
| retries: (optional) Number of retries to attempt.
|
| """
|
| - self._DeviceAdbCmd(['pull', remote, local], timeout, retries)
|
| + self._RunDeviceAdbCmd(['pull', remote, local], timeout, retries)
|
| _VerifyLocalFileExists(local)
|
|
|
| - def Shell(self, command, expect_rc=0, timeout=_DEFAULT_TIMEOUT,
|
| + def Shell(self, command, expect_status=0, timeout=_DEFAULT_TIMEOUT,
|
| retries=_DEFAULT_RETRIES):
|
| """Runs a shell command on the device.
|
|
|
| Args:
|
| - command: The shell command to run.
|
| - expect_rc: (optional) Check that the command's return code matches this
|
| - value. Default is 0. If set to None the test is skipped.
|
| + command: A string with the shell command to run.
|
| + expect_status: (optional) Check that the command's exit status matches
|
| + this value. Default is 0. If set to None the test is skipped.
|
| timeout: (optional) Timeout per try in seconds.
|
| retries: (optional) Number of retries to attempt.
|
|
|
| @@ -168,33 +174,30 @@ class AdbWrapper(object):
|
| The output of the shell command as a string.
|
|
|
| Raises:
|
| - device_errors.AdbCommandFailedError: If the return code doesn't match
|
| - |expect_rc|.
|
| + device_errors.AdbCommandFailedError: If the exit status doesn't match
|
| + |expect_status|.
|
| """
|
| - if expect_rc is None:
|
| - actual_command = command
|
| + if expect_status is None:
|
| + args = ['shell', command]
|
| else:
|
| - actual_command = '%s; echo %%$?;' % command.rstrip()
|
| - output = self._DeviceAdbCmd(
|
| - ['shell', actual_command], timeout, retries, check_error=False)
|
| - if expect_rc is not None:
|
| + args = ['shell', '%s; echo %%$?;' % command.rstrip()]
|
| + output = self._RunDeviceAdbCmd(args, timeout, retries, check_error=False)
|
| + if expect_status is not None:
|
| output_end = output.rfind('%')
|
| if output_end < 0:
|
| - # causes the string for rc to become empty and also raise a ValueError
|
| + # causes the status string to become empty and raise a ValueError
|
| output_end = len(output)
|
|
|
| try:
|
| - rc = int(output[output_end+1:])
|
| + status = int(output[output_end+1:])
|
| except ValueError:
|
| + logging.warning('exit status of shell command %r missing.', command)
|
| raise device_errors.AdbCommandFailedError(
|
| - ['shell'], 'command %r on device produced output %r where no'
|
| - ' valid return code was found' % (actual_command, output),
|
| - self._device_serial)
|
| -
|
| + args, output, device_serial=self._device_serial)
|
| output = output[:output_end]
|
| - if rc != expect_rc:
|
| - raise device_errors.AdbShellCommandFailedError(
|
| - command, rc, output, self._device_serial)
|
| + if status != expect_status:
|
| + raise device_errors.AdbCommandFailedError(
|
| + args, output, status, self._device_serial)
|
| return output
|
|
|
| def Logcat(self, filter_spec=None, timeout=_DEFAULT_TIMEOUT,
|
| @@ -212,7 +215,7 @@ class AdbWrapper(object):
|
| cmd = ['logcat']
|
| if filter_spec is not None:
|
| cmd.append(filter_spec)
|
| - return self._DeviceAdbCmd(cmd, timeout, retries, check_error=False)
|
| + return self._RunDeviceAdbCmd(cmd, timeout, retries, check_error=False)
|
|
|
| def Forward(self, local, remote, timeout=_DEFAULT_TIMEOUT,
|
| retries=_DEFAULT_RETRIES):
|
| @@ -232,7 +235,8 @@ class AdbWrapper(object):
|
| timeout: (optional) Timeout per try in seconds.
|
| retries: (optional) Number of retries to attempt.
|
| """
|
| - self._DeviceAdbCmd(['forward', str(local), str(remote)], timeout, retries)
|
| + self._RunDeviceAdbCmd(['forward', str(local), str(remote)], timeout,
|
| + retries)
|
|
|
| def JDWP(self, timeout=_DEFAULT_TIMEOUT, retries=_DEFAULT_RETRIES):
|
| """List of PIDs of processes hosting a JDWP transport.
|
| @@ -245,7 +249,7 @@ class AdbWrapper(object):
|
| A list of PIDs as strings.
|
| """
|
| return [a.strip() for a in
|
| - self._DeviceAdbCmd(['jdwp'], timeout, retries).split('\n')]
|
| + self._RunDeviceAdbCmd(['jdwp'], timeout, retries).split('\n')]
|
|
|
| def Install(self, apk_path, forward_lock=False, reinstall=False,
|
| sd_card=False, timeout=60*2, retries=_DEFAULT_RETRIES):
|
| @@ -268,9 +272,10 @@ class AdbWrapper(object):
|
| if sd_card:
|
| cmd.append('-s')
|
| cmd.append(apk_path)
|
| - output = self._DeviceAdbCmd(cmd, timeout, retries)
|
| + output = self._RunDeviceAdbCmd(cmd, timeout, retries)
|
| if 'Success' not in output:
|
| - raise device_errors.AdbCommandFailedError(cmd, output)
|
| + raise device_errors.AdbCommandFailedError(
|
| + cmd, output, device_serial=self._device_serial)
|
|
|
| def Uninstall(self, package, keep_data=False, timeout=_DEFAULT_TIMEOUT,
|
| retries=_DEFAULT_RETRIES):
|
| @@ -286,9 +291,10 @@ class AdbWrapper(object):
|
| if keep_data:
|
| cmd.append('-k')
|
| cmd.append(package)
|
| - output = self._DeviceAdbCmd(cmd, timeout, retries)
|
| + output = self._RunDeviceAdbCmd(cmd, timeout, retries)
|
| if 'Failure' in output:
|
| - raise device_errors.AdbCommandFailedError(cmd, output)
|
| + raise device_errors.AdbCommandFailedError(
|
| + cmd, output, device_serial=self._device_serial)
|
|
|
| def Backup(self, path, packages=None, apk=False, shared=False,
|
| nosystem=True, include_all=False, timeout=_DEFAULT_TIMEOUT,
|
| @@ -319,7 +325,7 @@ class AdbWrapper(object):
|
| cmd.extend(packages)
|
| assert bool(packages) ^ bool(include_all), (
|
| 'Provide \'packages\' or set \'include_all\' but not both.')
|
| - ret = self._DeviceAdbCmd(cmd, timeout, retries)
|
| + ret = self._RunDeviceAdbCmd(cmd, timeout, retries)
|
| _VerifyLocalFileExists(path)
|
| return ret
|
|
|
| @@ -332,7 +338,7 @@ class AdbWrapper(object):
|
| retries: (optional) Number of retries to attempt.
|
| """
|
| _VerifyLocalFileExists(path)
|
| - self._DeviceAdbCmd(['restore'] + [path], timeout, retries)
|
| + self._RunDeviceAdbCmd(['restore'] + [path], timeout, retries)
|
|
|
| def WaitForDevice(self, timeout=60*5, retries=_DEFAULT_RETRIES):
|
| """Block until the device is online.
|
| @@ -341,7 +347,7 @@ class AdbWrapper(object):
|
| timeout: (optional) Timeout per try in seconds.
|
| retries: (optional) Number of retries to attempt.
|
| """
|
| - self._DeviceAdbCmd(['wait-for-device'], timeout, retries)
|
| + self._RunDeviceAdbCmd(['wait-for-device'], timeout, retries)
|
|
|
| def GetState(self, timeout=_DEFAULT_TIMEOUT, retries=_DEFAULT_RETRIES):
|
| """Get device state.
|
| @@ -353,7 +359,7 @@ class AdbWrapper(object):
|
| Returns:
|
| One of 'offline', 'bootloader', or 'device'.
|
| """
|
| - return self._DeviceAdbCmd(['get-state'], timeout, retries).strip()
|
| + return self._RunDeviceAdbCmd(['get-state'], timeout, retries).strip()
|
|
|
| def GetDevPath(self, timeout=_DEFAULT_TIMEOUT, retries=_DEFAULT_RETRIES):
|
| """Gets the device path.
|
| @@ -365,11 +371,11 @@ class AdbWrapper(object):
|
| Returns:
|
| The device path (e.g. usb:3-4)
|
| """
|
| - return self._DeviceAdbCmd(['get-devpath'], timeout, retries)
|
| + return self._RunDeviceAdbCmd(['get-devpath'], timeout, retries)
|
|
|
| def Remount(self, timeout=_DEFAULT_TIMEOUT, retries=_DEFAULT_RETRIES):
|
| """Remounts the /system partition on the device read-write."""
|
| - self._DeviceAdbCmd(['remount'], timeout, retries)
|
| + self._RunDeviceAdbCmd(['remount'], timeout, retries)
|
|
|
| def Reboot(self, to_bootloader=False, timeout=60*5,
|
| retries=_DEFAULT_RETRIES):
|
| @@ -384,7 +390,7 @@ class AdbWrapper(object):
|
| cmd = ['reboot-bootloader']
|
| else:
|
| cmd = ['reboot']
|
| - self._DeviceAdbCmd(cmd, timeout, retries)
|
| + self._RunDeviceAdbCmd(cmd, timeout, retries)
|
|
|
| def Root(self, timeout=_DEFAULT_TIMEOUT, retries=_DEFAULT_RETRIES):
|
| """Restarts the adbd daemon with root permissions, if possible.
|
| @@ -393,7 +399,7 @@ class AdbWrapper(object):
|
| timeout: (optional) Timeout per try in seconds.
|
| retries: (optional) Number of retries to attempt.
|
| """
|
| - output = self._DeviceAdbCmd(['root'], timeout, retries)
|
| + output = self._RunDeviceAdbCmd(['root'], timeout, retries)
|
| if 'cannot' in output:
|
| - raise device_errors.AdbCommandFailedError(['root'], output)
|
| -
|
| + raise device_errors.AdbCommandFailedError(
|
| + ['root'], output, device_serial=self._device_serial)
|
|
|