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

Commit 2c1f03ad authored by Paul Jensen's avatar Paul Jensen Committed by android-build-merger
Browse files

Merge "If Internet probe is redirected, pass redirect destination to NetworkAgent." into nyc-dev

am: 3e6a6fc6

* commit '3e6a6fc6':
  If Internet probe is redirected, pass redirect destination to NetworkAgent.

Change-Id: I4a88bca105b1fceb7dc823b8a26991235944d405
parents 908beb79 3e6a6fc6
Loading
Loading
Loading
Loading
+13 −3
Original line number Diff line number Diff line
@@ -120,12 +120,17 @@ public abstract class NetworkAgent extends Handler {
     * either a bad network configuration (no internet link) or captive portal.
     *
     * arg1 = either {@code VALID_NETWORK} or {@code INVALID_NETWORK}
     * obj = Bundle containing map from {@code REDIRECT_URL_KEY} to {@code String}
     *       representing URL that Internet probe was redirect to, if it was redirected,
     *       or mapping to {@code null} otherwise.
     */
    public static final int CMD_REPORT_NETWORK_STATUS = BASE + 7;

    public static final int VALID_NETWORK = 1;
    public static final int INVALID_NETWORK = 2;

    public static String REDIRECT_URL_KEY = "redirect URL";

     /**
     * Sent by the NetworkAgent to ConnectivityService to indicate this network was
     * explicitly selected.  This should be sent before the NetworkInfo is marked
@@ -283,11 +288,12 @@ public abstract class NetworkAgent extends Handler {
                break;
            }
            case CMD_REPORT_NETWORK_STATUS: {
                String redirectUrl = ((Bundle)msg.obj).getString(REDIRECT_URL_KEY);
                if (VDBG) {
                    log("CMD_REPORT_NETWORK_STATUS(" +
                            (msg.arg1 == VALID_NETWORK ? "VALID)" : "INVALID)"));
                            (msg.arg1 == VALID_NETWORK ? "VALID, " : "INVALID, ") + redirectUrl);
                }
                networkStatus(msg.arg1);
                networkStatus(msg.arg1, redirectUrl);
                break;
            }
            case CMD_SAVE_ACCEPT_UNVALIDATED: {
@@ -443,8 +449,12 @@ public abstract class NetworkAgent extends Handler {
     *
     * This may be called multiple times as the network status changes and may
     * generate false negatives if we lose ip connectivity before the link is torn down.
     *
     * @param status one of {@code VALID_NETWORK} or {@code INVALID_NETWORK}.
     * @param redirectUrl If the Internet probe was redirected, this is the destination it was
     *         redirected to, otherwise {@code null}.
     */
    protected void networkStatus(int status) {
    protected void networkStatus(int status, String redirectUrl) {
    }

    /**
+11 −5
Original line number Diff line number Diff line
@@ -2025,11 +2025,15 @@ public class ConnectivityService extends IConnectivityManager.Stub
                default:
                    return false;
                case NetworkMonitor.EVENT_NETWORK_TESTED: {
                    NetworkAgentInfo nai = (NetworkAgentInfo)msg.obj;
                    if (isLiveNetworkAgent(nai, msg.what)) {
                    final NetworkAgentInfo nai;
                    synchronized (mNetworkForNetId) {
                        nai = mNetworkForNetId.get(msg.arg2);
                    }
                    if (nai != null) {
                        final boolean valid =
                                (msg.arg1 == NetworkMonitor.NETWORK_TEST_RESULT_VALID);
                        if (DBG) log(nai.name() + " validation " + (valid ? " passed" : "failed"));
                        if (DBG) log(nai.name() + " validation " + (valid ? "passed" : "failed") +
                                (msg.obj == null ? "" : " with redirect to " + (String)msg.obj));
                        if (valid != nai.lastValidated) {
                            final int oldScore = nai.getCurrentScore();
                            nai.lastValidated = valid;
@@ -2040,10 +2044,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
                        }
                        updateInetCondition(nai);
                        // Let the NetworkAgent know the state of its network
                        Bundle redirectUrlBundle = new Bundle();
                        redirectUrlBundle.putString(NetworkAgent.REDIRECT_URL_KEY, (String)msg.obj);
                        nai.asyncChannel.sendMessage(
                                android.net.NetworkAgent.CMD_REPORT_NETWORK_STATUS,
                                NetworkAgent.CMD_REPORT_NETWORK_STATUS,
                                (valid ? NetworkAgent.VALID_NETWORK : NetworkAgent.INVALID_NETWORK),
                                0, null);
                                0, redirectUrlBundle);
                    }
                    break;
                }
+35 −15
Original line number Diff line number Diff line
@@ -120,8 +120,9 @@ public class NetworkMonitor extends StateMachine {

    /**
     * Inform ConnectivityService that the network has been tested.
     * obj = NetworkAgentInfo
     * obj = String representing URL that Internet probe was redirect to, if it was redirected.
     * arg1 = One of the NETWORK_TESTED_RESULT_* constants.
     * arg2 = NetID.
     */
    public static final int EVENT_NETWORK_TESTED = BASE + 2;

@@ -334,8 +335,8 @@ public class NetworkMonitor extends StateMachine {
                            mDontDisplaySigninNotification = true;
                            mUserDoesNotWant = true;
                            mConnectivityServiceHandler.sendMessage(obtainMessage(
                                    EVENT_NETWORK_TESTED, NETWORK_TEST_RESULT_INVALID, 0,
                                    mNetworkAgentInfo));
                                    EVENT_NETWORK_TESTED, NETWORK_TEST_RESULT_INVALID,
                                    mNetworkAgentInfo.network.netId, null));
                            // TODO: Should teardown network.
                            mUidResponsibleForReeval = 0;
                            transitionTo(mEvaluatingState);
@@ -358,7 +359,7 @@ public class NetworkMonitor extends StateMachine {
            CaptivePortalStateChangeEvent.logEvent(
                   CaptivePortalStateChangeEvent.NETWORK_MONITOR_VALIDATED);
            mConnectivityServiceHandler.sendMessage(obtainMessage(EVENT_NETWORK_TESTED,
                    NETWORK_TEST_RESULT_VALID, 0, mNetworkAgentInfo));
                    NETWORK_TEST_RESULT_VALID, mNetworkAgentInfo.network.netId, null));
        }

        @Override
