1#/usr/bin/env python3.4 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_utils.bt.BluetoothBaseTest import BluetoothBaseTest 27from acts.test_utils.bt.BleEnum import AdvertiseSettingsAdvertiseMode 28from acts.test_utils.bt.BleEnum import ScanSettingsCallbackType 29from acts.test_utils.bt.BleEnum import ScanSettingsScanMode 30from acts.test_utils.bt.bt_test_utils import adv_succ 31from acts.test_utils.bt.bt_test_utils import generate_ble_advertise_objects 32from acts.test_utils.bt.bt_test_utils import generate_ble_scan_objects 33from acts.test_utils.bt.bt_test_utils import get_advanced_droid_list 34from acts.test_utils.bt.bt_test_utils import reset_bluetooth 35from acts.test_utils.bt.bt_test_utils import scan_result 36from acts.test_utils.bt.bt_test_utils import take_btsnoop_logs 37 38 39class ConcurrentBleAdvertisingTest(BluetoothBaseTest): 40 default_timeout = 10 41 max_advertisements = 4 42 43 def __init__(self, controllers): 44 BluetoothBaseTest.__init__(self, controllers) 45 self.droid_list = get_advanced_droid_list(self.android_devices) 46 self.scn_ad = self.android_devices[0] 47 self.adv_ad = self.android_devices[1] 48 self.max_advertisements = self.droid_list[1]['max_advertisements'] 49 if self.max_advertisements == 0: 50 self.tests = () 51 return 52 53 def on_fail(self, test_name, begin_time): 54 self.log.debug( 55 "Test {} failed. Gathering bugreport and btsnoop logs".format( 56 test_name)) 57 take_btsnoop_logs(self.android_devices, self, test_name) 58 reset_bluetooth(self.android_devices) 59 60 def setup_test(self): 61 return reset_bluetooth(self.android_devices) 62 63 def _verify_n_advertisements(self, num_advertisements, filter_list): 64 test_result = False 65 address_list = [] 66 self.scn_ad.droid.bleSetScanSettingsCallbackType( 67 ScanSettingsCallbackType.CALLBACK_TYPE_ALL_MATCHES.value) 68 self.scn_ad.droid.bleSetScanSettingsScanMode( 69 ScanSettingsScanMode.SCAN_MODE_LOW_LATENCY.value) 70 self.adv_ad.droid.bleSetAdvertiseSettingsAdvertiseMode( 71 AdvertiseSettingsAdvertiseMode.ADVERTISE_MODE_LOW_LATENCY.value) 72 advertise_data = self.adv_ad.droid.bleBuildAdvertiseData() 73 advertise_settings = self.adv_ad.droid.bleBuildAdvertiseSettings() 74 advertise_callback_list = [] 75 for i in range(num_advertisements): 76 advertise_callback = self.adv_ad.droid.bleGenBleAdvertiseCallback() 77 advertise_callback_list.append(advertise_callback) 78 self.adv_ad.droid.bleStartBleAdvertising( 79 advertise_callback, advertise_data, advertise_settings) 80 try: 81 self.adv_ad.ed.pop_event( 82 adv_succ.format(advertise_callback), self.default_timeout) 83 self.log.info("Advertisement {} started.".format(i + 1)) 84 except Empty as error: 85 self.log.info("Advertisement {} failed to start.".format(i + 86 1)) 87 self.log.debug("Test failed with Empty error: {}".format( 88 error)) 89 return False 90 except concurrent.futures._base.TimeoutError as error: 91 self.log.debug( 92 "Test failed, filtering callback onSuccess never occurred: " 93 "{}".format(error)) 94 return False 95 scan_settings = self.scn_ad.droid.bleBuildScanSetting() 96 scan_callback = self.scn_ad.droid.bleGenScanCallback() 97 self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings, 98 scan_callback) 99 start_time = time.time() 100 while (start_time + self.default_timeout) > time.time(): 101 event = None 102 try: 103 event = self.scn_ad.ed.pop_event( 104 scan_result.format(scan_callback), self.default_timeout) 105 except Empty as error: 106 self.log.debug("Test failed with: {}".format(error)) 107 return test_result 108 except concurrent.futures._base.TimeoutError as error: 109 self.log.debug("Test failed with: {}".format(error)) 110 return test_result 111 address = event['data']['Result']['deviceInfo']['address'] 112 if address not in address_list: 113 address_list.append(address) 114 if len(address_list) == num_advertisements: 115 test_result = True 116 break 117 for callback in advertise_callback_list: 118 self.adv_ad.droid.bleStopBleAdvertising(callback) 119 self.scn_ad.droid.bleStopBleScan(scan_callback) 120 return test_result 121 122 @BluetoothBaseTest.bt_test_wrap 123 def test_max_advertisements_defaults(self): 124 """Testing max advertisements. 125 126 Test that a single device can have the max advertisements 127 concurrently advertising. 128 129 Steps: 130 1. Setup the scanning android device. 131 2. Setup the advertiser android device. 132 3. Start scanning on the max_advertisements as defined in the script. 133 4. Verify that all advertisements are found. 134 135 Expected Result: 136 All advertisements should start without errors. 137 138 Returns: 139 Pass if True 140 Fail if False 141 142 TAGS: LE, Advertising, Concurrency 143 Priority: 0 144 """ 145 test_result = True 146 filter_list = self.scn_ad.droid.bleGenFilterList() 147 self.scn_ad.droid.bleBuildScanFilter(filter_list) 148 test_result = self._verify_n_advertisements(self.max_advertisements, 149 filter_list) 150 return test_result 151 152 @BluetoothBaseTest.bt_test_wrap 153 def test_max_advertisements_include_device_name_and_filter_device_name( 154 self): 155 """Testing max advertisement variant. 156 157 Test that a single device can have the max advertisements 158 concurrently advertising. Include the device name as a part of the filter 159 and advertisement data. 160 161 Steps: 162 1. Setup the scanning android device. 163 2. Setup the advertiser android device. 164 3. Include device name in each advertisement. 165 4. Include device name filter in the scanner. 166 5. Start scanning on the max_advertisements as defined in the script. 167 6. Verify that all advertisements are found. 168 169 Expected Result: 170 All advertisements should start without errors. 171 172 Returns: 173 Pass if True 174 Fail if False 175 176 TAGS: LE, Advertising, Concurrency 177 Priority: 2 178 """ 179 test_result = True 180 self.adv_ad.droid.bleSetAdvertiseDataIncludeDeviceName(True) 181 filter_list = self.scn_ad.droid.bleGenFilterList() 182 self.scn_ad.droid.bleSetScanFilterDeviceName( 183 self.adv_ad.droid.bluetoothGetLocalName()) 184 self.scn_ad.droid.bleBuildScanFilter(filter_list) 185 test_result = self._verify_n_advertisements(self.max_advertisements, 186 filter_list) 187 return test_result 188 189 @BluetoothBaseTest.bt_test_wrap 190 def test_max_advertisements_exclude_device_name_and_filter_device_name( 191 self): 192 """Test max advertisement variant. 193 194 Test that a single device can have the max advertisements concurrently 195 advertising. Include the device name as a part of the filter but not the 196 advertisement data. 197 198 Steps: 199 1. Setup the scanning android device. 200 2. Setup the advertiser android device. 201 3. Include device name filter in the scanner. 202 4. Start scanning on the max_advertisements as defined in the script. 203 5. Verify that no advertisements are found. 204 205 Expected Result: 206 All advertisements should start without errors. 207 208 Returns: 209 Pass if True 210 Fail if False 211 212 TAGS: LE, Advertising, Concurrency 213 Priority: 2 214 """ 215 test_result = True 216 self.adv_ad.droid.bleSetAdvertiseDataIncludeDeviceName(False) 217 filter_list = self.scn_ad.droid.bleGenFilterList() 218 self.scn_ad.droid.bleSetScanFilterDeviceName( 219 self.adv_ad.droid.bluetoothGetLocalName()) 220 self.scn_ad.droid.bleBuildScanFilter(filter_list) 221 test_result = self._verify_n_advertisements(self.max_advertisements, 222 filter_list) 223 return not test_result 224 225 @BluetoothBaseTest.bt_test_wrap 226 def test_max_advertisements_with_manufacturer_data(self): 227 """Test max advertisement variant. 228 229 Test that a single device can have the max advertisements concurrently 230 advertising. Include the manufacturer data as a part of the filter and 231 advertisement data. 232 233 Steps: 234 1. Setup the scanning android device. 235 2. Setup the advertiser android device. 236 3. Include manufacturer data in each advertisement. 237 4. Include manufacturer data filter in the scanner. 238 5. Start scanning on the max_advertisements as defined in the script. 239 6. Verify that all advertisements are found. 240 241 Expected Result: 242 All advertisements should start without errors. 243 244 Returns: 245 Pass if True 246 Fail if False 247 248 TAGS: LE, Advertising, Concurrency 249 Priority: 2 250 """ 251 test_result = True 252 filter_list = self.scn_ad.droid.bleGenFilterList() 253 self.scn_ad.droid.bleSetScanFilterManufacturerData(1, "1") 254 self.scn_ad.droid.bleBuildScanFilter(filter_list) 255 self.adv_ad.droid.bleAddAdvertiseDataManufacturerId(1, "1") 256 test_result = self._verify_n_advertisements(self.max_advertisements, 257 filter_list) 258 return test_result 259 260 @BluetoothBaseTest.bt_test_wrap 261 def test_max_advertisements_with_manufacturer_data_mask(self): 262 """Test max advertisements variant. 263 264 Test that a single device can have the max advertisements concurrently 265 advertising. Include the manufacturer data mask as a part of the filter 266 and advertisement data. 267 268 Steps: 269 1. Setup the scanning android device. 270 2. Setup the advertiser android device. 271 3. Include manufacturer data in each advertisement. 272 4. Include manufacturer data mask filter in the scanner. 273 5. Start scanning on the max_advertisements as defined in the script. 274 6. Verify that all advertisements are found. 275 276 Expected Result: 277 All advertisements should start without errors. 278 279 Returns: 280 Pass if True 281 Fail if False 282 283 TAGS: LE, Advertising, Concurrency 284 Priority: 2 285 """ 286 test_result = True 287 filter_list = self.scn_ad.droid.bleGenFilterList() 288 self.scn_ad.droid.bleSetScanFilterManufacturerData(1, "1", "1") 289 self.scn_ad.droid.bleBuildScanFilter(filter_list) 290 self.adv_ad.droid.bleAddAdvertiseDataManufacturerId(1, "1") 291 test_result = self._verify_n_advertisements(self.max_advertisements, 292 filter_list) 293 return test_result 294 295 @BluetoothBaseTest.bt_test_wrap 296 def test_max_advertisements_with_service_data(self): 297 """Test max advertisement variant. 298 299 Test that a single device can have the max advertisements concurrently 300 advertising. Include the service data as a part of the filter and 301 advertisement data. 302 303 Steps: 304 1. Setup the scanning android device. 305 2. Setup the advertiser android device. 306 3. Include service data in each advertisement. 307 4. Include service data filter in the scanner. 308 5. Start scanning on the max_advertisements as defined in the script. 309 6. Verify that all advertisements are found. 310 311 Expected Result: 312 All advertisements should start without errors. 313 314 Returns: 315 Pass if True 316 Fail if False 317 318 TAGS: LE, Advertising, Concurrency 319 Priority: 2 320 """ 321 test_result = True 322 filter_list = self.scn_ad.droid.bleGenFilterList() 323 self.scn_ad.droid.bleSetScanFilterServiceData( 324 "0000110A-0000-1000-8000-00805F9B34FB", "11,17,80") 325 self.scn_ad.droid.bleBuildScanFilter(filter_list) 326 self.adv_ad.droid.bleAddAdvertiseDataServiceData( 327 "0000110A-0000-1000-8000-00805F9B34FB", "11,17,80") 328 test_result = self._verify_n_advertisements(self.max_advertisements, 329 filter_list) 330 return test_result 331 332 @BluetoothBaseTest.bt_test_wrap 333 def test_max_advertisements_with_manufacturer_data_mask_and_include_device_name( 334 self): 335 """Test max advertisement variant. 336 337 Test that a single device can have the max advertisements concurrently 338 advertising. Include the device name and manufacturer data as a part of 339 the filter and advertisement data. 340 341 Steps: 342 1. Setup the scanning android device. 343 2. Setup the advertiser android device. 344 3. Include device name and manufacturer data in each advertisement. 345 4. Include device name and manufacturer data filter in the scanner. 346 5. Start scanning on the max_advertisements as defined in the script. 347 6. Verify that all advertisements are found. 348 349 Expected Result: 350 All advertisements should start without errors. 351 352 Returns: 353 Pass if True 354 Fail if False 355 356 TAGS: LE, Advertising, Concurrency 357 Priority: 2 358 """ 359 test_result = True 360 filter_list = self.scn_ad.droid.bleGenFilterList() 361 self.adv_ad.droid.bleSetAdvertiseDataIncludeDeviceName(True) 362 self.scn_ad.droid.bleSetScanFilterDeviceName( 363 self.adv_ad.droid.bluetoothGetLocalName()) 364 self.scn_ad.droid.bleSetScanFilterManufacturerData(1, "1", "1") 365 self.scn_ad.droid.bleBuildScanFilter(filter_list) 366 self.adv_ad.droid.bleAddAdvertiseDataManufacturerId(1, "1") 367 test_result = self._verify_n_advertisements(self.max_advertisements, 368 filter_list) 369 return test_result 370 371 @BluetoothBaseTest.bt_test_wrap 372 def test_max_advertisements_with_service_uuids(self): 373 """Test max advertisement variant. 374 375 Test that a single device can have the max advertisements concurrently 376 advertising. Include the service uuid as a part of the filter and 377 advertisement data. 378 379 Steps: 380 1. Setup the scanning android device. 381 2. Setup the advertiser android device. 382 3. Include service uuid in each advertisement. 383 4. Include service uuid filter in the scanner. 384 5. Start scanning on the max_advertisements as defined in the script. 385 6. Verify that all advertisements are found. 386 387 Expected Result: 388 All advertisements should start without errors. 389 390 Returns: 391 Pass if True 392 Fail if False 393 394 TAGS: LE, Advertising, Concurrency 395 Priority: 1 396 """ 397 test_result = True 398 filter_list = self.scn_ad.droid.bleGenFilterList() 399 self.scn_ad.droid.bleSetScanFilterServiceUuid( 400 "00000000-0000-1000-8000-00805f9b34fb") 401 self.scn_ad.droid.bleBuildScanFilter(filter_list) 402 self.adv_ad.droid.bleSetAdvertiseDataSetServiceUuids( 403 ["00000000-0000-1000-8000-00805f9b34fb"]) 404 test_result = self._verify_n_advertisements(self.max_advertisements, 405 filter_list) 406 return test_result 407 408 @BluetoothBaseTest.bt_test_wrap 409 def test_max_advertisements_with_service_uuid_and_service_mask(self): 410 """Test max advertisements variant. 411 412 Test that a single device can have the max advertisements concurrently 413 advertising. Include the service mask as a part of the filter and 414 advertisement data. 415 416 Steps: 417 1. Setup the scanning android device. 418 2. Setup the advertiser android device. 419 3. Include service uuid in each advertisement. 420 4. Include service mask filter in the scanner. 421 5. Start scanning on the max_advertisements as defined in the script. 422 6. Verify that all advertisements are found. 423 424 Expected Result: 425 All advertisements should start without errors. 426 427 Returns: 428 Pass if True 429 Fail if False 430 431 TAGS: LE, Advertising, Concurrency 432 Priority: 2 433 """ 434 test_result = True 435 filter_list = self.scn_ad.droid.bleGenFilterList() 436 self.scn_ad.droid.bleSetScanFilterServiceUuid( 437 "00000000-0000-1000-8000-00805f9b34fb", 438 "00000000-0000-1000-8000-00805f9b34fb") 439 self.scn_ad.droid.bleBuildScanFilter(filter_list) 440 self.adv_ad.droid.bleSetAdvertiseDataSetServiceUuids( 441 ["00000000-0000-1000-8000-00805f9b34fb"]) 442 test_result = self._verify_n_advertisements(self.max_advertisements, 443 filter_list) 444 return test_result 445 446 @BluetoothBaseTest.bt_test_wrap 447 def test_max_advertisements_plus_one(self): 448 """Test max advertisements plus one. 449 450 Test that a single device can have the max advertisements concurrently 451 advertising but fail on starting the max advertisements plus one. 452 filter and advertisement data. 453 454 Steps: 455 1. Setup the scanning android device. 456 2. Setup the advertiser android device. 457 3. Start max_advertisements + 1. 458 459 Expected Result: 460 The last advertisement should fail. 461 462 Returns: 463 Pass if True 464 Fail if False 465 466 TAGS: LE, Advertising, Concurrency 467 Priority: 0 468 """ 469 test_result = True 470 filter_list = self.scn_ad.droid.bleGenFilterList() 471 self.scn_ad.droid.bleBuildScanFilter(filter_list) 472 test_result = self._verify_n_advertisements( 473 self.max_advertisements + 1, filter_list) 474 return not test_result 475 476 @BluetoothBaseTest.bt_test_wrap 477 def test_start_two_advertisements_on_same_callback(self): 478 """Test invalid advertisement scenario. 479 480 Test that a single device cannot have two advertisements start on the 481 same callback. 482 483 Steps: 484 1. Setup the scanning android device. 485 2. Setup the advertiser android device. 486 3. Call start ble advertising on the same callback. 487 488 Expected Result: 489 The second call of start advertising on the same callback should fail. 490 491 Returns: 492 Pass if True 493 Fail if False 494 495 TAGS: LE, Advertising, Concurrency 496 Priority: 1 497 """ 498 test_result = True 499 advertise_callback, advertise_data, advertise_settings = ( 500 generate_ble_advertise_objects(self.adv_ad.droid)) 501 self.adv_ad.droid.bleStartBleAdvertising( 502 advertise_callback, advertise_data, advertise_settings) 503 try: 504 self.adv_ad.ed.pop_event( 505 adv_succ.format(advertise_callback), self.default_timeout) 506 except Empty as error: 507 self.log.debug("Test failed with Empty error: {}".format(error)) 508 return False 509 except concurrent.futures._base.TimeoutError as error: 510 self.log.debug( 511 "Test failed, filtering callback onSuccess never occurred: {}" 512 .format(error)) 513 try: 514 self.adv_ad.droid.bleStartBleAdvertising( 515 advertise_callback, advertise_data, advertise_settings) 516 self.adv_ad.ed.pop_event( 517 adv_succ.format(advertise_callback), self.default_timeout) 518 test_result = False 519 except Empty as error: 520 self.log.debug("Test passed with Empty error: {}".format(error)) 521 except concurrent.futures._base.TimeoutError as error: 522 self.log.debug( 523 "Test passed, filtering callback onSuccess never occurred: {}" 524 .format(error)) 525 526 return test_result 527 528 @BluetoothBaseTest.bt_test_wrap 529 def test_toggle_advertiser_bt_state(self): 530 """Test forcing stopping advertisements. 531 532 Test that a single device resets its callbacks when the bluetooth state is 533 reset. There should be no advertisements. 534 535 Steps: 536 1. Setup the scanning android device. 537 2. Setup the advertiser android device. 538 3. Call start ble advertising. 539 4. Toggle bluetooth on and off. 540 5. Scan for any advertisements. 541 542 Expected Result: 543 No advertisements should be found after toggling Bluetooth on the 544 advertising device. 545 546 Returns: 547 Pass if True 548 Fail if False 549 550 TAGS: LE, Advertising, Concurrency 551 Priority: 2 552 """ 553 test_result = True 554 advertise_callback, advertise_data, advertise_settings = ( 555 generate_ble_advertise_objects(self.adv_ad.droid)) 556 self.adv_ad.droid.bleStartBleAdvertising( 557 advertise_callback, advertise_data, advertise_settings) 558 try: 559 self.adv_ad.ed.pop_event( 560 adv_succ.format(advertise_callback), self.default_timeout) 561 except Empty as error: 562 self.log.debug("Test failed with Empty error: {}".format(error)) 563 return False 564 except concurrent.futures._base.TimeoutError as error: 565 self.log.debug( 566 "Test failed, filtering callback onSuccess never occurred: {}".format( 567 error)) 568 filter_list, scan_settings, scan_callback = generate_ble_scan_objects( 569 self.scn_ad.droid) 570 self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings, 571 scan_callback) 572 try: 573 self.scn_ad.ed.pop_event( 574 scan_result.format(scan_callback), self.default_timeout) 575 except Empty as error: 576 self.log.debug("Test failed with: {}".format(error)) 577 return False 578 except concurrent.futures._base.TimeoutError as error: 579 self.log.debug("Test failed with: {}".format(error)) 580 return False 581 self.scn_ad.droid.bleStopBleScan(scan_callback) 582 test_result = reset_bluetooth([self.android_devices[1]]) 583 self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings, 584 scan_callback) 585 if not test_result: 586 return test_result 587 try: 588 self.scn_ad.ed.pop_event( 589 scan_result.format(scan_callback), self.default_timeout) 590 return False 591 except Empty as error: 592 self.log.debug("Test passed with: {}".format(error)) 593 except concurrent.futures._base.TimeoutError as error: 594 self.log.debug("Test passed with: {}".format(error)) 595 self.scn_ad.droid.bleStopBleScan(scan_callback) 596 self.adv_ad.droid.bleStopBleAdvertising(advertise_callback) 597 return test_result 598 599 @BluetoothBaseTest.bt_test_wrap 600 def test_restart_advertise_callback_after_bt_toggle(self): 601 """Test starting an advertisement on a cleared out callback. 602 603 Test that a single device resets its callbacks when the bluetooth state 604 is reset. 605 606 Steps: 607 1. Setup the scanning android device. 608 2. Setup the advertiser android device. 609 3. Call start ble advertising. 610 4. Toggle bluetooth on and off. 611 5. Call start ble advertising on the same callback. 612 613 Expected Result: 614 Starting an advertisement on a callback id after toggling bluetooth 615 should fail. 616 617 Returns: 618 Pass if True 619 Fail if False 620 621 TAGS: LE, Advertising, Concurrency 622 Priority: 1 623 """ 624 test_result = True 625 advertise_callback, advertise_data, advertise_settings = ( 626 generate_ble_advertise_objects(self.adv_ad.droid)) 627 self.adv_ad.droid.bleStartBleAdvertising( 628 advertise_callback, advertise_data, advertise_settings) 629 try: 630 self.adv_ad.ed.pop_event( 631 adv_succ.format(advertise_callback), self.default_timeout) 632 except Empty as error: 633 self.log.debug("Test failed with Empty error: {}".format(error)) 634 test_result = False 635 except concurrent.futures._base.TimeoutError as error: 636 self.log.debug( 637 "Test failed, filtering callback onSuccess never occurred: {}".format( 638 error)) 639 test_result = reset_bluetooth([self.android_devices[1]]) 640 if not test_result: 641 return test_result 642 self.adv_ad.droid.bleStartBleAdvertising( 643 advertise_callback, advertise_data, advertise_settings) 644 try: 645 self.adv_ad.ed.pop_event( 646 adv_succ.format(advertise_callback), self.default_timeout) 647 except Empty as error: 648 self.log.debug("Test failed with Empty error: {}".format(error)) 649 test_result = False 650 except concurrent.futures._base.TimeoutError as error: 651 self.log.debug( 652 "Test failed, filtering callback onSuccess never occurred: {}".format( 653 error)) 654 return test_result 655