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