blob: 98e629406e53a9bed14f2cd43801accae4e62076 [file] [log] [blame]
# Lint as: python2, python3
# Copyright 2021 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.
"""A Batch of Bluetooth LE LLT health tests"""
from autotest_lib.server.cros.bluetooth import advertisements_data
DEFAULT_MIN_ADV_INTERVAL = 200
DEFAULT_MAX_ADV_INTERVAL = 500
from autotest_lib.server.cros.bluetooth.\
bluetooth_adapter_controller_role_tests \
import bluetooth_AdapterControllerRoleTests
from autotest_lib.server.cros.bluetooth.bluetooth_adapter_quick_tests \
import BluetoothAdapterQuickTests
from autotest_lib.server.cros.bluetooth.bluetooth_adapter_hidreports_tests \
import BluetoothAdapterHIDReportTests
from autotest_lib.server.cros.bluetooth.bluetooth_adapter_better_together \
import BluetoothAdapterBetterTogether
class bluetooth_AdapterLLTHealth(BluetoothAdapterHIDReportTests,
bluetooth_AdapterControllerRoleTests,
BluetoothAdapterBetterTogether):
"""A Batch of Bluetooth LE LLT health tests. This test is written
as a batch of tests in order to reduce test time, since auto-test
ramp up time is costly. The batch is using BluetoothAdapterQuickTests
wrapper methods to start and end a test and a batch of tests.
This class can be called to run the entire test batch or to run a
specific test only
"""
test_wrapper = BluetoothAdapterQuickTests.quick_test_test_decorator
batch_wrapper = BluetoothAdapterQuickTests.quick_test_batch_decorator
def discover_and_pair(self, device):
"""Discovers and pairs given device. Automatically connects too.
@param device: meta object for bt peer device
"""
self.test_discover_device(device.address)
self.test_pairing(device.address, device.pin, trusted=True)
self.test_connection_by_adapter(device.address)
def start_connectable_advertisement(self):
""" Initiate connectable advertising from DUT """
# Register and start advertising instance
# We ignore failure because the test isn't able to verify
# the min/max advertising intervals, but this is ok.
self.test_reset_advertising()
self.test_set_advertising_intervals(DEFAULT_MIN_ADV_INTERVAL,
DEFAULT_MAX_ADV_INTERVAL)
self.test_register_advertisement(advertisements_data.ADVERTISEMENTS[0],
1)
def pair_and_test_central(self, peripheral):
"""Connects DUT as central to a peripheral device.
@param peripheral: meta object for bt peer device
"""
# Pair the central device first -
# necessary for later connection to peripheral
self.pair_adapter_to_device(peripheral)
self.test_device_set_discoverable(peripheral, False)
self.start_connectable_advertisement()
# Discover DUT from peer
self.test_discover_by_device(peripheral)
# Connect to DUT from peer, putting DUT in peripheral role
self.test_connection_by_device(peripheral)
self.test_reset_advertising()
@test_wrapper('LLT: 1 Central 1 Peripheral. Order of connection CP',
devices={
'BLE_KEYBOARD': 1,
'BLE_MOUSE': 1
})
def llt_1c1p_connect_cp(self):
"""Tests llt with two peer devices.
Connects DUT as central to first device
and as peripheral to second device,
sends small amount of data over the connection
"""
self.verify_controller_capability(
required_roles=['central-peripheral'])
central = self.devices['BLE_MOUSE'][0]
peripheral = self.devices['BLE_KEYBOARD'][0]
# Establish connection from DUT as LE Central
self.discover_and_pair(central)
self.test_hid_device_created(central.address)
# Verify data transfer over the DUT LE central Connection
self.test_mouse_left_click(central)
# Now establish second connection with DUT as LE Peripheral
self.bluetooth_le_facade = self.bluetooth_facade
self.pair_and_test_central(peripheral)
self.run_keyboard_tests(peripheral)
# Verify data over LE Central connection again
self.test_mouse_left_click(central)
# Disconnect connections from DUT
self.test_disconnection_by_adapter(central.address)
self.test_disconnection_by_device(peripheral)
@test_wrapper('LLT: 1 Central 1 Peripheral. Order of connection PC',
devices={
'BLE_KEYBOARD': 1,
'BLE_MOUSE': 1
})
def llt_1c1p_connect_pc(self):
"""Tests llt with two peer devices,
Connects DUT as peripheral to first device
and as central to second device,
sends small amount of data over the connection
"""
self.verify_controller_capability(
required_roles=['central-peripheral'])
central = self.devices['BLE_MOUSE'][0]
peripheral = self.devices['BLE_KEYBOARD'][0]
# Establish the first connection with DUT as LE Peripheral
self.bluetooth_le_facade = self.bluetooth_facade
# Connect to DUT from peer, putting DUT in peripheral role
# Try transferring data over connection
self.pair_and_test_central(peripheral)
self.run_keyboard_tests(peripheral)
# Establish second connection from DUT as LE Central
self.discover_and_pair(central)
self.test_hid_device_created(central.address)
# Verify data transfer over the DUT LE Central Connection
self.test_mouse_left_click(central)
# Verfiy LE peripheral connection again
self.run_keyboard_tests(peripheral)
# Disconnect connections from DUT
self.test_disconnection_by_adapter(central.address)
self.test_disconnection_by_device(peripheral)
@test_wrapper('LLT: 1 Central 1 Peripheral while DUT advertising.'
'Order of connection PC',
devices={
'BLE_KEYBOARD': 1,
'BLE_MOUSE': 1
})
def llt_1c1p_connect_pc_while_adv(self):
"""Tests llt with two peer devices, while DUT advertising.
Connects DUT while advertising
as peripheral to first device
and as central to second device,
sends small amount of data over the connection
"""
self.verify_controller_capability(
required_roles=['central-peripheral'])
central = self.devices['BLE_MOUSE'][0]
peripheral = self.devices['BLE_KEYBOARD'][0]
# Establish the first connection with DUT as LE Peripheral
self.bluetooth_le_facade = self.bluetooth_facade
# Connect to DUT from peer, putting DUT in peripheral role
# Try transferring data over connection
self.pair_and_test_central(peripheral)
self.run_keyboard_tests(peripheral)
# Establish second connection from DUT as LE Central
# while advertising in progress
self.start_connectable_advertisement()
self.discover_and_pair(central)
self.test_hid_device_created(central.address)
# Verify data transfer over the DUT LE Central Connection
self.test_mouse_left_click(central)
# Verfiy LE Peripheral connection again
self.run_keyboard_tests(peripheral)
# Disconnect connections from DUT
self.test_disconnection_by_adapter(central.address)
self.test_disconnection_by_device(peripheral)
self.test_reset_advertising()
@test_wrapper('LLT: 2 Central 1 Peripheral. Order of connection CCP',
devices={
'BLE_KEYBOARD': 1,
'BLE_MOUSE': 1,
'BLE_PHONE': 1
})
def llt_2c1p_connect_ccp(self):
"""Tests llt with three peer devices.
Connects DUT as central to first and second devices,
connects DUT as peripheral to third device,
sends small amount of data over the connection
"""
self.verify_controller_capability(
required_roles=['central-peripheral'])
central_1 = self.devices['BLE_PHONE'][0]
central_2 = self.devices['BLE_MOUSE'][0]
peripheral = self.devices['BLE_KEYBOARD'][0]
# Establish two connections from DUT as LE Central
self.discover_and_pair(central_2)
self.test_hid_device_created(central_2.address)
# Verify data transfer over two DUT LE Central Connections
self.test_mouse_left_click(central_2)
central_1.RemoveDevice(self.bluetooth_facade.address)
self.test_smart_unlock_llt(address=central_1.address)
# Establish third connection with DUT as LE Peripheral
self.bluetooth_le_facade = self.bluetooth_facade
self.pair_and_test_central(peripheral)
self.run_keyboard_tests(peripheral)
# Verify data transfer over two DUT LE Central Connections
self.test_mouse_left_click(central_2)
# Disconnect connections from DUT
self.test_disconnection_by_adapter(central_1.address)
self.test_disconnection_by_adapter(central_2.address)
self.test_disconnection_by_device(peripheral)
@test_wrapper('LLT: 2 Central 1 Peripheral. Order of connection PCC',
devices={
'BLE_KEYBOARD': 1,
'BLE_MOUSE': 1,
'BLE_PHONE': 1
})
def llt_2c1p_connect_pcc(self):
"""Tests llt with three peer devices.
Connects DUT as peripheral to first device
and as central to second and third device,
sends small amount of data over the connection
"""
self.verify_controller_capability(
required_roles=['central-peripheral'])
central_1 = self.devices['BLE_PHONE'][0]
central_2 = self.devices['BLE_MOUSE'][0]
peripheral = self.devices['BLE_KEYBOARD'][0]
# Establish the first connection with DUT as LE Peripheral
self.bluetooth_le_facade = self.bluetooth_facade
# Connect to DUT from peer, putting DUT in peripheral role
# Try transferring data over connection
self.pair_and_test_central(peripheral)
self.run_keyboard_tests(peripheral)
# Establish connections from DUT as LE Central
self.discover_and_pair(central_2)
self.test_hid_device_created(central_2.address)
# Verify data transfer over two DUT LE Central Connections
self.test_mouse_left_click(central_2)
# Establish third connection
central_1.RemoveDevice(self.bluetooth_facade.address)
self.test_smart_unlock_llt(address=central_1.address)
# Verify once again data transfer over DUT LE Peripheral connection
self.run_keyboard_tests(peripheral)
# Disconnect connections from DUT
self.test_disconnection_by_adapter(central_1.address)
self.test_disconnection_by_adapter(central_2.address)
self.test_disconnection_by_device(peripheral)
@test_wrapper('LLT: 2 Central 1 Peripheral. Order of connection CPC',
devices={
'BLE_KEYBOARD': 1,
'BLE_MOUSE': 1,
'BLE_PHONE': 1
})
def llt_2c1p_connect_cpc(self):
"""Tests llt with three peer devices.
Connects DUT as central to first device,
as peripheral to second and as central to third device,
sends small amount of data over the connection
"""
self.verify_controller_capability(
required_roles=['central-peripheral'])
central_1 = self.devices['BLE_PHONE'][0]
central_2 = self.devices['BLE_MOUSE'][0]
peripheral = self.devices['BLE_KEYBOARD'][0]
# Establish the first connection with DUT as LE Central
central_1.RemoveDevice(self.bluetooth_facade.address)
self.test_smart_unlock_llt(address=central_1.address)
# Establish the second connection with DUT as LE Peripheral
self.bluetooth_le_facade = self.bluetooth_facade
# Connect to DUT from peer, putting DUT in peripheral role
# Try transferring data over connection
self.pair_and_test_central(peripheral)
self.run_keyboard_tests(peripheral)
# Establish third connections from DUT as LE Central
self.discover_and_pair(central_2)
self.test_hid_device_created(central_2.address)
# Verify data transfer over second LE Central Connections
self.test_mouse_left_click(central_2)
# Verify once again data transfer over DUT LE Peripheral connection
self.run_keyboard_tests(peripheral)
# Disconnect connections from DUT
self.test_disconnection_by_adapter(central_1.address)
self.test_disconnection_by_adapter(central_2.address)
self.test_disconnection_by_device(peripheral)
@test_wrapper('LLT: 2 Central 1 Peripheral while DUT advertising.'
'Order of connection PCC',
devices={
'BLE_KEYBOARD': 1,
'BLE_MOUSE': 1,
'BLE_PHONE': 1
})
def llt_2c1p_connect_pcc_while_adv(self):
"""Tests llt with three peer devices.
Connects DUT as peripheral to first device
and as central to second and third device while advertising,
sends small amount of data over the connection
"""
self.verify_controller_capability(
required_roles=['central-peripheral'])
central_1 = self.devices['BLE_MOUSE'][0]
central_2 = self.devices['BLE_PHONE'][0]
peripheral = self.devices['BLE_KEYBOARD'][0]
# Establish the first connection with DUT as LE Peripheral
self.bluetooth_le_facade = self.bluetooth_facade
# Connect to DUT from peer, putting DUT in peripheral role
# Try transferring data over connection
self.pair_and_test_central(peripheral)
self.run_keyboard_tests(peripheral)
# Connect as first LE Central while DUT is advertising
self.start_connectable_advertisement()
self.discover_and_pair(central_1)
self.test_hid_device_created(central_1.address)
# Establish second LE connection from DUT as LE Central
central_2.RemoveDevice(self.bluetooth_facade.address)
self.test_smart_unlock_llt(address=central_2.address)
# Verify data transfer over first LE Central Connections
self.test_mouse_left_click(central_1)
# Verify once again data transfer over DUT LE Peripheral connection
self.run_keyboard_tests(peripheral)
# Disconnect connections from DUT
self.test_disconnection_by_adapter(central_1.address)
self.test_disconnection_by_adapter(central_2.address)
self.test_disconnection_by_device(peripheral)
self.test_reset_advertising()
@test_wrapper('LLT: 2 Central 1 Peripheral while DUT Advertising.'
'Order of connection CPC',
devices={
'BLE_KEYBOARD': 1,
'BLE_MOUSE': 1,
'BLE_PHONE': 1
})
def llt_2c1p_connect_cpc_while_adv(self):
"""Tests llt with three peer devices.
Connects DUT while advertising as central to first device,
as peripheral to second and as central to third device,
sends small amount of data over the connection
"""
self.verify_controller_capability(
required_roles=['central-peripheral'])
central_1 = self.devices['BLE_PHONE'][0]
central_2 = self.devices['BLE_MOUSE'][0]
peripheral = self.devices['BLE_KEYBOARD'][0]
self.bluetooth_le_facade = self.bluetooth_facade
# Establish the first connection with DUT as LE Central
# while advertising in progress
self.start_connectable_advertisement()
central_1.RemoveDevice(self.bluetooth_facade.address)
self.test_smart_unlock_llt(address=central_1.address)
# Establish the second connection with DUT as LE Peripheral
# Try transferring data over connection
self.pair_and_test_central(peripheral)
self.run_keyboard_tests(peripheral)
# Establish third connections from DUT as LE Central
self.discover_and_pair(central_2)
self.test_hid_device_created(central_2.address)
# Verify data transfer over second LE Central Connections
self.test_mouse_left_click(central_2)
# Verify once again data transfer over DUT LE Peripheral connection
self.run_keyboard_tests(peripheral)
# Disconnect connections from DUT
self.test_disconnection_by_adapter(central_1.address)
self.test_disconnection_by_adapter(central_2.address)
self.test_disconnection_by_device(peripheral)
self.test_reset_advertising()
@test_wrapper('LLT: 1 Central 2 Peripheral. Order of connection CPP',
devices={
'BLE_KEYBOARD': 1,
'BLE_MOUSE': 1,
'BLE_PHONE': 1
})
def llt_2p1c_connect_cpp(self):
"""Tests llt with three peer devices.
Connects DUT as central to first device
and as peripheral to second and third devices,
sends small amount of data over the connection
"""
self.verify_controller_capability(
required_roles=['central-peripheral'])
peripheral_1 = self.devices['BLE_KEYBOARD'][0]
central_peer = self.devices['BLE_PHONE'][0]
peripheral_2 = self.devices['BLE_MOUSE'][0]
# Establish connection from DUT as LE Central
central_peer.RemoveDevice(self.bluetooth_facade.address)
self.test_smart_unlock_llt(address=central_peer.address)
self.bluetooth_le_facade = self.bluetooth_facade
# Connect to DUT from peer, putting DUT in peripheral role
# Try transferring data over connection
self.pair_and_test_central(peripheral_1)
self.run_keyboard_tests(peripheral_1)
# Establish and Verify second LE peripheral connection
self.pair_and_test_central(peripheral_2)
# Try transferring data over connection
self.test_mouse_left_click(peripheral_2)
# Verify traffic from LE Peripheral connections again
self.run_keyboard_tests(peripheral_1)
self.test_mouse_left_click(peripheral_2)
# Disconnect connections from DUT
self.test_disconnection_by_adapter(central_peer.address)
self.test_disconnection_by_device(peripheral_1)
self.test_disconnection_by_device(peripheral_2)
@test_wrapper('LLT: 1 Central 2 Peripheral. Order of connection PCP',
devices={
'BLE_KEYBOARD': 1,
'BLE_MOUSE': 1,
'BLE_PHONE': 1
})
def llt_2p1c_connect_pcp(self):
"""Tests llt with three peer devices.
Connects DUT as peripheral to first device,
as central to second and as peripheral to third devices,
sends small amount of data over the connection
"""
self.verify_controller_capability(
required_roles=['central-peripheral'])
peripheral_1 = self.devices['BLE_KEYBOARD'][0]
central_peer = self.devices['BLE_PHONE'][0]
peripheral_2 = self.devices['BLE_MOUSE'][0]
self.bluetooth_le_facade = self.bluetooth_facade
# Connect to DUT from peer, putting DUT in peripheral role
# Try transferring data over connection
self.pair_and_test_central(peripheral_1)
self.run_keyboard_tests(peripheral_1)
# Establish connection from DUT as LE Central
central_peer.RemoveDevice(self.bluetooth_facade.address)
self.test_smart_unlock_llt(address=central_peer.address)
# Establish and Verify second LE peripheral connection
self.pair_and_test_central(peripheral_2)
# Try transferring data over connection
self.test_mouse_left_click(peripheral_2)
# Verify traffic from LE Peripheral connections again
self.run_keyboard_tests(peripheral_1)
self.test_mouse_left_click(peripheral_2)
# Disconnect connections from DUT
self.test_disconnection_by_adapter(central_peer.address)
self.test_disconnection_by_device(peripheral_1)
self.test_disconnection_by_device(peripheral_2)
@test_wrapper('LLT: 1 Central 2 Peripheral. Order of connection PPC',
devices={
'BLE_KEYBOARD': 1,
'BLE_MOUSE': 1,
'BLE_PHONE': 1
})
def llt_2p1c_connect_ppc(self):
"""Tests llt with three peer devices.
Connects DUT as peripheral to first and second devices
and as central to third device,
sends small amount of data over the connection
"""
self.verify_controller_capability(
required_roles=['central-peripheral'])
peripheral_1 = self.devices['BLE_KEYBOARD'][0]
central_peer = self.devices['BLE_PHONE'][0]
peripheral_2 = self.devices['BLE_MOUSE'][0]
self.bluetooth_le_facade = self.bluetooth_facade
# Connect to DUT from peer, putting DUT in peripheral role
# Try transferring data over connection
self.pair_and_test_central(peripheral_1)
self.run_keyboard_tests(peripheral_1)
# Establish and Verify second LE peripheral connection
self.pair_and_test_central(peripheral_2)
# Try transferring data over connection
self.test_mouse_left_click(peripheral_2)
# Verify data transfer over two DUT LE Central Connections
central_peer.RemoveDevice(self.bluetooth_facade.address)
self.test_smart_unlock_llt(address=central_peer.address)
# Verify traffic from LE Peripheral connections again
self.run_keyboard_tests(peripheral_1)
self.test_mouse_left_click(peripheral_2)
# Disconnect connections from DUT
self.test_disconnection_by_adapter(central_peer.address)
self.test_disconnection_by_device(peripheral_1)
self.test_disconnection_by_device(peripheral_2)
@batch_wrapper('LLT Health')
def llt_health_batch_run(self, num_iterations=1, test_name=None):
"""Run the LE LLT health test batch or a specific given test.
The wrapper of this method is implemented in batch_decorator.
Using the decorator a test batch method can implement the only its
core tests invocations and let the decorator handle the wrapper,
which is taking care for whether to run a specific test or the
batch as a whole, and running the batch in iterations
@param num_iterations: how many iterations to run
@param test_name: specific test to run otherwise None to run the
whole batch
"""
self.llt_1c1p_connect_cp()
self.llt_1c1p_connect_pc()
self.llt_1c1p_connect_pc_while_adv()
self.llt_2c1p_connect_ccp()
self.llt_2c1p_connect_pcc()
self.llt_2c1p_connect_cpc()
self.llt_2c1p_connect_pcc_while_adv()
self.llt_2c1p_connect_cpc_while_adv()
self.llt_2p1c_connect_cpp()
self.llt_2p1c_connect_pcp()
self.llt_2p1c_connect_ppc()
def run_once(self,
host,
num_iterations=1,
args_dict=None,
test_name=None,
flag='Quick Health'):
"""Run the batch of Bluetooth LE LLT health tests
@param host: the DUT, usually a chromebook
@param num_iterations: the number of rounds to execute the test
@test_name: the test to run, or None for all tests
"""
# Initialize and run the test batch or the requested specific test
self.quick_test_init(host,
use_btpeer=True,
flag=flag,
args_dict=args_dict)
self.llt_health_batch_run(num_iterations, test_name)
self.quick_test_cleanup()