Restrict channel range in ACS
This allows the device to select one of the specified
channels when ACS is enabled.
Bug: 116839455
Test: Manual
Test: Unit test
Signed-off-by: Daichi Ueura <daichi.ueura@sony.com>
Change-Id: Ieb4aff67eba80e93d428d8adc6498483e26a440f
(cherry-picked from e53b8e0d87587aaa0757870b5120cf5146d3570b)
diff --git a/service/java/com/android/server/wifi/HostapdHal.java b/service/java/com/android/server/wifi/HostapdHal.java
index 57d99e6..d8f6f39 100644
--- a/service/java/com/android/server/wifi/HostapdHal.java
+++ b/service/java/com/android/server/wifi/HostapdHal.java
@@ -33,7 +33,9 @@
import com.android.server.wifi.WifiNative.HostapdDeathEventHandler;
import com.android.server.wifi.util.NativeUtil;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.NoSuchElementException;
import javax.annotation.concurrent.ThreadSafe;
@@ -52,6 +54,8 @@
private boolean mVerboseLoggingEnabled = false;
private final boolean mEnableAcs;
private final boolean mEnableIeee80211AC;
+ private final List<android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange>
+ mAcsChannelRanges;
// Hostapd HAL interface objects
private IServiceManager mIServiceManager = null;
@@ -97,6 +101,8 @@
mEnableAcs = context.getResources().getBoolean(R.bool.config_wifi_softap_acs_supported);
mEnableIeee80211AC =
context.getResources().getBoolean(R.bool.config_wifi_softap_ieee80211ac_supported);
+ mAcsChannelRanges = toAcsChannelRanges(context.getResources().getString(
+ R.string.config_wifi_softap_acs_supported_channel_list));
}
/**
@@ -320,7 +326,18 @@
nwParams.pskPassphrase = (config.preSharedKey != null) ? config.preSharedKey : "";
if (!checkHostapdAndLogFailure(methodStr)) return false;
try {
- HostapdStatus status = mIHostapd.addAccessPoint(ifaceParams, nwParams);
+ HostapdStatus status;
+ if (isV1_1()) {
+ android.hardware.wifi.hostapd.V1_1.IHostapd.IfaceParams ifaceParams1_1 =
+ new android.hardware.wifi.hostapd.V1_1.IHostapd.IfaceParams();
+ ifaceParams1_1.V1_0 = ifaceParams;
+ if (mEnableAcs) {
+ ifaceParams1_1.channelParams.acsChannelRanges.addAll(mAcsChannelRanges);
+ }
+ status = getHostapdMockableV1_1().addAccessPoint_1_1(ifaceParams1_1, nwParams);
+ } else {
+ status = mIHostapd.addAccessPoint(ifaceParams, nwParams);
+ }
if (!checkStatusAndLogFailure(status, methodStr)) {
return false;
}
@@ -528,6 +545,46 @@
}
/**
+ * Convert channel list string like '1-6,11' to list of AcsChannelRanges
+ */
+ private List<android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange>
+ toAcsChannelRanges(String channelListStr) {
+ ArrayList<android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange> acsChannelRanges =
+ new ArrayList<>();
+ String[] channelRanges = channelListStr.split(",");
+ for (String channelRange : channelRanges) {
+ android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange acsChannelRange =
+ new android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange();
+ try {
+ if (channelRange.contains("-")) {
+ String[] channels = channelRange.split("-");
+ if (channels.length != 2) {
+ Log.e(TAG, "Unrecognized channel range, length is " + channels.length);
+ continue;
+ }
+ int start = Integer.parseInt(channels[0]);
+ int end = Integer.parseInt(channels[1]);
+ if (start > end) {
+ Log.e(TAG, "Invalid channel range, from " + start + " to " + end);
+ continue;
+ }
+ acsChannelRange.start = start;
+ acsChannelRange.end = end;
+ } else {
+ acsChannelRange.start = Integer.parseInt(channelRange);
+ acsChannelRange.end = acsChannelRange.start;
+ }
+ } catch (NumberFormatException e) {
+ // Ignore malformed value
+ Log.e(TAG, "Malformed channel value detected: " + e);
+ continue;
+ }
+ acsChannelRanges.add(acsChannelRange);
+ }
+ return acsChannelRanges;
+ }
+
+ /**
* Returns false if Hostapd is null, and logs failure to call methodStr
*/
private boolean checkHostapdAndLogFailure(String methodStr) {
diff --git a/service/tests/wifitests/src/com/android/server/wifi/HostapdHalTest.java b/service/tests/wifitests/src/com/android/server/wifi/HostapdHalTest.java
index 453187c..20fd4fd 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/HostapdHalTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/HostapdHalTest.java
@@ -46,6 +46,8 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.ArrayList;
+
/**
* Unit tests for HostapdHal
*/
@@ -74,6 +76,9 @@
ArgumentCaptor.forClass(IServiceNotification.Stub.class);
private ArgumentCaptor<IHostapd.IfaceParams> mIfaceParamsCaptor =
ArgumentCaptor.forClass(IHostapd.IfaceParams.class);
+ private ArgumentCaptor<android.hardware.wifi.hostapd.V1_1.IHostapd.IfaceParams>
+ mIfaceParamsCaptorV1_1 =
+ ArgumentCaptor.forClass(android.hardware.wifi.hostapd.V1_1.IHostapd.IfaceParams.class);
private ArgumentCaptor<IHostapd.NetworkParams> mNetworkParamsCaptor =
ArgumentCaptor.forClass(IHostapd.NetworkParams.class);
private InOrder mInOrder;
@@ -106,6 +111,7 @@
mResources = new MockResources();
mResources.setBoolean(R.bool.config_wifi_softap_acs_supported, false);
mResources.setBoolean(R.bool.config_wifi_softap_ieee80211ac_supported, false);
+ mResources.setString(R.string.config_wifi_softap_acs_supported_channel_list, "");
mStatusSuccess = createHostapdStatus(HostapdStatusCode.SUCCESS);
mStatusFailure = createHostapdStatus(HostapdStatusCode.FAILURE_UNKNOWN);
@@ -441,6 +447,73 @@
}
/**
+ * Verifies the successful addition of access point.
+ * Verifies that channel info for ACS is handled.
+ */
+ @Test
+ public void testAddAccessPointSuccess_Psk_BandAny_WithACS_AcsChannels() throws Exception {
+ when(mServiceManagerMock.getTransport(anyString(), anyString()))
+ .thenReturn(IServiceManager.Transport.HWBINDER);
+ mIHostapdMockV1_1 = mock(android.hardware.wifi.hostapd.V1_1.IHostapd.class);
+ // Enable ACS and set available channels in the config.
+ final String acsChannelStr = "1,6,11-13,40";
+ android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange channelRange1 =
+ new android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange();
+ android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange channelRange2 =
+ new android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange();
+ android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange channelRange3 =
+ new android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange();
+ android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange channelRange4 =
+ new android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange();
+ channelRange1.start = channelRange1.end = 1;
+ channelRange2.start = channelRange2.end = 6;
+ channelRange3.start = 11;
+ channelRange3.end = 13;
+ channelRange4.start = channelRange4.end = 40;
+ ArrayList<android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange> acsChannelRanges =
+ new ArrayList<>();
+ acsChannelRanges.add(channelRange1);
+ acsChannelRanges.add(channelRange2);
+ acsChannelRanges.add(channelRange3);
+ acsChannelRanges.add(channelRange4);
+ mResources.setBoolean(R.bool.config_wifi_softap_acs_supported, true);
+ mResources.setString(R.string.config_wifi_softap_acs_supported_channel_list, acsChannelStr);
+ mHostapdHal = new HostapdHalSpy();
+
+ when(mIHostapdMockV1_1.addAccessPoint_1_1(
+ mIfaceParamsCaptorV1_1.capture(), mNetworkParamsCaptor.capture()))
+ .thenReturn(mStatusSuccess);
+
+ executeAndValidateInitializationSequenceV1_1(false);
+
+ WifiConfiguration configuration = new WifiConfiguration();
+ configuration.SSID = NETWORK_SSID;
+ configuration.hiddenSSID = false;
+ configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA2_PSK);
+ configuration.preSharedKey = NETWORK_PSK;
+ configuration.apBand = WifiConfiguration.AP_BAND_ANY;
+
+ assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME, configuration, mSoftApListener));
+ verify(mIHostapdMockV1_1).addAccessPoint_1_1(any(), any());
+
+ assertEquals(IFACE_NAME, mIfaceParamsCaptorV1_1.getValue().V1_0.ifaceName);
+ assertTrue(mIfaceParamsCaptorV1_1.getValue().V1_0.hwModeParams.enable80211N);
+ assertFalse(mIfaceParamsCaptorV1_1.getValue().V1_0.hwModeParams.enable80211AC);
+ assertEquals(IHostapd.Band.BAND_ANY,
+ mIfaceParamsCaptorV1_1.getValue().V1_0.channelParams.band);
+ assertTrue(mIfaceParamsCaptorV1_1.getValue().V1_0.channelParams.enableAcs);
+ assertTrue(mIfaceParamsCaptorV1_1.getValue().V1_0.channelParams.acsShouldExcludeDfs);
+ assertEquals(acsChannelRanges,
+ mIfaceParamsCaptorV1_1.getValue().channelParams.acsChannelRanges);
+
+ assertEquals(NativeUtil.stringToByteArrayList(NETWORK_SSID),
+ mNetworkParamsCaptor.getValue().ssid);
+ assertFalse(mNetworkParamsCaptor.getValue().isHidden);
+ assertEquals(IHostapd.EncryptionType.WPA2, mNetworkParamsCaptor.getValue().encryptionType);
+ assertEquals(NETWORK_PSK, mNetworkParamsCaptor.getValue().pskPassphrase);
+ }
+
+ /**
* Verifies the failure handling in addition of access point with an invalid band.
*/
@Test
@@ -537,6 +610,9 @@
when(mServiceManagerMock.getTransport(anyString(), anyString()))
.thenReturn(IServiceManager.Transport.HWBINDER);
mIHostapdMockV1_1 = mock(android.hardware.wifi.hostapd.V1_1.IHostapd.class);
+ when(mIHostapdMockV1_1.addAccessPoint_1_1(
+ mIfaceParamsCaptorV1_1.capture(), mNetworkParamsCaptor.capture()))
+ .thenReturn(mStatusSuccess);
executeAndValidateInitializationSequenceV1_1(false);
WifiConfiguration configuration = new WifiConfiguration();
@@ -544,7 +620,7 @@
configuration.apBand = WifiConfiguration.AP_BAND_2GHZ;
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME, configuration, mSoftApListener));
- verify(mIHostapdMock).addAccessPoint(any(), any());
+ verify(mIHostapdMockV1_1).addAccessPoint_1_1(any(), any());
// Trigger on failure.
mIHostapdCallback.onFailure(IFACE_NAME);