Home | History | Annotate | Download | only in concurrency
      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 Test script to exercises Ble Scans can run in concurrency.
     18 This test was designed to be run in a shield box.
     19 """
     20 
     21 import concurrent
     22 import time
     23 
     24 from queue import Empty
     25 from acts.test_decorators import test_tracker_info
     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 ScanSettingsCallbackType
     29 from acts.test_utils.bt.BleEnum import ScanSettingsScanMode
     30 from acts.test_utils.bt.bt_test_utils import adv_succ
     31 from acts.test_utils.bt.bt_test_utils import generate_ble_advertise_objects
     32 from acts.test_utils.bt.bt_test_utils import reset_bluetooth
     33 from acts.test_utils.bt.bt_test_utils import scan_failed
     34 from acts.test_utils.bt.bt_test_utils import scan_result
     35 from acts.test_utils.bt.bt_test_utils import take_btsnoop_logs
     36 
     37 
     38 class ConcurrentBleScanningTest(BluetoothBaseTest):
     39     default_timeout = 20
     40     max_concurrent_scans = 28
     41 
     42     def __init__(self, controllers):
     43         BluetoothBaseTest.__init__(self, controllers)
     44         self.scn_ad = self.android_devices[0]
     45         self.adv_ad = self.android_devices[1]
     46 
     47     def on_fail(self, test_name, begin_time):
     48         self.log.debug("Test {} failed. Gathering bugreport and btsnoop logs."
     49                        .format(test_name))
     50         take_btsnoop_logs(self.android_devices, self, test_name)
     51         reset_bluetooth(self.android_devices)
     52 
     53     def setup_test(self):
     54         return reset_bluetooth(self.android_devices)
     55 
     56     @BluetoothBaseTest.bt_test_wrap
     57     @test_tracker_info(uuid='e7f68b9b-fb3f-48e9-a272-e41c2a32b4bd')
     58     def test_max_concurrent_ble_scans(self):
     59         """Test max LE scans.
     60 
     61         Test that a single device can have max scans concurrently scanning.
     62 
     63         Steps:
     64         1. Initialize scanner
     65         2. Initialize advertiser
     66         3. Start advertising on the device from step 2
     67         4. Create max ble scan callbacks
     68         5. Start ble scan on each callback
     69         6. Verify that each callback triggers
     70         7. Stop all scans and advertisements
     71 
     72         Expected Result:
     73         All scanning instances should start without errors and the advertisement
     74         should be found on each scan instance.
     75 
     76         Returns:
     77           Pass if True
     78           Fail if False
     79 
     80         TAGS: LE, Scanning, Concurrency
     81         Priority: 0
     82         """
     83         test_result = True
     84         self.adv_ad.droid.bleSetAdvertiseDataIncludeDeviceName(True)
     85         self.scn_ad.droid.bleSetScanSettingsCallbackType(
     86             ScanSettingsCallbackType.CALLBACK_TYPE_ALL_MATCHES.value)
     87         self.scn_ad.droid.bleSetScanSettingsScanMode(
     88             ScanSettingsScanMode.SCAN_MODE_LOW_LATENCY.value)
     89         self.adv_ad.droid.bleSetAdvertiseSettingsAdvertiseMode(
     90             AdvertiseSettingsAdvertiseMode.ADVERTISE_MODE_LOW_LATENCY.value)
     91         advertise_callback, advertise_data, advertise_settings = (
     92             generate_ble_advertise_objects(self.adv_ad.droid))
     93         self.adv_ad.droid.bleSetAdvertiseSettingsIsConnectable(False)
     94         self.adv_ad.droid.bleStartBleAdvertising(
     95             advertise_callback, advertise_data, advertise_settings)
     96         try:
     97             self.adv_ad.ed.pop_event(
     98                 adv_succ.format(advertise_callback), self.default_timeout)
     99         except Empty as error:
    100             self.log.exception("Test failed with Empty error: {}".format(
    101                 error))
    102             test_result = False
    103         except concurrent.futures._base.TimeoutError as error:
    104             self.log.exception(
    105                 "Test failed callback onSuccess never occurred: "
    106                 "{}".format(error))
    107             test_result = False
    108         if not test_result:
    109             return test_result
    110         filter_list = self.scn_ad.droid.bleGenFilterList()
    111         self.scn_ad.droid.bleSetScanFilterDeviceName(
    112             self.adv_ad.droid.bluetoothGetLocalName())
    113         self.scn_ad.droid.bleBuildScanFilter(filter_list)
    114         scan_settings = self.scn_ad.droid.bleBuildScanSetting()
    115         scan_callback_list = []
    116         for i in range(self.max_concurrent_scans):
    117             self.log.debug("Concurrent Ble Scan iteration {}".format(i + 1))
    118             scan_callback = self.scn_ad.droid.bleGenScanCallback()
    119             scan_callback_list.append(scan_callback)
    120             self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings,
    121                                               scan_callback)
    122             try:
    123                 self.scn_ad.ed.pop_event(
    124                     scan_result.format(scan_callback), self.default_timeout)
    125                 self.log.info("Found scan event successfully. Iteration {} "
    126                               "successful.".format(i))
    127             except Exception:
    128                 self.log.info("Failed to find a scan result for callback {}"
    129                               .format(scan_callback))
    130                 test_result = False
    131                 break
    132         for callback in scan_callback_list:
    133             self.scn_ad.droid.bleStopBleScan(callback)
    134         self.adv_ad.droid.bleStopBleAdvertising(advertise_callback)
    135         if not test_result:
    136             return test_result
    137         self.log.info("Waiting for scan callbacks to stop completely.")
    138         # Wait for all scan callbacks to stop. There is no confirmation
    139         # otherwise.
    140         time.sleep(10)
    141         return test_result
    142 
    143     @BluetoothBaseTest.bt_test_wrap
    144     @test_tracker_info(uuid='58b0c45e-1cbc-420a-9e89-901518ffe3d1')
    145     def test_max_concurrent_ble_scans_then_discover_advertisement(self):
    146         """Test max LE scans variant.
    147 
    148         Test that a single device can have max scans concurrently scanning.
    149 
    150         Steps:
    151         1. Initialize scanner
    152         2. Initialize advertiser
    153         3. Create max ble scan callbacks
    154         4. Start ble scan on each callback
    155         5. Start advertising on the device from step 2
    156         6. Verify that each callback triggers
    157         7. Stop all scans and advertisements
    158 
    159         Expected Result:
    160         All scanning instances should start without errors and the advertisement
    161         should be found on each scan instance.
    162 
    163         Returns:
    164           Pass if True
    165           Fail if False
    166 
    167         TAGS: LE, Scanning, Concurrency
    168         Priority: 1
    169         """
    170         self.adv_ad.droid.bleSetAdvertiseDataIncludeDeviceName(True)
    171         self.scn_ad.droid.bleSetScanSettingsCallbackType(
    172             ScanSettingsCallbackType.CALLBACK_TYPE_ALL_MATCHES.value)
    173         self.scn_ad.droid.bleSetScanSettingsScanMode(
    174             ScanSettingsScanMode.SCAN_MODE_LOW_LATENCY.value)
    175         self.adv_ad.droid.bleSetAdvertiseSettingsAdvertiseMode(
    176             AdvertiseSettingsAdvertiseMode.ADVERTISE_MODE_LOW_LATENCY.value)
    177         advertise_callback, advertise_data, advertise_settings = (
    178             generate_ble_advertise_objects(self.adv_ad.droid))
    179         filter_list = self.scn_ad.droid.bleGenFilterList()
    180         self.scn_ad.droid.bleSetScanFilterDeviceName(
    181             self.adv_ad.droid.bluetoothGetLocalName())
    182         self.scn_ad.droid.bleBuildScanFilter(filter_list)
    183         scan_settings = self.scn_ad.droid.bleBuildScanSetting()
    184         scan_callback_list = []
    185         for i in range(self.max_concurrent_scans):
    186             self.log.debug("Concurrent Ble Scan iteration {}".format(i + 1))
    187             scan_callback = self.scn_ad.droid.bleGenScanCallback()
    188             scan_callback_list.append(scan_callback)
    189             self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings,
    190                                               scan_callback)
    191         self.adv_ad.droid.bleStartBleAdvertising(
    192             advertise_callback, advertise_data, advertise_settings)
    193         try:
    194             self.adv_ad.ed.pop_event(
    195                 adv_succ.format(advertise_callback), self.default_timeout)
    196         except Empty as error:
    197             self.log.exception("Test failed with Empty error: {}".format(
    198                 error))
    199             return False
    200         except concurrent.futures._base.TimeoutError as error:
    201             self.log.exception("Test failed, filtering callback onSuccess "
    202                                "never occurred: {}".format(error))
    203             return False
    204         i = 0
    205         for callback in scan_callback_list:
    206             try:
    207                 self.scn_ad.ed.pop_event(
    208                     scan_result.format(scan_callback), self.default_timeout)
    209                 self.log.info(
    210                     "Found scan event successfully. Iteration {} successful."
    211                     .format(i))
    212             except Exception:
    213                 self.log.info("Failed to find a scan result for callback {}"
    214                               .format(scan_callback))
    215                 return False
    216             i += 1
    217         for callback in scan_callback_list:
    218             self.scn_ad.droid.bleStopBleScan(callback)
    219         self.adv_ad.droid.bleStopBleAdvertising(advertise_callback)
    220         return True
    221 
    222     @BluetoothBaseTest.bt_test_wrap
    223     @test_tracker_info(uuid='7a45e45c-faf3-4e89-abb7-a52f63e53208')
    224     def test_max_concurrent_ble_scans_plus_one(self):
    225         """Test mac LE scans variant.
    226 
    227         Test that a single device can have max scans concurrently scanning.
    228 
    229         Steps:
    230         1. Initialize scanner
    231         3. Create max ble scan callbacks plus one
    232         5. Start ble scan on each callback
    233         6. Verify that the n+1th scan fails.
    234         7. Stop all scans
    235 
    236         Expected Result:
    237         The n+1th scan should fail to start.
    238 
    239         Returns:
    240           Pass if True
    241           Fail if False
    242 
    243         TAGS: LE, Scanning, Concurrency
    244         Priority: 1
    245         """
    246         test_result = True
    247         self.scn_ad.droid.bleSetScanSettingsCallbackType(
    248             ScanSettingsCallbackType.CALLBACK_TYPE_ALL_MATCHES.value)
    249         self.scn_ad.droid.bleSetScanSettingsScanMode(
    250             ScanSettingsScanMode.SCAN_MODE_LOW_LATENCY.value)
    251         filter_list = self.scn_ad.droid.bleGenFilterList()
    252         self.scn_ad.droid.bleBuildScanFilter(filter_list)
    253         scan_settings = self.scn_ad.droid.bleBuildScanSetting()
    254         scan_callback_list = []
    255         for i in range(self.max_concurrent_scans):
    256             self.log.debug("Concurrent Ble Scan iteration {}".format(i + 1))
    257             scan_callback = self.scn_ad.droid.bleGenScanCallback()
    258             self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings,
    259                                               scan_callback)
    260             scan_callback_list.append(scan_callback)
    261         scan_callback = self.scn_ad.droid.bleGenScanCallback()
    262         self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings,
    263                                           scan_callback)
    264         try:
    265             self.scn_ad.ed.pop_event(
    266                 scan_failed.format(scan_callback), self.default_timeout)
    267             self.log.info(
    268                 "Found scan event successfully. Iteration {} successful."
    269                 .format(i))
    270         except Exception:
    271             self.log.info("Failed to find a onScanFailed event for callback {}"
    272                           .format(scan_callback))
    273             test_result = False
    274         for callback in scan_callback_list:
    275             self.scn_ad.droid.bleStopBleScan(callback)
    276         return test_result
    277 
    278     @BluetoothBaseTest.bt_test_wrap
    279     @test_tracker_info(uuid='5a91f612-69e5-490f-b9d0-50d58a3db736')
    280     def test_max_concurrent_ble_scans_verify_scans_stop_independently(self):
    281         """Test max LE scans variant.
    282 
    283         Test that a single device can have max scans concurrently scanning.
    284 
    285         Steps:
    286         1. Initialize scanner
    287         2. Initialize advertiser
    288         3. Create max ble scan callbacks
    289         4. Start ble scan on each callback
    290         5. Start advertising on the device from step 2
    291         6. Verify that the first callback triggers
    292         7. Stop the scan and repeat steps 6 and 7 until all scans stopped
    293 
    294         Expected Result:
    295         All scanning instances should start without errors and the advertisement
    296         should be found on each scan instance. All scanning instances should
    297         stop successfully.
    298 
    299         Returns:
    300           Pass if True
    301           Fail if False
    302 
    303         TAGS: LE, Scanning, Concurrency
    304         Priority: 1
    305         """
    306         self.adv_ad.droid.bleSetAdvertiseDataIncludeDeviceName(True)
    307         self.scn_ad.droid.bleSetScanSettingsCallbackType(
    308             ScanSettingsCallbackType.CALLBACK_TYPE_ALL_MATCHES.value)
    309         self.scn_ad.droid.bleSetScanSettingsScanMode(
    310             ScanSettingsScanMode.SCAN_MODE_LOW_LATENCY.value)
    311         self.adv_ad.droid.bleSetAdvertiseSettingsAdvertiseMode(
    312             AdvertiseSettingsAdvertiseMode.ADVERTISE_MODE_LOW_LATENCY.value)
    313         advertise_callback, advertise_data, advertise_settings = (
    314             generate_ble_advertise_objects(self.adv_ad.droid))
    315         filter_list = self.scn_ad.droid.bleGenFilterList()
    316         self.scn_ad.droid.bleSetScanFilterDeviceName(
    317             self.adv_ad.droid.bluetoothGetLocalName())
    318         self.scn_ad.droid.bleBuildScanFilter(filter_list)
    319         scan_settings = self.scn_ad.droid.bleBuildScanSetting()
    320         scan_callback_list = []
    321         for i in range(self.max_concurrent_scans):
    322             self.log.debug("Concurrent Ble Scan iteration {}".format(i + 1))
    323             scan_callback = self.scn_ad.droid.bleGenScanCallback()
    324             scan_callback_list.append(scan_callback)
    325             self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings,
    326                                               scan_callback)
    327         self.adv_ad.droid.bleStartBleAdvertising(
    328             advertise_callback, advertise_data, advertise_settings)
    329         try:
    330             self.adv_ad.ed.pop_event(
    331                 adv_succ.format(advertise_callback), self.default_timeout)
    332         except Empty as error:
    333             self.log.exception("Test failed with Empty error: {}".format(
    334                 error))
    335             return False
    336         except concurrent.futures._base.TimeoutError as error:
    337             self.log.exception(
    338                 "Test failed, filtering callback onSuccess never"
    339                 " occurred: {}".format(error))
    340             return False
    341         i = 0
    342         for callback in scan_callback_list:
    343             expected_scan_event_name = scan_result.format(scan_callback)
    344             try:
    345                 self.scn_ad.ed.pop_event(expected_scan_event_name,
    346                                          self.default_timeout)
    347                 self.log.info(
    348                     "Found scan event successfully. Iteration {} successful.".
    349                     format(i))
    350                 i += 1
    351             except Exception:
    352                 self.log.info("Failed to find a scan result for callback {}".
    353                               format(scan_callback))
    354                 return False
    355             self.scn_ad.droid.bleStopBleScan(callback)
    356         self.adv_ad.droid.bleStopBleAdvertising(advertise_callback)
    357         return True
    358