예제 #1
0
    def _RunAdbCmd(cls,
                   args,
                   timeout=None,
                   retries=None,
                   device_serial=None,
                   check_error=True,
                   cpu_affinity=None):
        # pylint: disable=no-member
        try:
            status, output = cmd_helper.GetCmdStatusAndOutputWithTimeout(
                cls._BuildAdbCmd(args,
                                 device_serial,
                                 cpu_affinity=cpu_affinity),
                timeout_retry.CurrentTimeoutThreadGroup().GetRemainingTime())
        except OSError as e:
            if e.errno in (errno.ENOENT, errno.ENOEXEC):
                raise device_errors.NoAdbError(msg=str(e))
            else:
                raise

        if status != 0:
            raise device_errors.AdbCommandFailedError(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.startswith('error:'):
            raise device_errors.AdbCommandFailedError(args, output)
        return output
예제 #2
0
    def Pull(self, remote, local, **kwargs):
        """Pulls a file from the gce instance to the host.

    Args:
      remote: Path on the instance filesystem.
      local: Path on the host filesystem.
    """
        cmd = [
            'scp',
            '-p',
            '-r',
            '-o',
            'UserKnownHostsFile=/dev/null',
            '-o',
            'StrictHostKeyChecking=no',
            'root@%s:%s' % (self._instance_ip, remote),
            local,
        ]
        status, _ = cmd_helper.GetCmdStatusAndOutput(cmd)
        if status:
            raise device_errors.AdbCommandFailedError(
                cmd,
                'File not reachable on host: %s' % local,
                device_serial=str(self))

        try:
            adb_wrapper.VerifyLocalFileExists(local)
        except (subprocess.CalledProcessError, IOError):
            logging.exception(
                'Error when pulling files from android instance.')
            raise device_errors.AdbCommandFailedError(
                cmd,
                'File not reachable on host: %s' % local,
                device_serial=str(self))
예제 #3
0
    def Install(self,
                apk_path,
                forward_lock=False,
                reinstall=False,
                sd_card=False,
                **kwargs):
        """Installs an apk on the gce instance

    Args:
      apk_path: Host path to the APK file.
      forward_lock: (optional) If set forward-locks the app.
      reinstall: (optional) If set reinstalls the app, keeping its data.
      sd_card: (optional) If set installs on the SD card.
    """
        adb_wrapper.VerifyLocalFileExists(apk_path)
        cmd = ['install']
        if forward_lock:
            cmd.append('-l')
        if reinstall:
            cmd.append('-r')
        if sd_card:
            cmd.append('-s')
        self.Push(apk_path, '/data/local/tmp/tmp.apk')
        cmd = ['pm'] + cmd
        cmd.append('/data/local/tmp/tmp.apk')
        output = self.Shell(' '.join(cmd))
        self.Shell('rm /data/local/tmp/tmp.apk')
        if 'Success' not in output:
            raise device_errors.AdbCommandFailedError(
                cmd, output, device_serial=self._device_serial)
예제 #4
0
    def Install(self,
                apk_path,
                forward_lock=False,
                reinstall=False,
                sd_card=False,
                timeout=60 * 2,
                retries=_DEFAULT_RETRIES):
        """Install an apk on the device.

    Args:
      apk_path: Host path to the APK file.
      forward_lock: (optional) If set forward-locks the app.
      reinstall: (optional) If set reinstalls the app, keeping its data.
      sd_card: (optional) If set installs on the SD card.
      timeout: (optional) Timeout per try in seconds.
      retries: (optional) Number of retries to attempt.
    """
        _VerifyLocalFileExists(apk_path)
        cmd = ['install']
        if forward_lock:
            cmd.append('-l')
        if reinstall:
            cmd.append('-r')
        if sd_card:
            cmd.append('-s')
        cmd.append(apk_path)
        output = self._RunDeviceAdbCmd(cmd, timeout, retries)
        if 'Success' not in output:
            raise device_errors.AdbCommandFailedError(
                cmd, output, device_serial=self._device_serial)
예제 #5
0
  def InstallMultiple(self, apk_paths, forward_lock=False, reinstall=False,
                      sd_card=False, allow_downgrade=False, partial=False,
                      timeout=60 * 2, retries=DEFAULT_RETRIES):
    """Install an apk with splits on the device.

    Args:
      apk_paths: Host path to the APK file.
      forward_lock: (optional) If set forward-locks the app.
      reinstall: (optional) If set reinstalls the app, keeping its data.
      sd_card: (optional) If set installs on the SD card.
      allow_downgrade: (optional) Allow versionCode downgrade.
      partial: (optional) Package ID if apk_paths doesn't include all .apks.
      timeout: (optional) Timeout per try in seconds.
      retries: (optional) Number of retries to attempt.
    """
    for path in apk_paths:
      VerifyLocalFileExists(path)
    cmd = ['install-multiple']
    if forward_lock:
      cmd.append('-l')
    if reinstall:
      cmd.append('-r')
    if sd_card:
      cmd.append('-s')
    if allow_downgrade:
      cmd.append('-d')
    if partial:
      cmd.extend(('-p', partial))
    cmd.extend(apk_paths)
    output = self._RunDeviceAdbCmd(cmd, timeout, retries)
    if 'Success' not in output:
      raise device_errors.AdbCommandFailedError(
          cmd, output, device_serial=self._device_serial)
예제 #6
0
  def _RunAdbCmd(cls, args, timeout=None, retries=None, device_serial=None,
                 check_error=True, cpu_affinity=None,
                 ensure_logs_on_timeout=True):
    timeout = timeout_retry.CurrentTimeoutThreadGroup().GetRemainingTime()
    if ensure_logs_on_timeout and timeout:
      timeout = 0.95 * timeout
    try:
      status, output = cmd_helper.GetCmdStatusAndOutputWithTimeout(
          cls._BuildAdbCmd(args, device_serial, cpu_affinity=cpu_affinity),
          timeout, env=cls._ADB_ENV)
    except OSError as e:
      if e.errno in (errno.ENOENT, errno.ENOEXEC):
        raise device_errors.NoAdbError(msg=str(e))
      else:
        raise

    # Best effort to catch errors from adb; unfortunately adb is very
    # inconsistent with error reporting so many command failures present
    # differently.
    if status != 0 or (check_error and output.startswith('error:')):
      not_found_m = _DEVICE_NOT_FOUND_RE.match(output)
      device_waiting_m = _WAITING_FOR_DEVICE_RE.match(output)
      if (device_waiting_m is not None
          or (not_found_m is not None and
              not_found_m.group('serial') == device_serial)):
        raise device_errors.DeviceUnreachableError(device_serial)
      else:
        raise device_errors.AdbCommandFailedError(
            args, output, status, device_serial)

    return output
예제 #7
0
 def testPicklable_AdbCommandFailedError(self):
     original = device_errors.AdbCommandFailedError(
         ['these', 'are', 'adb', 'args'],
         'adb failure output',
         status=':(',
         device_serial='0123456789abcdef')
     self.assertIsPicklable(original)
예제 #8
0
    def _RunAdbCmd(cls,
                   args,
                   timeout=None,
                   retries=None,
                   device_serial=None,
                   check_error=True,
                   cpu_affinity=None):
        # pylint: disable=no-member
        try:
            status, output = cmd_helper.GetCmdStatusAndOutputWithTimeout(
                cls._BuildAdbCmd(args,
                                 device_serial,
                                 cpu_affinity=cpu_affinity),
                timeout_retry.CurrentTimeoutThreadGroup().GetRemainingTime())
        except OSError as e:
            if e.errno in (errno.ENOENT, errno.ENOEXEC):
                raise device_errors.NoAdbError(msg=str(e))
            else:
                raise

        # Best effort to catch errors from adb; unfortunately adb is very
        # inconsistent with error reporting so many command failures present
        # differently.
        if status != 0 or (check_error and output.startswith('error:')):
            m = _DEVICE_NOT_FOUND_RE.match(output)
            if m is not None and m.group('serial') == device_serial:
                raise device_errors.DeviceUnreachableError(device_serial)
            else:
                raise device_errors.AdbCommandFailedError(
                    args, output, status, device_serial)

        return output
예제 #9
0
 def testIsNotSvelte(self):
     with mock.patch(
             'devil.android.device_utils.DeviceUtils.RunShellCommand',
             side_effect=device_errors.AdbCommandFailedError('m', 'n')):
         backend = android_platform_backend.AndroidPlatformBackend(
             android_device.AndroidDevice('12345'), self._options)
         self.assertFalse(backend.IsSvelte())
예제 #10
0
 def _Connect(self,
              timeout=adb_wrapper.DEFAULT_TIMEOUT,
              retries=adb_wrapper.DEFAULT_RETRIES):
     """Connects ADB to the android gce instance."""
     cmd = ['connect', self._device_serial]
     output = self._RunAdbCmd(cmd, timeout=timeout, retries=retries)
     if 'unable to connect' in output:
         raise device_errors.AdbCommandFailedError(cmd, output)
     self.WaitForDevice()
예제 #11
0
 def ParseLine(line, cmd):
   cols = line.split(None, 3)
   if len(cols) < 4:
     raise device_errors.AdbCommandFailedError(
         cmd, line, "the output should be 4 columns, but is only %d columns"
         % len(cols), device_serial=self._device_serial)
   filename = cols.pop()
   stat = DeviceStat(*[int(num, base=16) for num in cols])
   return (filename, stat)
예제 #12
0
    def InstallMultiple(self,
                        apk_paths,
                        forward_lock=False,
                        reinstall=False,
                        sd_card=False,
                        allow_downgrade=False,
                        partial=False,
                        streaming=None,
                        timeout=DEFAULT_LONG_TIMEOUT,
                        retries=DEFAULT_RETRIES):
        """Install an apk with splits on the device.

    Args:
      apk_paths: Host path to the APK file.
      forward_lock: (optional) If set forward-locks the app.
      reinstall: (optional) If set reinstalls the app, keeping its data.
      sd_card: (optional) If set installs on the SD card.
      allow_downgrade: (optional) Allow versionCode downgrade.
      partial: (optional) Package ID if apk_paths doesn't include all .apks.
      streaming: (optional) If not set, use default way to install.
        If True, performs streaming install.
        If False, app is pushed to device and be installed from there.
        Note this option is not supported prior to adb version 1.0.40
      timeout: (optional) Timeout per try in seconds.
      retries: (optional) Number of retries to attempt.
    """
        for path in apk_paths:
            VerifyLocalFileExists(path)
        cmd = ['install-multiple']
        if forward_lock:
            cmd.append('-l')
        if reinstall:
            cmd.append('-r')
        if sd_card:
            cmd.append('-s')
        if allow_downgrade:
            cmd.append('-d')
        if streaming in (True, False):
            if (du_version.LooseVersion(self.Version()) <
                    du_version.LooseVersion('1.0.40')):
                logging.warning(
                    'adb: streaming options not supported prior to version 1.0.40 '
                    '(current: %s)', self.Version())
            elif streaming:
                cmd.append('--streaming')
            else:
                cmd.append('--no-streaming')
        if partial:
            cmd.extend(('-p', partial))
        cmd.extend(apk_paths)
        output = self._RunDeviceAdbCmd(cmd, timeout, retries)
        if 'Success' not in output:
            raise device_errors.AdbCommandFailedError(
                cmd, output, device_serial=self._device_serial)
예제 #13
0
    def Root(self, timeout=_DEFAULT_TIMEOUT, retries=_DEFAULT_RETRIES):
        """Restarts the adbd daemon with root permissions, if possible.

    Args:
      timeout: (optional) Timeout per try in seconds.
      retries: (optional) Number of retries to attempt.
    """
        output = self._RunDeviceAdbCmd(['root'], timeout, retries)
        if 'cannot' in output:
            raise device_errors.AdbCommandFailedError(
                ['root'], output, device_serial=self._device_serial)
예제 #14
0
    def EnableVerity(self, timeout=DEFAULT_TIMEOUT, retries=DEFAULT_RETRIES):
        """Enable Marshmallow's Verity security feature.

    Returns:
      The output of the enable-verity command as a string.
    """
        output = self._RunDeviceAdbCmd(['enable-verity'], timeout, retries)
        if output and not _VERITY_ENABLE_RE.search(output):
            raise device_errors.AdbCommandFailedError(
                ['enable-verity'], output, device_serial=self._device_serial)
        return output
예제 #15
0
    def test_getStatsNoPs(self, get_devices, get_battery):
        get_devices.return_value = [self.device]
        get_battery.return_value = self.battery
        # Throw exception when listing processes.
        self.device.ListProcesses.side_effect = device_errors.AdbCommandFailedError(
            ['ps'], 'something failed', 1)

        # Should be same status dict but without process stats.
        expected_status_no_ps = self.expected_status.copy()
        expected_status_no_ps['device_cereal'].pop('processes')

        status = device_monitor.get_all_status(None)
        self.assertEquals(expected_status_no_ps, status['devices'])
예제 #16
0
    def _RunAdbCmd(cls,
                   args,
                   timeout=None,
                   retries=None,
                   device_serial=None,
                   check_error=True,
                   cpu_affinity=None,
                   additional_env=None):
        if timeout:
            remaining = timeout_retry.CurrentTimeoutThreadGroup(
            ).GetRemainingTime()
            if remaining:
                # Use a slightly smaller timeout than remaining time to ensure that we
                # have time to collect output from the command.
                timeout = 0.95 * remaining
            else:
                timeout = None
        env = cls._ADB_ENV.copy()
        if additional_env:
            env.update(additional_env)
        try:
            adb_cmd = cls._BuildAdbCmd(args,
                                       device_serial,
                                       cpu_affinity=cpu_affinity)
            status, output = cmd_helper.GetCmdStatusAndOutputWithTimeout(
                adb_cmd, timeout, env=env)
        except OSError as e:
            if e.errno in (errno.ENOENT, errno.ENOEXEC):
                raise device_errors.NoAdbError(msg=str(e))
            else:
                raise
        except cmd_helper.TimeoutError:
            logger.error('Timeout on adb command: %r', adb_cmd)
            raise

        # Best effort to catch errors from adb; unfortunately adb is very
        # inconsistent with error reporting so many command failures present
        # differently.
        if status != 0 or (check_error and output.startswith('error:')):
            not_found_m = _DEVICE_NOT_FOUND_RE.search(output)
            device_waiting_m = _WAITING_FOR_DEVICE_RE.match(output)
            if (device_waiting_m is not None
                    or (not_found_m is not None
                        and not_found_m.group('serial') == device_serial)):
                raise device_errors.DeviceUnreachableError(device_serial)
            else:
                raise device_errors.AdbCommandFailedError(
                    args, output, status, device_serial)

        return output
예제 #17
0
  def Pull(self, remote, local, timeout=60 * 5, retries=DEFAULT_RETRIES):
    """Pulls a file from the device to the host.

    Args:
      remote: Path on the device filesystem.
      local: Path on the host filesystem.
      timeout: (optional) Timeout per try in seconds.
      retries: (optional) Number of retries to attempt.
    """
    cmd = ['pull', remote, local]
    self._RunDeviceAdbCmd(cmd, timeout, retries)
    try:
      VerifyLocalFileExists(local)
    except IOError:
      raise device_errors.AdbCommandFailedError(
          cmd, 'File not found on host: %s' % local, device_serial=str(self))
예제 #18
0
  def Uninstall(self, package, keep_data=False, timeout=DEFAULT_TIMEOUT,
                retries=DEFAULT_RETRIES):
    """Remove the app |package| from the device.

    Args:
      package: The package to uninstall.
      keep_data: (optional) If set keep the data and cache directories.
      timeout: (optional) Timeout per try in seconds.
      retries: (optional) Number of retries to attempt.
    """
    cmd = ['uninstall']
    if keep_data:
      cmd.append('-k')
    cmd.append(package)
    output = self._RunDeviceAdbCmd(cmd, timeout, retries)
    if 'Failure' in output or 'Exception' in output:
      raise device_errors.AdbCommandFailedError(
          cmd, output, device_serial=self._device_serial)
예제 #19
0
    def _PushObject(self, local, remote):
        """Copies an object from the host to the gce instance using scp.

    Args:
      local: Path on the host filesystem.
      remote: Path on the instance filesystem.
    """
        cmd = [
            'scp', '-r', '-o', 'UserKnownHostsFile=/dev/null', '-o',
            'StrictHostKeyChecking=no', local,
            'root@%s:%s' % (self._instance_ip, remote)
        ]
        status, _ = cmd_helper.GetCmdStatusAndOutput(cmd)
        if status:
            raise device_errors.AdbCommandFailedError(
                cmd,
                'File not reachable on host: %s' % local,
                device_serial=str(self))
예제 #20
0
    def Root(self, timeout=DEFAULT_TIMEOUT, retries=DEFAULT_RETRIES):
        """Restarts the adbd daemon with root permissions, if possible.

    Args:
      timeout: (optional) Timeout per try in seconds.
      retries: (optional) Number of retries to attempt.
    """
        try:
            output = self._RunDeviceAdbCmd(['root'], timeout, retries)
        except device_errors.AdbCommandFailedError as e:
            # For some devices, root can occasionally fail with this error and kick
            # the device into adb 'offline' mode. Assuming this is transient, try
            # waiting for the device to come back up before re-raising the exception
            # and proceeding with any retries.
            if 'unable to connect for root: closed' in e.output:
                self.WaitForDevice()
            raise
        if 'cannot' in output:
            raise device_errors.AdbCommandFailedError(
                ['root'], output, device_serial=self._device_serial)
예제 #21
0
  def Ls(self, path, timeout=DEFAULT_TIMEOUT, retries=DEFAULT_RETRIES):
    """List the contents of a directory on the device.

    Args:
      path: Path on the device filesystem.
      timeout: (optional) Timeout per try in seconds.
      retries: (optional) Number of retries to attempt.

    Returns:
      A list of pairs (filename, stat) for each file found in the directory,
      where the stat object has the properties: st_mode, st_size, and st_time.

    Raises:
      AdbCommandFailedError if |path| does not specify a valid and accessible
          directory in the device, or the output of "adb ls" command is less
          than four columns
    """

    def ParseLine(line, cmd):
      cols = line.split(None, 3)
      if len(cols) < 4:
        raise device_errors.AdbCommandFailedError(
            cmd,
            line,
            "the output should be 4 columns, but is only %d columns" %
            len(cols),
            device_serial=self._device_serial)
      filename = cols.pop()
      stat = DeviceStat(*[int(num, base=16) for num in cols])
      return (filename, stat)

    cmd = ['ls', path]
    lines = self._RunDeviceAdbCmd(
        cmd, timeout=timeout, retries=retries).splitlines()
    if lines:
      return [ParseLine(line, cmd) for line in lines]
    else:
      raise device_errors.AdbCommandFailedError(
          cmd,
          'path does not specify an accessible directory in the device',
          device_serial=self._device_serial)
예제 #22
0
 def action(cmd):
     if exists_result:
         return ''
     else:
         raise device_errors.AdbCommandFailedError(
             cmd, 'File not found', 1, str(self.adb))
예제 #23
0
 def DisableVerity(self, timeout=DEFAULT_TIMEOUT, retries=DEFAULT_RETRIES):
     """Disable Marshmallow's Verity security feature"""
     output = self._RunDeviceAdbCmd(['disable-verity'], timeout, retries)
     if output and _VERITY_DISABLE_RE.search(output):
         raise device_errors.AdbCommandFailedError(
             ['disable-verity'], output, device_serial=self._device_serial)