diff --git a/api/system-current.txt b/api/system-current.txt index 07319f3269cd8..7d9cf5f31b9db 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -4281,7 +4281,9 @@ package android.net { public class CaptivePortal implements android.os.Parcelable { method public void logEvent(int, @NonNull String); + method public void reevaluateNetwork(); method public void useNetwork(); + field public static final int APP_REQUEST_REEVALUATION_REQUIRED = 100; // 0x64 field public static final int APP_RETURN_DISMISSED = 0; // 0x0 field public static final int APP_RETURN_UNWANTED = 1; // 0x1 field public static final int APP_RETURN_WANTED_AS_IS = 2; // 0x2 diff --git a/api/test-current.txt b/api/test-current.txt index 7736b32a40619..9b702bb6a7efe 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -1350,7 +1350,9 @@ package android.net { public class CaptivePortal implements android.os.Parcelable { method public void logEvent(int, @NonNull String); + method public void reevaluateNetwork(); method public void useNetwork(); + field public static final int APP_REQUEST_REEVALUATION_REQUIRED = 100; // 0x64 field public static final int APP_RETURN_DISMISSED = 0; // 0x0 field public static final int APP_RETURN_UNWANTED = 1; // 0x1 field public static final int APP_RETURN_WANTED_AS_IS = 2; // 0x2 diff --git a/core/java/android/net/CaptivePortal.java b/core/java/android/net/CaptivePortal.java index a66fcae7d4a29..fb35b4bde3039 100644 --- a/core/java/android/net/CaptivePortal.java +++ b/core/java/android/net/CaptivePortal.java @@ -60,6 +60,18 @@ public class CaptivePortal implements Parcelable { @SystemApi @TestApi public static final int APP_RETURN_WANTED_AS_IS = 2; + /** Event offset of request codes from captive portal application. */ + private static final int APP_REQUEST_BASE = 100; + /** + * Request code from the captive portal application, indicating that the network condition may + * have changed and the network should be re-validated. + * @see ICaptivePortal#appRequest(int) + * @see android.net.INetworkMonitor#forceReevaluation(int) + * @hide + */ + @SystemApi + @TestApi + public static final int APP_REQUEST_REEVALUATION_REQUIRED = APP_REQUEST_BASE + 0; private final IBinder mBinder; @@ -135,6 +147,19 @@ public class CaptivePortal implements Parcelable { } } + /** + * Request that the system reevaluates the captive portal status. + * @hide + */ + @SystemApi + @TestApi + public void reevaluateNetwork() { + try { + ICaptivePortal.Stub.asInterface(mBinder).appRequest(APP_REQUEST_REEVALUATION_REQUIRED); + } catch (RemoteException e) { + } + } + /** * Log a captive portal login event. * @param eventId one of the CAPTIVE_PORTAL_LOGIN_* constants in metrics_constants.proto. diff --git a/core/java/android/net/ICaptivePortal.aidl b/core/java/android/net/ICaptivePortal.aidl index 707b4f699873a..fe21905c70029 100644 --- a/core/java/android/net/ICaptivePortal.aidl +++ b/core/java/android/net/ICaptivePortal.aidl @@ -21,6 +21,7 @@ package android.net; * @hide */ oneway interface ICaptivePortal { + void appRequest(int request); void appResponse(int response); void logEvent(int eventId, String packageName); } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 3a8a73657f396..657207237bf02 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -3609,16 +3609,31 @@ public class ConnectivityService extends IConnectivityManager.Stub enforceSettingsPermission(); } - // getNetworkAgentInfoForNetwork is thread-safe - final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(mNetwork); - if (nai == null) return; - - // nai.networkMonitor() is thread-safe - final NetworkMonitorManager nm = nai.networkMonitor(); + final NetworkMonitorManager nm = getNetworkMonitorManager(mNetwork); if (nm == null) return; nm.notifyCaptivePortalAppFinished(response); } + @Override + public void appRequest(final int request) { + final NetworkMonitorManager nm = getNetworkMonitorManager(mNetwork); + if (nm == null) return; + + if (request == CaptivePortal.APP_REQUEST_REEVALUATION_REQUIRED) { + nm.forceReevaluation(Binder.getCallingUid()); + } + } + + @Nullable + private NetworkMonitorManager getNetworkMonitorManager(final Network network) { + // getNetworkAgentInfoForNetwork is thread-safe + final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network); + if (nai == null) return null; + + // nai.networkMonitor() is thread-safe + return nai.networkMonitor(); + } + @Override public void logEvent(int eventId, String packageName) { enforceSettingsPermission(); diff --git a/tests/net/common/java/android/net/CaptivePortalTest.java b/tests/net/common/java/android/net/CaptivePortalTest.java index eed7159ffddc5..ca4ba63142a20 100644 --- a/tests/net/common/java/android/net/CaptivePortalTest.java +++ b/tests/net/common/java/android/net/CaptivePortalTest.java @@ -43,6 +43,11 @@ public class CaptivePortalTest { mCode = response; } + @Override + public void appRequest(final int request) throws RemoteException { + mCode = request; + } + @Override public void logEvent(int eventId, String packageName) throws RemoteException { mCode = eventId; @@ -79,6 +84,12 @@ public class CaptivePortalTest { assertEquals(result.mCode, CaptivePortal.APP_RETURN_WANTED_AS_IS); } + @Test + public void testReevaluateNetwork() { + final MyCaptivePortalImpl result = runCaptivePortalTest(c -> c.reevaluateNetwork()); + assertEquals(result.mCode, CaptivePortal.APP_REQUEST_REEVALUATION_REQUIRED); + } + @Test public void testLogEvent() { final MyCaptivePortalImpl result = runCaptivePortalTest(c -> c.logEvent(