Home | History | Annotate | Download | only in wifi
      1 #!/usr/bin/env python3.4
      2 #
      3 #   Copyright 2016 - The Android Open Source Project
      4 #
      5 #   Licensed under the Apache License, Version 2.0 (the "License");
      6 #   you may not use this file except in compliance with the License.
      7 #   You may obtain a copy of 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,
     13 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 #   See the License for the specific language governing permissions and
     15 #   limitations under the License.
     16 
     17 import itertools
     18 import queue
     19 
     20 from acts import asserts
     21 from acts import base_test
     22 from acts import utils
     23 from acts.test_decorators import test_tracker_info
     24 from acts.test_utils.wifi import wifi_test_utils as wutils
     25 
     26 BSSID_EVENT_WAIT = 30
     27 
     28 BSSID_EVENT_TAG = "WifiScannerBssid"
     29 SCAN_EVENT_TAG = "WifiScannerScan"
     30 SCANTIME = 10000  #framework support only 10s as minimum scan interval
     31 
     32 
     33 class WifiScannerBssidError(Exception):
     34     pass
     35 
     36 
     37 class WifiScannerBssidTest(base_test.BaseTestClass):
     38     def __init__(self, controllers):
     39         base_test.BaseTestClass.__init__(self, controllers)
     40         # A list of all test cases to be executed in this class.
     41         self.tests = ("test_wifi_track_bssid_sanity",
     42                       "test_wifi_track_bssid_found",
     43                       "test_wifi_track_bssid_lost",
     44                       "test_wifi_track_bssid_for_2g_while_scanning_5g_channels",
     45                       "test_wifi_track_bssid_for_5g_while_scanning_2g_channels",)
     46 
     47     def setup_class(self):
     48         self.default_scan_setting = {
     49             "band": wutils.WifiEnums.WIFI_BAND_BOTH_WITH_DFS,
     50             "periodInMs": SCANTIME,
     51             "reportEvents": wutils.WifiEnums.REPORT_EVENT_AFTER_EACH_SCAN,
     52             'numBssidsPerScan': 32
     53         }
     54         self.leeway = 5
     55         self.stime_channel = 47  #dwell time plus 2ms
     56         self.dut = self.android_devices[0]
     57         wutils.wifi_test_device_init(self.dut)
     58         self.attenuators = wutils.group_attenuators(self.attenuators)
     59         asserts.assert_true(self.dut.droid.wifiIsScannerSupported(),
     60                             "Device %s doesn't support WifiScanner, abort." %
     61                             self.dut.model)
     62         """It will setup the required dependencies and fetch the user params from
     63           config file"""
     64         self.attenuators[0].set_atten(0)
     65         self.attenuators[1].set_atten(0)
     66         req_params = ("bssid_2g", "bssid_5g", "bssid_dfs", "attenuator_id",
     67                       "max_bugreports")
     68         self.wifi_chs = wutils.WifiChannelUS(self.dut.model)
     69         self.unpack_userparams(req_params, two_ap_testbed=False)
     70 
     71     def teardown_class(self):
     72         BaseTestClass.teardown_test(self)
     73         self.log.debug("Shut down all wifi scanner activities.")
     74         self.dut.droid.wifiScannerShutdown()
     75 
     76     def on_fail(self, test_name, begin_time):
     77         if self.max_bugreports > 0:
     78             self.dut.take_bug_report(test_name, begin_time)
     79             self.max_bugreports -= 1
     80 
     81     """ Helper Functions Begin """
     82 
     83     def fetch_scan_result(self, scan_idx, scan_setting):
     84         """Fetch the scan result for provider listener index.
     85 
     86         This function calculate the time required for scanning based on scan setting
     87         and wait for scan result event, on triggering of event process the scan result.
     88 
     89         Args:
     90           scan_idx: Index of the scan listener.
     91           scan_setting: Setting used for starting the scan.
     92 
     93         Returns:
     94           scan_results: if scan result available.
     95         """
     96         #generating event wait time from scan setting plus leeway
     97         self.log.debug(scan_setting)
     98         scan_time, scan_channels = wutils.get_scan_time_and_channels(
     99             self.wifi_chs, scan_setting, self.stime_channel)
    100         scan_time += scan_setting['periodInMs'
    101                                   ]  #add scan period delay for next cycle
    102         if scan_setting[
    103                 "reportEvents"] == wutils.WifiEnums.REPORT_EVENT_AFTER_EACH_SCAN:
    104             waittime = int(scan_time / 1000) + self.leeway
    105         else:
    106             time_cache = scan_setting['periodInMs'] * 10  #default cache
    107             waittime = int((time_cache + scan_time) / 1000) + self.leeway
    108         event_name = "%s%sonResults" % (SCAN_EVENT_TAG, scan_idx)
    109         self.log.info("Waiting for the scan result event %s", event_name)
    110         event = self.dut.ed.pop_event(event_name, waittime)
    111         results = event["data"]["Results"]
    112         if len(results) > 0 and "ScanResults" in results[0]:
    113             return results[0]["ScanResults"]
    114 
    115     def start_scan_and_validate_environment(self, scan_setting,
    116                                             bssid_settings):
    117         """Validate environment for test using current scan result for provided
    118            settings.
    119 
    120         This function start the scan for given setting and verify that interested
    121         Bssids are in scan result or not.
    122 
    123         Args:
    124             scan_setting: Setting used for starting the scan.
    125             bssid_settings: list of bssid settings.
    126 
    127         Returns:
    128             True, if bssid not found in scan result.
    129         """
    130         try:
    131             data = wutils.start_wifi_background_scan(self.dut, scan_setting)
    132             self.scan_idx = data["Index"]
    133             results = self.fetch_scan_result(self.scan_idx, scan_setting)
    134             self.log.debug("scan result %s.", results)
    135             asserts.assert_true(results,
    136                                 "Device is not able to fetch the scan results")
    137             for result in results:
    138                 for bssid_setting in bssid_settings:
    139                     if bssid_setting[wutils.WifiEnums.BSSID_KEY] == result[
    140                             wutils.WifiEnums.BSSID_KEY]:
    141                         asserts.fail(("Test environment is not valid: Bssid %s"
    142                                       "already exist in current scan results")
    143                                      % result[wutils.WifiEnums.BSSID_KEY])
    144         except queue.Empty as error:
    145             self.dut.droid.wifiScannerStopBackgroundScan(self.scan_idx)
    146             raise AssertionError(
    147                 "OnResult event did not triggered for scanner\n%s" % error)
    148 
    149     def check_bssid_in_found_result(self, bssid_settings, found_results):
    150         """look for any tracked bssid in reported result of found bssids.
    151 
    152         Args:
    153             bssid_settings:Setting used for tracking bssids.
    154             found_results: Result reported in found event.
    155 
    156         Returns:
    157             True if bssid is present in result.
    158         """
    159         for bssid_setting in bssid_settings:
    160             for found_result in found_results:
    161                 if found_result[wutils.WifiEnums.BSSID_KEY] == bssid_setting[
    162                         wutils.WifiEnums.BSSID_KEY]:
    163                     return
    164         asserts.fail("Test fail because Bssid %s is not found in event results"
    165                      % bssid_settings)
    166 
    167     def track_bssid_with_vaild_scan_for_found(self, track_setting):
    168         """Common logic for tracking a bssid for Found event.
    169 
    170          1. Starts Wifi Scanner bssid tracking for interested bssids in track_setting.
    171          2. Start Wifi Scanner scan with default scan settings.
    172          3. Validate the environment to check AP is not in range.
    173          4. Attenuate the signal to make AP in range.
    174          5. Verified that onFound event is triggered for interested bssids in
    175             track setting.
    176 
    177         Args:
    178             track_setting: Setting for bssid tracking.
    179 
    180         Returns:
    181             True if found event occur for interested BSSID.
    182         """
    183         self.attenuators[self.attenuator_id].set_atten(90)
    184         data = wutils.start_wifi_track_bssid(self.dut, track_setting)
    185         idx = data["Index"]
    186         self.start_scan_and_validate_environment(self.default_scan_setting,
    187                                                  track_setting["bssidInfos"])
    188         try:
    189             self.attenuators[self.attenuator_id].set_atten(0)
    190             event_name = "%s%sonFound" % (BSSID_EVENT_TAG, idx)
    191             self.log.info("Waiting for the BSSID event %s", event_name)
    192             event = self.dut.ed.pop_event(event_name, BSSID_EVENT_WAIT)
    193             self.log.debug(event)
    194             self.check_bssid_in_found_result(track_setting["bssidInfos"],
    195                                              event["data"]["Results"])
    196         except queue.Empty as error:
    197             self.log.error(error)
    198             # log scan result for debugging
    199             results = self.fetch_scan_result(self.scan_idx,
    200                                              self.default_scan_setting)
    201             self.log.debug("scan result %s", results)
    202             raise AssertionError("Event %s did not triggered for %s\n%s" %
    203                                  (event_name, track_setting["bssidInfos"],
    204                                   error))
    205         finally:
    206             self.dut.droid.wifiScannerStopBackgroundScan(self.scan_idx)
    207             self.dut.droid.wifiScannerStopTrackingBssids(idx)
    208 
    209     def track_bssid_with_vaild_scan_for_lost(self, track_setting):
    210         """Common logic for tracking a bssid for Lost event.
    211 
    212          1. Start Wifi Scanner scan with default scan settings.
    213          2. Validate the environment to check AP is not in range.
    214          3. Starts Wifi Scanner bssid tracking for interested bssids in track_setting.
    215          4. Attenuate the signal to make Bssids in range.
    216          5. Verified that onFound event is triggered for interested bssids in
    217             track setting.
    218          6. Attenuate the signal to make Bssids out of range.
    219          7. Verified that onLost event is triggered.
    220 
    221         Args:
    222             track_setting: Setting for bssid tracking.
    223             scan_setting: Setting used for starting the scan.
    224 
    225         Returns:
    226             True if Lost event occur for interested BSSID.
    227         """
    228         self.attenuators[self.attenuator_id].set_atten(90)
    229         self.start_scan_and_validate_environment(self.default_scan_setting,
    230                                                  track_setting["bssidInfos"])
    231         idx = None
    232         found = False
    233         try:
    234             data = wutils.start_wifi_track_bssid(self.dut, track_setting)
    235             idx = data["Index"]
    236             self.attenuators[self.attenuator_id].set_atten(0)
    237             #onFound event should be occurre before tracking for onLost event
    238             event_name = "%s%sonFound" % (BSSID_EVENT_TAG, idx)
    239             self.log.info("Waiting for the BSSID event %s", event_name)
    240             event = self.dut.ed.pop_event(event_name, BSSID_EVENT_WAIT)
    241             self.log.debug(event)
    242             self.check_bssid_in_found_result(track_setting["bssidInfos"],
    243                                              event["data"]["Results"])
    244             self.attenuators[self.attenuator_id].set_atten(90)
    245             # log scan result for debugging
    246             for i in range(1, track_setting["apLostThreshold"]):
    247                 results = self.fetch_scan_result(self.scan_idx,
    248                                                  self.default_scan_setting)
    249                 self.log.debug("scan result %s %s", i, results)
    250             event_name = "%s%sonLost" % (BSSID_EVENT_TAG, idx)
    251             self.log.info("Waiting for the BSSID event %s", event_name)
    252             event = self.dut.ed.pop_event(event_name, BSSID_EVENT_WAIT)
    253             self.log.debug(event)
    254         except queue.Empty as error:
    255             raise AssertionError("Event %s did not triggered for %s\n%s" %
    256                                  (event_name, track_setting["bssidInfos"],
    257                                   error))
    258         finally:
    259             self.dut.droid.wifiScannerStopBackgroundScan(self.scan_idx)
    260             if idx:
    261                 self.dut.droid.wifiScannerStopTrackingBssids(idx)
    262 
    263     def wifi_generate_track_bssid_settings(self, isLost):
    264         """Generates all the combinations of different track setting parameters.
    265 
    266         Returns:
    267             A list of dictionaries each representing a set of track settings.
    268         """
    269         bssids = [[self.bssid_2g], [self.bssid_5g],
    270                   [self.bssid_2g, self.bssid_5g]]
    271         if self.dut.model != "hammerhead" or not self.two_ap_testbed:
    272             bssids.append([self.bssid_dfs])
    273         if isLost:
    274             apthreshold = (3, 5)
    275         else:
    276             apthreshold = (1, )
    277         # Create track setting strings based on the combinations
    278         setting_combinations = list(itertools.product(bssids, apthreshold))
    279         # Create scan setting strings based on the combinations
    280         track_settings = []
    281         for combo in setting_combinations:
    282             s = {}
    283             s["bssidInfos"] = combo[0]
    284             s["apLostThreshold"] = combo[1]
    285             track_settings.append(s)
    286         return track_settings
    287 
    288     def track_setting_to_string(self, track_setting):
    289         """Convert track setting to string for Bssids in that"""
    290         string = ""
    291         for bssid_setting in track_setting:
    292             string += bssid_setting[wutils.WifiEnums.BSSID_KEY]
    293             string += "_"
    294         return string
    295 
    296     def combineBssids(self, *track_settings):
    297         """Combine bssids in the track_settings to one list"""
    298         bssids = []
    299         for track_setting in track_settings:
    300             bssids.extend(track_setting["bssidInfos"])
    301         return bssids
    302 
    303     """ Helper Functions End """
    304     """ Tests Begin """
    305 
    306     @test_tracker_info(uuid="599a30b8-73ad-4314-a245-7ec58fc7e74b")
    307     def test_wifi_track_bssid_found(self):
    308         """Test bssid track for event found with a list of different settings.
    309 
    310          1. Starts Wifi Scanner bssid tracking for interested bssids in track_setting.
    311          2. Start Wifi Scanner scan with default scan settings.
    312          3. Validate the environment to check AP is not in range.
    313          4. Attenuate the signal to make AP in range.
    314          5. Verified that onFound event is triggered for interested bssids in
    315             track setting.
    316         """
    317         track_settings = self.wifi_generate_track_bssid_settings(False)
    318         name_func = lambda track_setting: "test_wifi_track_found_bssidInfos_%sapLostThreshold_%s" % (self.track_setting_to_string(track_setting["bssidInfos"]), track_setting["apLostThreshold"])
    319         failed = self.run_generated_testcases(
    320             self.track_bssid_with_vaild_scan_for_found,
    321             track_settings,
    322             name_func=name_func)
    323         asserts.assert_false(
    324             failed, "Track bssid found failed with these bssids: %s" % failed)
    325 
    326     @test_tracker_info(uuid="7ebd4b61-c408-45b3-b9b6-098753d46aa7")
    327     def test_wifi_track_bssid_lost(self):
    328         """Test bssid track for event lost with a list of different settings.
    329 
    330          1. Start Wifi Scanner scan with default scan settings.
    331          2. Validate the environment to check AP is not in range.
    332          3. Starts Wifi Scanner bssid tracking for interested bssids in track_setting.
    333          4. Attenuate the signal to make Bssids in range.
    334          5. Verified that onFound event is triggered for interested bssids in
    335             track setting.
    336          6. Attenuate the signal to make Bssids out of range.
    337          7. Verified that onLost event is triggered.
    338         """
    339         track_settings = self.wifi_generate_track_bssid_settings(True)
    340         name_func = lambda track_setting: "test_wifi_track_lost_bssidInfos_%sapLostThreshold_%s" % (self.track_setting_to_string(track_setting["bssidInfos"]), track_setting["apLostThreshold"])
    341         failed = self.run_generated_testcases(
    342             self.track_bssid_with_vaild_scan_for_lost,
    343             track_settings,
    344             name_func=name_func)
    345         asserts.assert_false(
    346             failed, "Track bssid lost failed with these bssids: %s" % failed)
    347 
    348     def test_wifi_track_bssid_sanity(self):
    349         """Test bssid track for event found and lost with default settings.
    350 
    351          1. Start WifiScanner scan for default scan settings.
    352          2. Start Bssid track for "bssid_2g" AP.
    353          3. Attenuate the signal to move in AP range.
    354          4. Verify that onFound event occur.
    355          5. Attenuate the signal to move out of range
    356          6. Verify that onLost event occur.
    357         """
    358         track_setting = {"bssidInfos": [self.bssid_2g], "apLostThreshold": 3}
    359         self.track_bssid_with_vaild_scan_for_lost(track_setting)
    360 
    361     def test_wifi_track_bssid_for_2g_while_scanning_5g_channels(self):
    362         """Test bssid track for 2g bssids while scanning 5g channels.
    363 
    364          1. Starts Wifi Scanner bssid tracking for 2g bssids in track_setting.
    365          2. Start Wifi Scanner scan for 5G Band only.
    366          3. Validate the environment to check AP is not in range.
    367          4. Attenuate the signal to make AP in range.
    368          5. Verified that onFound event isn't triggered for 2g bssids.
    369       """
    370         self.attenuators[self.attenuator_id].set_atten(90)
    371         scan_setting = {"band": wutils.WifiEnums.WIFI_BAND_5_GHZ,
    372                         "periodInMs": SCANTIME,
    373                         "reportEvents":
    374                         wutils.WifiEnums.REPORT_EVENT_AFTER_EACH_SCAN,
    375                         "numBssidsPerScan": 32}
    376         track_setting = {"bssidInfos": [self.bssid_2g], "apLostThreshold": 3}
    377         self.start_scan_and_validate_environment(scan_setting,
    378                                                  track_setting["bssidInfos"])
    379         idx = None
    380         try:
    381             data = wutils.start_wifi_track_bssid(self.dut, track_setting)
    382             idx = data["Index"]
    383             self.attenuators[self.attenuator_id].set_atten(0)
    384             event_name = "%s%sonFound" % (BSSID_EVENT_TAG, idx)
    385             self.log.info("Waiting for the BSSID event %s", event_name)
    386             #waiting for 2x time to make sure
    387             event = self.dut.ed.pop_event(event_name, BSSID_EVENT_WAIT * 2)
    388             self.log.debug(event)
    389             self.check_bssid_in_found_result(track_setting["bssidInfos"],
    390                                              event["data"]["Results"])
    391         except queue.Empty as error:
    392             self.log.info(
    393                 "As excepted event didn't occurred with different scan setting")
    394         finally:
    395             self.dut.droid.wifiScannerStopBackgroundScan(self.scan_idx)
    396             if idx:
    397                 self.dut.droid.wifiScannerStopTrackingBssids(idx)
    398 
    399     def test_wifi_track_bssid_for_5g_while_scanning_2g_channels(self):
    400         """Test bssid track for 5g bssids while scanning 2g channels.
    401 
    402            1. Starts Wifi Scanner bssid tracking for 5g bssids in track_setting.
    403            2. Start Wifi Scanner scan for 2G Band only.
    404            3. Validate the environment to check AP is not in range.
    405            4. Attenuate the signal to make AP in range.
    406            5. Verified that onFound event isn't triggered for 5g bssids.
    407         """
    408         self.attenuators[self.attenuator_id].set_atten(90)
    409         scan_setting = {"band": wutils.WifiEnums.WIFI_BAND_24_GHZ,
    410                         "periodInMs": SCANTIME,
    411                         "reportEvents":
    412                         wutils.WifiEnums.REPORT_EVENT_AFTER_EACH_SCAN,
    413                         "numBssidsPerScan": 32}
    414         track_setting = {"bssidInfos": [self.bssid_5g], "apLostThreshold": 3}
    415         data = wutils.start_wifi_track_bssid(self.dut, track_setting)
    416         idx = data["Index"]
    417         self.start_scan_and_validate_environment(scan_setting,
    418                                                  track_setting["bssidInfos"])
    419         try:
    420             self.attenuators[self.attenuator_id].set_atten(0)
    421             event_name = "%s%sonFound" % (BSSID_EVENT_TAG, idx)
    422             self.log.info("Waiting for the BSSID event %s", event_name)
    423             #waiting for 2x time to make sure
    424             event = self.dut.ed.pop_event(event_name, BSSID_EVENT_WAIT * 2)
    425             self.log.debug(event)
    426             self.check_bssid_in_found_result(track_setting["bssidInfos"],
    427                                              event["data"]["Results"])
    428         except queue.Empty as error:
    429             self.log.info(
    430                 "As excepted event didn't occurred with different scan setting")
    431         finally:
    432             self.dut.droid.wifiScannerStopBackgroundScan(self.scan_idx)
    433             if idx:
    434                 self.dut.droid.wifiScannerStopTrackingBssids(idx)
    435 
    436     def test_wifi_tracking_bssid_multi_listeners_found(self):
    437         """Test bssid tracking for multiple listeners
    438             1. Start BSSID tracking for 5g bssids
    439             2. Start BSSID tracking for 2g bssids
    440             3. Start WifiScanner scan on both bands.
    441             4. Valid the environment and check the APs are not in range.
    442             5. Attenuate the signal to make the APs in range.
    443             6. Verify onFound event triggered on both APs.
    444         """
    445         # Attenuate the signal to make APs invisible.
    446         self.attenuators[self.attenuator_id].set_atten(90)
    447         scan_setting = { "band": WifiEnums.WIFI_BAND_BOTH_WITH_DFS,
    448                          "periodInMs": SCANTIME,
    449                          "reportEvents": WifiEnums.REPORT_EVENT_AFTER_EACH_SCAN,
    450                          "numBssidsPerScan": 32}
    451         track_setting_5g = {"bssidInfos":[self.bssid_5g], "apLostThreshold":3}
    452         data_5g = start_wifi_track_bssid(self.dut, track_setting_5g)
    453         idx_5g = data_5g["Index"]
    454 
    455         track_setting_2g = {"bssidInfos":[self.bssid_2g], "apLostThreshold":3}
    456         data_2g = start_wifi_track_bssid(self.dut, track_setting_2g)
    457         idx_2g = data_2g["Index"]
    458 
    459         valid_env = self.start_scan_and_validate_environment(
    460             scan_setting, self.combineBssids(track_setting_5g, track_setting_2g))
    461         try:
    462             asserts.assert_true(valid_env,
    463                                 "Test environment is not valid, AP is in range")
    464             self.attenuators[self.attenuator_id].set_atten(0)
    465             event_name = "{}{}{}{}onFound".format(BSSID_EVENT_TAG, idx_5g, BSSID_EVENT_TAG, idx_2g)
    466             self.log.info("Waiting for the BSSID event {}".format(event_name))
    467             #waiting for 2x time to make sure
    468             event = self.dut.ed.pop_event(event_name, BSSID_EVENT_WAIT * 2)
    469             self.log.debug(event)
    470             found = self.check_bssid_in_found_result(
    471                 self.combineBssids(track_setting_5g, track_setting_2g),
    472                 event["data"]["Results"])
    473             asserts.assert_true(found,
    474                                 "Test failed because Bssid onFound event is not triggered")
    475         finally:
    476             self.dut.droid.wifiScannerStopBackgroundScan(self.scan_idx)
    477             if idx_5g:
    478                 self.dut.droid.wifiScannerStopTrackingBssids(idx_5g)
    479             if idx_2g:
    480                 self.dut.droid.wifiScannerStopTrackingBssids(idx_2g);
    481 
    482 """ Tests End """
    483