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

Commit f9729757 authored by Mike Yu's avatar Mike Yu
Browse files

Add tests for the network blocked status change

onBlockedStatusChanged is intruduced for network blocked status.
The changes in this patch are:
  - Test onBlockedStatusChanged which tells apps whether the
    network is blocked.
  - Fixed the tests which is affected by the order changed in
    onAvailable.

Test: as follows
    - runtest frameworks-net
    - runtest -x NetworkPolicyManagerServiceTest.java
Bug: 74575553
Change-Id: I383c037ed895ef69c478dc3cff69fb1e27c42845
parent 2417859f
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -910,7 +910,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
        registerPrivateDnsSettingsCallbacks();
        registerPrivateDnsSettingsCallbacks();
    }
    }


    private Tethering makeTethering() {
    @VisibleForTesting
    protected Tethering makeTethering() {
        // TODO: Move other elements into @Overridden getters.
        // TODO: Move other elements into @Overridden getters.
        final TetheringDependencies deps = new TetheringDependencies() {
        final TetheringDependencies deps = new TetheringDependencies() {
            @Override
            @Override
+80 −0
Original line number Original line Diff line number Diff line
@@ -26,13 +26,21 @@ import static android.net.NetworkPolicy.WARNING_DISABLED;
import static android.net.NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND;
import static android.net.NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND;
import static android.net.NetworkPolicyManager.POLICY_NONE;
import static android.net.NetworkPolicyManager.POLICY_NONE;
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
import static android.net.NetworkPolicyManager.RULE_NONE;
import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
import static android.net.NetworkPolicyManager.RULE_TEMPORARY_ALLOW_METERED;
import static android.net.NetworkPolicyManager.uidPoliciesToString;
import static android.net.NetworkPolicyManager.uidPoliciesToString;
import static android.net.NetworkPolicyManager.uidRulesToString;
import static android.net.NetworkStats.IFACE_ALL;
import static android.net.NetworkStats.IFACE_ALL;
import static android.net.NetworkStats.SET_ALL;
import static android.net.NetworkStats.SET_ALL;
import static android.net.NetworkStats.TAG_ALL;
import static android.net.NetworkStats.TAG_ALL;
import static android.net.NetworkTemplate.buildTemplateMobileAll;
import static android.net.NetworkTemplate.buildTemplateMobileAll;
import static android.net.NetworkTemplate.buildTemplateWifi;
import static android.net.NetworkTemplate.buildTemplateWifi;
import static android.net.TrafficStats.MB_IN_BYTES;
import static android.net.TrafficStats.MB_IN_BYTES;
import static android.os.Process.SYSTEM_UID;
import static android.telephony.CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED;
import static android.telephony.CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED;
import static android.telephony.CarrierConfigManager.DATA_CYCLE_THRESHOLD_DISABLED;
import static android.telephony.CarrierConfigManager.DATA_CYCLE_THRESHOLD_DISABLED;
import static android.telephony.CarrierConfigManager.DATA_CYCLE_USE_PLATFORM_DEFAULT;
import static android.telephony.CarrierConfigManager.DATA_CYCLE_USE_PLATFORM_DEFAULT;
@@ -125,6 +133,7 @@ import android.text.TextUtils;
import android.text.format.Time;
import android.text.format.Time;
import android.util.DataUnit;
import android.util.DataUnit;
import android.util.Log;
import android.util.Log;
import android.util.Pair;
import android.util.Range;
import android.util.Range;
import android.util.RecurrenceRule;
import android.util.RecurrenceRule;


@@ -169,6 +178,7 @@ import java.time.Period;
import java.time.ZoneId;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Calendar;
import java.util.Iterator;
import java.util.Iterator;
@@ -1642,6 +1652,76 @@ public class NetworkPolicyManagerServiceTest {
                true);
                true);
    }
    }


    /**
     * Exhaustively test isUidNetworkingBlocked to output the expected results based on external
     * conditions.
     */
    @Test
    public void testIsUidNetworkingBlocked() {
        final ArrayList<Pair<Boolean, Integer>> expectedBlockedStates = new ArrayList<>();

        // Metered network. Data saver on.
        expectedBlockedStates.add(new Pair<>(true, RULE_NONE));
        expectedBlockedStates.add(new Pair<>(false, RULE_ALLOW_METERED));
        expectedBlockedStates.add(new Pair<>(false, RULE_TEMPORARY_ALLOW_METERED));
        expectedBlockedStates.add(new Pair<>(true, RULE_REJECT_METERED));
        expectedBlockedStates.add(new Pair<>(true, RULE_ALLOW_ALL));
        expectedBlockedStates.add(new Pair<>(true, RULE_REJECT_ALL));
        verifyNetworkBlockedState(
                true /* metered */, true /* backgroundRestricted */, expectedBlockedStates);
        expectedBlockedStates.clear();

        // Metered network. Data saver off.
        expectedBlockedStates.add(new Pair<>(false, RULE_NONE));
        expectedBlockedStates.add(new Pair<>(false, RULE_ALLOW_METERED));
        expectedBlockedStates.add(new Pair<>(false, RULE_TEMPORARY_ALLOW_METERED));
        expectedBlockedStates.add(new Pair<>(true, RULE_REJECT_METERED));
        expectedBlockedStates.add(new Pair<>(false, RULE_ALLOW_ALL));
        expectedBlockedStates.add(new Pair<>(true, RULE_REJECT_ALL));
        verifyNetworkBlockedState(
                true /* metered */, false /* backgroundRestricted */, expectedBlockedStates);
        expectedBlockedStates.clear();

        // Non-metered network. Data saver on.
        expectedBlockedStates.add(new Pair<>(false, RULE_NONE));
        expectedBlockedStates.add(new Pair<>(false, RULE_ALLOW_METERED));
        expectedBlockedStates.add(new Pair<>(false, RULE_TEMPORARY_ALLOW_METERED));
        expectedBlockedStates.add(new Pair<>(false, RULE_REJECT_METERED));
        expectedBlockedStates.add(new Pair<>(false, RULE_ALLOW_ALL));
        expectedBlockedStates.add(new Pair<>(true, RULE_REJECT_ALL));
        verifyNetworkBlockedState(
                false /* metered */, true /* backgroundRestricted */, expectedBlockedStates);

        // Non-metered network. Data saver off. The result is the same as previous case since
        // the network is blocked only for RULE_REJECT_ALL regardless of data saver.
        verifyNetworkBlockedState(
                false /* metered */, false /* backgroundRestricted */, expectedBlockedStates);
        expectedBlockedStates.clear();
    }

    private void verifyNetworkBlockedState(boolean metered, boolean backgroundRestricted,
            ArrayList<Pair<Boolean, Integer>> expectedBlockedStateForRules) {
        final NetworkPolicyManagerInternal npmi = LocalServices
                .getService(NetworkPolicyManagerInternal.class);

        for (Pair<Boolean, Integer> pair : expectedBlockedStateForRules) {
            final boolean expectedResult = pair.first;
            final int rule = pair.second;
            assertEquals(formatBlockedStateError(UID_A, rule, metered, backgroundRestricted),
                    expectedResult,
                    npmi.isUidNetworkingBlocked(UID_A, rule, metered, backgroundRestricted));
            assertFalse(formatBlockedStateError(SYSTEM_UID, rule, metered, backgroundRestricted),
                    npmi.isUidNetworkingBlocked(SYSTEM_UID, rule, metered, backgroundRestricted));
        }
    }

    private String formatBlockedStateError(int uid, int rule, boolean metered,
            boolean backgroundRestricted) {
        return String.format(
                "Unexpected BlockedState: (uid=%d, rule=%s, metered=%b, backgroundRestricted=%b)",
                uid, uidRulesToString(rule), metered, backgroundRestricted);
    }

    private SubscriptionPlan buildMonthlyDataPlan(ZonedDateTime start, long limitBytes) {
    private SubscriptionPlan buildMonthlyDataPlan(ZonedDateTime start, long limitBytes) {
        return SubscriptionPlan.Builder
        return SubscriptionPlan.Builder
                .createRecurringMonthly(start)
                .createRecurringMonthly(start)
+2 −2
Original line number Original line Diff line number Diff line
@@ -219,7 +219,7 @@ public class ConnectivityManagerTest {
        // callback triggers
        // callback triggers
        captor.getValue().send(makeMessage(request, ConnectivityManager.CALLBACK_AVAILABLE));
        captor.getValue().send(makeMessage(request, ConnectivityManager.CALLBACK_AVAILABLE));
        verify(callback, timeout(500).times(1)).onAvailable(any(Network.class),
        verify(callback, timeout(500).times(1)).onAvailable(any(Network.class),
                any(NetworkCapabilities.class), any(LinkProperties.class));
                any(NetworkCapabilities.class), any(LinkProperties.class), anyBoolean());


        // unregister callback
        // unregister callback
        manager.unregisterNetworkCallback(callback);
        manager.unregisterNetworkCallback(callback);
@@ -247,7 +247,7 @@ public class ConnectivityManagerTest {
        // callback triggers
        // callback triggers
        captor.getValue().send(makeMessage(req1, ConnectivityManager.CALLBACK_AVAILABLE));
        captor.getValue().send(makeMessage(req1, ConnectivityManager.CALLBACK_AVAILABLE));
        verify(callback, timeout(100).times(1)).onAvailable(any(Network.class),
        verify(callback, timeout(100).times(1)).onAvailable(any(Network.class),
                any(NetworkCapabilities.class), any(LinkProperties.class));
                any(NetworkCapabilities.class), any(LinkProperties.class), anyBoolean());


        // unregister callback
        // unregister callback
        manager.unregisterNetworkCallback(callback);
        manager.unregisterNetworkCallback(callback);
+164 −8
Original line number Original line Diff line number Diff line
@@ -51,6 +51,10 @@ import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
import static android.net.NetworkPolicyManager.RULE_NONE;
import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;


import static com.android.internal.util.TestUtils.waitForIdleHandler;
import static com.android.internal.util.TestUtils.waitForIdleHandler;
import static com.android.internal.util.TestUtils.waitForIdleLooper;
import static com.android.internal.util.TestUtils.waitForIdleLooper;
@@ -92,6 +96,7 @@ import android.net.ConnectivityManager.PacketKeepalive;
import android.net.ConnectivityManager.PacketKeepaliveCallback;
import android.net.ConnectivityManager.PacketKeepaliveCallback;
import android.net.ConnectivityManager.TooManyRequestsException;
import android.net.ConnectivityManager.TooManyRequestsException;
import android.net.ConnectivityThread;
import android.net.ConnectivityThread;
import android.net.INetworkPolicyListener;
import android.net.INetworkPolicyManager;
import android.net.INetworkPolicyManager;
import android.net.INetworkStatsService;
import android.net.INetworkStatsService;
import android.net.InterfaceConfiguration;
import android.net.InterfaceConfiguration;
@@ -148,6 +153,7 @@ import com.android.server.connectivity.MockableSystemProperties;
import com.android.server.connectivity.Nat464Xlat;
import com.android.server.connectivity.Nat464Xlat;
import com.android.server.connectivity.NetworkAgentInfo;
import com.android.server.connectivity.NetworkAgentInfo;
import com.android.server.connectivity.NetworkMonitor;
import com.android.server.connectivity.NetworkMonitor;
import com.android.server.connectivity.Tethering;
import com.android.server.connectivity.Vpn;
import com.android.server.connectivity.Vpn;
import com.android.server.net.NetworkPinner;
import com.android.server.net.NetworkPinner;
import com.android.server.net.NetworkPolicyManagerInternal;
import com.android.server.net.NetworkPolicyManagerInternal;
@@ -215,11 +221,13 @@ public class ConnectivityServiceTest {
    private MockNetworkAgent mEthernetNetworkAgent;
    private MockNetworkAgent mEthernetNetworkAgent;
    private MockVpn mMockVpn;
    private MockVpn mMockVpn;
    private Context mContext;
    private Context mContext;
    private INetworkPolicyListener mPolicyListener;


    @Mock IpConnectivityMetrics.Logger mMetricsService;
    @Mock IpConnectivityMetrics.Logger mMetricsService;
    @Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
    @Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
    @Mock INetworkManagementService mNetworkManagementService;
    @Mock INetworkManagementService mNetworkManagementService;
    @Mock INetworkStatsService mStatsService;
    @Mock INetworkStatsService mStatsService;
    @Mock INetworkPolicyManager mNpm;


    private ArgumentCaptor<String[]> mStringArrayCaptor = ArgumentCaptor.forClass(String[].class);
    private ArgumentCaptor<String[]> mStringArrayCaptor = ArgumentCaptor.forClass(String[].class);


@@ -933,6 +941,11 @@ public class ConnectivityServiceTest {
            return mSystemProperties;
            return mSystemProperties;
        }
        }


        @Override
        protected Tethering makeTethering() {
            return mock(Tethering.class);
        }

        @Override
        @Override
        protected int reserveNetId() {
        protected int reserveNetId() {
            while (true) {
            while (true) {
@@ -1023,6 +1036,20 @@ public class ConnectivityServiceTest {
        public void waitForIdle() {
        public void waitForIdle() {
            waitForIdle(TIMEOUT_MS);
            waitForIdle(TIMEOUT_MS);
        }
        }

        public void setUidRulesChanged(int uidRules) {
            try {
                mPolicyListener.onUidRulesChanged(Process.myUid(), uidRules);
            } catch (RemoteException ignored) {
            }
        }

        public void setRestrictBackgroundChanged(boolean restrictBackground) {
            try {
                mPolicyListener.onRestrictBackgroundChanged(restrictBackground);
            } catch (RemoteException ignored) {
            }
        }
    }
    }


    /**
    /**
@@ -1055,12 +1082,18 @@ public class ConnectivityServiceTest {
        LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
        LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
        LocalServices.addService(
        LocalServices.addService(
                NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
                NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));

        mService = new WrappedConnectivityService(mServiceContext,
        mService = new WrappedConnectivityService(mServiceContext,
                mNetworkManagementService,
                mNetworkManagementService,
                mStatsService,
                mStatsService,
                mock(INetworkPolicyManager.class),
                mNpm,
                mock(IpConnectivityLog.class));
                mock(IpConnectivityLog.class));


        final ArgumentCaptor<INetworkPolicyListener> policyListenerCaptor =
                ArgumentCaptor.forClass(INetworkPolicyListener.class);
        verify(mNpm).registerListener(policyListenerCaptor.capture());
        mPolicyListener = policyListenerCaptor.getValue();

        // Create local CM before sending system ready so that we can answer
        // Create local CM before sending system ready so that we can answer
        // getSystemService() correctly.
        // getSystemService() correctly.
        mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
        mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
@@ -1441,7 +1474,8 @@ public class ConnectivityServiceTest {
        RESUMED,
        RESUMED,
        LOSING,
        LOSING,
        LOST,
        LOST,
        UNAVAILABLE
        UNAVAILABLE,
        BLOCKED_STATUS
    }
    }


    private static class CallbackInfo {
    private static class CallbackInfo {
@@ -1522,6 +1556,11 @@ public class ConnectivityServiceTest {
            setLastCallback(CallbackState.LOST, network, null);
            setLastCallback(CallbackState.LOST, network, null);
        }
        }


        @Override
        public void onBlockedStatusChanged(Network network, boolean blocked) {
            setLastCallback(CallbackState.BLOCKED_STATUS, network, blocked);
        }

        public Network getLastAvailableNetwork() {
        public Network getLastAvailableNetwork() {
            return mLastAvailableNetwork;
            return mLastAvailableNetwork;
        }
        }
@@ -1582,6 +1621,7 @@ public class ConnectivityServiceTest {
        // - onSuspended, iff the network was suspended when the callbacks fire.
        // - onSuspended, iff the network was suspended when the callbacks fire.
        // - onCapabilitiesChanged.
        // - onCapabilitiesChanged.
        // - onLinkPropertiesChanged.
        // - onLinkPropertiesChanged.
        // - onBlockedStatusChanged.
        //
        //
        // @param agent the network to expect the callbacks on.
        // @param agent the network to expect the callbacks on.
        // @param expectSuspended whether to expect a SUSPENDED callback.
        // @param expectSuspended whether to expect a SUSPENDED callback.
@@ -1589,7 +1629,7 @@ public class ConnectivityServiceTest {
        //        onCapabilitiesChanged callback.
        //        onCapabilitiesChanged callback.
        // @param timeoutMs how long to wait for the callbacks.
        // @param timeoutMs how long to wait for the callbacks.
        void expectAvailableCallbacks(MockNetworkAgent agent, boolean expectSuspended,
        void expectAvailableCallbacks(MockNetworkAgent agent, boolean expectSuspended,
                boolean expectValidated, int timeoutMs) {
                boolean expectValidated, boolean expectBlocked, int timeoutMs) {
            expectCallback(CallbackState.AVAILABLE, agent, timeoutMs);
            expectCallback(CallbackState.AVAILABLE, agent, timeoutMs);
            if (expectSuspended) {
            if (expectSuspended) {
                expectCallback(CallbackState.SUSPENDED, agent, timeoutMs);
                expectCallback(CallbackState.SUSPENDED, agent, timeoutMs);
@@ -1600,19 +1640,28 @@ public class ConnectivityServiceTest {
                expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, agent, timeoutMs);
                expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, agent, timeoutMs);
            }
            }
            expectCallback(CallbackState.LINK_PROPERTIES, agent, timeoutMs);
            expectCallback(CallbackState.LINK_PROPERTIES, agent, timeoutMs);
            expectBlockedStatusCallback(expectBlocked, agent);
        }
        }


        // Expects the available callbacks (validated), plus onSuspended.
        // Expects the available callbacks (validated), plus onSuspended.
        void expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent, boolean expectValidated) {
        void expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent, boolean expectValidated) {
            expectAvailableCallbacks(agent, true, expectValidated, TEST_CALLBACK_TIMEOUT_MS);
            expectAvailableCallbacks(agent, true, expectValidated, false, TEST_CALLBACK_TIMEOUT_MS);
        }
        }


        void expectAvailableCallbacksValidated(MockNetworkAgent agent) {
        void expectAvailableCallbacksValidated(MockNetworkAgent agent) {
            expectAvailableCallbacks(agent, false, true, TEST_CALLBACK_TIMEOUT_MS);
            expectAvailableCallbacks(agent, false, true, false, TEST_CALLBACK_TIMEOUT_MS);
        }

        void expectAvailableCallbacksValidatedAndBlocked(MockNetworkAgent agent) {
            expectAvailableCallbacks(agent, false, true, true, TEST_CALLBACK_TIMEOUT_MS);
        }
        }


        void expectAvailableCallbacksUnvalidated(MockNetworkAgent agent) {
        void expectAvailableCallbacksUnvalidated(MockNetworkAgent agent) {
            expectAvailableCallbacks(agent, false, false, TEST_CALLBACK_TIMEOUT_MS);
            expectAvailableCallbacks(agent, false, false, false, TEST_CALLBACK_TIMEOUT_MS);
        }

        void expectAvailableCallbacksUnvalidatedAndBlocked(MockNetworkAgent agent) {
            expectAvailableCallbacks(agent, false, false, true, TEST_CALLBACK_TIMEOUT_MS);
        }
        }


        // Expects the available callbacks (where the onCapabilitiesChanged must contain the
        // Expects the available callbacks (where the onCapabilitiesChanged must contain the
@@ -1623,6 +1672,9 @@ public class ConnectivityServiceTest {
            expectCallback(CallbackState.AVAILABLE, agent, TEST_CALLBACK_TIMEOUT_MS);
            expectCallback(CallbackState.AVAILABLE, agent, TEST_CALLBACK_TIMEOUT_MS);
            NetworkCapabilities nc1 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
            NetworkCapabilities nc1 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
            expectCallback(CallbackState.LINK_PROPERTIES, agent, TEST_CALLBACK_TIMEOUT_MS);
            expectCallback(CallbackState.LINK_PROPERTIES, agent, TEST_CALLBACK_TIMEOUT_MS);
            // Implicitly check the network is allowed to use.
            // TODO: should we need to consider if network is in blocked status in this case?
            expectBlockedStatusCallback(false, agent);
            NetworkCapabilities nc2 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
            NetworkCapabilities nc2 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
            assertEquals(nc1, nc2);
            assertEquals(nc1, nc2);
        }
        }
@@ -1665,6 +1717,12 @@ public class ConnectivityServiceTest {
                    fn.test((NetworkCapabilities) cbi.arg));
                    fn.test((NetworkCapabilities) cbi.arg));
        }
        }


        void expectBlockedStatusCallback(boolean expectBlocked, MockNetworkAgent agent) {
            CallbackInfo cbi = expectCallback(CallbackState.BLOCKED_STATUS, agent);
            boolean actualBlocked = (boolean) cbi.arg;
            assertEquals(expectBlocked, actualBlocked);
        }

        void assertNoCallback() {
        void assertNoCallback() {
            waitForIdle();
            waitForIdle();
            CallbackInfo c = mCallbacks.peek();
            CallbackInfo c = mCallbacks.peek();
@@ -3223,7 +3281,7 @@ public class ConnectivityServiceTest {


        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
        mWiFiNetworkAgent.connect(false);
        mWiFiNetworkAgent.connect(false);
        networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false,
        networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
                TEST_CALLBACK_TIMEOUT_MS);
                TEST_CALLBACK_TIMEOUT_MS);


        // pass timeout and validate that UNAVAILABLE is not called
        // pass timeout and validate that UNAVAILABLE is not called
@@ -3243,7 +3301,7 @@ public class ConnectivityServiceTest {


        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
        mWiFiNetworkAgent.connect(false);
        mWiFiNetworkAgent.connect(false);
        networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false,
        networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
                TEST_CALLBACK_TIMEOUT_MS);
                TEST_CALLBACK_TIMEOUT_MS);
        mWiFiNetworkAgent.disconnect();
        mWiFiNetworkAgent.disconnect();
        networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
        networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
@@ -3802,6 +3860,7 @@ public class ConnectivityServiceTest {
        networkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, networkAgent);
        networkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, networkAgent);
        CallbackInfo cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
        CallbackInfo cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
                networkAgent);
                networkAgent);
        networkCallback.expectCallback(CallbackState.BLOCKED_STATUS, networkAgent);
        networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
        networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
        networkCallback.assertNoCallback();
        networkCallback.assertNoCallback();
        checkDirectlyConnectedRoutes(cbi.arg, Arrays.asList(myIpv4Address),
        checkDirectlyConnectedRoutes(cbi.arg, Arrays.asList(myIpv4Address),
@@ -4010,6 +4069,7 @@ public class ConnectivityServiceTest {
                mCellNetworkAgent);
                mCellNetworkAgent);
        CallbackInfo cbi = cellNetworkCallback.expectCallback(
        CallbackInfo cbi = cellNetworkCallback.expectCallback(
                CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
                CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
        cellNetworkCallback.expectCallback(CallbackState.BLOCKED_STATUS, mCellNetworkAgent);
        cellNetworkCallback.assertNoCallback();
        cellNetworkCallback.assertNoCallback();
        assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
        assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
        assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
        assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
@@ -4068,6 +4128,7 @@ public class ConnectivityServiceTest {
                mCellNetworkAgent);
                mCellNetworkAgent);
        CallbackInfo cbi = cellNetworkCallback.expectCallback(
        CallbackInfo cbi = cellNetworkCallback.expectCallback(
                CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
                CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
        cellNetworkCallback.expectCallback(CallbackState.BLOCKED_STATUS, mCellNetworkAgent);
        cellNetworkCallback.assertNoCallback();
        cellNetworkCallback.assertNoCallback();
        assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
        assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
        assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
        assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
@@ -4444,6 +4505,101 @@ public class ConnectivityServiceTest {
        mMockVpn.disconnect();
        mMockVpn.disconnect();
    }
    }


    @Test
    public void testNetworkBlockedStatus() {
        final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
        final NetworkRequest cellRequest = new NetworkRequest.Builder()
                .addTransportType(TRANSPORT_CELLULAR)
                .build();
        mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);

        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
        mCellNetworkAgent.connect(true);
        cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);

        mService.setUidRulesChanged(RULE_REJECT_ALL);
        cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);

        // ConnectivityService should cache it not to invoke the callback again.
        mService.setUidRulesChanged(RULE_REJECT_METERED);
        cellNetworkCallback.assertNoCallback();

        mService.setUidRulesChanged(RULE_NONE);
        cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);

        mService.setUidRulesChanged(RULE_REJECT_METERED);
        cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);

        // Restrict the network based on UID rule and NOT_METERED capability change.
        mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
        cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
        cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
        mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
        cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED,
                mCellNetworkAgent);
        cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
        mService.setUidRulesChanged(RULE_ALLOW_METERED);
        cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);

        mService.setUidRulesChanged(RULE_NONE);
        cellNetworkCallback.assertNoCallback();

        // Restrict the network based on BackgroundRestricted.
        mService.setRestrictBackgroundChanged(true);
        cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
        mService.setRestrictBackgroundChanged(true);
        cellNetworkCallback.assertNoCallback();
        mService.setRestrictBackgroundChanged(false);
        cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
        cellNetworkCallback.assertNoCallback();

        mCm.unregisterNetworkCallback(cellNetworkCallback);
    }

    @Test
    public void testNetworkBlockedStatusBeforeAndAfterConnect() {
        final TestNetworkCallback defaultCallback = new TestNetworkCallback();
        mCm.registerDefaultNetworkCallback(defaultCallback);

        // No Networkcallbacks invoked before any network is active.
        mService.setUidRulesChanged(RULE_REJECT_ALL);
        mService.setUidRulesChanged(RULE_NONE);
        mService.setUidRulesChanged(RULE_REJECT_METERED);
        defaultCallback.assertNoCallback();

        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
        mCellNetworkAgent.connect(true);
        defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
        defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mCellNetworkAgent);

        // Allow to use the network after switching to NOT_METERED network.
        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
        mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
        mWiFiNetworkAgent.connect(true);
        defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);

        // Switch to METERED network. Restrict the use of the network.
        mWiFiNetworkAgent.disconnect();
        defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
        defaultCallback.expectAvailableCallbacksValidatedAndBlocked(mCellNetworkAgent);

        // Network becomes NOT_METERED.
        mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
        defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
        defaultCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);

        // Verify there's no Networkcallbacks invoked after data saver on/off.
        mService.setRestrictBackgroundChanged(true);
        mService.setRestrictBackgroundChanged(false);
        defaultCallback.assertNoCallback();

        mCellNetworkAgent.disconnect();
        defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
        defaultCallback.assertNoCallback();

        mCm.unregisterNetworkCallback(defaultCallback);
    }

    /**
    /**
     * Make simulated InterfaceConfig for Nat464Xlat to query clat lower layer info.
     * Make simulated InterfaceConfig for Nat464Xlat to query clat lower layer info.
     */
     */