# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import datetime
import errno
import functools
import logging
import os
import re
import signal
import stat
import sys
import time

import common

from autotest_lib.client.bin import utils as client_utils
from autotest_lib.client.common_lib import android_utils
from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib import global_config
from autotest_lib.client.common_lib.cros import dev_server
from autotest_lib.client.common_lib.cros import retry
from autotest_lib.server import afe_utils
from autotest_lib.server import autoserv_parser
from autotest_lib.server import constants as server_constants
from autotest_lib.server import utils
from autotest_lib.server.cros import provision
from autotest_lib.server.cros.dynamic_suite import tools
from autotest_lib.server.cros.dynamic_suite import constants
from autotest_lib.server.hosts import abstract_ssh
from autotest_lib.server.hosts import adb_label
from autotest_lib.server.hosts import base_label
from autotest_lib.server.hosts import teststation_host


CONFIG = global_config.global_config

ADB_CMD = 'adb'
FASTBOOT_CMD = 'fastboot'
SHELL_CMD = 'shell'
# Some devices have no serial, then `adb serial` has output such as:
# (no serial number)  device
# ??????????          device
DEVICE_NO_SERIAL_MSG = '(no serial number)'
DEVICE_NO_SERIAL_TAG = '<NO_SERIAL>'
# Regex to find an adb device. Examples:
# 0146B5580B01801B    device
# 018e0ecb20c97a62    device
# 172.22.75.141:5555  device
# localhost:22        device
DEVICE_FINDER_REGEX = (r'^(?P<SERIAL>([\w-]+)|((tcp:)?' +
                       '\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}([:]5555)?)|' +
                       '((tcp:)?localhost([:]22)?)|' +
                       re.escape(DEVICE_NO_SERIAL_MSG) +
                       r')[ \t]+(?:device|fastboot)')
CMD_OUTPUT_PREFIX = 'ADB_CMD_OUTPUT'
CMD_OUTPUT_REGEX = ('(?P<OUTPUT>[\s\S]*)%s:(?P<EXIT_CODE>\d{1,3})' %
                    CMD_OUTPUT_PREFIX)
RELEASE_FILE = 'ro.build.version.release'
BOARD_FILE = 'ro.product.device'
SDK_FILE = 'ro.build.version.sdk'
LOGCAT_FILE_FMT = 'logcat_%s.log'
TMP_DIR = '/data/local/tmp'
# Regex to pull out file type, perms and symlink. Example:
# lrwxrwx--- 1 6 root system 2015-09-12 19:21 blah_link -> ./blah
FILE_INFO_REGEX = '^(?P<TYPE>[dl-])(?P<PERMS>[rwx-]{9})'
FILE_SYMLINK_REGEX = '^.*-> (?P<SYMLINK>.+)'
# List of the perm stats indexed by the order they are listed in the example
# supplied above.
FILE_PERMS_FLAGS = [stat.S_IRUSR, stat.S_IWUSR, stat.S_IXUSR,
                    stat.S_IRGRP, stat.S_IWGRP, stat.S_IXGRP,
                    stat.S_IROTH, stat.S_IWOTH, stat.S_IXOTH]

# Default maximum number of seconds to wait for a device to be down.
DEFAULT_WAIT_DOWN_TIME_SECONDS = 10
# Default maximum number of seconds to wait for a device to be up.
DEFAULT_WAIT_UP_TIME_SECONDS = 300
# Maximum number of seconds to wait for a device to be up after it's wiped.
WAIT_UP_AFTER_WIPE_TIME_SECONDS = 1200

# Default timeout for retrying adb/fastboot command.
DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS = 10

OS_TYPE_ANDROID = 'android'
OS_TYPE_BRILLO = 'brillo'

# Regex to parse build name to get the detailed build information.
BUILD_REGEX = ('(?P<BRANCH>([^/]+))/(?P<BUILD_TARGET>([^/]+))-'
               '(?P<BUILD_TYPE>([^/]+))/(?P<BUILD_ID>([^/]+))')
# Regex to parse devserver url to get the detailed build information. Sample
# url: http://$devserver:8080/static/branch/target/build_id
DEVSERVER_URL_REGEX = '.*/%s/*' % BUILD_REGEX

ANDROID_IMAGE_FILE_FMT = '%(build_target)s-img-%(build_id)s.zip'

BRILLO_VENDOR_PARTITIONS_FILE_FMT = (
        '%(build_target)s-vendor_partitions-%(build_id)s.zip')
AUTOTEST_SERVER_PACKAGE_FILE_FMT = (
        '%(build_target)s-autotest_server_package-%(build_id)s.tar.bz2')
ADB_DEVICE_PREFIXES = ['product:', 'model:', 'device:']

# Command to provision a Brillo device.
# os_image_dir: The full path of the directory that contains all the Android image
# files (from the image zip file).
# vendor_partition_dir: The full path of the directory that contains all the
# Brillo vendor partitions, and provision-device script.
BRILLO_PROVISION_CMD = (
        'sudo ANDROID_PROVISION_OS_PARTITIONS=%(os_image_dir)s '
        'ANDROID_PROVISION_VENDOR_PARTITIONS=%(vendor_partition_dir)s '
        '%(vendor_partition_dir)s/provision-device')

# Default timeout in minutes for fastboot commands.
DEFAULT_FASTBOOT_RETRY_TIMEOUT_MIN = 10

# Default permissions for files/dirs copied from the device.
_DEFAULT_FILE_PERMS = 0o600
_DEFAULT_DIR_PERMS = 0o700

# Constants for getprop return value for a given property.
PROPERTY_VALUE_TRUE = '1'

# Timeout used for retrying installing apk. After reinstall apk failed, we try
# to reboot the device and try again.
APK_INSTALL_TIMEOUT_MIN = 5

# The amount of time to wait for package verification to be turned off.
DISABLE_PACKAGE_VERIFICATION_TIMEOUT_MIN = 1

# Directory where (non-Brillo) Android stores tombstone crash logs.
ANDROID_TOMBSTONE_CRASH_LOG_DIR = '/data/tombstones'
# Directory where Brillo stores crash logs for native (non-Java) crashes.
BRILLO_NATIVE_CRASH_LOG_DIR = '/data/misc/crash_reporter/crash'

# A specific string value to return when a timeout has occurred.
TIMEOUT_MSG = 'TIMEOUT_OCCURRED'

class AndroidInstallError(error.InstallError):
    """Generic error for Android installation related exceptions."""


