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