• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2015 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"""This module wraps Android's fastboot tool.
5
6This is a thin wrapper around the fastboot interface. Any additional complexity
7should be delegated to a higher level (ex. FastbootUtils).
8"""
9# pylint: disable=unused-argument
10
11from devil import devil_env
12from devil.android import decorators
13from devil.android import device_errors
14from devil.utils import cmd_helper
15from devil.utils import lazy
16
17_DEFAULT_TIMEOUT = 30
18_DEFAULT_RETRIES = 3
19_FLASH_TIMEOUT = _DEFAULT_TIMEOUT * 10
20
21
22class Fastboot(object):
23
24  _fastboot_path = lazy.WeakConstant(lambda: devil_env.config.FetchPath(
25      'fastboot'))
26
27  def __init__(self,
28               device_serial,
29               default_timeout=_DEFAULT_TIMEOUT,
30               default_retries=_DEFAULT_RETRIES):
31    """Initializes the FastbootWrapper.
32
33    Args:
34      device_serial: The device serial number as a string.
35    """
36    if not device_serial:
37      raise ValueError('A device serial must be specified')
38    self._device_serial = str(device_serial)
39    self._default_timeout = default_timeout
40    self._default_retries = default_retries
41
42  def __str__(self):
43    return self._device_serial
44
45  @classmethod
46  def _RunFastbootCommand(cls, cmd):
47    """Run a generic fastboot command.
48
49    Args:
50      cmd: Command to run. Must be list of args, the first one being the command
51
52    Returns:
53      output of command.
54
55    Raises:
56      TypeError: If cmd is not of type list.
57    """
58    if isinstance(cmd, list):
59      cmd = [cls._fastboot_path.read()] + cmd
60    else:
61      raise TypeError('Command for _RunDeviceFastbootCommand must be a list.')
62    # fastboot can't be trusted to keep non-error output out of stderr, so
63    # capture stderr as part of stdout.
64    status, output = cmd_helper.GetCmdStatusAndOutput(cmd, merge_stderr=True)
65    if int(status) != 0:
66      raise device_errors.FastbootCommandFailedError(cmd, output, status)
67    return output
68
69  def _RunDeviceFastbootCommand(self, cmd):
70    """Run a fastboot command on the device associated with this object.
71
72    Args:
73      cmd: Command to run. Must be list of args, the first one being the command
74
75    Returns:
76      output of command.
77
78    Raises:
79      TypeError: If cmd is not of type list.
80    """
81    if isinstance(cmd, list):
82      cmd = ['-s', self._device_serial] + cmd
83    return self._RunFastbootCommand(cmd)
84
85  @decorators.WithTimeoutAndRetriesDefaults(_DEFAULT_TIMEOUT, _DEFAULT_RETRIES)
86  def GetVar(self, variable, timeout=None, retries=None):
87    args = ['getvar', variable]
88    output = self._RunDeviceFastbootCommand(args)
89    # getvar returns timing information on the last line of output, so only
90    # parse the first line.
91    output = output.splitlines()[0]
92    # And the first line should match the format '$(var): $(value)'.
93    if variable + ': ' not in output:
94      raise device_errors.FastbootCommandFailedError(
95          args, output, message="Unknown 'getvar' output format.")
96    return output.split('%s: ' % variable)[1].strip()
97
98  @decorators.WithTimeoutAndRetriesDefaults(_FLASH_TIMEOUT, 0)
99  def Flash(self, partition, image, timeout=None, retries=None):
100    """Flash partition with img.
101
102    Args:
103      partition: Partition to be flashed.
104      image: location of image to flash with.
105    """
106    self._RunDeviceFastbootCommand(['flash', partition, image])
107
108  @classmethod
109  @decorators.WithTimeoutAndRetriesDefaults(_DEFAULT_TIMEOUT, _DEFAULT_RETRIES)
110  def Devices(cls, timeout=None, retries=None):
111    """Outputs list of devices in fastboot mode.
112
113    Returns:
114      List of Fastboot objects, one for each device in fastboot.
115    """
116    output = cls._RunFastbootCommand(['devices'])
117    return [Fastboot(line.split()[0]) for line in output.splitlines()]
118
119  @decorators.WithTimeoutAndRetriesFromInstance()
120  def RebootBootloader(self, timeout=None, retries=None):
121    """Reboot from fastboot, into fastboot."""
122    self._RunDeviceFastbootCommand(['reboot-bootloader'])
123
124  @decorators.WithTimeoutAndRetriesDefaults(_FLASH_TIMEOUT, 0)
125  def Reboot(self, timeout=None, retries=None):
126    """Reboot from fastboot to normal usage"""
127    self._RunDeviceFastbootCommand(['reboot'])
128
129  @decorators.WithTimeoutAndRetriesFromInstance()
130  def SetOemOffModeCharge(self, value, timeout=None, retries=None):
131    """Sets off mode charging
132
133    Args:
134      value: boolean value to set off-mode-charging on or off.
135    """
136    self._RunDeviceFastbootCommand(['oem', 'off-mode-charge', str(int(value))])
137