• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
17import json
18import os
19import itertools
20
21from queue import Empty
22from acts import asserts
23from acts.base_test import BaseTestClass
24from acts.utils import load_config
25from acts.test_utils.wifi.wifi_test_utils import start_wifi_track_bssid
26from acts.test_utils.wifi.wifi_test_utils import start_wifi_background_scan
27from acts.test_utils.wifi.wifi_test_utils import wifi_test_device_init
28from acts.test_utils.wifi.wifi_test_utils import WifiChannelUS
29from acts.test_utils.wifi.wifi_test_utils import WifiEnums
30from acts.test_utils.wifi.wifi_test_utils import get_scan_time_and_channels
31
32
33BSSID_EVENT_WAIT = 30
34
35BSSID_EVENT_TAG = "WifiScannerBssid"
36SCAN_EVENT_TAG = "WifiScannerScan"
37SCANTIME = 10000 #framework support only 10s as minimum scan interval
38
39class WifiScannerBssidError(Exception):
40    pass
41
42class 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