@@ -412,6 +413,21 @@ public class NetworkMonitor extends StateMachine {
        }
    }

    /**
     * Result of calling isCaptivePortal().
     * @hide
     */
    @VisibleForTesting
    public static final class CaptivePortalProbeResult {
        final int mHttpResponseCode; // HTTP response code returned from Internet probe.
        final String mRedirectUrl;   // Redirect destination returned from Internet probe.

        public CaptivePortalProbeResult(int httpResponseCode, String redirectUrl) {
            mHttpResponseCode = httpResponseCode;
            mRedirectUrl = redirectUrl;
        }
    }

    // Being in the EvaluatingState State indicates the Network is being evaluated for internet
    // connectivity, or that the user has indicated that this network is unwanted.
    private class EvaluatingState extends State {
@@ -464,19 +480,23 @@ public class NetworkMonitor extends StateMachine {
                    // IPv6) could each take SOCKET_TIMEOUT_MS.  During this time this StateMachine
                    // will be unresponsive. isCaptivePortal() could be executed on another Thread
                    // if this is found to cause problems.
                    int httpResponseCode = isCaptivePortal();
                    CaptivePortalProbeResult probeResult = isCaptivePortal();
                    CaptivePortalCheckResultEvent.logEvent(mNetworkAgentInfo.network.netId,
                            httpResponseCode);
                    if (httpResponseCode == 204) {
                            probeResult.mHttpResponseCode);
                    if (probeResult.mHttpResponseCode == 204) {
                        transitionTo(mValidatedState);
                    } else if (httpResponseCode >= 200 && httpResponseCode <= 399) {
                    } else if (probeResult.mHttpResponseCode >= 200 &&
                            probeResult.mHttpResponseCode <= 399) {
                        mConnectivityServiceHandler.sendMessage(obtainMessage(EVENT_NETWORK_TESTED,
                                NETWORK_TEST_RESULT_INVALID, mNetworkAgentInfo.network.netId,
                                probeResult.mRedirectUrl));
                        transitionTo(mCaptivePortalState);
                    } else {
                        final Message msg = obtainMessage(CMD_REEVALUATE, ++mReevaluateToken, 0);
                        sendMessageDelayed(msg, mReevaluateDelayMs);
                        mConnectivityServiceHandler.sendMessage(obtainMessage(
                                EVENT_NETWORK_TESTED, NETWORK_TEST_RESULT_INVALID, 0,
                                mNetworkAgentInfo));
                                EVENT_NETWORK_TESTED, NETWORK_TEST_RESULT_INVALID,
                                mNetworkAgentInfo.network.netId, probeResult.mRedirectUrl));
                        if (mAttempts >= BLAME_FOR_EVALUATION_ATTEMPTS) {
                            // Don't continue to blame UID forever.
                            TrafficStats.clearThreadStatsUid();
@@ -533,8 +553,6 @@ public class NetworkMonitor extends StateMachine {

        @Override
        public void enter() {
            mConnectivityServiceHandler.sendMessage(obtainMessage(EVENT_NETWORK_TESTED,
                    NETWORK_TEST_RESULT_INVALID, 0, mNetworkAgentInfo));
            // Don't annoy user with sign-in notifications.
            if (mDontDisplaySigninNotification) return;
            // Create a CustomIntentReceiver that sends us a
@@ -639,11 +657,12 @@ public class NetworkMonitor extends StateMachine {
     * Returns HTTP response code.
     */
    @VisibleForTesting
    protected int isCaptivePortal() {
        if (!mIsCaptivePortalCheckEnabled) return 204;
    protected CaptivePortalProbeResult isCaptivePortal() {
        if (!mIsCaptivePortalCheckEnabled) return new CaptivePortalProbeResult(204, null);

        HttpURLConnection urlConnection = null;
        int httpResponseCode = 599;
        String redirectUrl = null;
        try {
            URL url = new URL(getCaptivePortalServerUrl(mContext));
            // On networks with a PAC instead of fetching a URL that should result in a 204
@@ -699,6 +718,7 @@ public class NetworkMonitor extends StateMachine {
            long requestTimestamp = SystemClock.elapsedRealtime();

            httpResponseCode = urlConnection.getResponseCode();
            redirectUrl = urlConnection.getHeaderField("location");

            // Time how long it takes to get a response to our request
            long responseTimestamp = SystemClock.elapsedRealtime();
@@ -739,7 +759,7 @@ public class NetworkMonitor extends StateMachine {
                urlConnection.disconnect();
            }
        }
        return httpResponseCode;
        return new CaptivePortalProbeResult(httpResponseCode, redirectUrl);
    }

    /**
+28 −5
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@ import android.util.LogPrinter;
import com.android.internal.util.WakeupMessage;
import com.android.server.connectivity.NetworkAgentInfo;
import com.android.server.connectivity.NetworkMonitor;
import com.android.server.connectivity.NetworkMonitor.CaptivePortalProbeResult;
import com.android.server.net.NetworkPinner;

import java.net.InetAddress;
@@ -223,11 +224,15 @@ public class ConnectivityServiceTest extends AndroidTestCase {
        private final NetworkCapabilities mNetworkCapabilities;
        private final IdleableHandlerThread mHandlerThread;
        private final ConditionVariable mDisconnected = new ConditionVariable();
        private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
        private int mScore;
        private NetworkAgent mNetworkAgent;
        private int mStartKeepaliveError = PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED;
        private int mStopKeepaliveError = PacketKeepalive.NO_KEEPALIVE;
        private Integer mExpectedKeepaliveSlot = null;
        // Contains the redirectUrl from networkStatus(). Before reading, wait for
        // mNetworkStatusReceived.
        private String mRedirectUrl;

        MockNetworkAgent(int transport) {
            final int type = transportToLegacyType(transport);
@@ -266,6 +271,12 @@ public class ConnectivityServiceTest extends AndroidTestCase {
                public void stopPacketKeepalive(Message msg) {
                    onPacketKeepaliveEvent(msg.arg1, mStopKeepaliveError);
                }

                @Override
                public void networkStatus(int status, String redirectUrl) {
                    mRedirectUrl = redirectUrl;
                    mNetworkStatusReceived.open();
                }
            };
            // Waits for the NetworkAgent to be registered, which includes the creation of the
            // NetworkMonitor.
@@ -340,13 +351,15 @@ public class ConnectivityServiceTest extends AndroidTestCase {
            if (callback != null) mCm.unregisterNetworkCallback(callback);
        }

        public void connectWithCaptivePortal() {
        public void connectWithCaptivePortal(String redirectUrl) {
            mWrappedNetworkMonitor.gen204ProbeResult = 200;
            mWrappedNetworkMonitor.gen204ProbeRedirectUrl = redirectUrl;
            connect(false);
            waitFor(new Criteria() { public boolean get() {
                NetworkCapabilities caps = mCm.getNetworkCapabilities(getNetwork());
                return caps != null && caps.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL);} });
            mWrappedNetworkMonitor.gen204ProbeResult = 500;
            mWrappedNetworkMonitor.gen204ProbeRedirectUrl = null;
        }

        public void disconnect() {
@@ -381,6 +394,11 @@ public class ConnectivityServiceTest extends AndroidTestCase {
        public void setExpectedKeepaliveSlot(Integer slot) {
            mExpectedKeepaliveSlot = slot;
        }

        public String waitForRedirectUrl() {
            assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
            return mRedirectUrl;
        }
    }

    /**
@@ -543,6 +561,7 @@ public class ConnectivityServiceTest extends AndroidTestCase {
    private class WrappedNetworkMonitor extends NetworkMonitor {
        // HTTP response code fed back to NetworkMonitor for Internet connectivity probe.
        public int gen204ProbeResult = 500;
        public String gen204ProbeRedirectUrl = null;

        public WrappedNetworkMonitor(Context context, Handler handler,
            NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest) {
@@ -550,8 +569,8 @@ public class ConnectivityServiceTest extends AndroidTestCase {
        }

        @Override
        protected int isCaptivePortal() {
            return gen204ProbeResult;
        protected CaptivePortalProbeResult isCaptivePortal() {
            return new CaptivePortalProbeResult(gen204ProbeResult, gen204ProbeRedirectUrl);
        }

        @Override
@@ -1344,8 +1363,10 @@ public class ConnectivityServiceTest extends AndroidTestCase {
        // Bring up a network with a captive portal.
        // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
        mWiFiNetworkAgent.connectWithCaptivePortal();
        String firstRedirectUrl = "http://example.com/firstPath";
        mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
        captivePortalCallback.expectCallback(CallbackState.AVAILABLE);
        assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);

        // Take down network.
        // Expect onLost callback.
@@ -1355,8 +1376,10 @@ public class ConnectivityServiceTest extends AndroidTestCase {
        // Bring up a network with a captive portal.
        // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
        mWiFiNetworkAgent.connectWithCaptivePortal();
        String secondRedirectUrl = "http://example.com/secondPath";
        mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
        captivePortalCallback.expectCallback(CallbackState.AVAILABLE);
        assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);

        // Make captive portal disappear then revalidate.
        // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.