summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreeHugger Robot <treehugger-gerrit@google.com>2020-01-11 14:34:34 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2020-01-11 14:34:34 +0000
commit55ec406d188b3234c93bc35d1ad548b29937c79d (patch)
tree3b74ee9e0aceba08f60ca09eed3102bc4db4a057
parentf962d5a97b28ab265ce5de1c85f09b7f410dabf5 (diff)
parent4a5579017051ca6bc567186db346ef4e5536166c (diff)
Merge "softap: Add blocked/allowed client list support"
-rw-r--r--service/java/com/android/server/wifi/HostapdHal.java5
-rw-r--r--service/java/com/android/server/wifi/SoftApManager.java114
-rw-r--r--service/java/com/android/server/wifi/WifiServiceImpl.java34
-rw-r--r--service/java/com/android/server/wifi/util/ApConfigUtil.java49
-rw-r--r--tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java218
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java16
6 files changed, 390 insertions, 46 deletions
diff --git a/service/java/com/android/server/wifi/HostapdHal.java b/service/java/com/android/server/wifi/HostapdHal.java
index 2f461667e..45c02af43 100644
--- a/service/java/com/android/server/wifi/HostapdHal.java
+++ b/service/java/com/android/server/wifi/HostapdHal.java
@@ -28,6 +28,7 @@ import android.hidl.manager.V1_0.IServiceNotification;
import android.net.MacAddress;
import android.net.wifi.SoftApConfiguration;
import android.net.wifi.SoftApConfiguration.BandType;
+import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.IHwBinder.DeathRecipient;
import android.os.RemoteException;
@@ -585,10 +586,10 @@ public class HostapdHal {
byte[] clientMacByteArray = client.toByteArray();
short disconnectReason;
switch (reasonCode) {
- case ApConfigUtil.DISCONNECT_REASON_CODE_INVALID_AUTHENTICATION:
+ case WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER:
disconnectReason = Ieee80211ReasonCode.WLAN_REASON_PREV_AUTH_NOT_VALID;
break;
- case ApConfigUtil.DISCONNECT_REASON_CODE_NO_MORE_STAS:
+ case WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS:
disconnectReason = Ieee80211ReasonCode.WLAN_REASON_DISASSOC_AP_BUSY;
break;
default:
diff --git a/service/java/com/android/server/wifi/SoftApManager.java b/service/java/com/android/server/wifi/SoftApManager.java
index 742a3d05d..58b33553c 100644
--- a/service/java/com/android/server/wifi/SoftApManager.java
+++ b/service/java/com/android/server/wifi/SoftApManager.java
@@ -59,9 +59,11 @@ import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
+import java.util.Set;
/**
* Manage WiFi in AP mode.
@@ -117,6 +119,12 @@ public class SoftApManager implements ActiveModeManager {
private @Role int mRole = ROLE_UNSPECIFIED;
+ @NonNull
+ private Set<MacAddress> mBlockedClientList = new HashSet<>();
+
+ @NonNull
+ private Set<MacAddress> mAllowedClientList = new HashSet<>();
+
/**
* Listener for soft AP events.
*/
@@ -181,6 +189,10 @@ public class SoftApManager implements ActiveModeManager {
mSarManager = sarManager;
mWifiDiagnostics = wifiDiagnostics;
mStateMachine = new SoftApStateMachine(looper);
+ if (softApConfig != null) {
+ mBlockedClientList = new HashSet<>(softApConfig.getBlockedClientList());
+ mAllowedClientList = new HashSet<>(softApConfig.getAllowedClientList());
+ }
}
/**
@@ -394,20 +406,11 @@ public class SoftApManager implements ActiveModeManager {
Log.d(TAG, "SoftAP is a hidden network");
}
- if (config.getMaxNumberOfClients() != 0
- && !mCurrentSoftApCapability.isFeatureSupported(
- SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT)) {
- Log.d(TAG, "Error, Max Client control requires HAL support");
+ if (!ApConfigUtil.checkSupportAllConfiguration(config, mCurrentSoftApCapability)) {
+ Log.d(TAG, "Unsupported Configuration detect! config = " + config);
return ERROR_UNSUPPORTED_CONFIGURATION;
}
- if ((config.getSecurityType() == SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION
- || config.getSecurityType() == SoftApConfiguration.SECURITY_TYPE_WPA3_SAE)
- && !mCurrentSoftApCapability.isFeatureSupported(
- SoftApCapability.SOFTAP_FEATURE_WPA3_SAE)) {
- Log.d(TAG, "Error, SAE requires HAL support");
- return ERROR_UNSUPPORTED_CONFIGURATION;
- }
if (!mWifiNative.startSoftAp(mApInterfaceName,
localConfigBuilder.build(), mSoftApListener)) {
Log.e(TAG, "Soft AP start failed");
@@ -430,24 +433,39 @@ public class SoftApManager implements ActiveModeManager {
Log.d(TAG, "Soft AP is stopped");
}
- private boolean checkSoftApMaxClient(SoftApConfiguration config, WifiClient newClient) {
- boolean isAllow = true;
+ private boolean checkSoftApClient(SoftApConfiguration config, WifiClient newClient) {
+ if (!mCurrentSoftApCapability.isFeatureSupported(
+ SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT)) {
+ return true;
+ }
+
+ if (config.isClientControlByUserEnabled()
+ && !mAllowedClientList.contains(newClient.getMacAddress())) {
+ if (!mBlockedClientList.contains(newClient.getMacAddress())) {
+ mSoftApCallback.onBlockedClientConnecting(newClient,
+ WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER);
+ }
+ Log.d(TAG, "Force disconnect for unauthorized client: " + newClient);
+ mWifiNative.forceClientDisconnect(
+ mApInterfaceName, newClient.getMacAddress(),
+ WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER);
+ return false;
+ }
int maxConfig = mCurrentSoftApCapability.getMaxSupportedClients();
if (config.getMaxNumberOfClients() > 0) {
maxConfig = Math.min(maxConfig, config.getMaxNumberOfClients());
}
- if (mConnectedClients.size() == maxConfig) {
+
+ if (mConnectedClients.size() >= maxConfig) {
Log.i(TAG, "No more room for new client:" + newClient);
- if (mCurrentSoftApCapability.isFeatureSupported(
- SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT)) {
- Log.d(TAG, "Force disconnect for client: " + newClient);
- mWifiNative.forceClientDisconnect(
- mApInterfaceName, newClient.getMacAddress(),
- ApConfigUtil.DISCONNECT_REASON_CODE_NO_MORE_STAS);
- }
- isAllow = false;
+ mWifiNative.forceClientDisconnect(
+ mApInterfaceName, newClient.getMacAddress(),
+ WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS);
+ mSoftApCallback.onBlockedClientConnecting(newClient,
+ WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS);
+ return false;
}
- return isAllow;
+ return true;
}
private class SoftApStateMachine extends StateMachine {
@@ -555,8 +573,11 @@ public class SoftApManager implements ActiveModeManager {
break;
case CMD_UPDATE_CONFIG:
SoftApConfiguration newConfig = (SoftApConfiguration) message.obj;
+ Log.d(TAG, "Configuration changed to " + newConfig);
mApConfig = new SoftApModeConfiguration(mApConfig.getTargetMode(),
newConfig, mCurrentSoftApCapability);
+ mBlockedClientList = new HashSet<>(newConfig.getBlockedClientList());
+ mAllowedClientList = new HashSet<>(newConfig.getAllowedClientList());
break;
default:
// Ignore all other commands.
@@ -630,6 +651,10 @@ public class SoftApManager implements ActiveModeManager {
* configuration.
*/
private void updateClientConnection() {
+ if (!mCurrentSoftApCapability.isFeatureSupported(
+ SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT)) {
+ return;
+ }
final int maxAllowedClientsByHardwareAndCarrier =
mCurrentSoftApCapability.getMaxSupportedClients();
final int userApConfigMaxClientCount =
@@ -639,22 +664,39 @@ public class SoftApManager implements ActiveModeManager {
finalMaxClientCount = Math.min(userApConfigMaxClientCount,
maxAllowedClientsByHardwareAndCarrier);
}
- if (mConnectedClients.size() > finalMaxClientCount) {
- Log.d(TAG, "Capability Changed, update connected client");
+ int targetDisconnectClientNumber = mConnectedClients.size() - finalMaxClientCount;
+ List<WifiClient> allowedConnectedList = new ArrayList<>();
+ if (mApConfig.getSoftApConfiguration().isClientControlByUserEnabled()) {
+ // Check allow list first
Iterator<WifiClient> iterator = mConnectedClients.iterator();
- int remove_count = mConnectedClients.size() - finalMaxClientCount;
- if (mCurrentSoftApCapability.isFeatureSupported(
- SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT)) {
- while (iterator.hasNext()) {
- if (remove_count == 0) break;
- WifiClient client = iterator.next();
- Log.d(TAG, "Force disconnect for client: " + client);
+ while (iterator.hasNext()) {
+ WifiClient client = iterator.next();
+ if (mAllowedClientList.contains(client.getMacAddress())) {
+ allowedConnectedList.add(client);
+ } else {
+ Log.d(TAG, "Force disconnect for not allowed client: " + client);
mWifiNative.forceClientDisconnect(
mApInterfaceName, client.getMacAddress(),
- ApConfigUtil.DISCONNECT_REASON_CODE_NO_MORE_STAS);
- remove_count--;
+ WifiManager
+ .SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER);
+ targetDisconnectClientNumber--;
}
}
+ } else {
+ allowedConnectedList = new ArrayList<>(mConnectedClients);
+ }
+ if (targetDisconnectClientNumber > 0) {
+ Iterator<WifiClient> allowedClientIterator = allowedConnectedList.iterator();
+ while (allowedClientIterator.hasNext()) {
+ if (targetDisconnectClientNumber == 0) break;
+ WifiClient allowedClient = allowedClientIterator.next();
+ Log.d(TAG, "Force disconnect for client due to no more room: "
+ + allowedClient);
+ mWifiNative.forceClientDisconnect(
+ mApInterfaceName, allowedClient.getMacAddress(),
+ WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS);
+ targetDisconnectClientNumber--;
+ }
}
}
@@ -676,7 +718,7 @@ public class SoftApManager implements ActiveModeManager {
return;
}
if (isConnected) {
- boolean isAllow = checkSoftApMaxClient(
+ boolean isAllow = checkSoftApClient(
mApConfig.getSoftApConfiguration(), client);
if (isAllow) {
mConnectedClients.add(client);
@@ -926,6 +968,8 @@ public class SoftApManager implements ActiveModeManager {
boolean needRescheduleTimer =
mApConfig.getSoftApConfiguration().getShutdownTimeoutMillis()
!= newConfig.getShutdownTimeoutMillis();
+ mBlockedClientList = new HashSet<>(newConfig.getBlockedClientList());
+ mAllowedClientList = new HashSet<>(newConfig.getAllowedClientList());
mApConfig = new SoftApModeConfiguration(mApConfig.getTargetMode(),
newConfig, mCurrentSoftApCapability);
updateClientConnection();
diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java
index b9dc498ab..4bd2927e6 100644
--- a/service/java/com/android/server/wifi/WifiServiceImpl.java
+++ b/service/java/com/android/server/wifi/WifiServiceImpl.java
@@ -1127,6 +1127,27 @@ public class WifiServiceImpl extends BaseWifiService {
}
}
}
+
+ /**
+ * Called when client trying to connect but device blocked the client with specific reason.
+ *
+ * @param client the currently blocked client.
+ * @param blockedReason one of blocked reason from
+ * {@link WifiManager.SapClientBlockedReason}
+ */
+ @Override
+ public void onBlockedClientConnecting(WifiClient client, int blockedReason) {
+ Iterator<ISoftApCallback> iterator =
+ mRegisteredSoftApCallbacks.getCallbacks().iterator();
+ while (iterator.hasNext()) {
+ ISoftApCallback callback = iterator.next();
+ try {
+ callback.onBlockedClientConnecting(client, blockedReason);
+ } catch (RemoteException e) {
+ Log.e(TAG, "onBlockedClientConnecting: remote exception -- " + e);
+ }
+ }
+ }
}
/**
@@ -1483,6 +1504,18 @@ public class WifiServiceImpl extends BaseWifiService {
public void onCapabilityChanged(SoftApCapability capability) {
// Nothing to do
}
+
+ /**
+ * Called when client trying to connect but device blocked the client with specific reason.
+ *
+ * @param client the currently blocked client.
+ * @param blockedReason one of blocked reason from
+ * {@link WifiManager.SapClientBlockedReason}
+ */
+ @Override
+ public void onBlockedClientConnecting(WifiClient client, int blockedReason) {
+ // Nothing to do
+ }
}
/**
@@ -1508,6 +1541,7 @@ public class WifiServiceImpl extends BaseWifiService {
throw new IllegalArgumentException("Callback must not be null");
}
+
enforceNetworkSettingsPermission();
if (mVerboseLoggingEnabled) {
mLog.info("registerSoftApCallback uid=%").c(Binder.getCallingUid()).flush();
diff --git a/service/java/com/android/server/wifi/util/ApConfigUtil.java b/service/java/com/android/server/wifi/util/ApConfigUtil.java
index 45d3a9a12..77d0a5500 100644
--- a/service/java/com/android/server/wifi/util/ApConfigUtil.java
+++ b/service/java/com/android/server/wifi/util/ApConfigUtil.java
@@ -50,11 +50,6 @@ public class ApConfigUtil {
public static final int ERROR_GENERIC = 2;
public static final int ERROR_UNSUPPORTED_CONFIGURATION = 3;
- /* Reason code in IEEE Std 802.11-2016, 9.4.1.7, Table 9-45. */
- public static final int DISCONNECT_REASON_CODE_UNSPECIFIED_REASON = 1;
- public static final int DISCONNECT_REASON_CODE_INVALID_AUTHENTICATION = 2;
- public static final int DISCONNECT_REASON_CODE_NO_MORE_STAS = 5;
-
/* Random number generator used for AP channel selection. */
private static final Random sRandom = new Random();
@@ -410,6 +405,9 @@ public class ApConfigUtil {
* Helper function for converting SoftapConfiguration to WifiConfiguration.
* Note that WifiConfiguration only Supports 2GHz, 5GHz, 2GHz+5GHz bands,
* so conversion is limited to these bands.
+ *
+ * @param softApConfig the SoftApConfiguration which need to convert.
+ * @return the WifiConfiguration which convert from SoftApConfiguration.
*/
@NonNull
public static WifiConfiguration convertToWifiConfiguration(
@@ -454,6 +452,9 @@ public class ApConfigUtil {
* Only Support None and WPA2 configuration conversion.
* Note that WifiConfiguration only Supports 2GHz, 5GHz, 2GHz+5GHz bands,
* so conversion is limited to these bands.
+ *
+ * @param wifiConfig the WifiConfiguration which need to convert.
+ * @return the SoftApConfiguration which convert from WifiConfiguration.
*/
@NonNull
public static SoftApConfiguration fromWifiConfiguration(
@@ -492,6 +493,9 @@ public class ApConfigUtil {
/**
* Helper function to creating SoftApCapability instance with initial field from resource file.
+ *
+ * @param context the caller context used to get value from resource file.
+ * @return SoftApCapability which updated the feature support or not from resource.
*/
@NonNull
public static SoftApCapability updateCapabilityFromResource(@NonNull Context context) {
@@ -525,6 +529,9 @@ public class ApConfigUtil {
/**
* Helper function to get SAE support or not.
+ *
+ * @param context the caller context used to get value from resource file.
+ * @return true if supported, false otherwise.
*/
public static boolean isWpa3SaeSupported(@NonNull Context context) {
return context.getResources().getBoolean(
@@ -534,7 +541,10 @@ public class ApConfigUtil {
/**
* Helper function for comparing two SoftApConfiguration.
*
- * Return true if the difference between the two configurations requires a restart to apply.
+ * @param currentConfig the original configuration.
+ * @param newConfig the new configuration which plan to apply.
+ * @return true if the difference between the two configurations requires a restart to apply,
+ * false otherwise.
*/
public static boolean checkConfigurationChangeNeedToRestart(
SoftApConfiguration currentConfig, SoftApConfiguration newConfig) {
@@ -546,4 +556,31 @@ public class ApConfigUtil {
|| currentConfig.getBand() != newConfig.getBand()
|| currentConfig.getChannel() != newConfig.getChannel();
}
+
+
+ /**
+ * Helper function for checking all of the configuration are supported or not.
+ *
+ * @param config target configuration want to check.
+ * @param capability the capability which indicate feature support or not.
+ * @return true if supported, false otherwise.
+ */
+ public static boolean checkSupportAllConfiguration(SoftApConfiguration config,
+ SoftApCapability capability) {
+ if (!capability.isFeatureSupported(
+ SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT)
+ && (config.getMaxNumberOfClients() != 0 || config.isClientControlByUserEnabled())) {
+ Log.d(TAG, "Error, Client control requires HAL support");
+ return false;
+ }
+
+ if (!capability.isFeatureSupported(SoftApCapability.SOFTAP_FEATURE_WPA3_SAE)
+ && (config.getSecurityType()
+ == SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION
+ || config.getSecurityType() == SoftApConfiguration.SECURITY_TYPE_WPA3_SAE)) {
+ Log.d(TAG, "Error, SAE requires HAL support");
+ return false;
+ }
+ return true;
+ }
}
diff --git a/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java b/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java
index d46f7dd1b..66043dddf 100644
--- a/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java
@@ -70,7 +70,6 @@ import android.provider.Settings;
import androidx.test.filters.SmallTest;
import com.android.internal.util.WakeupMessage;
-import com.android.server.wifi.util.ApConfigUtil;
import com.android.wifi.resources.R;
import org.junit.Before;
@@ -1149,6 +1148,217 @@ public class SoftApManagerTest extends WifiBaseTest {
}
@Test
+ public void testForceClientDisconnectInvokeBecauseClientAuthorizationEnabled()
+ throws Exception {
+ mTestSoftApCapability.setMaxSupportedClients(10);
+ Builder configBuilder = new SoftApConfiguration.Builder();
+ configBuilder.setBand(SoftApConfiguration.BAND_2GHZ);
+ configBuilder.setSsid(TEST_SSID);
+ configBuilder.enableClientControlByUser(true);
+ SoftApModeConfiguration apConfig =
+ new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED,
+ configBuilder.build(), mTestSoftApCapability);
+ startSoftApAndVerifyEnabled(apConfig);
+
+ verify(mCallback).onConnectedClientsChanged(new ArrayList<>());
+
+ mSoftApListenerCaptor.getValue().onConnectedClientsChanged(
+ TEST_NATIVE_CLIENT, true);
+ mLooper.dispatchAll();
+
+ // Client is not allow verify
+ verify(mWifiNative).forceClientDisconnect(
+ TEST_INTERFACE_NAME, TEST_MAC_ADDRESS,
+ WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER);
+ verify(mWifiMetrics, never()).addSoftApNumAssociatedStationsChangedEvent(
+ 1, apConfig.getTargetMode());
+ verify(mCallback, never()).onConnectedClientsChanged(
+ Mockito.argThat((List<WifiClient> clients) ->
+ clients.contains(TEST_CONNECTED_CLIENT))
+ );
+
+ }
+
+ @Test
+ public void testClientConnectedAfterUpdateToAllowListwhenClientAuthorizationEnabled()
+ throws Exception {
+ mTestSoftApCapability.setMaxSupportedClients(10);
+ ArrayList<MacAddress> allowedClientList = new ArrayList<>();
+ Builder configBuilder = new SoftApConfiguration.Builder();
+ configBuilder.setBand(SoftApConfiguration.BAND_2GHZ);
+ configBuilder.setSsid(TEST_SSID);
+ configBuilder.enableClientControlByUser(true);
+ SoftApModeConfiguration apConfig =
+ new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED,
+ configBuilder.build(), mTestSoftApCapability);
+ startSoftApAndVerifyEnabled(apConfig);
+
+ verify(mCallback).onConnectedClientsChanged(new ArrayList<>());
+
+ mSoftApListenerCaptor.getValue().onConnectedClientsChanged(
+ TEST_NATIVE_CLIENT, true);
+ mLooper.dispatchAll();
+
+ // Client is not allow verify
+ verify(mWifiNative).forceClientDisconnect(
+ TEST_INTERFACE_NAME, TEST_MAC_ADDRESS,
+ WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER);
+ verify(mWifiMetrics, never()).addSoftApNumAssociatedStationsChangedEvent(
+ 1, apConfig.getTargetMode());
+ verify(mCallback, never()).onConnectedClientsChanged(
+ Mockito.argThat((List<WifiClient> clients) ->
+ clients.contains(TEST_CONNECTED_CLIENT))
+ );
+ verify(mCallback).onBlockedClientConnecting(TEST_CONNECTED_CLIENT,
+ WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER);
+ reset(mCallback);
+ reset(mWifiNative);
+ // Update configuration
+ allowedClientList.add(TEST_MAC_ADDRESS);
+ configBuilder.setClientList(new ArrayList<MacAddress>(), allowedClientList);
+ mSoftApManager.updateConfiguration(configBuilder.build());
+ mLooper.dispatchAll();
+ // Client connected again
+ mSoftApListenerCaptor.getValue().onConnectedClientsChanged(
+ TEST_NATIVE_CLIENT, true);
+ mLooper.dispatchAll();
+ verify(mWifiNative, never()).forceClientDisconnect(
+ TEST_INTERFACE_NAME, TEST_MAC_ADDRESS,
+ WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER);
+ verify(mWifiMetrics).addSoftApNumAssociatedStationsChangedEvent(
+ 1, apConfig.getTargetMode());
+ verify(mCallback).onConnectedClientsChanged(
+ Mockito.argThat((List<WifiClient> clients) ->
+ clients.contains(TEST_CONNECTED_CLIENT))
+ );
+ verify(mCallback, never()).onBlockedClientConnecting(TEST_CONNECTED_CLIENT,
+ WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER);
+ }
+
+ @Test
+ public void testClientConnectedAfterUpdateToBlockListwhenClientAuthorizationEnabled()
+ throws Exception {
+ mTestSoftApCapability.setMaxSupportedClients(10);
+ ArrayList<MacAddress> blockedClientList = new ArrayList<>();
+ Builder configBuilder = new SoftApConfiguration.Builder();
+ configBuilder.setBand(SoftApConfiguration.BAND_2GHZ);
+ configBuilder.setSsid(TEST_SSID);
+ configBuilder.enableClientControlByUser(true);
+ SoftApModeConfiguration apConfig =
+ new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED,
+ configBuilder.build(), mTestSoftApCapability);
+ startSoftApAndVerifyEnabled(apConfig);
+
+ verify(mCallback).onConnectedClientsChanged(new ArrayList<>());
+
+ mSoftApListenerCaptor.getValue().onConnectedClientsChanged(
+ TEST_NATIVE_CLIENT, true);
+ mLooper.dispatchAll();
+
+ // Client is not allow verify
+ verify(mWifiNative).forceClientDisconnect(
+ TEST_INTERFACE_NAME, TEST_MAC_ADDRESS,
+ WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER);
+ verify(mWifiMetrics, never()).addSoftApNumAssociatedStationsChangedEvent(
+ 1, apConfig.getTargetMode());
+ verify(mCallback, never()).onConnectedClientsChanged(
+ Mockito.argThat((List<WifiClient> clients) ->
+ clients.contains(TEST_CONNECTED_CLIENT))
+ );
+ verify(mCallback).onBlockedClientConnecting(TEST_CONNECTED_CLIENT,
+ WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER);
+ reset(mCallback);
+ reset(mWifiNative);
+ // Update configuration
+ blockedClientList.add(TEST_MAC_ADDRESS);
+ configBuilder.setClientList(blockedClientList, new ArrayList<MacAddress>());
+ mSoftApManager.updateConfiguration(configBuilder.build());
+ mLooper.dispatchAll();
+ // Client connected again
+ mSoftApListenerCaptor.getValue().onConnectedClientsChanged(
+ TEST_NATIVE_CLIENT, true);
+ mLooper.dispatchAll();
+ verify(mWifiNative).forceClientDisconnect(
+ TEST_INTERFACE_NAME, TEST_MAC_ADDRESS,
+ WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER);
+ verify(mWifiMetrics, never()).addSoftApNumAssociatedStationsChangedEvent(
+ 1, apConfig.getTargetMode());
+ verify(mCallback, never()).onConnectedClientsChanged(
+ Mockito.argThat((List<WifiClient> clients) ->
+ clients.contains(TEST_CONNECTED_CLIENT))
+ );
+ verify(mCallback, never()).onBlockedClientConnecting(TEST_CONNECTED_CLIENT,
+ WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER);
+ }
+
+ @Test
+ public void testConfigChangeToSmallAndClientAddBlockListCauseClientDisconnect()
+ throws Exception {
+ mTestSoftApCapability.setMaxSupportedClients(10);
+ ArrayList<MacAddress> allowedClientList = new ArrayList<>();
+ allowedClientList.add(TEST_MAC_ADDRESS);
+ allowedClientList.add(TEST_MAC_ADDRESS_2);
+ ArrayList<MacAddress> blockedClientList = new ArrayList<>();
+
+ Builder configBuilder = new SoftApConfiguration.Builder();
+ configBuilder.setBand(SoftApConfiguration.BAND_2GHZ);
+ configBuilder.setSsid(TEST_SSID);
+ configBuilder.enableClientControlByUser(true);
+ configBuilder.setMaxNumberOfClients(2);
+ configBuilder.setClientList(new ArrayList<MacAddress>(), allowedClientList);
+ SoftApModeConfiguration apConfig =
+ new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED,
+ configBuilder.build(), mTestSoftApCapability);
+ startSoftApAndVerifyEnabled(apConfig);
+
+ verify(mCallback).onConnectedClientsChanged(new ArrayList<>());
+
+ mSoftApListenerCaptor.getValue().onConnectedClientsChanged(
+ TEST_NATIVE_CLIENT, true);
+ mLooper.dispatchAll();
+
+ verify(mCallback, times(2)).onConnectedClientsChanged(
+ Mockito.argThat((List<WifiClient> clients) ->
+ clients.contains(TEST_CONNECTED_CLIENT))
+ );
+
+ verify(mWifiMetrics).addSoftApNumAssociatedStationsChangedEvent(
+ 1, apConfig.getTargetMode());
+ // Verify timer is canceled at this point
+ verify(mAlarmManager.getAlarmManager()).cancel(any(WakeupMessage.class));
+
+ // Second client connect and max client set is 1.
+ mSoftApListenerCaptor.getValue().onConnectedClientsChanged(
+ TEST_NATIVE_CLIENT_2, true);
+ mLooper.dispatchAll();
+
+ verify(mCallback, times(3)).onConnectedClientsChanged(
+ Mockito.argThat((List<WifiClient> clients) ->
+ clients.contains(TEST_CONNECTED_CLIENT_2))
+ );
+ verify(mWifiMetrics).addSoftApNumAssociatedStationsChangedEvent(
+ 2, apConfig.getTargetMode());
+ reset(mCallback);
+ reset(mWifiNative);
+ // Update configuration
+ allowedClientList.clear();
+ allowedClientList.add(TEST_MAC_ADDRESS_2);
+
+ blockedClientList.add(TEST_MAC_ADDRESS);
+ configBuilder.setClientList(blockedClientList, allowedClientList);
+ configBuilder.setMaxNumberOfClients(1);
+ mSoftApManager.updateConfiguration(configBuilder.build());
+ mLooper.dispatchAll();
+ verify(mWifiNative).forceClientDisconnect(
+ TEST_INTERFACE_NAME, TEST_MAC_ADDRESS,
+ WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER);
+ verify(mWifiNative, never()).forceClientDisconnect(
+ TEST_INTERFACE_NAME, TEST_MAC_ADDRESS,
+ WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS);
+ }
+
+
+ @Test
public void schedulesTimeoutTimerOnStart() throws Exception {
SoftApModeConfiguration apConfig =
new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null,
@@ -1410,7 +1620,7 @@ public class SoftApManagerTest extends WifiBaseTest {
mLooper.dispatchAll();
verify(mWifiNative).forceClientDisconnect(
TEST_INTERFACE_NAME, TEST_MAC_ADDRESS_2,
- ApConfigUtil.DISCONNECT_REASON_CODE_NO_MORE_STAS);
+ WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS);
verify(mWifiMetrics, never()).addSoftApNumAssociatedStationsChangedEvent(
2, apConfig.getTargetMode());
}
@@ -1616,9 +1826,11 @@ public class SoftApManagerTest extends WifiBaseTest {
mSoftApListenerCaptor.getValue().onConnectedClientsChanged(
TEST_NATIVE_CLIENT_2, true);
mLooper.dispatchAll();
+ // feature not support thus it should not trigger disconnect
verify(mWifiNative, never()).forceClientDisconnect(
any(), any(), anyInt());
- verify(mWifiMetrics, never()).addSoftApNumAssociatedStationsChangedEvent(
+ // feature not support thus client still allow connected.
+ verify(mWifiMetrics).addSoftApNumAssociatedStationsChangedEvent(
2, apConfig.getTargetMode());
}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
index dbba907a7..ff7711848 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
@@ -2275,6 +2275,7 @@ public class WifiServiceImplTest extends WifiBaseTest {
verify(mClientSoftApCallback, never()).onStateChanged(WIFI_AP_STATE_DISABLED, 0);
verify(mClientSoftApCallback, never()).onConnectedClientsChanged(any());
verify(mClientSoftApCallback, never()).onInfoChanged(any());
+ verify(mClientSoftApCallback, never()).onCapabilityChanged(any());
}
@@ -2298,6 +2299,9 @@ public class WifiServiceImplTest extends WifiBaseTest {
verify(callback).onStateChanged(WIFI_AP_STATE_DISABLED, 0);
verify(callback).onConnectedClientsChanged(Mockito.<WifiClient>anyList());
verify(callback).onInfoChanged(new SoftApInfo());
+ verify(callback).onCapabilityChanged(ApConfigUtil.updateCapabilityFromResource(mContext));
+ // Don't need to invoke callback when register.
+ verify(callback, never()).onBlockedClientConnecting(any(), anyInt());
}
/**
@@ -2371,14 +2375,18 @@ public class WifiServiceImplTest extends WifiBaseTest {
@Test
public void correctCallbackIsCalledAfterAddingTwoCallbacksAndRemovingOne() throws Exception {
final int callbackIdentifier = 1;
+ WifiClient testWifiClient = new WifiClient(MacAddress.fromString("22:33:44:55:66:77"));
mWifiServiceImpl.registerSoftApCallback(mAppBinder, mClientSoftApCallback,
callbackIdentifier);
+ mLooper.dispatchAll();
// Change state from default before registering the second callback
final List<WifiClient> testClients = new ArrayList();
mStateMachineSoftApCallback.onStateChanged(WIFI_AP_STATE_ENABLED, 0);
mStateMachineSoftApCallback.onConnectedClientsChanged(testClients);
mStateMachineSoftApCallback.onInfoChanged(mTestSoftApInfo);
+ mStateMachineSoftApCallback.onBlockedClientConnecting(testWifiClient, 0);
+
// Register another callback and verify the new state is returned in the immediate callback
final int anotherUid = 2;
@@ -2387,6 +2395,10 @@ public class WifiServiceImplTest extends WifiBaseTest {
verify(mAnotherSoftApCallback).onStateChanged(WIFI_AP_STATE_ENABLED, 0);
verify(mAnotherSoftApCallback).onConnectedClientsChanged(testClients);
verify(mAnotherSoftApCallback).onInfoChanged(mTestSoftApInfo);
+ // Verify only first callback will receive onBlockedClientConnecting since it call after
+ // first callback register but before another callback register.
+ verify(mClientSoftApCallback).onBlockedClientConnecting(testWifiClient, 0);
+ verify(mAnotherSoftApCallback, never()).onBlockedClientConnecting(testWifiClient, 0);
// unregister the fisrt callback
mWifiServiceImpl.unregisterSoftApCallback(callbackIdentifier);
@@ -2472,9 +2484,11 @@ public class WifiServiceImplTest extends WifiBaseTest {
@Test
public void updatesSoftApStateAndConnectedClientsOnSoftApEvents() throws Exception {
final List<WifiClient> testClients = new ArrayList();
+ WifiClient testWifiClient = new WifiClient(MacAddress.fromString("22:33:44:55:66:77"));
mStateMachineSoftApCallback.onStateChanged(WIFI_AP_STATE_ENABLED, 0);
mStateMachineSoftApCallback.onConnectedClientsChanged(testClients);
mStateMachineSoftApCallback.onInfoChanged(mTestSoftApInfo);
+ mStateMachineSoftApCallback.onBlockedClientConnecting(testWifiClient, 0);
// Register callback after num clients and soft AP are changed.
final int callbackIdentifier = 1;
@@ -2484,6 +2498,8 @@ public class WifiServiceImplTest extends WifiBaseTest {
verify(mClientSoftApCallback).onStateChanged(WIFI_AP_STATE_ENABLED, 0);
verify(mClientSoftApCallback).onConnectedClientsChanged(testClients);
verify(mClientSoftApCallback).onInfoChanged(mTestSoftApInfo);
+ // Don't need to invoke callback when register.
+ verify(mClientSoftApCallback, never()).onBlockedClientConnecting(any(), anyInt());
}
private class IntentFilterMatcher implements ArgumentMatcher<IntentFilter> {