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