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""" 17This test script exercises different Bluetooth 5 specific scan scenarios. 18It is expected that the second AndroidDevice is able to advertise. 19 20This test script was designed with this setup in mind: 21Shield box one: Android Device, Android Device 22""" 23 24from queue import Empty 25 26from acts import asserts 27from acts.test_decorators import test_tracker_info 28from acts.test_utils.bt.BluetoothBaseTest import BluetoothBaseTest 29from acts.test_utils.bt.bt_constants import ble_scan_settings_phys 30from acts.test_utils.bt.bt_constants import ble_scan_settings_modes 31from acts.test_utils.bt.bt_test_utils import batch_scan_result 32from acts.test_utils.bt.bt_test_utils import cleanup_scanners_and_advertisers 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 reset_bluetooth 36from acts.test_utils.bt.bt_constants import scan_result 37from acts.test_utils.bt.bt_test_utils import advertising_set_on_own_address_read 38from acts.test_utils.bt.bt_test_utils import advertising_set_started 39from acts import signals 40 41 42class Bt5ScanTest(BluetoothBaseTest): 43 default_timeout = 10 44 report_delay = 2000 45 scan_callbacks = [] 46 adv_callbacks = [] 47 active_scan_callback_list = [] 48 big_adv_data = { 49 "includeDeviceName": True, 50 "manufacturerData": [0x0123, "00112233445566778899AABBCCDDEE"], 51 "manufacturerData2": 52 [0x2540, [0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0xFF]], 53 "serviceData": [ 54 "b19d42dc-58ba-4b20-b6c1-6628e7d21de4", 55 "00112233445566778899AABBCCDDEE" 56 ], 57 "serviceData2": [ 58 "000042dc-58ba-4b20-b6c1-6628e7d21de4", 59 [0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0xFF] 60 ] 61 } 62 63 def __init__(self, controllers): 64 BluetoothBaseTest.__init__(self, controllers) 65 self.scn_ad = self.android_devices[0] 66 self.adv_ad = self.android_devices[1] 67 68 def setup_class(self): 69 if not self.scn_ad.droid.bluetoothIsLeExtendedAdvertisingSupported(): 70 raise signals.TestSkipClass( 71 "Scanner does not support LE Extended Advertising") 72 73 if not self.adv_ad.droid.bluetoothIsLeExtendedAdvertisingSupported(): 74 raise signals.TestSkipClass( 75 "Advertiser does not support LE Extended Advertising") 76 77 def teardown_test(self): 78 cleanup_scanners_and_advertisers( 79 self.scn_ad, self.active_scan_callback_list, self.adv_ad, []) 80 self.active_scan_callback_list = [] 81 82 def on_exception(self, test_name, begin_time): 83 reset_bluetooth(self.android_devices) 84 85 # This one does not relly test anything, but display very helpful 86 # information that might help with debugging. 87 @BluetoothBaseTest.bt_test_wrap 88 @test_tracker_info(uuid='787e0877-269f-4b9b-acb0-b98a8bb3770a') 89 def test_capabilities(self): 90 """Test capabilities 91 92 Test BT 5.0 scan scapabilities 93 94 Steps: 95 1. Test various vapabilities. 96 97 Expected Result: 98 Pass 99 100 Returns: 101 Pass if True 102 Fail if False 103 104 TAGS: BT5.0, Scanning 105 Priority: 2 106 """ 107 d = self.scn_ad.droid 108 sup2M = d.bluetoothIsLe2MPhySupported() 109 supCoded = d.bluetoothIsLeCodedPhySupported() 110 supExt = d.bluetoothIsLeExtendedAdvertisingSupported() 111 supPeriodic = d.bluetoothIsLePeriodicAdvertisingSupported() 112 maxDataLen = d.bluetoothGetLeMaximumAdvertisingDataLength() 113 self.log.info("Scanner capabilities:") 114 self.log.info("LE 2M: " + str(sup2M) + ", LE Coded: " + str( 115 supCoded) + ", LE Extended Advertising: " + str( 116 supExt) + ", LE Periodic Advertising: " + str(supPeriodic) + 117 ", maximum advertising data length: " + str(maxDataLen)) 118 d = self.adv_ad.droid 119 sup2M = d.bluetoothIsLe2MPhySupported() 120 supCoded = d.bluetoothIsLeCodedPhySupported() 121 supExt = d.bluetoothIsLeExtendedAdvertisingSupported() 122 supPeriodic = d.bluetoothIsLePeriodicAdvertisingSupported() 123 maxDataLen = d.bluetoothGetLeMaximumAdvertisingDataLength() 124 self.log.info("Advertiser capabilities:") 125 self.log.info("LE 2M: " + str(sup2M) + ", LE Coded: " + str( 126 supCoded) + ", LE Extended Advertising: " + str( 127 supExt) + ", LE Periodic Advertising: " + str(supPeriodic) + 128 ", maximum advertising data length: " + str(maxDataLen)) 129 return True 130 131 @BluetoothBaseTest.bt_test_wrap 132 @test_tracker_info(uuid='62d36679-bb91-465e-897f-2635433aac2f') 133 def test_1m_1m_extended_scan(self): 134 """Test scan on LE 1M PHY using LE 1M PHY as secondary. 135 136 Tests test verify that device is able to receive extended advertising 137 on 1M PHY when secondary is 1M PHY. 138 139 Steps: 140 1. Start advertising set on dut1 141 2. Start scanning on dut0, scan filter set to advertiser's device name 142 3. Try to find an event, expect found 143 4. Stop advertising 144 145 Expected Result: 146 Scan finds a advertisement. 147 148 Returns: 149 Pass if True 150 Fail if False 151 152 TAGS: LE Advertising Extension, BT5, LE, Advertising, Scanning 153 Priority: 1 154 """ 155 adv_callback = self.adv_ad.droid.bleAdvSetGenCallback() 156 self.adv_ad.droid.bleAdvSetStartAdvertisingSet({ 157 "connectable": True, 158 "legacyMode": False, 159 "primaryPhy": "PHY_LE_1M", 160 "secondaryPhy": "PHY_LE_1M", 161 "interval": 320 162 }, self.big_adv_data, None, None, None, 0, 0, adv_callback) 163 164 self.scn_ad.droid.bleSetScanSettingsLegacy(False) 165 self.scn_ad.droid.bleSetScanSettingsPhy(ble_scan_settings_phys['1m']) 166 167 filter_list, scan_settings, scan_callback = generate_ble_scan_objects( 168 self.scn_ad.droid) 169 170 adv_device_name = self.adv_ad.droid.bluetoothGetLocalName() 171 self.scn_ad.droid.bleSetScanFilterDeviceName(adv_device_name) 172 self.scn_ad.droid.bleBuildScanFilter(filter_list) 173 self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings, 174 scan_callback) 175 self.active_scan_callback_list.append(scan_callback) 176 177 try: 178 self.scn_ad.ed.pop_event( 179 scan_result.format(scan_callback), self.default_timeout) 180 except Empty: 181 self.log.error("Scan result not found") 182 self.adv_ad.droid.bleAdvSetStopAdvertisingSet(adv_callback) 183 return False 184 185 self.adv_ad.droid.bleAdvSetStopAdvertisingSet(adv_callback) 186 return True 187 188 @BluetoothBaseTest.bt_test_wrap 189 @test_tracker_info(uuid='3e3c9757-f7b6-4d1d-a2d6-8e2330d1a18e') 190 def test_1m_2m_extended_scan(self): 191 """Test scan on LE 1M PHY using LE 2M PHY as secondary. 192 193 Tests test verify that device is able to receive extended advertising 194 on 1M PHY when secondary is 2M PHY. 195 196 Steps: 197 1. Start advertising set on dut1 198 2. Start scanning on dut0, scan filter set to advertiser's device name 199 3. Try to find an event, expect found 200 4. Stop advertising 201 202 Expected Result: 203 Scan finds a advertisement. 204 205 Returns: 206 Pass if True 207 Fail if False 208 209 TAGS: LE Advertising Extension, BT5, LE, Advertising, Scanning 210 Priority: 1 211 """ 212 adv_callback = self.adv_ad.droid.bleAdvSetGenCallback() 213 self.adv_ad.droid.bleAdvSetStartAdvertisingSet({ 214 "connectable": True, 215 "legacyMode": False, 216 "primaryPhy": "PHY_LE_1M", 217 "secondaryPhy": "PHY_LE_2M", 218 "interval": 320 219 }, self.big_adv_data, None, None, None, 0, 0, adv_callback) 220 221 self.scn_ad.droid.bleSetScanSettingsLegacy(False) 222 self.scn_ad.droid.bleSetScanSettingsPhy(ble_scan_settings_phys['1m']) 223 224 filter_list, scan_settings, scan_callback = generate_ble_scan_objects( 225 self.scn_ad.droid) 226 227 adv_device_name = self.adv_ad.droid.bluetoothGetLocalName() 228 self.scn_ad.droid.bleSetScanFilterDeviceName(adv_device_name) 229 self.scn_ad.droid.bleBuildScanFilter(filter_list) 230 self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings, 231 scan_callback) 232 self.active_scan_callback_list.append(scan_callback) 233 234 try: 235 self.scn_ad.ed.pop_event( 236 scan_result.format(scan_callback), self.default_timeout) 237 except Empty: 238 self.log.error("Scan result not found") 239 self.adv_ad.droid.bleAdvSetStopAdvertisingSet(adv_callback) 240 return False 241 242 self.adv_ad.droid.bleAdvSetStopAdvertisingSet(adv_callback) 243 return True 244 245 @BluetoothBaseTest.bt_test_wrap 246 @test_tracker_info(uuid='236e9e5b-3853-4762-81ae-e88db03d74f3') 247 def test_legacy_scan_result_raw_length(self): 248 """Test that raw scan record data in legacy scan is 62 bytes long. 249 250 This is required for compability with older apps that make this 251 assumption. 252 253 Steps: 254 1. Start legacy advertising set on dut1 255 2. Start scanning on dut0, scan filter set to advertiser's device name 256 3. Try to find an event, expect found, verify scan recurd data length 257 4. Stop advertising 258 259 Expected Result: 260 Scan finds a legacy advertisement of proper size 261 262 Returns: 263 Pass if True 264 Fail if False 265 266 TAGS: LE Advertising Extension, BT5, LE, Advertising, Scanning 267 Priority: 1 268 """ 269 adv_callback = self.adv_ad.droid.bleAdvSetGenCallback() 270 self.adv_ad.droid.bleAdvSetStartAdvertisingSet({ 271 "connectable": True, 272 "scannable": True, 273 "legacyMode": True, 274 "interval": 320 275 }, {"includeDeviceName": True}, None, None, None, 0, 0, adv_callback) 276 277 self.scn_ad.droid.bleSetScanSettingsLegacy(True) 278 self.scn_ad.droid.bleSetScanSettingsPhy(ble_scan_settings_phys['1m']) 279 280 filter_list, scan_settings, scan_callback = generate_ble_scan_objects( 281 self.scn_ad.droid) 282 283 adv_device_name = self.adv_ad.droid.bluetoothGetLocalName() 284 self.scn_ad.droid.bleSetScanFilterDeviceName(adv_device_name) 285 self.scn_ad.droid.bleBuildScanFilter(filter_list) 286 self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings, 287 scan_callback) 288 self.active_scan_callback_list.append(scan_callback) 289 290 try: 291 evt = self.scn_ad.ed.pop_event( 292 scan_result.format(scan_callback), self.default_timeout) 293 rawData = evt['data']['Result']['scanRecord'] 294 asserts.assert_true(62 == len(rawData.split(",")), 295 "Raw data should be 62 bytes long.") 296 except Empty: 297 self.log.error("Scan result not found") 298 self.adv_ad.droid.bleAdvSetStopAdvertisingSet(adv_callback) 299 return False 300 301 self.adv_ad.droid.bleAdvSetStopAdvertisingSet(adv_callback) 302 return True 303 304 @BluetoothBaseTest.bt_test_wrap 305 @test_tracker_info(uuid='04632d8d-4303-476f-8f83-52c16be3713a') 306 def test_duration(self): 307 """Test scanning duration 308 309 Tests BT5.0 scanning duration 310 311 Steps: 312 1. Start advertising set 313 2. Start 5.0 scan 314 3. Scan for advertisement event 315 316 Expected Result: 317 Scan finds a legacy advertisement of proper size 318 319 Returns: 320 Pass if True 321 Fail if False 322 323 TAGS: BT5.0, LE, Advertising, Scanning 324 Priority: 1 325 """ 326 adv_callback = self.adv_ad.droid.bleAdvSetGenCallback() 327 self.adv_ad.droid.bleAdvSetStartAdvertisingSet({ 328 "connectable": True, 329 "legacyMode": False, 330 "primaryPhy": "PHY_LE_1M", 331 "secondaryPhy": "PHY_LE_2M", 332 "interval": 320 333 }, self.big_adv_data, None, None, None, 0, 0, adv_callback) 334 335 self.scn_ad.droid.bleSetScanSettingsLegacy(False) 336 self.scn_ad.droid.bleSetScanSettingsPhy(ble_scan_settings_phys['1m']) 337 338 filter_list, scan_settings, scan_callback = generate_ble_scan_objects( 339 self.scn_ad.droid) 340 341 adv_device_name = self.adv_ad.droid.bluetoothGetLocalName() 342 self.scn_ad.droid.bleSetScanFilterDeviceName(adv_device_name) 343 self.scn_ad.droid.bleBuildScanFilter(filter_list) 344 self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings, 345 scan_callback) 346 self.active_scan_callback_list.append(scan_callback) 347 348 try: 349 self.scn_ad.ed.pop_event( 350 scan_result.format(scan_callback), self.default_timeout) 351 except Empty: 352 self.log.error("Scan result not found") 353 self.adv_ad.droid.bleAdvSetStopAdvertisingSet(adv_callback) 354 return False 355 356 self.adv_ad.droid.bleAdvSetStopAdvertisingSet(adv_callback) 357 return True 358 359 @BluetoothBaseTest.bt_test_wrap 360 @test_tracker_info(uuid='a3704083-0f5c-4a46-b979-32ebc594d6ee') 361 def test_anonymous_advertising(self): 362 """Test anonymous advertising. 363 364 Tests test verify that device is able to receive anonymous advertising 365 on 1M PHY when secondary is 2M PHY. 366 367 Steps: 368 1. Start anonymous advertising set on dut1 369 2. Start scanning on dut0, scan filter set to advertiser's device name 370 3. Try to find an event, expect found 371 4. Stop advertising 372 373 Expected Result: 374 Scan finds a advertisement. 375 376 Returns: 377 Pass if True 378 Fail if False 379 380 TAGS: LE Advertising Extension, BT5, LE, Advertising, Scanning 381 Priority: 1 382 """ 383 adv_callback = self.adv_ad.droid.bleAdvSetGenCallback() 384 self.adv_ad.droid.bleAdvSetStartAdvertisingSet({ 385 "connectable": False, 386 "anonymous": True, 387 "legacyMode": False, 388 "primaryPhy": "PHY_LE_1M", 389 "secondaryPhy": "PHY_LE_2M", 390 "interval": 320 391 }, self.big_adv_data, None, None, None, 0, 0, adv_callback) 392 393 self.scn_ad.droid.bleSetScanSettingsLegacy(False) 394 self.scn_ad.droid.bleSetScanSettingsPhy(ble_scan_settings_phys['1m']) 395 396 filter_list, scan_settings, scan_callback = generate_ble_scan_objects( 397 self.scn_ad.droid) 398 399 adv_device_name = self.adv_ad.droid.bluetoothGetLocalName() 400 self.scn_ad.droid.bleSetScanFilterDeviceName(adv_device_name) 401 self.scn_ad.droid.bleBuildScanFilter(filter_list) 402 self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings, 403 scan_callback) 404 self.active_scan_callback_list.append(scan_callback) 405 406 try: 407 evt = self.scn_ad.ed.pop_event( 408 scan_result.format(scan_callback), self.default_timeout) 409 address = evt['data']['Result']['deviceInfo']['address'] 410 asserts.assert_true( 411 '00:00:00:00:00:00' == address, 412 "Anonymous address should be 00:00:00:00:00:00, but was " + 413 str(address)) 414 except Empty: 415 self.log.error("Scan result not found") 416 self.adv_ad.droid.bleAdvSetStopAdvertisingSet(adv_callback) 417 return False 418 419 self.adv_ad.droid.bleAdvSetStopAdvertisingSet(adv_callback) 420 return True 421 422 @BluetoothBaseTest.bt_test_wrap 423 @test_tracker_info(uuid='e3277355-eebf-4760-9502-e49a9289f6ab') 424 def test_get_own_address(self): 425 """Test obtaining own address for PTS. 426 427 Test obtaining own address. 428 429 Steps: 430 1. Start advertising set dut1 431 2. Grab address 432 3. Stop advertising 433 434 Expected Result: 435 Callback with address is received. 436 437 Returns: 438 Pass if True 439 Fail if False 440 441 TAGS: LE Advertising Extension, BT5, LE, Advertising 442 Priority: 1 443 """ 444 adv_callback = self.adv_ad.droid.bleAdvSetGenCallback() 445 self.adv_ad.droid.bleAdvSetStartAdvertisingSet({ 446 "connectable": False, 447 "anonymous": True, 448 "legacyMode": False, 449 "primaryPhy": "PHY_LE_1M", 450 "secondaryPhy": "PHY_LE_2M", 451 "interval": 320 452 }, self.big_adv_data, None, None, None, 0, 0, adv_callback) 453 454 set_id = -1 455 456 try: 457 evt = self.adv_ad.ed.pop_event( 458 advertising_set_started.format(adv_callback), 459 self.default_timeout) 460 self.log.info("data: " + str(evt['data'])) 461 set_id = evt['data']['setId'] 462 except Empty: 463 self.log.error("did not receive the set started event!") 464 self.adv_ad.droid.bleAdvSetStopAdvertisingSet(adv_callback) 465 return False 466 467 self.adv_ad.droid.bleAdvSetGetOwnAddress(set_id) 468 469 try: 470 evt = self.adv_ad.ed.pop_event( 471 advertising_set_on_own_address_read.format(set_id), 472 self.default_timeout) 473 address = evt['data']['address'] 474 self.log.info("Advertiser address is: " + str(address)) 475 except Empty: 476 self.log.error("onOwnAddressRead not received.") 477 self.adv_ad.droid.bleAdvSetStopAdvertisingSet(adv_callback) 478 return False 479 480 self.adv_ad.droid.bleAdvSetStopAdvertisingSet(adv_callback) 481 return True 482