diff options
author | Roshan Pius <rpius@google.com> | 2018-11-12 10:43:57 -0800 |
---|---|---|
committer | Roshan Pius <rpius@google.com> | 2018-11-16 16:30:41 -0800 |
commit | 016725de18209f64f887991e0cc84e75c99548df (patch) | |
tree | f4d1d02c0214337e56c0a6fb5b3290611463a655 | |
parent | f24f80b50bda56535985566202b149ad39f9a8cc (diff) | |
download | android_frameworks_opt_net_wifi-016725de18209f64f887991e0cc84e75c99548df.tar.gz android_frameworks_opt_net_wifi-016725de18209f64f887991e0cc84e75c99548df.tar.bz2 android_frameworks_opt_net_wifi-016725de18209f64f887991e0cc84e75c99548df.zip |
WifiNetworkFactory: Handle network connection/failure
Handle network connection status from ClientModeImpl after user picks a
network.
Also, disconnect from the user selected network on network release.
Bug: 113878056
Test: ./frameworks/opt/net/wifi/tests/wifitests/runtests.sh
Change-Id: I0eddb69364733e03004c1fdcd6948ec920a07a7e
-rw-r--r-- | service/java/com/android/server/wifi/WifiNetworkFactory.java | 69 | ||||
-rw-r--r-- | tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java | 197 |
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()); } |