# Lint as: python2, python3
# Copyright 2016 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.

"""Server side bluetooth adapter subtests."""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

from datetime import datetime, timedelta
import errno
import functools
import six.moves.http_client
import inspect
import logging
import multiprocessing
import os
import re
import socket
import threading
import time

import common
from autotest_lib.client.bin import utils
from autotest_lib.client.bin.input import input_event_recorder as recorder
from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib.cros.bluetooth import bluetooth_socket
from autotest_lib.client.cros.chameleon import chameleon
from autotest_lib.server.cros.bluetooth import bluetooth_peer_update
from autotest_lib.server.cros.bluetooth import bluetooth_test_utils
from autotest_lib.server import test

from autotest_lib.client.bin.input.linux_input import (
        BTN_LEFT, BTN_RIGHT, EV_KEY, EV_REL, REL_X, REL_Y, REL_WHEEL,
        REL_WHEEL_HI_RES, KEY_PLAYCD, KEY_PAUSECD, KEY_STOPCD, KEY_NEXTSONG,
        KEY_PREVIOUSSONG)
from autotest_lib.server.cros.bluetooth.bluetooth_gatt_client_utils import (
        GATT_ClientFacade, GATT_Application, GATT_HIDApplication)
from autotest_lib.server.cros.multimedia import remote_facade_factory
import six
from six.moves import map
from six.moves import range
from six.moves import zip


Event = recorder.Event

CHIPSET_TO_VIDPID = { 'BRCM-4354':[('0x002d','0x4354')],
                      'MVL-8897':[('0x02df','0x912d')],
                      'MVL-8997':[('0x1b4b','0x2b42')],
                      'QCA-9462': [('0x168c', '0x0034')],
                      'QCA-6174A-5':[('0x168c','0x003e')],
                      'QCA-6174A-3':[('0x271','0x050a')],   # UART
                      'Intel-AX200':[('0x8086', '0x2723')], # CcP2
                      'Intel-AX201':[('0x8086','0x02f0')],  # HrP2
                      'Intel-AC9260':[('0x8086','0x2526')], # ThP2
                      'Intel-AC9560':[('0x8086','0x31dc'),  # JfP2
                                      ('0x8086','0x9df0')],
                      'Intel-AC7260':[('0x8086','0x08b1'),  # WP2
                                      ('0x8086','0x08b2')],
                      'Intel-AC7265':[('0x8086','0x095a'),  # StP2
                                      ('0x8086','0x095b')],
                      'Realtek-RTL8822C-USB':[('0x10ec','0xc822')] }

# We have a number of chipsets that are no longer supported. Known issues
# related to firmware will be ignored on these devices (b/169328792).
UNSUPPORTED_CHIPSETS = [
        'BRCM-4354', 'MVL-8897', 'MVL-8997', 'Intel-AC7260', 'Intel-AC7265'
]

# Location of data traces relative to this (bluetooth_adapter_tests.py) file
BT_ADAPTER_TEST_PATH = os.path.dirname(__file__)
TRACE_LOCATION = os.path.join(BT_ADAPTER_TEST_PATH, 'input_traces/keyboard')

RESUME_DELTA = -5

# Delay binding the methods since host is only available at run time.
SUPPORTED_DEVICE_TYPES = {
    'MOUSE': lambda btpeer: btpeer.get_bluetooth_hid_mouse,
    'KEYBOARD': lambda btpeer: btpeer.get_bluetooth_hid_keyboard,
    'BLE_MOUSE': lambda btpeer: btpeer.get_ble_mouse,
    'BLE_KEYBOARD': lambda btpeer: btpeer.get_ble_keyboard,
    # Tester allows us to test DUT's discoverability, etc. from a peer
    'BLUETOOTH_TESTER': lambda btpeer: btpeer.get_bluetooth_tester,
    # This is a base object that does not emulate any Bluetooth device.
    # This object is preferred when only a pure XMLRPC server is needed
    # on the btpeer host, e.g., to perform servod methods.
    'BLUETOOTH_BASE': lambda btpeer: btpeer.get_bluetooth_base,
    # on the chameleon host, e.g., to perform servod methods.
    'BLUETOOTH_BASE': lambda chameleon: chameleon.get_bluetooth_base,
    # A phone device that supports Bluetooth
    'BLE_PHONE': lambda chameleon: chameleon.get_ble_phone,
    # A Bluetooth audio device emulating a headphone
    'BLUETOOTH_AUDIO': lambda chameleon: chameleon.get_bluetooth_audio,
}

COMMON_FAILURES = {
        'Freeing adapter /org/bluez/hci': 'adapter_freed',
        '/var/spool/crash/bluetoothd': 'bluetoothd_crashed',
}

# TODO(b/150898182) - Don't run some tests on tablet form factors
# This list was generated by looking for tablet models on Goldeneye and removing
# the ones that were not launched
TABLET_MODELS = ['kakadu', 'kodama', 'krane', 'dru', 'druwl', 'dumo']

# TODO(b/161005264) - Some tests rely on software rotation to pass, so we must
# know which models don't use software rotation. Use a static list until we can
# query the bluez API instead. Extended advertising is supported on platforms
# on 4.19 and 5.4, with HrP2, JfP2, CcP2, RTL8822C, or QCN3991 chipsets.
EXT_ADV_MODELS = ['ezkinil', 'trembyle', 'drawcia', 'drawlat', 'drawman',
                  'maglia', 'magolor', 'sarien', 'arcada', 'akemi',
                  'drallion', 'drallion360', 'hatch', 'stryke', 'helios',
                  'dragonair', 'dratini', 'duffy', 'jinlon', 'kaisa',
                  'kindred', 'kled', 'puff', 'kohaku', 'nightfury', 'morphius',
                  'lazor', 'trogdor']

# TODO(b/158336394) Realtek: Powers down during suspend due to high power usage
#                            during S3.
# TODO(b/168152910) Marvell: Powers down during suspend due to flakiness when
#                            entering suspend.  This will also skip the tests
#                            for Veyron (which don't power down right now) but
#                            reconnect tests are still enabled for that platform
#                            to check for suspend stability.
SUSPEND_POWER_DOWN_CHIPSETS = ['Realtek-RTL8822C-USB', 'MVL-8897', 'MVL-8997']


def method_name():
    """Get the method name of a class.

    This function is supposed to be invoked inside a class and will
    return current method name who invokes this function.

    @returns: the string of the method name inside the class.
    """
    return inspect.getouterframes(inspect.currentframe())[1][3]


def _run_method(method, method_name, *args, **kwargs):
    """Run a target method and capture exceptions if any.

    This is just a wrapper of the target method so that we do not need to
    write the exception capturing structure repeatedly. The method could
    be either a device method or a facade method.

    @param method: the method to run
    @param method_name: the name of the method

    @returns: the return value of target method() if successful.
              False otherwise.

    """
    result = False
    try:
        result = method(*args, **kwargs)
    except Exception as e:
        logging.error('%s: %s', method_name, e)
    except:
        logging.error('%s: unexpected error', method_name)
    return result


def get_bluetooth_emulated_device(btpeer, device_type):
    """Get the bluetooth emulated device object.

    @param btpeer: the Bluetooth peer device
    @param device_type : the bluetooth device type, e.g., 'MOUSE'

    @returns: the bluetooth device object

    """

    def _retry_device_method(method_name, legal_falsy_values=[]):
        """retry the emulated device's method.

        The method is invoked as device.xxxx() e.g., device.GetAdvertisedName().

        Note that the method name string is provided to get the device's actual
        method object at run time through getattr(). The rebinding is required
        because a new device may have been created previously or during the
        execution of fix_serial_device().

        Given a device's method, it is not feasible to get the method name
        through __name__ attribute. This limitation is due to the fact that
        the device is a dotted object of an XML RPC server proxy.
        As an example, with the method name 'GetAdvertisedName', we could
        derive the correspoinding method device.GetAdvertisedName. On the
        contrary, given device.GetAdvertisedName, it is not feasible to get the
        method name by device.GetAdvertisedName.__name__

        Also note that if the device method fails, we would try remediation
        step and retry the device method. The remediation steps are
         1) re-creating the serial device.
         2) reset (powercycle) the bluetooth dongle.
         3) reboot Bluetooth peer.
        If the device method still fails after these steps, we fail the test

        The default values exist for uses of this function before the options
        were added, ideally we should change zero_ok to False.

        @param method_name: the string of the method name.
        @param legal_falsy_values: Values that are falsy but might be OK.

        @returns: the result returned by the device's method if the call was
                  successful

        @raises: TestError if the devices's method fails or if repair of
                 peripheral kit fails

        """

        action_table = [('recreate' , 'Fixing the serial device'),
                        ('reset', 'Power cycle the peer device'),
                        ('reboot', 'Reboot the chamleond host')]

        for i, (action, description) in enumerate(action_table):
            logging.info('Attempt %s : %s ', i+1, method_name)

            result = _run_method(getattr(device, method_name), method_name)
            if _is_successful(result, legal_falsy_values):
                return result

            logging.error('%s failed the %s time. Attempting to %s',
                          method_name,i,description)
            if not fix_serial_device(btpeer, device, action):
                logging.info('%s failed', description)
            else:
                logging.info('%s successful', description)

        #try it last time after fix it by last action
        result = _run_method(getattr(device, method_name), method_name)
        if _is_successful(result, legal_falsy_values):
            return result

        raise error.TestError('Failed to execute %s. Bluetooth peer device is'
                              'not working' % method_name)


    if device_type not in SUPPORTED_DEVICE_TYPES:
        raise error.TestError('The device type is not supported: %s',
                              device_type)

    # Get the bluetooth device object and query some important properties.
    device = SUPPORTED_DEVICE_TYPES[device_type](btpeer)()

    # Get some properties of the kit
    # NOTE: Strings updated here must be kept in sync with Btpeer.
    device._capabilities = _retry_device_method('GetCapabilities')
    device._transports = device._capabilities["CAP_TRANSPORTS"]
    device._is_le_only = ("TRANSPORT_LE" in device._transports and
                          len(device._transports) == 1)
    device._has_pin = device._capabilities["CAP_HAS_PIN"]
    device.can_init_connection = device._capabilities["CAP_INIT_CONNECT"]

    _retry_device_method('Init')
    logging.info('device type: %s', device_type)

    device.name = _retry_device_method('GetAdvertisedName')
    logging.info('device name: %s', device.name)

    device.address = _retry_device_method('GetLocalBluetoothAddress')
    logging.info('address: %s', device.address)

    pin_falsy_values = [] if device._has_pin else [None]
    device.pin = _retry_device_method('GetPinCode', pin_falsy_values)
    logging.info('pin: %s', device.pin)

    class_falsy_values = [None] if device._is_le_only else [0]

    # Class of service is None for LE-only devices. Don't fail or parse it.
    device.class_of_service = _retry_device_method('GetClassOfService',
                                                   class_falsy_values)
    if device._is_le_only:
        parsed_class_of_service = device.class_of_service
    else:
        parsed_class_of_service = "0x%04X" % device.class_of_service
    logging.info('class of service: %s', parsed_class_of_service)

    device.class_of_device = _retry_device_method('GetClassOfDevice',
                                                  class_falsy_values)
    # Class of device is None for LE-only devices. Don't fail or parse it.
    if device._is_le_only:
        parsed_class_of_device = device.class_of_device
    else:
        parsed_class_of_device = "0x%04X" % device.class_of_device
    logging.info('class of device: %s', parsed_class_of_device)

    device.device_type = _retry_device_method('GetDeviceType')
    logging.info('device type: %s', device.device_type)

    device.authentication_mode = None
    if not device._is_le_only:
        device.authentication_mode = _retry_device_method('GetAuthenticationMode')
        logging.info('authentication mode: %s', device.authentication_mode)

    device.port = _retry_device_method('GetPort')
    logging.info('serial port: %s\n', device.port)

    return device


def recreate_serial_device(device):
    """Create and connect to a new serial device.

    @param device: the bluetooth HID device

    @returns: True if the serial device is re-created successfully.

    """
    logging.info('Remove the old serial device and create a new one.')
    if device is not None:
        try:
            device.Close()
        except:
            logging.error('failed to close the serial device.')
            return False
    try:
        device.CreateSerialDevice()
        return True
    except:
        logging.error('failed to invoke CreateSerialDevice.')
        return False


def _check_device_init(device, operation):
    # Check if the serial device could initialize, connect, and
    # enter command mode correctly.
    logging.info('Checking device status...')
    if not _run_method(device.Init, 'Init'):
        logging.info('device.Init: failed after %s', operation)
        return False
    if not device.CheckSerialConnection():
        logging.info('device.CheckSerialConnection: failed after %s', operation)
        return False
    if not _run_method(device.EnterCommandMode, 'EnterCommandMode'):
        logging.info('device.EnterCommandMode: failed after %s', operation)
        return False
    logging.info('The device is created successfully after %s.', operation)
    return True

def _reboot_btpeer(btpeer, device):
    """ Reboot Bluetooth peer device.

    Also power cycle the device since reboot may not do that.."""

    # Chameleond fizz hosts should have write protect removed and
    # set_gbb_flags set to 0 to minimize boot time
    REBOOT_SLEEP_SECS = 10
    RESET_SLEEP_SECS = 1

    # Close the bluetooth peripheral device and reboot the chameleon board.
    device.Close()
    logging.info("Powercycling the device")
    device.PowerCycle()
    time.sleep(RESET_SLEEP_SECS)
    logging.info('rebooting Bluetooth peer...')
    btpeer.reboot()

    # Every btpeer reboot would take a bit more than REBOOT_SLEEP_SECS.
    # Sleep REBOOT_SLEEP_SECS and then begin probing the btpeer board.
    time.sleep(REBOOT_SLEEP_SECS)
    return _check_device_init(device, 'reboot')

def _reset_device_power(device):
    """Power cycle the device."""
    RESET_SLEEP_SECS = 1
    try:
        if not device.PowerCycle():
            logging.info('device.PowerCycle() failed')
            return False
    except:
        logging.error('exception in device.PowerCycle')
    else:
        logging.info('device powercycled')
    time.sleep(RESET_SLEEP_SECS)
    return _check_device_init(device, 'reset')

def _is_successful(result, legal_falsy_values=[]):
    """Is the method result considered successful?

    Some method results, for example that of class_of_service, may be 0 which is
    considered a valid result. Occassionally, None is acceptable.

    The default values exist for uses of this function before the options were
    added, ideally we should change zero_ok to False.

    @param result: a method result
    @param legal_falsy_values: Values that are falsy but might be OK.

    @returns: True if bool(result) is True, or if result is 0 and zero_ok, or if
              result is None and none_ok.
    """
    truthiness_of_result = bool(result)
    return truthiness_of_result or result in legal_falsy_values


def _flag_common_failures(instance):
    """Checks if a common failure has occurred during the test run

    Scans system logs for known signs of failure. If a failure is discovered,
    it is added to the test results, to make it easier to identify common root
    causes from Stainless
    """

    for fail_tag, fail_log in COMMON_FAILURES.items():
        if instance.bluetooth_facade.messages_find(fail_tag):
            logging.error('Detected failure tag: %s', fail_tag)
            # We mark this instance's results with the discovered failure
            if type(instance.results) is dict:
                instance.results[fail_log] = True


def fix_serial_device(btpeer, device, operation='reset'):
    """Fix the serial device.

    This function tries to fix the serial device by
    (1) re-creating a serial device, or
    (2) power cycling the usb port to which device is connected
    (3) rebooting the Bluetooth peeer

    Argument operation determine which of the steps above are perform

    Note that rebooting the btpeer board or resetting the device will remove
    the state on the peripheral which might cause test failures. Please use
    reset/reboot only before or after a test.

    @param btpeer: the Bluetooth peer
    @param device: the bluetooth device.
    @param operation: Recovery operation to perform 'recreate/reset/reboot'

    @returns: True if the serial device is fixed. False otherwise.

    """

    if operation == 'recreate':
        # Check the serial connection. Fix it if needed.
        if device.CheckSerialConnection():
            # The USB serial connection still exists.
            # Re-connection suffices to solve the problem. The problem
            # is usually caused by serial port change. For example,
            # the serial port changed from /dev/ttyUSB0 to /dev/ttyUSB1.
            logging.info('retry: creating a new serial device...')
            return recreate_serial_device(device)
        else:
            # Recreate the bluetooth peer device
            return _check_device_init(device, operation)

    elif operation == 'reset':
        # Powercycle the USB port where the bluetooth peer device is connected.
        # RN-42 and RN-52 share the same vid:pid so both will be powercycled.
        # This will only work on fizz host with write protection removed.
        # Note that the state on the device will be lost.
        return _reset_device_power(device)

    elif operation == 'reboot':
        # Reboot the Bluetooth peer device.
        # The device is power cycled before rebooting Bluetooth peer device
        return _reboot_btpeer(btpeer, device)

    else:
        logging.error('fix_serial_device Invalid operation %s', operation)
        return False


def retry(test_method, instance, *args, **kwargs):
    """Execute the target facade test_method(). Retry if failing the first time.

    A test_method is something like self.test_xxxx() in BluetoothAdapterTests,
    e.g., BluetoothAdapterTests.test_bluetoothd_running().

    @param test_method: the test method to retry

    @returns: True if the return value of test_method() is successful.
              False otherwise.

    """
    if _is_successful(_run_method(test_method, test_method.__name__,
                                  instance, *args, **kwargs)):
        return True

    # Try to fix the serial device if applicable.
    logging.error('%s failed at the 1st time: (%s)', test_method.__name__,
                  str(instance.results))

    # If this test does not use any attached serial device, just re-run
    # the test.
    logging.info('%s: retry the 2nd time.', test_method.__name__)
    time.sleep(1)


    if not hasattr(instance, 'use_btpeer'):
        return _is_successful(_run_method(test_method, test_method.__name__,
                                          instance, *args, **kwargs))
    for device_type in SUPPORTED_DEVICE_TYPES:
        for device in getattr(instance, 'devices')[device_type]:
            #fix_serial_device in 'recreate' mode doesn't require btpeer
            #so just pass None for convenient.
            if not fix_serial_device(None, device, "recreate"):
                return False

    logging.info('%s: retry the 2nd time.', test_method.__name__)
    return _is_successful(_run_method(test_method, test_method.__name__,
                                      instance, *args, **kwargs))


