| #!/usr/bin/env python3 |
| # |
| # Copyright 2021 - The Android Open Source Project |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| import time |
| from acts import asserts |
| from acts import signals |
| from acts.test_decorators import test_tracker_info |
| import acts_contrib.test_utils.wifi.wifi_test_utils as wutils |
| from acts_contrib.test_utils.wifi.WifiBaseTest import WifiBaseTest |
| from acts.controllers.ap_lib.hostapd_constants import BAND_2G |
| from acts.controllers.ap_lib.hostapd_constants import BAND_5G |
| from acts.controllers.ap_lib import hostapd_constants |
| |
| # TODO: Find a better way to get real country code and channels data. |
| COUNTRY_5G_NOT_ALLOWED = ["JP", "GB", "DE"] |
| WIFI_5G_NON_DFS_CHANNELS = [36, 38, 40, 42, 44, 46, 48, 149, 153, 157, 161, 165] |
| WIFI_5G_DFS_CHANNELS = [52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140] |
| WIFI_EU_SRD_CHANNELS = [149, 153, 157, 161, 165] |
| |
| BRIDGED_AP_LAUNCH_INTERVAL_5_SECONDS = 5 |
| WifiEnums = wutils.WifiEnums |
| |
| |
| class WifiCountrySoftApAcsTest(WifiBaseTest): |
| """WiFi WifiSoftApCountryAcsTest test class. |
| |
| Test Bed Requirement: |
| * Android DUT x 1. |
| * OpenWrt x 1. |
| """ |
| |
| def setup_class(self): |
| super().setup_class() |
| |
| self.dut = self.android_devices[0] |
| self.client = self.android_devices[1] |
| |
| if "OpenWrtAP" in self.user_params: |
| self.openwrt = self.access_points[0] |
| self.openwrt.log.info("Rebooting OpenWrt") |
| self.openwrt.reboot() |
| self.openwrt.verify_wifi_status(timeout=60) |
| |
| req_params = [] |
| opt_param = [] |
| |
| self.unpack_userparams( |
| req_param_names=req_params, opt_param_names=opt_param) |
| |
| def setup_test(self): |
| super().setup_test() |
| for ad in self.android_devices: |
| wutils.reset_wifi(ad) |
| wutils.wifi_toggle_state(self.dut, True) |
| wutils.wifi_toggle_state(self.client, True) |
| |
| def teardown_test(self): |
| super().teardown_test() |
| if self.dut.droid.wifiIsApEnabled(): |
| wutils.stop_wifi_tethering(self.dut) |
| |
| for ad in self.android_devices: |
| wutils.reset_wifi(ad) |
| wutils.set_wifi_country_code( |
| ad, wutils.WifiEnums.CountryCode.US) |
| |
| def teardown_class(self): |
| super().teardown_class() |
| for ad in self.android_devices: |
| wutils.reset_wifi(ad) |
| |
| if "AccessPoint" in self.user_params: |
| del self.user_params["reference_networks"] |
| del self.user_params["open_network"] |
| |
| def is_bridgedap_supported(self, *args): |
| return self.dut.droid.wifiIsBridgedApConcurrencySupported() |
| |
| def set_country_code_and_verify(self, ad, country_code): |
| """ Set Country Code to DUT. |
| |
| Args: |
| ad: An AndroidDevice object. |
| country_code: String; 2 letter ISO country code, e,g,. "US". |
| """ |
| wutils.set_wifi_country_code(ad, country_code) |
| # Wi-Fi OFF and ON to make sure country code take effect. |
| wutils.wifi_toggle_state(ad, False) |
| wutils.wifi_toggle_state(ad, True) |
| |
| country = ad.droid.wifiGetCountryCode() |
| asserts.assert_true(country == country_code, |
| "country code {} is not set".format(country_code)) |
| ad.log.info("Country code set to : {}".format(country)) |
| |
| def connect_wifi_network(self, init_sta_band, init_sta_chan): |
| """Enable OpenWrt with a 2G/5G channels and a DUT connect to it. |
| |
| Args: |
| init_sta_band: String; "2g" or "5g". |
| init_sta_chan: Integer; use to setup OpenWrt 2G/5G channel. |
| |
| Returns: |
| ap_freq: Integer'; represent the frequency of the AP which |
| the DUT connect to. |
| """ |
| |
| # Enable a Wi-Fi network and DUT connect to it. |
| if init_sta_band == BAND_2G: |
| connect = BAND_2G |
| channel_2g = init_sta_chan |
| channel_5g = hostapd_constants.AP_DEFAULT_CHANNEL_5G |
| elif init_sta_band == BAND_5G: |
| connect = BAND_5G |
| channel_2g = hostapd_constants.AP_DEFAULT_CHANNEL_2G |
| channel_5g = init_sta_chan |
| |
| # Enable OpenWrt AP. |
| if "OpenWrtAP" in self.user_params: |
| self.openwrt = self.access_points[0] |
| self.configure_openwrt_ap_and_start(wpa_network=True, |
| channel_2g=channel_2g, |
| channel_5g=channel_5g) |
| self.ap1_2g = self.wpa_networks[0][BAND_2G] |
| self.ap1_5g = self.wpa_networks[0][BAND_5G] |
| |
| self.openwrt.log.info("OpenWrt AP 2G: {}".format(self.ap1_2g)) |
| self.openwrt.log.info("OpenWrt AP 5G: {}".format(self.ap1_5g)) |
| |
| if connect == BAND_2G: |
| wutils.connect_to_wifi_network(self.dut, self.ap1_2g) |
| elif connect == BAND_5G: |
| wutils.connect_to_wifi_network(self.dut, self.ap1_5g) |
| |
| ap_freq = self.dut.droid.wifiGetConnectionInfo()["frequency"] |
| self.dut.log.info("DUT connected to AP on freq: {}, chan: {}". |
| format(ap_freq, WifiEnums.freq_to_channel[ap_freq])) |
| return ap_freq |
| |
| def enable_softap(self, ad): |
| """ Enable SoftAp of the DUT |
| |
| Args: |
| ad: An AndroidDevice object. |
| |
| Returns: |
| (freq1, freq2): Integer; a 2G frequency and a 5G frequency if DUT |
| support BridgedAp. |
| freq: Integer; a frequency from SoftAp. |
| None, bandwidth: Just a placeholder, won't be used. |
| |
| Raises: |
| TestFailure if no BridgedAp instances. |
| """ |
| # Enable SoftAp |
| # Create SoftAp config. |
| config = wutils.create_softap_config() |
| # If DUT support BridgedAp, then two BridgedAp instances enabled. |
| if self.dut.droid.wifiIsBridgedApConcurrencySupported(): |
| wutils.save_wifi_soft_ap_config( |
| ad, |
| config, |
| bands=[WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G, |
| WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G_5G]) |
| # If DUT does not support BridgedAp, 2G OR 5G SoftAp enabled. |
| else: |
| if self.init_softap_band == BAND_2G: |
| band = WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G |
| elif self.init_softap_band == BAND_5G: |
| band = WifiEnums.WIFI_CONFIG_SOFTAP_BAND_5G |
| wutils.save_wifi_soft_ap_config(ad, config, band=band) |
| wutils.start_wifi_tethering_saved_config(ad) |
| time.sleep(BRIDGED_AP_LAUNCH_INTERVAL_5_SECONDS) |
| |
| # if DUT support BridgedAp: |
| if ad.droid.wifiIsBridgedApConcurrencySupported(): |
| callbackId = ad.droid.registerSoftApCallback() |
| infos = wutils.get_current_softap_infos(ad, callbackId, True) |
| ad.droid.unregisterSoftApCallback(callbackId) |
| # if DUT BridgedAp has two instances, return two frequencies. |
| if len(infos) == 2: |
| freq_1 = infos[0]["frequency"] |
| freq_2 = infos[1]["frequency"] |
| return freq_1, freq_2 |
| # if DUT BridgedAp has only one instances, return the frequency. |
| elif len(infos) == 1: |
| freq = infos[0]["frequency"] |
| return freq, None |
| else: |
| raise signals.TestFailure("There should be SoftAp instance.") |
| # if DUT does not support BridgedAp: |
| else: |
| # Return SoftAp frequency. |
| callbackId = ad.droid.registerSoftApCallback() |
| freq, bandwidth = wutils.get_current_softap_info(ad, callbackId, |
| True) |
| ad.log.info("SoftAp freq: {}".format(freq)) |
| ad.droid.unregisterSoftApCallback(callbackId) |
| return freq, bandwidth |
| |
| def collect_acs_failures(self, freq1, freq2, country, init_sta_band, |
| init_sta_chan, init_softap_band): |
| """ Verify SoftAp ACS rules and return error message when fail. |
| |
| Args: |
| freq1: Integer; frequency from SoftAp. |
| freq2: Integer; frequency from SoftAp. |
| country: String; Two letters country code, e.g., "US". |
| init_sta_band: String; "2g" or "5g". |
| init_sta_chan: Integer; use to setup OpenWrt 2G/5G channel. |
| init_softap_band: String: "2g" or "5g". |
| |
| Returns: List of string; contains failure messages. |
| """ |
| # If DUT support BridgedAp(Dual SoftAp). |
| # Decide which is softap_2g_freq, which is softap_5g_freq |
| self.softap_freq_1 = freq1 |
| if self.dut.droid.wifiIsBridgedApConcurrencySupported(): |
| self.softap_freq_2 = freq2 |
| if self.softap_freq_1 in WifiEnums.ALL_2G_FREQUENCIES: |
| self.softap_2g_freq = self.softap_freq_1 |
| elif self.softap_freq_1 in WifiEnums.ALL_5G_FREQUENCIES: |
| self.softap_5g_freq = self.softap_freq_1 |
| if self.softap_freq_2 in WifiEnums.ALL_2G_FREQUENCIES: |
| self.softap_2g_freq = self.softap_freq_2 |
| elif self.softap_freq_2 in WifiEnums.ALL_5G_FREQUENCIES: |
| self.softap_5g_freq = self.softap_freq_2 |
| # If DUT does not support BridgedAp(Dual SoftAp). |
| # Decide the frequency is softap_2g_freq or softap_5g_freq |
| else: |
| if self.softap_freq_1 in WifiEnums.ALL_2G_FREQUENCIES: |
| self.softap_2g_freq = self.softap_freq_1 |
| elif self.softap_freq_1 in WifiEnums.ALL_5G_FREQUENCIES: |
| self.softap_5g_freq = self.softap_freq_1 |
| |
| # Verify ACS when SoftAp 2G enabled. |
| failures = [] |
| if init_softap_band == BAND_2G: |
| if init_sta_band == BAND_2G: |
| self.dut.log.info("Verifying 2G SoftAp chan == 2G STA chan") |
| if self.softap_2g_freq != self.actual_sta_freq: |
| failures.append("Expect 2G SoftAp chan == 2G STA chan") |
| else: |
| self.dut.log.info("Verifying SoftAp still operates on 2G") |
| if self.softap_2g_freq not in WifiEnums.ALL_2G_FREQUENCIES: |
| failures.append("Expect SoftAp still operates on 2G") |
| |
| # Verify ACS when SoftAp 5G enabled. |
| elif init_softap_band == BAND_5G: |
| if (country in COUNTRY_5G_NOT_ALLOWED or |
| init_sta_chan in WIFI_5G_DFS_CHANNELS or |
| init_sta_chan in WIFI_EU_SRD_CHANNELS): |
| self.dut.log.info("Verifying SoftAp fallback to 2G") |
| if self.softap_2g_freq not in WifiEnums.ALL_2G_FREQUENCIES: |
| failures.append("Expect SoftAp fallback to 2G.") |
| else: |
| if init_sta_band == BAND_2G: |
| self.dut.log.info("Verifying SoftAp still operates on 5G") |
| if self.softap_5g_freq not in WifiEnums.ALL_5G_FREQUENCIES: |
| failures.append("Expect SoftAp still operates on 5G.") |
| elif init_sta_chan in WIFI_5G_NON_DFS_CHANNELS: |
| self.dut.log.info("Verify 5G SoftAp chan == 5g STA chan") |
| if self.softap_5g_freq != self.actual_sta_freq: |
| failures.append("Expect 5G SoftAp chan == 5G STA chan") |
| failures = "\n".join(failures) |
| return failures |
| |
| def validate_country_softap_acs(self, country, init_sta_band, |
| init_sta_chan, init_softap_band): |
| """ Verify SoftAp ACS on certain country work as expected. |
| |
| Steps: |
| Get country, STA band, STA channel from test case name. |
| Set a country code to the DUT. |
| Enable a Wi-Fi network. |
| DUT connects to the Wi-Fi network. |
| DUT enable SoftAp. |
| P20 and previous |
| Enable SoftAp (2G OR 5G). |
| P21 and later: |
| Enable BridgedAp (2G AND 5G) |
| Get SoftAp(or BridgedAp) channel. |
| Get AP channel. |
| Verify Country SoftAp ACS. |
| |
| Args: |
| country: String; Two letters country code, e.g., "US". |
| init_sta_band: String; "2g" or "5g". |
| init_sta_chan: Integer; use to setup OpenWrt 2G/5G channel. |
| init_softap_band: String: "2g" or "5g". |
| |
| Returns: List of string; contains failure messages. |
| """ |
| self.init_softap_band = init_softap_band |
| # Set a country code to the DUT. |
| self.set_country_code_and_verify(self.dut, country) |
| # Get DUT STA frequency. |
| self.actual_sta_freq = self.connect_wifi_network(init_sta_band, |
| init_sta_chan) |
| # DUT Enable SoftAp. |
| freq1, freq2 = self.enable_softap(self.dut) |
| # Verify Country SoftAp ACS. |
| return self.collect_acs_failures(freq1, freq2, country, init_sta_band, |
| init_sta_chan, init_softap_band) |
| |
| # Tests |
| |
| @test_tracker_info(uuid="003c67f7-f4cc-4f04-ab34-28c71a7602d9") |
| def test_country_us_softap_acs_sta_2g_ch_1_softap_2g(self): |
| """Verify SoftAp ACS on STA 2G CH1 and SoftAp 2G in US. |
| Steps: See docstring of validate_country_softap_acs().""" |
| failures = self.validate_country_softap_acs("US", "2g", 1, "2g") |
| asserts.assert_false(failures, str(failures)) |
| |
| @test_tracker_info(uuid="b3c0a7a4-150f-469c-9191-8d446b2e2593") |
| def test_country_us_softap_acs_sta_5g_ch_36_softap_2g(self): |
| """Verify SoftAp ACS on STA 5G NON-DFS CH36 and SoftAp 2G in US. |
| Steps: See docstring of validate_country_softap_acs().""" |
| failures = self.validate_country_softap_acs("US", "5g", 36, "2g") |
| asserts.assert_false(failures, str(failures)) |
| |
| @test_tracker_info(uuid="7c660706-e63d-4753-bb6e-dacdf4c36cc0") |
| def test_country_us_softap_acs_sta_5g_ch_132_softap_2g(self): |
| """Verify SoftAp ACS on STA 5G DFS CH52 and SoftAp 2G in US. |
| Steps: See docstring of validate_country_softap_acs().""" |
| failures = self.validate_country_softap_acs("US", "5g", 132, "2g") |
| asserts.assert_false(failures, str(failures)) |
| |
| @test_tracker_info(uuid="31973348-852e-4cd7-9a72-6e8f333623c5") |
| def test_country_de_softap_acs_sta_5g_ch_161_softap_2g(self): |
| """Verify SoftAp ACS on STA 5G EU SRD CH149 and SoftAp 2G in DE. |
| Steps: See docstring of validate_country_softap_acs().""" |
| failures = self.validate_country_softap_acs("US", "5g", 161, "2g") |
| asserts.assert_false(failures, str(failures)) |
| |
| @test_tracker_info(uuid="8ebba60c-a32c-46b3-b9da-411b1ef66288") |
| def test_country_us_softap_acs_sta_2g_ch_1_softap_5g(self): |
| """Verify SoftAp ACS on STA 2G CH1 and SoftAp 5G in US. |
| Steps: See docstring of validate_country_softap_acs().""" |
| failures = self.validate_country_softap_acs("US", "2g", 1, "5g") |
| asserts.assert_false(failures, str(failures)) |
| |
| @test_tracker_info(uuid="503ece09-3030-4a69-ae15-320f5104ddd2") |
| def test_country_us_softap_acs_sta_5g_ch_36_softap_5g(self): |
| """Verify SoftAp ACS on STA 5G NON-DFS CH36 and SoftAp 5G in US. |
| Steps: See docstring of validate_country_softap_acs().""" |
| failures = self.validate_country_softap_acs("US", "5g", 36, "5g") |
| asserts.assert_false(failures, str(failures)) |
| |
| @test_tracker_info(uuid="35a5f2f5-067d-4d67-aeb8-58fb253f4b97") |
| def test_country_us_softap_acs_sta_5g_ch_132_softap_5g(self): |
| """Verify SoftAp ACS on STA 5G DFS CH52 and SoftAp 5G in US. |
| Steps: See docstring of validate_country_softap_acs().""" |
| failures = self.validate_country_softap_acs("US", "5g", 132, "5g") |
| asserts.assert_false(failures, str(failures)) |
| |
| @test_tracker_info(uuid="866954a3-72b6-4e7d-853f-9e1659cdf305") |
| def test_country_de_softap_acs_sta_5g_ch_161_softap_5g(self): |
| """Verify SoftAp ACS on STA 5G EU SRD CH149 and SoftAp 5G in DE. |
| Steps: See docstring of validate_country_softap_acs().""" |
| failures = self.validate_country_softap_acs("DE", "5g", 161, "5g") |
| asserts.assert_false(failures, str(failures)) |
| |
| @test_tracker_info(uuid="866954a3-72b6-4e7d-853f-9e1659cdf305") |
| def test_country_jp_softap_acs_sta_5g_ch_36_softap_5g(self): |
| """Verify SoftAp ACS on STA 5G EU SRD CH149 and SoftAp 5G in DE. |
| Steps: See docstring of validate_country_softap_acs().""" |
| failures = self.validate_country_softap_acs("JP", "5g", 36, "5g") |
| asserts.assert_false(failures, str(failures)) |