blob: d0f856678d67ef574f5c447c19b19eb73103371e [file] [log] [blame]
# Copyright 2015 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""This module wraps Android's fastboot tool.
This is a thin wrapper around the fastboot interface. Any additional complexity
should be delegated to a higher level (ex. FastbootUtils).
"""
# pylint: disable=unused-argument
from devil import devil_env
from devil.android import decorators
from devil.android import device_errors
from devil.utils import cmd_helper
from devil.utils import lazy
_DEFAULT_TIMEOUT = 30
_DEFAULT_RETRIES = 3
_FLASH_TIMEOUT = _DEFAULT_TIMEOUT * 10
class Fastboot(object):
_fastboot_path = lazy.WeakConstant(lambda: devil_env.config.FetchPath(
'fastboot'))
def __init__(self,
device_serial,
default_timeout=_DEFAULT_TIMEOUT,
default_retries=_DEFAULT_RETRIES):
"""Initializes the FastbootWrapper.
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)
self._default_timeout = default_timeout
self._default_retries = default_retries
def __str__(self):
return self._device_serial
@classmethod
def _RunFastbootCommand(cls, cmd):
"""Run a generic fastboot command.
Args:
cmd: Command to run. Must be list of args, the first one being the command
Returns:
output of command.
Raises:
TypeError: If cmd is not of type list.
"""
if isinstance(cmd, list):
cmd = [cls._fastboot_path.read()] + cmd
else:
raise TypeError('Command for _RunDeviceFastbootCommand must be a list.')
# fastboot can't be trusted to keep non-error output out of stderr, so
# capture stderr as part of stdout.
status, output = cmd_helper.GetCmdStatusAndOutput(cmd, merge_stderr=True)
if int(status) != 0:
raise device_errors.FastbootCommandFailedError(cmd, output, status)
return output
def _RunDeviceFastbootCommand(self, cmd):
"""Run a fastboot command on the device associated with this object.
Args:
cmd: Command to run. Must be list of args, the first one being the command
Returns:
output of command.
Raises:
TypeError: If cmd is not of type list.
"""
if isinstance(cmd, list):
cmd = ['-s', self._device_serial] + cmd
return self._RunFastbootCommand(cmd)
@decorators.WithTimeoutAndRetriesDefaults(_DEFAULT_TIMEOUT, _DEFAULT_RETRIES)
def GetVar(self, variable, timeout=None, retries=None):
args = ['getvar', variable]
output = self._RunDeviceFastbootCommand(args)
# getvar returns timing information on the last line of output, so only
# parse the first line.
output = output.splitlines()[0]
# And the first line should match the format '$(var): $(value)'.
if variable + ': ' not in output:
raise device_errors.FastbootCommandFailedError(
args, output, message="Unknown 'getvar' output format.")
return output.split('%s: ' % variable)[1].strip()
@decorators.WithTimeoutAndRetriesDefaults(_FLASH_TIMEOUT, 0)
def Flash(self, partition, image, timeout=None, retries=None):
"""Flash partition with img.
Args:
partition: Partition to be flashed.
image: location of image to flash with.
"""
self._RunDeviceFastbootCommand(['flash', partition, image])
@classmethod
@decorators.WithTimeoutAndRetriesDefaults(_DEFAULT_TIMEOUT, _DEFAULT_RETRIES)
def Devices(cls, timeout=None, retries=None):
"""Outputs list of devices in fastboot mode.
Returns:
List of Fastboot objects, one for each device in fastboot.
"""
output = cls._RunFastbootCommand(['devices'])
return [Fastboot(line.split()[0]) for line in output.splitlines()]
@decorators.WithTimeoutAndRetriesFromInstance()
def RebootBootloader(self, timeout=None, retries=None):
"""Reboot from fastboot, into fastboot."""
self._RunDeviceFastbootCommand(['reboot-bootloader'])
@decorators.WithTimeoutAndRetriesDefaults(_FLASH_TIMEOUT, 0)
def Reboot(self, timeout=None, retries=None):
"""Reboot from fastboot to normal usage"""
self._RunDeviceFastbootCommand(['reboot'])
@decorators.WithTimeoutAndRetriesFromInstance()
def SetOemOffModeCharge(self, value, timeout=None, retries=None):
"""Sets off mode charging
Args:
value: boolean value to set off-mode-charging on or off.
"""
self._RunDeviceFastbootCommand(['oem', 'off-mode-charge', str(int(value))])