def test_retry_and_log(test_method_or_retry_flag,
                       messages_start=True,
                       messages_stop=True):
    """A decorator that logs test results, collects error messages, and retries
       on request.

    @param test_method_or_retry_flag: either the test_method or a retry_flag.
        There are some possibilities of this argument:
        1. the test_method to conduct and retry: should retry the test_method.
            This occurs with
            @test_retry_and_log
        2. the retry flag is True. Should retry the test_method.
            This occurs with
            @test_retry_and_log(True)
        3. the retry flag is False. Do not retry the test_method.
            This occurs with
            @test_retry_and_log(False)

    @param messages_start: Start collecting messages before running the test
    @param messages_stop: Stop collecting messages after running the test and
                          analyze the results.

    @returns: a wrapper of the test_method with test log. The retry mechanism
        would depend on the retry flag.

    """

    def decorator(test_method):
        """A decorator wrapper of the decorated test_method.

        @param test_method: the test method being decorated.

        @returns the wrapper of the test method.

        """
        @functools.wraps(test_method)
        def wrapper(instance, *args, **kwargs):
            """A wrapper of the decorated method.

            @param instance: an BluetoothAdapterTests instance

            @returns the result of the test method

            """
            instance.results = None
            fail_msg = None
            test_result = False
            should_raise = hasattr(instance, 'fail_fast') and instance.fail_fast

            instance.last_test_method = test_method.__name__
            syslog_captured = False

            try:
                if messages_start:
                    # Grab /var/log/messages output during test run
                    instance.bluetooth_facade.messages_start()

                if callable(test_method_or_retry_flag
                            ) or test_method_or_retry_flag:
                    test_result = retry(test_method, instance, *args, **kwargs)
                else:
                    test_result = test_method(instance, *args, **kwargs)

                if messages_stop:
                    syslog_captured = instance.bluetooth_facade.messages_stop()

                if test_result:
                    logging.info('[*** passed: {}]'.format(
                            test_method.__name__))
                else:
                    if syslog_captured:
                        _flag_common_failures(instance)
                    fail_msg = '[--- failed: {} ({})]'.format(
                            test_method.__name__, str(instance.results))
                    logging.error(fail_msg)
                    instance.fails.append(fail_msg)
            # Log TestError and TestNA and let the quicktest wrapper catch it.
            # Those errors should skip out of the testcase entirely.
            except error.TestNAError as e:
                fail_msg = '[--- TESTNA {} ({})]'.format(
                        test_method.__name__, str(e))
                logging.error(fail_msg)
                raise
            except error.TestError as e:
                fail_msg = '[--- ERROR {} ({})]'.format(
                        test_method.__name__, str(e))
                logging.error(fail_msg)
                raise
            except error.TestFail as e:
                fail_msg = '[--- failed {} ({})]'.format(
                        test_method.__name__, str(e))
                logging.error(fail_msg)
                instance.fails.append(fail_msg)
                should_raise = True

            # Check whether we should fail fast
            if fail_msg and should_raise:
                logging.info('Fail fast')
                raise error.TestFail(instance.fails)

            return test_result

        return wrapper

    if callable(test_method_or_retry_flag):
        # If the decorator function comes with no argument like
        # @test_retry_and_log
        return decorator(test_method_or_retry_flag)
    else:
        # If the decorator function comes with an argument like
        # @test_retry_and_log(False)
        return decorator


def test_case_log(method):
    """A decorator for test case methods.

    The main purpose of this decorator is to display the test case name
    in the test log which looks like

        <... test_case_RA3_CD_SI200_CD_PC_CD_UA3 ...>

    @param method: the test case method to decorate.

    @returns: a wrapper function of the decorated method.

    """
    @functools.wraps(method)
    def wrapper(instance, *args, **kwargs):
        """Log the name of the wrapped method before execution"""
        logging.info('\n<... %s ...>', method.__name__)
        method(instance, *args, **kwargs)
    return wrapper


