1# Copyright 2019 The Chromium OS Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5""" 6Server side bluetooth tests on adapter pairing and connecting to a bluetooth 7HID device. 8""" 9 10import logging 11import time 12 13from autotest_lib.server.cros.bluetooth import bluetooth_adapter_tests 14 15 16class BluetoothAdapterPairingTests( 17 bluetooth_adapter_tests.BluetoothAdapterTests): 18 """Server side bluetooth adapter pairing and connecting to bluetooth device 19 20 This test tries to verify that the adapter of the DUT could 21 pair and connect to a bluetooth HID device correctly. 22 23 In particular, the following subtests are performed. Look at the 24 docstrings of the subtests for more details. 25 - 26 27 Refer to BluetoothAdapterTests for all subtests performed in this test. 28 29 """ 30 31 # TODO(josephsih): Reduce the sleep intervals to speed up the tests. 32 PAIR_TEST_SLEEP_SECS = 5 33 34 def pairing_test(self, device, check_connected_method=lambda device: True, 35 pairing_twice=False, suspend_resume=False, reboot=False): 36 """Running Bluetooth adapter tests about pairing to a device.""" 37 38 # Reset the adapter to forget previously paired devices if any. 39 self.test_reset_on_adapter() 40 41 # The adapter must be set to the pairable state. 42 self.test_pairable() 43 44 # Test if the adapter could discover the target device. 45 time.sleep(self.PAIR_TEST_SLEEP_SECS) 46 self.test_discover_device(device.address) 47 48 # Test if the discovery could be stopped. 49 time.sleep(self.PAIR_TEST_SLEEP_SECS) 50 self.test_stop_discovery() 51 52 # Test if the discovered device class of service is correct. 53 self.test_device_class_of_service(device.address, 54 device.class_of_service) 55 56 # Test if the discovered device class of device is correct. 57 self.test_device_class_of_device(device.address, 58 device.class_of_device) 59 60 # Verify that the adapter could pair with the device. 61 # Also set the device trusted when pairing is done. 62 time.sleep(self.PAIR_TEST_SLEEP_SECS) 63 self.test_pairing(device.address, device.pin, trusted=True) 64 65 # Verify that the adapter could connect to the device. 66 time.sleep(self.PAIR_TEST_SLEEP_SECS) 67 self.test_connection_by_adapter(device.address) 68 69 # Test if the discovered device name is correct. 70 # Sometimes, it takes quite a long time after discovering 71 # the device (more than 60 seconds) to resolve the device name. 72 # Hence, it is safer to test the device name after pairing and 73 # connection is done. 74 time.sleep(self.PAIR_TEST_SLEEP_SECS) 75 self.test_device_name(device.address, device.name) 76 77 # Test if the device is still connected after suspend/resume. 78 if suspend_resume: 79 self.suspend_resume() 80 81 time.sleep(self.PAIR_TEST_SLEEP_SECS) 82 self.test_device_is_paired(device.address) 83 84 85 # check if peripheral is connected after suspend resume 86 if not self.ignore_failure(check_connected_method, device): 87 logging.info("device not connected after suspend_resume") 88 self.test_connection_by_device(device) 89 else: 90 logging.info("device remains connected after suspend_resume") 91 92 time.sleep(self.PAIR_TEST_SLEEP_SECS) 93 check_connected_method(device) 94 95 time.sleep(self.PAIR_TEST_SLEEP_SECS) 96 self.test_device_name(device.address, device.name) 97 98 # Test if the device is still connected after reboot. 99 # if reboot: 100 # self.host.reboot() 101 102 # time.sleep(self.PAIR_TEST_SLEEP_SECS) 103 # self.test_device_is_paired(device.address) 104 105 # # After a reboot, we need to wake the peripheral 106 # # as it is not connected. 107 # time.sleep(self.PAIR_TEST_SLEEP_SECS) 108 # self.test_connection_by_adapter(device.address) 109 110 # time.sleep(self.PAIR_TEST_SLEEP_SECS) 111 # self.test_device_is_connected(device.address) 112 113 # time.sleep(self.PAIR_TEST_SLEEP_SECS) 114 # self.test_device_name(device.address, device.name) 115 116 # Verify that the adapter could disconnect the device. 117 self.test_disconnection_by_adapter(device.address) 118 119 time.sleep(self.PAIR_TEST_SLEEP_SECS) 120 if device.can_init_connection: 121 # Verify that the device could initiate the connection. 122 self.test_connection_by_device(device) 123 check_connected_method(device) 124 else: 125 # Reconnect so that we can test disconnection from the kit 126 self.test_connection_by_adapter(device.address) 127 128 # TODO(alent): Needs a new capability, but this is a good proxy 129 if device.can_init_connection: 130 # Verify that the device could initiate the disconnection. 131 self.test_disconnection_by_device(device) 132 else: 133 # Reconnect so that we can test disconnection from the kit 134 self.test_disconnection_by_adapter(device.address) 135 136 # Verify that the adapter could remove the paired device. 137 self.test_remove_pairing(device.address) 138 139 # Check if the device could be re-paired after being forgotten. 140 if pairing_twice: 141 # Test if the adapter could discover the target device again. 142 time.sleep(self.PAIR_TEST_SLEEP_SECS) 143 self.test_discover_device(device.address) 144 145 # Verify that the adapter could pair with the device again. 146 # Also set the device trusted when pairing is done. 147 time.sleep(self.PAIR_TEST_SLEEP_SECS) 148 self.test_pairing(device.address, device.pin, trusted=True) 149 150 # Verify that the adapter could remove the paired device again. 151 time.sleep(self.PAIR_TEST_SLEEP_SECS) 152 self.test_remove_pairing(device.address) 153 154 155 def connect_disconnect_loop(self, device, loops): 156 """Perform a connect disconnect loop test""" 157 158 # First pair and disconnect, to emulate real life scenario 159 self.test_discover_device(device.address) 160 # self.bluetooth_facade.is_discovering() doesn't work as expected: 161 # crbug:905374 162 # self.test_stop_discovery() 163 self.bluetooth_facade.stop_discovery() 164 time.sleep(self.PAIR_TEST_SLEEP_SECS) 165 self.test_pairing(device.address, device.pin, trusted=True) 166 time.sleep(self.PAIR_TEST_SLEEP_SECS) 167 # Disconnect the device 168 self.test_disconnection_by_adapter(device.address) 169 total_duration_by_adapter = 0 170 loop_cnt = 0 171 for i in xrange(0, loops): 172 173 # Verify device didn't connect automatically 174 time.sleep(2) 175 self.test_device_is_not_connected(device.address) 176 177 start_time = time.time() 178 self.test_connection_by_adapter(device.address) 179 end_time = time.time() 180 time_diff = end_time - start_time 181 182 # Verify device is now connected 183 self.test_device_is_connected(device.address) 184 self.test_disconnection_by_adapter(device.address) 185 186 if not bool(self.fails): 187 loop_cnt += 1 188 total_duration_by_adapter += time_diff 189 logging.info('%d: Connection establishment duration %f sec', 190 i, time_diff) 191 else: 192 break 193 194 if not bool(self.fails): 195 logging.info('Average duration (by adapter) %f sec', 196 total_duration_by_adapter/loop_cnt) 197 198 199 def auto_reconnect_loop(self, device, loops, 200 check_connected_method=lambda device: True): 201 """Running a loop to verify the paired peer can auto reconnect""" 202 203 # Let the adapter pair, and connect to the target device first 204 self.test_discover_device(device.address) 205 # self.bluetooth_facade.is_discovering() doesn't work as expected: 206 # crbug:905374 207 # self.test_stop_discovery() 208 self.bluetooth_facade.stop_discovery() 209 time.sleep(self.PAIR_TEST_SLEEP_SECS) 210 self.test_pairing(device.address, device.pin, trusted=True) 211 time.sleep(self.PAIR_TEST_SLEEP_SECS) 212 self.test_connection_by_adapter(device.address) 213 214 total_reconnection_duration = 0 215 loop_cnt = 0 216 for i in xrange(loops): 217 # Restart and clear peer HID device 218 self.restart_peers() 219 start_time = time.time() 220 221 # Verify that the device is reconnecting 222 self.test_device_is_connected(device.address) 223 check_connected_method(device) 224 end_time = time.time() 225 time_diff = end_time - start_time 226 227 if not bool(self.fails): 228 total_reconnection_duration += time_diff 229 loop_cnt += 1 230 logging.info('%d: Reconnection duration %f sec', i, time_diff) 231 else: 232 break 233 234 if not bool(self.fails): 235 logging.info('Average Reconnection duration %f sec', 236 total_reconnection_duration/loop_cnt) 237