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

Commit 91aa5bc4 authored by Remi NGUYEN VAN's avatar Remi NGUYEN VAN
Browse files

Send LinkProperties update on new capport data

When new CaptivePortalData is received from NetworkMonitor, send a
LinkProperties updated callback.
The updated LinkProperties only contain CaptivePortalData if the
receiver has NETWORK_SETTINGS or MAINLINE_NETWORK_STACK permissions, as
defined in the current callback code.

Test: atest FrameworksNetTests
Bug: 139269711

Change-Id: I68595a519171b31792259849efff5f58c43cacd4
parent 3819be42
Loading
Loading
Loading
Loading
+33 −0
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ import android.content.IntentFilter;
import android.content.res.Configuration;
import android.database.ContentObserver;
import android.net.CaptivePortal;
import android.net.CaptivePortalData;
import android.net.ConnectionInfo;
import android.net.ConnectivityDiagnosticsManager.ConnectivityReport;
import android.net.ConnectivityDiagnosticsManager.DataStallReport;
@@ -547,6 +548,14 @@ public class ConnectivityService extends IConnectivityManager.Stub
     */
    public static final int EVENT_PROBE_STATUS_CHANGED = 46;

    /**
     * Event for NetworkMonitor to inform ConnectivityService that captive portal data has changed.
     * arg1 = unused
     * arg2 = netId
     * obj = captive portal data
     */
    private static final int EVENT_CAPPORT_DATA_CHANGED = 47;

    /**
     * Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification
     * should be shown.
@@ -2817,6 +2826,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
                    updatePrivateDns(nai, (PrivateDnsConfig) msg.obj);
                    break;
                }
                case EVENT_CAPPORT_DATA_CHANGED: {
                    final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2);
                    if (nai == null) break;
                    handleCaptivePortalDataUpdate(nai, (CaptivePortalData) msg.obj);
                    break;
                }
            }
            return true;
        }
@@ -2983,6 +2998,13 @@ public class ConnectivityService extends IConnectivityManager.Stub
                    probesCompleted, probesSucceeded, new Integer(mNetId)));
        }

        @Override
        public void notifyCaptivePortalDataChanged(CaptivePortalData data) {
            mTrackerHandler.sendMessage(mTrackerHandler.obtainMessage(
                    EVENT_CAPPORT_DATA_CHANGED,
                    0, mNetId, data));
        }

        @Override
        public void showProvisioningNotification(String action, String packageName) {
            final Intent intent = new Intent(action);
@@ -3111,6 +3133,13 @@ public class ConnectivityService extends IConnectivityManager.Stub
        handleUpdateLinkProperties(nai, new LinkProperties(nai.linkProperties));
    }

    private void handleCaptivePortalDataUpdate(@NonNull final NetworkAgentInfo nai,
            @Nullable final CaptivePortalData data) {
        nai.captivePortalData = data;
        // CaptivePortalData will be merged into LinkProperties from NetworkAgentInfo
        handleUpdateLinkProperties(nai, new LinkProperties(nai.linkProperties));
    }

    /**
     * Updates the linger state from the network requests inside the NAI.
     * @param nai the agent info to update
@@ -5847,6 +5876,10 @@ public class ConnectivityService extends IConnectivityManager.Stub

        updateWakeOnLan(newLp);

        // Captive portal data is obtained from NetworkMonitor and stored in NetworkAgentInfo,
        // it is not contained in LinkProperties sent from NetworkAgents so needs to be merged here.
        newLp.setCaptivePortalData(networkAgent.captivePortalData);

        // TODO - move this check to cover the whole function
        if (!Objects.equals(newLp, oldLp)) {
            synchronized (networkAgent) {
+5 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.net.NetworkCapabilities.transportNamesOf;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.net.CaptivePortalData;
import android.net.IDnsResolver;
import android.net.INetd;
import android.net.INetworkMonitor;
@@ -167,6 +168,10 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
    // Set to true when partial connectivity was detected.
    public boolean partialConnectivity;

    // Captive portal info of the network, if any.
    // Obtained by ConnectivityService and merged into NetworkAgent-provided information.
    public CaptivePortalData captivePortalData;

    // Networks are lingered when they become unneeded as a result of their NetworkRequests being
    // satisfied by a higher-scoring network. so as to allow communication to wrap up before the
    // network is taken down.  This usually only happens to the default network. Lingering ends with
+51 −6
Original line number Diff line number Diff line
@@ -799,6 +799,14 @@ public class ConnectivityServiceTest {
            mProbesSucceeded = probesSucceeded;
        }

        void notifyCaptivePortalDataChanged(CaptivePortalData data) {
            try {
                mNmCallbacks.notifyCaptivePortalDataChanged(data);
            } catch (RemoteException e) {
                throw new AssertionError("This cannot happen", e);
            }
        }

        public String waitForRedirectUrl() {
            assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
            return mRedirectUrl;
@@ -1845,18 +1853,21 @@ public class ConnectivityServiceTest {
        final Uri capportUrl = Uri.parse("https://capport.example.com/api");
        final CaptivePortalData capportData = new CaptivePortalData.Builder()
                .setCaptive(true).build();

        final Uri expectedCapportUrl = sanitized ? null : capportUrl;
        newLp.setCaptivePortalApiUrl(capportUrl);
        newLp.setCaptivePortalData(capportData);
        mWiFiNetworkAgent.sendLinkProperties(newLp);
        callback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
                Objects.equals(expectedCapportUrl, lp.getCaptivePortalApiUrl()));
        defaultCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
                Objects.equals(expectedCapportUrl, lp.getCaptivePortalApiUrl()));

        final Uri expectedCapportUrl = sanitized ? null : capportUrl;
        final CaptivePortalData expectedCapportData = sanitized ? null : capportData;
        mWiFiNetworkAgent.notifyCaptivePortalDataChanged(capportData);
        callback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
                Objects.equals(expectedCapportUrl, lp.getCaptivePortalApiUrl())
                && Objects.equals(expectedCapportData, lp.getCaptivePortalData()));
                Objects.equals(expectedCapportData, lp.getCaptivePortalData()));
        defaultCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
                Objects.equals(expectedCapportUrl, lp.getCaptivePortalApiUrl())
                && Objects.equals(expectedCapportData, lp.getCaptivePortalData()));
                Objects.equals(expectedCapportData, lp.getCaptivePortalData()));

        final LinkProperties lp = mCm.getLinkProperties(mWiFiNetworkAgent.getNetwork());
        assertEquals(expectedCapportUrl, lp.getCaptivePortalApiUrl());
@@ -2810,6 +2821,40 @@ public class ConnectivityServiceTest {
        assertNoCallbacks(captivePortalCallback, validatedCallback);
    }

    @Test
    public void testCaptivePortalApi() throws Exception {
        mServiceContext.setPermission(
                android.Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED);

        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);
        final String redirectUrl = "http://example.com/firstPath";

        mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl, false /* isStrictMode */);
        captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);

        final CaptivePortalData testData = new CaptivePortalData.Builder()
                .setUserPortalUrl(Uri.parse(redirectUrl))
                .setBytesRemaining(12345L)
                .build();

        mWiFiNetworkAgent.notifyCaptivePortalDataChanged(testData);

        captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
                lp -> testData.equals(lp.getCaptivePortalData()));

        final LinkProperties newLps = new LinkProperties();
        newLps.setMtu(1234);
        mWiFiNetworkAgent.sendLinkProperties(newLps);
        // CaptivePortalData is not lost and unchanged when LPs are received from the NetworkAgent
        captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
                lp -> testData.equals(lp.getCaptivePortalData()) && lp.getMtu() == 1234);
    }

    private NetworkRequest.Builder newWifiRequestBuilder() {
        return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
    }