Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 399b7500 authored by Chiachang Wang's avatar Chiachang Wang Committed by Android (Google) Code Review
Browse files

Merge "Update multiple validation result to ConnectivityService" into qt-dev

parents 8f1b7c77 8d573213
Loading
Loading
Loading
Loading
+136 −25
Original line number Original line Diff line number Diff line
@@ -24,8 +24,13 @@ import static android.net.ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.DnsResolver.FLAG_EMPTY;
import static android.net.DnsResolver.FLAG_EMPTY;
import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_INVALID;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS;
import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_FALLBACK;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTP;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTPS;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_PRIVDNS;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
@@ -69,7 +74,6 @@ import android.content.IntentFilter;
import android.content.res.Resources;
import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager;
import android.net.DnsResolver;
import android.net.DnsResolver;
import android.net.INetworkMonitor;
import android.net.INetworkMonitorCallbacks;
import android.net.INetworkMonitorCallbacks;
import android.net.LinkProperties;
import android.net.LinkProperties;
import android.net.Network;
import android.net.Network;
@@ -277,7 +281,7 @@ public class NetworkMonitor extends StateMachine {
    private static final int BLAME_FOR_EVALUATION_ATTEMPTS = 5;
    private static final int BLAME_FOR_EVALUATION_ATTEMPTS = 5;
    // Delay between reevaluations once a captive portal has been found.
    // Delay between reevaluations once a captive portal has been found.
    private static final int CAPTIVE_PORTAL_REEVALUATE_DELAY_MS = 10 * 60 * 1000;
    private static final int CAPTIVE_PORTAL_REEVALUATE_DELAY_MS = 10 * 60 * 1000;

    private static final int NETWORK_VALIDATION_RESULT_INVALID = 0;
    private String mPrivateDnsProviderHostname = "";
    private String mPrivateDnsProviderHostname = "";


    private final Context mContext;
    private final Context mContext;
@@ -348,7 +352,8 @@ public class NetworkMonitor extends StateMachine {
    private long mLastProbeTime;
    private long mLastProbeTime;
    // Set to true if data stall is suspected and reset to false after metrics are sent to statsd.
    // Set to true if data stall is suspected and reset to false after metrics are sent to statsd.
    private boolean mCollectDataStallMetrics;
    private boolean mCollectDataStallMetrics;
    private boolean mAcceptPartialConnectivity;
    private boolean mAcceptPartialConnectivity = false;
    private final EvaluationState mEvaluationState = new EvaluationState();


    public NetworkMonitor(Context context, INetworkMonitorCallbacks cb, Network network,
    public NetworkMonitor(Context context, INetworkMonitorCallbacks cb, Network network,
            SharedLog validationLog) {
            SharedLog validationLog) {
@@ -601,7 +606,8 @@ public class NetworkMonitor extends StateMachine {
                        case APP_RETURN_UNWANTED:
                        case APP_RETURN_UNWANTED:
                            mDontDisplaySigninNotification = true;
                            mDontDisplaySigninNotification = true;
                            mUserDoesNotWant = true;
                            mUserDoesNotWant = true;
                            notifyNetworkTested(NETWORK_TEST_RESULT_INVALID, null);
                            mEvaluationState.reportEvaluationResult(
                                    NETWORK_VALIDATION_RESULT_INVALID, null);
                            // TODO: Should teardown network.
                            // TODO: Should teardown network.
                            mUidResponsibleForReeval = 0;
                            mUidResponsibleForReeval = 0;
                            transitionTo(mEvaluatingState);
                            transitionTo(mEvaluatingState);
@@ -653,7 +659,7 @@ public class NetworkMonitor extends StateMachine {
                // re-evaluating and get the result of partial connectivity, ProbingState will
                // re-evaluating and get the result of partial connectivity, ProbingState will
                // disable HTTPS probe and transition to EvaluatingPrivateDnsState.
                // disable HTTPS probe and transition to EvaluatingPrivateDnsState.
                case EVENT_ACCEPT_PARTIAL_CONNECTIVITY:
                case EVENT_ACCEPT_PARTIAL_CONNECTIVITY:
                    mAcceptPartialConnectivity = true;
                    maybeDisableHttpsProbing(true /* acceptPartial */);
                    break;
                    break;
                case EVENT_LINK_PROPERTIES_CHANGED:
                case EVENT_LINK_PROPERTIES_CHANGED:
                    mLinkProperties = (LinkProperties) message.obj;
                    mLinkProperties = (LinkProperties) message.obj;
@@ -677,7 +683,14 @@ public class NetworkMonitor extends StateMachine {
        public void enter() {
        public void enter() {
            maybeLogEvaluationResult(
            maybeLogEvaluationResult(
                    networkEventType(validationStage(), EvaluationResult.VALIDATED));
                    networkEventType(validationStage(), EvaluationResult.VALIDATED));
            notifyNetworkTested(INetworkMonitor.NETWORK_TEST_RESULT_VALID, null);
            // If the user has accepted that and HTTPS probing is disabled, then mark the network
            // as validated and partial so that settings can keep informing the user that the
            // connection is limited.
            int result = NETWORK_VALIDATION_RESULT_VALID;
            if (!mUseHttps && mAcceptPartialConnectivity) {
                result |= NETWORK_VALIDATION_RESULT_PARTIAL;
            }
            mEvaluationState.reportEvaluationResult(result, null /* redirectUrl */);
            mValidations++;
            mValidations++;
        }
        }


@@ -820,6 +833,9 @@ public class NetworkMonitor extends StateMachine {
            }
            }
            mReevaluateDelayMs = INITIAL_REEVALUATE_DELAY_MS;
            mReevaluateDelayMs = INITIAL_REEVALUATE_DELAY_MS;
            mEvaluateAttempts = 0;
            mEvaluateAttempts = 0;
            // Reset all current probe results to zero, but retain current validation state until
            // validation succeeds or fails.
            mEvaluationState.clearProbeResults();
        }
        }


        @Override
        @Override
@@ -875,8 +891,7 @@ public class NetworkMonitor extends StateMachine {
                // 1. Network is connected and finish the network validation.
                // 1. Network is connected and finish the network validation.
                // 2. NetworkMonitor detects network is partial connectivity and user accepts it.
                // 2. NetworkMonitor detects network is partial connectivity and user accepts it.
                case EVENT_ACCEPT_PARTIAL_CONNECTIVITY:
                case EVENT_ACCEPT_PARTIAL_CONNECTIVITY:
                    mAcceptPartialConnectivity = true;
                    maybeDisableHttpsProbing(true /* acceptPartial */);
                    mUseHttps = false;
                    transitionTo(mEvaluatingPrivateDnsState);
                    transitionTo(mEvaluatingPrivateDnsState);
                    return HANDLED;
                    return HANDLED;
                default:
                default:
@@ -1019,6 +1034,8 @@ public class NetworkMonitor extends StateMachine {
                mPrivateDnsConfig = null;
                mPrivateDnsConfig = null;
                validationLog("Strict mode hostname resolution failed: " + uhe.getMessage());
                validationLog("Strict mode hostname resolution failed: " + uhe.getMessage());
            }
            }
            mEvaluationState.reportProbeResult(NETWORK_VALIDATION_PROBE_PRIVDNS,
                    (mPrivateDnsConfig != null) /* succeeded */);
        }
        }


        private void notifyPrivateDnsConfigResolved() {
        private void notifyPrivateDnsConfigResolved() {
@@ -1030,8 +1047,8 @@ public class NetworkMonitor extends StateMachine {
        }
        }


        private void handlePrivateDnsEvaluationFailure() {
        private void handlePrivateDnsEvaluationFailure() {
            notifyNetworkTested(NETWORK_TEST_RESULT_INVALID, null);
            mEvaluationState.reportEvaluationResult(NETWORK_VALIDATION_RESULT_INVALID,

                    null /* redirectUrl */);
            // Queue up a re-evaluation with backoff.
            // Queue up a re-evaluation with backoff.
            //
            //
            // TODO: Consider abandoning this state after a few attempts and
            // TODO: Consider abandoning this state after a few attempts and
@@ -1050,21 +1067,22 @@ public class NetworkMonitor extends StateMachine {
            final String host = UUID.randomUUID().toString().substring(0, 8)
            final String host = UUID.randomUUID().toString().substring(0, 8)
                    + oneTimeHostnameSuffix;
                    + oneTimeHostnameSuffix;
            final Stopwatch watch = new Stopwatch().start();
            final Stopwatch watch = new Stopwatch().start();
            boolean success = false;
            long time;
            try {
            try {
                final InetAddress[] ips = mNetwork.getAllByName(host);
                final InetAddress[] ips = mNetwork.getAllByName(host);
                final long time = watch.stop();
                time = watch.stop();
                final String strIps = Arrays.toString(ips);
                final String strIps = Arrays.toString(ips);
                final boolean success = (ips != null && ips.length > 0);
                success = (ips != null && ips.length > 0);
                validationLog(PROBE_PRIVDNS, host, String.format("%dms: %s", time, strIps));
                validationLog(PROBE_PRIVDNS, host, String.format("%dms: %s", time, strIps));
                logValidationProbe(time, PROBE_PRIVDNS, success ? DNS_SUCCESS : DNS_FAILURE);
                return success;
            } catch (UnknownHostException uhe) {
            } catch (UnknownHostException uhe) {
                final long time = watch.stop();
                time = watch.stop();
                validationLog(PROBE_PRIVDNS, host,
                validationLog(PROBE_PRIVDNS, host,
                        String.format("%dms - Error: %s", time, uhe.getMessage()));
                        String.format("%dms - Error: %s", time, uhe.getMessage()));
                logValidationProbe(time, PROBE_PRIVDNS, DNS_FAILURE);
            }
            }
            return false;
            logValidationProbe(time, PROBE_PRIVDNS, success ? DNS_SUCCESS : DNS_FAILURE);
            mEvaluationState.reportProbeResult(NETWORK_VALIDATION_PROBE_PRIVDNS, success);
            return success;
        }
        }
    }
    }


@@ -1106,22 +1124,24 @@ public class NetworkMonitor extends StateMachine {
                        // state (even if no Private DNS validation required).
                        // state (even if no Private DNS validation required).
                        transitionTo(mEvaluatingPrivateDnsState);
                        transitionTo(mEvaluatingPrivateDnsState);
                    } else if (probeResult.isPortal()) {
                    } else if (probeResult.isPortal()) {
                        notifyNetworkTested(NETWORK_TEST_RESULT_INVALID, probeResult.redirectUrl);
                        mEvaluationState.reportEvaluationResult(NETWORK_VALIDATION_RESULT_INVALID,
                                probeResult.redirectUrl);
                        mLastPortalProbeResult = probeResult;
                        mLastPortalProbeResult = probeResult;
                        transitionTo(mCaptivePortalState);
                        transitionTo(mCaptivePortalState);
                    } else if (probeResult.isPartialConnectivity()) {
                    } else if (probeResult.isPartialConnectivity()) {
                        logNetworkEvent(NetworkEvent.NETWORK_PARTIAL_CONNECTIVITY);
                        mEvaluationState.reportEvaluationResult(NETWORK_VALIDATION_RESULT_PARTIAL,
                        notifyNetworkTested(NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY,
                                null /* redirectUrl */);
                                probeResult.redirectUrl);
                        // Check if disable https probing needed.
                        maybeDisableHttpsProbing(mAcceptPartialConnectivity);
                        if (mAcceptPartialConnectivity) {
                        if (mAcceptPartialConnectivity) {
                            mUseHttps = false;
                            transitionTo(mEvaluatingPrivateDnsState);
                            transitionTo(mEvaluatingPrivateDnsState);
                        } else {
                        } else {
                            transitionTo(mWaitingForNextProbeState);
                            transitionTo(mWaitingForNextProbeState);
                        }
                        }
                    } else {
                    } else {
                        logNetworkEvent(NetworkEvent.NETWORK_VALIDATION_FAILED);
                        logNetworkEvent(NetworkEvent.NETWORK_VALIDATION_FAILED);
                        notifyNetworkTested(NETWORK_TEST_RESULT_INVALID, probeResult.redirectUrl);
                        mEvaluationState.reportEvaluationResult(NETWORK_VALIDATION_RESULT_INVALID,
                                null /* redirectUrl */);
                        transitionTo(mWaitingForNextProbeState);
                        transitionTo(mWaitingForNextProbeState);
                    }
                    }
                    return HANDLED;
                    return HANDLED;
@@ -1469,10 +1489,13 @@ public class NetworkMonitor extends StateMachine {
        final CaptivePortalProbeResult result;
        final CaptivePortalProbeResult result;
        if (pacUrl != null) {
        if (pacUrl != null) {
            result = sendDnsAndHttpProbes(null, pacUrl, ValidationProbeEvent.PROBE_PAC);
            result = sendDnsAndHttpProbes(null, pacUrl, ValidationProbeEvent.PROBE_PAC);
            reportHttpProbeResult(NETWORK_VALIDATION_PROBE_HTTP, result);
        } else if (mUseHttps) {
        } else if (mUseHttps) {
            // Probe results are reported inside sendParallelHttpProbes.
            result = sendParallelHttpProbes(proxyInfo, httpsUrl, httpUrl);
            result = sendParallelHttpProbes(proxyInfo, httpsUrl, httpUrl);
        } else {
        } else {
            result = sendDnsAndHttpProbes(proxyInfo, httpUrl, ValidationProbeEvent.PROBE_HTTP);
            result = sendDnsAndHttpProbes(proxyInfo, httpUrl, ValidationProbeEvent.PROBE_HTTP);
            reportHttpProbeResult(NETWORK_VALIDATION_PROBE_HTTP, result);
        }
        }


        long endTime = SystemClock.elapsedRealtime();
        long endTime = SystemClock.elapsedRealtime();
@@ -1484,6 +1507,7 @@ public class NetworkMonitor extends StateMachine {
        log("isCaptivePortal: isSuccessful()=" + result.isSuccessful()
        log("isCaptivePortal: isSuccessful()=" + result.isSuccessful()
                + " isPortal()=" + result.isPortal()
                + " isPortal()=" + result.isPortal()
                + " RedirectUrl=" + result.redirectUrl
                + " RedirectUrl=" + result.redirectUrl
                + " isPartialConnectivity()=" + result.isPartialConnectivity()
                + " Time=" + (endTime - startTime) + "ms");
                + " Time=" + (endTime - startTime) + "ms");


        return result;
        return result;
@@ -1498,6 +1522,10 @@ public class NetworkMonitor extends StateMachine {
        // Only do this if HttpURLConnection is about to, to avoid any potentially
        // Only do this if HttpURLConnection is about to, to avoid any potentially
        // unnecessary resolution.
        // unnecessary resolution.
        final String host = (proxy != null) ? proxy.getHost() : url.getHost();
        final String host = (proxy != null) ? proxy.getHost() : url.getHost();
        // This method cannot safely report probe results because it might not be running on the
        // state machine thread. Reporting results here would cause races and potentially send
        // information to callers that does not make sense because the state machine has already
        // changed state.
        sendDnsProbe(host);
        sendDnsProbe(host);
        return sendHttpProbe(url, probeType, null);
        return sendHttpProbe(url, probeType, null);
    }
    }
@@ -1682,10 +1710,12 @@ public class NetworkMonitor extends StateMachine {


        // Look for a conclusive probe result first.
        // Look for a conclusive probe result first.
        if (httpResult.isPortal()) {
        if (httpResult.isPortal()) {
            reportHttpProbeResult(NETWORK_VALIDATION_PROBE_HTTP, httpResult);
            return httpResult;
            return httpResult;
        }
        }
        // httpsResult.isPortal() is not expected, but check it nonetheless.
        // httpsResult.isPortal() is not expected, but check it nonetheless.
        if (httpsResult.isPortal() || httpsResult.isSuccessful()) {
        if (httpsResult.isPortal() || httpsResult.isSuccessful()) {
            reportHttpProbeResult(NETWORK_VALIDATION_PROBE_HTTPS, httpsResult);
            return httpsResult;
            return httpsResult;
        }
        }
        // If a fallback method exists, use it to retry portal detection.
        // If a fallback method exists, use it to retry portal detection.
@@ -1695,6 +1725,7 @@ public class NetworkMonitor extends StateMachine {
        CaptivePortalProbeResult fallbackProbeResult = null;
        CaptivePortalProbeResult fallbackProbeResult = null;
        if (fallbackUrl != null) {
        if (fallbackUrl != null) {
            fallbackProbeResult = sendHttpProbe(fallbackUrl, PROBE_FALLBACK, probeSpec);
            fallbackProbeResult = sendHttpProbe(fallbackUrl, PROBE_FALLBACK, probeSpec);
            reportHttpProbeResult(NETWORK_VALIDATION_PROBE_FALLBACK, fallbackProbeResult);
            if (fallbackProbeResult.isPortal()) {
            if (fallbackProbeResult.isPortal()) {
                return fallbackProbeResult;
                return fallbackProbeResult;
            }
            }
@@ -1702,10 +1733,15 @@ public class NetworkMonitor extends StateMachine {
        // Otherwise wait until http and https probes completes and use their results.
        // Otherwise wait until http and https probes completes and use their results.
        try {
        try {
            httpProbe.join();
            httpProbe.join();
            reportHttpProbeResult(NETWORK_VALIDATION_PROBE_HTTP, httpProbe.result());

            if (httpProbe.result().isPortal()) {
            if (httpProbe.result().isPortal()) {
                return httpProbe.result();
                return httpProbe.result();
            }
            }

            httpsProbe.join();
            httpsProbe.join();
            reportHttpProbeResult(NETWORK_VALIDATION_PROBE_HTTPS, httpsProbe.result());

            final boolean isHttpSuccessful =
            final boolean isHttpSuccessful =
                    (httpProbe.result().isSuccessful()
                    (httpProbe.result().isSuccessful()
                    || (fallbackProbeResult != null && fallbackProbeResult.isSuccessful()));
                    || (fallbackProbeResult != null && fallbackProbeResult.isSuccessful()));
@@ -2024,4 +2060,79 @@ public class NetworkMonitor extends StateMachine {


        return result;
        return result;
    }
    }

    // Class to keep state of evaluation results and probe results.
    // The main purpose is to ensure NetworkMonitor can notify ConnectivityService of probe results
    // as soon as they happen, without triggering any other changes. This requires keeping state on
    // the most recent evaluation result. Calling reportProbeResult will ensure that the results
    // reported to ConnectivityService contain the previous evaluation result, and thus won't
    // trigger a validation or partial connectivity state change.
    @VisibleForTesting
    protected class EvaluationState {
        // The latest validation result for this network. This is a bitmask of
        // INetworkMonitor.NETWORK_VALIDATION_RESULT_* constants.
        private int mEvaluationResult = NETWORK_VALIDATION_RESULT_INVALID;
        // Indicates which probes have completed since clearProbeResults was called.
        // This is a bitmask of INetworkMonitor.NETWORK_VALIDATION_PROBE_* constants.
        private int mProbeResults = 0;
        // The latest redirect URL.
        private String mRedirectUrl;

        protected void clearProbeResults() {
            mProbeResults = 0;
        }

        // Probe result for http probe should be updated from reportHttpProbeResult().
        protected void reportProbeResult(int probeResult, boolean succeeded) {
            if (succeeded) {
                mProbeResults |= probeResult;
            } else {
                mProbeResults &= ~probeResult;
            }
            notifyNetworkTested(getNetworkTestResult(), mRedirectUrl);
        }

        protected void reportEvaluationResult(int result, @Nullable String redirectUrl) {
            mEvaluationResult = result;
            mRedirectUrl = redirectUrl;
            notifyNetworkTested(getNetworkTestResult(), mRedirectUrl);
        }

        protected int getNetworkTestResult() {
            return mEvaluationResult | mProbeResults;
        }
    }

    @VisibleForTesting
    protected EvaluationState getEvaluationState() {
        return mEvaluationState;
    }

    private void maybeDisableHttpsProbing(boolean acceptPartial) {
        mAcceptPartialConnectivity = acceptPartial;
        // Ignore https probe in next validation if user accept partial connectivity on a partial
        // connectivity network.
        if (((mEvaluationState.getNetworkTestResult() & NETWORK_VALIDATION_RESULT_PARTIAL) != 0)
                && mAcceptPartialConnectivity) {
            mUseHttps = false;
        }
    }

    // Report HTTP, HTTP or FALLBACK probe result.
    @VisibleForTesting
    protected void reportHttpProbeResult(int probeResult,
                @NonNull final CaptivePortalProbeResult result) {
        boolean succeeded = result.isSuccessful();
        // The success of a HTTP probe does not tell us whether the DNS probe succeeded.
        // The DNS and HTTP probes run one after the other in sendDnsAndHttpProbes, and that
        // method cannot report the result of the DNS probe because that it could be running
        // on a different thread which is racing with the main state machine thread. So, if
        // an HTTP or HTTPS probe succeeded, assume that the DNS probe succeeded. But if an
        // HTTP or HTTPS probe failed, don't assume that DNS is not working.
        // TODO: fix this.
        if (succeeded) {
            probeResult |= NETWORK_VALIDATION_PROBE_DNS;
        }
        mEvaluationState.reportProbeResult(probeResult, succeeded);
    }
}
}
+179 −44

File changed.

Preview size limit exceeded, changes collapsed.

+14 −18
Original line number Original line Diff line number Diff line
@@ -25,8 +25,8 @@ import static android.net.ConnectivityManager.TYPE_NONE;
import static android.net.ConnectivityManager.TYPE_VPN;
import static android.net.ConnectivityManager.TYPE_VPN;
import static android.net.ConnectivityManager.getNetworkTypeName;
import static android.net.ConnectivityManager.getNetworkTypeName;
import static android.net.ConnectivityManager.isNetworkTypeValid;
import static android.net.ConnectivityManager.isNetworkTypeValid;
import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL;
import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_VALID;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID;
import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
@@ -2605,21 +2605,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
                    final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2);
                    final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2);
                    if (nai == null) break;
                    if (nai == null) break;


                    final boolean partialConnectivity =
                    final boolean wasPartial = nai.partialConnectivity;
                            (msg.arg1 == NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY)
                    nai.partialConnectivity = ((msg.arg1 & NETWORK_VALIDATION_RESULT_PARTIAL) != 0);
                                    || (nai.networkMisc.acceptPartialConnectivity
                                            && nai.partialConnectivity);
                    // Once a network is determined to have partial connectivity, it cannot
                    // go back to full connectivity without a disconnect. This is because
                    // NetworkMonitor can only communicate either PARTIAL_CONNECTIVITY or VALID,
                    // but not both.
                    // TODO: Provide multi-testResult to improve the communication between
                    // ConnectivityService and NetworkMonitor, so that ConnectivityService could
                    // know the real status of network.
                    final boolean partialConnectivityChanged =
                    final boolean partialConnectivityChanged =
                            (partialConnectivity && !nai.partialConnectivity);
                            (wasPartial != nai.partialConnectivity);


                    final boolean valid = (msg.arg1 == NETWORK_TEST_RESULT_VALID);
                    final boolean valid = ((msg.arg1 & NETWORK_VALIDATION_RESULT_VALID) != 0);
                    final boolean wasValidated = nai.lastValidated;
                    final boolean wasValidated = nai.lastValidated;
                    final boolean wasDefault = isDefaultNetwork(nai);
                    final boolean wasDefault = isDefaultNetwork(nai);
                    if (nai.everCaptivePortalDetected && !nai.captivePortalLoginNotified
                    if (nai.everCaptivePortalDetected && !nai.captivePortalLoginNotified
@@ -2649,21 +2640,23 @@ public class ConnectivityService extends IConnectivityManager.Stub
                        if (oldScore != nai.getCurrentScore()) sendUpdatedScoreToFactories(nai);
                        if (oldScore != nai.getCurrentScore()) sendUpdatedScoreToFactories(nai);
                        if (valid) {
                        if (valid) {
                            handleFreshlyValidatedNetwork(nai);
                            handleFreshlyValidatedNetwork(nai);
                            // Clear NO_INTERNET and LOST_INTERNET notifications if network becomes
                            // Clear NO_INTERNET, PARTIAL_CONNECTIVITY and LOST_INTERNET
                            // valid.
                            // notifications if network becomes valid.
                            mNotifier.clearNotification(nai.network.netId,
                            mNotifier.clearNotification(nai.network.netId,
                                    NotificationType.NO_INTERNET);
                                    NotificationType.NO_INTERNET);
                            mNotifier.clearNotification(nai.network.netId,
                            mNotifier.clearNotification(nai.network.netId,
                                    NotificationType.LOST_INTERNET);
                                    NotificationType.LOST_INTERNET);
                            mNotifier.clearNotification(nai.network.netId,
                                    NotificationType.PARTIAL_CONNECTIVITY);
                        }
                        }
                    } else if (partialConnectivityChanged) {
                    } else if (partialConnectivityChanged) {
                        nai.partialConnectivity = partialConnectivity;
                        updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities);
                        updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities);
                    }
                    }
                    updateInetCondition(nai);
                    updateInetCondition(nai);
                    // Let the NetworkAgent know the state of its network
                    // Let the NetworkAgent know the state of its network
                    Bundle redirectUrlBundle = new Bundle();
                    Bundle redirectUrlBundle = new Bundle();
                    redirectUrlBundle.putString(NetworkAgent.REDIRECT_URL_KEY, redirectUrl);
                    redirectUrlBundle.putString(NetworkAgent.REDIRECT_URL_KEY, redirectUrl);
                    // TODO: Evaluate to update partial connectivity to status to NetworkAgent.
                    nai.asyncChannel.sendMessage(
                    nai.asyncChannel.sendMessage(
                            NetworkAgent.CMD_REPORT_NETWORK_STATUS,
                            NetworkAgent.CMD_REPORT_NETWORK_STATUS,
                            (valid ? NetworkAgent.VALID_NETWORK : NetworkAgent.INVALID_NETWORK),
                            (valid ? NetworkAgent.VALID_NETWORK : NetworkAgent.INVALID_NETWORK),
@@ -3443,6 +3436,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
            // Inform NetworkMonitor that partial connectivity is acceptable. This will likely
            // Inform NetworkMonitor that partial connectivity is acceptable. This will likely
            // result in a partial connectivity result which will be processed by
            // result in a partial connectivity result which will be processed by
            // maybeHandleNetworkMonitorMessage.
            // maybeHandleNetworkMonitorMessage.
            //
            // TODO: NetworkMonitor does not refer to the "never ask again" bit. The bit is stored
            // per network. Therefore, NetworkMonitor may still do https probe.
            try {
            try {
                nai.networkMonitor().setAcceptPartialConnectivity();
                nai.networkMonitor().setAcceptPartialConnectivity();
            } catch (RemoteException e) {
            } catch (RemoteException e) {
+75 −9

File changed.

Preview size limit exceeded, changes collapsed.