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