diff options
author | Roshan Pius <rpius@google.com> | 2019-03-07 10:14:51 -0800 |
---|---|---|
committer | Roshan Pius <rpius@google.com> | 2019-03-14 07:47:44 -0700 |
commit | 0cd22728c628e51e8f259f8404a97dec49804424 (patch) | |
tree | 50d7abd4a1f2e2288f022d0f09e29b0783fbe855 | |
parent | d03677ad20ec1d521f11461160dcb56fa8b3bfff (diff) | |
download | android_frameworks_opt_net_wifi-0cd22728c628e51e8f259f8404a97dec49804424.tar.gz android_frameworks_opt_net_wifi-0cd22728c628e51e8f259f8404a97dec49804424.tar.bz2 android_frameworks_opt_net_wifi-0cd22728c628e51e8f259f8404a97dec49804424.zip |
WifiConfigManager: Temporarily blacklist on disconnect
When an external entity (settings for example) triggers
WifiManager.disconnect() API, ensure that we blacklist the network
temporarily for 1 hour. Any internal disconnects triggered by the stack
will not result in blacklisting the network.
Bug: 126503889
Test: ./frameworks/opt/net/wifi/tests/wifitests/runtests.sh
Change-Id: If66fd078fa74b8153a9d1aca2ed362b2246f276d
10 files changed, 92 insertions, 41 deletions
diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java index 444219d2b..1b460cb90 100644 --- a/service/java/com/android/server/wifi/ClientModeImpl.java +++ b/service/java/com/android/server/wifi/ClientModeImpl.java @@ -17,6 +17,7 @@ package com.android.server.wifi; import static android.net.shared.LinkPropertiesParcelableUtil.toStableParcelable; +import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WIFI_MANAGER_DISCONNECT; import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED; import static android.net.wifi.WifiManager.WIFI_STATE_DISABLING; import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED; @@ -1587,20 +1588,19 @@ public class ClientModeImpl extends StateMachine { } /** - * Disconnect from Access Point + * Method to trigger a disconnect. + * Note: To be used from within the wifi stack. */ - public void disconnectCommand() { - sendMessage(CMD_DISCONNECT); + public void disconnectCommandInternal() { + sendMessage(CMD_DISCONNECT, 0 /* fromExternal */); } /** * Method to trigger a disconnect. - * - * @param uid UID of requesting caller - * @param reason disconnect reason + * Note: To be used from public API surface. */ - public void disconnectCommand(int uid, int reason) { - sendMessage(CMD_DISCONNECT, uid, reason); + public void disconnectCommandExternal() { + sendMessage(CMD_DISCONNECT, 1 /* fromExternal */); } /** @@ -3671,7 +3671,7 @@ public class ClientModeImpl extends StateMachine { if (removedNetworkIds.contains(mTargetNetworkId) || removedNetworkIds.contains(mLastNetworkId)) { // Disconnect and let autojoin reselect a new network - sendMessage(CMD_DISCONNECT); + disconnectCommandInternal(); } break; case CMD_USER_UNLOCK: @@ -4129,7 +4129,7 @@ public class ClientModeImpl extends StateMachine { netId = message.arg1; if (netId == mTargetNetworkId || netId == mLastNetworkId) { // Disconnect and let autojoin reselect a new network - sendMessage(CMD_DISCONNECT); + disconnectCommandInternal(); } break; case CMD_ENABLE_NETWORK: @@ -4153,7 +4153,7 @@ public class ClientModeImpl extends StateMachine { replyToMessage(message, WifiManager.DISABLE_NETWORK_SUCCEEDED); if (netId == mTargetNetworkId || netId == mLastNetworkId) { // Disconnect and let autojoin reselect a new network - sendMessage(CMD_DISCONNECT); + disconnectCommandInternal(); } } else { loge("Failed to disable network"); @@ -4168,7 +4168,7 @@ public class ClientModeImpl extends StateMachine { if (config.networkId == mTargetNetworkId || config.networkId == mLastNetworkId) { // Disconnect and let autojoin reselect a new network - sendMessage(CMD_DISCONNECT); + disconnectCommandInternal(); } } break; @@ -4328,7 +4328,7 @@ public class ClientModeImpl extends StateMachine { if (removedNetworkIds.contains(mTargetNetworkId) || removedNetworkIds.contains(mLastNetworkId)) { // Disconnect and let autojoin reselect a new network. - sendMessage(CMD_DISCONNECT); + disconnectCommandInternal(); } break; case CMD_REMOVE_USER_CONFIGURATIONS: @@ -4337,7 +4337,7 @@ public class ClientModeImpl extends StateMachine { if (removedNetworkIds.contains(mTargetNetworkId) || removedNetworkIds.contains(mLastNetworkId)) { // Disconnect and let autojoin reselect a new network. - sendMessage(CMD_DISCONNECT); + disconnectCommandInternal(); } break; case WifiManager.CONNECT_NETWORK: @@ -4418,7 +4418,7 @@ public class ClientModeImpl extends StateMachine { netId = message.arg1; if (netId == mTargetNetworkId || netId == mLastNetworkId) { // Disconnect and let autojoin reselect a new network - sendMessage(CMD_DISCONNECT); + disconnectCommandInternal(); } break; case CMD_ASSOCIATED_BSSID: @@ -4482,7 +4482,7 @@ public class ClientModeImpl extends StateMachine { } else { logw("Connected to unknown networkId " + mLastNetworkId + ", disconnecting..."); - sendMessage(CMD_DISCONNECT); + disconnectCommandInternal(); } break; case WifiMonitor.NETWORK_DISCONNECTION_EVENT: @@ -4515,7 +4515,7 @@ public class ClientModeImpl extends StateMachine { if (isProviderOwnedNetwork(mTargetNetworkId, fqdn) || isProviderOwnedNetwork(mLastNetworkId, fqdn)) { logd("Disconnect from current network since its provider is updated"); - sendMessage(CMD_DISCONNECT); + disconnectCommandInternal(); } replyToMessage(message, message.what, SUCCESS); } else { @@ -4528,7 +4528,7 @@ public class ClientModeImpl extends StateMachine { if (isProviderOwnedNetwork(mTargetNetworkId, fqdn) || isProviderOwnedNetwork(mLastNetworkId, fqdn)) { logd("Disconnect from current network since its provider is removed"); - sendMessage(CMD_DISCONNECT); + disconnectCommandInternal(); } mWifiConfigManager.removePasspointConfiguredNetwork(fqdn); replyToMessage(message, message.what, SUCCESS); @@ -5055,8 +5055,17 @@ public class ClientModeImpl extends StateMachine { } break; case CMD_DISCONNECT: - mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT, - StaEvent.DISCONNECT_GENERIC); + boolean fromExternal = message.arg1 == 1; + if (fromExternal) { + mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT, + StaEvent.DISCONNECT_API); + // For external disconnect requests, temporarily disable the network. + mWifiConfigManager.updateNetworkSelectionStatus( + mLastNetworkId, DISABLED_BY_WIFI_MANAGER_DISCONNECT); + } else { + mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT, + StaEvent.DISCONNECT_GENERIC); + } mWifiNative.disconnect(mInterfaceName); transitionTo(mDisconnectingState); break; diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java index dfb3cd20f..92bec08a3 100644 --- a/service/java/com/android/server/wifi/WifiConfigManager.java +++ b/service/java/com/android/server/wifi/WifiConfigManager.java @@ -16,6 +16,8 @@ package com.android.server.wifi; +import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_DISABLED_PERMANENT_STARTING_INDEX; + import android.annotation.Nullable; import android.app.ActivityManager; import android.app.admin.DeviceAdminInfo; @@ -126,6 +128,7 @@ public class WifiConfigManager { 1, // threshold for DISABLED_NO_INTERNET_TEMPORARY 1, // threshold for DISABLED_WPS_START 6, // threshold for DISABLED_TLS_VERSION_MISMATCH + 1, // threshold for DISABLED_BY_WIFI_MANAGER_DISCONNECT 1, // threshold for DISABLED_AUTHENTICATION_NO_CREDENTIALS 1, // threshold for DISABLED_NO_INTERNET_PERMANENT 1, // threshold for DISABLED_BY_WIFI_MANAGER @@ -150,6 +153,7 @@ public class WifiConfigManager { 10 * 60 * 1000, // threshold for DISABLED_NO_INTERNET_TEMPORARY 0 * 60 * 1000, // threshold for DISABLED_WPS_START Integer.MAX_VALUE, // threshold for DISABLED_TLS_VERSION + 1 * 60 * 60 * 1000, // threshold for DISABLED_BY_WIFI_MANAGER_DISCONNECT Integer.MAX_VALUE, // threshold for DISABLED_AUTHENTICATION_NO_CREDENTIALS Integer.MAX_VALUE, // threshold for DISABLED_NO_INTERNET_PERMANENT Integer.MAX_VALUE, // threshold for DISABLED_BY_WIFI_MANAGER @@ -1564,7 +1568,7 @@ public class WifiConfigManager { if (reason == NetworkSelectionStatus.NETWORK_SELECTION_ENABLE) { setNetworkSelectionEnabled(config); setNetworkStatus(config, WifiConfiguration.Status.ENABLED); - } else if (reason < NetworkSelectionStatus.DISABLED_TLS_VERSION_MISMATCH) { + } else if (reason < NETWORK_SELECTION_DISABLED_PERMANENT_STARTING_INDEX) { setNetworkSelectionTemporarilyDisabled(config, reason); } else { setNetworkSelectionPermanentlyDisabled(config, reason); diff --git a/service/java/com/android/server/wifi/WifiNetworkFactory.java b/service/java/com/android/server/wifi/WifiNetworkFactory.java index 057fc99ac..98f72c2e2 100644 --- a/service/java/com/android/server/wifi/WifiNetworkFactory.java +++ b/service/java/com/android/server/wifi/WifiNetworkFactory.java @@ -937,7 +937,7 @@ public class WifiNetworkFactory extends NetworkFactory { // Invoked at the termination of current connected request processing. private void teardownForConnectedNetwork() { Log.i(TAG, "Disconnecting from network on reset"); - mWifiInjector.getClientModeImpl().disconnectCommand(); + mWifiInjector.getClientModeImpl().disconnectCommandInternal(); mConnectedSpecificNetworkRequest = null; mConnectedSpecificNetworkRequestSpecifier = null; // ensure there is no active request in progress. diff --git a/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java b/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java index 12055704e..121d1cb60 100644 --- a/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java +++ b/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java @@ -504,7 +504,7 @@ public class WifiNetworkSuggestionsManager { if (mActiveNetworkSuggestionsMatchingConnection.isEmpty()) { Log.i(TAG, "Only network suggestion matching the connected network removed. " + "Disconnecting..."); - mWifiInjector.getClientModeImpl().disconnectCommand(); + mWifiInjector.getClientModeImpl().disconnectCommandInternal(); } } } diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java index 728a4b4ec..83e8cb0f0 100644 --- a/service/java/com/android/server/wifi/WifiServiceImpl.java +++ b/service/java/com/android/server/wifi/WifiServiceImpl.java @@ -1644,7 +1644,7 @@ public class WifiServiceImpl extends BaseWifiService { return false; } mLog.info("disconnect uid=%").c(Binder.getCallingUid()).flush(); - mClientModeImpl.disconnectCommand(); + mClientModeImpl.disconnectCommandExternal(); return true; } diff --git a/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java b/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java index 22e8c2c1f..4e7bec64d 100644 --- a/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java +++ b/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java @@ -3304,4 +3304,40 @@ public class ClientModeImplTest { assertEquals(OP_PACKAGE_NAME, mCmi.getWifiInfo().getNetworkSuggestionOrSpecifierPackageName()); } + + /** + * Verifies the handling of disconnect initiated from API surface when connected to a network. + */ + @Test + public void testExternalDisconnectWhenConnected() throws Exception { + connect(); + + mCmi.disconnectCommandExternal(); // Simulate settings invoking this. + mLooper.dispatchAll(); + + verify(mWifiNative).disconnect(WIFI_IFACE_NAME); + verify(mWifiMetrics).logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT, + StaEvent.DISCONNECT_API); + // verify that we temp blacklist the network. + verify(mWifiConfigManager).updateNetworkSelectionStatus(0, + WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WIFI_MANAGER_DISCONNECT); + } + + /** + * Verifies the handling of disconnect initiated internally when connected to a network. + */ + @Test + public void testInternalDisconnectWhenConnected() throws Exception { + connect(); + + mCmi.disconnectCommandInternal(); // Internal stack initiated disconnect. + mLooper.dispatchAll(); + + verify(mWifiNative).disconnect(WIFI_IFACE_NAME); + verify(mWifiMetrics).logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT, + StaEvent.DISCONNECT_GENERIC); + // verify that we don't temp blacklist the network. + verify(mWifiConfigManager, never()).updateNetworkSelectionStatus(0, + WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WIFI_MANAGER_DISCONNECT); + } } diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java index 5155ccb5f..2fe85902e 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java @@ -16,6 +16,8 @@ package com.android.server.wifi; +import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_DISABLED_PERMANENT_STARTING_INDEX; + import static org.junit.Assert.*; import static org.mockito.Mockito.*; @@ -4978,7 +4980,7 @@ public class WifiConfigManagerTest { NetworkSelectionStatus.INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP, retrievedDisableTime); verifyUpdateNetworkStatus(retrievedNetwork, WifiConfiguration.Status.ENABLED); - } else if (reason < NetworkSelectionStatus.DISABLED_TLS_VERSION_MISMATCH) { + } else if (reason < NETWORK_SELECTION_DISABLED_PERMANENT_STARTING_INDEX) { // For temporarily disabled networks, we need to ensure that the current status remains // until the threshold is crossed. assertEquals(temporaryDisableReasonCounter, retrievedDisableReasonCounter); diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java index a35d99da1..5a41ae90e 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java @@ -587,7 +587,7 @@ 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(); + verify(mClientModeImpl, never()).disconnectCommandInternal(); // Re-enable connectivity manager . verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false); @@ -1411,7 +1411,7 @@ public class WifiNetworkFactoryTest { // Now release the network request. mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); // Verify that we triggered a disconnect. - verify(mClientModeImpl).disconnectCommand(); + verify(mClientModeImpl).disconnectCommandInternal(); // Re-enable connectivity manager . verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false); } @@ -1586,12 +1586,12 @@ public class WifiNetworkFactoryTest { verify(mWifiConnectivityManager, times(1)).setSpecificNetworkRequestInProgress(true); verify(mWifiScanner, times(2)).startScan(any(), any(), any()); // we shouldn't disconnect until the user accepts the next request. - verify(mClientModeImpl, never()).disconnectCommand(); + verify(mClientModeImpl, never()).disconnectCommandInternal(); // Remove the connected request1 & ensure we disconnect. mNetworkRequest.networkCapabilities.setNetworkSpecifier(specifier1); mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); - verify(mClientModeImpl).disconnectCommand(); + verify(mClientModeImpl).disconnectCommandInternal(); verifyNoMoreInteractions(mWifiConnectivityManager, mWifiScanner, mClientModeImpl, mAlarmManager); @@ -1636,7 +1636,7 @@ public class WifiNetworkFactoryTest { // We shouldn't explicitly disconnect, the new connection attempt will implicitly disconnect // from the connected network. - verify(mClientModeImpl, never()).disconnectCommand(); + verify(mClientModeImpl, never()).disconnectCommandInternal(); // Remove the stale request1 & ensure nothing happens (because it was replaced by the // second request) @@ -1649,7 +1649,7 @@ public class WifiNetworkFactoryTest { // Now remove the rejected request2, ensure we disconnect & re-enable auto-join. mNetworkRequest.networkCapabilities.setNetworkSpecifier(specifier2); mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); - verify(mClientModeImpl).disconnectCommand(); + verify(mClientModeImpl).disconnectCommandInternal(); verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false); verifyNoMoreInteractions(mWifiConnectivityManager, mWifiScanner, mClientModeImpl, @@ -1685,12 +1685,12 @@ public class WifiNetworkFactoryTest { // we shouldn't disconnect/re-enable auto-join until the connected request is released. verify(mWifiConnectivityManager, never()).setSpecificNetworkRequestInProgress(false); - verify(mClientModeImpl, never()).disconnectCommand(); + verify(mClientModeImpl, never()).disconnectCommandInternal(); // Remove the connected request1 & ensure we disconnect & ensure auto-join is re-enabled. mNetworkRequest.networkCapabilities.setNetworkSpecifier(specifier1); mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); - verify(mClientModeImpl).disconnectCommand(); + verify(mClientModeImpl).disconnectCommandInternal(); verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false); verifyNoMoreInteractions(mWifiConnectivityManager, mWifiScanner, mClientModeImpl, diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java index eb09d239b..4e2cb9b5d 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java @@ -1257,7 +1257,7 @@ public class WifiNetworkSuggestionsManagerTest { // Now remove the network suggestion and ensure we did not trigger a disconnect. assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, mWifiNetworkSuggestionsManager.remove(networkSuggestionList, TEST_PACKAGE_1)); - verify(mClientModeImpl, never()).disconnectCommand(); + verify(mClientModeImpl, never()).disconnectCommandInternal(); } /** @@ -1293,11 +1293,11 @@ public class WifiNetworkSuggestionsManagerTest { // Now remove one of the apps and ensure we did not trigger a disconnect. mWifiNetworkSuggestionsManager.removeApp(TEST_PACKAGE_1); - verify(mClientModeImpl, never()).disconnectCommand(); + verify(mClientModeImpl, never()).disconnectCommandInternal(); // Now remove the other app and ensure we trigger a disconnect. mWifiNetworkSuggestionsManager.removeApp(TEST_PACKAGE_2); - verify(mClientModeImpl).disconnectCommand(); + verify(mClientModeImpl).disconnectCommandInternal(); } /** @@ -1324,7 +1324,7 @@ public class WifiNetworkSuggestionsManagerTest { // Now remove the app and ensure we did not trigger a disconnect. mWifiNetworkSuggestionsManager.removeApp(TEST_PACKAGE_1); - verify(mClientModeImpl, never()).disconnectCommand(); + verify(mClientModeImpl, never()).disconnectCommandInternal(); } /** @@ -1356,7 +1356,7 @@ public class WifiNetworkSuggestionsManagerTest { // Now remove the app and ensure we did not trigger a disconnect. mWifiNetworkSuggestionsManager.removeApp(TEST_PACKAGE_1); - verify(mClientModeImpl, never()).disconnectCommand(); + verify(mClientModeImpl, never()).disconnectCommandInternal(); } /** diff --git a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java index 48efb51a6..191acc6a7 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java @@ -2780,7 +2780,7 @@ public class WifiServiceImplTest { doThrow(new SecurityException()).when(mAppOpsManager) .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); assertTrue(mWifiServiceImpl.disconnect(TEST_PACKAGE_NAME)); - verify(mClientModeImpl).disconnectCommand(); + verify(mClientModeImpl).disconnectCommandExternal(); } /** @@ -2792,7 +2792,7 @@ public class WifiServiceImplTest { public void testDisconnectWithChangeWifiStatePerm() throws Exception { assertFalse(mWifiServiceImpl.disconnect(TEST_PACKAGE_NAME)); verifyCheckChangePermission(TEST_PACKAGE_NAME); - verify(mClientModeImpl, never()).disconnectCommand(); + verify(mClientModeImpl, never()).disconnectCommandExternal(); } /** @@ -2811,7 +2811,7 @@ public class WifiServiceImplTest { } verifyCheckChangePermission(TEST_PACKAGE_NAME); - verify(mClientModeImpl, never()).disconnectCommand(); + verify(mClientModeImpl, never()).disconnectCommandExternal(); } @Test |