diff options
3 files changed, 200 insertions, 19 deletions
diff --git a/service/java/com/android/server/wifi/WifiNetworkFactory.java b/service/java/com/android/server/wifi/WifiNetworkFactory.java index 1c1d5e57c..aaf2b2e6b 100644 --- a/service/java/com/android/server/wifi/WifiNetworkFactory.java +++ b/service/java/com/android/server/wifi/WifiNetworkFactory.java @@ -93,6 +93,7 @@ public class WifiNetworkFactory extends NetworkFactory { // Verbose logging flag. private boolean mVerboseLoggingEnabled = false; private boolean mPeriodicScanTimerSet = false; + private boolean mConnectionTimeoutSet = false; private boolean mIsConnectedToUserSelectedNetwork = false; // Scan listener for scan requests. @@ -365,6 +366,8 @@ public class WifiNetworkFactory extends NetworkFactory { return; } retrieveWifiScanner(); + // Reset state from any previous request. + resetStateForActiveRequestStart(); // Store the active network request. mActiveSpecificNetworkRequest = new NetworkRequest(networkRequest); @@ -408,11 +411,7 @@ public class WifiNetworkFactory extends NetworkFactory { 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(); + resetStateForActiveRequestEnd(); } } @@ -470,14 +469,12 @@ public class WifiNetworkFactory extends NetworkFactory { mUserSelectedNetwork = network; // Post an alarm to handle connection timeout. - mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, - mClock.getElapsedSinceBootMillis() + NETWORK_CONNECTION_TIMEOUT_MS, - TAG, mConnectionTimeoutAlarmListener, mHandler); + scheduleConnectionTimeout(); } private void handleRejectUserSelection() { Log.w(TAG, "User dismissed notification"); - resetState(); + resetStateForActiveRequestEnd(); } private boolean isUserSelectedNetwork(WifiConfiguration config) { @@ -522,7 +519,7 @@ public class WifiNetworkFactory extends NetworkFactory { } } // Cancel connection timeout alarm. - mAlarmManager.cancel(mConnectionTimeoutAlarmListener); + cancelConnectionTimeout(); // Set the connection status. mIsConnectedToUserSelectedNetwork = true; } @@ -545,25 +542,39 @@ public class WifiNetworkFactory extends NetworkFactory { + callback, e); } } - // Cancel any connection timeout alarm. - mAlarmManager.cancel(mConnectionTimeoutAlarmListener); - resetState(); + resetStateForActiveRequestEnd(); } private void resetState() { + if (mIsConnectedToUserSelectedNetwork) { + Log.i(TAG, "Disconnecting from network on reset"); + mWifiInjector.getClientModeImpl().disconnectCommand(); + } // Reset the active network request. mActiveSpecificNetworkRequest = null; mActiveSpecificNetworkRequestSpecifier = null; mUserSelectedNetwork = null; mIsConnectedToUserSelectedNetwork = false; cancelPeriodicScans(); - // Re-enable Auto-join. - mWifiConnectivityManager.setSpecificNetworkRequestInProgress(false); + cancelConnectionTimeout(); + // Remove any callbacks registered for the request. + mRegisteredCallbacks.clear(); // TODO(b/113878056): Force-release the network request to let the app know early that the // attempt failed. // TODO(b/113878056): End UI flow here. } + // Invoked at the termination of previous active request processing. + private void resetStateForActiveRequestEnd() { + resetState(); + mWifiConnectivityManager.setSpecificNetworkRequestInProgress(false); + } + + // Invoked at the start of new active request processing. + private void resetStateForActiveRequestStart() { + resetState(); + } + /** * Check if the request comes from foreground app/service. */ @@ -707,5 +718,19 @@ public class WifiNetworkFactory extends NetworkFactory { } } } + + private void cancelConnectionTimeout() { + if (mConnectionTimeoutSet) { + mAlarmManager.cancel(mConnectionTimeoutAlarmListener); + mConnectionTimeoutSet = false; + } + } + + private void scheduleConnectionTimeout() { + mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, + mClock.getElapsedSinceBootMillis() + NETWORK_CONNECTION_TIMEOUT_MS, + TAG, mConnectionTimeoutAlarmListener, mHandler); + mConnectionTimeoutSet = true; + } } diff --git a/service/java/com/android/server/wifi/util/ExternalCallbackTracker.java b/service/java/com/android/server/wifi/util/ExternalCallbackTracker.java index 4bb846985..8f92da431 100644 --- a/service/java/com/android/server/wifi/util/ExternalCallbackTracker.java +++ b/service/java/com/android/server/wifi/util/ExternalCallbackTracker.java @@ -174,4 +174,14 @@ public class ExternalCallbackTracker<T> { public int getNumCallbacks() { return mCallbacks.size(); } + + /** + * Remove all callbacks registered. + */ + public void clear() { + for (ExternalCallbackHolder<T> externalCallback : mCallbacks.values()) { + externalCallback.reset(); + } + mCallbacks.clear(); + } } diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java index 6ef48557d..dfc31d9b2 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java @@ -110,6 +110,8 @@ public class WifiNetworkFactoryTest { ArgumentCaptor.forClass(WorkSource.class); ArgumentCaptor<INetworkRequestUserSelectionCallback> mNetworkRequestUserSelectionCallback = ArgumentCaptor.forClass(INetworkRequestUserSelectionCallback.class); + ArgumentCaptor<OnAlarmListener> mPeriodicScanListenerArgumentCaptor = + ArgumentCaptor.forClass(OnAlarmListener.class); ArgumentCaptor<OnAlarmListener> mConnectionTimeoutAlarmListenerArgumentCaptor = ArgumentCaptor.forClass(OnAlarmListener.class); @@ -1057,6 +1059,149 @@ public class WifiNetworkFactoryTest { mWifiNetworkFactory.getActiveSpecificNetworkRequestUid(connectedNetwork)); } + /** + * Verify handling for new network request while processing another one. + */ + @Test + public void testHandleNetworkRequestWithSpecifierWhenScanning() throws Exception { + WifiNetworkSpecifier specifier1 = createWifiNetworkSpecifier(TEST_UID_1, false); + mNetworkRequest.networkCapabilities.setNetworkSpecifier(specifier1); + mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); + + // Send second request. + WifiNetworkSpecifier specifier2 = createWifiNetworkSpecifier(TEST_UID_2, false); + mNetworkRequest.networkCapabilities.setNetworkSpecifier(specifier2); + mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); + + verify(mWifiConnectivityManager, times(2)).setSpecificNetworkRequestInProgress(true); + verify(mWifiScanner, times(2)).startScan(any(), any(), any()); + + // Remove the stale request1 & ensure nothing happens. + mNetworkRequest.networkCapabilities.setNetworkSpecifier(specifier1); + mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); + + verifyNoMoreInteractions(mWifiConnectivityManager, mWifiScanner, mClientModeImpl, + mAlarmManager); + + // Remove the active request2 & ensure auto-join is re-enabled. + mNetworkRequest.networkCapabilities.setNetworkSpecifier(specifier2); + mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); + + verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false); + } + + /** + * Verify handling for new network request while processing another one. + */ + @Test + public void testHandleNetworkRequestWithSpecifierAfterMatch() throws Exception { + sendNetworkRequestAndSetupForUserSelection(); + WifiNetworkSpecifier specifier1 = + (WifiNetworkSpecifier) mNetworkRequest.networkCapabilities.getNetworkSpecifier(); + + INetworkRequestUserSelectionCallback networkRequestUserSelectionCallback = + mNetworkRequestUserSelectionCallback.getValue(); + assertNotNull(networkRequestUserSelectionCallback); + + // Send second request. + WifiNetworkSpecifier specifier2 = createWifiNetworkSpecifier(TEST_UID_2, false); + mNetworkRequest.networkCapabilities.setNetworkSpecifier(specifier2); + mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); + + // Ignore stale callbacks. + WifiConfiguration selectedNetwork = WifiConfigurationTestUtil.createOpenNetwork(); + networkRequestUserSelectionCallback.select(selectedNetwork); + mLooper.dispatchAll(); + + verify(mWifiConnectivityManager, times(2)).setSpecificNetworkRequestInProgress(true); + verify(mWifiScanner, times(2)).startScan(any(), any(), any()); + verify(mAlarmManager).cancel(mPeriodicScanListenerArgumentCaptor.getValue()); + + // Remove the stale request1 & ensure nothing happens. + mNetworkRequest.networkCapabilities.setNetworkSpecifier(specifier1); + mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); + + verifyNoMoreInteractions(mWifiConnectivityManager, mWifiScanner, mClientModeImpl, + mAlarmManager); + + // Remove the active request2 & ensure auto-join is re-enabled. + mNetworkRequest.networkCapabilities.setNetworkSpecifier(specifier2); + mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); + + verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false); + } + + /** + * Verify handling for new network request while processing another one. + */ + @Test + public void testHandleNetworkRequestWithSpecifierAfterConnect() throws Exception { + sendNetworkRequestAndSetupForConnectionStatus(); + WifiNetworkSpecifier specifier1 = + (WifiNetworkSpecifier) mNetworkRequest.networkCapabilities.getNetworkSpecifier(); + + // Send second request. + WifiNetworkSpecifier specifier2 = createWifiNetworkSpecifier(TEST_UID_2, false); + mNetworkRequest.networkCapabilities.setNetworkSpecifier(specifier2); + mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); + + verify(mWifiConnectivityManager, times(2)).setSpecificNetworkRequestInProgress(true); + verify(mWifiScanner, times(2)).startScan(any(), any(), any()); + verify(mAlarmManager).cancel(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue()); + + // Remove the stale request1 & ensure nothing happens. + mNetworkRequest.networkCapabilities.setNetworkSpecifier(specifier1); + mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); + + verifyNoMoreInteractions(mWifiConnectivityManager, mWifiScanner, mClientModeImpl, + mAlarmManager); + + // Remove the active request2 & ensure auto-join is re-enabled. + mNetworkRequest.networkCapabilities.setNetworkSpecifier(specifier2); + mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); + + verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false); + } + + /** + * Verify handling for new network request while processing another one. + */ + @Test + public void testHandleNetworkRequestWithSpecifierAfterConnectionSuccess() throws Exception { + sendNetworkRequestAndSetupForConnectionStatus(); + WifiNetworkSpecifier specifier1 = + (WifiNetworkSpecifier) mNetworkRequest.networkCapabilities.getNetworkSpecifier(); + + // Send network connection success indication. + assertNotNull(mSelectedNetwork); + mWifiNetworkFactory.handleConnectionAttemptEnded( + WifiMetrics.ConnectionEvent.FAILURE_NONE, mSelectedNetwork); + + // Cancel the connection timeout. + verify(mAlarmManager).cancel(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue()); + + // Send second request. + WifiNetworkSpecifier specifier2 = createWifiNetworkSpecifier(TEST_UID_2, false); + mNetworkRequest.networkCapabilities.setNetworkSpecifier(specifier2); + mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); + + verify(mWifiConnectivityManager, times(2)).setSpecificNetworkRequestInProgress(true); + verify(mWifiScanner, times(2)).startScan(any(), any(), any()); + verify(mClientModeImpl).disconnectCommand(); + + // Remove the stale request1 & ensure nothing happens. + mNetworkRequest.networkCapabilities.setNetworkSpecifier(specifier1); + mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); + + verifyNoMoreInteractions(mWifiConnectivityManager, mWifiScanner, mClientModeImpl, + mAlarmManager); + + // Remove the active request2 & ensure auto-join is re-enabled. + mNetworkRequest.networkCapabilities.setNetworkSpecifier(specifier2); + mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); + + verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false); + } // Helper method to setup the necessary pre-requisite steps for tracking connection status. private Messenger sendNetworkRequestAndSetupForConnectionStatus() throws RemoteException { @@ -1073,6 +1218,9 @@ public class WifiNetworkFactoryTest { networkRequestUserSelectionCallback.select(mSelectedNetwork); mLooper.dispatchAll(); + // Cancel the periodic scan timer. + verify(mAlarmManager).cancel(mPeriodicScanListenerArgumentCaptor.getValue()); + ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); verify(mClientModeImpl).sendMessage(messageCaptor.capture()); @@ -1126,8 +1274,6 @@ public class WifiNetworkFactoryTest { private void verifyPeriodicScans(long...expectedIntervalsInSeconds) { when(mClock.getElapsedSinceBootMillis()).thenReturn(0L); - ArgumentCaptor<OnAlarmListener> alarmListenerArgumentCaptor = - ArgumentCaptor.forClass(OnAlarmListener.class); OnAlarmListener alarmListener = null; ArgumentCaptor<ScanListener> scanListenerArgumentCaptor = ArgumentCaptor.forClass(ScanListener.class); @@ -1154,8 +1300,8 @@ public class WifiNetworkFactoryTest { inOrder.verify(mAlarmManager).set(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), eq(expectedNextIntervalInMs), any(), - alarmListenerArgumentCaptor.capture(), any()); - alarmListener = alarmListenerArgumentCaptor.getValue(); + mPeriodicScanListenerArgumentCaptor.capture(), any()); + alarmListener = mPeriodicScanListenerArgumentCaptor.getValue(); assertNotNull(alarmListener); } |