Home | History | Annotate | Download | only in bt5
      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 Bluetooth 5 specific scan scenarios.
     18 It is expected that the second AndroidDevice is able to advertise.
     19 
     20 This test script was designed with this setup in mind:
     21 Shield box one: Android Device, Android Device
     22 """
     23 
     24 from queue import Empty
     25 
     26 from acts import asserts
     27 from acts.test_decorators import test_tracker_info
     28 from acts.test_utils.bt.BluetoothBaseTest import BluetoothBaseTest
     29 from acts.test_utils.bt.bt_constants import ble_scan_settings_phys
     30 from acts.test_utils.bt.bt_constants import ble_scan_settings_modes
     31 from acts.test_utils.bt.bt_test_utils import batch_scan_result
     32 from acts.test_utils.bt.bt_test_utils import cleanup_scanners_and_advertisers
     33 from acts.test_utils.bt.bt_test_utils import generate_ble_advertise_objects
     34 from acts.test_utils.bt.bt_test_utils import generate_ble_scan_objects
     35 from acts.test_utils.bt.bt_test_utils import reset_bluetooth
     36 from acts.test_utils.bt.bt_constants import scan_result
     37 from acts.test_utils.bt.bt_test_utils import advertising_set_on_own_address_read
     38 from acts.test_utils.bt.bt_test_utils import advertising_set_started
     39 from acts import signals
     40 
     41 
     42 class 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