1be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik# Copyright 2015 The Chromium Authors. All rights reserved.
2be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik# Use of this source code is governed by a BSD-style license that can be
3be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik# found in the LICENSE file.
4be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
5be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik"""Provides a variety of device interactions based on fastboot."""
6be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik# pylint: disable=unused-argument
7be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
8a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craikimport collections
9be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikimport contextlib
10be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikimport fnmatch
11be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikimport logging
12be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikimport os
13be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikimport re
14be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
15be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikfrom devil.android import decorators
16be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikfrom devil.android import device_errors
17be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikfrom devil.android.sdk import fastboot
18be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikfrom devil.utils import timeout_retry
19be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
20ee838d1c4002134ff5af32da272140586c4d31deJohn Recklogger = logging.getLogger(__name__)
21ee838d1c4002134ff5af32da272140586c4d31deJohn Reck
22be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik_DEFAULT_TIMEOUT = 30
23be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik_DEFAULT_RETRIES = 3
24be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik_FASTBOOT_REBOOT_TIMEOUT = 10 * _DEFAULT_TIMEOUT
25a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik_KNOWN_PARTITIONS = collections.OrderedDict([
26a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik      ('bootloader', {'image': 'bootloader*.img', 'restart': True}),
27a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik      ('radio', {'image': 'radio*.img', 'restart': True}),
28a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik      ('boot', {'image': 'boot.img'}),
29a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik      ('recovery', {'image': 'recovery.img'}),
30a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik      ('system', {'image': 'system.img'}),
31a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik      ('userdata', {'image': 'userdata.img', 'wipe_only': True}),
32a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik      ('cache', {'image': 'cache.img', 'wipe_only': True}),
33a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik      ('vendor', {'image': 'vendor*.img', 'optional': True}),
34a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  ])
35a23c9e9f6fc22fe5611def685e1984062b13b560Chris CraikALL_PARTITIONS = _KNOWN_PARTITIONS.keys()
36a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik
37a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik
38a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craikdef _FindAndVerifyPartitionsAndImages(partitions, directory):
39a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  """Validate partitions and images.
40a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik
41a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  Validate all partition names and partition directories. Cannot stop mid
42a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  flash so its important to validate everything first.
43a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik
44a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  Args:
45a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    Partitions: partitions to be tested.
46a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    directory: directory containing the images.
47a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik
48a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  Returns:
49a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    Dictionary with exact partition, image name mapping.
50a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  """
51a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik
52a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  files = os.listdir(directory)
53a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  return_dict = collections.OrderedDict()
54a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik
55a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  def find_file(pattern):
56a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    for filename in files:
57a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik      if fnmatch.fnmatch(filename, pattern):
58a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik        return os.path.join(directory, filename)
59a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    return None
60a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  for partition in partitions:
61a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    partition_info = _KNOWN_PARTITIONS[partition]
62a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    image_file = find_file(partition_info['image'])
63a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    if image_file:
64a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik      return_dict[partition] = image_file
65a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    elif not partition_info.get('optional'):
66a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik      raise device_errors.FastbootCommandFailedError(
67a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik          'Failed to flash device. Could not find image for %s.',
68a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik          partition_info['image'])
69a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  return return_dict
70be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
71be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
72be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikclass FastbootUtils(object):
73be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
74be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  _FASTBOOT_WAIT_TIME = 1
75be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  _BOARD_VERIFICATION_FILE = 'android-info.txt'
76be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
77be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  def __init__(self, device, fastbooter=None, default_timeout=_DEFAULT_TIMEOUT,
78be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik               default_retries=_DEFAULT_RETRIES):
79be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    """FastbootUtils constructor.
80be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
81be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    Example Usage to flash a device:
82be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      fastboot = fastboot_utils.FastbootUtils(device)
83be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      fastboot.FlashDevice('/path/to/build/directory')
84be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
85be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    Args:
86be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      device: A DeviceUtils instance.
87be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      fastbooter: Optional fastboot object. If none is passed, one will
88be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        be created.
89be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      default_timeout: An integer containing the default number of seconds to
90be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        wait for an operation to complete if no explicit value is provided.
91be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      default_retries: An integer containing the default number or times an
92be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        operation should be retried on failure if no explicit value is provided.
93be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    """
94be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    self._device = device
95be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    self._board = device.product_board
96be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    self._serial = str(device)
97be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    self._default_timeout = default_timeout
98be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    self._default_retries = default_retries
99be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    if fastbooter:
100be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      self.fastboot = fastbooter
101be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    else:
102be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      self.fastboot = fastboot.Fastboot(self._serial)
103be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
104be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  @decorators.WithTimeoutAndRetriesFromInstance()
105be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  def WaitForFastbootMode(self, timeout=None, retries=None):
106be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    """Wait for device to boot into fastboot mode.
107be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
108be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    This waits for the device serial to show up in fastboot devices output.
109be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    """
110be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    def fastboot_mode():
111be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      return self._serial in self.fastboot.Devices()
112be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
113be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    timeout_retry.WaitFor(fastboot_mode, wait_period=self._FASTBOOT_WAIT_TIME)
114be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
115be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  @decorators.WithTimeoutAndRetriesFromInstance(
116be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      min_default_timeout=_FASTBOOT_REBOOT_TIMEOUT)
117be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  def EnableFastbootMode(self, timeout=None, retries=None):
118be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    """Reboots phone into fastboot mode.
119be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
120be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    Roots phone if needed, then reboots phone into fastboot mode and waits.
121be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    """
122be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    self._device.EnableRoot()
123be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    self._device.adb.Reboot(to_bootloader=True)
124be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    self.WaitForFastbootMode()
125be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
126be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  @decorators.WithTimeoutAndRetriesFromInstance(
127be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      min_default_timeout=_FASTBOOT_REBOOT_TIMEOUT)
128a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  def Reboot(
129a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik      self, bootloader=False, wait_for_reboot=True, timeout=None, retries=None):
130be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    """Reboots out of fastboot mode.
131be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
132be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    It reboots the phone either back into fastboot, or to a regular boot. It
133be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    then blocks until the device is ready.
134be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
135be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    Args:
136be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      bootloader: If set to True, reboots back into bootloader.
137be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    """
138be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    if bootloader:
139be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      self.fastboot.RebootBootloader()
140be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      self.WaitForFastbootMode()
141be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    else:
142be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      self.fastboot.Reboot()
143a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik      if wait_for_reboot:
144a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik        self._device.WaitUntilFullyBooted(timeout=_FASTBOOT_REBOOT_TIMEOUT)
145be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
146be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  def _VerifyBoard(self, directory):
147be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    """Validate as best as possible that the android build matches the device.
148be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
149be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    Goes through build files and checks if the board name is mentioned in the
150be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    |self._BOARD_VERIFICATION_FILE| or in the build archive.
151be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
152be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    Args:
153be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      directory: directory where build files are located.
154be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    """
155be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    files = os.listdir(directory)
156be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    board_regex = re.compile(r'require board=(\w+)')
157be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    if self._BOARD_VERIFICATION_FILE in files:
158be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      with open(os.path.join(directory, self._BOARD_VERIFICATION_FILE)) as f:
159be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        for line in f:
160be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik          m = board_regex.match(line)
161be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik          if m:
162be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik            board_name = m.group(1)
163be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik            if board_name == self._board:
164be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik              return True
165be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik            elif board_name:
166be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik              return False
167be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik            else:
168ee838d1c4002134ff5af32da272140586c4d31deJohn Reck              logger.warning('No board type found in %s.',
169ee838d1c4002134ff5af32da272140586c4d31deJohn Reck                             self._BOARD_VERIFICATION_FILE)
170be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    else:
171ee838d1c4002134ff5af32da272140586c4d31deJohn Reck      logger.warning('%s not found. Unable to use it to verify device.',
172ee838d1c4002134ff5af32da272140586c4d31deJohn Reck                     self._BOARD_VERIFICATION_FILE)
173be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
174be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    zip_regex = re.compile(r'.*%s.*\.zip' % re.escape(self._board))
175be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    for f in files:
176be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      if zip_regex.match(f):
177be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        return True
178be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
179be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    return False
180be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
181be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  def _FlashPartitions(self, partitions, directory, wipe=False, force=False):
182be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    """Flashes all given partiitons with all given images.
183be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
184be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    Args:
185be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      partitions: List of partitions to flash.
186be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      directory: Directory where all partitions can be found.
187be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      wipe: If set to true, will automatically detect if cache and userdata
188be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik          partitions are sent, and if so ignore them.
189be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      force: boolean to decide to ignore board name safety checks.
190be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
191be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    Raises:
192be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      device_errors.CommandFailedError(): If image cannot be found or if bad
193be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik          partition name is give.
194be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    """
195be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    if not self._VerifyBoard(directory):
196be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      if force:
197ee838d1c4002134ff5af32da272140586c4d31deJohn Reck        logger.warning('Could not verify build is meant to be installed on '
198ee838d1c4002134ff5af32da272140586c4d31deJohn Reck                       'the current device type, but force flag is set. '
199ee838d1c4002134ff5af32da272140586c4d31deJohn Reck                       'Flashing device. Possibly dangerous operation.')
200be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      else:
201be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        raise device_errors.CommandFailedError(
202be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik            'Could not verify build is meant to be installed on the current '
203be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik            'device type. Run again with force=True to force flashing with an '
204be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik            'unverified board.')
205be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
206a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    flash_image_files = _FindAndVerifyPartitionsAndImages(partitions, directory)
207a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    partitions = flash_image_files.keys()
208be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    for partition in partitions:
209a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik      if _KNOWN_PARTITIONS[partition].get('wipe_only') and not wipe:
210ee838d1c4002134ff5af32da272140586c4d31deJohn Reck        logger.info(
211be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik            'Not flashing in wipe mode. Skipping partition %s.', partition)
212be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      else:
213ee838d1c4002134ff5af32da272140586c4d31deJohn Reck        logger.info(
214be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik            'Flashing %s with %s', partition, flash_image_files[partition])
215be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        self.fastboot.Flash(partition, flash_image_files[partition])
216a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik        if _KNOWN_PARTITIONS[partition].get('restart', False):
217be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik          self.Reboot(bootloader=True)
218be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
219be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  @contextlib.contextmanager
220a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  def FastbootMode(self, wait_for_reboot=True, timeout=None, retries=None):
221be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    """Context manager that enables fastboot mode, and reboots after.
222be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
223be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    Example usage:
224be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      with FastbootMode():
225be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        Flash Device
226be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      # Anything that runs after flashing.
227be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    """
228be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    self.EnableFastbootMode()
229be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    self.fastboot.SetOemOffModeCharge(False)
230be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    try:
231be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      yield self
232be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    finally:
233be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      self.fastboot.SetOemOffModeCharge(True)
234a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik      self.Reboot(wait_for_reboot=wait_for_reboot)
235be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
236be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  def FlashDevice(self, directory, partitions=None, wipe=False):
237be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    """Flash device with build in |directory|.
238be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
239be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    Directory must contain bootloader, radio, boot, recovery, system, userdata,
240be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    and cache .img files from an android build. This is a dangerous operation so
241be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    use with care.
242be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
243be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    Args:
244be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      fastboot: A FastbootUtils instance.
245be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      directory: Directory with build files.
246be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      wipe: Wipes cache and userdata if set to true.
247be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      partitions: List of partitions to flash. Defaults to all.
248be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    """
249be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    if partitions is None:
250be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      partitions = ALL_PARTITIONS
251a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    # If a device is wiped, then it will no longer have adb keys so it cannot be
252a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    # communicated with to verify that it is rebooted. It is up to the user of
253a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    # this script to ensure that the adb keys are set on the device after using
254a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    # this to wipe a device.
255a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    with self.FastbootMode(wait_for_reboot=not wipe):
256be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      self._FlashPartitions(partitions, directory, wipe=wipe)
257