summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--service/java/com/android/server/wifi/WifiNetworkFactory.java69
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java197
2 files changed, 258 insertions, 8 deletions
diff --git a/service/java/com/android/server/wifi/WifiNetworkFactory.java b/service/java/com/android/server/wifi/WifiNetworkFactory.java
index a14459382..98766dc41 100644
--- a/service/java/com/android/server/wifi/WifiNetworkFactory.java
+++ b/service/java/com/android/server/wifi/WifiNetworkFactory.java
@@ -19,6 +19,7 @@ package com.android.server.wifi;
import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.server.wifi.util.NativeUtil.addEnclosingQuotes;
+import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.AlarmManager;
import android.content.Context;
@@ -41,6 +42,7 @@ import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.os.WorkSource;
+import android.text.TextUtils;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
@@ -51,6 +53,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
/**
@@ -89,6 +92,7 @@ public class WifiNetworkFactory extends NetworkFactory {
// Verbose logging flag.
private boolean mVerboseLoggingEnabled = false;
private boolean mPeriodicScanTimerSet = false;
+ private boolean mIsConnectedToUserSelectedNetwork = false;
// Scan listener for scan requests.
private class NetworkFactoryScanListener implements WifiScanner.ScanListener {
@@ -155,7 +159,7 @@ public class WifiNetworkFactory extends NetworkFactory {
@Override
public void onAlarm() {
Log.e(TAG, "Timed-out connecting to network");
- handleNetworkConnectionFailure();
+ handleNetworkConnectionFailure(mUserSelectedNetwork);
}
}
@@ -201,7 +205,7 @@ public class WifiNetworkFactory extends NetworkFactory {
break;
case WifiManager.CONNECT_NETWORK_FAILED:
Log.e(TAG, "Failed to trigger network connection");
- handleNetworkConnectionFailure();
+ handleNetworkConnectionFailure(mUserSelectedNetwork);
break;
default:
Log.e(TAG, "Unknown message " + msg.what);
@@ -395,10 +399,18 @@ public class WifiNetworkFactory extends NetworkFactory {
Log.e(TAG, "Invalid network specifier mentioned. Ingoring");
return;
}
+ if (mActiveSpecificNetworkRequest == null) {
+ Log.e(TAG, "Network release received with no active request. Ignoring");
+ return;
+ }
if (!mActiveSpecificNetworkRequest.equals(networkRequest)) {
Log.e(TAG, "Network specifier does not match the active request. Ignoring");
return;
}
+ if (mIsConnectedToUserSelectedNetwork) {
+ Log.i(TAG, "Disconnecting from network on request release");
+ mWifiInjector.getClientModeImpl().disconnectCommand();
+ }
resetState();
}
}
@@ -449,18 +461,62 @@ public class WifiNetworkFactory extends NetworkFactory {
resetState();
}
+ private boolean isUserSelectedNetwork(WifiConfiguration config) {
+ if (!TextUtils.equals(mUserSelectedNetwork.SSID, config.SSID)) {
+ return false;
+ }
+ if (!Objects.equals(
+ mUserSelectedNetwork.allowedKeyManagement, config.allowedKeyManagement)) {
+ return false;
+ }
+ return true;
+ }
+
/**
* Invoked by {@link ClientModeImpl} on successful connection to a network.
*/
- public void handleNetworkConnectionSuccess(WifiConfiguration network) {
- // TODO(b/113878056): Handle network connection
+ public void handleNetworkConnectionSuccess(@NonNull WifiConfiguration connectedNetwork) {
+ if (mUserSelectedNetwork == null || connectedNetwork == null) return;
+ if (!isUserSelectedNetwork(connectedNetwork)) {
+ Log.w(TAG, "Connected to unknown network " + connectedNetwork + ". Ignoring...");
+ return;
+ }
+ Log.d(TAG, "Connected to network " + mUserSelectedNetwork);
+ for (INetworkRequestMatchCallback callback : mRegisteredCallbacks.getCallbacks()) {
+ try {
+ callback.onUserSelectionConnectSuccess(mUserSelectedNetwork);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to invoke network request connect failure callback "
+ + callback, e);
+ }
+ }
+ // Cancel connection timeout alarm.
+ mAlarmManager.cancel(mConnectionTimeoutAlarmListener);
+ // Set the connection status.
+ mIsConnectedToUserSelectedNetwork = true;
}
/**
* Invoked by {@link ClientModeImpl} on failure to connect to a network.
*/
- public void handleNetworkConnectionFailure() {
- // TODO(b/113878056): Handle connection failure.
+ public void handleNetworkConnectionFailure(@NonNull WifiConfiguration failedNetwork) {
+ if (mUserSelectedNetwork == null || failedNetwork == null) return;
+ if (!isUserSelectedNetwork(failedNetwork)) {
+ Log.w(TAG, "Connection failed to unknown network " + failedNetwork + ". Ignoring...");
+ return;
+ }
+ Log.e(TAG, "Failed to Connect to network " + mUserSelectedNetwork);
+ for (INetworkRequestMatchCallback callback : mRegisteredCallbacks.getCallbacks()) {
+ try {
+ callback.onUserSelectionConnectFailure(mUserSelectedNetwork);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to invoke network request connect failure callback "
+ + callback, e);
+ }
+ }
+ // Cancel any connection timeout alarm.
+ mAlarmManager.cancel(mConnectionTimeoutAlarmListener);
+ resetState();
}
private void resetState() {
@@ -468,6 +524,7 @@ public class WifiNetworkFactory extends NetworkFactory {
mActiveSpecificNetworkRequest = null;
mActiveSpecificNetworkRequestSpecifier = null;
mUserSelectedNetwork = null;
+ mIsConnectedToUserSelectedNetwork = false;
cancelPeriodicScans();
// Re-enable Auto-join.
mWifiConnectivityManager.setSpecificNetworkRequestInProgress(false);
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java
index d279bde52..c72da94b1 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java
@@ -45,6 +45,7 @@ import android.net.wifi.WifiScanner.ScanListener;
import android.net.wifi.WifiScanner.ScanSettings;
import android.os.IBinder;
import android.os.Message;
+import android.os.Messenger;
import android.os.PatternMatcher;
import android.os.RemoteException;
import android.os.WorkSource;
@@ -101,12 +102,15 @@ public class WifiNetworkFactoryTest {
TestLooper mLooper;
NetworkRequest mNetworkRequest;
WifiScanner.ScanData[] mTestScanDatas;
+ WifiConfiguration mSelectedNetwork;
ArgumentCaptor<ScanSettings> mScanSettingsArgumentCaptor =
ArgumentCaptor.forClass(ScanSettings.class);
ArgumentCaptor<WorkSource> mWorkSourceArgumentCaptor =
ArgumentCaptor.forClass(WorkSource.class);
ArgumentCaptor<INetworkRequestUserSelectionCallback> mNetworkRequestUserSelectionCallback =
ArgumentCaptor.forClass(INetworkRequestUserSelectionCallback.class);
+ ArgumentCaptor<OnAlarmListener> mConnectionTimeoutAlarmListenerArgumentCaptor =
+ ArgumentCaptor.forClass(OnAlarmListener.class);
private WifiNetworkFactory mWifiNetworkFactory;
@@ -419,6 +423,8 @@ public class WifiNetworkFactoryTest {
// Release the network request.
mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest);
+ // Verify that we did not trigger a disconnect because we've not yet connected.
+ verify(mClientModeImpl, never()).disconnectCommand();
// Re-enable connectivity manager .
verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false);
}
@@ -861,6 +867,195 @@ public class WifiNetworkFactoryTest {
verifyNoMoreInteractions(mClientModeImpl);
}
+ /**
+ * Verify handling of connection timeout.
+ */
+ @Test
+ public void testNetworkSpecifierHandleConnectionTimeout() throws Exception {
+ sendNetworkRequestAndSetupForConnectionStatus();
+
+ // Simulate connection timeout.
+ mConnectionTimeoutAlarmListenerArgumentCaptor.getValue().onAlarm();
+
+ // Verify that we sent the connection failure callback.
+ verify(mNetworkRequestMatchCallback).onUserSelectionConnectFailure(mSelectedNetwork);
+ // Verify we reset the network request handling.
+ verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false);
+ }
+
+ /**
+ * Verify handling of connection trigger failure.
+ */
+ @Test
+ public void testNetworkSpecifierHandleConnectionTriggerFailure() throws Exception {
+ Messenger replyToMsgr = sendNetworkRequestAndSetupForConnectionStatus();
+
+ // Send failure message.
+ Message failureMsg = Message.obtain();
+ failureMsg.what = WifiManager.CONNECT_NETWORK_FAILED;
+ replyToMsgr.send(failureMsg);
+ mLooper.dispatchAll();
+
+ // Verify that we sent the connection failure callback.
+ verify(mNetworkRequestMatchCallback).onUserSelectionConnectFailure(mSelectedNetwork);
+ // verify we canceled the timeout alarm.
+ verify(mAlarmManager).cancel(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue());
+ // Verify we reset the network request handling.
+ verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false);
+ }
+
+ /**
+ * Verify handling of connection failure.
+ */
+ @Test
+ public void testNetworkSpecifierHandleConnectionFailure() throws Exception {
+ sendNetworkRequestAndSetupForConnectionStatus();
+
+ // Send network connection failure indication.
+ assertNotNull(mSelectedNetwork);
+ mWifiNetworkFactory.handleNetworkConnectionFailure(mSelectedNetwork);
+
+ // Verify that we sent the connection failure callback.
+ verify(mNetworkRequestMatchCallback).onUserSelectionConnectFailure(mSelectedNetwork);
+ // verify we canceled the timeout alarm.
+ verify(mAlarmManager).cancel(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue());
+ // Verify we reset the network request handling.
+ verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false);
+ }
+
+ /**
+ * Verify handling of connection failure to a different network.
+ */
+ @Test
+ public void testNetworkSpecifierHandleConnectionFailureToWrongNetwork() throws Exception {
+ sendNetworkRequestAndSetupForConnectionStatus();
+
+ // Send network connection failure to a different network indication.
+ assertNotNull(mSelectedNetwork);
+ WifiConfiguration connectedNetwork = new WifiConfiguration(mSelectedNetwork);
+ connectedNetwork.SSID += "test";
+ mWifiNetworkFactory.handleNetworkConnectionFailure(connectedNetwork);
+
+ // Verify that we sent the connection failure callback.
+ verify(mNetworkRequestMatchCallback, never())
+ .onUserSelectionConnectFailure(mSelectedNetwork);
+ // verify we canceled the timeout alarm.
+ verify(mAlarmManager, never())
+ .cancel(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue());
+ // Verify we reset the network request handling.
+ verify(mWifiConnectivityManager, never())
+ .setSpecificNetworkRequestInProgress(false);
+
+ // Send network connection success to the correct network indication.
+ mWifiNetworkFactory.handleNetworkConnectionFailure(mSelectedNetwork);
+
+ // Verify that we sent the connection failure callback.
+ verify(mNetworkRequestMatchCallback).onUserSelectionConnectFailure(mSelectedNetwork);
+ // verify we canceled the timeout alarm.
+ verify(mAlarmManager).cancel(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue());
+ // Verify we reset the network request handling.
+ verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false);
+ }
+
+ /**
+ * Verify handling of connection success.
+ */
+ @Test
+ public void testNetworkSpecifierHandleConnectionSuccess() throws Exception {
+ sendNetworkRequestAndSetupForConnectionStatus();
+
+ // Send network connection success indication.
+ assertNotNull(mSelectedNetwork);
+ mWifiNetworkFactory.handleNetworkConnectionSuccess(mSelectedNetwork);
+
+ // Verify that we sent the connection success callback.
+ verify(mNetworkRequestMatchCallback).onUserSelectionConnectSuccess(mSelectedNetwork);
+ // verify we canceled the timeout alarm.
+ verify(mAlarmManager).cancel(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue());
+ }
+
+ /**
+ * Verify handling of connection success to a different network.
+ */
+ @Test
+ public void testNetworkSpecifierHandleConnectionSuccessToWrongNetwork() throws Exception {
+ sendNetworkRequestAndSetupForConnectionStatus();
+
+ // Send network connection success to a different network indication.
+ assertNotNull(mSelectedNetwork);
+ WifiConfiguration connectedNetwork = new WifiConfiguration(mSelectedNetwork);
+ connectedNetwork.SSID += "test";
+ mWifiNetworkFactory.handleNetworkConnectionSuccess(connectedNetwork);
+
+ // verify that we did not send out the success callback and did not stop the alarm timeout.
+ verify(mNetworkRequestMatchCallback, never())
+ .onUserSelectionConnectSuccess(mSelectedNetwork);
+ verify(mAlarmManager, never())
+ .cancel(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue());
+
+ // Send network connection success to the correct network indication.
+ mWifiNetworkFactory.handleNetworkConnectionSuccess(mSelectedNetwork);
+
+ // Verify that we sent the connection success callback.
+ verify(mNetworkRequestMatchCallback).onUserSelectionConnectSuccess(mSelectedNetwork);
+ // verify we canceled the timeout alarm.
+ verify(mAlarmManager).cancel(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue());
+ }
+
+ /**
+ * Verify handling of request release after connecting to the network.
+ */
+ @Test
+ public void testHandleNetworkReleaseWithSpecifierAfterConnectionSuccess() throws Exception {
+ sendNetworkRequestAndSetupForConnectionStatus();
+
+ // Send network connection success indication.
+ assertNotNull(mSelectedNetwork);
+ mWifiNetworkFactory.handleNetworkConnectionSuccess(mSelectedNetwork);
+
+ // Verify that we sent the connection success callback.
+ verify(mNetworkRequestMatchCallback).onUserSelectionConnectSuccess(mSelectedNetwork);
+ // verify we canceled the timeout alarm.
+ verify(mAlarmManager).cancel(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue());
+
+ // Now release the network request.
+ mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest);
+ // Verify that we triggered a disconnect.
+ verify(mClientModeImpl).disconnectCommand();
+ // Re-enable connectivity manager .
+ verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false);
+ }
+
+ // Helper method to setup the necessary pre-requisite steps for tracking connection status.
+ private Messenger sendNetworkRequestAndSetupForConnectionStatus() throws RemoteException {
+ when(mClock.getElapsedSinceBootMillis()).thenReturn(0L);
+
+ sendNetworkRequestAndSetupForUserSelection();
+
+ INetworkRequestUserSelectionCallback networkRequestUserSelectionCallback =
+ mNetworkRequestUserSelectionCallback.getValue();
+ assertNotNull(networkRequestUserSelectionCallback);
+
+ // Now trigger user selection to one of the network.
+ mSelectedNetwork = WifiConfigurationTestUtil.createOpenNetwork();
+ networkRequestUserSelectionCallback.select(mSelectedNetwork);
+ mLooper.dispatchAll();
+
+ ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
+ verify(mClientModeImpl).sendMessage(messageCaptor.capture());
+
+ Message message = messageCaptor.getValue();
+ assertNotNull(message);
+
+ // Start the connection timeout alarm.
+ verify(mAlarmManager).set(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
+ eq((long) WifiNetworkFactory.NETWORK_CONNECTION_TIMEOUT_MS), any(),
+ mConnectionTimeoutAlarmListenerArgumentCaptor.capture(), any());
+ assertNotNull(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue());
+
+ return message.replyTo;
+ }
+
// Helper method to setup the necessary pre-requisite steps for user selection.
private void sendNetworkRequestAndSetupForUserSelection() throws RemoteException {
// Setup scan data for open networks.
@@ -888,8 +1083,6 @@ public class WifiNetworkFactoryTest {
verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(true);
verifyPeriodicScans(0, PERIODIC_SCAN_INTERVAL_MS);
- ArgumentCaptor<List<ScanResult>> matchedScanResultsCaptor =
- ArgumentCaptor.forClass(List.class);
verify(mNetworkRequestMatchCallback).onMatch(anyList());
}