Home | History | Annotate | Download | only in hosts
      1 # Copyright (c) 2013 The Chromium OS 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 import functools
      5 import logging
      6 import os
      7 import re
      8 import stat
      9 import sys
     10 import time
     11 
     12 import common
     13 
     14 from autotest_lib.client.common_lib import error
     15 from autotest_lib.client.common_lib.cros import dev_server
     16 from autotest_lib.client.common_lib.cros import retry
     17 from autotest_lib.server import autoserv_parser
     18 from autotest_lib.server import constants as server_constants
     19 from autotest_lib.server import utils
     20 from autotest_lib.server.cros import provision
     21 from autotest_lib.server.cros.dynamic_suite import constants
     22 from autotest_lib.server.hosts import abstract_ssh
     23 from autotest_lib.server.hosts import teststation_host
     24 
     25 
     26 ADB_CMD = 'adb'
     27 FASTBOOT_CMD = 'fastboot'
     28 SHELL_CMD = 'shell'
     29 # Some devices have no serial, then `adb serial` has output such as:
     30 # (no serial number)  device
     31 # ??????????          device
     32 DEVICE_NO_SERIAL_MSG = '(no serial number)'
     33 DEVICE_NO_SERIAL_TAG = '<NO_SERIAL>'
     34 # Regex to find an adb device. Examples:
     35 # 0146B5580B01801B    device
     36 # 018e0ecb20c97a62    device
     37 # 172.22.75.141:5555  device
     38 DEVICE_FINDER_REGEX = ('^(?P<SERIAL>([\w]+)|(\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3})|' +
     39                        re.escape(DEVICE_NO_SERIAL_MSG) +
     40                        ')([:]5555)?[ \t]+(?:device|fastboot)')
     41 CMD_OUTPUT_PREFIX = 'ADB_CMD_OUTPUT'
     42 CMD_OUTPUT_REGEX = ('(?P<OUTPUT>[\s\S]*)%s:(?P<EXIT_CODE>\d{1,3})' %
     43                     CMD_OUTPUT_PREFIX)
     44 RELEASE_FILE = 'ro.build.version.release'
     45 BOARD_FILE = 'ro.product.device'
     46 TMP_DIR = '/data/local/tmp'
     47 # Regex to pull out file type, perms and symlink. Example:
     48 # lrwxrwx--- 1 6 root system 2015-09-12 19:21 blah_link -> ./blah
     49 FILE_INFO_REGEX = '^(?P<TYPE>[dl-])(?P<PERMS>[rwx-]{9})'
     50 FILE_SYMLINK_REGEX = '^.*-> (?P<SYMLINK>.+)'
     51 # List of the perm stats indexed by the order they are listed in the example
     52 # supplied above.
     53 FILE_PERMS_FLAGS = [stat.S_IRUSR, stat.S_IWUSR, stat.S_IXUSR,
     54                     stat.S_IRGRP, stat.S_IWGRP, stat.S_IXGRP,
     55                     stat.S_IROTH, stat.S_IWOTH, stat.S_IXOTH]
     56 
     57 # Default maximum number of seconds to wait for a device to be down.
     58 DEFAULT_WAIT_DOWN_TIME_SECONDS = 10
     59 # Default maximum number of seconds to wait for a device to be up.
     60 DEFAULT_WAIT_UP_TIME_SECONDS = 300
     61 # Maximum number of seconds to wait for a device to be up after it's wiped.
     62 WAIT_UP_AFTER_WIPE_TIME_SECONDS = 1200
     63 
     64 OS_TYPE_ANDROID = 'android'
     65 OS_TYPE_BRILLO = 'brillo'
     66 
     67 # Regex to parse build name to get the detailed build information.
     68 BUILD_REGEX = ('(?P<BRANCH>([^/]+))/(?P<BOARD>([^/]+))-'
     69                '(?P<BUILD_TYPE>([^/]+))/(?P<BUILD_ID>([^/]+))')
     70 # Regex to parse devserver url to get the detailed build information. Sample
     71 # url: http://$devserver:8080/static/branch/target/build_id
     72 DEVSERVER_URL_REGEX = '.*/%s/*' % BUILD_REGEX
     73 
     74 ANDROID_IMAGE_FILE_FMT = '%(board)s-img-%(build_id)s.zip'
     75 ANDROID_BOOTLOADER = 'bootloader.img'
     76 ANDROID_RADIO = 'radio.img'
     77 ANDROID_BOOT = 'boot.img'
     78 ANDROID_SYSTEM = 'system.img'
     79 ANDROID_VENDOR = 'vendor.img'
     80 BRILLO_VENDOR_PARTITIONS_FILE_FMT = (
     81         '%(board)s-vendor_partitions-%(build_id)s.zip')
     82 
     83 # Image files not inside the image zip file. These files should be downloaded
     84 # directly from devserver.
     85 ANDROID_STANDALONE_IMAGES = [ANDROID_BOOTLOADER, ANDROID_RADIO]
     86 # Image files that are packaged in a zip file, e.g., shamu-img-123456.zip
     87 ANDROID_ZIPPED_IMAGES = [ANDROID_BOOT, ANDROID_SYSTEM, ANDROID_VENDOR]
     88 # All image files to be flashed to an Android device.
     89 ANDROID_IMAGES = ANDROID_STANDALONE_IMAGES + ANDROID_ZIPPED_IMAGES
     90 
     91 # Command to provision a Brillo device.
     92 # os_image_dir: The full path of the directory that contains all the Android image
     93 # files (from the image zip file).
     94 # vendor_partition_dir: The full path of the directory that contains all the
     95 # Brillo vendor partitions, and provision-device script.
     96 BRILLO_PROVISION_CMD = (
     97         'sudo ANDROID_PROVISION_OS_PARTITIONS=%(os_image_dir)s '
     98         'ANDROID_PROVISION_VENDOR_PARTITIONS=%(vendor_partition_dir)s '
     99         '%(vendor_partition_dir)s/provision-device')
    100 
    101 class AndroidInstallError(error.InstallError):
    102     """Generic error for Android installation related exceptions."""
    103 
    104 
    105 class ADBHost(abstract_ssh.AbstractSSHHost):
    106     """This class represents a host running an ADB server."""
    107 
    108     VERSION_PREFIX = provision.ANDROID_BUILD_VERSION_PREFIX
    109     _LABEL_FUNCTIONS = []
    110     _DETECTABLE_LABELS = []
    111     label_decorator = functools.partial(utils.add_label_detector,
    112                                         _LABEL_FUNCTIONS,
    113                                         _DETECTABLE_LABELS)
    114 
    115     _parser = autoserv_parser.autoserv_parser
    116 
    117     @staticmethod
    118     def check_host(host, timeout=10):
    119         """
    120         Check if the given host is an adb host.
    121 
    122         If SSH connectivity can't be established, check_host will try to use
    123         user 'adb' as well. If SSH connectivity still can't be established
    124         then the original SSH user is restored.
    125 
    126         @param host: An ssh host representing a device.
    127         @param timeout: The timeout for the run command.
    128 
    129 
    130         @return: True if the host device has adb.
    131 
    132         @raises AutoservRunError: If the command failed.
    133         @raises AutoservSSHTimeout: Ssh connection has timed out.
    134         """
    135         # host object may not have user attribute if it's a LocalHost object.
    136         current_user = host.user if hasattr(host, 'user') else None
    137         try:
    138             if not (host.hostname == 'localhost' or
    139                     host.verify_ssh_user_access()):
    140                 host.user = 'adb'
    141             result = host.run(
    142                     'test -f %s' % server_constants.ANDROID_TESTER_FILEFLAG,
    143                     timeout=timeout)
    144         except (error.AutoservRunError, error.AutoservSSHTimeout):
    145             if current_user is not None:
    146                 host.user = current_user
    147             return False
    148         return result.exit_status == 0
    149 
    150 
    151     # TODO(garnold) Remove the 'serials' argument once all clients are made to
    152     # not use it.
    153     def _initialize(self, hostname='localhost', serials=None,
    154                     adb_serial=None, fastboot_serial=None,
    155                     device_hostname=None, teststation=None, *args, **dargs):
    156         """Initialize an ADB Host.
    157 
    158         This will create an ADB Host. Hostname should always refer to the
    159         test station connected to an Android DUT. This will be the DUT
    160         to test with.  If there are multiple, serial must be specified or an
    161         exception will be raised.  If device_hostname is supplied then all
    162         ADB commands will run over TCP/IP.
    163 
    164         @param hostname: Hostname of the machine running ADB.
    165         @param serials: DEPRECATED (to be removed)
    166         @param adb_serial: An ADB device serial. If None, assume a single
    167                            device is attached (and fail otherwise).
    168         @param fastboot_serial: A fastboot device serial. If None, defaults to
    169                                 the ADB serial (or assumes a single device if
    170                                 the latter is None).
    171         @param device_hostname: Hostname or IP of the android device we want to
    172                                 interact with. If supplied all ADB interactions
    173                                 run over TCP/IP.
    174         @param teststation: The teststation object ADBHost should use.
    175         """
    176         # Sets up the is_client_install_supported field.
    177         super(ADBHost, self)._initialize(hostname=hostname,
    178                                          is_client_install_supported=False,
    179                                          *args, **dargs)
    180         if device_hostname and (adb_serial or fastboot_serial):
    181             raise error.AutoservError(
    182                     'TCP/IP and USB modes are mutually exclusive')
    183 
    184 
    185         self.tmp_dirs = []
    186         self._device_hostname = device_hostname
    187         self._use_tcpip = False
    188         # TODO (sbasi/kevcheng): Once the teststation host is committed,
    189         # refactor the serial retrieval.
    190         adb_serial = adb_serial or self.host_attributes.get('serials', None)
    191         self.adb_serial = adb_serial
    192         self.fastboot_serial = fastboot_serial or adb_serial
    193         self.teststation = (teststation if teststation
    194                 else teststation_host.create_teststationhost(hostname=hostname))
    195 
    196         msg ='Initializing ADB device on host: %s' % hostname
    197         if self._device_hostname:
    198             msg += ', device hostname: %s' % self._device_hostname
    199         if self.adb_serial:
    200             msg += ', ADB serial: %s' % self.adb_serial
    201         if self.fastboot_serial:
    202             msg += ', fastboot serial: %s' % self.fastboot_serial
    203         logging.debug(msg)
    204 
    205         # Try resetting the ADB daemon on the device, however if we are
    206         # creating the host to do a repair job, the device maybe inaccesible
    207         # via ADB.
    208         try:
    209             self._reset_adbd_connection()
    210         except (error.AutotestHostRunError, error.AutoservRunError) as e:
    211             logging.error('Unable to reset the device adb daemon connection: '
    212                           '%s.', e)
    213         self._os_type = None
    214 
    215 
    216     def _connect_over_tcpip_as_needed(self):
    217         """Connect to the ADB device over TCP/IP if so configured."""
    218         if not self._device_hostname:
    219             return
    220         logging.debug('Connecting to device over TCP/IP')
    221         if self._device_hostname == self.adb_serial:
    222             # We previously had a connection to this device, restart the ADB
    223             # server.
    224             self.adb_run('kill-server')
    225         # Ensure that connection commands don't run over TCP/IP.
    226         self._use_tcpip = False
    227         self.adb_run('tcpip 5555', timeout=10, ignore_timeout=True)
    228         time.sleep(2)
    229         try:
    230             self.adb_run('connect %s' % self._device_hostname)
    231         except (error.AutoservRunError, error.CmdError) as e:
    232             raise error.AutoservError('Failed to connect via TCP/IP: %s' % e)
    233         # Allow ADB a bit of time after connecting before interacting with the
    234         # device.
    235         time.sleep(5)
    236         # Switch back to using TCP/IP.
    237         self._use_tcpip = True
    238 
    239 
    240     def _restart_adbd_with_root_permissions(self):
    241         """Restarts the adb daemon with root permissions."""
    242         self.adb_run('root')
    243         # TODO(ralphnathan): Remove this sleep once b/19749057 is resolved.
    244         time.sleep(1)
    245         self.adb_run('wait-for-device')
    246 
    247 
    248     def _reset_adbd_connection(self):
    249         """Resets adbd connection to the device after a reboot/initialization"""
    250         self._restart_adbd_with_root_permissions()
    251         self._connect_over_tcpip_as_needed()
    252 
    253 
    254     # pylint: disable=missing-docstring
    255     def adb_run(self, command, **kwargs):
    256         """Runs an adb command.
    257 
    258         This command will launch on the test station.
    259 
    260         Refer to _device_run method for docstring for parameters.
    261         """
    262         return self._device_run(ADB_CMD, command, **kwargs)
    263 
    264 
    265     # pylint: disable=missing-docstring
    266     def fastboot_run(self, command, **kwargs):
    267         """Runs an fastboot command.
    268 
    269         This command will launch on the test station.
    270 
    271         Refer to _device_run method for docstring for parameters.
    272         """
    273         return self._device_run(FASTBOOT_CMD, command, **kwargs)
    274 
    275 
    276     def _device_run(self, function, command, shell=False,
    277                     timeout=3600, ignore_status=False, ignore_timeout=False,
    278                     stdout=utils.TEE_TO_LOGS, stderr=utils.TEE_TO_LOGS,
    279                     connect_timeout=30, options='', stdin=None, verbose=True,
    280                     require_sudo=False, args=()):
    281         """Runs a command named `function` on the test station.
    282 
    283         This command will launch on the test station.
    284 
    285         @param command: Command to run.
    286         @param shell: If true the command runs in the adb shell otherwise if
    287                       False it will be passed directly to adb. For example
    288                       reboot with shell=False will call 'adb reboot'. This
    289                       option only applies to function adb.
    290         @param timeout: Time limit in seconds before attempting to
    291                         kill the running process. The run() function
    292                         will take a few seconds longer than 'timeout'
    293                         to complete if it has to kill the process.
    294         @param ignore_status: Do not raise an exception, no matter
    295                               what the exit code of the command is.
    296         @param ignore_timeout: Bool True if command timeouts should be
    297                                ignored.  Will return None on command timeout.
    298         @param stdout: Redirect stdout.
    299         @param stderr: Redirect stderr.
    300         @param connect_timeout: Connection timeout (in seconds)
    301         @param options: String with additional ssh command options
    302         @param stdin: Stdin to pass (a string) to the executed command
    303         @param require_sudo: True to require sudo to run the command. Default is
    304                              False.
    305         @param args: Sequence of strings to pass as arguments to command by
    306                      quoting them in " and escaping their contents if
    307                      necessary.
    308 
    309         @returns a CMDResult object.
    310         """
    311         if function == ADB_CMD:
    312             serial = self.adb_serial
    313         elif function == FASTBOOT_CMD:
    314             serial = self.fastboot_serial
    315         else:
    316             raise NotImplementedError('Mode %s is not supported' % function)
    317 
    318         if function != ADB_CMD and shell:
    319             raise error.CmdError('shell option is only applicable to `adb`.')
    320 
    321         cmd = '%s%s ' % ('sudo -n ' if require_sudo else '', function)
    322 
    323         if serial:
    324             cmd += '-s %s ' % serial
    325         elif self._use_tcpip:
    326             cmd += '-s %s:5555 ' % self._device_hostname
    327 
    328         if shell:
    329             cmd += '%s ' % SHELL_CMD
    330         cmd += command
    331 
    332         if verbose:
    333             logging.debug('Command: %s', cmd)
    334 
    335         return self.teststation.run(cmd, timeout=timeout,
    336                 ignore_status=ignore_status,
    337                 ignore_timeout=ignore_timeout, stdout_tee=stdout,
    338                 stderr_tee=stderr, options=options, stdin=stdin,
    339                 connect_timeout=connect_timeout, args=args)
    340 
    341 
    342     def get_board_name(self):
    343         """Get the name of the board, e.g., shamu, dragonboard etc.
    344         """
    345         return self.run_output('getprop %s' % BOARD_FILE)
    346 
    347 
    348     @label_decorator()
    349     def get_board(self):
    350         """Determine the correct board label for the device.
    351 
    352         @returns a string representing this device's board.
    353         """
    354         board = self.get_board_name()
    355         board_os = self.get_os_type()
    356         return constants.BOARD_PREFIX + '-'.join([board_os, board])
    357 
    358 
    359     def job_start(self):
    360         """
    361         Disable log collection on adb_hosts.
    362 
    363         TODO(sbasi): crbug.com/305427
    364         """
    365 
    366 
    367     def run(self, command, timeout=3600, ignore_status=False,
    368             ignore_timeout=False, stdout_tee=utils.TEE_TO_LOGS,
    369             stderr_tee=utils.TEE_TO_LOGS, connect_timeout=30, options='',
    370             stdin=None, verbose=True, args=()):
    371         """Run a command on the adb device.
    372 
    373         The command given will be ran directly on the adb device; for example
    374         'ls' will be ran as: 'abd shell ls'
    375 
    376         @param command: The command line string.
    377         @param timeout: Time limit in seconds before attempting to
    378                         kill the running process. The run() function
    379                         will take a few seconds longer than 'timeout'
    380                         to complete if it has to kill the process.
    381         @param ignore_status: Do not raise an exception, no matter
    382                               what the exit code of the command is.
    383         @param ignore_timeout: Bool True if command timeouts should be
    384                                ignored.  Will return None on command timeout.
    385         @param stdout_tee: Redirect stdout.
    386         @param stderr_tee: Redirect stderr.
    387         @param connect_timeout: Connection timeout (in seconds).
    388         @param options: String with additional ssh command options.
    389         @param stdin: Stdin to pass (a string) to the executed command
    390         @param args: Sequence of strings to pass as arguments to command by
    391                      quoting them in " and escaping their contents if
    392                      necessary.
    393 
    394         @returns A CMDResult object or None if the call timed out and
    395                  ignore_timeout is True.
    396 
    397         @raises AutoservRunError: If the command failed.
    398         @raises AutoservSSHTimeout: Ssh connection has timed out.
    399         """
    400         command = ('"%s; echo %s:\$?"' %
    401                 (utils.sh_escape(command), CMD_OUTPUT_PREFIX))
    402         result = self.adb_run(
    403                 command, shell=True, timeout=timeout,
    404                 ignore_status=ignore_status, ignore_timeout=ignore_timeout,
    405                 stdout=stdout_tee, stderr=stderr_tee,
    406                 connect_timeout=connect_timeout, options=options, stdin=stdin,
    407                 verbose=verbose, args=args)
    408         if not result:
    409             # In case of timeouts.
    410             return None
    411 
    412         parse_output = re.match(CMD_OUTPUT_REGEX, result.stdout)
    413         if not parse_output and not ignore_status:
    414             raise error.AutoservRunError(
    415                     'Failed to parse the exit code for command: %s' %
    416                     command, result)
    417         elif parse_output:
    418             result.stdout = parse_output.group('OUTPUT')
    419             result.exit_status = int(parse_output.group('EXIT_CODE'))
    420             if result.exit_status != 0 and not ignore_status:
    421                 raise error.AutoservRunError(command, result)
    422         return result
    423 
    424 
    425     def wait_up(self, timeout=DEFAULT_WAIT_UP_TIME_SECONDS, command=ADB_CMD):
    426         """Wait until the remote host is up or the timeout expires.
    427 
    428         Overrides wait_down from AbstractSSHHost.
    429 
    430         @param timeout: Time limit in seconds before returning even if the host
    431                 is not up.
    432         @param command: The command used to test if a device is up, i.e.,
    433                 accessible by the given command. Default is set to `adb`.
    434 
    435         @returns True if the host was found to be up before the timeout expires,
    436                  False otherwise.
    437         """
    438         @retry.retry(error.TimeoutException, timeout_min=timeout/60.0,
    439                      delay_sec=1)
    440         def _wait_up():
    441             if not self.is_up(command=command):
    442                 raise error.TimeoutException('Device is still down.')
    443             return True
    444 
    445         try:
    446             _wait_up()
    447             logging.debug('Host %s is now up, and can be accessed by %s.',
    448                           self.hostname, command)
    449             return True
    450         except error.TimeoutException:
    451             logging.debug('Host %s is still down after waiting %d seconds',
    452                           self.hostname, timeout)
    453             return False
    454 
    455 
    456     def wait_down(self, timeout=DEFAULT_WAIT_DOWN_TIME_SECONDS,
    457                   warning_timer=None, old_boot_id=None, command=ADB_CMD):
    458         """Wait till the host goes down, i.e., not accessible by given command.
    459 
    460         Overrides wait_down from AbstractSSHHost.
    461 
    462         @param timeout: Time in seconds to wait for the host to go down.
    463         @param warning_timer: Time limit in seconds that will generate
    464                               a warning if the host is not down yet.
    465                               Currently ignored.
    466         @param old_boot_id: Not applicable for adb_host.
    467         @param command: `adb`, test if the device can be accessed by adb
    468                 command, or `fastboot`, test if the device can be accessed by
    469                 fastboot command. Default is set to `adb`.
    470 
    471         @returns True if the device goes down before the timeout, False
    472                  otherwise.
    473         """
    474         @retry.retry(error.TimeoutException, timeout_min=timeout/60.0,
    475                      delay_sec=1)
    476         def _wait_down():
    477             if self.is_up(command=command):
    478                 raise error.TimeoutException('Device is still up.')
    479             return True
    480 
    481         try:
    482             _wait_down()
    483             logging.debug('Host %s is now down', self.hostname)
    484             return True
    485         except error.TimeoutException:
    486             logging.debug('Host %s is still up after waiting %d seconds',
    487                           self.hostname, timeout)
    488             return False
    489 
    490 
    491     def reboot(self):
    492         """Reboot the android device via adb.
    493 
    494         @raises AutoservRebootError if reboot failed.
    495         """
    496         # Not calling super.reboot() as we want to reboot the ADB device not
    497         # the test station we are running ADB on.
    498         self.adb_run('reboot', timeout=10, ignore_timeout=True)
    499         if not self.wait_down():
    500             raise error.AutoservRebootError(
    501                     'ADB Device is still up after reboot')
    502         if not self.wait_up():
    503             raise error.AutoservRebootError(
    504                     'ADB Device failed to return from reboot.')
    505         self._reset_adbd_connection()
    506 
    507 
    508     def remount(self):
    509         """Remounts paritions on the device read-write.
    510 
    511         Specifically, the /system, /vendor (if present) and /oem (if present)
    512         partitions on the device are remounted read-write.
    513         """
    514         self.adb_run('remount')
    515 
    516 
    517     @staticmethod
    518     def parse_device_serials(devices_output):
    519         """Return a list of parsed serials from the output.
    520 
    521         @param devices_output: Output from either an adb or fastboot command.
    522 
    523         @returns List of device serials
    524         """
    525         devices = []
    526         for line in devices_output.splitlines():
    527             match = re.search(DEVICE_FINDER_REGEX, line)
    528             if match:
    529                 serial = match.group('SERIAL')
    530                 if serial == DEVICE_NO_SERIAL_MSG or re.match(r'^\?+$', serial):
    531                     serial = DEVICE_NO_SERIAL_TAG
    532                 logging.debug('Found Device: %s', serial)
    533                 devices.append(serial)
    534         return devices
    535 
    536 
    537     def _get_devices(self, use_adb):
    538         """Get a list of devices currently attached to the test station.
    539 
    540         @params use_adb: True to get adb accessible devices. Set to False to
    541                          get fastboot accessible devices.
    542 
    543         @returns a list of devices attached to the test station.
    544         """
    545         if use_adb:
    546             result = self.adb_run('devices')
    547         else:
    548             result = self.fastboot_run('devices')
    549         return self.parse_device_serials(result.stdout)
    550 
    551 
    552     def adb_devices(self):
    553         """Get a list of devices currently attached to the test station and
    554         accessible with the adb command."""
    555         devices = self._get_devices(use_adb=True)
    556         if self.adb_serial is None and len(devices) > 1:
    557             raise error.AutoservError(
    558                     'Not given ADB serial but multiple devices detected')
    559         return devices
    560 
    561 
    562     def fastboot_devices(self):
    563         """Get a list of devices currently attached to the test station and
    564         accessible by fastboot command.
    565         """
    566         devices = self._get_devices(use_adb=False)
    567         if self.fastboot_serial is None and len(devices) > 1:
    568             raise error.AutoservError(
    569                     'Not given fastboot serial but multiple devices detected')
    570         return devices
    571 
    572 
    573     def is_up(self, timeout=0, command=ADB_CMD):
    574         """Determine if the specified adb device is up with expected mode.
    575 
    576         @param timeout: Not currently used.
    577         @param command: `adb`, the device can be accessed by adb command,
    578                 or `fastboot`, the device can be accessed by fastboot command.
    579                 Default is set to `adb`.
    580 
    581         @returns True if the device is detectable by given command, False
    582                  otherwise.
    583 
    584         """
    585         if command == ADB_CMD:
    586             devices = self.adb_devices()
    587             serial = self.adb_serial
    588             # ADB has a device state, if the device is not online, no
    589             # subsequent ADB command will complete.
    590             if len(devices) == 0 or not self.is_device_ready():
    591                 logging.debug('Waiting for device to enter the ready state.')
    592                 return False
    593         elif command == FASTBOOT_CMD:
    594             devices = self.fastboot_devices()
    595             serial = self.fastboot_serial
    596         else:
    597             raise NotImplementedError('Mode %s is not supported' % command)
    598 
    599         return bool(devices and (not serial or serial in devices))
    600 
    601 
    602     def close(self):
    603         """Close the ADBHost object.
    604 
    605         Called as the test ends. Will return the device to USB mode and kill
    606         the ADB server.
    607         """
    608         if self._use_tcpip:
    609             # Return the device to usb mode.
    610             self.adb_run('usb')
    611         # TODO(sbasi) Originally, we would kill the server after each test to
    612         # reduce the opportunity for bad server state to hang around.
    613         # Unfortunately, there is a period of time after each kill during which
    614         # the Android device becomes unusable, and if we start the next test
    615         # too quickly, we'll get an error complaining about no ADB device
    616         # attached.
    617         #self.adb_run('kill-server')
    618         # |close| the associated teststation as well.
    619         self.teststation.close()
    620         return super(ADBHost, self).close()
    621 
    622 
    623     def syslog(self, message, tag='autotest'):
    624         """Logs a message to syslog on the device.
    625 
    626         @param message String message to log into syslog
    627         @param tag String tag prefix for syslog
    628 
    629         """
    630         self.run('log -t "%s" "%s"' % (tag, message))
    631 
    632 
    633     def get_autodir(self):
    634         """Return the directory to install autotest for client side tests."""
    635         return '/data/autotest'
    636 
    637 
    638     def is_device_ready(self):
    639         """Return the if the device is ready for ADB commands."""
    640         dev_state = self.adb_run('get-state').stdout.strip()
    641         logging.debug('Current device state: %s', dev_state)
    642         return dev_state == 'device'
    643 
    644 
    645     def verify_connectivity(self):
    646         """Verify we can connect to the device."""
    647         if not self.is_device_ready():
    648             raise error.AutoservHostError('device state is not in the '
    649                                           '\'device\' state.')
    650 
    651 
    652     def verify_software(self):
    653         """Verify working software on an adb_host.
    654 
    655         TODO (crbug.com/532222): Actually implement this method.
    656         """
    657         # Check if adb and fastboot are present.
    658         self.teststation.run('which adb')
    659         self.teststation.run('which fastboot')
    660         self.teststation.run('which unzip')
    661 
    662 
    663     def verify_job_repo_url(self, tag=''):
    664         """Make sure job_repo_url of this host is valid.
    665 
    666         TODO (crbug.com/532223): Actually implement this method.
    667 
    668         @param tag: The tag from the server job, in the format
    669                     <job_id>-<user>/<hostname>, or <hostless> for a server job.
    670         """
    671         return
    672 
    673 
    674     def repair(self):
    675         """Attempt to get the DUT to pass `self.verify()`."""
    676         try:
    677             self.ensure_adb_mode(timeout=30)
    678             return
    679         except error.AutoservError as e:
    680             logging.error(e)
    681         logging.debug('Verifying the device is accessible via fastboot.')
    682         self.ensure_bootloader_mode()
    683         if not self.job.run_test(
    684                 'provision_AndroidUpdate', host=self, value=None,
    685                 force=True, repair=True):
    686             raise error.AutoservRepairTotalFailure(
    687                     'Unable to repair the device.')
    688 
    689 
    690     def send_file(self, source, dest, delete_dest=False,
    691                   preserve_symlinks=False):
    692         """Copy files from the drone to the device.
    693 
    694         Just a note, there is the possibility the test station is localhost
    695         which makes some of these steps redundant (e.g. creating tmp dir) but
    696         that scenario will undoubtedly be a development scenario (test station
    697         is also the moblab) and not the typical live test running scenario so
    698         the redundancy I think is harmless.
    699 
    700         @param source: The file/directory on the drone to send to the device.
    701         @param dest: The destination path on the device to copy to.
    702         @param delete_dest: A flag set to choose whether or not to delete
    703                             dest on the device if it exists.
    704         @param preserve_symlinks: Controls if symlinks on the source will be
    705                                   copied as such on the destination or
    706                                   transformed into the referenced
    707                                   file/directory.
    708         """
    709         # If we need to preserve symlinks, let's check if the source is a
    710         # symlink itself and if so, just create it on the device.
    711         if preserve_symlinks:
    712             symlink_target = None
    713             try:
    714                 symlink_target = os.readlink(source)
    715             except OSError:
    716                 # Guess it's not a symlink.
    717                 pass
    718 
    719             if symlink_target is not None:
    720                 # Once we create the symlink, let's get out of here.
    721                 self.run('ln -s %s %s' % (symlink_target, dest))
    722                 return
    723 
    724         # Stage the files on the test station.
    725         tmp_dir = self.teststation.get_tmp_dir()
    726         src_path = os.path.join(tmp_dir, os.path.basename(dest))
    727         # Now copy the file over to the test station so you can reference the
    728         # file in the push command.
    729         self.teststation.send_file(source, src_path,
    730                                    preserve_symlinks=preserve_symlinks)
    731 
    732         if delete_dest:
    733             self.run('rm -rf %s' % dest)
    734 
    735         self.adb_run('push %s %s' % (src_path, dest))
    736 
    737         # Cleanup the test station.
    738         try:
    739             self.teststation.run('rm -rf %s' % tmp_dir)
    740         except (error.AutoservRunError, error.AutoservSSHTimeout) as e:
    741             logging.warn('failed to remove dir %s: %s', tmp_dir, e)
    742 
    743 
    744     def _get_file_info(self, dest):
    745         """Get permission and possible symlink info about file on the device.
    746 
    747         These files are on the device so we only have shell commands (via adb)
    748         to get the info we want.  We'll use 'ls' to get it all.
    749 
    750         @param dest: File to get info about.
    751 
    752         @returns a dict of the file permissions and symlink.
    753         """
    754         # Grab file info.
    755         file_info = self.run_output('ls -l %s' % dest)
    756         symlink = None
    757         perms = 0
    758         match = re.match(FILE_INFO_REGEX, file_info)
    759         if match:
    760             # Check if it's a symlink and grab the linked dest if it is.
    761             if match.group('TYPE') == 'l':
    762                 symlink_match = re.match(FILE_SYMLINK_REGEX, file_info)
    763                 if symlink_match:
    764                     symlink = symlink_match.group('SYMLINK')
    765 
    766             # Set the perms.
    767             for perm, perm_flag in zip(match.group('PERMS'), FILE_PERMS_FLAGS):
    768                 if perm != '-':
    769                     perms |= perm_flag
    770 
    771         return {'perms': perms,
    772                 'symlink': symlink}
    773 
    774 
    775     def get_file(self, source, dest, delete_dest=False, preserve_perm=True,
    776                  preserve_symlinks=False):
    777         """Copy files from the device to the drone.
    778 
    779         Just a note, there is the possibility the test station is localhost
    780         which makes some of these steps redundant (e.g. creating tmp dir) but
    781         that scenario will undoubtedly be a development scenario (test station
    782         is also the moblab) and not the typical live test running scenario so
    783         the redundancy I think is harmless.
    784 
    785         @param source: The file/directory on the device to copy back to the
    786                        drone.
    787         @param dest: The destination path on the drone to copy to.
    788         @param delete_dest: A flag set to choose whether or not to delete
    789                             dest on the drone if it exists.
    790         @param preserve_perm: Tells get_file() to try to preserve the sources
    791                               permissions on files and dirs.
    792         @param preserve_symlinks: Try to preserve symlinks instead of
    793                                   transforming them into files/dirs on copy.
    794         """
    795         # Stage the files on the test station.
    796         tmp_dir = self.teststation.get_tmp_dir()
    797         dest_path = os.path.join(tmp_dir, os.path.basename(source))
    798 
    799         if delete_dest:
    800             self.teststation.run('rm -rf %s' % dest)
    801 
    802         source_info = {}
    803         if preserve_symlinks or preserve_perm:
    804             source_info = self._get_file_info(source)
    805 
    806         # If we want to preserve symlinks, just create it here, otherwise pull
    807         # the file off the device.
    808         if preserve_symlinks and source_info['symlink']:
    809             os.symlink(source_info['symlink'], dest)
    810         else:
    811             self.adb_run('pull %s %s' % (source, dest_path))
    812 
    813             # Copy over the file from the test station and clean up.
    814             self.teststation.get_file(dest_path, dest)
    815             try:
    816                 self.teststation.run('rm -rf %s' % tmp_dir)
    817             except (error.AutoservRunError, error.AutoservSSHTimeout) as e:
    818                 logging.warn('failed to remove dir %s: %s', tmp_dir, e)
    819 
    820         if preserve_perm:
    821             os.chmod(dest, source_info['perms'])
    822 
    823 
    824     def get_release_version(self):
    825         """Get the release version from the RELEASE_FILE on the device.
    826 
    827         @returns The release string in the RELEASE_FILE.
    828 
    829         """
    830         return self.run_output('getprop %s' % RELEASE_FILE)
    831 
    832 
    833     def get_tmp_dir(self, parent=''):
    834         """Return a suitable temporary directory on the device.
    835 
    836         We ensure this is a subdirectory of /data/local/tmp.
    837 
    838         @param parent: Parent directory of the returned tmp dir.
    839 
    840         @returns a path to the temp directory on the host.
    841         """
    842         # TODO(kevcheng): Refactor the cleanup of tmp dir to be inherited
    843         #                 from the parent.
    844         if not parent.startswith(TMP_DIR):
    845             parent = os.path.join(TMP_DIR, parent.lstrip(os.path.sep))
    846         self.run('mkdir -p %s' % parent)
    847         tmp_dir = self.run_output('mktemp -d -p %s' % parent)
    848         self.tmp_dirs.append(tmp_dir)
    849         return tmp_dir
    850 
    851 
    852     def get_platform(self):
    853         """Determine the correct platform label for this host.
    854 
    855         TODO (crbug.com/536250): Figure out what we want to do for adb_host's
    856                                  get_platform.
    857 
    858         @returns a string representing this host's platform.
    859         """
    860         return 'adb'
    861 
    862 
    863     def get_os_type(self):
    864         """Get the OS type of the DUT, e.g., android or brillo.
    865         """
    866         if not self._os_type:
    867             if self.run_output('getprop ro.product.brand') == 'Brillo':
    868                 self._os_type = OS_TYPE_BRILLO
    869             else:
    870                 self._os_type = OS_TYPE_ANDROID
    871 
    872         return self._os_type
    873 
    874 
    875     def _forward(self, reverse, args):
    876         """Execute a forwarding command.
    877 
    878         @param reverse: Whether this is reverse forwarding (Boolean).
    879         @param args: List of command arguments.
    880         """
    881         cmd = '%s %s' % ('reverse' if reverse else 'forward', ' '.join(args))
    882         self.adb_run(cmd)
    883 
    884 
    885     def add_forwarding(self, src, dst, reverse=False, rebind=True):
    886         """Forward a port between the ADB host and device.
    887 
    888         Port specifications are any strings accepted as such by ADB, for
    889         example 'tcp:8080'.
    890 
    891         @param src: Port specification to forward from.
    892         @param dst: Port specification to forward to.
    893         @param reverse: Do reverse forwarding from device to host (Boolean).
    894         @param rebind: Allow rebinding an already bound port (Boolean).
    895         """
    896         args = []
    897         if not rebind:
    898             args.append('--no-rebind')
    899         args += [src, dst]
    900         self._forward(reverse, args)
    901 
    902 
    903     def remove_forwarding(self, src=None, reverse=False):
    904         """Removes forwarding on port.
    905 
    906         @param src: Port specification, or None to remove all forwarding.
    907         @param reverse: Whether this is reverse forwarding (Boolean).
    908         """
    909         args = []
    910         if src is None:
    911             args.append('--remove-all')
    912         else:
    913             args += ['--remove', src]
    914         self._forward(reverse, args)
    915 
    916 
    917     def rpc_port_forward(self, port, local_port):
    918         """
    919         Forwards a port securely through a tunnel process from the server
    920         to the DUT for RPC server connection.
    921         Add a 'ADB forward' rule to forward the RPC packets from the AdbHost
    922         to the DUT.
    923 
    924         @param port: remote port on the DUT.
    925         @param local_port: local forwarding port.
    926 
    927         @return: the tunnel process.
    928         """
    929         self.add_forwarding('tcp:%s' % port, 'tcp:%s' % port)
    930         return super(ADBHost, self).rpc_port_forward(port, local_port)
    931 
    932 
    933     def rpc_port_disconnect(self, tunnel_proc, port):
    934         """
    935         Disconnects a previously forwarded port from the server to the DUT for
    936         RPC server connection.
    937         Remove the previously added 'ADB forward' rule to forward the RPC
    938         packets from the AdbHost to the DUT.
    939 
    940         @param tunnel_proc: the original tunnel process returned from
    941                             |rpc_port_forward|.
    942         @param port: remote port on the DUT.
    943 
    944         """
    945         self.remove_forwarding('tcp:%s' % port)
    946         super(ADBHost, self).rpc_port_disconnect(tunnel_proc, port)
    947 
    948 
    949     def ensure_bootloader_mode(self):
    950         """Ensure the device is in bootloader mode.
    951 
    952         @raise: error.AutoservError if the device failed to reboot into
    953                 bootloader mode.
    954         """
    955         if self.is_up(command=FASTBOOT_CMD):
    956             return
    957         self.adb_run('reboot bootloader')
    958         if not self.wait_up(command=FASTBOOT_CMD):
    959             raise error.AutoservError(
    960                     'The device failed to reboot into bootloader mode.')
    961 
    962 
    963     def ensure_adb_mode(self, timeout=DEFAULT_WAIT_UP_TIME_SECONDS):
    964         """Ensure the device is up and can be accessed by adb command.
    965 
    966         @param timeout: Time limit in seconds before returning even if the host
    967                         is not up.
    968 
    969         @raise: error.AutoservError if the device failed to reboot into
    970                 adb mode.
    971         """
    972         if self.is_up():
    973             return
    974         self.fastboot_run('reboot')
    975         if not self.wait_up(timeout=timeout):
    976             raise error.AutoservError(
    977                     'The device failed to reboot into adb mode.')
    978         self._reset_adbd_connection()
    979 
    980 
    981     @classmethod
    982     def _get_build_info_from_build_url(cls, build_url):
    983         """Get the Android build information from the build url.
    984 
    985         @param build_url: The url to use for downloading Android artifacts.
    986                 pattern: http://$devserver:###/static/branch/target/build_id
    987 
    988         @return: A dictionary of build information, including keys: board,
    989                  branch, target, build_id.
    990         @raise AndroidInstallError: If failed to parse build_url.
    991         """
    992         if not build_url:
    993             raise AndroidInstallError('Need build_url to download image files.')
    994 
    995         try:
    996             match = re.match(DEVSERVER_URL_REGEX, build_url)
    997             return {'board': match.group('BOARD'),
    998                     'branch': match.group('BRANCH'),
    999                     'target': ('%s-%s' % (match.group('BOARD'),
   1000                                           match.group('BUILD_TYPE'))),
   1001                     'build_id': match.group('BUILD_ID')}
   1002         except (AttributeError, IndexError, ValueError) as e:
   1003             raise AndroidInstallError(
   1004                     'Failed to parse build url: %s\nError: %s' % (build_url, e))
   1005 
   1006 
   1007     @retry.retry(error.AutoservRunError, timeout_min=10)
   1008     def _download_file(self, build_url, file, dest_dir):
   1009         """Download the given file from the build url.
   1010 
   1011         @param build_url: The url to use for downloading Android artifacts.
   1012                 pattern: http://$devserver:###/static/branch/target/build_id
   1013         @param file: Name of the file to be downloaded, e.g., boot.img.
   1014         @param dest_dir: Destination folder for the file to be downloaded to.
   1015         """
   1016         src_url = os.path.join(build_url, file)
   1017         dest_file = os.path.join(dest_dir, file)
   1018         try:
   1019             self.teststation.run('wget -q -O "%s" "%s"' % (dest_file, src_url))
   1020         except:
   1021             # Delete the destination file if download failed.
   1022             self.teststation.run('rm -f "%s"' % dest_file)
   1023             raise
   1024 
   1025 
   1026     def stage_android_image_files(self, build_url):
   1027         """Download required image files from the given build_url to a local
   1028         directory in the machine runs fastboot command.
   1029 
   1030         @param build_url: The url to use for downloading Android artifacts.
   1031                 pattern: http://$devserver:###/static/branch/target/build_id
   1032 
   1033         @return: Path to the directory contains image files.
   1034         """
   1035         build_info = self._get_build_info_from_build_url(build_url)
   1036 
   1037         zipped_image_file = ANDROID_IMAGE_FILE_FMT % build_info
   1038         image_dir = self.teststation.get_tmp_dir()
   1039         image_files = [zipped_image_file] + ANDROID_STANDALONE_IMAGES
   1040 
   1041         try:
   1042             for image_file in image_files:
   1043                 self._download_file(build_url, image_file, image_dir)
   1044 
   1045             self.teststation.run('unzip "%s/%s" -x -d "%s"' %
   1046                                  (image_dir, zipped_image_file, image_dir))
   1047 
   1048             return image_dir
   1049         except:
   1050             self.teststation.run('rm -rf %s' % image_dir)
   1051             raise
   1052 
   1053 
   1054     def stage_brillo_image_files(self, build_url):
   1055         """Download required brillo image files from the given build_url to a
   1056         local directory in the machine runs fastboot command.
   1057 
   1058         @param build_url: The url to use for downloading Android artifacts.
   1059                 pattern: http://$devserver:###/static/branch/target/build_id
   1060 
   1061         @return: Path to the directory contains image files.
   1062         """
   1063         build_info = self._get_build_info_from_build_url(build_url)
   1064 
   1065         zipped_image_file = ANDROID_IMAGE_FILE_FMT % build_info
   1066         vendor_partitions_file = BRILLO_VENDOR_PARTITIONS_FILE_FMT % build_info
   1067         image_dir = self.teststation.get_tmp_dir()
   1068         image_files = [zipped_image_file, vendor_partitions_file]
   1069 
   1070         try:
   1071             for image_file in image_files:
   1072                 self._download_file(build_url, image_file, image_dir)
   1073 
   1074             self.teststation.run('unzip "%s/%s" -x -d "%s"' %
   1075                                  (image_dir, zipped_image_file, image_dir))
   1076             self.teststation.run('unzip "%s/%s" -x -d "%s"' %
   1077                                  (image_dir, vendor_partitions_file,
   1078                                   os.path.join(image_dir, 'vendor')))
   1079             return image_dir
   1080         except:
   1081             self.teststation.run('rm -rf %s' % image_dir)
   1082             raise
   1083 
   1084 
   1085     def stage_build_for_install(self, build_name, os_type=None):
   1086         """Stage a build on a devserver and return the build_url and devserver.
   1087 
   1088         @param build_name: a name like git-master/shamu-userdebug/2040953
   1089 
   1090         @returns a tuple with an update URL like:
   1091             http://172.22.50.122:8080/git-master/shamu-userdebug/2040953
   1092             and the devserver instance.
   1093         """
   1094         os_type = os_type or self.get_os_type()
   1095         logging.info('Staging build for installation: %s', build_name)
   1096         devserver = dev_server.AndroidBuildServer.resolve(build_name,
   1097                                                           self.hostname)
   1098         build_name = devserver.translate(build_name)
   1099         branch, target, build_id = utils.parse_android_build(build_name)
   1100         is_brillo = os_type == OS_TYPE_BRILLO
   1101         devserver.trigger_download(target, build_id, branch, is_brillo,
   1102                                    synchronous=False)
   1103         return '%s/static/%s' % (devserver.url(), build_name), devserver
   1104 
   1105 
   1106     def install_android(self, build_url, build_local_path=None, wipe=True,
   1107                         flash_all=False):
   1108         """Install the Android DUT.
   1109 
   1110         Following are the steps used here to provision an android device:
   1111         1. If build_local_path is not set, download the image zip file, e.g.,
   1112            shamu-img-2284311.zip, unzip it.
   1113         2. Run fastboot to install following artifacts:
   1114            bootloader, radio, boot, system, vendor(only if exists)
   1115 
   1116         Repair is not supported for Android devices yet.
   1117 
   1118         @param build_url: The url to use for downloading Android artifacts.
   1119                 pattern: http://$devserver:###/static/$build
   1120         @param build_local_path: The path to a local folder that contains the
   1121                 image files needed to provision the device. Note that the folder
   1122                 is in the machine running adb command, rather than the drone.
   1123         @param wipe: If true, userdata will be wiped before flashing.
   1124         @param flash_all: If True, all img files found in img_path will be
   1125                 flashed. Otherwise, only boot and system are flashed.
   1126 
   1127         @raises AndroidInstallError if any error occurs.
   1128         """
   1129         # If the build is not staged in local server yet, clean up the temp
   1130         # folder used to store image files after the provision is completed.
   1131         delete_build_folder = bool(not build_local_path)
   1132 
   1133         try:
   1134             # Download image files needed for provision to a local directory.
   1135             if not build_local_path:
   1136                 build_local_path = self.stage_android_image_files(build_url)
   1137 
   1138             # Device needs to be in bootloader mode for flashing.
   1139             self.ensure_bootloader_mode()
   1140 
   1141             if wipe:
   1142                 self.fastboot_run('-w')
   1143 
   1144             # Get all *.img file in the build_local_path.
   1145             list_file_cmd = 'ls -d %s' % os.path.join(build_local_path, '*.img')
   1146             image_files = self.teststation.run(
   1147                     list_file_cmd).stdout.strip().split()
   1148             images = dict([(os.path.basename(f), f) for f in image_files])
   1149             for image, image_file in images.items():
   1150                 if image not in ANDROID_IMAGES:
   1151                     continue
   1152                 logging.info('Flashing %s...', image_file)
   1153                 self.fastboot_run('flash %s %s' % (image[:-4], image_file))
   1154                 if image == ANDROID_BOOTLOADER:
   1155                     self.fastboot_run('reboot-bootloader')
   1156                     self.wait_up(command=FASTBOOT_CMD)
   1157         except Exception as e:
   1158             logging.error('Install Android build failed with error: %s', e)
   1159             # Re-raise the exception with type of AndroidInstallError.
   1160             raise AndroidInstallError, sys.exc_info()[1], sys.exc_info()[2]
   1161         finally:
   1162             if delete_build_folder:
   1163                 self.teststation.run('rm -rf %s' % build_local_path)
   1164             timeout = (WAIT_UP_AFTER_WIPE_TIME_SECONDS if wipe else
   1165                        DEFAULT_WAIT_UP_TIME_SECONDS)
   1166             self.ensure_adb_mode(timeout=timeout)
   1167         logging.info('Successfully installed Android build staged at %s.',
   1168                      build_url)
   1169 
   1170 
   1171     def install_brillo(self, build_url, build_local_path=None):
   1172         """Install the Brillo DUT.
   1173 
   1174         Following are the steps used here to provision an android device:
   1175         1. If build_local_path is not set, download the image zip file, e.g.,
   1176            dragonboard-img-123456.zip, unzip it. And download the vendor
   1177            partition zip file, e.g., dragonboard-vendor_partitions-123456.zip,
   1178            unzip it to vendor folder.
   1179         2. Run provision_device script to install OS images and vendor
   1180            partitions.
   1181 
   1182         @param build_url: The url to use for downloading Android artifacts.
   1183                 pattern: http://$devserver:###/static/$build
   1184         @param build_local_path: The path to a local folder that contains the
   1185                 image files needed to provision the device. Note that the folder
   1186                 is in the machine running adb command, rather than the drone.
   1187 
   1188         @raises AndroidInstallError if any error occurs.
   1189         """
   1190         # If the build is not staged in local server yet, clean up the temp
   1191         # folder used to store image files after the provision is completed.
   1192         delete_build_folder = bool(not build_local_path)
   1193 
   1194         try:
   1195             # Download image files needed for provision to a local directory.
   1196             if not build_local_path:
   1197                 build_local_path = self.stage_brillo_image_files(build_url)
   1198 
   1199             # Device needs to be in bootloader mode for flashing.
   1200             self.ensure_bootloader_mode()
   1201 
   1202             # Run provision_device command to install image files and vendor
   1203             # partitions.
   1204             vendor_partition_dir = os.path.join(build_local_path, 'vendor')
   1205             cmd = (BRILLO_PROVISION_CMD %
   1206                    {'os_image_dir': build_local_path,
   1207                     'vendor_partition_dir': vendor_partition_dir})
   1208             self.teststation.run(cmd)
   1209         except Exception as e:
   1210             logging.error('Install Brillo build failed with error: %s', e)
   1211             # Re-raise the exception with type of AndroidInstallError.
   1212             raise AndroidInstallError, sys.exc_info()[1], sys.exc_info()[2]
   1213         finally:
   1214             if delete_build_folder:
   1215                 self.teststation.run('rm -rf %s' % build_local_path)
   1216             self.ensure_adb_mode()
   1217         logging.info('Successfully installed Android build staged at %s.',
   1218                      build_url)
   1219 
   1220 
   1221     def machine_install(self, build_url=None, build_local_path=None, wipe=True,
   1222                         flash_all=False, os_type=None):
   1223         """Install the DUT.
   1224 
   1225         @param build_url: The url to use for downloading Android artifacts.
   1226                 pattern: http://$devserver:###/static/$build. If build_url is
   1227                 set to None, the code may try _parser.options.image to do the
   1228                 installation. If none of them is set, machine_install will fail.
   1229         @param build_local_path: The path to a local directory that contains the
   1230                 image files needed to provision the device.
   1231         @param wipe: If true, userdata will be wiped before flashing.
   1232         @param flash_all: If True, all img files found in img_path will be
   1233                 flashed. Otherwise, only boot and system are flashed.
   1234 
   1235         @returns Name of the image installed.
   1236         """
   1237         os_type = os_type or self.get_os_type()
   1238         if not build_url and self._parser.options.image:
   1239             build_url, _ = self.stage_build_for_install(
   1240                     self._parser.options.image, os_type=os_type)
   1241         if os_type == OS_TYPE_ANDROID:
   1242             self.install_android(
   1243                     build_url=build_url, build_local_path=build_local_path,
   1244                     wipe=wipe, flash_all=flash_all)
   1245         elif os_type == OS_TYPE_BRILLO:
   1246             self.install_brillo(
   1247                     build_url=build_url, build_local_path=build_local_path)
   1248         else:
   1249             raise error.InstallError(
   1250                     'Installation of os type %s is not supported.' %
   1251                     self.get_os_type())
   1252         return build_url.split('static/')[-1]
   1253 
   1254 
   1255     def list_files_glob(self, path_glob):
   1256         """Get a list of files on the device given glob pattern path.
   1257 
   1258         @param path_glob: The path glob that we want to return the list of
   1259                 files that match the glob.  Relative paths will not work as
   1260                 expected.  Supply an absolute path to get the list of files
   1261                 you're hoping for.
   1262 
   1263         @returns List of files that match the path_glob.
   1264         """
   1265         # This is just in case path_glob has no path separator.
   1266         base_path = os.path.dirname(path_glob) or '.'
   1267         result = self.run('find %s -path \'%s\' -print' %
   1268                           (base_path, path_glob))
   1269         if result.exit_status != 0:
   1270             return []
   1271         return result.stdout.splitlines()
   1272 
   1273 
   1274     def install_apk(self, apk):
   1275         """Install the specified apk.
   1276 
   1277         This will install the apk and override it if it's already installed and
   1278         will also allow for downgraded apks.
   1279 
   1280         @param apk: The path to apk file.
   1281         """
   1282         self.adb_run('install -r -d %s' % apk)
   1283