aboutsummaryrefslogtreecommitdiff
path: root/catapult/devil/devil/android/sdk/fastboot.py
blob: d0f856678d67ef574f5c447c19b19eb73103371e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# 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))])