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