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 """ 17 This test script exercises different filters and outcomes not exercised in 18 FilteringTest. 19 """ 20 21 import concurrent 22 import pprint 23 import time 24 25 from queue import Empty 26 from acts.test_utils.bt.BluetoothBaseTest import BluetoothBaseTest 27 from acts.test_utils.bt.BleEnum import AdvertiseSettingsAdvertiseMode 28 from acts.test_utils.bt.BleEnum import ScanSettingsScanMode 29 from acts.test_utils.bt.bt_test_utils import generate_ble_advertise_objects 30 from acts.test_utils.bt.bt_test_utils import generate_ble_scan_objects 31 from acts.test_utils.bt.bt_test_utils import get_advanced_droid_list 32 from acts.test_utils.bt.bt_test_utils import batch_scan_result 33 from acts.test_utils.bt.bt_test_utils import scan_result 34 35 36 class UniqueFilteringTest(BluetoothBaseTest): 37 default_timeout = 10 38 39 def __init__(self, controllers): 40 BluetoothBaseTest.__init__(self, controllers) 41 self.droid_list = get_advanced_droid_list(self.android_devices) 42 self.scn_ad = self.android_devices[0] 43 self.adv_ad = self.android_devices[1] 44 if self.droid_list[1]['max_advertisements'] == 0: 45 self.tests = () 46 return 47 48 def blescan_verify_onfailure_event_handler(self, event): 49 self.log.debug("Verifying onFailure event") 50 self.log.debug(pprint.pformat(event)) 51 return event 52 53 def blescan_verify_onscanresult_event_handler(self, 54 event, 55 expected_callbacktype=None, 56 system_time_nanos=None): 57 test_result = True 58 self.log.debug("Verifying onScanResult event") 59 self.log.debug(pprint.pformat(event)) 60 callbacktype = event['data']['CallbackType'] 61 if callbacktype != expected_callbacktype: 62 self.log.debug( 63 "Expected callback type: {}, Found callback type: {}" 64 .format(expected_callbacktype, callbacktype)) 65 test_result = False 66 return test_result 67 68 def blescan_get_mac_address_event_handler(self, event): 69 return event['data']['Result']['deviceInfo']['address'] 70 71 def blescan_verify_onbatchscanresult_event_handler( 72 self, 73 event, 74 system_time_nanos=None, 75 report_delay_nanos=None): 76 test_result = True 77 self.log.debug("Verifying onBatchScanResult event") 78 self.log.debug(pprint.pformat(event)) 79 for result in event['data']['Results']: 80 timestamp_nanos = result['timestampNanos'] 81 length_of_time = timestamp_nanos - system_time_nanos 82 self.log.debug("Difference in time in between scan start and " 83 "onBatchScanResult: {}".format(length_of_time)) 84 buffer = 1000000000 # 1 second 85 if length_of_time > (report_delay_nanos + buffer): 86 self.log.debug( 87 "Difference was greater than the allowable difference.") 88 test_result = False 89 return test_result 90 91 @BluetoothBaseTest.bt_test_wrap 92 def test_scan_flush_pending_scan_results(self): 93 """Test LE scan api flush pending results. 94 95 Test that flush pending scan results doesn't affect onScanResults from 96 triggering. 97 98 Steps: 99 1. Setup the scanning android device. 100 2. Setup the advertiser android devices. 101 3. Trigger bluetoothFlushPendingScanResults on the scanning droid. 102 4. Verify that only one onScanResults callback was triggered. 103 104 Expected Result: 105 After flushing pending scan results, make sure only one onScanResult 106 callback was triggered. 107 108 Returns: 109 Pass if True 110 Fail if False 111 112 TAGS: LE, Advertising, Filtering, Scanning 113 Priority: 1 114 """ 115 test_result = True 116 self.adv_ad.droid.bleSetAdvertiseSettingsAdvertiseMode( 117 AdvertiseSettingsAdvertiseMode.ADVERTISE_MODE_LOW_LATENCY.value) 118 filter_list, scan_settings, scan_callback = generate_ble_scan_objects( 119 self.scn_ad.droid) 120 expected_event_name = scan_result.format(scan_callback) 121 advertise_callback, advertise_data, advertise_settings = ( 122 generate_ble_advertise_objects(self.adv_ad.droid)) 123 self.adv_ad.droid.bleStartBleAdvertising( 124 advertise_callback, advertise_data, advertise_settings) 125 self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings, 126 scan_callback) 127 self.scn_ad.droid.bleFlushPendingScanResults(scan_callback) 128 worker = self.scn_ad.ed.handle_event( 129 self.blescan_verify_onscanresult_event_handler, 130 expected_event_name, ([1]), self.default_timeout) 131 try: 132 self.log.debug(worker.result(self.default_timeout)) 133 except Empty as error: 134 test_result = False 135 self.log.debug("Test failed with Empty error: {}".format(error)) 136 except concurrent.futures._base.TimeoutError as error: 137 test_result = False 138 self.log.debug("Test failed with TimeoutError: {}".format(error)) 139 self.scn_ad.droid.bleStopBleScan(scan_callback) 140 self.adv_ad.droid.bleStopBleAdvertising(advertise_callback) 141 return test_result 142 143 @BluetoothBaseTest.bt_test_wrap 144 def test_scan_trigger_on_batch_scan_results(self): 145 """Test triggering batch scan results. 146 147 Test that triggers onBatchScanResults and verifies the time to trigger 148 within one second leeway. 149 150 Steps: 151 1. Setup the scanning android device with report delay seconds set to 152 5000. 153 2. Setup the advertiser android devices. 154 3. Verify that only one onBatchScanResult callback was triggered. 155 4. Compare the system time that the scan was started with the elapsed 156 time that is in the callback. 157 158 Expected Result: 159 The scan event dispatcher should find an onBatchScanResult event. 160 161 Returns: 162 Pass if True 163 Fail if False 164 165 TAGS: LE, Advertising, Filtering, Scanning, Batch Scanning 166 Priority: 2 167 """ 168 test_result = True 169 self.scn_ad.droid.bleSetScanSettingsReportDelayMillis(5000) 170 filter_list, scan_settings, scan_callback = generate_ble_scan_objects( 171 self.scn_ad.droid) 172 expected_event_name = batch_scan_result.format(scan_callback) 173 self.adv_ad.droid.bleSetAdvertiseDataIncludeDeviceName(True) 174 self.adv_ad.droid.bleSetAdvertiseDataIncludeTxPowerLevel(True) 175 advertise_callback, advertise_data, advertise_settings = ( 176 generate_ble_advertise_objects(self.adv_ad.droid)) 177 self.adv_ad.droid.bleStartBleAdvertising( 178 advertise_callback, advertise_data, advertise_settings) 179 self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings, 180 scan_callback) 181 system_time_nanos = self.scn_ad.droid.getSystemElapsedRealtimeNanos() 182 self.log.debug("Current system time: {}".format(system_time_nanos)) 183 worker = self.scn_ad.ed.handle_event( 184 self.blescan_verify_onbatchscanresult_event_handler, 185 expected_event_name, ([system_time_nanos, 5000000000]), 186 self.default_timeout) 187 try: 188 self.log.debug(worker.result(self.default_timeout)) 189 except Empty as error: 190 test_result = False 191 self.log.debug("Test failed with: {}".format(error)) 192 except concurrent.futures._base.TimeoutError as error: 193 test_result = False 194 self.log.debug("Test failed with: {}".format(error)) 195 self.scn_ad.droid.bleStopBleScan(scan_callback) 196 self.adv_ad.droid.bleStopBleAdvertising(advertise_callback) 197 return test_result 198 199 @BluetoothBaseTest.bt_test_wrap 200 def test_scan_flush_results_without_on_batch_scan_results_triggered(self): 201 """Test that doesn't expect a batch scan result. 202 203 Test flush pending scan results with a report delay seconds set to 0. 204 No onBatchScanResults callback should be triggered. 205 206 Steps: 207 1. Setup the scanning android device with report delay seconds set to 0 208 (or just use default). 209 2. Setup the advertiser android devices. 210 211 Expected Result: 212 Verify that no onBatchScanResults were triggered. 213 214 Returns: 215 Pass if True 216 Fail if False 217 218 TAGS: LE, Advertising, Filtering, Scanning, Batch Scanning 219 Priority: 2 220 """ 221 test_result = True 222 filter_list, scan_settings, scan_callback = generate_ble_scan_objects( 223 self.scn_ad.droid) 224 expected_event_name = batch_scan_result.format(scan_callback) 225 advertise_callback, advertise_data, advertise_settings = ( 226 generate_ble_advertise_objects(self.adv_ad.droid)) 227 self.adv_ad.droid.bleStartBleAdvertising( 228 advertise_callback, advertise_data, advertise_settings) 229 self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings, 230 scan_callback) 231 worker = self.scn_ad.ed.handle_event( 232 self.blescan_verify_onbatchscanresult_event_handler, 233 expected_event_name, ([]), self.default_timeout) 234 self.scn_ad.droid.bleFlushPendingScanResults(scan_callback) 235 try: 236 event_info = self.scn_ad.ed.pop_event(expected_event_name, 10) 237 self.log.debug("Unexpectedly found an advertiser: {}".format( 238 event_info)) 239 test_result = False 240 except Empty: 241 self.log.debug("No {} events were found as expected.".format( 242 batch_scan_result)) 243 self.scn_ad.droid.bleStopBleScan(scan_callback) 244 self.adv_ad.droid.bleStopBleAdvertising(advertise_callback) 245 return test_result 246 247 @BluetoothBaseTest.bt_test_wrap 248 def test_scan_non_existent_name_filter(self): 249 """Test non-existent name filter. 250 251 Test scan filter on non-existent device name. 252 253 Steps: 254 1. Setup the scanning android device with scan filter for device name 255 set to an unexpected value. 256 2. Setup the advertiser android devices. 257 3. Verify that no onScanResults were triggered. 258 259 Expected Result: 260 No advertisements were found. 261 262 Returns: 263 Pass if True 264 Fail if False 265 266 TAGS: LE, Advertising, Filtering, Scanning 267 Priority: 2 268 """ 269 test_result = True 270 filter_name = "{}_probably_wont_find".format( 271 self.adv_ad.droid.bluetoothGetLocalName()) 272 self.adv_ad.droid.bleSetAdvertiseDataIncludeDeviceName(True) 273 self.scn_ad.droid.bleSetScanFilterDeviceName(filter_name) 274 filter_list, scan_settings, scan_callback = generate_ble_scan_objects( 275 self.scn_ad.droid) 276 self.scn_ad.droid.bleBuildScanFilter(filter_list) 277 expected_event_name = scan_result.format(scan_callback) 278 self.adv_ad.droid.bleSetAdvertiseDataIncludeDeviceName(True) 279 self.adv_ad.droid.bleSetAdvertiseDataIncludeTxPowerLevel(True) 280 advertise_callback, advertise_data, advertise_settings = ( 281 generate_ble_advertise_objects(self.adv_ad.droid)) 282 self.adv_ad.droid.bleStartBleAdvertising( 283 advertise_callback, advertise_data, advertise_settings) 284 self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings, 285 scan_callback) 286 try: 287 event_info = self.scn_ad.ed.pop_event(expected_event_name, 288 self.default_timeout) 289 self.log.error("Unexpectedly found an advertiser: {}".format( 290 event_info)) 291 test_result = False 292 except Empty: 293 self.log.debug("No events were found as expected.") 294 self.scn_ad.droid.bleStopBleScan(scan_callback) 295 self.adv_ad.droid.bleStopBleAdvertising(advertise_callback) 296 return test_result 297 298 @BluetoothBaseTest.bt_test_wrap 299 def test_scan_advertisement_with_device_service_uuid_filter_expect_no_events( 300 self): 301 """Test scan filtering against an advertisement with no data. 302 303 Test that exercises a service uuid filter on the scanner but no server 304 uuid added to the advertisement. 305 306 Steps: 307 1. Setup the scanning android device with scan filter including a 308 service uuid and mask. 309 2. Setup the advertiser android devices. 310 3. Verify that no onScanResults were triggered. 311 312 Expected Result: 313 Verify no advertisements found. 314 315 Returns: 316 Pass if True 317 Fail if False 318 319 TAGS: LE, Advertising, Filtering, Scanning 320 Priority: 1 321 """ 322 test_result = True 323 service_uuid = "00000000-0000-1000-8000-00805F9B34FB" 324 service_mask = "00000000-0000-1000-8000-00805F9B34FA" 325 self.adv_ad.droid.bleSetAdvertiseDataIncludeDeviceName(True) 326 self.scn_ad.droid.bleSetScanFilterServiceUuid(service_uuid, 327 service_mask) 328 self.adv_ad.droid.bleSetAdvertiseSettingsAdvertiseMode( 329 AdvertiseSettingsAdvertiseMode.ADVERTISE_MODE_LOW_LATENCY.value) 330 filter_list, scan_settings, scan_callback = generate_ble_scan_objects( 331 self.scn_ad.droid) 332 self.scn_ad.droid.bleBuildScanFilter(filter_list) 333 expected_event_name = scan_result.format(scan_callback) 334 self.adv_ad.droid.bleSetAdvertiseDataIncludeDeviceName(True) 335 self.adv_ad.droid.bleSetAdvertiseDataIncludeTxPowerLevel(True) 336 advertise_callback, advertise_data, advertise_settings = ( 337 generate_ble_advertise_objects(self.adv_ad.droid)) 338 self.adv_ad.droid.bleStartBleAdvertising( 339 advertise_callback, advertise_data, advertise_settings) 340 self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings, 341 scan_callback) 342 worker = self.scn_ad.ed.handle_event( 343 self.blescan_verify_onscanresult_event_handler, 344 expected_event_name, ([1]), self.default_timeout) 345 try: 346 event_info = self.scn_ad.ed.pop_event(expected_event_name, 347 self.default_timeout) 348 self.log.error("Unexpectedly found an advertiser:".format( 349 event_info)) 350 test_result = False 351 except Empty as error: 352 self.log.debug("No events were found as expected.") 353 self.scn_ad.droid.bleStopBleScan(scan_callback) 354 self.adv_ad.droid.bleStopBleAdvertising(advertise_callback) 355 return test_result 356 357 @BluetoothBaseTest.bt_test_wrap 358 def test_scan_filtering_multiple_advertisements_manufacturer_data(self): 359 """Test scan filtering against multiple varying advertisements. 360 361 Test scan filtering against multiple varying advertisements. The first 362 advertisement will have partial manufacturer data that matches the 363 the full manufacturer data in the second advertisement. 364 365 Steps: 366 1. Setup up an advertisement with manufacturer data "1,2,3". 367 2. Setup a second advertisement with manufacturer data 368 "1,2,3,4,5,6,7,8". 369 3. Start advertising on each advertisement. 370 4. Create a scan filter that includes manufacturer data "1,2,3". 371 372 Expected Result: 373 TBD. Right now Shamu finds only the first advertisement with 374 manufacturer data "1,2,3". 375 376 Returns: 377 Pass if True 378 Fail if False 379 380 TAGS: LE, Advertising, Filtering, Scanning 381 Priority: 2 382 """ 383 test_result = True 384 self.adv_ad.droid.bleSetAdvertiseSettingsAdvertiseMode( 385 AdvertiseSettingsAdvertiseMode.ADVERTISE_MODE_LOW_LATENCY.value) 386 self.adv_ad.droid.bleAddAdvertiseDataManufacturerId(117, "1,2,3") 387 advertise_callback, advertise_data, advertise_settings = ( 388 generate_ble_advertise_objects(self.adv_ad.droid)) 389 self.adv_ad.droid.bleSetAdvertiseSettingsAdvertiseMode( 390 AdvertiseSettingsAdvertiseMode.ADVERTISE_MODE_LOW_LATENCY.value) 391 self.adv_ad.droid.bleAddAdvertiseDataManufacturerId(117, 392 "1,2,3,4,5,6,7,8") 393 advertise_callback1, advertise_data1, advertise_settings1 = ( 394 generate_ble_advertise_objects(self.adv_ad.droid)) 395 self.adv_ad.droid.bleStartBleAdvertising( 396 advertise_callback, advertise_data, advertise_settings) 397 self.adv_ad.droid.bleStartBleAdvertising( 398 advertise_callback1, advertise_data1, advertise_settings1) 399 400 filter_list = self.scn_ad.droid.bleGenFilterList() 401 self.scn_ad.droid.bleSetScanSettingsScanMode( 402 ScanSettingsScanMode.SCAN_MODE_LOW_LATENCY.value) 403 scan_settings = self.scn_ad.droid.bleBuildScanSetting() 404 scan_callback = self.scn_ad.droid.bleGenScanCallback() 405 self.scn_ad.droid.bleSetScanFilterManufacturerData(117, "1,2,3", 406 "127,127,127") 407 self.scn_ad.droid.bleBuildScanFilter(filter_list) 408 self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings, 409 scan_callback) 410 return test_result 411 412 @BluetoothBaseTest.bt_test_wrap 413 def test_scan_filter_device_address(self): 414 """Test scan filtering of a device address. 415 416 This test will have to create two scanning instances. The first will 417 have no filters and will find the generic advertisement's mac address. 418 The second will have a filter of the found mac address. 419 420 Steps: 421 1. Start a generic advertisement. 422 2. Start a generic scanner. 423 3. Find the advertisement and extract the mac address. 424 4. Stop the first scanner. 425 5. Create a new scanner with scan filter with a mac address filter of 426 what was found in step 3. 427 6. Start the scanner. 428 429 Expected Result: 430 Verify that the advertisement was found in the second scan instance. 431 432 Returns: 433 Pass if True 434 Fail if False 435 436 TAGS: LE, Advertising, Filtering, Scanning 437 Priority: 1 438 """ 439 test_result = True 440 self.scn_ad.droid.bleSetScanSettingsScanMode( 441 ScanSettingsScanMode.SCAN_MODE_LOW_LATENCY.value) 442 filter_list, scan_settings, scan_callback = generate_ble_scan_objects( 443 self.scn_ad.droid) 444 expected_event_name = scan_result.format(scan_callback) 445 self.adv_ad.droid.bleSetAdvertiseSettingsAdvertiseMode( 446 AdvertiseSettingsAdvertiseMode.ADVERTISE_MODE_LOW_LATENCY.value) 447 advertise_callback, advertise_data, advertise_settings = ( 448 generate_ble_advertise_objects(self.adv_ad.droid)) 449 self.adv_ad.droid.bleStartBleAdvertising( 450 advertise_callback, advertise_data, advertise_settings) 451 self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings, 452 scan_callback) 453 event_info = self.scn_ad.ed.pop_event(expected_event_name, 454 self.default_timeout) 455 mac_address = event_info['data']['Result']['deviceInfo']['address'] 456 self.log.info("Filter advertisement with address {}".format( 457 mac_address)) 458 self.scn_ad.droid.bleStopBleScan(scan_callback) 459 self.scn_ad.droid.bleSetScanSettingsScanMode( 460 ScanSettingsScanMode.SCAN_MODE_LOW_LATENCY.value) 461 self.scn_ad.droid.bleSetScanFilterDeviceAddress(mac_address) 462 filter_list2, scan_settings2, scan_callback2 = ( 463 generate_ble_scan_objects(self.scn_ad.droid)) 464 465 self.scn_ad.droid.bleBuildScanFilter(filter_list2) 466 self.scn_ad.droid.bleStartBleScan(filter_list2, scan_settings2, 467 scan_callback2) 468 expected_event_name = scan_result.format(scan_callback2) 469 found_event = self.scn_ad.ed.pop_event(expected_event_name, 470 self.default_timeout) 471 if (found_event['data']['Result']['deviceInfo']['address'] != 472 mac_address): 473 test_result = False 474 self.scn_ad.droid.bleStopBleScan(scan_callback2) 475 self.adv_ad.droid.bleStopBleAdvertising(advertise_callback) 476 return test_result 477