1#!/usr/bin/env python3 2# 3# Copyright (C) 2016 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); you may not 6# use this file except in compliance with the License. You may obtain a copy of 7# the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14# License for the specific language governing permissions and limitations under 15# the License. 16""" 17Test script to exercises different ways Ble Advertisements can run in 18concurrency. This test was designed to be run in a shield box. 19""" 20 21import concurrent 22import time 23 24from queue import Empty 25from acts.test_decorators import test_tracker_info 26from acts_contrib.test_utils.bt.BluetoothBaseTest import BluetoothBaseTest 27from acts_contrib.test_utils.bt.bt_test_utils import BtTestUtilsError 28from acts_contrib.test_utils.bt.bt_constants import ble_advertise_settings_modes 29from acts_contrib.test_utils.bt.bt_constants import ble_scan_settings_callback_types 30from acts_contrib.test_utils.bt.bt_constants import ble_scan_settings_modes 31from acts_contrib.test_utils.bt.bt_constants import adv_succ 32from acts_contrib.test_utils.bt.bt_test_utils import generate_ble_advertise_objects 33from acts_contrib.test_utils.bt.bt_test_utils import generate_ble_scan_objects 34from acts_contrib.test_utils.bt.bt_test_utils import get_advanced_droid_list 35from acts_contrib.test_utils.bt.bt_test_utils import reset_bluetooth 36from acts_contrib.test_utils.bt.bt_test_utils import scan_and_verify_n_advertisements 37from acts_contrib.test_utils.bt.bt_constants import scan_result 38from acts_contrib.test_utils.bt.bt_test_utils import setup_n_advertisements 39from acts_contrib.test_utils.bt.bt_test_utils import take_btsnoop_logs 40from acts_contrib.test_utils.bt.bt_test_utils import teardown_n_advertisements 41 42 43class ConcurrentBleAdvertisingTest(BluetoothBaseTest): 44 default_timeout = 10 45 droid_list = [] 46 max_advertisements = -1 47 48 def setup_class(self): 49 super().setup_class() 50 self.scn_ad = self.android_devices[0] 51 self.adv_ad = self.android_devices[1] 52 self.droid_list = get_advanced_droid_list(self.android_devices) 53 self.max_advertisements = self.droid_list[1]['max_advertisements'] 54 55 def setup_test(self): 56 super().setup_test() 57 return reset_bluetooth(self.android_devices) 58 59 def _verify_n_advertisements(self, num_advertisements): 60 try: 61 advertise_callback_list = setup_n_advertisements( 62 self.adv_ad, num_advertisements) 63 except BtTestUtilsError: 64 return False 65 try: 66 scan_and_verify_n_advertisements(self.scn_ad, num_advertisements) 67 except BtTestUtilsError: 68 return False 69 teardown_n_advertisements(self.adv_ad, len(advertise_callback_list), 70 advertise_callback_list) 71 return True 72 73 @BluetoothBaseTest.bt_test_wrap 74 @test_tracker_info(uuid='abc03874-6d7a-4b5d-9f29-18731a102793') 75 def test_max_advertisements_defaults(self): 76 """Testing max advertisements. 77 78 Test that a single device can have the max advertisements 79 concurrently advertising. 80 81 Steps: 82 1. Setup the scanning android device. 83 2. Setup the advertiser android device. 84 3. Start scanning on the max_advertisements as defined in the script. 85 4. Verify that all advertisements are found. 86 87 Expected Result: 88 All advertisements should start without errors. 89 90 Returns: 91 Pass if True 92 Fail if False 93 94 TAGS: LE, Advertising, Concurrency 95 Priority: 0 96 """ 97 return self._verify_n_advertisements(self.max_advertisements) 98 99 @BluetoothBaseTest.bt_test_wrap 100 @test_tracker_info(uuid='50ee137e-eb71-40ef-b72f-a5fd646190d2') 101 def test_max_advertisements_include_device_name_and_filter_device_name( 102 self): 103 """Testing max advertisement variant. 104 105 Test that a single device can have the max advertisements 106 concurrently advertising. Include the device name as a part of the filter 107 and advertisement data. 108 109 Steps: 110 1. Setup the scanning android device. 111 2. Setup the advertiser android device. 112 3. Include device name in each advertisement. 113 4. Include device name filter in the scanner. 114 5. Start scanning on the max_advertisements as defined in the script. 115 6. Verify that all advertisements are found. 116 117 Expected Result: 118 All advertisements should start without errors. 119 120 Returns: 121 Pass if True 122 Fail if False 123 124 TAGS: LE, Advertising, Concurrency 125 Priority: 2 126 """ 127 self.adv_ad.droid.bleSetAdvertiseDataIncludeDeviceName(True) 128 self.scn_ad.droid.bleSetScanFilterDeviceName( 129 self.adv_ad.droid.bluetoothGetLocalName()) 130 return self._verify_n_advertisements(self.max_advertisements) 131 132 @BluetoothBaseTest.bt_test_wrap 133 @test_tracker_info(uuid='f7e9ba2b-6286-4510-a8a0-f1df831056c0') 134 def test_max_advertisements_exclude_device_name_and_filter_device_name( 135 self): 136 """Test max advertisement variant. 137 138 Test that a single device can have the max advertisements concurrently 139 advertising. Include the device name as a part of the filter but not the 140 advertisement data. 141 142 Steps: 143 1. Setup the scanning android device. 144 2. Setup the advertiser android device. 145 3. Include device name filter in the scanner. 146 4. Start scanning on the max_advertisements as defined in the script. 147 5. Verify that no advertisements are found. 148 149 Expected Result: 150 All advertisements should start without errors. 151 152 Returns: 153 Pass if True 154 Fail if False 155 156 TAGS: LE, Advertising, Concurrency 157 Priority: 2 158 """ 159 self.adv_ad.droid.bleSetAdvertiseDataIncludeDeviceName(False) 160 self.scn_ad.droid.bleSetScanFilterDeviceName( 161 self.adv_ad.droid.bluetoothGetLocalName()) 162 return not self._verify_n_advertisements(self.max_advertisements) 163 164 @BluetoothBaseTest.bt_test_wrap 165 @test_tracker_info(uuid='6ce102d7-61e1-4ca0-bcfb-767437b86c2b') 166 def test_max_advertisements_with_manufacturer_data(self): 167 """Test max advertisement variant. 168 169 Test that a single device can have the max advertisements concurrently 170 advertising. Include the manufacturer data as a part of the filter and 171 advertisement data. 172 173 Steps: 174 1. Setup the scanning android device. 175 2. Setup the advertiser android device. 176 3. Include manufacturer data in each advertisement. 177 4. Include manufacturer data filter in the scanner. 178 5. Start scanning on the max_advertisements as defined in the script. 179 6. Verify that all advertisements are found. 180 181 Expected Result: 182 All advertisements should start without errors. 183 184 Returns: 185 Pass if True 186 Fail if False 187 188 TAGS: LE, Advertising, Concurrency 189 Priority: 2 190 """ 191 self.scn_ad.droid.bleSetScanFilterManufacturerData(1, [1]) 192 self.adv_ad.droid.bleAddAdvertiseDataManufacturerId(1, [1]) 193 return self._verify_n_advertisements(self.max_advertisements) 194 195 @BluetoothBaseTest.bt_test_wrap 196 @test_tracker_info(uuid='2fc7d5e8-1539-42a8-8681-ce0b8bfc0924') 197 def test_max_advertisements_with_manufacturer_data_mask(self): 198 """Test max advertisements variant. 199 200 Test that a single device can have the max advertisements concurrently 201 advertising. Include the manufacturer data mask as a part of the filter 202 and advertisement data. 203 204 Steps: 205 1. Setup the scanning android device. 206 2. Setup the advertiser android device. 207 3. Include manufacturer data in each advertisement. 208 4. Include manufacturer data mask filter in the scanner. 209 5. Start scanning on the max_advertisements as defined in the script. 210 6. Verify that all advertisements are found. 211 212 Expected Result: 213 All advertisements should start without errors. 214 215 Returns: 216 Pass if True 217 Fail if False 218 219 TAGS: LE, Advertising, Concurrency 220 Priority: 2 221 """ 222 self.scn_ad.droid.bleSetScanFilterManufacturerData(1, [1], [1]) 223 self.adv_ad.droid.bleAddAdvertiseDataManufacturerId(1, [1]) 224 return self._verify_n_advertisements(self.max_advertisements) 225 226 @BluetoothBaseTest.bt_test_wrap 227 @test_tracker_info(uuid='9ef615ed-1705-44ae-ab5b-f7e8fb4bb770') 228 def test_max_advertisements_with_service_data(self): 229 """Test max advertisement variant. 230 231 Test that a single device can have the max advertisements concurrently 232 advertising. Include the service data as a part of the filter and 233 advertisement data. 234 235 Steps: 236 1. Setup the scanning android device. 237 2. Setup the advertiser android device. 238 3. Include service data in each advertisement. 239 4. Include service data filter in the scanner. 240 5. Start scanning on the max_advertisements as defined in the script. 241 6. Verify that all advertisements are found. 242 243 Expected Result: 244 All advertisements should start without errors. 245 246 Returns: 247 Pass if True 248 Fail if False 249 250 TAGS: LE, Advertising, Concurrency 251 Priority: 2 252 """ 253 test_result = True 254 filter_list = self.scn_ad.droid.bleGenFilterList() 255 self.scn_ad.droid.bleSetScanFilterServiceData( 256 "0000110A-0000-1000-8000-00805F9B34FB", [11, 17, 80]) 257 self.adv_ad.droid.bleAddAdvertiseDataServiceData( 258 "0000110A-0000-1000-8000-00805F9B34FB", [11, 17, 80]) 259 return self._verify_n_advertisements(self.max_advertisements) 260 261 @BluetoothBaseTest.bt_test_wrap 262 @test_tracker_info(uuid='9ef615ed-1705-44ae-ab5b-f7e8fb4bb770') 263 def test_max_advertisements_with_manufacturer_data_mask_and_include_device_name( 264 self): 265 """Test max advertisement variant. 266 267 Test that a single device can have the max advertisements concurrently 268 advertising. Include the device name and manufacturer data as a part of 269 the filter and advertisement data. 270 271 Steps: 272 1. Setup the scanning android device. 273 2. Setup the advertiser android device. 274 3. Include device name and manufacturer data in each advertisement. 275 4. Include device name and manufacturer data filter in the scanner. 276 5. Start scanning on the max_advertisements as defined in the script. 277 6. Verify that all advertisements are found. 278 279 Expected Result: 280 All advertisements should start without errors. 281 282 Returns: 283 Pass if True 284 Fail if False 285 286 TAGS: LE, Advertising, Concurrency 287 Priority: 2 288 """ 289 self.adv_ad.droid.bleSetAdvertiseDataIncludeDeviceName(True) 290 self.scn_ad.droid.bleSetScanFilterDeviceName( 291 self.adv_ad.droid.bluetoothGetLocalName()) 292 self.scn_ad.droid.bleSetScanFilterManufacturerData(1, [1], [1]) 293 self.adv_ad.droid.bleAddAdvertiseDataManufacturerId(1, [1]) 294 return self._verify_n_advertisements(self.max_advertisements) 295 296 @BluetoothBaseTest.bt_test_wrap 297 @test_tracker_info(uuid='c2ca85fb-6663-431d-aa30-5286a85dbbe0') 298 def test_max_advertisements_with_service_uuids(self): 299 """Test max advertisement variant. 300 301 Test that a single device can have the max advertisements concurrently 302 advertising. Include the service uuid as a part of the filter and 303 advertisement data. 304 305 Steps: 306 1. Setup the scanning android device. 307 2. Setup the advertiser android device. 308 3. Include service uuid in each advertisement. 309 4. Include service uuid filter in the scanner. 310 5. Start scanning on the max_advertisements as defined in the script. 311 6. Verify that all advertisements are found. 312 313 Expected Result: 314 All advertisements should start without errors. 315 316 Returns: 317 Pass if True 318 Fail if False 319 320 TAGS: LE, Advertising, Concurrency 321 Priority: 1 322 """ 323 self.scn_ad.droid.bleSetScanFilterServiceUuid( 324 "00000000-0000-1000-8000-00805f9b34fb") 325 self.adv_ad.droid.bleSetAdvertiseDataSetServiceUuids( 326 ["00000000-0000-1000-8000-00805f9b34fb"]) 327 return self._verify_n_advertisements(self.max_advertisements) 328 329 @BluetoothBaseTest.bt_test_wrap 330 @test_tracker_info(uuid='756e026f-64d7-4a2f-935a-3790c0ac4503') 331 def test_max_advertisements_with_service_uuid_and_service_mask(self): 332 """Test max advertisements variant. 333 334 Test that a single device can have the max advertisements concurrently 335 advertising. Include the service mask as a part of the filter and 336 advertisement data. 337 338 Steps: 339 1. Setup the scanning android device. 340 2. Setup the advertiser android device. 341 3. Include service uuid in each advertisement. 342 4. Include service mask filter in the scanner. 343 5. Start scanning on the max_advertisements as defined in the script. 344 6. Verify that all advertisements are found. 345 346 Expected Result: 347 All advertisements should start without errors. 348 349 Returns: 350 Pass if True 351 Fail if False 352 353 TAGS: LE, Advertising, Concurrency 354 Priority: 2 355 """ 356 self.scn_ad.droid.bleSetScanFilterServiceUuid( 357 "00000000-0000-1000-8000-00805f9b34fb", 358 "00000000-0000-1000-8000-00805f9b34fb") 359 self.adv_ad.droid.bleSetAdvertiseDataSetServiceUuids( 360 ["00000000-0000-1000-8000-00805f9b34fb"]) 361 return self._verify_n_advertisements(self.max_advertisements) 362 363 @BluetoothBaseTest.bt_test_wrap 364 @test_tracker_info(uuid='79c4b6cd-9f07-49a9-829f-69b29ea8d322') 365 def test_max_advertisements_plus_one(self): 366 """Test max advertisements plus one. 367 368 Test that a single device can have the max advertisements concurrently 369 advertising but fail on starting the max advertisements plus one. 370 filter and advertisement data. 371 372 Steps: 373 1. Setup the scanning android device. 374 2. Setup the advertiser android device. 375 3. Start max_advertisements + 1. 376 377 Expected Result: 378 The last advertisement should fail. 379 380 Returns: 381 Pass if True 382 Fail if False 383 384 TAGS: LE, Advertising, Concurrency 385 Priority: 0 386 """ 387 return not self._verify_n_advertisements(self.max_advertisements + 1) 388 389 @BluetoothBaseTest.bt_test_wrap 390 @test_tracker_info(uuid='0bd6e490-a501-4fe1-88e5-9b77970c0b95') 391 def test_start_two_advertisements_on_same_callback(self): 392 """Test invalid advertisement scenario. 393 394 Test that a single device cannot have two advertisements start on the 395 same callback. 396 397 Steps: 398 1. Setup the scanning android device. 399 2. Setup the advertiser android device. 400 3. Call start ble advertising on the same callback. 401 402 Expected Result: 403 The second call of start advertising on the same callback should fail. 404 405 Returns: 406 Pass if True 407 Fail if False 408 409 TAGS: LE, Advertising, Concurrency 410 Priority: 1 411 """ 412 test_result = True 413 advertise_callback, advertise_data, advertise_settings = ( 414 generate_ble_advertise_objects(self.adv_ad.droid)) 415 self.adv_ad.droid.bleStartBleAdvertising(advertise_callback, 416 advertise_data, 417 advertise_settings) 418 try: 419 self.adv_ad.ed.pop_event(adv_succ.format(advertise_callback), 420 self.default_timeout) 421 except Empty as error: 422 self.log.error("Test failed with Empty error: {}".format(error)) 423 return False 424 except concurrent.futures._base.TimeoutError as error: 425 self.log.debug( 426 "Test failed, filtering callback onSuccess never occurred: {}". 427 format(error)) 428 try: 429 self.adv_ad.droid.bleStartBleAdvertising(advertise_callback, 430 advertise_data, 431 advertise_settings) 432 self.adv_ad.ed.pop_event(adv_succ.format(advertise_callback), 433 self.default_timeout) 434 test_result = False 435 except Empty as error: 436 self.log.debug("Test passed with Empty error: {}".format(error)) 437 except concurrent.futures._base.TimeoutError as error: 438 self.log.debug( 439 "Test passed, filtering callback onSuccess never occurred: {}". 440 format(error)) 441 442 return test_result 443 444 @BluetoothBaseTest.bt_test_wrap 445 @test_tracker_info(uuid='12632b31-22b9-4121-80b6-1263b9d90909') 446 def test_toggle_advertiser_bt_state(self): 447 """Test forcing stopping advertisements. 448 449 Test that a single device resets its callbacks when the bluetooth state is 450 reset. There should be no advertisements. 451 452 Steps: 453 1. Setup the scanning android device. 454 2. Setup the advertiser android device. 455 3. Call start ble advertising. 456 4. Toggle bluetooth on and off. 457 5. Scan for any advertisements. 458 459 Expected Result: 460 No advertisements should be found after toggling Bluetooth on the 461 advertising device. 462 463 Returns: 464 Pass if True 465 Fail if False 466 467 TAGS: LE, Advertising, Concurrency 468 Priority: 2 469 """ 470 test_result = True 471 self.adv_ad.droid.bleSetAdvertiseDataIncludeDeviceName(True) 472 advertise_callback, advertise_data, advertise_settings = ( 473 generate_ble_advertise_objects(self.adv_ad.droid)) 474 self.adv_ad.droid.bleStartBleAdvertising(advertise_callback, 475 advertise_data, 476 advertise_settings) 477 try: 478 self.adv_ad.ed.pop_event(adv_succ.format(advertise_callback), 479 self.default_timeout) 480 except Empty as error: 481 self.log.error("Test failed with Empty error: {}".format(error)) 482 return False 483 except concurrent.futures._base.TimeoutError as error: 484 self.log.error( 485 "Test failed, filtering callback onSuccess never occurred: {}". 486 format(error)) 487 self.scn_ad.droid.bleSetScanSettingsScanMode( 488 ble_scan_settings_modes['low_latency']) 489 self.scn_ad.droid.bleSetScanFilterDeviceName( 490 self.adv_ad.droid.bluetoothGetLocalName()) 491 filter_list, scan_settings, scan_callback = generate_ble_scan_objects( 492 self.scn_ad.droid) 493 self.scn_ad.droid.bleBuildScanFilter(filter_list) 494 self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings, 495 scan_callback) 496 try: 497 self.scn_ad.ed.pop_event(scan_result.format(scan_callback), 498 self.default_timeout) 499 except Empty as error: 500 self.log.error("Test failed with: {}".format(error)) 501 return False 502 self.scn_ad.droid.bleStopBleScan(scan_callback) 503 test_result = reset_bluetooth([self.android_devices[1]]) 504 self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings, 505 scan_callback) 506 if not test_result: 507 return False 508 try: 509 expected_event = scan_result.format(scan_callback) 510 event = self.scn_ad.ed.pop_event(expected_event, 511 self.default_timeout) 512 self.log.error("Event {} not expected. Found: {}".format( 513 expected_event, event)) 514 return False 515 except Empty as error: 516 self.log.debug("Test passed with: {}".format(error)) 517 self.scn_ad.droid.bleStopBleScan(scan_callback) 518 self.adv_ad.droid.bleStopBleAdvertising(advertise_callback) 519 return True 520 521 @BluetoothBaseTest.bt_test_wrap 522 @test_tracker_info(uuid='785c5c77-d5d4-4d0f-8b7b-3eb1f1646d2c') 523 def test_restart_advertise_callback_after_bt_toggle(self): 524 """Test starting an advertisement on a cleared out callback. 525 526 Test that a single device resets its callbacks when the bluetooth state 527 is reset. 528 529 Steps: 530 1. Setup the scanning android device. 531 2. Setup the advertiser android device. 532 3. Call start ble advertising. 533 4. Toggle bluetooth on and off. 534 5. Call start ble advertising on the same callback. 535 536 Expected Result: 537 Starting an advertisement on a callback id after toggling bluetooth 538 should fail. 539 540 Returns: 541 Pass if True 542 Fail if False 543 544 TAGS: LE, Advertising, Concurrency 545 Priority: 1 546 """ 547 test_result = True 548 advertise_callback, advertise_data, advertise_settings = ( 549 generate_ble_advertise_objects(self.adv_ad.droid)) 550 self.adv_ad.droid.bleStartBleAdvertising(advertise_callback, 551 advertise_data, 552 advertise_settings) 553 try: 554 self.adv_ad.ed.pop_event(adv_succ.format(advertise_callback), 555 self.default_timeout) 556 except Empty as error: 557 self.log.error("Test failed with Empty error: {}".format(error)) 558 test_result = False 559 except concurrent.futures._base.TimeoutError as error: 560 self.log.debug( 561 "Test failed, filtering callback onSuccess never occurred: {}". 562 format(error)) 563 test_result = reset_bluetooth([self.android_devices[1]]) 564 if not test_result: 565 return test_result 566 self.adv_ad.droid.bleStartBleAdvertising(advertise_callback, 567 advertise_data, 568 advertise_settings) 569 try: 570 self.adv_ad.ed.pop_event(adv_succ.format(advertise_callback), 571 self.default_timeout) 572 except Empty as error: 573 self.log.error("Test failed with Empty error: {}".format(error)) 574 test_result = False 575 except concurrent.futures._base.TimeoutError as error: 576 self.log.debug( 577 "Test failed, filtering callback onSuccess never occurred: {}". 578 format(error)) 579 return test_result 580 581 @BluetoothBaseTest.bt_test_wrap 582 @test_tracker_info(uuid='dd5529b7-6774-4580-8b29-d84568c15442') 583 def test_timeout(self): 584 """Test starting advertiser with timeout. 585 586 Test that when a timeout is used, the advertiser is cleaned properly, 587 and next one can be started. 588 589 Steps: 590 1. Setup the advertiser android device with 4 second timeout. 591 2. Call start ble advertising. 592 3. Wait 5 seconds, to make sure advertiser times out. 593 4. Repeat steps 1-4 four times. 594 595 Expected Result: 596 Starting the advertising should succeed each time. 597 598 Returns: 599 Pass if True 600 Fail if False 601 602 TAGS: LE, Advertising, Concurrency 603 Priority: 1 604 """ 605 advertise_timeout_s = 4 606 num_iterations = 4 607 test_result = True 608 609 for i in range(0, num_iterations): 610 advertise_callback, advertise_data, advertise_settings = ( 611 generate_ble_advertise_objects(self.adv_ad.droid)) 612 613 self.adv_ad.droid.bleSetAdvertiseSettingsTimeout( 614 advertise_timeout_s * 1000) 615 616 self.adv_ad.droid.bleStartBleAdvertising(advertise_callback, 617 advertise_data, 618 advertise_settings) 619 try: 620 self.adv_ad.ed.pop_event(adv_succ.format(advertise_callback), 621 self.default_timeout) 622 except Empty as error: 623 self.log.error( 624 "Test failed with Empty error: {}".format(error)) 625 test_result = False 626 except concurrent.futures._base.TimeoutError as error: 627 self.log.debug( 628 "Test failed, filtering callback onSuccess never occurred: {}" 629 .format(error)) 630 631 if not test_result: 632 return test_result 633 634 time.sleep(advertise_timeout_s + 1) 635 636 return test_result 637