diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java index 2535974c19..dd4f33bfa5 100755 --- a/service/src/com/android/server/ConnectivityService.java +++ b/service/src/com/android/server/ConnectivityService.java @@ -736,6 +736,12 @@ public class ConnectivityService extends IConnectivityManager.Stub */ private static final int EVENT_INITIAL_EVALUATION_TIMEOUT = 57; + /** + * Used internally when the user does not want the network from captive portal app. + * obj = Network + */ + private static final int EVENT_USER_DOES_NOT_WANT = 58; + /** * Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification * should be shown. @@ -5055,6 +5061,10 @@ public class ConnectivityService extends IConnectivityManager.Stub public void appResponse(final int response) { if (response == CaptivePortal.APP_RETURN_WANTED_AS_IS) { enforceSettingsPermission(); + } else if (response == CaptivePortal.APP_RETURN_UNWANTED) { + mHandler.sendMessage(mHandler.obtainMessage(EVENT_USER_DOES_NOT_WANT, mNetwork)); + // Since the network will be disconnected, skip notifying NetworkMonitor + return; } final NetworkMonitorManager nm = getNetworkMonitorManager(mNetwork); @@ -5496,6 +5506,12 @@ public class ConnectivityService extends IConnectivityManager.Stub case EVENT_INGRESS_RATE_LIMIT_CHANGED: handleIngressRateLimitChanged(); break; + case EVENT_USER_DOES_NOT_WANT: + final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork((Network) msg.obj); + if (nai == null) break; + nai.onPreventAutomaticReconnect(); + nai.disconnect(); + break; } } } diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java index 8c9917ed52..3d8073f39c 100755 --- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java @@ -228,6 +228,7 @@ import android.content.pm.ServiceInfo; import android.content.pm.UserInfo; import android.content.res.Resources; import android.location.LocationManager; +import android.net.CaptivePortal; import android.net.CaptivePortalData; import android.net.ConnectionInfo; import android.net.ConnectivityDiagnosticsManager.DataStallReport; @@ -4440,6 +4441,27 @@ public class ConnectivityServiceTest { validatedCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent); } + private Intent startCaptivePortalApp(TestNetworkAgentWrapper networkAgent) throws Exception { + Network network = networkAgent.getNetwork(); + // Check that startCaptivePortalApp sends the expected command to NetworkMonitor. + mCm.startCaptivePortalApp(network); + waitForIdle(); + verify(networkAgent.mNetworkMonitor).launchCaptivePortalApp(); + + // NetworkMonitor uses startCaptivePortal(Network, Bundle) (startCaptivePortalAppInternal) + final Bundle testBundle = new Bundle(); + final String testKey = "testkey"; + final String testValue = "testvalue"; + testBundle.putString(testKey, testValue); + mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + PERMISSION_GRANTED); + mCm.startCaptivePortalApp(network, testBundle); + final Intent signInIntent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS); + assertEquals(ACTION_CAPTIVE_PORTAL_SIGN_IN, signInIntent.getAction()); + assertEquals(testValue, signInIntent.getStringExtra(testKey)); + return signInIntent; + } + @Test public void testCaptivePortalApp() throws Exception { final TestNetworkCallback captivePortalCallback = new TestNetworkCallback(); @@ -4476,22 +4498,7 @@ public class ConnectivityServiceTest { captivePortalCallback.expect(CallbackEntry.NETWORK_CAPS_UPDATED, mWiFiNetworkAgent); - // Check that startCaptivePortalApp sends the expected command to NetworkMonitor. - mCm.startCaptivePortalApp(wifiNetwork); - waitForIdle(); - verify(mWiFiNetworkAgent.mNetworkMonitor).launchCaptivePortalApp(); - - // NetworkMonitor uses startCaptivePortal(Network, Bundle) (startCaptivePortalAppInternal) - final Bundle testBundle = new Bundle(); - final String testKey = "testkey"; - final String testValue = "testvalue"; - testBundle.putString(testKey, testValue); - mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, - PERMISSION_GRANTED); - mCm.startCaptivePortalApp(wifiNetwork, testBundle); - final Intent signInIntent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS); - assertEquals(ACTION_CAPTIVE_PORTAL_SIGN_IN, signInIntent.getAction()); - assertEquals(testValue, signInIntent.getStringExtra(testKey)); + startCaptivePortalApp(mWiFiNetworkAgent); // Report that the captive portal is dismissed, and check that callbacks are fired mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */); @@ -4503,6 +4510,37 @@ public class ConnectivityServiceTest { mCm.unregisterNetworkCallback(captivePortalCallback); } + @Test + public void testCaptivePortalApp_IgnoreNetwork() throws Exception { + final TestNetworkCallback captivePortalCallback = new TestNetworkCallback(); + final NetworkRequest captivePortalRequest = new NetworkRequest.Builder() + .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build(); + mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback); + + mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); + mWiFiNetworkAgent.connectWithCaptivePortal(TEST_REDIRECT_URL, false); + captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); + + final Intent signInIntent = startCaptivePortalApp(mWiFiNetworkAgent); + final CaptivePortal captivePortal = signInIntent + .getParcelableExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL); + + captivePortal.ignoreNetwork(); + waitForIdle(); + + // Since network will disconnect, ensure no notification of response to NetworkMonitor + verify(mWiFiNetworkAgent.mNetworkMonitor, never()) + .notifyCaptivePortalAppFinished(CaptivePortal.APP_RETURN_UNWANTED); + + // Report that the network is disconnected + mWiFiNetworkAgent.expectDisconnected(); + mWiFiNetworkAgent.expectPreventReconnectReceived(); + verify(mWiFiNetworkAgent.mNetworkMonitor).notifyNetworkDisconnected(); + captivePortalCallback.expect(CallbackEntry.LOST, mWiFiNetworkAgent); + + mCm.unregisterNetworkCallback(captivePortalCallback); + } + @Test public void testAvoidOrIgnoreCaptivePortals() throws Exception { final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();