class BluetoothAdapterTests(test.test):
    """Server side bluetooth adapter tests.

    This test class tries to thoroughly verify most of the important work
    states of a bluetooth adapter.

    The various test methods are supposed to be invoked by actual autotest
    tests such as server/cros/site_tests/bluetooth_Adapter*.

    """
    version = 1
    ADAPTER_ACTION_SLEEP_SECS = 1
    ADAPTER_PAIRING_TIMEOUT_SECS = 60
    ADAPTER_CONNECTION_TIMEOUT_SECS = 30
    # Wait after connect for input device to be ready for use
    ADAPTER_HID_INPUT_DELAY = 5
    ADAPTER_DISCONNECTION_TIMEOUT_SECS = 30
    ADAPTER_PAIRING_POLLING_SLEEP_SECS = 3
    ADAPTER_DISCOVER_TIMEOUT_SECS = 60          # 30 seconds too short sometimes
    ADAPTER_DISCOVER_POLLING_SLEEP_SECS = 1
    ADAPTER_DISCOVER_NAME_TIMEOUT_SECS = 30
    ADAPTER_WAKE_ENABLE_TIMEOUT_SECS = 30

    ADAPTER_WAIT_DEFAULT_TIMEOUT_SECS = 10
    ADAPTER_POLLING_DEFAULT_SLEEP_SECS = 1

    HID_REPORT_SLEEP_SECS = 1


    DEFAULT_START_DELAY_SECS = 0
    DEFAULT_HOLD_INTERVAL_SECS = 10
    DEFAULT_HOLD_TIMEOUT_SECS = 60
    DEFAULT_HOLD_SLEEP_SECS = 1

    # Default suspend time in seconds for suspend resume.
    SUSPEND_TIME_SECS=10
    SUSPEND_ENTER_SECS=10
    RESUME_TIME_SECS=30
    RESUME_INTERNAL_TIMEOUT_SECS = 180

    # Minimum RSSI required for peer devices during testing
    MIN_RSSI = -70

    # hci0 is the default hci device if there is no external bluetooth dongle.
    EXPECTED_HCI = 'hci0'

    CLASS_OF_SERVICE_MASK = 0xFFE000
    CLASS_OF_DEVICE_MASK = 0x001FFF

    # Constants about advertising.
    DAFAULT_MIN_ADVERTISEMENT_INTERVAL_MS = 181.25
    DAFAULT_MAX_ADVERTISEMENT_INTERVAL_MS = 181.25
    ADVERTISING_INTERVAL_UNIT = 0.625

    # Error messages about advertising dbus methods.
    ERROR_FAILED_TO_REGISTER_ADVERTISEMENT = (
            'org.bluez.Error.NotPermitted: Maximum advertisements reached')
    ERROR_INVALID_ADVERTISING_INTERVALS = (
            'org.bluez.Error.InvalidArguments: Invalid arguments')

    # Supported profiles by chrome os.
    SUPPORTED_UUIDS = {
            'GATT_UUID': '00001801-0000-1000-8000-00805f9b34fb',
            'A2DP_SOURCE_UUID': '0000110a-0000-1000-8000-00805f9b34fb',
            'HFP_AG_UUID': '0000111f-0000-1000-8000-00805f9b34fb',
            'PNP_UUID': '00001200-0000-1000-8000-00805f9b34fb',
            'GAP_UUID': '00001800-0000-1000-8000-00805f9b34fb'}

    # Board list for name/ID test check. These devices don't need to be tested
    REFERENCE_BOARDS = [
            'rambi', 'nyan', 'oak', 'reef', 'yorp', 'bip', 'volteer',
            'volteer2'
    ]

    # Path for btmon logs
    BTMON_DIR_LOG_PATH = '/var/log/btmon'

    # Path for usbmon logs
    USBMON_DIR_LOG_PATH = '/var/log/usbmon'

    # The agent capability of various device types.
    AGENT_CAPABILITY = {
            'BLUETOOTH_AUDIO': 'NoInputNoOutput',
    }

    def assert_on_fail(self, result, raiseNA=False):
        """ If the called function returns a false-like value, raise an error.

        Call test methods (i.e. with @test_retry_and_log) wrapped with this
        function and failures will raise instead of continuing the test.

        For example:
            self.assert_on_fail(self.test_pairing(...))

        @param result: Result of test method called.
        @param raiseNA: Whether to raise TestNAError instead of TestFail

        @raises error.TestNAError
        @raises error.TestFail
        """
        if not result:
            failure_msg = 'Assert on fail: {}'.format(self.last_test_method)
            logging.error(failure_msg)
            if raiseNA:
                raise error.TestNAError(failure_msg)
            else:
                raise error.TestFail(failure_msg)


    # TODO(b/131170539) remove when sarien/arcada no longer have _signed
    # postfix
    def get_base_platform_name(self):
        """Returns the DUT platform name

        If the DUT is a DVT device, _signed or _unsigned may be appended
            to the device name, which we should ignore in our BT tests

        @returns: String name of the DUT's platform with _signed or
                _unsigned removed
        """

        platform = self.host.get_platform()

        return platform.replace('_signed', '').replace('_unsigned', '')


    def group_btpeers_type(self):
        """Group all Bluetooth peers by the type of their detected device."""

        # Use previously created btpeer_group instead of creating new
        if len(self.btpeer_group_copy) > 0:
            logging.info('Using previously created btpeer group')
            for device_type in SUPPORTED_DEVICE_TYPES:
                self.btpeer_group[device_type] = \
                    self.btpeer_group_copy[device_type][:]
            return

        # Create new btpeer_group
        for device_type in SUPPORTED_DEVICE_TYPES:
            self.btpeer_group[device_type] = list()
            # Create copy of btpeer_group
            self.btpeer_group_copy[device_type] = list()

        for idx, btpeer in enumerate(self.host.btpeer_list):
            for device_type,gen_device_func in SUPPORTED_DEVICE_TYPES.items():
                try:
                    device = gen_device_func(btpeer)()
                    if device.CheckSerialConnection():
                        self.btpeer_group[device_type].append(btpeer)
                        logging.info('%d-th btpeer find device %s', \
                                     idx, device_type)
                        # Create copy of btpeer_group
                        self.btpeer_group_copy[device_type].append(btpeer)
                except:
                    logging.debug('Error with initializing %s on %d-th'
                                  'btpeer', device_type, idx)
            if len(self.btpeer_group[device_type]) == 0:
                logging.error('No device is detected on %d-th btpeer', idx)

        logging.debug("self.bt_group is %s",self.btpeer_group)


    def wait_for_device(self, device, timeout=10):
        """Waits for device to become available again

        We reset raspberry pi peer between tests. This method helps us wait to
        prevent us from trying to use the device before it comes back up again.

        @param device: proxy object of peripheral device
        """

        def is_device_ready():
            """Tries to use a service of the device

            @returns: True if device is available to provide service
                      False otherwise
            """

            try:
                # Call a simple (fast) function to determine if device is online
                # and reachable. If we can query this property, we know the
                # device is available for us to use
                getattr(device, 'GetCapabilities')()

            except Exception as e:
                return False

            return True


        try:
            utils.poll_for_condition(condition=is_device_ready,
                                     desc='wait_for_device',
                                     timeout=timeout)

        except utils.TimeoutError as e:
            raise error.TestError('Peer is not available after waiting')


    def clear_raspi_device(self, device):
        """Clears a device on a raspi peer by resetting bluetooth stack

        @param device: proxy object of peripheral device
        """

        try:
            device.ResetStack()

        except socket.error as e:
            # Ignore conn reset, expected during stack reset
            if e.errno != errno.ECONNRESET:
                raise

        except chameleon.ChameleonConnectionError as e:
            # Ignore chameleon conn reset, expected during stack reset
            if str(errno.ECONNRESET) not in str(e):
                raise

        except six.moves.http_client.BadStatusLine as e:
            # BadStatusLine occurs occasionally when chameleon
            # is restarted. We ignore it here
            logging.error('Ignoring badstatusline exception')
            pass

        # Catch generic Fault exception by rpc server, ignore
        # method not available as it indicates platform didn't
        # support method and that's ok
        except Exception as e:
            if not (e.__class__.__name__ == 'Fault' and
                'is not supported' in str(e)):
                raise

        # Ensure device is back online before continuing
        self.wait_for_device(device, timeout=30)

    def device_set_powered(self, device, powered):
        """Set raspi BT powered state.

        @param powered: Powered state to set on Raspi.
        """
        if powered:
            device.AdapterPowerOn()
        else:
            device.AdapterPowerOff()

    def get_device_rasp(self, device_num, on_start=True):
        """Get all bluetooth device objects from Bluetooth peer devices
        This method should be called only after group_btpeers_type
        @param device_num : dict of {device_type:number}, to specify the number
                            of device needed for each device_type.

        @param on_start: boolean describing whether the requested clear is for a
                            new test, or in the middle of a current one

        @returns: True if Success.
        """

        logging.info("in get_device_rasp %s onstart %s", device_num, on_start)
        total_num_devices = sum(device_num.values())
        if total_num_devices > len(self.host.btpeer_list):
            logging.error(
                    'Total number of devices %s is greater than the'
                    ' number of Bluetooth peers %s', total_num_devices,
                    len(self.host.btpeer_list))
            return False

        for device_type, number in device_num.items():
            total_num_devices += number
            if len(self.btpeer_group[device_type]) < number:
                logging.error('Number of Bluetooth peers with device type'
                      '%s is %d, which is less then needed %d', device_type,
                      len(self.btpeer_group[device_type]), number)
                return False

            for btpeer in self.btpeer_group[device_type][:number]:
                logging.info("getting emulated %s", device_type)
                device = self.reset_device(btpeer, device_type, on_start)

                self.devices[device_type].append(device)

                # Remove this btpeer from btpeer_group since it is already
                # configured as a specific device
                for temp_device in SUPPORTED_DEVICE_TYPES:
                    if btpeer in self.btpeer_group[temp_device]:
                        self.btpeer_group[temp_device].remove(btpeer)

        return True


    def get_device(self, device_type, on_start=True):
        """Get the bluetooth device object.

        @param device_type : the bluetooth device type, e.g., 'MOUSE'

        @param on_start: boolean describing whether the requested clear is for a
                            new test, or in the middle of a current one

        @returns: the bluetooth device object

        """

        self.devices[device_type].append(
                self.reset_device(self.host.btpeer, device_type, on_start))

        return self.devices[device_type][-1]


    def reset_device(self, peer, device_type, clear_device=True):
        """Reset the peer device in order to be used as a different type.

        @param peer: the peer device to reset with new device type
        @param device_type : the new bluetooth device type, e.g., 'MOUSE'
        @param clear_device: whether to clear the device state

        @returns: the bluetooth device object

        """
        device = get_bluetooth_emulated_device(peer, device_type)

        # Re-fresh device to clean state if test is starting
        if clear_device:
            self.clear_raspi_device(device)

        try:
            # Tell generic chameleon to bind to this device type
            device.SpecifyDeviceType(device_type)

        # Catch generic Fault exception by rpc server, ignore method not
        # available as it indicates platform didn't support method and that's
        # ok
        except Exception as e:
            if not (e.__class__.__name__ == 'Fault' and
                    'is not supported' in str(e)):
                logging.error("got exception %s", str(e))
                raise

        return device


    def is_device_available(self, btpeer, device_type):
        """Determines if the named device is available on the linked peer

        @param device_type: the bluetooth HID device type, e.g., 'MOUSE'

        @returns: True if it is able to resolve the device, false otherwise
        """

        device = SUPPORTED_DEVICE_TYPES[device_type](btpeer)()
        try:
            # The proxy prevents us from checking if the object is None directly
            # so instead we call a fast method that any peripheral must support.
            # This will fail if the object over the proxy doesn't exist
            getattr(device, 'GetCapabilities')()

        except Exception as e:
            return False

        return True


    def list_devices_available(self):
        """Queries which devices are available on btpeer(s)

        @returns: dict mapping HID device types to number of supporting peers
                  available, e.g. {'MOUSE':1, 'KEYBOARD':1}
        """
        devices_available = {}
        for device_type in SUPPORTED_DEVICE_TYPES:
            for btpeer in self.host.btpeer_list:
                if self.is_device_available(btpeer, device_type):
                    devices_available[device_type] = \
                        devices_available.get(device_type, 0) + 1

        logging.debug("devices available are %s", devices_available)
        return devices_available


    def suspend_resume(self, suspend_time=SUSPEND_TIME_SECS):
        """Suspend the DUT for a while and then resume.

        @param suspend_time: the suspend time in secs
        @raises errors.TestFail if the device reboots during suspend

        """
        boot_id = self.host.get_boot_id()
        suspend = self.suspend_async(suspend_time=suspend_time)
        start_time = self.bluetooth_facade.get_device_time()

        # Give the system some time to enter suspend
        self.test_suspend_and_wait_for_sleep(
                suspend, sleep_timeout=self.SUSPEND_ENTER_SECS)

        # Wait for resume - since we're not testing suspend itself, we are
        # lenient with the resume time here
        self.test_wait_for_resume(boot_id,
                                  suspend,
                                  resume_timeout=suspend_time,
                                  test_start_time=start_time)


    def reboot(self):
        """Reboot the DUT and recreate necessary processes and variables"""
        self.host.reboot()

        # We need to recreate the bluetooth_facade after a reboot.
        # Delete the proxy first so it won't delete the old one, which
        # invokes disconnection, after creating the new one.
        if hasattr(self, 'factory'):
            del self.factory
        if hasattr(self, 'bluetooth_facade'):
            del self.bluetooth_facade
        if hasattr(self, 'input_facade'):
            del self.input_facade
        self.factory = remote_facade_factory.RemoteFacadeFactory(
                self.host, disable_arc=True, no_chrome=not self.start_browser)
        self.bluetooth_facade = self.factory.create_bluetooth_facade()
        self.input_facade = self.factory.create_input_facade()

        # Re-enable debugging verbose since Chrome will set it to
        # default(disable).
        self.enable_disable_debug_log(enable=True)

        # Re-disable cellular
        self.enable_disable_cellular(enable=False)

        # Re-disable ui
        self.enable_disable_ui(enable=False)

        self.start_new_btmon()
        self.start_new_usbmon()


    def _wait_till_condition_holds(self, func, method_name,
                                   timeout=DEFAULT_HOLD_TIMEOUT_SECS,
                                   sleep_interval=DEFAULT_HOLD_SLEEP_SECS,
                                   hold_interval=DEFAULT_HOLD_INTERVAL_SECS,
                                   start_delay=DEFAULT_START_DELAY_SECS):
        """ Wait for the func() to hold true for a period of time


        @param func: the function to wait for.
        @param method_name: the invoking class method.
        @param timeout: number of seconds to wait before giving up.
        @param sleep_interval: the interval in seconds to sleep between
                invoking func().
        @param hold_interval: the interval in seconds for the condition to
                             remain true
        @param start_delay: interval in seconds to wait before starting

        @returns: True if the condition is met,
                  False otherwise

        """
        if start_delay > 0:
            logging.debug('waiting for %s secs before checking %s',start_delay,
                          method_name)
            time.sleep(start_delay)

        try:
            utils.poll_till_condition_holds(condition=func,
                                            timeout=timeout,
                                            sleep_interval=sleep_interval,
                                            hold_interval = hold_interval,
                                            desc=('Waiting %s' % method_name))
            return True
        except utils.TimeoutError as e:
            logging.error('%s: %s', method_name, e)
        except Exception as e:
            logging.error('%s: %s', method_name, e)
            err = 'bluetoothd possibly crashed. Check out /var/log/messages.'
            logging.error(err)
        except:
            logging.error('%s: unexpected error', method_name)
        return False


    def _wait_for_condition(self, func, method_name,
                            timeout=ADAPTER_WAIT_DEFAULT_TIMEOUT_SECS,
                            sleep_interval=ADAPTER_POLLING_DEFAULT_SLEEP_SECS,
                            start_delay=DEFAULT_START_DELAY_SECS):
        """Wait for the func() to become True.

        @param func: the function to wait for.
        @param method_name: the invoking class method.
        @param timeout: number of seconds to wait before giving up.
        @param sleep_interval: the interval in seconds to sleep between
                invoking func().
        @param start_delay: interval in seconds to wait before starting

        @returns: True if the condition is met,
                  False otherwise

        """

        if start_delay > 0:
            logging.debug('waiting for %s secs before checking %s',start_delay,
                          method_name)
            time.sleep(start_delay)

        try:
            utils.poll_for_condition(condition=func,
                                     timeout=timeout,
                                     sleep_interval=sleep_interval,
                                     desc=('Waiting %s' % method_name))
            return True
        except utils.TimeoutError as e:
            logging.error('%s: %s', method_name, e)
        except Exception as e:
            logging.error('%s: %s', method_name, e)
            err = 'bluetoothd possibly crashed. Check out /var/log/messages.'
            logging.error(err)
        except:
            logging.error('%s: unexpected error', method_name)
        return False

    def ignore_failure(instance, test_method, *args, **kwargs):
        """ Wrapper to prevent a test_method failure from failing the test batch

        Sometimes a test method needs to be used as a normal function, for its
        result. This wrapper prevent test_method failure being recorded in
        instance.fails and causing a failure of the quick test batch.

        @param test_method: test_method
        @returns: result of the test_method
        """

        original_fails = instance.fails[:]
        test_result = test_method(*args, **kwargs)
        if not test_result:
            logging.info("%s failure is ignored",test_method.__name__)
            instance.fails = original_fails
        return test_result


    def start_agent(self, device):
        """Start the pairing agent of the device if applicable.

        @param device: the peer device
        """
        dev_type = device.GetDeviceType()
        capability = self.AGENT_CAPABILITY.get(dev_type)
        if capability:
            device.StartPairingAgent(capability)


    def stop_agent(self, device):
        """Stop the pairing agent of the device if applicable.

        @param device: the peer device
        """
        dev_type = device.GetDeviceType()
        capability = self.AGENT_CAPABILITY.get(dev_type)
        if capability:
            device.StopPairingAgent()


    # -------------------------------------------------------------------
    # Adater standalone tests
    # -------------------------------------------------------------------


    def service_exists(self, service_name):
        """Checks if a service exists on the DUT

        @param service_name: name of the service

        @returns: True if service status can be queried, else False
        """

        status_cmd = 'initctl status {}'.format(service_name)
        try:
            # Querying the status of a non-existent service throws an
            # AutoservRunError exception.  If no exception is thrown, we know
            # the service exists
            self.host.run(status_cmd)

        except error.AutoservRunError:
            return False

        return True


    def service_enabled(self, service_name):
        """Checks if a service is running on the DUT

        @param service_name: name of the service

        @throws: AutoservRunError is thrown if there is no service with the
                provided name installed on the DUT.

        @returns: True if service is currently running, else False
        """

        status_cmd = 'initctl status {}'.format(service_name)
        output = self.host.run(status_cmd).stdout

        return 'start/running' in output


    def _initctl_services(self, services, command):
        """Use initctl to control service on the DUT

        @param services: list of string service names
        @param command: initctl command on the services
                        'start': to start the service
                        'stop': to stop the service
                        'restart': to restart the service

        @returns: True if services were set successfully, else False
        """
        for service in services:
            # Some platforms will not support all services. In these cases,
            # no need to fail, since they won't interfere with our tests
            if not self.service_exists(service):
                logging.debug('Service %s does not exist on DUT', service)
                continue

            # A sample call to enable or disable a service is as follows:
            # "initctl stop modemfwd"
            if command in ['start', 'stop']:
                enable = command == 'start'
                if self.service_enabled(service) != enable:
                    self.host.run('initctl {} {}'.format(command, service))

                if self.service_enabled(service) != enable:
                    logging.error('Failed to set initctl service to state %d',
                                  enable)
                    return False

                if enable:
                    logging.info('Service {} enabled'.format(service))
                else:
                    logging.info('Service {} disabled'.format(service))

            elif command == 'restart':
                if self.service_enabled(service):
                    self.host.run('initctl {} {}'.format(command, service))
                else:
                    # Just start a stopped job.
                    self.host.run('initctl {} {}'.format('start', service))
                logging.info('Service {} restarted'.format(service))

            else:
                logging.error('unknown command {} on services {}'.format(
                              command, services))
                return False

        return True


    def enable_disable_services(self, services, enable):
        """Enable or disable service on the DUT

        @param services: list of string service names
        @param enable: True to enable services, False to disable

        @returns: True if services were set successfully, else False
        """
        command = 'start' if enable else 'stop'
        return self._initctl_services(services, command)


    def enable_disable_cellular(self, enable):
        """Enable cellular services on the DUT

        @param enable: True to enable cellular services
                       False to disable cellular services

        @returns: True if services were set successfully, else False
        """
        cellular_services = ['modemmanager', 'modemfwd']

        return self.enable_disable_services(cellular_services, enable)


    def enable_disable_ui(self, enable):
        """Enable UI service on the DUT

        @param enable: True to enable UI services
                       False to disable UI services

        @returns: True if services were set successfully, else False
        """
        ui_services = ['ui']

        return self.enable_disable_services(ui_services, enable)


    def restart_services(self, services):
        """Restart a service on the DUT

        @param services: the services, e.g., ['cras',]

        @returns: True if services were set successfully, else False
        """
        return self._initctl_services(services, 'restart')


    def restart_cras(self):
        """Restart the cras service on the DUT

        @returns: True if cras was restart successfully, else False
        """
        return self.restart_services(['cras', ])


    def enable_disable_debug_log(self, enable):
        """Enable or disable debug log in DUT
        @param enable: True to enable all of the debug log,
                       False to disable all of the debug log.
        """
        level = int(enable)
        self.bluetooth_facade.set_debug_log_levels(level, level, level, level)


    def start_new_btmon(self):
        """ Start a new btmon process and save the log """

        # Kill all btmon process before creating a new one
        self.host.run('pkill btmon || true')

        # Make sure the directory exists
        self.host.run('mkdir -p %s' % self.BTMON_DIR_LOG_PATH)

        # Time format. Ex, 2020_02_20_17_52_45
        now = time.strftime("%Y_%m_%d_%H_%M_%S")
        file_name = 'btsnoop_%s' % now
        self.host.run_background('btmon -SAw %s/%s' % (self.BTMON_DIR_LOG_PATH,
                                                       file_name))

    def start_new_usbmon(self):
        """ Start a new USBMON process and save the log """

        # Kill all usbmon process before creating a new one
        self.host.run('pkill tcpdump || true')

        # Make sure the directory exists
        self.host.run('mkdir -p %s' % self.USBMON_DIR_LOG_PATH)

        # Time format. Ex, 2020_02_20_17_52_45
        now = time.strftime("%Y_%m_%d_%H_%M_%S")
        file_name = 'usbmon_%s' % now
        self.host.run_background('tcpdump -i usbmon0 -w %s/%s' %
                                 (self.USBMON_DIR_LOG_PATH, file_name))


    def log_message(self, msg):
        """ Write a string to log."""
        self.bluetooth_facade.log_message(msg)

    def is_wrt_supported(self):
        """ Check if Bluetooth adapter support WRT logs. """
        return self.bluetooth_facade.is_wrt_supported()

    def enable_wrt_logs(self):
        """ Enable WRT logs from Intel Adapters."""
        return self.bluetooth_facade.enable_wrt_logs()

    def collect_wrt_logs(self):
        """ Collect WRT logs from Intel Adapters."""
        return self.bluetooth_facade.collect_wrt_logs()

    def get_num_connected_devices(self):
        """ Return number of remote devices currently connected to the DUT.

        @returns: The number of devices known to bluez with the Connected
            property active
        """

        num_connected_devices = 0
        for dev in self.bluetooth_facade.get_devices():
            if dev and dev.get('Connected', 0):
                num_connected_devices += 1

        return num_connected_devices

    @test_retry_and_log
    def test_bluetoothd_running(self):
        """Test that bluetoothd is running."""
        return self.bluetooth_facade.is_bluetoothd_running()


    @test_retry_and_log
    def test_start_bluetoothd(self):
        """Test that bluetoothd could be started successfully."""
        return self.bluetooth_facade.start_bluetoothd()


    @test_retry_and_log
    def test_stop_bluetoothd(self):
        """Test that bluetoothd could be stopped successfully."""
        return self.bluetooth_facade.stop_bluetoothd()


    @test_retry_and_log
    def test_has_adapter(self):
        """Verify that there is an adapter. This will return True only if both
        the kernel and bluetooth daemon see the adapter.
        """
        return self.bluetooth_facade.has_adapter()

    @test_retry_and_log
    def test_adapter_work_state(self):
        """Test that the bluetooth adapter is in the correct working state.

        This includes that the adapter is detectable, is powered on,
        and its hci device is hci0.
        """
        has_adapter = self.bluetooth_facade.has_adapter()
        is_powered_on = self._wait_for_condition(
                self.bluetooth_facade.is_powered_on, method_name())
        hci = self.bluetooth_facade.get_hci() == self.EXPECTED_HCI
        self.results = {
                'has_adapter': has_adapter,
                'is_powered_on': is_powered_on,
                'hci': hci}
        return all(self.results.values())

    @test_retry_and_log(False)
    def test_adapter_wake_enabled(self):
        """Test that the bluetooth adapter is wakeup enabled.
        """
        wake_enabled = self._wait_for_condition(
                self.bluetooth_facade.is_wake_enabled, method_name(),
                timeout=self.ADAPTER_WAKE_ENABLE_TIMEOUT_SECS)

        self.results = { 'wake_enabled': wake_enabled }
        return any(self.results.values())

    @test_retry_and_log(False)
    def test_device_wake_allowed(self, device_address):
        """Test that given device can wake the system."""
        self.results = {
                'Wake allowed':
                self.bluetooth_facade.get_device_property(
                        device_address, 'WakeAllowed')
        }

        return all(self.results.values())

    @test_retry_and_log(False)
    def test_device_wake_not_allowed(self, device_address):
        """Test that given device cannot wake the system."""
        self.results = {
                'Wake not allowed':
                not self.bluetooth_facade.get_device_property(
                        device_address, 'WakeAllowed')
        }

        return all(self.results.values())

    @test_retry_and_log(False)
    def test_adapter_set_wake_disabled(self):
        """Disable wake and verify it was written. """
        success = self.bluetooth_facade.set_wake_enabled(False)
        self.results = { 'disable_wake': success }
        return all(self.results.values())

    @test_retry_and_log
    def test_power_on_adapter(self):
        """Test that the adapter could be powered on successfully."""
        power_on = self.bluetooth_facade.set_powered(True)
        is_powered_on = self._wait_for_condition(
                self.bluetooth_facade.is_powered_on, method_name())

        self.results = {'power_on': power_on, 'is_powered_on': is_powered_on}
        return all(self.results.values())


    @test_retry_and_log
    def test_power_off_adapter(self):
        """Test that the adapter could be powered off successfully."""
        power_off = self.bluetooth_facade.set_powered(False)
        is_powered_off = self._wait_for_condition(
                lambda: not self.bluetooth_facade.is_powered_on(),
                method_name())

        self.results = {
                'power_off': power_off,
                'is_powered_off': is_powered_off}
        return all(self.results.values())


    @test_retry_and_log
    def test_reset_on_adapter(self):
        """Test that the adapter could be reset on successfully.

        This includes restarting bluetoothd, and removing the settings
        and cached devices.
        """
        reset_on = self.bluetooth_facade.reset_on()
        is_powered_on = self._wait_for_condition(
                self.bluetooth_facade.is_powered_on, method_name())

        self.results = {'reset_on': reset_on, 'is_powered_on': is_powered_on}
        return all(self.results.values())


    @test_retry_and_log
    def test_reset_off_adapter(self):
        """Test that the adapter could be reset off successfully.

        This includes restarting bluetoothd, and removing the settings
        and cached devices.
        """
        reset_off = self.bluetooth_facade.reset_off()
        is_powered_off = self._wait_for_condition(
                lambda: not self.bluetooth_facade.is_powered_on(),
                method_name())

        self.results = {
                'reset_off': reset_off,
                'is_powered_off': is_powered_off}
        return all(self.results.values())


    def test_is_powered_off(self):
        """Check if the adapter is powered off."""
        is_powered_off = not self.bluetooth_facade.is_powered_on()
        self.results = {'is_powered_off': is_powered_off}
        return all(self.results.values())


    @test_retry_and_log(False)
    def test_is_facade_valid(self):
        """Checks whether the bluetooth facade is in a good state.

        If bluetoothd restarts (i.e. due to a crash), the object proxies will no
        longer be valid (because the session will be closed). Check whether the
        session failed and wait for a new session if it did.
        """
        initially_ok = self.bluetooth_facade.is_bluetoothd_valid()
        bluez_started = initially_ok or self.bluetooth_facade.start_bluetoothd()

        self.results = {
                'initially_ok': initially_ok,
                'bluez_started': bluez_started
        }
        return all(self.results.values())


    @test_retry_and_log(False)
    def test_is_adapter_valid(self):
        """Verify the bluetooth adapter is retrievable at test start

        @raises: error.TestNAError if we fail to retrieve the adapter on
                    an unsupported chipset
                 error.TestFail if we fail to retrieve the adapter on any other
                    platform

        @returns: True if the adapter was located properly
        """

        if not self.bluetooth_facade.has_adapter():
            logging.error('No adapter available, rebooting to recover')

            self.reboot()

            chipset = self.get_chipset_name()

            if not chipset:
                raise error.TestFail('Unknown adapter is missing')

            # A missing adapter is a rare but known issue on several platforms
            # that have no vendor support (b/169328792). Since there is no fix
            # possible, we forgive these failures by raising a TestNA.
            if chipset in UNSUPPORTED_CHIPSETS:
                raise error.TestNAError('Unsupported adapter is missing')

            raise error.TestFail('Adapter is missing')

        return True

    @test_retry_and_log
    def test_UUIDs(self):
        """Test that basic profiles are supported."""
        adapter_UUIDs = self.bluetooth_facade.get_UUIDs()
        self.results = [uuid for uuid in self.SUPPORTED_UUIDS.values()
                        if uuid not in adapter_UUIDs]
        return not bool(self.results)


    @test_retry_and_log
    def test_start_discovery(self):
        """Test that the adapter could start discovery."""
        start_discovery, _ = self.bluetooth_facade.start_discovery()
        is_discovering = self._wait_for_condition(
                self.bluetooth_facade.is_discovering, method_name())

        self.results = {
                'start_discovery': start_discovery,
                'is_discovering': is_discovering}
        return all(self.results.values())

    @test_retry_and_log(False)
    def test_is_discovering(self):
        """Test that the adapter is already discovering."""
        is_discovering = self._wait_for_condition(
                self.bluetooth_facade.is_discovering, method_name())

        self.results = {'is_discovering': is_discovering}
        return all(self.results.values())

    @test_retry_and_log
    def test_stop_discovery(self):
        """Test that the adapter could stop discovery."""
        if not self.bluetooth_facade.is_discovering():
            return True

        stop_discovery, _ = self.bluetooth_facade.stop_discovery()
        is_not_discovering = self._wait_for_condition(
                lambda: not self.bluetooth_facade.is_discovering(),
                method_name())

        self.results = {
                'stop_discovery': stop_discovery,
                'is_not_discovering': is_not_discovering}
        return all(self.results.values())


    @test_retry_and_log
    def test_discoverable(self):
        """Test that the adapter could be set discoverable."""
        set_discoverable = self.bluetooth_facade.set_discoverable(True)
        is_discoverable = self._wait_for_condition(
                self.bluetooth_facade.is_discoverable, method_name())

        self.results = {
                'set_discoverable': set_discoverable,
                'is_discoverable': is_discoverable}
        return all(self.results.values())

    @test_retry_and_log(False)
    def test_is_discoverable(self):
        """Test that the adapter is discoverable."""
        is_discoverable = self._wait_for_condition(
                self.bluetooth_facade.is_discoverable, method_name())

        self.results = {'is_discoverable': is_discoverable}
        return all(self.results.values())


    def _test_timeout_property(self, set_property, check_property, set_timeout,
                              get_timeout, property_name,
                              timeout_values = [0, 60, 180]):
        """Common method to test (Discoverable/Pairable)Timeout .

        This is used to test
        - DiscoverableTimeout property
        - PairableTimeout property

        The test performs the following
           - Set PropertyTimeout
           - Read PropertyTimeout and make sure values match
           - Set adapter propety
           - In a loop check if property is active
           - Test fails property is false before timeout
           - Test fails property is True after timeout
           Repeat the test for different values for timeout

           Note : Value of 0 mean it never timeouts, so the test will
                 end after 30 seconds.
        """
        def check_timeout(timeout):
            """Check for timeout value in loop while recording failures."""
            actual_timeout = get_timeout()
            if timeout != actual_timeout:
                logging.debug('%s timeout value read %s does not '
                              'match value set %s, yet', property_name,
                              actual_timeout, timeout)
                return False
            else:
                return True

        def _test_timeout_property(timeout):
            # minium time after timeout before checking property
            MIN_DELTA_SECS = 3
            # Time between checking  property
            WAIT_TIME_SECS = 2

            # Set and read back the timeout value
            if not set_timeout(timeout):
                logging.error('Setting the %s timeout failed',property_name)
                return False


            if not self._wait_for_condition(lambda : check_timeout(timeout),
                                            'check_'+property_name):
                logging.error('checking %s_timeout value timed out',
                              property_name)
                return False

            #
            # Check that the timeout works
            # Check property is true until timeout
            # and then it is not

            property_set = set_property(True)
            property_is_true = self._wait_for_condition(check_property,
                                                        method_name())

            self.results = { 'set_%s' % property_name : property_set,
                             'is_%s' % property_name: property_is_true}
            logging.debug(self.results)

            if not all(self.results.values()):
                logging.error('Setting %s failed',property_name)
                return False

            start_time = time.time()
            while True:
                time.sleep(WAIT_TIME_SECS)
                cur_time = time.time()
                property_set = check_property()
                time_elapsed = cur_time - start_time

                # Ignore check_property results made near the timeout
                # to avoid spurious failures.
                if abs(int(timeout - time_elapsed)) < MIN_DELTA_SECS:
                    continue

                # Timeout of zero seconds mean that the adapter never times out
                # Check for 30 seconds and then exit the test.
                if timeout == 0:
                    if not property_set:
                        logging.error('Adapter is not %s after %.2f '
                                      'secs with a timeout of zero ',
                                      property_name, time_elapsed)
                        return False
                    elif time_elapsed > 30:
                        logging.debug('Adapter %s after %.2f seconds '
                                      'with timeout of zero as expected' ,
                                      property_name, time_elapsed)
                        return True
                    continue

                #
                # Check if property is true till timeout ends and
                # false afterwards
                #
                if time_elapsed < timeout:
                    if not property_set:
                        logging.error('Adapter is not %s after %.2f '
                                      'secs before timeout of %.2f',
                                      property_name, time_elapsed, timeout)
                        return False
                else:
                    if property_set:
                        logging.error('Adapter is still %s after '
                                      ' %.2f secs with timeout of %.2f',
                                      property_name, time_elapsed, timeout)
                        return False
                    else:
                        logging.debug('Adapter not %s after %.2f '
                                      'secs with timeout of %.2f as expected ',
                                      property_name, time_elapsed, timeout)
                        return True

        default_value = check_property()
        default_timeout = get_timeout()

        result = []
        try:
            for timeout in timeout_values:
                result.append(_test_timeout_property(timeout))
            logging.debug("Test returning %s", all(result))
            return all(result)
        except:
            logging.error("exception in test_%s_timeout",property_name)
            raise
        finally:
            # Set the property back to default value permanently before
            # exiting the test
            set_timeout(0)
            set_property(default_value)
            # Set the timeout back to default value before exiting the test
            set_timeout(default_timeout)


    @test_retry_and_log
    def test_discoverable_timeout(self, timeout_values = [0, 60, 180]):
        """Test adapter dbus property DiscoverableTimeout."""
        return self._test_timeout_property(
            set_property = self.bluetooth_facade.set_discoverable,
            check_property = self.bluetooth_facade.is_discoverable,
            set_timeout = self.bluetooth_facade.set_discoverable_timeout,
            get_timeout = self.bluetooth_facade.get_discoverable_timeout,
            property_name = 'discoverable',
            timeout_values = timeout_values)

    @test_retry_and_log
    def test_pairable_timeout(self, timeout_values = [0, 60, 180]):
        """Test adapter dbus property PairableTimeout."""
        return self._test_timeout_property(
            set_property = self.bluetooth_facade.set_pairable,
            check_property = self.bluetooth_facade.is_pairable,
            set_timeout = self.bluetooth_facade.set_pairable_timeout,
            get_timeout = self.bluetooth_facade.get_pairable_timeout,
            property_name = 'pairable',
            timeout_values = timeout_values)


    @test_retry_and_log
    def test_nondiscoverable(self):
        """Test that the adapter could be set non-discoverable."""
        set_nondiscoverable = self.bluetooth_facade.set_discoverable(False)
        is_nondiscoverable = self._wait_for_condition(
                lambda: not self.bluetooth_facade.is_discoverable(),
                method_name())

        self.results = {
                'set_nondiscoverable': set_nondiscoverable,
                'is_nondiscoverable': is_nondiscoverable}
        return all(self.results.values())


    @test_retry_and_log
    def test_pairable(self):
        """Test that the adapter could be set pairable."""
        set_pairable = self.bluetooth_facade.set_pairable(True)
        is_pairable = self._wait_for_condition(
                self.bluetooth_facade.is_pairable, method_name())

        self.results = {
                'set_pairable': set_pairable,
                'is_pairable': is_pairable}
        return all(self.results.values())


    @test_retry_and_log
    def test_nonpairable(self):
        """Test that the adapter could be set non-pairable."""
        set_nonpairable = self.bluetooth_facade.set_pairable(False)
        is_nonpairable = self._wait_for_condition(
                lambda: not self.bluetooth_facade.is_pairable(), method_name())

        self.results = {
                'set_nonpairable': set_nonpairable,
                'is_nonpairable': is_nonpairable}
        return all(self.results.values())


    @test_retry_and_log(False)
    def test_check_valid_adapter_id(self):
        """Fail if the Bluetooth ID is not in the correct format.

        @returns True if adapter ID follows expected format, False otherwise
        """

        device = self.get_base_platform_name()
        adapter_info = self.get_adapter_properties()

        # Don't complete test if this is a reference board
        if device in self.REFERENCE_BOARDS:
            return True

        modalias = adapter_info['Modalias']
        logging.debug('Saw Bluetooth ID of: %s', modalias)

        # Valid Device ID is:
        # <00E0(Google)>/<C405(Chrome OS)>/<non-zero versionNumber>
        bt_format = 'bluetooth:v00E0pC405d(?!0000)'

        if not re.match(bt_format, modalias):
            return False

        return True


    @test_retry_and_log(False)
    def test_check_valid_alias(self):
        """Fail if the Bluetooth alias is not in the correct format.

        @returns True if adapter alias follows expected format, False otherwise
        """

        device = self.get_base_platform_name()
        adapter_info = self.get_adapter_properties()

        # Don't complete test if this is a reference board
        if device in self.REFERENCE_BOARDS:
            return True

        alias = adapter_info['Alias']
        logging.debug('Saw Bluetooth Alias of: %s', alias)

        device_type = self.host.get_board_type().lower()
        alias_format = '%s_[a-z0-9]{4}' % device_type

        self.results = {}

        alias_was_correct = True
        if not re.match(alias_format, alias.lower()):
            alias_was_correct = False
            logging.info('unexpected alias %s found', alias)
            self.results['alias_found'] = alias

        self.results['alias_was_correct'] = alias_was_correct
        return all(self.results.values())


    # -------------------------------------------------------------------
    # Tests about general discovering, pairing, and connection
    # -------------------------------------------------------------------


    @test_retry_and_log(False)
    def test_discover_device(self,
                             device_address,
                             start_discovery=True,
                             stop_discovery=True):
        """Test that the adapter could discover the specified device address.

        @param device_address: Address of the device.
        @param start_discovery: Whether to start discovery. Set to False if you
                                call start_discovery before calling this.
        @param stop_discovery: Whether to stop discovery at the end. If this is
                               set to False, make sure to call
                               test_stop_discovery afterwards.

        @returns: True if the device is found. False otherwise.

        """
        has_device_initially = False
        discovery_stopped = False
        is_not_discovering = False
        device_discovered = False
        # If start discovery is not set, discovery must already be started
        discovery_started = not start_discovery
        has_device = self.bluetooth_facade.has_device

        if has_device(device_address):
            has_device_initially = True
        else:
            if start_discovery:
                discovery_started = self.bluetooth_facade.start_discovery()

            if discovery_started:
                try:
                    utils.poll_for_condition(
                            condition=(lambda: has_device(device_address)),
                            timeout=self.ADAPTER_DISCOVER_TIMEOUT_SECS,
                            sleep_interval=
                            self.ADAPTER_DISCOVER_POLLING_SLEEP_SECS,
                            desc='Waiting for discovering %s' % device_address)
                    device_discovered = True
                except utils.TimeoutError as e:
                    logging.error('test_discover_device: %s', e)
                except Exception as e:
                    logging.error('test_discover_device: %s', e)
                    err = ('bluetoothd probably crashed.'
                           'Check out /var/log/messages')
                    logging.error(err)
                except:
                    logging.error('test_discover_device: unexpected error')

            if start_discovery and stop_discovery:
                discovery_stopped, _ = self.bluetooth_facade.stop_discovery()
                is_not_discovering = self._wait_for_condition(
                        lambda: not self.bluetooth_facade.is_discovering(),
                        method_name())

        self.results = {
                'has_device_initially': has_device_initially,
                'should_start_discovery': start_discovery,
                'should_stop_discovery': stop_discovery,
                'start_discovery': discovery_started,
                'stop_discovery': discovery_stopped,
                'is_not_discovering': is_not_discovering,
                'device_discovered': device_discovered}

        # Make sure a discovered device properly started and stopped discovery
        device_found = device_discovered and discovery_started and (
                discovery_stopped and is_not_discovering
                if stop_discovery else True)

        return has_device_initially or device_found


    def _test_discover_by_device(self, device):
        return device.Discover(self.bluetooth_facade.address)

    @test_retry_and_log(False, messages_start=False, messages_stop=False)
    def test_discover_by_device(self, device):
        """Test that the device could discover the adapter address.

        @param device: Meta device to represent peer device.

        @returns: True if the adapter is found by the device.
        """
        adapter_discovered = False
        discover_by_device = self._test_discover_by_device
        discovered_initially = discover_by_device(device)

        if not discovered_initially:
            try:
                utils.poll_for_condition(
                        condition=(lambda: discover_by_device(device)),
                        timeout=self.ADAPTER_DISCOVER_TIMEOUT_SECS,
                        sleep_interval=
                        self.ADAPTER_DISCOVER_POLLING_SLEEP_SECS,
                        desc='Waiting for adapter to be discovered')
                adapter_discovered = True
            except utils.TimeoutError as e:
                logging.error('test_discover_by_device: %s', e)
            except Exception as e:
                logging.error('test_discover_by_device: %s', e)
                err = ('bluetoothd probably crashed.'
                       'Check out /var/log/messages')
                logging.error(err)
            except:
                logging.error('test_discover_by_device: unexpected error')

        self.results = {
            'adapter_discovered_initially': discovered_initially,
            'adapter_discovered': adapter_discovered
        }
        return any(self.results.values())

    @test_retry_and_log(False, messages_start=False, messages_stop=False)
    def test_discover_by_device_fails(self, device):
        """Test that the device could not discover the adapter address.

        @param device: Meta device to represent peer device.

        @returns False if the adapter is found by the device.
        """
        self.results = {
                'adapter_discovered': self._test_discover_by_device(device)
        }
        return not any(self.results.values())

    @test_retry_and_log(False, messages_start=False, messages_stop=False)
    def test_device_set_discoverable(self, device, discoverable):
        """Test that we could set the peer device to discoverable. """
        try:
            device.SetDiscoverable(discoverable)
        except:
            return False

        return True

    @test_retry_and_log
    def test_pairing(self, device_address, pin, trusted=True):
        """Test that the adapter could pair with the device successfully.

        @param device_address: Address of the device.
        @param pin: pin code to pair with the device.
        @param trusted: indicating whether to set the device trusted.

        @returns: True if pairing succeeds. False otherwise.

        """

        def _pair_device():
            """Pair to the device.

            @returns: True if it could pair with the device. False otherwise.

            """
            return self.bluetooth_facade.pair_legacy_device(
                    device_address, pin, trusted,
                    self.ADAPTER_PAIRING_TIMEOUT_SECS)


        def _verify_connection_info():
            """Verify that connection info to device is retrievable.

            @returns: True if the connection info is retrievable.
                      False otherwise.
            """
            return (self.bluetooth_facade.get_connection_info(device_address)
                    is not None)

        def _verify_connected():
            """Verify the device is connected.

            @returns: True if the device is connected, False otherwise.
            """
            return self.bluetooth_facade.device_is_connected(device_address)

        has_device = False
        paired = False
        connected = False
        connection_info_retrievable = False
        connected_devices = self.get_num_connected_devices()

        if self.bluetooth_facade.has_device(device_address):
            has_device = True
            try:
                utils.poll_for_condition(
                        condition=_pair_device,
                        timeout=self.ADAPTER_PAIRING_TIMEOUT_SECS,
                        sleep_interval=self.ADAPTER_PAIRING_POLLING_SLEEP_SECS,
                        desc='Waiting for pairing %s' % device_address)
                paired = True
            except utils.TimeoutError as e:
                logging.error('test_pairing: %s', e)
            except:
                logging.error('test_pairing: unexpected error')

            connection_info_retrievable = _verify_connection_info()
            connected = _verify_connected()

        self.results = {
                'has_device': has_device,
                'paired': paired,
                'connected': connected,
                'connection_info_retrievable': connection_info_retrievable,
                'connection_num': connected_devices + 1
        }

        return all(self.results.values())

    @test_retry_and_log
    def test_remove_pairing(self, device_address):
        """Test that the adapter could remove the paired device.

        @param device_address: Address of the device.

        @returns: True if the device is removed successfully. False otherwise.

        """
        device_is_paired_initially = self.bluetooth_facade.device_is_paired(
                device_address)
        remove_pairing = False
        pairing_removed = False

        if device_is_paired_initially:
            remove_pairing = self.bluetooth_facade.remove_device_object(
                    device_address)
            pairing_removed = not self.bluetooth_facade.device_is_paired(
                    device_address)

        self.results = {
                'device_is_paired_initially': device_is_paired_initially,
                'remove_pairing': remove_pairing,
                'pairing_removed': pairing_removed}
        return all(self.results.values())


    def test_set_trusted(self, device_address, trusted=True):
        """Test whether the device with the specified address is trusted.

        @param device_address: Address of the device.
        @param trusted : True or False indicating if trusted is expected.

        @returns: True if the device's "Trusted" property is as specified;
                  False otherwise.

        """

        set_trusted = self.bluetooth_facade.set_trusted(
                device_address, trusted)

        actual_trusted = self.bluetooth_facade.get_device_property(
                                device_address, 'Trusted')

        self.results = {
                'set_trusted': set_trusted,
                'actual trusted': actual_trusted,
                'expected trusted': trusted}
        return actual_trusted == trusted


    @test_retry_and_log
    def test_connection_by_adapter(self, device_address):
        """Test that the adapter of dut could connect to the device successfully

        It is the caller's responsibility to pair to the device before
        doing connection.

        @param device_address: Address of the device.

        @returns: True if connection is performed. False otherwise.

        """

        def _connect_device():
            """Connect to the device.

            @returns: True if it could connect to the device. False otherwise.

            """
            return self.bluetooth_facade.connect_device(device_address)


        has_device = False
        connected = False
        if self.bluetooth_facade.has_device(device_address):
            has_device = True
            try:
                utils.poll_for_condition(
                        condition=_connect_device,
                        timeout=self.ADAPTER_PAIRING_TIMEOUT_SECS,
                        sleep_interval=self.ADAPTER_PAIRING_POLLING_SLEEP_SECS,
                        desc='Waiting for connecting to %s' % device_address)
                connected = True
            except utils.TimeoutError as e:
                logging.error('test_connection_by_adapter: %s', e)
            except:
                logging.error('test_connection_by_adapter: unexpected error')

        self.results = {'has_device': has_device, 'connected': connected}
        return all(self.results.values())


    @test_retry_and_log
    def test_disconnection_by_adapter(self, device_address):
        """Test that the adapter of dut could disconnect the device successfully

        @param device_address: Address of the device.

        @returns: True if disconnection is performed. False otherwise.

        """
        return self.bluetooth_facade.disconnect_device(device_address)


    def _enter_command_mode(self, device):
        """Let the device enter command mode.

        Before using the device, need to call this method to make sure
        it is in the command mode.

        @param device: the bluetooth HID device

        @returns: True if successful. False otherwise.

        """
        result = _is_successful(_run_method(device.EnterCommandMode,
                                            'EnterCommandMode'))
        if not result:
            logging.error('EnterCommandMode failed')
        return result


    @test_retry_and_log
    def test_connection_by_device(self, device):
        """Test that the device could connect to the adapter successfully.

        This emulates the behavior that a device may initiate a
        connection request after waking up from power saving mode.

        @param device: the bluetooth HID device

        @returns: True if connection is performed correctly by device and
                  the adapter also enters connection state.
                  False otherwise.

        """
        if not self._enter_command_mode(device):
            return False

        method_name = 'test_connection_by_device'
        connection_by_device = False
        adapter_address = self.bluetooth_facade.address
        try:
            connection_by_device = device.ConnectToRemoteAddress(
                adapter_address)
        except Exception as e:
            logging.error('%s (device): %s', method_name, e)
        except:
            logging.error('%s (device): unexpected error', method_name)

        connection_seen_by_adapter = False
        device_address = device.address
        device_is_connected = self.bluetooth_facade.device_is_connected
        try:
            utils.poll_for_condition(
                    condition=lambda: device_is_connected(device_address),
                    timeout=self.ADAPTER_CONNECTION_TIMEOUT_SECS,
                    desc=('Waiting for connection from %s' % device_address))
            connection_seen_by_adapter = True

            # Although the connect may be complete, it can take a few
            # seconds for the input device to be ready for use
            time.sleep(self.ADAPTER_HID_INPUT_DELAY)
        except utils.TimeoutError as e:
            logging.error('%s (adapter): %s', method_name, e)
        except:
            logging.error('%s (adapter): unexpected error', method_name)

        self.results = {
                'connection_by_device': connection_by_device,
                'connection_seen_by_adapter': connection_seen_by_adapter}
        return all(self.results.values())

    @test_retry_and_log(True, messages_start=False, messages_stop=False)
    def test_connection_by_device_only(self, device, adapter_address):
        """Test that the device could connect to adapter successfully.

        This is a modified version of test_connection_by_device that only
        communicates with the peer device and not the host (in case the host is
        suspended for example).

        @param device: the bluetooth peer device
        @param adapter_address: address of the adapter

        @returns: True if the connection was established by the device or False.
        """
        connected = device.ConnectToRemoteAddress(adapter_address)
        if connected:
            # Although the connect may be complete, it can take a few
            # seconds for the input device to be ready for use
            time.sleep(self.ADAPTER_HID_INPUT_DELAY)

        self.results = {
            'connection_by_device': connected
        }

        return all(self.results.values())


    @test_retry_and_log
    def test_disconnection_by_device(self, device):
        """Test that the device could disconnect the adapter successfully.

        This emulates the behavior that a device may initiate a
        disconnection request before going into power saving mode.

        Note: should not try to enter command mode in this method. When
              a device is connected, there is no way to enter command mode.
              One could just issue a special disconnect command without
              entering command mode.

        @param device: the bluetooth HID device

        @returns: True if disconnection is performed correctly by device and
                  the adapter also observes the disconnection.
                  False otherwise.

        """
        method_name = 'test_disconnection_by_device'
        disconnection_by_device = False
        try:
            device.Disconnect()
            disconnection_by_device = True
        except Exception as e:
            logging.error('%s (device): %s', method_name, e)
        except:
            logging.error('%s (device): unexpected error', method_name)

        disconnection_seen_by_adapter = False
        device_address = device.address
        device_is_connected = self.bluetooth_facade.device_is_connected
        try:
            utils.poll_for_condition(
                    condition=lambda: not device_is_connected(device_address),
                    timeout=self.ADAPTER_DISCONNECTION_TIMEOUT_SECS,
                    desc=('Waiting for disconnection from %s' % device_address))
            disconnection_seen_by_adapter = True
        except utils.TimeoutError as e:
            logging.error('%s (adapter): %s', method_name, e)
        except:
            logging.error('%s (adapter): unexpected error', method_name)

        self.results = {
                'disconnection_by_device': disconnection_by_device,
                'disconnection_seen_by_adapter': disconnection_seen_by_adapter}
        return all(self.results.values())


    @test_retry_and_log(False)
    def test_device_is_connected(self, device_address):
        """Test that device address given is currently connected.

        @param device_address: Address of the device.

        @returns: True if the device is connected.
                  False otherwise.
        """

        def _is_connected():
            """Test if device is connected.

            @returns: True if device is connected. False otherwise.

            """
            return self.bluetooth_facade.device_is_connected(device_address)


        method_name = 'test_device_is_connected'
        has_device = False
        connected = False
        if self.bluetooth_facade.has_device(device_address):
            has_device = True
            try:
                utils.poll_for_condition(
                        condition=_is_connected,
                        timeout=self.ADAPTER_CONNECTION_TIMEOUT_SECS,
                        sleep_interval=self.ADAPTER_PAIRING_POLLING_SLEEP_SECS,
                        desc='Waiting to check connection to %s' %
                              device_address)
                connected = True
            except utils.TimeoutError as e:
                logging.error('%s: %s', method_name, e)
            except:
                logging.error('%s: unexpected error', method_name)
        self.results = {'has_device': has_device, 'connected': connected}
        return all(self.results.values())


    @test_retry_and_log(False)
    def test_device_is_not_connected(self, device_address):
        """Test that device address given is NOT currently connected.

        @param device_address: Address of the device.

        @returns: True if the device is NOT connected.
                  False otherwise.

        """

        def _is_not_connected():
            """Test if device is not connected.

            @returns: True if device is not connected. False otherwise.

            """
            return not self.bluetooth_facade.device_is_connected(
                    device_address)


        method_name = 'test_device_is_not_connected'
        not_connected = False
        if self.bluetooth_facade.has_device(device_address):
            try:
                utils.poll_for_condition(
                        condition=_is_not_connected,
                        timeout=self.ADAPTER_CONNECTION_TIMEOUT_SECS,
                        sleep_interval=self.ADAPTER_PAIRING_POLLING_SLEEP_SECS,
                        desc='Waiting to check connection to %s' %
                              device_address)
                not_connected = True
            except utils.TimeoutError as e:
                logging.error('%s: %s', method_name, e)
            except:
                logging.error('%s: unexpected error', method_name)
                raise
        else:
            not_connected = True
        self.results = {'not_connected': not_connected}
        return all(self.results.values())


    @test_retry_and_log
    def test_device_is_paired(self, device_address):
        """Test that the device address given is currently paired.

        @param device_address: Address of the device.

        @returns: True if the device is paired.
                  False otherwise.

        """
        def _is_paired():
            """Test if device is paired.

            @returns: True if device is paired. False otherwise.

            """
            return self.bluetooth_facade.device_is_paired(device_address)


        method_name = 'test_device_is_paired'
        has_device = False
        paired = False
        if self.bluetooth_facade.has_device(device_address):
            has_device = True
            try:
                utils.poll_for_condition(
                        condition=_is_paired,
                        timeout=self.ADAPTER_PAIRING_TIMEOUT_SECS,
                        sleep_interval=self.ADAPTER_PAIRING_POLLING_SLEEP_SECS,
                        desc='Waiting for connection to %s' % device_address)
                paired = True
            except utils.TimeoutError as e:
                logging.error('%s: %s', method_name, e)
            except:
                logging.error('%s: unexpected error', method_name)
        self.results = {'has_device': has_device, 'paired': paired}
        return all(self.results.values())


    def _get_device_name(self, device_address):
        """Get the device name.

        @returns: True if the device name is derived. None otherwise.

        """

        self.discovered_device_name = self.bluetooth_facade.get_device_property(
                                device_address, 'Name')

        return bool(self.discovered_device_name)


    @test_retry_and_log
    def test_device_name(self, device_address, expected_device_name):
        """Test that the device name discovered by the adapter is correct.

        @param device_address: Address of the device.
        @param expected_device_name: the bluetooth device name

        @returns: True if the discovered_device_name is expected_device_name.
                  False otherwise.

        """
        try:
            utils.poll_for_condition(
                    condition=lambda: self._get_device_name(device_address),
                    timeout=self.ADAPTER_DISCOVER_NAME_TIMEOUT_SECS,
                    sleep_interval=self.ADAPTER_DISCOVER_POLLING_SLEEP_SECS,
                    desc='Waiting for device name of %s' % device_address)
        except utils.TimeoutError as e:
            logging.error('test_device_name: %s', e)
        except:
            logging.error('test_device_name: unexpected error')

        self.results = {
                'expected_device_name': expected_device_name,
                'discovered_device_name': self.discovered_device_name}
        return self.discovered_device_name == expected_device_name


    @test_retry_and_log
    def test_device_class_of_service(self, device_address,
                                     expected_class_of_service):
        """Test that the discovered device class of service is as expected.

        @param device_address: Address of the device.
        @param expected_class_of_service: the expected class of service

        @returns: True if the discovered class of service matches the
                  expected class of service. False otherwise.

        """

        device_class = self.bluetooth_facade.get_device_property(device_address,
                                                                 'Class')
        discovered_class_of_service = (device_class & self.CLASS_OF_SERVICE_MASK
                                       if device_class else None)

        self.results = {
                'device_class': device_class,
                'expected_class_of_service': expected_class_of_service,
                'discovered_class_of_service': discovered_class_of_service}
        return discovered_class_of_service == expected_class_of_service


    @test_retry_and_log
    def test_device_class_of_device(self, device_address,
                                    expected_class_of_device):
        """Test that the discovered device class of device is as expected.

        @param device_address: Address of the device.
        @param expected_class_of_device: the expected class of device

        @returns: True if the discovered class of device matches the
                  expected class of device. False otherwise.

        """

        device_class = self.bluetooth_facade.get_device_property(device_address,
                                                                 'Class')
        discovered_class_of_device = (device_class & self.CLASS_OF_DEVICE_MASK
                                      if device_class else None)

        self.results = {
                'device_class': device_class,
                'expected_class_of_device': expected_class_of_device,
                'discovered_class_of_device': discovered_class_of_device}
        return discovered_class_of_device == expected_class_of_device


    def _get_btmon_log(self, method, logging_timespan=1):
        """Capture the btmon log when executing the specified method.

        @param method: the method to capture log.
                       The method would be executed only when it is not None.
                       This allows us to simply capture btmon log without
                       executing any command.
        @param logging_timespan: capture btmon log for logging_timespan seconds.

        """
        self.bluetooth_le_facade.btmon_start()
        self.advertising_msg = method() if method else ''
        time.sleep(logging_timespan)
        self.bluetooth_le_facade.btmon_stop()


    def convert_to_adv_jiffies(self, adv_interval_ms):
        """Convert adv interval in ms to jiffies, i.e., multiples of 0.625 ms.

        @param adv_interval_ms: an advertising interval

        @returns: the equivalent jiffies

        """
        return adv_interval_ms / self.ADVERTISING_INTERVAL_UNIT


    def compute_duration(self, max_adv_interval_ms):
        """Compute duration from max_adv_interval_ms.

        Advertising duration is calculated approximately as
            duration = max_adv_interval_ms / 1000.0 * 1.1

        @param max_adv_interval_ms: max advertising interval in milliseconds.

        @returns: duration in seconds.

        """
        return max_adv_interval_ms / 1000.0 * 1.1


    def compute_logging_timespan(self, max_adv_interval_ms):
        """Compute the logging timespan from max_adv_interval_ms.

        The logging timespan is the time needed to record btmon log.

        @param max_adv_interval_ms: max advertising interval in milliseconds.

        @returns: logging_timespan in seconds.

        """
        duration = self.compute_duration(max_adv_interval_ms)
        logging_timespan = max(self.count_advertisements * duration, 1)
        return logging_timespan


    @test_retry_and_log(False)
    def test_check_duration_and_intervals(self, min_adv_interval_ms,
                                          max_adv_interval_ms,
                                          number_advertisements):
        """Verify that every advertisements are scheduled according to the
        duration and intervals.

        An advertisement would be scheduled at the time span of
             duration * number_advertisements

        @param min_adv_interval_ms: min advertising interval in milliseconds.
        @param max_adv_interval_ms: max advertising interval in milliseconds.
        @param number_advertisements: the number of existing advertisements

        @returns: True if all advertisements are scheduled based on the
                duration and intervals.

        """


        def within_tolerance(expected, actual, max_error=0.1):
            """Determine if the percent error is within specified tolerance.

            @param expected: The expected value.
            @param actual: The actual (measured) value.
            @param max_error: The maximum percent error acceptable.

            @returns: True if the percent error is less than or equal to
                      max_error.
            """
            return abs(expected - actual) / abs(expected) <= max_error


        start_str = 'Set Advertising Intervals:'
        search_strings = ['HCI Command: LE Set Advertising Data', 'Company']
        search_str = '|'.join(search_strings)

        contents = self.bluetooth_le_facade.btmon_get(search_str=search_str,
                                                      start_str=start_str)

        # Company string looks like
        #   Company: not assigned (65283)
        company_pattern = re.compile('Company:.*\((\d*)\)')

        # The string with timestamp looks like
        #   < HCI Command: LE Set Advertising Data (0x08|0x0008) [hci0] 3.799236
        set_adv_time_str = 'LE Set Advertising Data.*\[hci\d\].*(\d+\.\d+)'
        set_adv_time_pattern = re.compile(set_adv_time_str)

        adv_timestamps = {}
        timestamp = None
        manufacturer_id = None
        for line in contents:
            result = set_adv_time_pattern.search(line)
            if result:
                timestamp = float(result.group(1))

            result = company_pattern.search(line)
            if result:
                manufacturer_id = '0x%04x' % int(result.group(1))

            if timestamp and manufacturer_id:
                if manufacturer_id not in adv_timestamps:
                    adv_timestamps[manufacturer_id] = []
                adv_timestamps[manufacturer_id].append(timestamp)
                timestamp = None
                manufacturer_id = None

        duration = self.compute_duration(max_adv_interval_ms)
        expected_timespan = duration * number_advertisements

        check_duration = True
        for manufacturer_id, values in six.iteritems(adv_timestamps):
            logging.debug('manufacturer_id %s: %s', manufacturer_id, values)
            timespans = [values[i] - values[i - 1]
                         for i in range(1, len(values))]
            errors = [timespans[i] for i in range(len(timespans))
                      if not within_tolerance(expected_timespan, timespans[i])]
            logging.debug('timespans: %s', timespans)
            logging.debug('errors: %s', errors)
            if bool(errors):
                check_duration = False

        # Verify that the advertising intervals are also correct.
        min_adv_interval_ms_found, max_adv_interval_ms_found = (
                self._verify_advertising_intervals(min_adv_interval_ms,
                                                   max_adv_interval_ms))

        self.results = {
                'check_duration': check_duration,
                'max_adv_interval_ms_found': max_adv_interval_ms_found,
                'max_adv_interval_ms_found': max_adv_interval_ms_found,
        }
        return all(self.results.values())


    def _get_min_max_intervals_strings(self, min_adv_interval_ms,
                                       max_adv_interval_ms):
        """Get the min and max advertising intervals strings shown in btmon.

        Advertising intervals shown in the btmon log look like
            Min advertising interval: 1280.000 msec (0x0800)
            Max advertising interval: 1280.000 msec (0x0800)

        @param min_adv_interval_ms: min advertising interval in milliseconds.
        @param max_adv_interval_ms: max advertising interval in milliseconds.

        @returns: the min and max intervals strings.

        """
        min_str = ('Min advertising interval: %.3f msec (0x%04x)' %
                   (min_adv_interval_ms,
                    min_adv_interval_ms / self.ADVERTISING_INTERVAL_UNIT))
        logging.debug('min_adv_interval_ms: %s', min_str)

        max_str = ('Max advertising interval: %.3f msec (0x%04x)' %
                   (max_adv_interval_ms,
                    max_adv_interval_ms / self.ADVERTISING_INTERVAL_UNIT))
        logging.debug('max_adv_interval_ms: %s', max_str)

        return (min_str, max_str)


    def _verify_advertising_intervals(self, min_adv_interval_ms,
                                      max_adv_interval_ms):
        """Verify min and max advertising intervals.

        Advertising intervals look like
            Min advertising interval: 1280.000 msec (0x0800)
            Max advertising interval: 1280.000 msec (0x0800)

        @param min_adv_interval_ms: min advertising interval in milliseconds.
        @param max_adv_interval_ms: max advertising interval in milliseconds.

        @returns: a tuple of (True, True) if both min and max advertising
            intervals could be found. Otherwise, the corresponding element
            in the tuple if False.

        """
        min_str, max_str = self._get_min_max_intervals_strings(
                min_adv_interval_ms, max_adv_interval_ms)

        min_adv_interval_ms_found = self.bluetooth_le_facade.btmon_find(min_str)
        max_adv_interval_ms_found = self.bluetooth_le_facade.btmon_find(max_str)

        return min_adv_interval_ms_found, max_adv_interval_ms_found


    def _verify_scan_response_data(self, adv_data):
        """Verify advertisement's scan response data is correct

        Unlike the other fixed advertising fields, Scan Response Data is set
        in a tag-value data format. This function helps verify the data format
        for specific tag values to ensure scan response was propagated correctly

        @param adv_data: Dictionary defining advertising fields to be registered
                with bluetoothd daemon's RegisterAdvertisement interface

        @returns: True if all Registered Scan Response tags were located in
                btmon trace, False otherwise
        """

        scan_rsp = adv_data.get('ScanResponseData')
        if not scan_rsp:
            return True

        for tag, data in scan_rsp.items():
            # Validate 16 bit Service Data tag
            if int(tag, 16) == 0x16:
                # First two bytes of data are endian-corrected UUID, followed
                # by service data
                uuid = '%x%x' % (data[1], data[0])
                data_str = ''.join(
                        ['%02x' % data[i] for i in range(2, len(data))])

                # Service data has the following format in btmon trace:
                # Service Data (UUID 0xfef3): 01020304
                search_str = 'Service Data (UUID 0x{}): {}'.format(
                        uuid, data_str)

                # Fail if data can't be located in btmon trace
                if not self.bluetooth_le_facade.btmon_find(search_str):
                    return False

        return True

    def test_advertising_flags(self, flag_strs=[]):
        """Verify that advertising flags are set in registered advertisement

        Each flag has a specific descriptor that appears in btmon trace. This
        simple checker validates that the desired flag descriptors appear in
        btmon trace when the advertisement was registered.

        @param flag_strs: Flag string descriptors expected in btmon trace

        #returns: True if all flag descriptors were located, False otherwise
        """

        for flag_str in flag_strs:
            if not self.bluetooth_le_facade.btmon_find(flag_str):
                logging.info(
                        'Flag descriptor not located: {}'.format(flag_str))
                return False

        return True

    def ext_adv_enabled(self):
        """ Check if platform supports extended advertising

        @returns True if extended advertising is supported, else False
        """
        platform = self.get_base_platform_name()
        return platform in EXT_ADV_MODELS


    @test_retry_and_log(False)
    def test_register_advertisement(self, advertisement_data, instance_id,
                                    min_adv_interval_ms, max_adv_interval_ms):
        """Verify that an advertisement is registered correctly.

        This test verifies the following data:
        - advertisement added
        - manufacturer data
        - service UUIDs
        - service data
        - advertising intervals
        - advertising enabled

        @param advertisement_data: the data of an advertisement to register.
        @param instance_id: the instance id which starts at 1.
        @param min_adv_interval_ms: min_adv_interval in milliseconds.
        @param max_adv_interval_ms: max_adv_interval in milliseconds.

        @returns: True if the advertisement is registered correctly.
                  False otherwise.

        """
        # When registering a new advertisement, it is possible that another
        # instance is advertising. It may need to wait for all other
        # advertisements to complete advertising once.
        self.count_advertisements += 1
        logging_timespan = self.compute_logging_timespan(max_adv_interval_ms)
        self._get_btmon_log(
                lambda: self.bluetooth_le_facade.register_advertisement(
                        advertisement_data),
                logging_timespan=logging_timespan)

        # Verify that a new advertisement is added.
        advertisement_added = (
                self.bluetooth_le_facade.btmon_find('Advertising Added') and
                self.bluetooth_le_facade.btmon_find('Instance: %d' %
                                                    instance_id))

        # Verify that the manufacturer data could be found.
        manufacturer_data = advertisement_data.get('ManufacturerData', '')
        manufacturer_data_found = True
        for manufacturer_id in manufacturer_data:
            # The 'not assigned' text below means the manufacturer id
            # is not actually assigned to any real manufacturer.
            # For real 16-bit manufacturer UUIDs, refer to
            #  https://www.bluetooth.com/specifications/assigned-numbers/16-bit-UUIDs-for-Members
            manufacturer_data_found = self.bluetooth_le_facade.btmon_find(
                    'Company: not assigned (%d)' % int(manufacturer_id, 16))

        # Verify that all service UUIDs could be found.
        service_uuids_found = True
        for uuid in advertisement_data.get('ServiceUUIDs', []):
            # Service UUIDs looks like ['0x180D', '0x180F']
            #   Heart Rate (0x180D)
            #   Battery Service (0x180F)
            # For actual 16-bit service UUIDs, refer to
            #   https://www.bluetooth.com/specifications/gatt/services
            if not self.bluetooth_le_facade.btmon_find('0x%s' % uuid):
                service_uuids_found = False
                break

        # Verify service data.
        service_data_found = True
        for uuid, data in advertisement_data.get('ServiceData', {}).items():
            # A service data looks like
            #   Service Data (UUID 0x9999): 0001020304
            # while uuid is '9999' and data is [0x00, 0x01, 0x02, 0x03, 0x04]
            data_str = ''.join(['%02x' % n for n in data])
            if not self.bluetooth_le_facade.btmon_find(
                    'Service Data (UUID 0x%s): %s' % (uuid, data_str)):
                service_data_found = False
                break

        # Broadcast advertisements are overwritten in some kernel versions to
        # be more aggressive. Verify that the advertising intervals are correct
        # if this mode is not used
        if advertisement_data.get('Type') != 'broadcast':
            min_adv_interval_ms_found, max_adv_interval_ms_found = (
                    self._verify_advertising_intervals(min_adv_interval_ms,
                                                       max_adv_interval_ms))

        else:
            min_adv_interval_ms_found = True
            max_adv_interval_ms_found = True

        scan_rsp_correct = self._verify_scan_response_data(advertisement_data)

        # Verify advertising is enabled.
        advertising_enabled = self.bluetooth_le_facade.btmon_find(
                'Advertising: Enabled (0x01)')

        self.results = {
                'advertisement_added': advertisement_added,
                'manufacturer_data_found': manufacturer_data_found,
                'service_uuids_found': service_uuids_found,
                'service_data_found': service_data_found,
                'min_adv_interval_ms_found': min_adv_interval_ms_found,
                'max_adv_interval_ms_found': max_adv_interval_ms_found,
                'scan_rsp_correct': scan_rsp_correct,
                'advertising_enabled': advertising_enabled,
        }
        return all(self.results.values())


    @test_retry_and_log(False)
    def test_fail_to_register_advertisement(self, advertisement_data,
                                            min_adv_interval_ms,
                                            max_adv_interval_ms):
        """Verify that failure is incurred when max advertisements are reached.

        This test verifies that a registration failure is incurred when
        max advertisements are reached. The error message looks like:

            org.bluez.Error.Failed: Maximum advertisements reached

        @param advertisement_data: the advertisement to register.
        @param min_adv_interval_ms: min_adv_interval in milliseconds.
        @param max_adv_interval_ms: max_adv_interval in milliseconds.

        @returns: True if the error message is received correctly.
                  False otherwise.

        """
        logging_timespan = self.compute_logging_timespan(max_adv_interval_ms)
        self._get_btmon_log(
                lambda: self.bluetooth_le_facade.register_advertisement(
                        advertisement_data),
                logging_timespan=logging_timespan)

        # Verify that it failed to register advertisement due to the fact
        # that max advertisements are reached.
        failed_to_register_error = (self.ERROR_FAILED_TO_REGISTER_ADVERTISEMENT
                                    in self.advertising_msg)

        # Verify that no new advertisement is added.
        advertisement_not_added = not self.bluetooth_le_facade.btmon_find(
                'Advertising Added:')

        self.results = {
                'failed_to_register_error': failed_to_register_error,
                'advertisement_not_added': advertisement_not_added,
        }

        # If the registration fails and extended advertising is available,
        # there will be no events in btmon. Therefore, we only run this part of
        # the test if extended advertising is not available, indicating that
        # software advertisement rotation is being used.
        if not self.ext_adv_enabled():
            # Verify that the advertising intervals are correct.
            min_adv_interval_ms_found, max_adv_interval_ms_found = (
                    self._verify_advertising_intervals(min_adv_interval_ms,
                                                       max_adv_interval_ms))

            # Verify advertising remains enabled.
            advertising_enabled = self.bluetooth_le_facade.btmon_find(
                    'Advertising: Enabled (0x01)')

            self.results.update({
                'min_adv_interval_ms_found': min_adv_interval_ms_found,
                'max_adv_interval_ms_found': max_adv_interval_ms_found,
                'advertising_enabled': advertising_enabled,
            })

        return all(self.results.values())


    @test_retry_and_log(False)
    def test_unregister_advertisement(self, advertisement_data, instance_id,
                                      advertising_disabled):
        """Verify that an advertisement is unregistered correctly.

        This test verifies the following data:
        - advertisement removed
        - advertising status: enabled if there are advertisements left;
                              disabled otherwise.

        @param advertisement_data: the data of an advertisement to unregister.
        @param instance_id: the instance id of the advertisement to remove.
        @param advertising_disabled: is advertising disabled? This happens
                only when all advertisements are removed.

        @returns: True if the advertisement is unregistered correctly.
                  False otherwise.

        """
        self.count_advertisements -= 1
        self._get_btmon_log(
                lambda: self.bluetooth_le_facade.unregister_advertisement(
                        advertisement_data))

        # Verify that the advertisement is removed.
        advertisement_removed = (
                self.bluetooth_le_facade.btmon_find('Advertising Removed') and
                self.bluetooth_le_facade.btmon_find('Instance: %d' %
                                                    instance_id))

        # If advertising_disabled is True, there should be no log like
        #       'Advertising: Enabled (0x01)'
        # If advertising_disabled is False, there should be log like
        #       'Advertising: Enabled (0x01)'

        # Only need to check advertising status when the last advertisement
        # is removed. For any other advertisements prior to the last one,
        # we may or may not observe 'Advertising: Enabled (0x01)' message.
        # Hence, the test would become flaky if we insist to see that message.
        # A possible workaround is to sleep for a while and then check the
        # message. The drawback is that we may need to wait up to 10 seconds
        # if the advertising duration and intervals are long.
        # In a test case, we always run test_check_duration_and_intervals()
        # to check if advertising duration and intervals are correct after
        # un-registering one or all advertisements, it is safe to do so.
        advertising_enabled_found = self.bluetooth_le_facade.btmon_find(
                'Advertising: Enabled (0x01)')
        advertising_disabled_found = self.bluetooth_le_facade.btmon_find(
                'Advertising: Disabled (0x00)')
        advertising_status_correct = not advertising_disabled or (
                advertising_disabled_found and not advertising_enabled_found)

        self.results = {
                'advertisement_removed': advertisement_removed,
                'advertising_status_correct': advertising_status_correct,
        }
        return all(self.results.values())


    @test_retry_and_log(False)
    def test_set_advertising_intervals(self, min_adv_interval_ms,
                                       max_adv_interval_ms):
        """Verify that new advertising intervals are set correctly.

        Note that setting advertising intervals does not enable/disable
        advertising. Hence, there is no need to check the advertising
        status.

        @param min_adv_interval_ms: the min advertising interval in ms.
        @param max_adv_interval_ms: the max advertising interval in ms.

        @returns: True if the new advertising intervals are correct.
                  False otherwise.

        """
        self._get_btmon_log(
                lambda: self.bluetooth_le_facade.set_advertising_intervals(
                        min_adv_interval_ms, max_adv_interval_ms))

        # Verify the new advertising intervals.
        # With intervals of 200 ms and 200 ms, the log looks like
        #   bluetoothd: Set Advertising Intervals: 0x0140, 0x0140
        txt = 'bluetoothd: Set Advertising Intervals: 0x%04x, 0x%04x'
        adv_intervals_found = self.bluetooth_le_facade.btmon_find(
                txt % (self.convert_to_adv_jiffies(min_adv_interval_ms),
                       self.convert_to_adv_jiffies(max_adv_interval_ms)))

        self.results = {'adv_intervals_found': adv_intervals_found}
        return all(self.results.values())


    @test_retry_and_log(False)
    def test_fail_to_set_advertising_intervals(
            self, invalid_min_adv_interval_ms, invalid_max_adv_interval_ms,
            orig_min_adv_interval_ms, orig_max_adv_interval_ms):
        """Verify that setting invalid advertising intervals results in error.

        If invalid min/max advertising intervals are given, it would incur
        the error: 'org.bluez.Error.InvalidArguments: Invalid arguments'.
        Note that valid advertising intervals fall between 20 ms and 10,240 ms.

        @param invalid_min_adv_interval_ms: the invalid min advertising interval
                in ms.
        @param invalid_max_adv_interval_ms: the invalid max advertising interval
                in ms.
        @param orig_min_adv_interval_ms: the original min advertising interval
                in ms.
        @param orig_max_adv_interval_ms: the original max advertising interval
                in ms.

        @returns: True if it fails to set invalid advertising intervals.
                  False otherwise.

        """
        self._get_btmon_log(
                lambda: self.bluetooth_le_facade.set_advertising_intervals(
                        invalid_min_adv_interval_ms,
                        invalid_max_adv_interval_ms))

        # Verify that the invalid error is observed in the dbus error callback
        # message.
        invalid_intervals_error = (self.ERROR_INVALID_ADVERTISING_INTERVALS in
                                   self.advertising_msg)

        # Verify that the min/max advertising intervals remain the same
        # after setting the invalid advertising intervals.
        #
        # In btmon log, we would see the following message first.
        #    bluetoothd: Set Advertising Intervals: 0x0010, 0x0010
        # And then, we should check if "Min advertising interval" and
        # "Max advertising interval" remain the same.
        start_str = 'bluetoothd: Set Advertising Intervals: 0x%04x, 0x%04x' % (
                self.convert_to_adv_jiffies(invalid_min_adv_interval_ms),
                self.convert_to_adv_jiffies(invalid_max_adv_interval_ms))

        search_strings = ['Min advertising interval:',
                          'Max advertising interval:']
        search_str = '|'.join(search_strings)

        contents = self.bluetooth_le_facade.btmon_get(search_str=search_str,
                                                      start_str=start_str)

        # The min/max advertising intervals of all advertisements should remain
        # the same as the previous valid ones.
        min_max_str = '[Min|Max] advertising interval: (\d*\.\d*) msec'
        min_max_pattern = re.compile(min_max_str)
        correct_orig_min_adv_interval = True
        correct_orig_max_adv_interval = True
        for line in contents:
            result = min_max_pattern.search(line)
            if result:
                interval = float(result.group(1))
                if 'Min' in line and interval != orig_min_adv_interval_ms:
                    correct_orig_min_adv_interval = False
                elif 'Max' in line and interval != orig_max_adv_interval_ms:
                    correct_orig_max_adv_interval = False

        self.results = {
                'invalid_intervals_error': invalid_intervals_error,
                'correct_orig_min_adv_interval': correct_orig_min_adv_interval,
                'correct_orig_max_adv_interval': correct_orig_max_adv_interval}

        return all(self.results.values())


    @test_retry_and_log(False)
    def test_check_advertising_intervals(self, min_adv_interval_ms,
                                         max_adv_interval_ms):
        """Verify that the advertising intervals are as expected.

        @param min_adv_interval_ms: the min advertising interval in ms.
        @param max_adv_interval_ms: the max advertising interval in ms.

        @returns: True if the advertising intervals are correct.
                  False otherwise.

        """
        self._get_btmon_log(None)

        # Verify that the advertising intervals are correct.
        min_adv_interval_ms_found, max_adv_interval_ms_found = (
                self._verify_advertising_intervals(min_adv_interval_ms,
                                                   max_adv_interval_ms))

        self.results = {
                'min_adv_interval_ms_found': min_adv_interval_ms_found,
                'max_adv_interval_ms_found': max_adv_interval_ms_found,
        }
        return all(self.results.values())


    @test_retry_and_log(False)
    def test_reset_advertising(self, instance_ids=[]):
        """Verify that advertising is reset correctly.

        Note that reset advertising would set advertising intervals to
        the default values. However, we would not be able to observe
        the values change until new advertisements are registered.
        Therefore, it is required that a test_register_advertisement()
        test is conducted after this test.

        If instance_ids is [], all advertisements would still be removed
        if there are any. However, no need to check 'Advertising Removed'
        in btmon log since we may or may not be able to observe the message.
        This feature is needed if this test is invoked as the first one in
        a test case to reset advertising. In this situation, this test does
        not know how many advertisements exist.

        @param instance_ids: the list of instance IDs that should be removed.

        @returns: True if advertising is reset correctly.
                  False otherwise.

        """
        self.count_advertisements = 0
        self._get_btmon_log(
                lambda: self.bluetooth_le_facade.reset_advertising())

        # Verify that every advertisement is removed. When an advertisement
        # with instance id 1 is removed, the log looks like
        #   Advertising Removed
        #       instance: 1
        if len(instance_ids) > 0:
            advertisement_removed = self.bluetooth_le_facade.btmon_find(
                    'Advertising Removed')
            if advertisement_removed:
                for instance_id in instance_ids:
                    txt = 'Instance: %d' % instance_id
                    if not self.bluetooth_le_facade.btmon_find(txt):
                        advertisement_removed = False
                        break
        else:
            advertisement_removed = True

        if not advertisement_removed:
            logging.error('Failed to remove advertisement')

        # Verify that "Reset Advertising Intervals" command has been issued.
        reset_advertising_intervals = self.bluetooth_le_facade.btmon_find(
                'bluetoothd: Reset Advertising Intervals')

        # Verify the advertising is disabled.
        advertising_disabled_observied = self.bluetooth_le_facade.btmon_find(
                'Advertising: Disabled')
        # If there are no existing advertisements, we may not observe
        # 'Advertising: Disabled'.
        advertising_disabled = (instance_ids == [] or
                                advertising_disabled_observied)

        self.results = {
                'advertisement_removed': advertisement_removed,
                'reset_advertising_intervals': reset_advertising_intervals,
                'advertising_disabled': advertising_disabled,
        }
        return all(self.results.values())


    @test_retry_and_log(False)
    def test_receive_advertisement(self, address=None, UUID=None, timeout=10):
        """Verifies that we receive an advertisement with specific contents

        Since test_discover_device only uses the existence of a device dbus path
        to indicate when a device is discovered, it is not adequate if we want
        to verify that we have received an advertisement from a device. This
        test monitors btmon around a discovery instance and searches for the
        relevant advertising report.

        @param address: String address of peer
        @param UUID: String of hex data
        @param timeout: seconds to listen for traffic

        @returns True if report was located, otherwise False
        """

        def _discover_devices():
            self.test_start_discovery()
            time.sleep(timeout)
            self.test_stop_discovery()

        # Run discovery, record btmon log
        self._get_btmon_log(_discover_devices)

        # Grab all logs received
        btmon_log = '\n'.join(self.bluetooth_le_facade.btmon_get('', ''))

        desired_strs = []

        if address is not None:
            desired_strs.append('Address: {}'.format(address))

        if UUID is not None:
            desired_strs.append('({})'.format(UUID))

        # Split btmon events by HCI and MGMT delimiters
        event_delimiter = '|'.join(['@ MGMT', '> HCI', '< HCI'])
        btmon_events = re.split(event_delimiter, btmon_log)

        features_located = False

        for event_str in btmon_events:
            if 'Advertising Report' not in event_str:
                continue

            for desired_str in desired_strs:
                if desired_str not in event_str:
                    break

            else:
                features_located = True

        self.results = {
                'features_located': features_located,
        }
        return all(self.results.values())


    def add_device(self, address, address_type, action):
        """Add a device to the Kernel action list."""
        return self.bluetooth_facade.add_device(address, address_type, action)


    def remove_device(self, address, address_type):
        """Remove a device from the Kernel action list."""
        return self.bluetooth_facade.remove_device(address,address_type)


    def read_supported_commands(self):
        """Read the set of supported commands from the Kernel."""
        return self.bluetooth_facade.read_supported_commands()


    def read_info(self):
        """Read the adapter information from the Kernel."""
        return self.bluetooth_facade.read_info()


    def get_adapter_properties(self):
        """Read the adapter properties from the Bluetooth Daemon."""
        return self.bluetooth_facade.get_adapter_properties()


    def get_dev_info(self):
        """Read raw HCI device information."""
        return self.bluetooth_facade.get_dev_info()

    def log_settings(self, msg, settings):
        """function convert MGMT_OP_READ_INFO settings to string

        @param msg: string to include in output
        @param settings: bitstring returned by MGMT_OP_READ_INFO
        @return : List of strings indicating different settings
        """
        strs = []
        if settings & bluetooth_socket.MGMT_SETTING_POWERED:
            strs.append("POWERED")
        if settings & bluetooth_socket.MGMT_SETTING_CONNECTABLE:
            strs.append("CONNECTABLE")
        if settings & bluetooth_socket.MGMT_SETTING_FAST_CONNECTABLE:
            strs.append("FAST-CONNECTABLE")
        if settings & bluetooth_socket.MGMT_SETTING_DISCOVERABLE:
            strs.append("DISCOVERABLE")
        if settings & bluetooth_socket.MGMT_SETTING_PAIRABLE:
            strs.append("PAIRABLE")
        if settings & bluetooth_socket.MGMT_SETTING_LINK_SECURITY:
            strs.append("LINK-SECURITY")
        if settings & bluetooth_socket.MGMT_SETTING_SSP:
            strs.append("SSP")
        if settings & bluetooth_socket.MGMT_SETTING_BREDR:
            strs.append("BR/EDR")
        if settings & bluetooth_socket.MGMT_SETTING_HS:
            strs.append("HS")
        if settings & bluetooth_socket.MGMT_SETTING_LE:
            strs.append("LE")
        logging.debug('%s : %s', msg, " ".join(strs))
        return strs

    def log_flags(self, msg, flags):
        """Function to convert HCI state configuration to a string

        @param msg: string to include in output
        @param settings: bitstring returned by get_dev_info
        @return : List of strings indicating different flags
        """
        strs = []
        if flags & bluetooth_socket.HCI_UP:
            strs.append("UP")
        else:
            strs.append("DOWN")
        if flags & bluetooth_socket.HCI_INIT:
            strs.append("INIT")
        if flags & bluetooth_socket.HCI_RUNNING:
            strs.append("RUNNING")
        if flags & bluetooth_socket.HCI_PSCAN:
            strs.append("PSCAN")
        if flags & bluetooth_socket.HCI_ISCAN:
            strs.append("ISCAN")
        if flags & bluetooth_socket.HCI_AUTH:
            strs.append("AUTH")
        if flags & bluetooth_socket.HCI_ENCRYPT:
            strs.append("ENCRYPT")
        if flags & bluetooth_socket.HCI_INQUIRY:
            strs.append("INQUIRY")
        if flags & bluetooth_socket.HCI_RAW:
            strs.append("RAW")
        logging.debug('%s [HCI]: %s', msg, " ".join(strs))
        return strs


    @test_retry_and_log(False)
    def test_service_resolved(self, address):
        """Test that the services under device address can be resolved

        @param address: MAC address of a device

        @returns: True if the ServicesResolved property is changed before
                 timeout, False otherwise.

        """
        is_resolved_func = self.bluetooth_facade.device_services_resolved
        return self._wait_for_condition(lambda : is_resolved_func(address),\
                                        method_name())


    @test_retry_and_log(False)
    def test_gatt_browse(self, address):
        """Test that the GATT client can get the attributes correctly

        @param address: MAC address of a device

        @returns: True if the attribute map received by GATT client is the same
                  as expected. False otherwise.

        """

        gatt_client_facade = GATT_ClientFacade(self.bluetooth_facade)
        actual_app = gatt_client_facade.browse(address)
        expected_app = GATT_HIDApplication()
        diff = GATT_Application.diff(actual_app, expected_app)

        self.result = {
            'actural_result': actual_app,
            'expected_result': expected_app
        }

        gatt_attribute_hierarchy = ['Device', 'Service', 'Characteristic',
                                    'Descriptor']
        # Remove any difference in object path
        for parent, child in zip(gatt_attribute_hierarchy,
                                 gatt_attribute_hierarchy[1:]):
            pattern = re.compile('^%s .* is different in %s' % (child, parent))
            for diff_str in diff[::]:
                if pattern.search(diff_str):
                    diff.remove(diff_str)

        if len(diff) != 0:
            logging.error('Application Diff: %s', diff)
            return False
        return True


    def _record_input_events(self, device, gesture, address=None):
        """Record the input events.

        @param device: the bluetooth HID device.
        @param gesture: the gesture method to perform.

        @returns: the input events received on the DUT.

        """
        self.input_facade.initialize_input_recorder(device.name, uniq=address)
        self.input_facade.start_input_recorder(device.name)
        time.sleep(self.HID_REPORT_SLEEP_SECS)
        gesture()
        time.sleep(self.HID_REPORT_SLEEP_SECS)
        self.input_facade.stop_input_recorder(device.name)
        time.sleep(self.HID_REPORT_SLEEP_SECS)
        event_values = self.input_facade.get_input_events(device.name)
        events = [Event(*ev) for ev in event_values]
        return events


    # -------------------------------------------------------------------
    # Bluetooth mouse related tests
    # -------------------------------------------------------------------


    def _test_mouse_click(self, device, button):
        """Test that the mouse click events could be received correctly.

        @param device: the meta device containing a bluetooth HID device
        @param button: which button to test, 'LEFT' or 'RIGHT'

        @returns: True if the report received by the host matches the
                  expected one. False otherwise.

        """
        if button == 'LEFT':
            gesture = device.LeftClick
        elif button == 'RIGHT':
            gesture = device.RightClick
        else:
            raise error.TestError('Button (%s) is not valid.' % button)

        actual_events = self._record_input_events(device,
                                                  gesture,
                                                  address=device.address)

        linux_input_button = {'LEFT': BTN_LEFT, 'RIGHT': BTN_RIGHT}
        expected_events = [
                # Button down
                recorder.MSC_SCAN_BTN_EVENT[button],
                Event(EV_KEY, linux_input_button[button], 1),
                recorder.SYN_EVENT,
                # Button up
                recorder.MSC_SCAN_BTN_EVENT[button],
                Event(EV_KEY, linux_input_button[button], 0),
                recorder.SYN_EVENT]

        self.results = {
                'actual_events': list(map(str, actual_events)),
                'expected_events': list(map(str, expected_events))}
        return actual_events == expected_events


    @test_retry_and_log
    def test_mouse_left_click(self, device):
        """Test that the mouse left click events could be received correctly.

        @param device: the meta device containing a bluetooth HID device

        @returns: True if the report received by the host matches the
                  expected one. False otherwise.

        """
        return self._test_mouse_click(device, 'LEFT')


    @test_retry_and_log
    def test_mouse_right_click(self, device):
        """Test that the mouse right click events could be received correctly.

        @param device: the meta device containing a bluetooth HID device

        @returns: True if the report received by the host matches the
                  expected one. False otherwise.

        """
        return self._test_mouse_click(device, 'RIGHT')


    def _test_mouse_move(self, device, delta_x=0, delta_y=0):
        """Test that the mouse move events could be received correctly.

        @param device: the meta device containing a bluetooth HID device
        @param delta_x: the distance to move cursor in x axis
        @param delta_y: the distance to move cursor in y axis

        @returns: True if the report received by the host matches the
                  expected one. False otherwise.

        """
        gesture = lambda: device.Move(delta_x, delta_y)
        actual_events = self._record_input_events(device,
                                                  gesture,
                                                  address=device.address)

        events_x = [Event(EV_REL, REL_X, delta_x)] if delta_x else []
        events_y = [Event(EV_REL, REL_Y, delta_y)] if delta_y else []
        expected_events = events_x + events_y + [recorder.SYN_EVENT]

        self.results = {
                'actual_events': list(map(str, actual_events)),
                'expected_events': list(map(str, expected_events))}
        return actual_events == expected_events


    @test_retry_and_log
    def test_mouse_move_in_x(self, device, delta_x):
        """Test that the mouse move events in x could be received correctly.

        @param device: the meta device containing a bluetooth HID device
        @param delta_x: the distance to move cursor in x axis

        @returns: True if the report received by the host matches the
                  expected one. False otherwise.

        """
        return self._test_mouse_move(device, delta_x=delta_x)


    @test_retry_and_log
    def test_mouse_move_in_y(self, device, delta_y):
        """Test that the mouse move events in y could be received correctly.

        @param device: the meta device containing a bluetooth HID device
        @param delta_y: the distance to move cursor in y axis

        @returns: True if the report received by the host matches the
                  expected one. False otherwise.

        """
        return self._test_mouse_move(device, delta_y=delta_y)


    @test_retry_and_log
    def test_mouse_move_in_xy(self, device, delta_x, delta_y):
        """Test that the mouse move events could be received correctly.

        @param device: the meta device containing a bluetooth HID device
        @param delta_x: the distance to move cursor in x axis
        @param delta_y: the distance to move cursor in y axis

        @returns: True if the report received by the host matches the
                  expected one. False otherwise.

        """
        return self._test_mouse_move(device, delta_x=delta_x, delta_y=delta_y)


    def _test_mouse_scroll(self, device, units):
        """Test that the mouse wheel events could be received correctly.

        @param device: the meta device containing a bluetooth HID device
        @param units: the units to scroll in y axis

        @returns: True if the report received by the host matches the
                  expected one. False otherwise.

        """
        gesture = lambda: device.Scroll(units)
        recorded_events = self._record_input_events(device,
                                                    gesture,
                                                    address=device.address)

        # Since high-speed scrolling events are inserted after they are passed
        # through bluetooth module, we ignore these events since they are
        # irrelevant for us
        scroll_events = [ev for ev in recorded_events
                            if ev.code != REL_WHEEL_HI_RES]

        expected_events = [Event(EV_REL, REL_WHEEL, units), recorder.SYN_EVENT]
        self.results = {
                'scroll_events': list(map(str, scroll_events)),
                'expected_events': list(map(str, expected_events))}
        return scroll_events == expected_events


    @test_retry_and_log
    def test_mouse_scroll_down(self, device, delta_y):
        """Test that the mouse wheel events could be received correctly.

        @param device: the meta device containing a bluetooth HID device
        @param delta_y: the units to scroll down in y axis;
                        should be a postive value

        @returns: True if the report received by the host matches the
                  expected one. False otherwise.

        """
        if delta_y > 0:
            return self._test_mouse_scroll(device, delta_y)
        else:
            raise error.TestError('delta_y (%d) should be a positive value',
                                  delta_y)


    @test_retry_and_log
    def test_mouse_scroll_up(self, device, delta_y):
        """Test that the mouse wheel events could be received correctly.

        @param device: the meta device containing a bluetooth HID device
        @param delta_y: the units to scroll up in y axis;
                        should be a postive value

        @returns: True if the report received by the host matches the
                  expected one. False otherwise.

        """
        if delta_y > 0:
            return self._test_mouse_scroll(device, -delta_y)
        else:
            raise error.TestError('delta_y (%d) should be a positive value',
                                  delta_y)


    @test_retry_and_log
    def test_mouse_click_and_drag(self, device, delta_x, delta_y):
        """Test that the mouse click-and-drag events could be received
        correctly.

        @param device: the meta device containing a bluetooth HID device
        @param delta_x: the distance to drag in x axis
        @param delta_y: the distance to drag in y axis

        @returns: True if the report received by the host matches the
                  expected one. False otherwise.

        """
        gesture = lambda: device.ClickAndDrag(delta_x, delta_y)
        actual_events = self._record_input_events(device,
                                                  gesture,
                                                  address=device.address)

        button = 'LEFT'
        expected_events = (
                [# Button down
                 recorder.MSC_SCAN_BTN_EVENT[button],
                 Event(EV_KEY, BTN_LEFT, 1),
                 recorder.SYN_EVENT] +
                # cursor movement in x and y
                ([Event(EV_REL, REL_X, delta_x)] if delta_x else []) +
                ([Event(EV_REL, REL_Y, delta_y)] if delta_y else []) +
                [recorder.SYN_EVENT] +
                # Button up
                [recorder.MSC_SCAN_BTN_EVENT[button],
                 Event(EV_KEY, BTN_LEFT, 0),
                 recorder.SYN_EVENT])

        self.results = {
                'actual_events': list(map(str, actual_events)),
                'expected_events': list(map(str, expected_events))}
        return actual_events == expected_events


    # -------------------------------------------------------------------
    # Bluetooth keyboard related tests
    # -------------------------------------------------------------------

    # TODO may be deprecated as stated in b:140515628
    @test_retry_and_log
    def test_keyboard_input_from_string(self, device, string_to_send):
        """Test that the keyboard's key events could be received correctly.

        @param device: the meta device containing a bluetooth HID device
        @param string_to_send: the set of keys that will be pressed one-by-one

        @returns: True if the report received by the host matches the
                  expected one. False otherwise.

        """

        gesture = lambda: device.KeyboardSendString(string_to_send)

        actual_events = self._record_input_events(device,
                                                  gesture,
                                                  address=device.address)

        resulting_string = bluetooth_test_utils.reconstruct_string(
                           actual_events)

        return string_to_send == resulting_string


    @test_retry_and_log
    def test_keyboard_input_from_trace(self, device, trace_name):
        """ Tests that keyboard events can be transmitted and received correctly

        @param device: the meta device containing a bluetooth HID device
        @param trace_name: string name for keyboard activity trace to be used
                           in the test i.e. "simple_text"

        @returns: true if the recorded output matches the expected output
                  false otherwise
        """
        length_correct = True
        content_correct = True

        # Read data from trace I/O files
        input_trace = bluetooth_test_utils.parse_trace_file(os.path.join(
                      TRACE_LOCATION, '{}_input.txt'.format(trace_name)))
        output_trace = bluetooth_test_utils.parse_trace_file(os.path.join(
                      TRACE_LOCATION, '{}_output.txt'.format(trace_name)))

        if not input_trace or not output_trace:
            logging.error('Failure in using trace')
            return False

        # Disregard timing data for now
        input_scan_codes = [tup[1] for tup in input_trace]
        predicted_events = [Event(*tup[1]) for tup in output_trace]

        # Create and run this trace as a gesture
        gesture = lambda: device.KeyboardSendTrace(input_scan_codes)
        rec_events = self._record_input_events(device,
                                               gesture,
                                               address=device.address)

        # Filter out any input events that were not from the keyboard
        rec_key_events = [ev for ev in rec_events if ev.type == EV_KEY]

        # Fail if we didn't record the correct number of events
        if len(rec_key_events) != len(input_scan_codes):
            logging.info('Expected {} events, received {}'.format(
                    len(input_scan_codes), len(rec_key_events)))
            length_correct = False

        for idx, predicted in enumerate(predicted_events):
            recorded = rec_key_events[idx]

            if not predicted == recorded:
                content_correct = False
                break

        self.results = {
            'received_events': len(rec_key_events) > 0,
            'length_correct': length_correct,
            'content_correct': content_correct,
        }

        return all(self.results)


    def is_newer_kernel_version(self, version, minimum_version):
        """ Check if given kernel version is newer than unsupported version."""

        return utils.compare_versions(version, minimum_version) >= 0


    def is_supported_kernel_version(self, kernel_version, minimum_version,
                                    msg=None):
        """ Check if kernel version is greater than minimum version.

            Check if given kernel version is greater than or equal to minimum
            version. Raise TEST_NA if given kernel version is lower than the
            minimum version.

            Note: Kernel version may have suffixes, so ensure that minimum
            version should be the smallest version that is permissible.
            Ex: If minimum version is 3.8.11 then 3.8.11-<random> will
            pass the check.

            @param kernel_version: kernel version to be checked as a string
            @param: minimum_version: minimum kernel version requried

            @returns: None

            @raises: TEST_NA if kernel version is not greater than the minimum
                     version
        """

        logging.debug('kernel version is {} minimum version'
                      'is {}'.format(kernel_version,minimum_version))

        if msg is None:
            msg = 'Test not supported on this kernel version'

        if not self.is_newer_kernel_version(kernel_version, minimum_version):
            logging.info('Kernel version check failed: %s', msg)
            raise error.TestNAError(msg)

        logging.debug('Kernel version check passed')


    # -------------------------------------------------------------------
    # Bluetooth AVRCP related test
    # -------------------------------------------------------------------


    @test_retry_and_log
    def test_avrcp_event(self, device, generator, avrcp_event):
        """Tests that AVRCP events can be transmitted and received correctly

        @param device: the meta device containing a Bluetooth AVRCP capable
                       audio device.
        @param generator: the peer device generator/function which trigger
                          the AVRCP event.
        @param avrcp_event: the AVRCP event to test.

        @returns: true if the recorded output matches the expected output
                  false otherwise
        """
        logging.debug('AVRCP Event Test, Event: %s', avrcp_event)
        linux_input_button = {'play': KEY_PLAYCD, 'pause': KEY_PAUSECD,
                              'stop': KEY_STOPCD, 'next': KEY_NEXTSONG,
                              'previous': KEY_PREVIOUSSONG}
        expected_event = [
                # Button down
                Event(EV_KEY, linux_input_button[avrcp_event], 1),
                recorder.SYN_EVENT,
                # Button up
                Event(EV_KEY, linux_input_button[avrcp_event], 0),
                recorder.SYN_EVENT]

        gesture = lambda: generator(avrcp_event)
        actual_event = self._record_input_events(device, gesture)

        return actual_event == expected_event


    # -------------------------------------------------------------------
    # Servod related tests
    # -------------------------------------------------------------------

    @test_retry_and_log
    def test_power_consumption(self, device, max_power_mw):
        """Test the average power consumption."""
        power_mw = device.servod.MeasurePowerConsumption()
        self.results = {'power_mw': power_mw}

        if (power_mw is None):
            logging.error('Failed to measure power consumption')
            return False

        power_mw = float(power_mw)
        logging.info('power consumption (mw): %f (max allowed: %f)',
                     power_mw, max_power_mw)

        return power_mw <= max_power_mw


    @test_retry_and_log
    def test_start_notify(self, object_path, cccd_value):
        """Test that a notification can be started on a characteristic

        @param object_path: the object path of the characteristic.
        @param cccd_value: Possible CCCD values include
               0x00 - inferred from the remote characteristic's properties
               0x01 - notification
               0x02 - indication

        @returns: The test results.

        """
        if object_path is None:
            logging.error('Invalid object path')
            return False

        start_notify = self.bluetooth_facade.start_notify(
            object_path, cccd_value)
        is_notifying = self._wait_for_condition(
            lambda: self.bluetooth_facade.is_notifying(
                object_path), method_name())

        self.results = {
            'start_notify': start_notify,
            'is_notifying': is_notifying}

        return all(self.results.values())


    @test_retry_and_log
    def test_stop_notify(self, object_path):
        """Test that a notification can be stopped on a characteristic

        @param object_path: the object path of the characteristic.

        @returns: The test results.

        """
        if object_path is None:
            logging.error('Invalid object path')
            return False

        stop_notify = self.bluetooth_facade.stop_notify(object_path)
        is_not_notifying = self._wait_for_condition(
            lambda: not self.bluetooth_facade.is_notifying(
                object_path), method_name())

        self.results = {
            'stop_notify': stop_notify,
            'is_not_notifying': is_not_notifying}

        return all(self.results.values())


    @test_retry_and_log(False)
    def test_set_discovery_filter(self, filter):
        """Test set discovery filter"""

        return self.bluetooth_facade.set_discovery_filter(filter)


    @test_retry_and_log(False)
    def test_set_le_connection_parameters(self, address, parameters):
        """Test set LE connection parameters"""

        return self.bluetooth_facade.set_le_connection_parameters(
            address, parameters)


    @test_retry_and_log(False)
    def test_get_connection_info(self, address):
        """Test that connection info to device is retrievable."""

        return (self.bluetooth_facade.get_connection_info(address)
                is not None)


    @test_retry_and_log(False, messages_stop=False)
    def test_suspend_and_wait_for_sleep(self, suspend, sleep_timeout):
        """ Suspend the device and wait until it is sleeping.

        @param suspend: Sub-process that does the actual suspend call.
        @param sleep_timeout time limit in seconds to allow the host sleep.

        @return True if host is asleep within a short timeout, False otherwise.
        """
        suspend.start()
        try:
            self.host.test_wait_for_sleep(sleep_timeout)
        except Exception as e:
            suspend.join()
            self.results = {'exception': str(e)}
            return False

        return True


    @test_retry_and_log(False, messages_start=False)
    def test_wait_for_resume(self,
                             boot_id,
                             suspend,
                             resume_timeout,
                             test_start_time,
                             resume_slack=RESUME_DELTA,
                             fail_on_timeout=False,
                             fail_early_wake=True):
        """ Wait for device to resume from suspend.

        @param boot_id: Current boot id
        @param suspend: Sub-process that does actual suspend call.
        @param resume_timeout: Expect device to resume in given timeout.
        @param test_start_time: When was this test started? (device time)
        @param resume_slack: Allow some slack on resume timeout.
        @param fail_on_timeout: Fails if timeout is reached
        @param fail_early_wake: Fails if timeout isn't reached

        @return True if suspend sub-process completed without error.
        """
        success = False
        results = {}

        def _check_timeout(delta):
            if delta > timedelta(seconds=resume_timeout):
                return not fail_on_timeout
            else:
                return not fail_early_wake

        def _check_suspend_attempt_or_raise(test_start, wake_at):
            """Make sure suspend attempt was recent or raise TestNA.

            If we're looking at a previous suspend attempt, it means the test
            didn't trigger a suspend properly (i.e. no powerd call)

            @param test_start: When we started the test.
            @param wake_at: When powerd suspend resumed.

            @raises: error.TestNAError if found suspend occurred before we
                     started the test.
            """
            # If the last suspend attempt was before we started the test, it's
            # probably not a recent attempt.
            if wake_at < test_start:
                raise error.TestNAError(
                        'No recent suspend attempt found. '
                        'Started test at {} but last suspend ended at {}'.
                        format(test_start, wake_at))

            return True

        def _check_retcode_or_raise(retcode):
            """Make sure powerd return was successful.

            @param retcode: Return code of powerd_suspend.

            @raises: error.TestNAError if failed suspend due to non-BT
            @return: False if BT woke us, True otherwise
            """
            if retcode:
                if self.bluetooth_facade.bt_caused_last_resume():
                    return False
                else:
                    raise error.TestNAError(
                            'Failed suspend due to non-BT wake')

            return True

        # Sometimes it takes longer to resume from suspend; give some leeway
        resume_timeout = resume_timeout + resume_slack
        results['resume timeout'] = resume_timeout
        try:
            start = datetime.now()

            # Wait for resume needs to wait longer in case device rebooted.
            # Otherwise, the test will fail with errno 111 (connection refused)
            self.host.test_wait_for_resume(
                boot_id, resume_timeout=self.RESUME_INTERNAL_TIMEOUT_SECS)

            results['device accessible on resume'] = True

            # As of now, a timeout in test_wait_for_resume doesn't raise. Start
            # by first measuring the delta until network is back up to the dut.
            network_delta = datetime.now() - start

            # Use powerd logs to see how much time we actually spent in suspend
            # If the network went down during suspend, we will have spent less
            # time in suspend than expected. If we can't find info via powerd,
            # we can use measured time instead.
            info = self.bluetooth_facade.find_last_suspend_via_powerd_logs()
            if info:
                (start_suspend_at, end_suspend_at, retcode) = info
                actual_delta = end_suspend_at - start_suspend_at
                results['powerd time to resume'] = actual_delta.total_seconds()
                results['powerd retcode'] = retcode

                # Resume is successful if suspend occurred correctly and woke up
                # within the timeout. One significant caveat is that we only
                # fail here if BT blocked suspend, not if we woke spuriously.
                # This is by design (we depend on the timeout to check for
                # spurious wakeup).
                success = _check_suspend_attempt_or_raise(
                        test_start_time,
                        end_suspend_at) and _check_retcode_or_raise(
                                retcode) and _check_timeout(actual_delta)
            else:
                results['time to resume'] = network_delta.total_seconds()
                success = _check_timeout(network_delta)
        except error.TestFail as e:
            results['device accessible on resume'] = False
            success = False
            logging.error('wait_for_resume: %s', e)

            # If the resume failed due to a reboot, raise the testFail and exit
            # early from the test
            if 'client rebooted' in str(e):
                raise
        finally:
            suspend.join()

        results['success'] = success
        results['suspend exit code'] = suspend.exitcode
        self.results = results

        return all([success, suspend.exitcode == 0])


    def suspend_async(self, suspend_time, expect_bt_wake=False):
        """ Suspend asynchronously and return process for joining

        @param suspend_time: how long to stay in suspend
        @param expect_bt_wake: Whether we expect bluetooth to wake us from
            suspend. If true, we expect this resume will occur early

        @returns multiprocessing.Process object with suspend task
        """

        def _action_suspend():
            try:
                self.bluetooth_facade.do_suspend(suspend_time, expect_bt_wake)
            except socket.error as e:
                # Socket errors may occur after suspend if the underlying
                # connection is lost during suspend (happens if usb-ethernet
                # disconnects and reconnects on resume). Catch all these errors
                # and swallow them.
                logging.warning(
                        'Socket error on suspend. Swallowing error: %s',
                        str(e))
            return 0

        proc = multiprocessing.Process(target=_action_suspend)
        proc.daemon = True
        return proc


    def device_connect_async(self,
                             device_type,
                             device,
                             adapter_address,
                             delay_wake=1,
                             should_wake=True):
        """ Connects peer device asynchronously with DUT.

        This function uses a thread instead of a subprocess so that the test
        result is stored for the test. Otherwise, the test connection was
        sometimes failing but the test itself was passing.

        @param device_type: The device type (used to check if it's LE)
        @param device: the meta device with the peer device
        @param adapter_address: the address of the adapter
        @param delay_wake: delay wakeup by this many seconds
        @param should_wake: Should this cause a wakeup?

        @returns threading.Thread object with device connect task
        """

        def _action_device_connect():
            time.sleep(delay_wake)
            if 'BLE' in device_type:
                # LE reconnects by advertising (dut controller will create LE
                # connection, not the peer device)
                self.test_device_set_discoverable(device, True)
            else:
                # Classic requires peer to initiate a connection to wake up the
                # dut
                connect_func = self.test_connection_by_device_only
                if should_wake:
                    connect_func(device, adapter_address)
                else:
                    # If we're not expecting wake, this connect attempt will
                    # probably fail.
                    self.ignore_failure(connect_func, device, adapter_address)

        thread = threading.Thread(target=_action_device_connect)
        return thread


    @test_retry_and_log(False)
    def test_hid_device_created(self, device_address):
        """ Tests that the hid device is created before using it for tests.

        @param device_address: Address of peripheral device
        """
        device_found = self.bluetooth_facade.wait_for_hid_device(
                device_address)
        self.results = {
                'device_found': device_found
        }
        return all(self.results.values())


    @test_retry_and_log
    def test_battery_reporting(self, device):
        """ Tests that battery reporting through GATT can be received

        @param device: the meta device containing a Bluetooth device

        @returns: true if battery reporting is received
        """

        percentage = self.bluetooth_facade.get_battery_property(
                device.address, 'Percentage')

        return percentage > 0

    def _apply_new_adapter_alias(self, alias):
        """ Sets new system alias and applies discoverable setting

        @param alias: string alias to be applied to Adapter->Alias property
        """

        # Set Adapter's Alias property
        self.bluetooth_facade.set_adapter_alias(alias)

        # Set discoverable setting on
        self.bluetooth_facade.set_discoverable(True)

    @test_retry_and_log(False)
    def test_set_adapter_alias(self, alias):
        """ Validates that a new adapter alias is applied correctly

        @param alias: string alias to be applied to Adapter->Alias property

        @returns: True if the applied alias is properly applied in btmon trace
        """

        orig_alias = self.get_adapter_properties()['Alias']
        self.bluetooth_le_facade = self.bluetooth_facade

        # 1. Capture btmon logs around alias set operation
        self._get_btmon_log(lambda: self._apply_new_adapter_alias(alias))

        # 2. Verify that name appears in btmon trace with the following format:
        # "Name (complete): Chromebook_BA0E" as appears in EIR data set
        expected_alias_str = 'Name (complete): ' + alias
        alias_found = self.bluetooth_facade.btmon_find(expected_alias_str)

        # 3. Re-apply previous bluez alias as other tests expect default
        self.bluetooth_facade.set_adapter_alias(orig_alias)

        self.results = {'alias_found': alias_found}
        return all(self.results.values())

    # -------------------------------------------------------------------
    # Autotest methods
    # -------------------------------------------------------------------


    def initialize(self):
        """Initialize bluetooth adapter tests."""
        # Run through every tests and collect failed tests in self.fails.
        self.fails = []

        # If a test depends on multiple conditions, write the results of
        # the conditions in self.results so that it is easy to know
        # what conditions failed by looking at the log.
        self.results = None

        # Some tests may instantiate a peripheral device for testing.
        self.devices = dict()
        self.shared_peers = []
        for device_type in SUPPORTED_DEVICE_TYPES:
            self.devices[device_type] = list()

        # The count of registered advertisements.
        self.count_advertisements = 0


    def update_btpeer(self):
        """ Check and update the chameleond bundle on Bluetooth peer
        Latest chameleond bundle and git commit is stored in the google cloud
        This function compares the git commit of the Bluetooth peers and update
        the peer if the commit does not match

        @returns True: If all peer are updated to (or currently) in latest
                       commit. False if any update fails

        """
        def _update_btpeer():
            status = {}
            for peer in self.host.btpeer_list:
                status[peer] = {}
                status[peer]['update_needed'] = \
                    bluetooth_peer_update.is_update_needed(peer, commit)

            logging.debug(status)
            if not any([v['update_needed'] for v in status.values()]):
                logging.info('No peer needed update')
                return True
            logging.debug('Atleast one peer needs update')

            if not bluetooth_peer_update.download_installation_files(self.host,
                                                                     commit):
                logging.error('Unable to download installation files ')
                return False

            # TODO(b:160782273) Make this parallel
            for peer in self.host.btpeer_list:
                if status[peer]['update_needed']:
                    status[peer]['updated'], status[peer]['reason'] = \
                        bluetooth_peer_update.update_peer(peer, commit)

            for peer, v in status.items():
                if not v['update_needed']:
                    logging.debug('peer %s did not need update', str(peer.host))
                elif not v['updated']:
                    logging.error('update peer %s failed %s', str(peer.host),
                                  v['reason'])
                else:
                    logging.debug('peer %s updated successfully',
                                  str(peer.host))

            return all([v['updated'] for v in status.values()
                        if v['update_needed']])

        try:
            commit = None
            (_, commit) = bluetooth_peer_update.get_latest_commit()
            if commit is None:
                logging.error('Unable to get current commit')
                return False

            return _update_btpeer()
        except Exception as e:
            logging.error('Exception %s in update_btpeer', str(e))
            return False
        finally:
            if not bluetooth_peer_update.cleanup(self.host, commit):
                logging.error('Update peer cleanup failed')


    def get_chipset_name(self):
        """ Get the name of BT/WiFi chipset on this host

        @returns chipset name if successful else ''
        """
        (vid,pid) = self.bluetooth_facade.get_wlan_vid_pid()
        logging.debug('Bluetooth module vid pid is %s %s', vid, pid)
        if vid is None or pid is None:
            # Controllers that aren't WLAN+BT combo chips does not expose
            # Vendor ID/Product ID. Use alternate method.
            # This will return one of ['WCN3991', ''] or a string containing
            # the name of chipset read from DUT
            return self.bluetooth_facade.get_bt_module_name()
        for name, l in CHIPSET_TO_VIDPID.items():
            if (vid, pid) in l:
                return name
        return ''


    def verify_device_rssi(self, address_list):
        """ Test device rssi is over required threshold.

        @param address_list: List of peer devices to verify address for

        @raises error.TestNA if any device isn't found or RSSI is too low
        """
        try:
            self.test_start_discovery()
            for device_address in address_list:
                # The RSSI property is only maintained while discovery is
                # enabled.  Stopping discovery removes the property. Thus, look
                # up the RSSI without modifying discovery state.
                found = self.test_discover_device(device_address,
                                                  start_discovery=False,
                                                  stop_discovery=False)
                rssi = self.bluetooth_facade.get_device_property(
                        device_address, 'RSSI')

                if not found:
                    logging.info('Failing with TEST_NA as peer %s was not'
                                  ' discovered', device_address)
                    raise error.TestNAError(
                            'Peer {} not discovered'.format(device_address))

                if not rssi or rssi < self.MIN_RSSI:
                    logging.info('Failing with TEST_NA since RSSI (%s) is low ',
                                  rssi)
                    raise error.TestNAError(
                            'Peer {} RSSI is too low: {}'.format(
                                    device_address, rssi))

                logging.info('Peer {} RSSI {}'.format(device_address, rssi))
        finally:
            self.test_stop_discovery()


    def verify_controller_capability(self, required_roles=[],
                                     test_type=''):
        """Raise an exception if required role support isn't present

        @param required_roles: List of test role requirements in
                               ["central", "peripheral", "central-peripheral"]

        @raises: error.TestFail if device does not meet requirements
                                AND test_type is 'AVL'
                 error.TestNA if device does not meet requirements
                                and test_type is not 'AVL'
        """

        adapter_props = self.get_adapter_properties()

        supported_roles = adapter_props.get('Roles', [])

        for req in required_roles:
            if req not in supported_roles:
                # We don't meet requirements, throw error
                msg = 'Role requirement {} not in supported modes {}'.format(
                      req, supported_roles)

                if test_type == 'AVL':
                    raise error.TestFail(msg)

                logging.info('Failing with TEST_NA due to %s', msg)
                raise error.TestNAError(msg)


    def set_fail_fast(self, args_dict, default=False):
        """Set whether the test should fail fast if running into any problem

        By default it should not fail fast so that a batch test can continue
        running the rest after a failure in one test

        :param args_dict: the arguments passed int from the command line
        :param default: the default value when the flag is missing from the
                        args_dict

        """
        flag_name = 'fail_fast'
        if args_dict and flag_name in args_dict:
            self.fail_fast = bool(args_dict[flag_name].lower() == 'true')
        else:
            self.fail_fast = default


    def assert_discover_and_pair(self, device):
        """ Discovers and pairs given device. Automatically connects too.

        If any of the test expressions fail, it will raise an error so only call
        this function as a setup for a test.
        """
        self.assert_on_fail(self.test_device_set_discoverable(device, True))
        self.assert_on_fail(self.test_discover_device(device.address))
        self.assert_on_fail(
                self.test_pairing(device.address, device.pin, trusted=True))

    def run_once(self, *args, **kwargs):
        """This method should be implemented by children classes.

        Typically, the run_once() method would look like:

        factory = remote_facade_factory.RemoteFacadeFactory(host)
        self.bluetooth_facade = factory.create_bluetooth_facade()

        self.test_bluetoothd_running()
        # ...
        # invoke more self.test_xxx() tests.
        # ...

        if self.fails:
            raise error.TestFail(self.fails)

        """
        raise NotImplementedError


    def cleanup(self, test_state='END'):
        """Clean up bluetooth adapter tests.

        @param test_state: string describing the requested clear is for
                           a new test(NEW), the middle of the test(MID),
                           or the end of the test(END).
        """

        if test_state == 'END':
            # Disable all the bluetooth debug logs
            self.enable_disable_debug_log(enable=False)

            # Re-enable cellular services
            self.enable_disable_cellular(enable=True)

            # Re-enable ui
            self.enable_disable_ui(enable=True)

            if hasattr(self, 'host'):
                # Stop btmon process
                self.host.run('pkill btmon || true')

                #Stop tcpdump usbmon process
                self.host.run('pkill tcpdump || true')


        # Close the device properly if a device is instantiated.
        # Note: do not write something like the following statements
        #           if self.devices[device_type]:
        #       or
        #           if bool(self.devices[device_type]):
        #       Otherwise, it would try to invoke bluetooth_mouse.__nonzero__()
        #       which just does not exist.
        for device_name, device_list  in self.devices.items():
            for device in device_list:
                if device is not None:
                    device.Close()

                    # Power cycle BT device if we're in the middle of a test
                    if test_state == 'MID':
                        device.PowerCycle()

        self.devices = dict()
        for device_type in SUPPORTED_DEVICE_TYPES:
            self.devices[device_type] = list()
