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