1# Lint as: python2, python3 2# Copyright 2019 The Chromium OS Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6"""A Batch of of Bluetooth LE health tests""" 7 8import time 9 10from autotest_lib.server.cros.bluetooth.bluetooth_adapter_controller_role_tests\ 11 import bluetooth_AdapterControllerRoleTests 12from autotest_lib.server.cros.bluetooth.bluetooth_adapter_quick_tests import ( 13 BluetoothAdapterQuickTests) 14from autotest_lib.server.cros.bluetooth.bluetooth_adapter_pairing_tests import ( 15 BluetoothAdapterPairingTests) 16from autotest_lib.server.cros.bluetooth.bluetooth_adapter_hidreports_tests \ 17 import BluetoothAdapterHIDReportTests 18 19 20# TODO(b/161174805) - veyron_fievel and veyron_mickey experiencing an 21# unexpected re-connect to peer, causing peer tests to fail. LE Role tests are 22# being hit especially hard, so temporarily disabling these tests on veyron 23LAB_VEYRON_MODELS = ['veyron_mickey', 'veyron_fievel'] 24 25class bluetooth_AdapterLEHealth(BluetoothAdapterQuickTests, 26 BluetoothAdapterPairingTests, 27 BluetoothAdapterHIDReportTests, 28 bluetooth_AdapterControllerRoleTests): 29 """A Batch of Bluetooth LE health tests. This test is written as a batch 30 of tests in order to reduce test time, since auto-test ramp up time is 31 costly. The batch is using BluetoothAdapterQuickTests wrapper methods to 32 start and end a test and a batch of tests. 33 34 This class can be called to run the entire test batch or to run a 35 specific test only 36 """ 37 38 test_wrapper = BluetoothAdapterQuickTests.quick_test_test_decorator 39 batch_wrapper = BluetoothAdapterQuickTests.quick_test_batch_decorator 40 41 @test_wrapper('Discovery Test', 42 devices={"BLE_MOUSE": 1}, 43 supports_floss=True) 44 def le_discovery_test(self): 45 """Performs discovery test with mouse peripheral""" 46 device = self.devices['BLE_MOUSE'][0] 47 48 self.test_discover_device(device.address) 49 50 # Removed due to b:149093897 - the raspi peer can't instantly update 51 # the advertised name, causing this test to fail 52 # self.test_device_name(device.address, device.name) 53 54 55 @test_wrapper('Connect Disconnect by Device Loop', 56 devices={'BLE_MOUSE': 1}, 57 flags=['Quick Health']) 58 def le_connect_disconnect_by_device_loop(self): 59 """Run connect/disconnect loop initiated by device. 60 The test also checks that there are no undesired 61 reconnections. 62 """ 63 64 device = self.devices['BLE_MOUSE'][0] 65 self.connect_disconnect_by_device_loop( 66 device=device, 67 loops=3, 68 device_type='BLE_MOUSE', 69 check_connected_method=self.test_mouse_move_in_xy) 70 71 72 @test_wrapper('Connect Disconnect Loop', devices={'BLE_MOUSE':1}) 73 def le_connect_disconnect_loop(self): 74 """Run connect/disconnect loop initiated by DUT. 75 The test also checks that there are no undesired 76 reconnections. 77 TODO(ysahvit) - add connection creation attempts 78 initiated by HID device 79 """ 80 81 device = self.devices['BLE_MOUSE'][0] 82 self.connect_disconnect_loop(device=device, loops=3) 83 84 85 @test_wrapper('HID Reconnect Speed', 86 devices={'BLE_MOUSE': 1}, 87 flags=['Quick Health'], 88 supports_floss=True) 89 def le_hid_reconnect_speed(self): 90 """Test the speed of a LE HID device reconnect to DUT""" 91 92 device = self.devices['BLE_MOUSE'][0] 93 self.hid_reconnect_speed(device=device, device_type='BLE_MOUSE') 94 95 96 @test_wrapper('HID Report Reboot', 97 devices={'BLE_MOUSE': 1}, 98 flags=['Quick Health']) 99 def le_hid_reports_reboot(self): 100 """Performs HID report test over reboot with BLE mouse peripheral""" 101 102 device = self.devices['BLE_MOUSE'][0] 103 self.run_hid_reports_test( 104 device, 105 check_connected_method=self.test_mouse_move_in_xy, 106 reboot=True) 107 108 @test_wrapper('HID Report Restart', 109 devices={'BLE_MOUSE': 1}, 110 flags=['Quick Health'], 111 supports_floss=True) 112 def le_hid_reports_restart(self): 113 """Performs HID report test over bluetoothd restart with BLE mouse 114 peripheral 115 """ 116 117 device = self.devices['BLE_MOUSE'][0] 118 self.run_hid_reports_test( 119 device, 120 check_connected_method=self.test_mouse_move_in_xy, 121 restart=True) 122 123 124 @test_wrapper('Mouse Reports', 125 devices={'BLE_MOUSE': 1}, 126 supports_floss=True) 127 def le_mouse_reports(self): 128 """Run all bluetooth mouse reports tests""" 129 130 device = self.devices['BLE_MOUSE'][0] 131 # Let the adapter pair, and connect to the target device. 132 self.test_discover_device(device.address) 133 time.sleep(self.TEST_SLEEP_SECS) 134 self.test_pairing(device.address, device.pin, trusted=True) 135 136 # With raspberry pi peer, it takes a moment before the device is 137 # registered as an input device. Without delay, the input recorder 138 # doesn't find the device 139 time.sleep(1) 140 self.run_mouse_tests(device=device) 141 142 143 @test_wrapper('Keyboard Reports', 144 devices={'BLE_KEYBOARD': 1}, 145 supports_floss=True) 146 def le_keyboard_reports(self): 147 """Run all bluetooth keyboard reports tests""" 148 149 device = self.devices['BLE_KEYBOARD'][0] 150 # Let the adapter pair, and connect to the target device. 151 self.test_discover_device(device.address) 152 time.sleep(self.TEST_SLEEP_SECS) 153 self.test_pairing(device.address, device.pin, trusted=True) 154 155 # With raspberry pi peer, it takes a moment before the device is 156 # registered as an input device. Without delay, the input recorder 157 # doesn't find the device 158 time.sleep(1) 159 self.run_keyboard_tests(device=device) 160 161 162 @test_wrapper('Battery Reporting', devices={'BLE_MOUSE': 1}) 163 def battery_reporting(self): 164 """Run battery reporting tests""" 165 166 device = self.devices['BLE_MOUSE'][0] 167 # Let the adapter pair, and connect to the target device. 168 self.assert_on_fail(self.test_discover_device(device.address)) 169 self.assert_on_fail( 170 self.test_pairing(device.address, device.pin, trusted=True)) 171 172 self.run_battery_reporting_tests(device=device) 173 174 @test_wrapper('Auto Reconnect', 175 devices={'BLE_MOUSE': 1}, 176 supports_floss=True) 177 def le_auto_reconnect(self): 178 """LE reconnection loop by reseting HID and check reconnection""" 179 180 device = self.devices['BLE_MOUSE'][0] 181 self.auto_reconnect_loop( 182 device=device, 183 loops=3, 184 check_connected_method=self.test_mouse_left_click) 185 186 # TODO(b/165690676) - Test is disabled for AVL while it stabilizes in flaky 187 # suite. Remove flags once it's in stable suite. 188 @test_wrapper('Power toggle and Connect Loop', devices={'BLE_MOUSE': 1}) 189 def le_power_toggle_connect_loop(self): 190 """Run autoconnect loop and cycle adapter power between runs. 191 The test makes sure the peer can reconnect after an adapter power 192 cycle. 193 """ 194 device = self.devices['BLE_MOUSE'][0] 195 self.auto_reconnect_loop( 196 device=device, 197 loops=3, 198 check_connected_method=self.test_mouse_left_click, 199 restart_adapter=True) 200 201 202 @test_wrapper('GATT Client', devices={'BLE_KEYBOARD':1}) 203 def le_gatt_client_attribute_browse_test(self): 204 """Browse the whole tree-structured GATT attributes""" 205 206 device = self.devices['BLE_KEYBOARD'][0] 207 self.test_discover_device(device.address) 208 time.sleep(self.TEST_SLEEP_SECS) 209 self.test_pairing(device.address, device.pin, trusted=True) 210 self.test_service_resolved(device.address) 211 self.test_gatt_browse(device.address) 212 213 214 # TODO (b/165949047) Flaky behavior on MVL/4.4 kernel causes flakiness when 215 # connection is initiated by the peripheral. Skip the test until 2021 uprev 216 @test_wrapper('LE secondary Test', 217 devices={'BLE_KEYBOARD': 1}, 218 skip_models=LAB_VEYRON_MODELS + ['bob']) 219 def le_role_secondary(self): 220 """Tests connection as secondary""" 221 222 self.verify_controller_capability( 223 required_roles=['peripheral'], 224 test_type=self.flag) 225 226 kbd = self.devices['BLE_KEYBOARD'][0] 227 kbd_test_func = lambda device: self.test_keyboard_input_from_trace( 228 device, 'simple_text') 229 self.controller_secondary_role_test(kbd, kbd_test_func) 230 231 232 @test_wrapper('LE primary Before secondary Test', 233 devices={'BLE_KEYBOARD':1, 'BLE_MOUSE':1}, 234 skip_models=LAB_VEYRON_MODELS) 235 def le_role_primary_before_secondary(self): 236 """Tests connection as primary and then as secondary""" 237 238 self.verify_controller_capability( 239 required_roles=['central-peripheral'], 240 test_type=self.flag) 241 242 kbd = self.devices['BLE_KEYBOARD'][0] 243 mouse = self.devices['BLE_MOUSE'][0] 244 245 kbd_test_func = lambda device: self.test_keyboard_input_from_trace( 246 device, 'simple_text') 247 mouse_test_func = self.test_mouse_left_click 248 249 hid_test_device = (mouse, mouse_test_func, 'pre') 250 self.controller_secondary_role_test( 251 kbd, kbd_test_func, secondary_info=hid_test_device) 252 253 254 @test_wrapper('LE secondary Before primary Test', devices={'BLE_KEYBOARD':1, 255 'BLE_MOUSE':1}, 256 skip_models=LAB_VEYRON_MODELS) 257 def le_role_secondary_before_primary(self): 258 """Tests connection as secondary and then as primary""" 259 260 self.verify_controller_capability( 261 required_roles=['central-peripheral'], 262 test_type=self.flag) 263 264 kbd = self.devices['BLE_KEYBOARD'][0] 265 mouse = self.devices['BLE_MOUSE'][0] 266 267 kbd_test_func = lambda device: self.test_keyboard_input_from_trace( 268 device, 'simple_text') 269 mouse_test_func = self.test_mouse_left_click 270 271 hid_test_device = (mouse, mouse_test_func, 'mid') 272 self.controller_secondary_role_test( 273 kbd, kbd_test_func, secondary_info=hid_test_device) 274 275 276 @test_wrapper('LE Sender Role Test', devices={'BLE_KEYBOARD':1}, 277 skip_models=LAB_VEYRON_MODELS) 278 def le_role_sender(self): 279 """Tests basic Nearby Sender role""" 280 281 self.verify_controller_capability( 282 required_roles=['central'], 283 test_type=self.flag) 284 285 kbd = self.devices['BLE_KEYBOARD'][0] 286 kbd_test_func = lambda device: self.test_keyboard_input_from_trace( 287 device, 'simple_text') 288 289 self.nearby_sender_role_test(kbd, kbd_test_func) 290 291 292 @test_wrapper('LE Sender Role Test During HID', 293 devices={'BLE_KEYBOARD':1, 'BLE_MOUSE':1}, 294 skip_models=LAB_VEYRON_MODELS) 295 def le_role_sender_during_hid(self): 296 """Tests Nearby Sender role while already connected to HID device""" 297 298 self.verify_controller_capability( 299 required_roles=['central-peripheral'], 300 test_type=self.flag) 301 302 kbd = self.devices['BLE_KEYBOARD'][0] 303 mouse = self.devices['BLE_MOUSE'][0] 304 305 kbd_test_func = lambda device: self.test_keyboard_input_from_trace( 306 device, 'simple_text') 307 mouse_test_func = self.test_mouse_left_click 308 309 hid_test_device = (mouse, mouse_test_func, 'pre') 310 self.nearby_sender_role_test( 311 kbd, kbd_test_func, secondary_info=hid_test_device) 312 313 314 @test_wrapper('LE HID Test During Sender Role', 315 devices={'BLE_KEYBOARD':1, 'BLE_MOUSE':1}, 316 skip_models=LAB_VEYRON_MODELS) 317 def le_role_hid_during_sender(self): 318 """Tests HID device while already in Nearby Sender role""" 319 320 self.verify_controller_capability( 321 required_roles=['central'], 322 test_type=self.flag) 323 324 kbd = self.devices['BLE_KEYBOARD'][0] 325 mouse = self.devices['BLE_MOUSE'][0] 326 327 kbd_test_func = lambda device: self.test_keyboard_input_from_trace( 328 device, 'simple_text') 329 mouse_test_func = self.test_mouse_left_click 330 331 hid_test_device = (mouse, mouse_test_func, 'mid') 332 self.nearby_sender_role_test( 333 kbd, kbd_test_func, secondary_info=hid_test_device) 334 335 336 # TODO (b/165949047) Flaky behavior on MVL/4.4 kernel causes flakiness when 337 # connection is initiated by the peripheral. Skip the test until 2021 uprev 338 @test_wrapper('LE Receiver Role Test', 339 devices={'BLE_KEYBOARD': 1}, 340 skip_models=LAB_VEYRON_MODELS + ['bob']) 341 def le_role_receiver(self): 342 """Tests basic Nearby Receiver role""" 343 344 self.verify_controller_capability( 345 required_roles=['peripheral'], 346 test_type=self.flag) 347 348 kbd = self.devices['BLE_KEYBOARD'][0] 349 kbd_test_func = lambda device: self.test_keyboard_input_from_trace( 350 device, 'simple_text') 351 352 self.nearby_receiver_role_test(kbd, kbd_test_func) 353 354 355 @test_wrapper('LE Receiver Role Test During HID', 356 devices={'BLE_KEYBOARD':1, 'BLE_MOUSE':1}, 357 skip_models=LAB_VEYRON_MODELS) 358 def le_role_receiver_during_hid(self): 359 """Tests Nearby Receiver role while already connected to HID device""" 360 361 self.verify_controller_capability( 362 required_roles=['central-peripheral'], 363 test_type=self.flag) 364 365 kbd = self.devices['BLE_KEYBOARD'][0] 366 mouse = self.devices['BLE_MOUSE'][0] 367 368 kbd_test_func = lambda device: self.test_keyboard_input_from_trace( 369 device, 'simple_text') 370 mouse_test_func = self.test_mouse_left_click 371 372 hid_test_device = (mouse, mouse_test_func, 'pre') 373 self.nearby_receiver_role_test( 374 kbd, kbd_test_func, secondary_info=hid_test_device) 375 376 377 @test_wrapper('LE HID Test During Receiver Adv', 378 devices={ 379 'BLE_KEYBOARD': 1, 380 'BLE_MOUSE': 1 381 }, 382 skip_models=LAB_VEYRON_MODELS) 383 def le_role_hid_during_receiver_adv(self): 384 """Tests HID device while already in Nearby Receiver role adv state""" 385 386 self.verify_controller_capability( 387 required_roles=['central-peripheral'], 388 test_type=self.flag) 389 390 kbd = self.devices['BLE_KEYBOARD'][0] 391 mouse = self.devices['BLE_MOUSE'][0] 392 393 kbd_test_func = lambda device: self.test_keyboard_input_from_trace( 394 device, 'simple_text') 395 mouse_test_func = self.test_mouse_left_click 396 397 hid_test_device = (mouse, mouse_test_func, 'mid') 398 self.nearby_receiver_role_test( 399 kbd, kbd_test_func, secondary_info=hid_test_device) 400 401 402 @test_wrapper('LE HID Test During Receiver Role', 403 devices={'BLE_KEYBOARD':1, 'BLE_MOUSE':1}, 404 skip_models=LAB_VEYRON_MODELS) 405 def le_role_hid_during_receiver_connection(self): 406 """Tests HID device while already in Nearby Receiver role connection""" 407 408 self.verify_controller_capability( 409 required_roles=['central-peripheral'], 410 test_type=self.flag) 411 412 kbd = self.devices['BLE_KEYBOARD'][0] 413 mouse = self.devices['BLE_MOUSE'][0] 414 415 kbd_test_func = lambda device: self.test_keyboard_input_from_trace( 416 device, 'simple_text') 417 mouse_test_func = self.test_mouse_left_click 418 419 hid_test_device = (mouse, mouse_test_func, 'end') 420 self.nearby_receiver_role_test( 421 kbd, kbd_test_func, secondary_info=hid_test_device) 422 423 424 @batch_wrapper('LE Health') 425 def le_health_batch_run(self, num_iterations=1, test_name=None): 426 """Run the LE health test batch or a specific given test. 427 The wrapper of this method is implemented in batch_decorator. 428 Using the decorator a test batch method can implement the only its 429 core tests invocations and let the decorator handle the wrapper, 430 which is taking care for whether to run a specific test or the 431 batch as a whole, and running the batch in iterations 432 433 @param num_iterations: how many interations to run 434 @param test_name: specifc test to run otherwise None to run the 435 whole batch 436 """ 437 self.le_connect_disconnect_by_device_loop() 438 self.le_connect_disconnect_loop() 439 self.le_hid_reconnect_speed() 440 self.le_hid_reports_reboot() 441 self.le_hid_reports_restart() 442 self.le_power_toggle_connect_loop() 443 self.le_mouse_reports() 444 self.le_keyboard_reports() 445 self.le_auto_reconnect() 446 self.le_discovery_test() 447 448 # Controller role tests 449 self.le_role_hid_during_receiver_adv() 450 self.le_role_hid_during_sender() 451 self.le_role_primary_before_secondary() 452 self.le_role_receiver() 453 self.le_role_receiver_during_hid() 454 self.le_role_secondary() 455 self.le_role_sender() 456 self.le_role_sender_during_hid() 457 458 459 def run_once(self, 460 host, 461 num_iterations=1, 462 args_dict=None, 463 test_name=None, 464 flag='Quick Health', 465 floss=False): 466 """Run the batch of Bluetooth LE health tests 467 468 @param host: the DUT, usually a chromebook 469 @param num_iterations: the number of rounds to execute the test 470 @test_name: the test to run, or None for all tests 471 """ 472 473 # Initialize and run the test batch or the requested specific test 474 self.quick_test_init(host, 475 use_btpeer=True, 476 flag=flag, 477 args_dict=args_dict, 478 floss=floss) 479 self.le_health_batch_run(num_iterations, test_name) 480 self.quick_test_cleanup() 481