diff --git a/api/system-current.txt b/api/system-current.txt index 1d6b595bc9661..b89a1da22ca27 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -3193,6 +3193,7 @@ package android.net { method public int[] getTransportTypes(); method public boolean satisfiedByNetworkCapabilities(android.net.NetworkCapabilities); field public static final int NET_CAPABILITY_OEM_PAID = 22; // 0x16 + field public static final int NET_CAPABILITY_PARTIAL_CONNECTIVITY = 24; // 0x18 } public class NetworkKey implements android.os.Parcelable { @@ -3341,10 +3342,12 @@ package android.net.captiveportal { ctor public CaptivePortalProbeResult(int, String, String); ctor public CaptivePortalProbeResult(int, String, String, android.net.captiveportal.CaptivePortalProbeSpec); method public boolean isFailed(); + method public boolean isPartialConnectivity(); method public boolean isPortal(); method public boolean isSuccessful(); field public static final android.net.captiveportal.CaptivePortalProbeResult FAILED; field public static final int FAILED_CODE = 599; // 0x257 + field public static final android.net.captiveportal.CaptivePortalProbeResult PARTIAL; field public static final int PORTAL_CODE = 302; // 0x12e field public static final android.net.captiveportal.CaptivePortalProbeResult SUCCESS; field public static final int SUCCESS_CODE = 204; // 0xcc @@ -3476,6 +3479,7 @@ package android.net.metrics { field public static final int NETWORK_FIRST_VALIDATION_PORTAL_FOUND = 10; // 0xa field public static final int NETWORK_FIRST_VALIDATION_SUCCESS = 8; // 0x8 field public static final int NETWORK_LINGER = 5; // 0x5 + field public static final int NETWORK_PARTIAL_CONNECTIVITY = 13; // 0xd field public static final int NETWORK_REVALIDATION_PORTAL_FOUND = 11; // 0xb field public static final int NETWORK_REVALIDATION_SUCCESS = 9; // 0x9 field public static final int NETWORK_UNLINGER = 6; // 0x6 diff --git a/api/test-current.txt b/api/test-current.txt index 055066337da5c..d43b1c4ec275c 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -751,10 +751,12 @@ package android.net.captiveportal { ctor public CaptivePortalProbeResult(int, String, String); ctor public CaptivePortalProbeResult(int, String, String, android.net.captiveportal.CaptivePortalProbeSpec); method public boolean isFailed(); + method public boolean isPartialConnectivity(); method public boolean isPortal(); method public boolean isSuccessful(); field public static final android.net.captiveportal.CaptivePortalProbeResult FAILED; field public static final int FAILED_CODE = 599; // 0x257 + field public static final android.net.captiveportal.CaptivePortalProbeResult PARTIAL; field public static final int PORTAL_CODE = 302; // 0x12e field public static final android.net.captiveportal.CaptivePortalProbeResult SUCCESS; field public static final int SUCCESS_CODE = 204; // 0xcc @@ -886,6 +888,7 @@ package android.net.metrics { field public static final int NETWORK_FIRST_VALIDATION_PORTAL_FOUND = 10; // 0xa field public static final int NETWORK_FIRST_VALIDATION_SUCCESS = 8; // 0x8 field public static final int NETWORK_LINGER = 5; // 0x5 + field public static final int NETWORK_PARTIAL_CONNECTIVITY = 13; // 0xd field public static final int NETWORK_REVALIDATION_PORTAL_FOUND = 11; // 0xb field public static final int NETWORK_REVALIDATION_SUCCESS = 9; // 0x9 field public static final int NETWORK_UNLINGER = 6; // 0x6 diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 249357e3633d7..91fefa2f1cb09 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -426,6 +426,16 @@ public class ConnectivityManager { public static final String ACTION_PROMPT_LOST_VALIDATION = "android.net.conn.PROMPT_LOST_VALIDATION"; + /** + * Action used to display a dialog that asks the user whether to stay connected to a network + * that has not validated. This intent is used to start the dialog in settings via + * startActivity. + * + * @hide + */ + public static final String ACTION_PROMPT_PARTIAL_CONNECTIVITY = + "android.net.conn.PROMPT_PARTIAL_CONNECTIVITY"; + /** * Invalid tethering type. * @see #startTethering(int, boolean, OnStartTetheringCallback) @@ -4018,7 +4028,7 @@ public class ConnectivityManager { * * @hide */ - @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) + @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setAcceptUnvalidated(Network network, boolean accept, boolean always) { try { mService.setAcceptUnvalidated(network, accept, always); @@ -4027,6 +4037,29 @@ public class ConnectivityManager { } } + /** + * Informs the system whether it should consider the network as validated even if it only has + * partial connectivity. If {@code accept} is true, then the network will be considered as + * validated even if connectivity is only partial. If {@code always} is true, then the choice + * is remembered, so that the next time the user connects to this network, the system will + * switch to it. + * + * @param network The network to accept. + * @param accept Whether to consider the network as validated even if it has partial + * connectivity. + * @param always Whether to remember this choice in the future. + * + * @hide + */ + @RequiresPermission(android.Manifest.permission.NETWORK_STACK) + public void setAcceptPartialConnectivity(Network network, boolean accept, boolean always) { + try { + mService.setAcceptPartialConnectivity(network, accept, always); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * Informs the system to penalize {@code network}'s score when it becomes unvalidated. This is * only meaningful if the system is configured not to penalize such networks, e.g., if the @@ -4037,7 +4070,7 @@ public class ConnectivityManager { * * @hide */ - @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) + @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setAvoidUnvalidated(Network network) { try { mService.setAvoidUnvalidated(network); diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index 9fc56b4e3d36b..2df4e75c49a42 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -176,6 +176,7 @@ interface IConnectivityManager void releaseNetworkRequest(in NetworkRequest networkRequest); void setAcceptUnvalidated(in Network network, boolean accept, boolean always); + void setAcceptPartialConnectivity(in Network network, boolean accept, boolean always); void setAvoidUnvalidated(in Network network); void startCaptivePortalApp(in Network network); void startCaptivePortalAppInternal(in Network network, in Bundle appExtras); diff --git a/core/java/android/net/INetworkMonitor.aidl b/core/java/android/net/INetworkMonitor.aidl index c94cdde15aa8c..5d1ab983c5fcd 100644 --- a/core/java/android/net/INetworkMonitor.aidl +++ b/core/java/android/net/INetworkMonitor.aidl @@ -32,9 +32,16 @@ oneway interface INetworkMonitor { // 3. a broken network (e.g. DNS failed, connect failed, HTTP request failed). const int NETWORK_TEST_RESULT_INVALID = 1; + // After a network has been tested, this result can be sent with EVENT_NETWORK_TESTED. + // The network may be used as a default internet connection, but it was found to be a partial + // connectivity network which can get the pass result for http probe but get the failed result + // for https probe. + const int NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY = 2; + void start(); void launchCaptivePortalApp(); void notifyCaptivePortalAppFinished(int response); + void notifyAcceptPartialConnectivity(); void forceReevaluation(int uid); void notifyPrivateDnsChanged(in PrivateDnsConfigParcel config); void notifyDnsResponse(int returnCode); diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index 0a63e75d1a310..e1cfe991de8da 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -143,7 +143,8 @@ public final class NetworkCapabilities implements Parcelable { NET_CAPABILITY_NOT_CONGESTED, NET_CAPABILITY_NOT_SUSPENDED, NET_CAPABILITY_OEM_PAID, - NET_CAPABILITY_MCX + NET_CAPABILITY_MCX, + NET_CAPABILITY_PARTIAL_CONNECTIVITY, }) public @interface NetCapability { } @@ -304,8 +305,15 @@ public final class NetworkCapabilities implements Parcelable { */ public static final int NET_CAPABILITY_MCX = 23; + /** + * Indicates that this network was tested to only provide partial connectivity. + * @hide + */ + @SystemApi + public static final int NET_CAPABILITY_PARTIAL_CONNECTIVITY = 24; + private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS; - private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_MCX; + private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_PARTIAL_CONNECTIVITY; /** * Network capabilities that are expected to be mutable, i.e., can change while a particular @@ -320,7 +328,8 @@ public final class NetworkCapabilities implements Parcelable { | (1 << NET_CAPABILITY_NOT_ROAMING) | (1 << NET_CAPABILITY_FOREGROUND) | (1 << NET_CAPABILITY_NOT_CONGESTED) - | (1 << NET_CAPABILITY_NOT_SUSPENDED); + | (1 << NET_CAPABILITY_NOT_SUSPENDED) + | (1 << NET_CAPABILITY_PARTIAL_CONNECTIVITY); /** * Network capabilities that are not allowed in NetworkRequests. This exists because the @@ -374,6 +383,15 @@ public final class NetworkCapabilities implements Parcelable { (1 << NET_CAPABILITY_SUPL) | (1 << NET_CAPABILITY_WIFI_P2P); + /** + * Capabilities that are managed by ConnectivityService. + */ + private static final long CONNECTIVITY_MANAGED_CAPABILITIES = + (1 << NET_CAPABILITY_VALIDATED) + | (1 << NET_CAPABILITY_CAPTIVE_PORTAL) + | (1 << NET_CAPABILITY_FOREGROUND) + | (1 << NET_CAPABILITY_PARTIAL_CONNECTIVITY); + /** * Adds the given capability to this {@code NetworkCapability} instance. * Multiple capabilities may be applied sequentially. Note that when searching @@ -507,6 +525,14 @@ public final class NetworkCapabilities implements Parcelable { && ((mUnwantedNetworkCapabilities & (1 << capability)) != 0); } + /** + * Check if this NetworkCapabilities has system managed capabilities or not. + * @hide + */ + public boolean hasConnectivityManagedCapability() { + return ((mNetworkCapabilities & CONNECTIVITY_MANAGED_CAPABILITIES) != 0); + } + /** Note this method may result in having the same capability in wanted and unwanted lists. */ private void combineNetCapabilities(NetworkCapabilities nc) { this.mNetworkCapabilities |= nc.mNetworkCapabilities; @@ -1599,31 +1625,32 @@ public final class NetworkCapabilities implements Parcelable { */ public static String capabilityNameOf(@NetCapability int capability) { switch (capability) { - case NET_CAPABILITY_MMS: return "MMS"; - case NET_CAPABILITY_SUPL: return "SUPL"; - case NET_CAPABILITY_DUN: return "DUN"; - case NET_CAPABILITY_FOTA: return "FOTA"; - case NET_CAPABILITY_IMS: return "IMS"; - case NET_CAPABILITY_CBS: return "CBS"; - case NET_CAPABILITY_WIFI_P2P: return "WIFI_P2P"; - case NET_CAPABILITY_IA: return "IA"; - case NET_CAPABILITY_RCS: return "RCS"; - case NET_CAPABILITY_XCAP: return "XCAP"; - case NET_CAPABILITY_EIMS: return "EIMS"; - case NET_CAPABILITY_NOT_METERED: return "NOT_METERED"; - case NET_CAPABILITY_INTERNET: return "INTERNET"; - case NET_CAPABILITY_NOT_RESTRICTED: return "NOT_RESTRICTED"; - case NET_CAPABILITY_TRUSTED: return "TRUSTED"; - case NET_CAPABILITY_NOT_VPN: return "NOT_VPN"; - case NET_CAPABILITY_VALIDATED: return "VALIDATED"; - case NET_CAPABILITY_CAPTIVE_PORTAL: return "CAPTIVE_PORTAL"; - case NET_CAPABILITY_NOT_ROAMING: return "NOT_ROAMING"; - case NET_CAPABILITY_FOREGROUND: return "FOREGROUND"; - case NET_CAPABILITY_NOT_CONGESTED: return "NOT_CONGESTED"; - case NET_CAPABILITY_NOT_SUSPENDED: return "NOT_SUSPENDED"; - case NET_CAPABILITY_OEM_PAID: return "OEM_PAID"; - case NET_CAPABILITY_MCX: return "MCX"; - default: return Integer.toString(capability); + case NET_CAPABILITY_MMS: return "MMS"; + case NET_CAPABILITY_SUPL: return "SUPL"; + case NET_CAPABILITY_DUN: return "DUN"; + case NET_CAPABILITY_FOTA: return "FOTA"; + case NET_CAPABILITY_IMS: return "IMS"; + case NET_CAPABILITY_CBS: return "CBS"; + case NET_CAPABILITY_WIFI_P2P: return "WIFI_P2P"; + case NET_CAPABILITY_IA: return "IA"; + case NET_CAPABILITY_RCS: return "RCS"; + case NET_CAPABILITY_XCAP: return "XCAP"; + case NET_CAPABILITY_EIMS: return "EIMS"; + case NET_CAPABILITY_NOT_METERED: return "NOT_METERED"; + case NET_CAPABILITY_INTERNET: return "INTERNET"; + case NET_CAPABILITY_NOT_RESTRICTED: return "NOT_RESTRICTED"; + case NET_CAPABILITY_TRUSTED: return "TRUSTED"; + case NET_CAPABILITY_NOT_VPN: return "NOT_VPN"; + case NET_CAPABILITY_VALIDATED: return "VALIDATED"; + case NET_CAPABILITY_CAPTIVE_PORTAL: return "CAPTIVE_PORTAL"; + case NET_CAPABILITY_NOT_ROAMING: return "NOT_ROAMING"; + case NET_CAPABILITY_FOREGROUND: return "FOREGROUND"; + case NET_CAPABILITY_NOT_CONGESTED: return "NOT_CONGESTED"; + case NET_CAPABILITY_NOT_SUSPENDED: return "NOT_SUSPENDED"; + case NET_CAPABILITY_OEM_PAID: return "OEM_PAID"; + case NET_CAPABILITY_MCX: return "MCX"; + case NET_CAPABILITY_PARTIAL_CONNECTIVITY: return "PARTIAL_CONNECTIVITY"; + default: return Integer.toString(capability); } } diff --git a/core/java/android/net/NetworkMisc.java b/core/java/android/net/NetworkMisc.java index c0487b521b466..6fb239015aee4 100644 --- a/core/java/android/net/NetworkMisc.java +++ b/core/java/android/net/NetworkMisc.java @@ -51,6 +51,12 @@ public class NetworkMisc implements Parcelable { */ public boolean acceptUnvalidated; + /** + * Whether the user explicitly set that this network should be validated even if presence of + * only partial internet connectivity. + */ + public boolean acceptPartialConnectivity; + /** * Set to avoid surfacing the "Sign in to network" notification. * if carrier receivers/apps are registered to handle the carrier-specific provisioning diff --git a/core/java/android/net/captiveportal/CaptivePortalProbeResult.java b/core/java/android/net/captiveportal/CaptivePortalProbeResult.java index 7432687e136f6..3930344e5d27b 100644 --- a/core/java/android/net/captiveportal/CaptivePortalProbeResult.java +++ b/core/java/android/net/captiveportal/CaptivePortalProbeResult.java @@ -30,10 +30,20 @@ public final class CaptivePortalProbeResult { public static final int SUCCESS_CODE = 204; public static final int FAILED_CODE = 599; public static final int PORTAL_CODE = 302; + // Set partial connectivity http response code to -1 to prevent conflict with the other http + // response codes. Besides the default http response code of probe result is set as 599 in + // NetworkMonitor#sendParallelHttpProbes(), so response code will be set as -1 only when + // NetworkMonitor detects partial connectivity. + /** + * @hide + */ + public static final int PARTIAL_CODE = -1; public static final CaptivePortalProbeResult FAILED = new CaptivePortalProbeResult(FAILED_CODE); public static final CaptivePortalProbeResult SUCCESS = new CaptivePortalProbeResult(SUCCESS_CODE); + public static final CaptivePortalProbeResult PARTIAL = + new CaptivePortalProbeResult(PARTIAL_CODE); private final int mHttpResponseCode; // HTTP response code returned from Internet probe. public final String redirectUrl; // Redirect destination returned from Internet probe. @@ -69,4 +79,8 @@ public final class CaptivePortalProbeResult { public boolean isFailed() { return !isSuccessful() && !isPortal(); } + + public boolean isPartialConnectivity() { + return mHttpResponseCode == PARTIAL_CODE; + } } diff --git a/core/java/android/net/metrics/NetworkEvent.java b/core/java/android/net/metrics/NetworkEvent.java index f5b2ff1304949..5128115800217 100644 --- a/core/java/android/net/metrics/NetworkEvent.java +++ b/core/java/android/net/metrics/NetworkEvent.java @@ -50,6 +50,8 @@ public final class NetworkEvent implements IpConnectivityLog.Event { public static final int NETWORK_CONSECUTIVE_DNS_TIMEOUT_FOUND = 12; + public static final int NETWORK_PARTIAL_CONNECTIVITY = 13; + /** @hide */ @IntDef(value = { NETWORK_CONNECTED, @@ -64,6 +66,7 @@ public final class NetworkEvent implements IpConnectivityLog.Event { NETWORK_FIRST_VALIDATION_PORTAL_FOUND, NETWORK_REVALIDATION_PORTAL_FOUND, NETWORK_CONSECUTIVE_DNS_TIMEOUT_FOUND, + NETWORK_PARTIAL_CONNECTIVITY, }) @Retention(RetentionPolicy.SOURCE) public @interface EventType {} diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index b412f0fdb9b5f..b4e69adc119ce 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -3197,13 +3197,18 @@ %1$s - Wi-Fi has no internet access + %1$s has no internet access Tap for options Connected + + %1$s has limited connectivity + + + Tap to connect anyway