| # 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, DEFAULT_MIN_ADV_INTERVAL, |
| DEFAULT_MAX_ADV_INTERVAL) |
| |
| |
| 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, |
| btpeer_args=[], |
| 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, |
| btpeer_args=btpeer_args) |
| self.llt_health_batch_run(num_iterations, test_name) |
| self.quick_test_cleanup() |