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

Commit 2dd63972 authored by android-build-team Robot's avatar android-build-team Robot
Browse files

Snap for 6549158 from bd7a0158 to sc-release

Change-Id: I0a2f66ce8004fd8868ce49cfb61037f12cfac586
parents e6d6aa09 bd7a0158
Loading
Loading
Loading
Loading
+20 −2
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.networkstack;

import static android.app.NotificationManager.IMPORTANCE_NONE;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
@@ -142,7 +144,19 @@ public class NetworkStackNotifier {
                resources.getString(title),
                importance);
        channel.setDescription(resources.getString(description));
        mNotificationManager.createNotificationChannel(channel);
        getNotificationManagerForChannels().createNotificationChannel(channel);
    }

    /**
     * Get the NotificationManager to use to query channels, as opposed to posting notifications.
     *
     * Although notifications are posted as USER_ALL, notification channels are always created
     * based on the UID calling NotificationManager, regardless of the context UserHandle.
     * When querying notification channels, using a USER_ALL context would return no channel: the
     * default context (as UserHandle 0 for NetworkStack) must be used.
     */
    private NotificationManager getNotificationManagerForChannels() {
        return mContext.getSystemService(NotificationManager.class);
    }

    /**
@@ -284,7 +298,11 @@ public class NetworkStackNotifier {
    }

    private boolean isVenueInfoNotificationEnabled() {
        return mNotificationManager.getNotificationChannel(CHANNEL_VENUE_INFO) != null;
        final NotificationChannel channel = getNotificationManagerForChannels()
                .getNotificationChannel(CHANNEL_VENUE_INFO);
        if (channel == null) return false;

        return channel.getImportance() != IMPORTANCE_NONE;
    }

    private static String getNotificationTag(@NonNull Network network) {
+2 −2
Original line number Diff line number Diff line
@@ -194,9 +194,9 @@ public final class DataStallDetectionStats {
        }

        /**
         * Set the dns evaluation type into Builder.
         * Set the data stall evaluation type into Builder.
         *
         * @param type the return code of the dns event.
         * @param type the signal type causing a data stall to be suspected.
         * @return {@code this} {@link Builder} instance.
         */
        public Builder setEvaluationType(int type) {
+30 −27
Original line number Diff line number Diff line
@@ -1436,7 +1436,7 @@ public class NetworkMonitor extends StateMachine {
            }

            final int token = ++mProbeToken;
            final EvaluationThreadDeps deps = new EvaluationThreadDeps(mNetworkCapabilities);
            final ValidationProperties deps = new ValidationProperties(mNetworkCapabilities);
            mThread = new Thread(() -> sendMessage(obtainMessage(CMD_PROBE_COMPLETE, token, 0,
                    isCaptivePortal(deps))));
            mThread.start();
@@ -2151,24 +2151,24 @@ public class NetworkMonitor extends StateMachine {
    }

    /**
     * Parameters that can be accessed by the evaluation thread in a thread-safe way.
     * Validation properties that can be accessed by the evaluation thread in a thread-safe way.
     *
     * Parameters such as LinkProperties and NetworkCapabilities cannot be accessed by the
     * evaluation thread directly, as they are managed in the state machine thread and not
     * synchronized. This class provides a copy of the required data that is not modified and can be
     * used safely by the evaluation thread.
     */
    private static class EvaluationThreadDeps {
        // TODO: add parameters that are accessed in a non-thread-safe way from the evaluation
        // thread (read from LinkProperties, NetworkCapabilities, useHttps, validationStage)
    private static class ValidationProperties {
        // TODO: add other properties that are needed for evaluation and currently extracted in a
        // non-thread-safe way from LinkProperties, NetworkCapabilities, etc.
        private final boolean mIsTestNetwork;

        EvaluationThreadDeps(NetworkCapabilities nc) {
        ValidationProperties(NetworkCapabilities nc) {
            this.mIsTestNetwork = nc.hasTransport(TRANSPORT_TEST);
        }
    }

    private CaptivePortalProbeResult isCaptivePortal(EvaluationThreadDeps deps) {
    private CaptivePortalProbeResult isCaptivePortal(ValidationProperties properties) {
        if (!mIsCaptivePortalCheckEnabled) {
            validationLog("Validation disabled.");
            return CaptivePortalProbeResult.success(CaptivePortalProbeResult.PROBE_UNKNOWN);
@@ -2216,11 +2216,12 @@ public class NetworkMonitor extends StateMachine {
            reportHttpProbeResult(NETWORK_VALIDATION_PROBE_HTTP, result);
        } else if (mUseHttps && httpsUrls.length == 1 && httpUrls.length == 1) {
            // Probe results are reported inside sendHttpAndHttpsParallelWithFallbackProbes.
            result = sendHttpAndHttpsParallelWithFallbackProbes(deps, proxyInfo,
            result = sendHttpAndHttpsParallelWithFallbackProbes(properties, proxyInfo,
                    httpsUrls[0], httpUrls[0]);
        } else if (mUseHttps) {
            // Support result aggregation from multiple Urls.
            result = sendMultiParallelHttpAndHttpsProbes(deps, proxyInfo, httpsUrls, httpUrls);
            result = sendMultiParallelHttpAndHttpsProbes(properties, proxyInfo, httpsUrls,
                    httpUrls);
        } else {
            result = sendDnsAndHttpProbes(proxyInfo, httpUrls[0], ValidationProbeEvent.PROBE_HTTP);
            reportHttpProbeResult(NETWORK_VALIDATION_PROBE_HTTP, result);
@@ -2502,12 +2503,12 @@ public class NetworkMonitor extends StateMachine {
        private final CountDownLatch mLatch;
        private final Probe mProbe;

        ProbeThread(CountDownLatch latch, EvaluationThreadDeps deps, ProxyInfo proxy, URL url,
        ProbeThread(CountDownLatch latch, ValidationProperties properties, ProxyInfo proxy, URL url,
                int probeType, Uri captivePortalApiUrl) {
            mLatch = latch;
            mProbe = (probeType == ValidationProbeEvent.PROBE_HTTPS)
                    ? new HttpsProbe(deps, proxy, url, captivePortalApiUrl)
                    : new HttpProbe(deps, proxy, url, captivePortalApiUrl);
                    ? new HttpsProbe(properties, proxy, url, captivePortalApiUrl)
                    : new HttpProbe(properties, proxy, url, captivePortalApiUrl);
            mResult = CaptivePortalProbeResult.failed(probeType);
        }

@@ -2532,14 +2533,14 @@ public class NetworkMonitor extends StateMachine {
    }

    private abstract static class Probe {
        protected final EvaluationThreadDeps mDeps;
        protected final ValidationProperties mProperties;
        protected final ProxyInfo mProxy;
        protected final URL mUrl;
        protected final Uri mCaptivePortalApiUrl;

        protected Probe(EvaluationThreadDeps deps, ProxyInfo proxy, URL url,
        protected Probe(ValidationProperties properties, ProxyInfo proxy, URL url,
                Uri captivePortalApiUrl) {
            mDeps = deps;
            mProperties = properties;
            mProxy = proxy;
            mUrl = url;
            mCaptivePortalApiUrl = captivePortalApiUrl;
@@ -2549,8 +2550,9 @@ public class NetworkMonitor extends StateMachine {
    }

    final class HttpsProbe extends Probe {
        HttpsProbe(EvaluationThreadDeps deps, ProxyInfo proxy, URL url, Uri captivePortalApiUrl) {
            super(deps, proxy, url, captivePortalApiUrl);
        HttpsProbe(ValidationProperties properties, ProxyInfo proxy, URL url,
                Uri captivePortalApiUrl) {
            super(properties, proxy, url, captivePortalApiUrl);
        }

        @Override
@@ -2560,8 +2562,9 @@ public class NetworkMonitor extends StateMachine {
    }

    final class HttpProbe extends Probe {
        HttpProbe(EvaluationThreadDeps deps, ProxyInfo proxy, URL url, Uri captivePortalApiUrl) {
            super(deps, proxy, url, captivePortalApiUrl);
        HttpProbe(ValidationProperties properties, ProxyInfo proxy, URL url,
                Uri captivePortalApiUrl) {
            super(properties, proxy, url, captivePortalApiUrl);
        }

        private CaptivePortalDataShim tryCapportApiProbe() {
@@ -2574,7 +2577,7 @@ public class NetworkMonitor extends StateMachine {
                // Protocol must be HTTPS
                // (as per https://www.ietf.org/id/draft-ietf-capport-api-07.txt, #4).
                // Only allow HTTP on localhost, for testing.
                final boolean isTestLocalhostHttp = mDeps.mIsTestNetwork
                final boolean isTestLocalhostHttp = mProperties.mIsTestNetwork
                        && "localhost".equals(url.getHost()) && "http".equals(url.getProtocol());
                if (!"https".equals(url.getProtocol()) && !isTestLocalhostHttp) {
                    validationLog("Invalid captive portal API protocol: " + url.getProtocol());
@@ -2660,8 +2663,8 @@ public class NetworkMonitor extends StateMachine {
    }

    private CaptivePortalProbeResult sendMultiParallelHttpAndHttpsProbes(
            @NonNull EvaluationThreadDeps deps, @Nullable ProxyInfo proxy, @NonNull URL[] httpsUrls,
            @NonNull URL[] httpUrls) {
            @NonNull ValidationProperties properties, @Nullable ProxyInfo proxy,
            @NonNull URL[] httpsUrls, @NonNull URL[] httpUrls) {
        // If multiple URLs are required to ensure the correctness of validation, send parallel
        // probes to explore the result in separate probe threads and aggregate those results into
        // one as the final result for either HTTP or HTTPS.
@@ -2686,12 +2689,12 @@ public class NetworkMonitor extends StateMachine {
            // TODO: Have the capport probe as a different probe for cleanliness.
            final URL urlMaybeWithCapport = httpUrls[0];
            for (final URL url : httpUrls) {
                futures.add(ecs.submit(() -> new HttpProbe(deps, proxy, url,
                futures.add(ecs.submit(() -> new HttpProbe(properties, proxy, url,
                        url.equals(urlMaybeWithCapport) ? capportApiUrl : null).sendProbe()));
            }

            for (final URL url : httpsUrls) {
                futures.add(ecs.submit(() -> new HttpsProbe(deps, proxy, url, capportApiUrl)
                futures.add(ecs.submit(() -> new HttpsProbe(properties, proxy, url, capportApiUrl)
                        .sendProbe()));
            }

@@ -2788,15 +2791,15 @@ public class NetworkMonitor extends StateMachine {
    }

    private CaptivePortalProbeResult sendHttpAndHttpsParallelWithFallbackProbes(
            EvaluationThreadDeps deps, ProxyInfo proxy, URL httpsUrl, URL httpUrl) {
            ValidationProperties properties, ProxyInfo proxy, URL httpsUrl, URL httpUrl) {
        // Number of probes to wait for. If a probe completes with a conclusive answer
        // it shortcuts the latch immediately by forcing the count to 0.
        final CountDownLatch latch = new CountDownLatch(2);

        final Uri capportApiUrl = getCaptivePortalApiUrl(mLinkProperties);
        final ProbeThread httpsProbe = new ProbeThread(latch, deps, proxy, httpsUrl,
        final ProbeThread httpsProbe = new ProbeThread(latch, properties, proxy, httpsUrl,
                ValidationProbeEvent.PROBE_HTTPS, capportApiUrl);
        final ProbeThread httpProbe = new ProbeThread(latch, deps, proxy, httpUrl,
        final ProbeThread httpProbe = new ProbeThread(latch, properties, proxy, httpUrl,
                ValidationProbeEvent.PROBE_HTTP, capportApiUrl);

        try {
+8 −2
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.NotificationManager.IMPORTANCE_DEFAULT
import android.app.NotificationManager.IMPORTANCE_NONE
import android.app.PendingIntent
import android.app.PendingIntent.FLAG_UPDATE_CURRENT
import android.content.Context
@@ -80,6 +81,8 @@ class NetworkStackNotifierTest {
    @Mock
    private lateinit var mNm: NotificationManager
    @Mock
    private lateinit var mNotificationChannelsNm: NotificationManager
    @Mock
    private lateinit var mCm: ConnectivityManager
    @Mock
    private lateinit var mResources: Resources
@@ -141,10 +144,12 @@ class NetworkStackNotifierTest {
                realContext.packageName, 0, UserHandle.ALL)

        mAllUserContext.mockService(Context.NOTIFICATION_SERVICE, NotificationManager::class, mNm)
        mContext.mockService(Context.NOTIFICATION_SERVICE, NotificationManager::class,
                mNotificationChannelsNm)
        mContext.mockService(Context.CONNECTIVITY_SERVICE, ConnectivityManager::class, mCm)

        doReturn(NotificationChannel(CHANNEL_VENUE_INFO, "TestChannel", IMPORTANCE_DEFAULT))
                .`when`(mNm).getNotificationChannel(CHANNEL_VENUE_INFO)
                .`when`(mNotificationChannelsNm).getNotificationChannel(CHANNEL_VENUE_INFO)

        doReturn(mPendingIntent).`when`(mDependencies).getActivityPendingIntent(
                any(), any(), anyInt())
@@ -247,7 +252,8 @@ class NetworkStackNotifierTest {
    fun testConnectedVenueInfoNotification_VenueInfoDisabled() {
        // Venue info (CaptivePortalData) is not available for API <= Q
        assumeTrue(NetworkInformationShimImpl.useApiAboveQ())
        doReturn(null).`when`(mNm).getNotificationChannel(CHANNEL_VENUE_INFO)
        val channel = NotificationChannel(CHANNEL_VENUE_INFO, "test channel", IMPORTANCE_NONE)
        doReturn(channel).`when`(mNotificationChannelsNm).getNotificationChannel(CHANNEL_VENUE_INFO)
        mNotifier.notifyCaptivePortalValidationPending(TEST_NETWORK)
        onLinkPropertiesChanged(mTestCapportLp)
        onDefaultNetworkAvailable(TEST_NETWORK)
+2 −1
Original line number Diff line number Diff line
@@ -1117,7 +1117,8 @@ public class NetworkMonitorTest {

        // Second check should be triggered automatically after the reevaluate delay, and uses the
        // URL chosen by mRandom
        // This test is appropriate to cover reevaluate behavior as long as the timeout is short
        // Ensure that the reevaluate delay is not changed to a large value, otherwise this test
        // would block for too long and a different test strategy should be used.
        assertTrue(INITIAL_REEVALUATE_DELAY_MS < 2000);
        verify(mOtherFallbackConnection, timeout(INITIAL_REEVALUATE_DELAY_MS + HANDLER_TIMEOUT_MS))
                .getResponseCode();