summaryrefslogtreecommitdiff
path: root/wifi
diff options
context:
space:
mode:
authorLes Lee <lesl@google.com>2020-12-23 13:53:17 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2020-12-23 13:53:17 +0000
commitb241613297cb47a48eacbe9a140e9a27299781f7 (patch)
tree0ecd7fffaeb941a6923790f89f730c649b524cee /wifi
parentcf749b91549aab68a28de6e1b467fb2f6536a34a (diff)
parente5436af58ca25daef3f22d707346fb368238e69c (diff)
Merge changes from topic "bridged_AP_callback"
* changes: wifi: Add callback onConnectedClientsOrInfoChanged handling wifi: Add new callback to support use case in bridged mode
Diffstat (limited to 'wifi')
-rw-r--r--wifi/api/system-current.txt3
-rw-r--r--wifi/java/android/net/wifi/ISoftApCallback.aidl23
-rw-r--r--wifi/java/android/net/wifi/WifiManager.java145
-rw-r--r--wifi/tests/src/android/net/wifi/WifiManagerTest.java335
4 files changed, 427 insertions, 79 deletions
diff --git a/wifi/api/system-current.txt b/wifi/api/system-current.txt
index 257f9d53e59f..23e396251f74 100644
--- a/wifi/api/system-current.txt
+++ b/wifi/api/system-current.txt
@@ -639,8 +639,9 @@ package android.net.wifi {
method public default void onBlockedClientConnecting(@NonNull android.net.wifi.WifiClient, int);
method public default void onCapabilityChanged(@NonNull android.net.wifi.SoftApCapability);
method public default void onConnectedClientsChanged(@NonNull java.util.List<android.net.wifi.WifiClient>);
+ method public default void onConnectedClientsChanged(@NonNull android.net.wifi.SoftApInfo, @NonNull java.util.List<android.net.wifi.WifiClient>);
method public default void onInfoChanged(@NonNull android.net.wifi.SoftApInfo);
- method public default void onInfoListChanged(@NonNull java.util.List<android.net.wifi.SoftApInfo>);
+ method public default void onInfoChanged(@NonNull java.util.List<android.net.wifi.SoftApInfo>);
method public default void onStateChanged(int, int);
}
diff --git a/wifi/java/android/net/wifi/ISoftApCallback.aidl b/wifi/java/android/net/wifi/ISoftApCallback.aidl
index a28a8fb626b1..3db0a5dfe9c2 100644
--- a/wifi/java/android/net/wifi/ISoftApCallback.aidl
+++ b/wifi/java/android/net/wifi/ISoftApCallback.aidl
@@ -40,25 +40,16 @@ oneway interface ISoftApCallback
void onStateChanged(int state, int failureReason);
/**
- * Service to manager callback providing connected client's information.
- *
- * @param clients the currently connected clients
- */
- void onConnectedClientsChanged(in List<WifiClient> clients);
-
- /**
- * Service to manager callback providing information of softap.
- *
- * @param softApInfo is the softap information. {@link SoftApInfo}
- */
- void onInfoChanged(in SoftApInfo softApInfo);
-
- /**
* Service to manager callback providing informations of softap.
*
- * @param softApInfoList is the list of the softap informations. {@link SoftApInfo}
+ * @param infos The currently {@link SoftApInfo} in each AP instance.
+ * @param clients The currently connected clients in each AP instance.
+ * @param isBridged whether or not the current AP enabled on bridged mode.
+ * @param isRegistration whether or not the callbackk was triggered when register.
*/
- void onInfoListChanged(in List<SoftApInfo> softApInfoList);
+ void onConnectedClientsOrInfoChanged(in Map<String, SoftApInfo> infos,
+ in Map<String, List<WifiClient>> clients, boolean isBridged,
+ boolean isRegistration);
/**
* Service to manager callback providing capability of softap.
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 6496cc7a3ba3..5618ee8e4233 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -4026,13 +4026,33 @@ public class WifiManager {
*/
default void onConnectedClientsChanged(@NonNull List<WifiClient> clients) {}
+
+ /**
+ * Called when the connected clients for a soft AP instance change.
+ *
+ * When the Soft AP is configured in single AP mode, this callback is invoked
+ * with the same {@link SoftApInfo} for all connected clients changes.
+ * When the Soft AP is configured in bridged mode, this callback is invoked with
+ * the corresponding {@link SoftApInfo} for the instance in which the connected clients
+ * changed.
+ *
+ * Use {@link #onConnectedClientsChanged(List<WifiClient>)} if you don't care about
+ * the mapping from SoftApInfo instance to connected clients.
+ *
+ * @param info The {@link SoftApInfo} of the AP.
+ * @param clients The currently connected clients on the AP instance specified by
+ * {@code info}.
+ */
+ default void onConnectedClientsChanged(@NonNull SoftApInfo info,
+ @NonNull List<WifiClient> clients) {}
+
/**
* Called when information of softap changes.
*
* Note: this API is only valid when the Soft AP is configured as a single AP
* - not as a bridged AP (2 Soft APs). When the Soft AP is configured as bridged AP
* this callback will not be triggered - use the
- * {@link #onInfoListChanged(List<SoftApInfo>)} callback in bridged AP mode.
+ * {@link #onInfoChanged(List<SoftApInfo>)} callback in bridged AP mode.
*
* @param softApInfo is the softap information. {@link SoftApInfo}
*/
@@ -4050,11 +4070,15 @@ public class WifiManager {
* as a single AP, and two information elements will be returned in the list
* when the Soft AP is configured in bridged mode.
*
+ * Note: One of the Soft APs may be shut down independently of the other by the framework,
+ * for instance if no devices are connected to it for some duration.
+ * In that case, one information element will be returned in the list in bridged mode.
+ *
* See {@link #isBridgedApConcurrencySupported()} for the detail of the bridged AP.
*
* @param softApInfoList is the list of the softap information elements. {@link SoftApInfo}
*/
- default void onInfoListChanged(@NonNull List<SoftApInfo> softApInfoList) {
+ default void onInfoChanged(@NonNull List<SoftApInfo> softApInfoList) {
// Do nothing: can be updated to add SoftApInfo details (e.g. channel) to the UI.
}
@@ -4093,6 +4117,16 @@ public class WifiManager {
private class SoftApCallbackProxy extends ISoftApCallback.Stub {
private final Executor mExecutor;
private final SoftApCallback mCallback;
+ private Map<String, List<WifiClient>> mCurrentClients = new HashMap<>();
+ private Map<String, SoftApInfo> mCurrentInfos = new HashMap<>();
+
+ private List<WifiClient> getConnectedClientList(Map<String, List<WifiClient>> clientsMap) {
+ List<WifiClient> connectedClientList = new ArrayList<>();
+ for (List<WifiClient> it : clientsMap.values()) {
+ connectedClientList.addAll(it);
+ }
+ return connectedClientList;
+ }
SoftApCallbackProxy(Executor executor, SoftApCallback callback) {
mExecutor = executor;
@@ -4113,41 +4147,84 @@ public class WifiManager {
}
@Override
- public void onConnectedClientsChanged(List<WifiClient> clients) {
+ public void onConnectedClientsOrInfoChanged(Map<String, SoftApInfo> infos,
+ Map<String, List<WifiClient>> clients, boolean isBridged, boolean isRegistration) {
if (mVerboseLoggingEnabled) {
- Log.v(TAG, "SoftApCallbackProxy: onConnectedClientsChanged: clients="
- + clients.size() + " clients");
+ Log.v(TAG, "SoftApCallbackProxy: onConnectedClientsOrInfoChanged: clients: "
+ + clients + ", infos: " + infos + ", isBridged is " + isBridged
+ + ", isRegistration is " + isRegistration);
}
- Binder.clearCallingIdentity();
- mExecutor.execute(() -> {
- mCallback.onConnectedClientsChanged(clients);
- });
- }
-
- @Override
- public void onInfoChanged(SoftApInfo softApInfo) {
- if (mVerboseLoggingEnabled) {
- Log.v(TAG, "SoftApCallbackProxy: onInfoChange: softApInfo=" + softApInfo);
+ List<SoftApInfo> changedInfoList = new ArrayList<>(infos.values());
+ Map<SoftApInfo, List<WifiClient>> changedInfoClients = new HashMap<>();
+ boolean isInfoChanged = infos.size() != mCurrentInfos.size();
+ for (SoftApInfo info : mCurrentInfos.values()) {
+ String changedInstance = info.getApInstanceIdentifier();
+ if (!changedInfoList.contains(info)) {
+ isInfoChanged = true;
+ if (mCurrentClients.getOrDefault(changedInstance,
+ Collections.emptyList()).size() > 0) {
+ Log.d(TAG, "SoftApCallbackProxy: info changed on client connected"
+ + " instance(Shut Down case)");
+ //Here should notify client changed on old info
+ changedInfoClients.put(info, Collections.emptyList());
+ }
+ } else {
+ // info doesn't change, check client list
+ List<WifiClient> changedClientList = clients.getOrDefault(
+ changedInstance, Collections.emptyList());
+ if (changedClientList.size()
+ != mCurrentClients
+ .getOrDefault(changedInstance, Collections.emptyList()).size()) {
+ // Here should notify client changed on new info(same as old info)
+ changedInfoClients.put(info, changedClientList);
+ Log.d(TAG, "SoftApCallbackProxy: client changed on " + info
+ + " list: " + changedClientList);
+ }
+ }
}
+ if (!isInfoChanged && changedInfoClients.isEmpty()
+ && !isRegistration) {
+ Log.v(TAG, "SoftApCallbackProxy: No changed & Not Registration,"
+ + " don't need to notify the client");
+ return;
+ }
+ mCurrentClients = clients;
+ mCurrentInfos = infos;
Binder.clearCallingIdentity();
- mExecutor.execute(() -> {
- mCallback.onInfoChanged(softApInfo);
- });
- }
+ // Notify the clients changed first for old info shutdown case
+ for (SoftApInfo changedInfo : changedInfoClients.keySet()) {
+ Log.v(TAG, "send onConnectedClientsChanged, changedInfo is " + changedInfo);
+ mExecutor.execute(() -> {
+ mCallback.onConnectedClientsChanged(
+ changedInfo, changedInfoClients.get(changedInfo));
+ });
+ }
- @Override
- public void onInfoListChanged(List<SoftApInfo> softApInfoList) {
- if (mVerboseLoggingEnabled) {
- Log.v(TAG, "SoftApCallbackProxy: onInfoListChange: softApInfoList="
- + softApInfoList);
+ if (isInfoChanged || isRegistration) {
+ if (!isBridged) {
+ SoftApInfo newInfo = changedInfoList.isEmpty()
+ ? new SoftApInfo() : changedInfoList.get(0);
+ Log.v(TAG, "SoftApCallbackProxy: send InfoChanged, newInfo: " + newInfo);
+ mExecutor.execute(() -> {
+ mCallback.onInfoChanged(newInfo);
+ });
+ }
+ Log.v(TAG, "SoftApCallbackProxy: send InfoChanged, changedInfoList: "
+ + changedInfoList);
+ mExecutor.execute(() -> {
+ mCallback.onInfoChanged(changedInfoList);
+ });
}
- Binder.clearCallingIdentity();
- mExecutor.execute(() -> {
- mCallback.onInfoListChanged(softApInfoList);
- });
+ if (isRegistration || !changedInfoClients.isEmpty()) {
+ Log.v(TAG, "SoftApCallbackProxy: send onConnectedClientsChanged(clients): "
+ + getConnectedClientList(clients));
+ mExecutor.execute(() -> {
+ mCallback.onConnectedClientsChanged(getConnectedClientList(clients));
+ });
+ }
}
@Override
@@ -4184,8 +4261,20 @@ public class WifiManager {
* <li> {@link SoftApCallback#onStateChanged(int, int)}</li>
* <li> {@link SoftApCallback#onConnectedClientsChanged(List<WifiClient>)}</li>
* <li> {@link SoftApCallback#onInfoChanged(SoftApInfo)}</li>
+ * <li> {@link SoftApCallback#onInfoChanged(List<SoftApInfo>)}</li>
* <li> {@link SoftApCallback#onCapabilityChanged(SoftApCapability)}</li>
* </ul>
+ *
+ * Use {@link SoftApCallback#onConnectedClientsChanged(List<WifiClient>)} to know if there are
+ * any clients connected to any of the bridged instances of this AP (if bridged AP is enabled).
+ * Use {@link SoftApCallback#onConnectedClientsChanged(SoftApInfo, List<WifiClient>)} to know
+ * if there are any clients connected to a specific bridged instance of this AP
+ * (if bridged AP is enabled).
+ *
+ * Note: Caller will receive the callback
+ * {@link SoftApCallback#onConnectedClientsChangedWithApInfo(SoftApInfo, List<WifiClient>)}
+ * on registration when there are clients connected to AP.
+ *
* These will be dispatched on registration to provide the caller with the current state
* (and are not an indication of any current change). Note that receiving an immediate
* WIFI_AP_STATE_FAILED value for soft AP state indicates that the latest attempt to start
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index b15fa2c926f4..274cff2f41e8 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -67,6 +67,7 @@ import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -110,6 +111,7 @@ import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
@@ -135,10 +137,18 @@ public class WifiManagerTest {
private static final String TEST_FEATURE_ID = "TestFeature";
private static final String TEST_COUNTRY_CODE = "US";
private static final String[] TEST_MAC_ADDRESSES = {"da:a1:19:0:0:0"};
- private static final int TEST_AP_FREQUENCY = 2412;
- private static final int TEST_AP_BANDWIDTH = SoftApInfo.CHANNEL_WIDTH_20MHZ;
private static final int TEST_SUB_ID = 3;
- private static final String TEST_AP_INSTANCE = "wlan1";
+ private static final String[] TEST_AP_INSTANCES = new String[] {"wlan1", "wlan2"};
+ private static final int[] TEST_AP_FREQS = new int[] {2412, 5220};
+ private static final int[] TEST_AP_BWS = new int[] {SoftApInfo.CHANNEL_WIDTH_20MHZ_NOHT,
+ SoftApInfo.CHANNEL_WIDTH_80MHZ};
+ private static final MacAddress[] TEST_AP_BSSIDS = new MacAddress[] {
+ MacAddress.fromString("22:33:44:55:66:77"),
+ MacAddress.fromString("aa:bb:cc:dd:ee:ff")};
+ private static final MacAddress[] TEST_AP_CLIENTS = new MacAddress[] {
+ MacAddress.fromString("22:33:44:aa:aa:77"),
+ MacAddress.fromString("aa:bb:cc:11:11:ff"),
+ MacAddress.fromString("22:bb:cc:11:aa:ff")};
@Mock Context mContext;
@Mock android.net.wifi.IWifiManager mWifiService;
@@ -165,6 +175,11 @@ public class WifiManagerTest {
private CoexCallback mCoexCallback;
private WifiActivityEnergyInfo mWifiActivityEnergyInfo;
+ private HashMap<String, SoftApInfo> mTestSoftApInfoMap = new HashMap<>();
+ private HashMap<String, List<WifiClient>> mTestWifiClientsMap = new HashMap<>();
+ private SoftApInfo mTestApInfo1 = new SoftApInfo();
+ private SoftApInfo mTestApInfo2 = new SoftApInfo();
+
/**
* Util function to check public field which used for softap in WifiConfiguration
* same as the value in SoftApConfiguration.
@@ -209,6 +224,31 @@ public class WifiManagerTest {
.build();
}
+ private void initTestInfoAndAddToTestMap(int numberOfInfos) {
+ if (numberOfInfos > 2) return;
+ for (int i = 0; i < numberOfInfos; i++) {
+ SoftApInfo info = mTestApInfo1;
+ if (i == 1) info = mTestApInfo2;
+ info.setFrequency(TEST_AP_FREQS[i]);
+ info.setBandwidth(TEST_AP_BWS[i]);
+ info.setBssid(TEST_AP_BSSIDS[i]);
+ info.setApInstanceIdentifier(TEST_AP_INSTANCES[i]);
+ mTestSoftApInfoMap.put(TEST_AP_INSTANCES[i], info);
+ }
+ }
+
+ private List<WifiClient> initWifiClientAndAddToTestMap(String targetInstance,
+ int numberOfClients, int startIdx) {
+ if (numberOfClients > 3) return null;
+ List<WifiClient> clients = new ArrayList<>();
+ for (int i = startIdx; i < startIdx + numberOfClients; i++) {
+ WifiClient client = new WifiClient(TEST_AP_CLIENTS[i], targetInstance);
+ clients.add(client);
+ }
+ mTestWifiClientsMap.put(targetInstance, clients);
+ return clients;
+ }
+
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
@@ -233,6 +273,8 @@ public class WifiManagerTest {
}
};
mWifiActivityEnergyInfo = new WifiActivityEnergyInfo(0, 0, 0, 0, 0, 0);
+ mTestSoftApInfoMap.clear();
+ mTestWifiClientsMap.clear();
}
/**
@@ -1087,11 +1129,149 @@ public class WifiManagerTest {
mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(),
anyInt());
-
- final List<WifiClient> testClients = new ArrayList();
- callbackCaptor.getValue().onConnectedClientsChanged(testClients);
+ List<WifiClient> clientList;
+ // Verify the register callback in disable state.
+ callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
+ (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
+ (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, true);
+ mLooper.dispatchAll();
+ verify(mSoftApCallback).onConnectedClientsChanged(new ArrayList<WifiClient>());
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
+ verify(mSoftApCallback).onInfoChanged(new SoftApInfo());
+ verify(mSoftApCallback).onInfoChanged(new ArrayList<SoftApInfo>());
+ // After verify, reset mSoftApCallback for nex test
+ reset(mSoftApCallback);
+
+ // Single AP mode Test
+ // Test info update
+ initTestInfoAndAddToTestMap(1);
+ callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
+ (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
+ (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
+ mLooper.dispatchAll();
+ verify(mSoftApCallback).onInfoChanged(mTestApInfo1);
+ verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
+ infos.contains(mTestApInfo1)));
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
+ // After verify, reset mSoftApCallback for nex test
+ reset(mSoftApCallback);
+
+ // Test first client connected
+ clientList = initWifiClientAndAddToTestMap(TEST_AP_INSTANCES[0], 1, 0);
+ callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
+ (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
+ (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
+ mLooper.dispatchAll();
+ // checked NO any infoChanged, includes InfoChanged(SoftApInfo)
+ // and InfoChanged(List<SoftApInfo>)
+ verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
+ verify(mSoftApCallback, never()).onInfoChanged(any(List.class));
+ verify(mSoftApCallback).onConnectedClientsChanged(mTestApInfo1, clientList);
+ verify(mSoftApCallback).onConnectedClientsChanged(clientList);
+ // After verify, reset mSoftApCallback for nex test
+ reset(mSoftApCallback);
+
+ // Test second client connected
+ mTestWifiClientsMap.clear();
+ clientList = initWifiClientAndAddToTestMap(TEST_AP_INSTANCES[0], 2, 0);
+ callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
+ (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
+ (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
+ mLooper.dispatchAll();
+ // checked NO any infoChanged, includes InfoChanged(SoftApInfo)
+ // and InfoChanged(List<SoftApInfo>)
+ verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
+ verify(mSoftApCallback, never()).onInfoChanged(any(List.class));
+ verify(mSoftApCallback).onConnectedClientsChanged(mTestApInfo1, clientList);
+ verify(mSoftApCallback).onConnectedClientsChanged(clientList);
+ // After verify, reset mSoftApCallback for nex test
+ reset(mSoftApCallback);
+
+ // Test second client disconnect
+ mTestWifiClientsMap.clear();
+ clientList = initWifiClientAndAddToTestMap(TEST_AP_INSTANCES[0], 1, 0);
+ callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
+ (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
+ (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
mLooper.dispatchAll();
- verify(mSoftApCallback).onConnectedClientsChanged(testClients);
+ // checked NO any infoChanged, includes InfoChanged(SoftApInfo)
+ // and InfoChanged(List<SoftApInfo>)
+ verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
+ verify(mSoftApCallback, never()).onInfoChanged(any(List.class));
+ verify(mSoftApCallback).onConnectedClientsChanged(mTestApInfo1, clientList);
+ verify(mSoftApCallback).onConnectedClientsChanged(clientList);
+ // After verify, reset mSoftApCallback for nex test
+ reset(mSoftApCallback);
+
+ // Test bridged mode case
+ mTestSoftApInfoMap.clear();
+ initTestInfoAndAddToTestMap(2);
+ callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
+ (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
+ (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), true, false);
+ mLooper.dispatchAll();
+ verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
+ verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
+ infos.contains(mTestApInfo1) && infos.contains(mTestApInfo2)
+ ));
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
+ // After verify, reset mSoftApCallback for nex test
+ reset(mSoftApCallback);
+
+ // Test client connect to second instance
+ List<WifiClient> clientListOnSecond =
+ initWifiClientAndAddToTestMap(TEST_AP_INSTANCES[1], 1, 2); // client3 to wlan2
+ List<WifiClient> totalList = new ArrayList<>();
+ totalList.addAll(clientList);
+ totalList.addAll(clientListOnSecond);
+ callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
+ (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
+ (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), true, false);
+ mLooper.dispatchAll();
+ // checked NO any infoChanged, includes InfoChanged(SoftApInfo)
+ // and InfoChanged(List<SoftApInfo>)
+ verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
+ verify(mSoftApCallback, never()).onInfoChanged(any(List.class));
+ verify(mSoftApCallback).onConnectedClientsChanged(mTestApInfo2, clientListOnSecond);
+ verify(mSoftApCallback).onConnectedClientsChanged(totalList);
+ // After verify, reset mSoftApCallback for nex test
+ reset(mSoftApCallback);
+
+ // Test shutdown on second instance
+ mTestSoftApInfoMap.clear();
+ mTestWifiClientsMap.clear();
+ initTestInfoAndAddToTestMap(1);
+ clientList = initWifiClientAndAddToTestMap(TEST_AP_INSTANCES[0], 1, 0);
+ callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
+ (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
+ (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), true, false);
+ mLooper.dispatchAll();
+ verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
+ verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
+ infos.contains(mTestApInfo1)));
+ // second instance have client connected before, thus it should send empty list
+ verify(mSoftApCallback).onConnectedClientsChanged(
+ mTestApInfo2, new ArrayList<WifiClient>());
+ verify(mSoftApCallback).onConnectedClientsChanged(clientList);
+ // After verify, reset mSoftApCallback for nex test
+ reset(mSoftApCallback);
+
+ // Test bridged mode disable when client connected
+ mTestSoftApInfoMap.clear();
+ mTestWifiClientsMap.clear();
+ callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
+ (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
+ (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), true, false);
+ mLooper.dispatchAll();
+ verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
+ verify(mSoftApCallback).onInfoChanged(new ArrayList<SoftApInfo>());
+ verify(mSoftApCallback).onConnectedClientsChanged(new ArrayList<WifiClient>());
+ verify(mSoftApCallback).onConnectedClientsChanged(
+ mTestApInfo1, new ArrayList<WifiClient>());
+ // After verify, reset mSoftApCallback for nex test
+ reset(mSoftApCallback);
}
@@ -1100,42 +1280,140 @@ public class WifiManagerTest {
*/
@Test
public void softApCallbackProxyCallsOnSoftApInfoChanged() throws Exception {
- SoftApInfo testSoftApInfo = new SoftApInfo();
- testSoftApInfo.setFrequency(TEST_AP_FREQUENCY);
- testSoftApInfo.setBandwidth(TEST_AP_BANDWIDTH);
ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(),
anyInt());
-
- callbackCaptor.getValue().onInfoChanged(testSoftApInfo);
+ // Verify the register callback in disable state.
+ callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
+ (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
+ (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, true);
+ mLooper.dispatchAll();
+ verify(mSoftApCallback).onConnectedClientsChanged(new ArrayList<WifiClient>());
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
+ verify(mSoftApCallback).onInfoChanged(new SoftApInfo());
+ verify(mSoftApCallback).onInfoChanged(new ArrayList<SoftApInfo>());
+ // After verify, reset mSoftApCallback for nex test
+ reset(mSoftApCallback);
+
+ // Single AP mode Test
+ // Test info update
+ initTestInfoAndAddToTestMap(1);
+ callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
+ (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
+ (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
mLooper.dispatchAll();
- verify(mSoftApCallback).onInfoChanged(testSoftApInfo);
+ verify(mSoftApCallback).onInfoChanged(mTestApInfo1);
+ verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
+ infos.contains(mTestApInfo1)));
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
+ // After verify, reset mSoftApCallback for nex test
+ reset(mSoftApCallback);
+
+ // Test info changed
+ SoftApInfo changedInfo = new SoftApInfo(mTestSoftApInfoMap.get(TEST_AP_INSTANCES[0]));
+ changedInfo.setFrequency(2422);
+ mTestSoftApInfoMap.put(TEST_AP_INSTANCES[0], changedInfo);
+ callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
+ (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
+ (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
+ mLooper.dispatchAll();
+ verify(mSoftApCallback).onInfoChanged(changedInfo);
+ verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
+ infos.contains(changedInfo)));
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
+
+ // Test Stop, all of infos is empty
+ mTestSoftApInfoMap.clear();
+ callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
+ (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
+ (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
+ mLooper.dispatchAll();
+ verify(mSoftApCallback).onInfoChanged(new SoftApInfo());
+ verify(mSoftApCallback).onInfoChanged(new ArrayList<SoftApInfo>());
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
+ // After verify, reset mSoftApCallback for nex test
+ reset(mSoftApCallback);
}
/*
* Verify client-provided callback is being called through callback proxy
*/
@Test
- public void softApCallbackProxyCallsOnSoftApInfoListChanged() throws Exception {
- SoftApInfo testSoftApInfo = new SoftApInfo();
- testSoftApInfo.setFrequency(TEST_AP_FREQUENCY);
- testSoftApInfo.setBandwidth(TEST_AP_BANDWIDTH);
- List<SoftApInfo> infoList = new ArrayList<>();
- infoList.add(testSoftApInfo);
+ public void softApCallbackProxyCallsOnSoftApInfoChangedInBridgedMode() throws Exception {
ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(),
anyInt());
- callbackCaptor.getValue().onInfoListChanged(infoList);
+ // Test bridged mode case
+ initTestInfoAndAddToTestMap(2);
+ callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
+ (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
+ (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), true, false);
+ mLooper.dispatchAll();
+ verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
+ verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
+ infos.contains(mTestApInfo1) && infos.contains(mTestApInfo2)
+ ));
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
+ // After verify, reset mSoftApCallback for nex test
+ reset(mSoftApCallback);
+
+ // Test bridged mode case but an info changed
+ SoftApInfo changedInfoBridgedMode = new SoftApInfo(mTestSoftApInfoMap.get(
+ TEST_AP_INSTANCES[0]));
+ changedInfoBridgedMode.setFrequency(2422);
+ mTestSoftApInfoMap.put(TEST_AP_INSTANCES[0], changedInfoBridgedMode);
+ callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
+ (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
+ (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), true, false);
mLooper.dispatchAll();
- verify(mSoftApCallback).onInfoListChanged(infoList);
+ verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
+ verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
+ infos.contains(changedInfoBridgedMode) && infos.contains(mTestApInfo2)
+ ));
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
+ // After verify, reset mSoftApCallback for nex test
+ reset(mSoftApCallback);
+
+ // Test bridged mode case but an instance shutdown
+ mTestSoftApInfoMap.clear();
+ initTestInfoAndAddToTestMap(1);
+ callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
+ (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
+ (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), true, false);
+ mLooper.dispatchAll();
+ verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
+ verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
+ infos.contains(mTestApInfo1)
+ ));
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
+ // After verify, reset mSoftApCallback for nex test
+ reset(mSoftApCallback);
+
+ // Test bridged mode disable case
+ mTestSoftApInfoMap.clear();
+ callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
+ (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
+ (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), true, false);
+ mLooper.dispatchAll();
+ verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
+ verify(mSoftApCallback).onInfoChanged(new ArrayList<SoftApInfo>());
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
+ // After verify, reset mSoftApCallback for nex test
+ reset(mSoftApCallback);
}
-
/*
* Verify client-provided callback is being called through callback proxy
*/
@@ -1160,7 +1438,7 @@ public class WifiManagerTest {
@Test
public void softApCallbackProxyCallsOnBlockedClientConnecting() throws Exception {
WifiClient testWifiClient = new WifiClient(MacAddress.fromString("22:33:44:55:66:77"),
- TEST_AP_INSTANCE);
+ TEST_AP_INSTANCES[0]);
ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
@@ -1179,11 +1457,6 @@ public class WifiManagerTest {
*/
@Test
public void softApCallbackProxyCallsOnMultipleUpdates() throws Exception {
- SoftApInfo testSoftApInfo = new SoftApInfo();
- testSoftApInfo.setFrequency(TEST_AP_FREQUENCY);
- testSoftApInfo.setBandwidth(TEST_AP_BANDWIDTH);
- List<SoftApInfo> infoList = new ArrayList<>();
- infoList.add(testSoftApInfo);
SoftApCapability testSoftApCapability = new SoftApCapability(0);
testSoftApCapability.setMaxSupportedClients(10);
ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
@@ -1194,18 +1467,12 @@ public class WifiManagerTest {
final List<WifiClient> testClients = new ArrayList();
callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_ENABLING, 0);
- callbackCaptor.getValue().onConnectedClientsChanged(testClients);
- callbackCaptor.getValue().onInfoChanged(testSoftApInfo);
- callbackCaptor.getValue().onInfoListChanged(infoList);
callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL);
callbackCaptor.getValue().onCapabilityChanged(testSoftApCapability);
mLooper.dispatchAll();
verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_ENABLING, 0);
- verify(mSoftApCallback).onConnectedClientsChanged(testClients);
- verify(mSoftApCallback).onInfoChanged(testSoftApInfo);
- verify(mSoftApCallback).onInfoListChanged(infoList);
verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL);
verify(mSoftApCallback).onCapabilityChanged(testSoftApCapability);
}