class ADBHost(abstract_ssh.AbstractSSHHost):
    """This class represents a host running an ADB server."""

    VERSION_PREFIX = provision.ANDROID_BUILD_VERSION_PREFIX
    _LABEL_FUNCTIONS = []
    _DETECTABLE_LABELS = []
    label_decorator = functools.partial(utils.add_label_detector,
                                        _LABEL_FUNCTIONS,
                                        _DETECTABLE_LABELS)

    _parser = autoserv_parser.autoserv_parser

    # Minimum build id that supports server side packaging. Older builds may
    # not have server side package built or with Autotest code change to support
    # server-side packaging.
    MIN_VERSION_SUPPORT_SSP = CONFIG.get_config_value(
            'AUTOSERV', 'min_launch_control_build_id_support_ssp', type=int)

    @staticmethod
    def check_host(host, timeout=10):
        """
        Check if the given host is an adb host.

        If SSH connectivity can't be established, check_host will try to use
        user 'adb' as well. If SSH connectivity still can't be established
        then the original SSH user is restored.

        @param host: An ssh host representing a device.
        @param timeout: The timeout for the run command.


        @return: True if the host device has adb.

        @raises AutoservRunError: If the command failed.
        @raises AutoservSSHTimeout: Ssh connection has timed out.
        """
        # host object may not have user attribute if it's a LocalHost object.
        current_user = host.user if hasattr(host, 'user') else None
        try:
            if not (host.hostname == 'localhost' or
                    host.verify_ssh_user_access()):
                host.user = 'adb'
            result = host.run(
                    'test -f %s' % server_constants.ANDROID_TESTER_FILEFLAG,
                    timeout=timeout)
        except (error.GenericHostRunError, error.AutoservSSHTimeout):
            if current_user is not None:
                host.user = current_user
            return False
        return result.exit_status == 0


    def _initialize(self, hostname='localhost', serials=None,
                    adb_serial=None, fastboot_serial=None,
                    teststation=None, *args, **dargs):
        """Initialize an ADB Host.

        This will create an ADB Host. Hostname should always refer to the
        test station connected to an Android DUT. This will be the DUT
        to test with.  If there are multiple, serial must be specified or an
        exception will be raised.

        @param hostname: Hostname of the machine running ADB.
        @param serials: DEPRECATED (to be removed)
        @param adb_serial: An ADB device serial. If None, assume a single
                           device is attached (and fail otherwise).
        @param fastboot_serial: A fastboot device serial. If None, defaults to
                                the ADB serial (or assumes a single device if
                                the latter is None).
        @param teststation: The teststation object ADBHost should use.
        """
        # Sets up the is_client_install_supported field.
        super(ADBHost, self)._initialize(hostname=hostname,
                                         is_client_install_supported=False,
                                         *args, **dargs)

        self.tmp_dirs = []
        self.labels = base_label.LabelRetriever(adb_label.ADB_LABELS)
        adb_serial = adb_serial or self._afe_host.attributes.get('serials')
        fastboot_serial = (fastboot_serial or
                self._afe_host.attributes.get('fastboot_serial'))

        self.adb_serial = adb_serial
        if adb_serial:
            adb_prefix = any(adb_serial.startswith(p)
                             for p in ADB_DEVICE_PREFIXES)
            self.fastboot_serial = (fastboot_serial or
                    ('tcp:%s' % adb_serial.split(':')[0] if
                    ':' in adb_serial and not adb_prefix else adb_serial))
            self._use_tcpip = ':' in adb_serial and not adb_prefix
        else:
            self.fastboot_serial = fastboot_serial or adb_serial
            self._use_tcpip = False
        self.teststation = (teststation if teststation
                else teststation_host.create_teststationhost(
                        hostname=hostname,
                        user=self.user,
                        password=self.password,
                        port=self.port
                ))

        msg ='Initializing ADB device on host: %s' % hostname
        if self.adb_serial:
            msg += ', ADB serial: %s' % self.adb_serial
        if self.fastboot_serial:
            msg += ', fastboot serial: %s' % self.fastboot_serial
        logging.debug(msg)

        self._os_type = None


    def _connect_over_tcpip_as_needed(self):
        """Connect to the ADB device over TCP/IP if so configured."""
        if not self._use_tcpip:
            return
        logging.debug('Connecting to device over TCP/IP')
        self.adb_run('connect %s' % self.adb_serial)


    def _restart_adbd_with_root_permissions(self):
        """Restarts the adb daemon with root permissions."""
        @retry.retry(error.GenericHostRunError, timeout_min=20/60.0,
                     delay_sec=1)
        def run_adb_root():
            """Run command `adb root`."""
            self.adb_run('root')

        # adb command may flake with error "device not found". Retry the root
        # command to reduce the chance of flake.
        run_adb_root()
        # TODO(ralphnathan): Remove this sleep once b/19749057 is resolved.
        time.sleep(1)
        self._connect_over_tcpip_as_needed()
        self.adb_run('wait-for-device')


    def _set_tcp_port(self):
        """Ensure the device remains in tcp/ip mode after a reboot."""
        if not self._use_tcpip:
            return
        port = self.adb_serial.split(':')[-1]
        self.run('setprop persist.adb.tcp.port %s' % port)


    def _reset_adbd_connection(self):
        """Resets adbd connection to the device after a reboot/initialization"""
        self._connect_over_tcpip_as_needed()
        self._restart_adbd_with_root_permissions()
        self._set_tcp_port()


    # pylint: disable=missing-docstring
    def adb_run(self, command, **kwargs):
        """Runs an adb command.

        This command will launch on the test station.

        Refer to _device_run method for docstring for parameters.
        """
        return self._device_run(ADB_CMD, command, **kwargs)


    # pylint: disable=missing-docstring
    def fastboot_run(self, command, **kwargs):
        """Runs an fastboot command.

        This command will launch on the test station.

        Refer to _device_run method for docstring for parameters.
        """
        return self._device_run(FASTBOOT_CMD, command, **kwargs)


    # pylint: disable=missing-docstring
    @retry.retry(error.GenericHostRunError,
                 timeout_min=DEFAULT_FASTBOOT_RETRY_TIMEOUT_MIN)
    def _fastboot_run_with_retry(self, command, **kwargs):
        """Runs an fastboot command with retry.

        This command will launch on the test station.

        Refer to _device_run method for docstring for parameters.
        """
        return self.fastboot_run(command, **kwargs)


    def _log_adb_pid(self):
        """Log the pid of adb server.

        adb's server is known to have bugs and randomly restart. BY logging
        the server's pid it will allow us to better debug random adb failures.
        """
        adb_pid = self.teststation.run('pgrep -f "adb.*server"')
        logging.debug('ADB Server PID: %s', adb_pid.stdout)


    def _device_run(self, function, command, shell=False,
                    timeout=3600, ignore_status=False, ignore_timeout=False,
                    stdout=utils.TEE_TO_LOGS, stderr=utils.TEE_TO_LOGS,
                    connect_timeout=30, options='', stdin=None, verbose=True,
                    require_sudo=False, args=()):
        """Runs a command named `function` on the test station.

        This command will launch on the test station.

        @param command: Command to run.
        @param shell: If true the command runs in the adb shell otherwise if
                      False it will be passed directly to adb. For example
                      reboot with shell=False will call 'adb reboot'. This
                      option only applies to function adb.
        @param timeout: Time limit in seconds before attempting to
                        kill the running process. The run() function
                        will take a few seconds longer than 'timeout'
                        to complete if it has to kill the process.
        @param ignore_status: Do not raise an exception, no matter
                              what the exit code of the command is.
        @param ignore_timeout: Bool True if command timeouts should be
                               ignored.  Will return None on command timeout.
        @param stdout: Redirect stdout.
        @param stderr: Redirect stderr.
        @param connect_timeout: Connection timeout (in seconds)
        @param options: String with additional ssh command options
        @param stdin: Stdin to pass (a string) to the executed command
        @param require_sudo: True to require sudo to run the command. Default is
                             False.
        @param args: Sequence of strings to pass as arguments to command by
                     quoting them in " and escaping their contents if
                     necessary.

        @returns a CMDResult object.
        """
        if function == ADB_CMD:
            serial = self.adb_serial
        elif function == FASTBOOT_CMD:
            serial = self.fastboot_serial
        else:
            raise NotImplementedError('Mode %s is not supported' % function)

        if function != ADB_CMD and shell:
            raise error.CmdError('shell option is only applicable to `adb`.')

        client_side_cmd = 'timeout --signal=%d %d %s' % (signal.SIGKILL,
                                                         timeout + 1, function)
        cmd = '%s%s ' % ('sudo -n ' if require_sudo else '', client_side_cmd)

        if serial:
            cmd += '-s %s ' % serial

        if shell:
            cmd += '%s ' % SHELL_CMD
        cmd += command

        self._log_adb_pid()

        if verbose:
            logging.debug('Command: %s', cmd)

        return self.teststation.run(cmd, timeout=timeout,
                ignore_status=ignore_status,
                ignore_timeout=ignore_timeout, stdout_tee=stdout,
                stderr_tee=stderr, options=options, stdin=stdin,
                connect_timeout=connect_timeout, args=args)


    def _run_output_with_retry(self, cmd):
        """Call run_output method for the given command with retry.

        adb command can be flaky some time, and the command may fail or return
        empty string. It may take several retries until a value can be returned.

        @param cmd: The command to run.

        @return: Return value from the command after retry.
        """
        try:
            return client_utils.poll_for_condition(
                    lambda: self.run_output(cmd, ignore_status=True),
                    timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
                    sleep_interval=0.5,
                    desc='Get return value for command `%s`' % cmd)
        except client_utils.TimeoutError:
            return ''


    def get_device_aliases(self):
        """Get all aliases for this device."""
        product = self.get_product_name()
        return android_utils.AndroidAliases.get_product_aliases(product)

    def get_product_name(self):
        """Get the product name of the device, eg., shamu, bat"""
        return self.run_output('getprop %s' % BOARD_FILE)

    def get_board_name(self):
        """Get the name of the board, e.g., shamu, bat_land etc.
        """
        product = self.get_product_name()
        return android_utils.AndroidAliases.get_board_name(product)


    @label_decorator()
    def get_board(self):
        """Determine the correct board label for the device.

        @returns a string representing this device's board.
        """
        board = self.get_board_name()
        board_os = self.get_os_type()
        return constants.BOARD_PREFIX + '-'.join([board_os, board])


    def job_start(self):
        """Overload of parent which intentionally doesn't log certain files.

        The parent implementation attempts to log certain Linux files, such as
        /var/log, which do not exist on Android, thus there is no call to the
        parent's job_start().  The sync call is made so that logcat logs can be
        approximately matched to server logs.
        """
        # Try resetting the ADB daemon on the device, however if we are
        # creating the host to do a repair job, the device maybe inaccesible
        # via ADB.
        try:
            self._reset_adbd_connection()
        except error.GenericHostRunError as e:
            logging.error('Unable to reset the device adb daemon connection: '
                          '%s.', e)

        if self.is_up():
            self._sync_time()
            self._enable_native_crash_logging()


    def run(self, command, timeout=3600, ignore_status=False,
            ignore_timeout=False, stdout_tee=utils.TEE_TO_LOGS,
            stderr_tee=utils.TEE_TO_LOGS, connect_timeout=30, options='',
            stdin=None, verbose=True, args=()):
        """Run a command on the adb device.

        The command given will be ran directly on the adb device; for example
        'ls' will be ran as: 'abd shell ls'

        @param command: The command line string.
        @param timeout: Time limit in seconds before attempting to
                        kill the running process. The run() function
                        will take a few seconds longer than 'timeout'
                        to complete if it has to kill the process.
        @param ignore_status: Do not raise an exception, no matter
                              what the exit code of the command is.
        @param ignore_timeout: Bool True if command timeouts should be
                               ignored.  Will return None on command timeout.
        @param stdout_tee: Redirect stdout.
        @param stderr_tee: Redirect stderr.
        @param connect_timeout: Connection timeout (in seconds).
        @param options: String with additional ssh command options.
        @param stdin: Stdin to pass (a string) to the executed command
        @param args: Sequence of strings to pass as arguments to command by
                     quoting them in " and escaping their contents if
                     necessary.

        @returns A CMDResult object or None if the call timed out and
                 ignore_timeout is True.

        @raises AutoservRunError: If the command failed.
        @raises AutoservSSHTimeout: Ssh connection has timed out.
        """
        command = ('"%s; echo %s:\$?"' %
                   (utils.sh_escape(command), CMD_OUTPUT_PREFIX))

        def _run():
            """Run the command and try to parse the exit code.
            """
            result = self.adb_run(
                    command, shell=True, timeout=timeout,
                    ignore_status=ignore_status, ignore_timeout=ignore_timeout,
                    stdout=stdout_tee, stderr=stderr_tee,
                    connect_timeout=connect_timeout, options=options,
                    stdin=stdin, verbose=verbose, args=args)
            if not result:
                # In case of timeouts. Set the return to a specific string
                # value. That way the caller of poll_for_condition knows
                # a timeout occurs and should return None. Return None here will
                # lead to the command to be retried.
                return TIMEOUT_MSG
            parse_output = re.match(CMD_OUTPUT_REGEX, result.stdout)
            if not parse_output and not ignore_status:
                logging.error('Failed to parse the exit code for command: `%s`.'
                              ' result: `%s`', command, result.stdout)
                return None
            elif parse_output:
                result.stdout = parse_output.group('OUTPUT')
                result.exit_status = int(parse_output.group('EXIT_CODE'))
                if result.exit_status != 0 and not ignore_status:
                    raise error.AutoservRunError(command, result)
            return result

        result = client_utils.poll_for_condition(
                lambda: _run(),
                timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
                sleep_interval=0.5,
                desc='Run command `%s`' % command)
        return None if result == TIMEOUT_MSG else result


    def check_boot_to_adb_complete(self, exception_type=error.TimeoutException):
        """Check if the device has finished booting and accessible by adb.

        @param exception_type: Type of exception to raise. Default is set to
                error.TimeoutException for retry.

        @raise exception_type: If the device has not finished booting yet, raise
                an exception of type `exception_type`.
        """
        bootcomplete = self._run_output_with_retry('getprop dev.bootcomplete')
        if bootcomplete != PROPERTY_VALUE_TRUE:
            raise exception_type('dev.bootcomplete is %s.' % bootcomplete)
        if self.get_os_type() == OS_TYPE_ANDROID:
            boot_completed = self._run_output_with_retry(
                    'getprop sys.boot_completed')
            if boot_completed != PROPERTY_VALUE_TRUE:
                raise exception_type('sys.boot_completed is %s.' %
                                     boot_completed)


    def wait_up(self, timeout=DEFAULT_WAIT_UP_TIME_SECONDS, command=ADB_CMD):
        """Wait until the remote host is up or the timeout expires.

        Overrides wait_down from AbstractSSHHost.

        @param timeout: Time limit in seconds before returning even if the host
                is not up.
        @param command: The command used to test if a device is up, i.e.,
                accessible by the given command. Default is set to `adb`.

        @returns True if the host was found to be up before the timeout expires,
                 False otherwise.
        """
        @retry.retry(error.TimeoutException, timeout_min=timeout/60.0,
                     delay_sec=1)
        def _wait_up():
            if not self.is_up(command=command):
                raise error.TimeoutException('Device is still down.')
            if command == ADB_CMD:
                self.check_boot_to_adb_complete()
            return True

        try:
            _wait_up()
            logging.debug('Host %s is now up, and can be accessed by %s.',
                          self.hostname, command)
            return True
        except error.TimeoutException:
            logging.debug('Host %s is still down after waiting %d seconds',
                          self.hostname, timeout)
            return False


    def wait_down(self, timeout=DEFAULT_WAIT_DOWN_TIME_SECONDS,
                  warning_timer=None, old_boot_id=None, command=ADB_CMD,
                  boot_id=None):
        """Wait till the host goes down.

        Return when the host is down (not accessible via the command) OR when
        the device's boot_id changes (if a boot_id was provided).

        Overrides wait_down from AbstractSSHHost.

        @param timeout: Time in seconds to wait for the host to go down.
        @param warning_timer: Time limit in seconds that will generate
                              a warning if the host is not down yet.
                              Currently ignored.
        @param old_boot_id: Not applicable for adb_host.
        @param command: `adb`, test if the device can be accessed by adb
                command, or `fastboot`, test if the device can be accessed by
                fastboot command. Default is set to `adb`.
        @param boot_id: UUID of previous boot (consider the device down when the
                        boot_id changes from this value). Ignored if None.

        @returns True if the device goes down before the timeout, False
                 otherwise.
        """
        @retry.retry(error.TimeoutException, timeout_min=timeout/60.0,
                     delay_sec=1)
        def _wait_down():
            up = self.is_up(command=command)
            if not up:
                return True
            if boot_id:
                try:
                    new_boot_id = self.get_boot_id()
                    if new_boot_id != boot_id:
                        return True
                except error.GenericHostRunError:
                    pass
            raise error.TimeoutException('Device is still up.')

        try:
            _wait_down()
            logging.debug('Host %s is now down', self.hostname)
            return True
        except error.TimeoutException:
            logging.debug('Host %s is still up after waiting %d seconds',
                          self.hostname, timeout)
            return False


    def reboot(self):
        """Reboot the android device via adb.

        @raises AutoservRebootError if reboot failed.
        """
        # Not calling super.reboot() as we want to reboot the ADB device not
        # the test station we are running ADB on.
        boot_id = self.get_boot_id()
        self.adb_run('reboot', timeout=10, ignore_timeout=True)
        if not self.wait_down(boot_id=boot_id):
            raise error.AutoservRebootError(
                    'ADB Device is still up after reboot')
        if not self.wait_up():
            raise error.AutoservRebootError(
                    'ADB Device failed to return from reboot.')
        self._reset_adbd_connection()


    def fastboot_reboot(self):
        """Do a fastboot reboot to go back to adb.

        @raises AutoservRebootError if reboot failed.
        """
        self.fastboot_run('reboot')
        if not self.wait_down(command=FASTBOOT_CMD):
            raise error.AutoservRebootError(
                    'Device is still in fastboot mode after reboot')
        if not self.wait_up():
            raise error.AutoservRebootError(
                    'Device failed to boot to adb after fastboot reboot.')
        self._reset_adbd_connection()


    def remount(self):
        """Remounts paritions on the device read-write.

        Specifically, the /system, /vendor (if present) and /oem (if present)
        partitions on the device are remounted read-write.
        """
        self.adb_run('remount')


    @staticmethod
    def parse_device_serials(devices_output):
        """Return a list of parsed serials from the output.

        @param devices_output: Output from either an adb or fastboot command.

        @returns List of device serials
        """
        devices = []
        for line in devices_output.splitlines():
            match = re.search(DEVICE_FINDER_REGEX, line)
            if match:
                serial = match.group('SERIAL')
                if serial == DEVICE_NO_SERIAL_MSG or re.match(r'^\?+$', serial):
                    serial = DEVICE_NO_SERIAL_TAG
                logging.debug('Found Device: %s', serial)
                devices.append(serial)
        return devices


    def _get_devices(self, use_adb):
        """Get a list of devices currently attached to the test station.

        @params use_adb: True to get adb accessible devices. Set to False to
                         get fastboot accessible devices.

        @returns a list of devices attached to the test station.
        """
        if use_adb:
            result = self.adb_run('devices').stdout
            if self.adb_serial and self.adb_serial not in result:
                self._connect_over_tcpip_as_needed()
        else:
            result = self.fastboot_run('devices').stdout
            if (self.fastboot_serial and
                self.fastboot_serial not in result):
                # fastboot devices won't list the devices using TCP
                try:
                    if 'product' in self.fastboot_run('getvar product',
                                                      timeout=2).stderr:
                        result += '\n%s\tfastboot' % self.fastboot_serial
                # The main reason we do a general Exception catch here instead
                # of setting ignore_timeout/status to True is because even when
                # the fastboot process has been nuked, it still stays around and
                # so bgjob wants to warn us of this and tries to read the
                # /proc/<pid>/stack file which then promptly returns an
                # 'Operation not permitted' error since we're running as moblab
                # and we don't have permission to read those files.
                except Exception:
                    pass
        return self.parse_device_serials(result)


    def adb_devices(self):
        """Get a list of devices currently attached to the test station and
        accessible with the adb command."""
        devices = self._get_devices(use_adb=True)
        if self.adb_serial is None and len(devices) > 1:
            raise error.AutoservError(
                    'Not given ADB serial but multiple devices detected')
        return devices


    def fastboot_devices(self):
        """Get a list of devices currently attached to the test station and
        accessible by fastboot command.
        """
        devices = self._get_devices(use_adb=False)
        if self.fastboot_serial is None and len(devices) > 1:
            raise error.AutoservError(
                    'Not given fastboot serial but multiple devices detected')
        return devices


    def is_up(self, timeout=0, command=ADB_CMD):
        """Determine if the specified adb device is up with expected mode.

        @param timeout: Not currently used.
        @param command: `adb`, the device can be accessed by adb command,
                or `fastboot`, the device can be accessed by fastboot command.
                Default is set to `adb`.

        @returns True if the device is detectable by given command, False
                 otherwise.

        """
        if command == ADB_CMD:
            devices = self.adb_devices()
            serial = self.adb_serial
            # ADB has a device state, if the device is not online, no
            # subsequent ADB command will complete.
            # DUT with single device connected may not have adb_serial set.
            # Therefore, skip checking if serial is in the list of adb devices
            # if self.adb_serial is not set.
            if (serial and serial not in devices) or not self.is_device_ready():
                logging.debug('Waiting for device to enter the ready state.')
                return False
        elif command == FASTBOOT_CMD:
            devices = self.fastboot_devices()
            serial = self.fastboot_serial
        else:
            raise NotImplementedError('Mode %s is not supported' % command)

        return bool(devices and (not serial or serial in devices))


    def stop_loggers(self):
        """Inherited stop_loggers function.

        Calls parent function and captures logcat, since the end of the run
        is logically the end/stop of the logcat log.
        """
        super(ADBHost, self).stop_loggers()

        # When called from atest and tools like it there will be no job.
        if not self.job:
            return

        # Record logcat log to a temporary file on the teststation.
        tmp_dir = self.teststation.get_tmp_dir()
        logcat_filename = LOGCAT_FILE_FMT % self.adb_serial
        teststation_filename = os.path.join(tmp_dir, logcat_filename)
        try:
            self.adb_run('logcat -v time -d > "%s"' % (teststation_filename),
                         timeout=20)
        except (error.GenericHostRunError, error.AutoservSSHTimeout,
                error.CmdTimeoutError):
            return
        # Copy-back the log to the drone's results directory.
        results_logcat_filename = os.path.join(self.job.resultdir,
                                               logcat_filename)
        self.teststation.get_file(teststation_filename,
                                  results_logcat_filename)
        try:
            self.teststation.run('rm -rf %s' % tmp_dir)
        except (error.GenericHostRunError, error.AutoservSSHTimeout) as e:
            logging.warn('failed to remove dir %s: %s', tmp_dir, e)

        self._collect_crash_logs()


    def close(self):
        """Close the ADBHost object.

        Called as the test ends. Will return the device to USB mode and kill
        the ADB server.
        """
        super(ADBHost, self).close()
        self.teststation.close()


    def syslog(self, message, tag='autotest'):
        """Logs a message to syslog on the device.

        @param message String message to log into syslog
        @param tag String tag prefix for syslog

        """
        self.run('log -t "%s" "%s"' % (tag, message))


    def get_autodir(self):
        """Return the directory to install autotest for client side tests."""
        return '/data/autotest'


    def is_device_ready(self):
        """Return the if the device is ready for ADB commands."""
        try:
            # Retry to avoid possible flakes.
            is_ready = client_utils.poll_for_condition(
                lambda: self.adb_run('get-state').stdout.strip() == 'device',
                timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS, sleep_interval=1,
                desc='Waiting for device state to be `device`')
        except client_utils.TimeoutError:
            is_ready = False

        logging.debug('Device state is %sready', '' if is_ready else 'NOT ')
        return is_ready


    def verify_connectivity(self):
        """Verify we can connect to the device."""
        if not self.is_device_ready():
            raise error.AutoservHostError('device state is not in the '
                                          '\'device\' state.')


    def verify_software(self):
        """Verify working software on an adb_host.

        """
        # Check if adb and fastboot are present.
        self.teststation.run('which adb')
        self.teststation.run('which fastboot')
        self.teststation.run('which unzip')

        # Apply checks only for Android device.
        if self.get_os_type() == OS_TYPE_ANDROID:
            # Make sure ro.boot.hardware and ro.build.product match.
            hardware = self._run_output_with_retry('getprop ro.boot.hardware')
            product = self._run_output_with_retry('getprop ro.build.product')
            if hardware != product:
                raise error.AutoservHostError('ro.boot.hardware: %s does not '
                                              'match to ro.build.product: %s' %
                                              (hardware, product))


    def verify_job_repo_url(self, tag=''):
        """Make sure job_repo_url of this host is valid.

        TODO (crbug.com/532223): Actually implement this method.

        @param tag: The tag from the server job, in the format
                    <job_id>-<user>/<hostname>, or <hostless> for a server job.
        """
        return


    def repair(self):
        """Attempt to get the DUT to pass `self.verify()`."""
        try:
            self.ensure_adb_mode(timeout=30)
            return
        except error.AutoservError as e:
            logging.error(e)
        logging.debug('Verifying the device is accessible via fastboot.')
        self.ensure_bootloader_mode()
        if not self.job.run_test(
                'provision_AndroidUpdate', host=self, value=None,
                force=True, repair=True):
            raise error.AutoservRepairTotalFailure(
                    'Unable to repair the device.')


    def send_file(self, source, dest, delete_dest=False,
                  preserve_symlinks=False):
        """Copy files from the drone to the device.

        Just a note, there is the possibility the test station is localhost
        which makes some of these steps redundant (e.g. creating tmp dir) but
        that scenario will undoubtedly be a development scenario (test station
        is also the moblab) and not the typical live test running scenario so
        the redundancy I think is harmless.

        @param source: The file/directory on the drone to send to the device.
        @param dest: The destination path on the device to copy to.
        @param delete_dest: A flag set to choose whether or not to delete
                            dest on the device if it exists.
        @param preserve_symlinks: Controls if symlinks on the source will be
                                  copied as such on the destination or
                                  transformed into the referenced
                                  file/directory.
        """
        # If we need to preserve symlinks, let's check if the source is a
        # symlink itself and if so, just create it on the device.
        if preserve_symlinks:
            symlink_target = None
            try:
                symlink_target = os.readlink(source)
            except OSError:
                # Guess it's not a symlink.
                pass

            if symlink_target is not None:
                # Once we create the symlink, let's get out of here.
                self.run('ln -s %s %s' % (symlink_target, dest))
                return

        # Stage the files on the test station.
        tmp_dir = self.teststation.get_tmp_dir()
        src_path = os.path.join(tmp_dir, os.path.basename(dest))
        # Now copy the file over to the test station so you can reference the
        # file in the push command.
        self.teststation.send_file(source, src_path,
                                   preserve_symlinks=preserve_symlinks)

        if delete_dest:
            self.run('rm -rf %s' % dest)

        self.adb_run('push %s %s' % (src_path, dest))

        # Cleanup the test station.
        try:
            self.teststation.run('rm -rf %s' % tmp_dir)
        except (error.GenericHostRunError, error.AutoservSSHTimeout) as e:
            logging.warn('failed to remove dir %s: %s', tmp_dir, e)


    def _get_file_info(self, dest):
        """Get permission and possible symlink info about file on the device.

        These files are on the device so we only have shell commands (via adb)
        to get the info we want.  We'll use 'ls' to get it all.

        @param dest: File to get info about.

        @returns a dict of the file permissions and symlink.
        """
        # Grab file info.
        file_info = self.run_output('ls -ld %s' % dest)
        symlink = None
        perms = 0
        match = re.match(FILE_INFO_REGEX, file_info)
        if match:
            # Check if it's a symlink and grab the linked dest if it is.
            if match.group('TYPE') == 'l':
                symlink_match = re.match(FILE_SYMLINK_REGEX, file_info)
                if symlink_match:
                    symlink = symlink_match.group('SYMLINK')

            # Set the perms.
            for perm, perm_flag in zip(match.group('PERMS'), FILE_PERMS_FLAGS):
                if perm != '-':
                    perms |= perm_flag

        return {'perms': perms,
                'symlink': symlink}


    def get_file(self, source, dest, delete_dest=False, preserve_perm=True,
                 preserve_symlinks=False):
        """Copy files from the device to the drone.

        Just a note, there is the possibility the test station is localhost
        which makes some of these steps redundant (e.g. creating tmp dir) but
        that scenario will undoubtedly be a development scenario (test station
        is also the moblab) and not the typical live test running scenario so
        the redundancy I think is harmless.

        @param source: The file/directory on the device to copy back to the
                       drone.
        @param dest: The destination path on the drone to copy to.
        @param delete_dest: A flag set to choose whether or not to delete
                            dest on the drone if it exists.
        @param preserve_perm: Tells get_file() to try to preserve the sources
                              permissions on files and dirs.
        @param preserve_symlinks: Try to preserve symlinks instead of
                                  transforming them into files/dirs on copy.
        """
        # Stage the files on the test station under teststation_temp_dir.
        teststation_temp_dir = self.teststation.get_tmp_dir()
        teststation_dest = os.path.join(teststation_temp_dir,
                                        os.path.basename(source))

        source_info = {}
        if preserve_symlinks or preserve_perm:
            source_info = self._get_file_info(source)

        # If we want to preserve symlinks, just create it here, otherwise pull
        # the file off the device.
        #
        # TODO(sadmac): Directories containing symlinks won't behave as
        # expected.
        if preserve_symlinks and source_info['symlink']:
            os.symlink(source_info['symlink'], dest)
        else:
            self.adb_run('pull %s %s' % (source, teststation_temp_dir))

            # Copy over the file from the test station and clean up.
            self.teststation.get_file(teststation_dest, dest,
                                      delete_dest=delete_dest)
            try:
                self.teststation.run('rm -rf %s' % teststation_temp_dir)
            except (error.GenericHostRunError, error.AutoservSSHTimeout) as e:
                logging.warn('failed to remove dir %s: %s',
                             teststation_temp_dir, e)

            # Source will be copied under dest if either:
            #  1. Source is a directory and doesn't end with /.
            #  2. Source is a file and dest is a directory.
            command = '[ -d %s ]' % source
            source_is_dir = self.run(command,
                                     ignore_status=True).exit_status == 0
            logging.debug('%s on the device %s a directory', source,
                          'is' if source_is_dir else 'is not')

            if ((source_is_dir and not source.endswith(os.sep)) or
                (not source_is_dir and os.path.isdir(dest))):
                receive_path = os.path.join(dest, os.path.basename(source))
            else:
                receive_path = dest

            if not os.path.exists(receive_path):
                logging.warning('Expected file %s does not exist; skipping'
                                ' permissions copy', receive_path)
                return

            # Set the permissions of the received file/dirs.
            if os.path.isdir(receive_path):
                for root, _dirs, files in os.walk(receive_path):
                    def process(rel_path, default_perm):
                        info = self._get_file_info(os.path.join(source,
                                                                rel_path))
                        if info['perms'] != 0:
                            target = os.path.join(receive_path, rel_path)
                            if preserve_perm:
                                os.chmod(target, info['perms'])
                            else:
                                os.chmod(target, default_perm)

                    rel_root = os.path.relpath(root, receive_path)
                    process(rel_root, _DEFAULT_DIR_PERMS)
                    for f in files:
                        process(os.path.join(rel_root, f), _DEFAULT_FILE_PERMS)
            elif preserve_perm:
                os.chmod(receive_path, source_info['perms'])
            else:
                os.chmod(receive_path, _DEFAULT_FILE_PERMS)


    def get_release_version(self):
        """Get the release version from the RELEASE_FILE on the device.

        @returns The release string in the RELEASE_FILE.

        """
        return self.run_output('getprop %s' % RELEASE_FILE)


    def get_tmp_dir(self, parent=''):
        """Return a suitable temporary directory on the device.

        We ensure this is a subdirectory of /data/local/tmp.

        @param parent: Parent directory of the returned tmp dir.

        @returns a path to the temp directory on the host.
        """
        # TODO(kevcheng): Refactor the cleanup of tmp dir to be inherited
        #                 from the parent.
        if not parent.startswith(TMP_DIR):
            parent = os.path.join(TMP_DIR, parent.lstrip(os.path.sep))
        self.run('mkdir -p %s' % parent)
        tmp_dir = self.run_output('mktemp -d -p %s' % parent)
        self.tmp_dirs.append(tmp_dir)
        return tmp_dir


    def get_platform(self):
        """Determine the correct platform label for this host.

        @returns a string representing this host's platform.
        """
        return 'adb'


    def get_os_type(self):
        """Get the OS type of the DUT, e.g., android or brillo.
        """
        if not self._os_type:
            if self.run_output('getprop ro.product.brand') == 'Brillo':
                self._os_type = OS_TYPE_BRILLO
            else:
                self._os_type = OS_TYPE_ANDROID

        return self._os_type


    def _forward(self, reverse, args):
        """Execute a forwarding command.

        @param reverse: Whether this is reverse forwarding (Boolean).
        @param args: List of command arguments.
        """
        cmd = '%s %s' % ('reverse' if reverse else 'forward', ' '.join(args))
        self.adb_run(cmd)


    def add_forwarding(self, src, dst, reverse=False, rebind=True):
        """Forward a port between the ADB host and device.

        Port specifications are any strings accepted as such by ADB, for
        example 'tcp:8080'.

        @param src: Port specification to forward from.
        @param dst: Port specification to forward to.
        @param reverse: Do reverse forwarding from device to host (Boolean).
        @param rebind: Allow rebinding an already bound port (Boolean).
        """
        args = []
        if not rebind:
            args.append('--no-rebind')
        args += [src, dst]
        self._forward(reverse, args)


    def remove_forwarding(self, src=None, reverse=False):
        """Removes forwarding on port.

        @param src: Port specification, or None to remove all forwarding.
        @param reverse: Whether this is reverse forwarding (Boolean).
        """
        args = []
        if src is None:
            args.append('--remove-all')
        else:
            args += ['--remove', src]
        self._forward(reverse, args)


    def create_ssh_tunnel(self, port, local_port):
        """
        Forwards a port securely through a tunnel process from the server
        to the DUT for RPC server connection.
        Add a 'ADB forward' rule to forward the RPC packets from the AdbHost
        to the DUT.

        @param port: remote port on the DUT.
        @param local_port: local forwarding port.

        @return: the tunnel process.
        """
        self.add_forwarding('tcp:%s' % port, 'tcp:%s' % port)
        return super(ADBHost, self).create_ssh_tunnel(port, local_port)


    def disconnect_ssh_tunnel(self, tunnel_proc, port):
        """
        Disconnects a previously forwarded port from the server to the DUT for
        RPC server connection.
        Remove the previously added 'ADB forward' rule to forward the RPC
        packets from the AdbHost to the DUT.

        @param tunnel_proc: the original tunnel process returned from
                            |create_ssh_tunnel|.
        @param port: remote port on the DUT.

        """
        self.remove_forwarding('tcp:%s' % port)
        super(ADBHost, self).disconnect_ssh_tunnel(tunnel_proc, port)


    def ensure_bootloader_mode(self):
        """Ensure the device is in bootloader mode.

        @raise: error.AutoservError if the device failed to reboot into
                bootloader mode.
        """
        if self.is_up(command=FASTBOOT_CMD):
            return
        self.adb_run('reboot bootloader')
        if not self.wait_up(command=FASTBOOT_CMD):
            raise error.AutoservError(
                    'The device failed to reboot into bootloader mode.')


    def ensure_adb_mode(self, timeout=DEFAULT_WAIT_UP_TIME_SECONDS):
        """Ensure the device is up and can be accessed by adb command.

        @param timeout: Time limit in seconds before returning even if the host
                        is not up.

        @raise: error.AutoservError if the device failed to reboot into
                adb mode.
        """
        if self.is_up():
            return
        # Ignore timeout error to allow `fastboot reboot` to fail quietly and
        # check if the device is in adb mode.
        self.fastboot_run('reboot', timeout=timeout, ignore_timeout=True)
        if not self.wait_up(timeout=timeout):
            raise error.AutoservError(
                    'The device failed to reboot into adb mode.')
        self._reset_adbd_connection()


    @classmethod
    def get_build_info_from_build_url(cls, build_url):
        """Get the Android build information from the build url.

        @param build_url: The url to use for downloading Android artifacts.
                pattern: http://$devserver:###/static/branch/target/build_id

        @return: A dictionary of build information, including keys:
                 build_target, branch, target, build_id.
        @raise AndroidInstallError: If failed to parse build_url.
        """
        if not build_url:
            raise AndroidInstallError('Need build_url to download image files.')

        try:
            match = re.match(DEVSERVER_URL_REGEX, build_url)
            return {'build_target': match.group('BUILD_TARGET'),
                    'branch': match.group('BRANCH'),
                    'target': ('%s-%s' % (match.group('BUILD_TARGET'),
                                          match.group('BUILD_TYPE'))),
                    'build_id': match.group('BUILD_ID')}
        except (AttributeError, IndexError, ValueError) as e:
            raise AndroidInstallError(
                    'Failed to parse build url: %s\nError: %s' % (build_url, e))


    @retry.retry(error.GenericHostRunError, timeout_min=10)
    def download_file(self, build_url, file, dest_dir, unzip=False,
                      unzip_dest=None):
        """Download the given file from the build url.

        @param build_url: The url to use for downloading Android artifacts.
                pattern: http://$devserver:###/static/branch/target/build_id
        @param file: Name of the file to be downloaded, e.g., boot.img.
        @param dest_dir: Destination folder for the file to be downloaded to.
        @param unzip: If True, unzip the downloaded file.
        @param unzip_dest: Location to unzip the downloaded file to. If not
                           provided, dest_dir is used.
        """
        # Append the file name to the url if build_url is linked to the folder
        # containing the file.
        if not build_url.endswith('/%s' % file):
            src_url = os.path.join(build_url, file)
        else:
            src_url = build_url
        dest_file = os.path.join(dest_dir, file)
        try:
            self.teststation.run('wget -q -O "%s" "%s"' % (dest_file, src_url))
            if unzip:
                unzip_dest = unzip_dest or dest_dir
                self.teststation.run('unzip "%s/%s" -x -d "%s"' %
                                     (dest_dir, file, unzip_dest))
        except:
            # Delete the destination file if download failed.
            self.teststation.run('rm -f "%s"' % dest_file)
            raise


    def stage_android_image_files(self, build_url):
        """Download required image files from the given build_url to a local
        directory in the machine runs fastboot command.

        @param build_url: The url to use for downloading Android artifacts.
                pattern: http://$devserver:###/static/branch/target/build_id

        @return: Path to the directory contains image files.
        """
        build_info = self.get_build_info_from_build_url(build_url)

        zipped_image_file = ANDROID_IMAGE_FILE_FMT % build_info
        image_dir = self.teststation.get_tmp_dir()

        try:
            self.download_file(build_url, zipped_image_file, image_dir,
                               unzip=True)
            images = android_utils.AndroidImageFiles.get_standalone_images(
                    build_info['build_target'])
            for image_file in images:
                self.download_file(build_url, image_file, image_dir)

            return image_dir
        except:
            self.teststation.run('rm -rf %s' % image_dir)
            raise


    def stage_brillo_image_files(self, build_url):
        """Download required brillo image files from the given build_url to a
        local directory in the machine runs fastboot command.

        @param build_url: The url to use for downloading Android artifacts.
                pattern: http://$devserver:###/static/branch/target/build_id

        @return: Path to the directory contains image files.
        """
        build_info = self.get_build_info_from_build_url(build_url)

        zipped_image_file = ANDROID_IMAGE_FILE_FMT % build_info
        vendor_partitions_file = BRILLO_VENDOR_PARTITIONS_FILE_FMT % build_info
        image_dir = self.teststation.get_tmp_dir()

        try:
            self.download_file(build_url, zipped_image_file, image_dir,
                               unzip=True)
            self.download_file(build_url, vendor_partitions_file, image_dir,
                               unzip=True,
                               unzip_dest=os.path.join(image_dir, 'vendor'))
            return image_dir
        except:
            self.teststation.run('rm -rf %s' % image_dir)
            raise


    def stage_build_for_install(self, build_name, os_type=None):
        """Stage a build on a devserver and return the build_url and devserver.

        @param build_name: a name like git-master/shamu-userdebug/2040953

        @returns a tuple with an update URL like:
            http://172.22.50.122:8080/git-master/shamu-userdebug/2040953
            and the devserver instance.
        """
        os_type = os_type or self.get_os_type()
        logging.info('Staging build for installation: %s', build_name)
        devserver = dev_server.AndroidBuildServer.resolve(build_name,
                                                          self.hostname)
        build_name = devserver.translate(build_name)
        branch, target, build_id = utils.parse_launch_control_build(build_name)
        devserver.trigger_download(target, build_id, branch,
                                   os=os_type, synchronous=False)
        return '%s/static/%s' % (devserver.url(), build_name), devserver


    def install_android(self, build_url, build_local_path=None, wipe=True,
                        flash_all=False, disable_package_verification=True,
                        skip_setup_wizard=True):
        """Install the Android DUT.

        Following are the steps used here to provision an android device:
        1. If build_local_path is not set, download the image zip file, e.g.,
           shamu-img-2284311.zip, unzip it.
        2. Run fastboot to install following artifacts:
           bootloader, radio, boot, system, vendor(only if exists)

        Repair is not supported for Android devices yet.

        @param build_url: The url to use for downloading Android artifacts.
                pattern: http://$devserver:###/static/$build
        @param build_local_path: The path to a local folder that contains the
                image files needed to provision the device. Note that the folder
                is in the machine running adb command, rather than the drone.
        @param wipe: If true, userdata will be wiped before flashing.
        @param flash_all: If True, all img files found in img_path will be
                flashed. Otherwise, only boot and system are flashed.

        @raises AndroidInstallError if any error occurs.
        """
        # If the build is not staged in local server yet, clean up the temp
        # folder used to store image files after the provision is completed.
        delete_build_folder = bool(not build_local_path)

        try:
            # Download image files needed for provision to a local directory.
            if not build_local_path:
                build_local_path = self.stage_android_image_files(build_url)

            # Device needs to be in bootloader mode for flashing.
            self.ensure_bootloader_mode()

            if wipe:
                self._fastboot_run_with_retry('-w')

            # Get all *.img file in the build_local_path.
            list_file_cmd = 'ls -d %s' % os.path.join(build_local_path, '*.img')
            image_files = self.teststation.run(
                    list_file_cmd).stdout.strip().split()
            images = dict([(os.path.basename(f), f) for f in image_files])
            build_info = self.get_build_info_from_build_url(build_url)
            board = build_info['build_target']
            all_images = (
                    android_utils.AndroidImageFiles.get_standalone_images(board)
                    + android_utils.AndroidImageFiles.get_zipped_images(board))

            # Sort images to be flashed, bootloader needs to be the first one.
            bootloader = android_utils.AndroidImageFiles.BOOTLOADER
            sorted_images = sorted(
                    images.items(),
                    key=lambda pair: 0 if pair[0] == bootloader else 1)
            for image, image_file in sorted_images:
                if image not in all_images:
                    continue
                logging.info('Flashing %s...', image_file)
                self._fastboot_run_with_retry('-S 256M flash %s %s' %
                                              (image[:-4], image_file))
                if image == android_utils.AndroidImageFiles.BOOTLOADER:
                    self.fastboot_run('reboot-bootloader')
                    self.wait_up(command=FASTBOOT_CMD)
        except Exception as e:
            logging.error('Install Android build failed with error: %s', e)
            # Re-raise the exception with type of AndroidInstallError.
            raise AndroidInstallError, sys.exc_info()[1], sys.exc_info()[2]
        finally:
            if delete_build_folder:
                self.teststation.run('rm -rf %s' % build_local_path)
            timeout = (WAIT_UP_AFTER_WIPE_TIME_SECONDS if wipe else
                       DEFAULT_WAIT_UP_TIME_SECONDS)
            self.ensure_adb_mode(timeout=timeout)
            if disable_package_verification:
                # TODO: Use a whitelist of devices to do this for rather than
                # doing it by default.
                self.disable_package_verification()
            if skip_setup_wizard:
                try:
                    self.skip_setup_wizard()
                except error.GenericHostRunError:
                    logging.error('Could not skip setup wizard.')
        logging.info('Successfully installed Android build staged at %s.',
                     build_url)


    def install_brillo(self, build_url, build_local_path=None):
        """Install the Brillo DUT.

        Following are the steps used here to provision an android device:
        1. If build_local_path is not set, download the image zip file, e.g.,
           dragonboard-img-123456.zip, unzip it. And download the vendor
           partition zip file, e.g., dragonboard-vendor_partitions-123456.zip,
           unzip it to vendor folder.
        2. Run provision_device script to install OS images and vendor
           partitions.

        @param build_url: The url to use for downloading Android artifacts.
                pattern: http://$devserver:###/static/$build
        @param build_local_path: The path to a local folder that contains the
                image files needed to provision the device. Note that the folder
                is in the machine running adb command, rather than the drone.

        @raises AndroidInstallError if any error occurs.
        """
        # If the build is not staged in local server yet, clean up the temp
        # folder used to store image files after the provision is completed.
        delete_build_folder = bool(not build_local_path)

        try:
            # Download image files needed for provision to a local directory.
            if not build_local_path:
                build_local_path = self.stage_brillo_image_files(build_url)

            # Device needs to be in bootloader mode for flashing.
            self.ensure_bootloader_mode()

            # Run provision_device command to install image files and vendor
            # partitions.
            vendor_partition_dir = os.path.join(build_local_path, 'vendor')
            cmd = (BRILLO_PROVISION_CMD %
                   {'os_image_dir': build_local_path,
                    'vendor_partition_dir': vendor_partition_dir})
            if self.fastboot_serial:
                cmd += ' -s %s ' % self.fastboot_serial
            self.teststation.run(cmd)
        except Exception as e:
            logging.error('Install Brillo build failed with error: %s', e)
            # Re-raise the exception with type of AndroidInstallError.
            raise AndroidInstallError, sys.exc_info()[1], sys.exc_info()[2]
        finally:
            if delete_build_folder:
                self.teststation.run('rm -rf %s' % build_local_path)
            self.ensure_adb_mode()
        logging.info('Successfully installed Android build staged at %s.',
                     build_url)


    @property
    def job_repo_url_attribute(self):
        """Get the host attribute name for job_repo_url, which should append the
        adb serial.
        """
        return '%s_%s' % (constants.JOB_REPO_URL, self.adb_serial)


    def machine_install(self, build_url=None, build_local_path=None, wipe=True,
                        flash_all=False, os_type=None):
        """Install the DUT.

        @param build_url: The url to use for downloading Android artifacts.
                pattern: http://$devserver:###/static/$build. If build_url is
                set to None, the code may try _parser.options.image to do the
                installation. If none of them is set, machine_install will fail.
        @param build_local_path: The path to a local directory that contains the
                image files needed to provision the device.
        @param wipe: If true, userdata will be wiped before flashing.
        @param flash_all: If True, all img files found in img_path will be
                flashed. Otherwise, only boot and system are flashed.

        @returns A tuple of (image_name, host_attributes).
                image_name is the name of image installed, e.g.,
                git_mnc-release/shamu-userdebug/1234
                host_attributes is a dictionary of (attribute, value), which
                can be saved to afe_host_attributes table in database. This
                method returns a dictionary with a single entry of
                `job_repo_url_[adb_serial]`: devserver_url, where devserver_url
                is a url to the build staged on devserver.
        """
        os_type = os_type or self.get_os_type()
        if not build_url and self._parser.options.image:
            build_url, _ = self.stage_build_for_install(
                    self._parser.options.image, os_type=os_type)
        if os_type == OS_TYPE_ANDROID:
            self.install_android(
                    build_url=build_url, build_local_path=build_local_path,
                    wipe=wipe, flash_all=flash_all)
        elif os_type == OS_TYPE_BRILLO:
            self.install_brillo(
                    build_url=build_url, build_local_path=build_local_path)
        else:
            raise error.InstallError(
                    'Installation of os type %s is not supported.' %
                    self.get_os_type())
        return (build_url.split('static/')[-1],
                {self.job_repo_url_attribute: build_url})


    def list_files_glob(self, path_glob):
        """Get a list of files on the device given glob pattern path.

        @param path_glob: The path glob that we want to return the list of
                files that match the glob.  Relative paths will not work as
                expected.  Supply an absolute path to get the list of files
                you're hoping for.

        @returns List of files that match the path_glob.
        """
        # This is just in case path_glob has no path separator.
        base_path = os.path.dirname(path_glob) or '.'
        result = self.run('find %s -path \'%s\' -print' %
                          (base_path, path_glob), ignore_status=True)
        if result.exit_status != 0:
            return []
        return result.stdout.splitlines()


    @retry.retry(error.GenericHostRunError,
                 timeout_min=DISABLE_PACKAGE_VERIFICATION_TIMEOUT_MIN)
    def disable_package_verification(self):
        """Disables package verification on an android device.

        Disables the package verificatoin manager allowing any package to be
        installed without checking
        """
        logging.info('Disabling package verification on %s.', self.adb_serial)
        self.check_boot_to_adb_complete()
        self.run('am broadcast -a '
                 'com.google.gservices.intent.action.GSERVICES_OVERRIDE -e '
                 'global:package_verifier_enable 0')


    @retry.retry(error.GenericHostRunError, timeout_min=APK_INSTALL_TIMEOUT_MIN)
    def install_apk(self, apk, force_reinstall=True):
        """Install the specified apk.

        This will install the apk and override it if it's already installed and
        will also allow for downgraded apks.

        @param apk: The path to apk file.
        @param force_reinstall: True to reinstall the apk even if it's already
                installed. Default is set to True.

        @returns a CMDResult object.
        """
        try:
            client_utils.poll_for_condition(
                    lambda: self.run('pm list packages',
                                     ignore_status=True).exit_status == 0,
                    timeout=120)
            client_utils.poll_for_condition(
                    lambda: self.run('service list | grep mount',
                                     ignore_status=True).exit_status == 0,
                    timeout=120)
            return self.adb_run('install %s -d %s' %
                                ('-r' if force_reinstall else '', apk))
        except error.GenericHostRunError:
            self.reboot()
            raise


    def uninstall_package(self, package):
        """Remove the specified package.

        @param package: Android package name.

        @raises GenericHostRunError: uninstall failed
        """
        result = self.adb_run('uninstall %s' % package)

        if self.is_apk_installed(package):
            raise error.GenericHostRunError('Uninstall of "%s" failed.'
                                            % package, result)


    @retry.retry(error.GenericHostRunError, timeout_min=0.2)
    def _confirm_apk_installed(self, package_name):
        """Confirm if apk is already installed with the given name.

        `pm list packages` command is not reliable some time. The retry helps to
        reduce the chance of false negative.

        @param package_name: Name of the package, e.g., com.android.phone.

        @raise AutoservRunError: If the package is not found or pm list command
                failed for any reason.
        """
        name = 'package:%s' % package_name
        self.adb_run('shell pm list packages | grep -w "%s"' % name)


    def is_apk_installed(self, package_name):
        """Check if apk is already installed with the given name.

        @param package_name: Name of the package, e.g., com.android.phone.

        @return: True if package is installed. False otherwise.
        """
        try:
            self._confirm_apk_installed(package_name)
            return True
        except:
            return False

    @retry.retry(error.GenericHostRunError, timeout_min=1)
    def skip_setup_wizard(self):
        """Skip the setup wizard.

        Skip the starting setup wizard that normally shows up on android.
        """
        logging.info('Skipping setup wizard on %s.', self.adb_serial)
        self.check_boot_to_adb_complete()
        self.run('am start -n com.google.android.setupwizard/'
                 '.SetupWizardExitActivity')


    def get_attributes_to_clear_before_provision(self):
        """Get a list of attributes to be cleared before machine_install starts.
        """
        return [self.job_repo_url_attribute]


    def get_labels(self):
        """Return a list of the labels gathered from the devices connected.

        @return: A list of strings that denote the labels from all the devices
                 connected.
        """
        return self.labels.get_labels(self)


    def update_labels(self):
        """Update the labels for this testbed."""
        self.labels.update_labels(self)


    def stage_server_side_package(self, image=None):
        """Stage autotest server-side package on devserver.

        @param image: A build name, e.g., git_mnc_dev/shamu-eng/123

        @return: A url to the autotest server-side package.

        @raise: error.AutoservError if fail to locate the build to test with, or
                fail to stage server-side package.
        """
        # If enable_drone_in_restricted_subnet is False, do not set hostname
        # in devserver.resolve call, so a devserver in non-restricted subnet
        # is picked to stage autotest server package for drone to download.
        hostname = self.hostname
        if not utils.ENABLE_DRONE_IN_RESTRICTED_SUBNET:
            hostname = None
        if image:
            ds = dev_server.AndroidBuildServer.resolve(image, hostname)
        else:
            job_repo_url = afe_utils.get_host_attribute(
                    self, self.job_repo_url_attribute)
            if job_repo_url:
                devserver_url, image = (
                        tools.get_devserver_build_from_package_url(
                                job_repo_url, True))
                # If enable_drone_in_restricted_subnet is True, use the
                # existing devserver. Otherwise, resolve a new one in
                # non-restricted subnet.
                if utils.ENABLE_DRONE_IN_RESTRICTED_SUBNET:
                    ds = dev_server.AndroidBuildServer(devserver_url)
                else:
                    ds = dev_server.AndroidBuildServer.resolve(image)
            else:
                labels = afe_utils.get_labels(self, self.VERSION_PREFIX)
                if not labels:
                    raise error.AutoservError(
                            'Failed to stage server-side package. The host has '
                            'no job_report_url attribute or version label.')
                image = labels[0][len(self.VERSION_PREFIX + ':'):]
                ds = dev_server.AndroidBuildServer.resolve(image, hostname)

        branch, target, build_id = utils.parse_launch_control_build(image)
        build_target, _ = utils.parse_launch_control_target(target)

        # For any build older than MIN_VERSION_SUPPORT_SSP, server side
        # packaging is not supported.
        try:
            # Some build ids may have special character before the actual
            # number, skip such characters.
            actual_build_id = build_id
            if build_id.startswith('P'):
                actual_build_id = build_id[1:]
            if int(actual_build_id) < self.MIN_VERSION_SUPPORT_SSP:
                raise error.AutoservError(
                        'Build %s is older than %s. Server side packaging is '
                        'disabled.' % (image, self.MIN_VERSION_SUPPORT_SSP))
        except ValueError:
            raise error.AutoservError(
                    'Failed to compare build id in %s with the minimum '
                    'version that supports server side packaging. Server '
                    'side packaging is disabled.' % image)

        ds.stage_artifacts(target, build_id, branch,
                           artifacts=['autotest_server_package'])
        autotest_server_package_name = (AUTOTEST_SERVER_PACKAGE_FILE_FMT %
                                        {'build_target': build_target,
                                         'build_id': build_id})
        return '%s/static/%s/%s' % (ds.url(), image,
                                    autotest_server_package_name)


    def _sync_time(self):
        """Approximate synchronization of time between host and ADB device.

        This sets the ADB/Android device's clock to approximately the same
        time as the Autotest host for the purposes of comparing Android system
        logs such as logcat to logs from the Autotest host system.
        """
        command = 'date '
        sdk_version = int(self.run('getprop %s' % SDK_FILE).stdout)
        if sdk_version < 23:
            # Android L and earlier use this format: date -s (format).
            command += ('-s %s' %
                        datetime.datetime.now().strftime('%Y%m%d.%H%M%S'))
        else:
            # Android M and later use this format: date -u (format).
            command += ('-u %s' %
                        datetime.datetime.utcnow().strftime('%m%d%H%M%Y.%S'))
        self.run(command, timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
                 ignore_timeout=True)


    def _enable_native_crash_logging(self):
        """Enable native (non-Java) crash logging.
        """
        if self.get_os_type() == OS_TYPE_ANDROID:
            self._enable_android_native_crash_logging()


    def _enable_brillo_native_crash_logging(self):
        """Enables native crash logging for a Brillo DUT.
        """
        try:
            self.run('touch /data/misc/metrics/enabled',
                     timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
                     ignore_timeout=True)
            # If running, crash_sender will delete crash files every hour.
            self.run('stop crash_sender',
                     timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
                     ignore_timeout=True)
        except error.GenericHostRunError as e:
            logging.warn(e)
            logging.warn('Failed to enable Brillo native crash logging.')


    def _enable_android_native_crash_logging(self):
        """Enables native crash logging for an Android DUT.
        """
        # debuggerd should be enabled by default on Android.
        result = self.run('pgrep debuggerd',
                          timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
                          ignore_timeout=True, ignore_status=True)
        if not result or result.exit_status != 0:
            logging.debug('Unable to confirm that debuggerd is running.')


    def _collect_crash_logs(self):
        """Copies crash log files from the DUT to the drone.
        """
        if self.get_os_type() == OS_TYPE_BRILLO:
            self._collect_crash_logs_dut(BRILLO_NATIVE_CRASH_LOG_DIR)
        elif self.get_os_type() == OS_TYPE_ANDROID:
            self._collect_crash_logs_dut(ANDROID_TOMBSTONE_CRASH_LOG_DIR)


    def _collect_crash_logs_dut(self, log_directory):
        """Copies native crash logs from the Android/Brillo DUT to the drone.

        @param log_directory: absolute path of the directory on the DUT where
                log files are stored.
        """
        files = None
        try:
            result = self.run('find %s -maxdepth 1 -type f' % log_directory,
                              timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS)
            files = result.stdout.strip().split()
        except (error.GenericHostRunError, error.AutoservSSHTimeout,
                error.CmdTimeoutError):
            logging.debug('Unable to call find %s, unable to find crash logs',
                          log_directory)
        if not files:
            logging.debug('There are no crash logs on the DUT.')
            return

        crash_dir = os.path.join(self.job.resultdir, 'crash')
        try:
            os.mkdir(crash_dir)
        except OSError as e:
            if e.errno != errno.EEXIST:
                raise e

        for f in files:
            logging.debug('DUT native crash file produced: %s', f)
            dest = os.path.join(crash_dir, os.path.basename(f))
            # We've had cases where the crash file on the DUT has permissions
            # "000". Let's override permissions to make them sane for the user
            # collecting the crashes.
            self.get_file(source=f, dest=dest, preserve_perm=False)
