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

Commit 07979a07 authored by Cody Kesting's avatar Cody Kesting
Browse files

Implement Network policy in VcnManagementService.

This CL implements #getUnderlyingNetworkPolicy() for
VcnManagementService. Specifically, it takes the provided
NetworkCapabilities and checks for a corresponding VCN. If one exists,
a VcnUnderlyingNetworkPolicy will be returned with a copy of the
original NetworkCapabilities without the capability NOT_VCN_MANAGED and
with the unwanted capability NOT_VCN_MANAGED.

Any NetworkCapabilities without a corresponding VCN will be returned a
VcnUnderlyingNetworkPolicy with the original NetworkCapabilities intact.

Bug: 175914059
Test: atest FrameworksVcnTests
Change-Id: Icdffc4f586f58a0e5b6290d5c6449e2bbed5cab0
parent f029daa4
Loading
Loading
Loading
Loading
+38 −2
Original line number Diff line number Diff line
@@ -27,10 +27,12 @@ import android.content.Context;
import android.net.ConnectivityManager;
import android.net.LinkProperties;
import android.net.NetworkCapabilities;
import android.net.TelephonyNetworkSpecifier;
import android.net.vcn.IVcnManagementService;
import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
import android.net.vcn.VcnConfig;
import android.net.vcn.VcnUnderlyingNetworkPolicy;
import android.net.wifi.WifiInfo;
import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
@@ -291,6 +293,12 @@ public class VcnManagementService extends IVcnManagementService.Stub {
                @NonNull VcnConfig config) {
            return new Vcn(vcnContext, subscriptionGroup, config);
        }

        /** Gets the subId indicated by the given {@link WifiInfo}. */
        public int getSubIdForWifiInfo(@NonNull WifiInfo wifiInfo) {
            // TODO(b/178501049): use the subId indicated by WifiInfo#getSubscriptionId
            return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
        }
    }

    /** Notifies the VcnManagementService that external dependencies can be set up. */
@@ -582,8 +590,36 @@ public class VcnManagementService extends IVcnManagementService.Stub {
                "Must have permission NETWORK_FACTORY or be the SystemServer to get underlying"
                        + " Network policies");

        // TODO(b/175914059): implement policy generation once VcnManagementService is able to
        // determine policies
        // Defensive copy in case this call is in-process and the given NetworkCapabilities mutates
        networkCapabilities = new NetworkCapabilities(networkCapabilities);

        int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
        if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
                && networkCapabilities.getNetworkSpecifier() instanceof TelephonyNetworkSpecifier) {
            TelephonyNetworkSpecifier telephonyNetworkSpecifier =
                    (TelephonyNetworkSpecifier) networkCapabilities.getNetworkSpecifier();
            subId = telephonyNetworkSpecifier.getSubscriptionId();
        } else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
                && networkCapabilities.getTransportInfo() instanceof WifiInfo) {
            WifiInfo wifiInfo = (WifiInfo) networkCapabilities.getTransportInfo();
            subId = mDeps.getSubIdForWifiInfo(wifiInfo);
        }

        boolean isVcnManagedNetwork = false;
        if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
            synchronized (mLock) {
                ParcelUuid subGroup = mLastSnapshot.getGroupForSubId(subId);

                // TODO(b/178140910): only mark the Network as VCN-managed if not in safe mode
                if (mVcns.containsKey(subGroup)) {
                    isVcnManagedNetwork = true;
                }
            }
        }
        if (isVcnManagedNetwork) {
            networkCapabilities.removeCapability(
                    NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED);
        }

        return new VcnUnderlyingNetworkPolicy(false /* isTearDownRequested */, networkCapabilities);
    }
+87 −11
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@ import static com.android.server.vcn.VcnTestUtils.setupSystemService;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -30,6 +29,7 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.argThat;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
@@ -39,16 +39,20 @@ import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.app.AppOpsManager;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.LinkProperties;
import android.net.NetworkCapabilities;
import android.net.NetworkCapabilities.Transport;
import android.net.TelephonyNetworkSpecifier;
import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
import android.net.vcn.VcnConfig;
import android.net.vcn.VcnConfigTest;
import android.net.vcn.VcnUnderlyingNetworkPolicy;
import android.net.wifi.WifiInfo;
import android.os.IBinder;
import android.os.ParcelUuid;
import android.os.PersistableBundle;
@@ -253,7 +257,14 @@ public class VcnManagementServiceTest {
        verify(mConfigReadWriteHelper).readFromDisk();
    }

    private void triggerSubscriptionTrackerCallback(Set<ParcelUuid> activeSubscriptionGroups) {
    private TelephonySubscriptionSnapshot triggerSubscriptionTrackerCbAndGetSnapshot(
            Set<ParcelUuid> activeSubscriptionGroups) {
        return triggerSubscriptionTrackerCbAndGetSnapshot(
                activeSubscriptionGroups, Collections.emptyMap());
    }

    private TelephonySubscriptionSnapshot triggerSubscriptionTrackerCbAndGetSnapshot(
            Set<ParcelUuid> activeSubscriptionGroups, Map<Integer, ParcelUuid> subIdToGroupMap) {
        final TelephonySubscriptionSnapshot snapshot = mock(TelephonySubscriptionSnapshot.class);
        doReturn(activeSubscriptionGroups).when(snapshot).getActiveSubscriptionGroups();

@@ -267,8 +278,14 @@ public class VcnManagementServiceTest {
                        argThat(val -> activeSubscriptionGroups.contains(val)),
                        eq(TEST_PACKAGE_NAME));

        doAnswer(invocation -> {
            return subIdToGroupMap.get(invocation.getArgument(0));
        }).when(snapshot).getGroupForSubId(anyInt());

        final TelephonySubscriptionTrackerCallback cb = getTelephonySubscriptionTrackerCallback();
        cb.onNewSnapshot(snapshot);

        return snapshot;
    }

    private TelephonySubscriptionTrackerCallback getTelephonySubscriptionTrackerCallback() {
@@ -287,7 +304,7 @@ public class VcnManagementServiceTest {

    @Test
    public void testTelephonyNetworkTrackerCallbackStartsInstances() throws Exception {
        triggerSubscriptionTrackerCallback(Collections.singleton(TEST_UUID_1));
        triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(TEST_UUID_1));
        verify(mMockDeps).newVcn(eq(mVcnContext), eq(TEST_UUID_1), eq(TEST_VCN_CONFIG));
    }

@@ -296,7 +313,7 @@ public class VcnManagementServiceTest {
        final TelephonySubscriptionTrackerCallback cb = getTelephonySubscriptionTrackerCallback();
        final Vcn vcn = startAndGetVcnInstance(TEST_UUID_2);

        triggerSubscriptionTrackerCallback(Collections.emptySet());
        triggerSubscriptionTrackerCbAndGetSnapshot(Collections.emptySet());

        // Verify teardown after delay
        mTestLooper.moveTimeForward(VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS);
@@ -311,13 +328,13 @@ public class VcnManagementServiceTest {
        final Vcn vcn = startAndGetVcnInstance(TEST_UUID_2);

        // Simulate SIM unloaded
        triggerSubscriptionTrackerCallback(Collections.emptySet());
        triggerSubscriptionTrackerCbAndGetSnapshot(Collections.emptySet());

        // Simulate new SIM loaded right during teardown delay.
        mTestLooper.moveTimeForward(
                VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS / 2);
        mTestLooper.dispatchAll();
        triggerSubscriptionTrackerCallback(Collections.singleton(TEST_UUID_2));
        triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(TEST_UUID_2));

        // Verify that even after the full timeout duration, the VCN instance is not torn down
        mTestLooper.moveTimeForward(VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS);
@@ -331,7 +348,7 @@ public class VcnManagementServiceTest {
        final Vcn oldInstance = startAndGetVcnInstance(TEST_UUID_2);

        // Simulate SIM unloaded
        triggerSubscriptionTrackerCallback(Collections.emptySet());
        triggerSubscriptionTrackerCbAndGetSnapshot(Collections.emptySet());

        // Config cleared, SIM reloaded & config re-added right before teardown delay, staring new
        // vcnInstance.
@@ -496,14 +513,73 @@ public class VcnManagementServiceTest {
        mVcnMgmtSvc.removeVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
    }

    private void setUpVcnSubscription(int subId, ParcelUuid subGroup) {
        mVcnMgmtSvc.setVcnConfig(subGroup, TEST_VCN_CONFIG, TEST_PACKAGE_NAME);

        triggerSubscriptionTrackerCbAndGetSnapshot(
                Collections.singleton(subGroup), Collections.singletonMap(subId, subGroup));
    }

    private void verifyMergedNetworkCapabilities(
            NetworkCapabilities mergedCapabilities, @Transport int transportType) {
        assertTrue(mergedCapabilities.hasTransport(transportType));
        assertFalse(
                mergedCapabilities.hasCapability(
                        NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED));
    }

    @Test
    public void testGetUnderlyingNetworkPolicy() throws Exception {
    public void testGetUnderlyingNetworkPolicyTransportCell() throws Exception {
        setUpVcnSubscription(TEST_SUBSCRIPTION_ID, TEST_UUID_2);

        NetworkCapabilities nc =
                new NetworkCapabilities.Builder()
                        .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
                        .setNetworkSpecifier(new TelephonyNetworkSpecifier(TEST_SUBSCRIPTION_ID))
                        .build();

        VcnUnderlyingNetworkPolicy policy =
                mVcnMgmtSvc.getUnderlyingNetworkPolicy(nc, new LinkProperties());

        assertFalse(policy.isTeardownRequested());
        verifyMergedNetworkCapabilities(
                policy.getMergedNetworkCapabilities(), NetworkCapabilities.TRANSPORT_CELLULAR);
    }

    @Test
    public void testGetUnderlyingNetworkPolicyTransportWifi() throws Exception {
        setUpVcnSubscription(TEST_SUBSCRIPTION_ID, TEST_UUID_2);

        WifiInfo wifiInfo = mock(WifiInfo.class);
        when(wifiInfo.makeCopy(anyBoolean())).thenReturn(wifiInfo);
        when(mMockDeps.getSubIdForWifiInfo(eq(wifiInfo))).thenReturn(TEST_SUBSCRIPTION_ID);
        NetworkCapabilities nc =
                new NetworkCapabilities.Builder()
                        .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
                        .setTransportInfo(wifiInfo)
                        .build();

        VcnUnderlyingNetworkPolicy policy =
                mVcnMgmtSvc.getUnderlyingNetworkPolicy(nc, new LinkProperties());

        assertFalse(policy.isTeardownRequested());
        verifyMergedNetworkCapabilities(
                policy.getMergedNetworkCapabilities(), NetworkCapabilities.TRANSPORT_WIFI);
    }

    @Test
    public void testGetUnderlyingNetworkPolicyNonVcnNetwork() throws Exception {
        NetworkCapabilities nc =
                new NetworkCapabilities.Builder()
                        .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
                        .setNetworkSpecifier(new TelephonyNetworkSpecifier(TEST_SUBSCRIPTION_ID))
                        .build();

        VcnUnderlyingNetworkPolicy policy =
                mVcnMgmtSvc.getUnderlyingNetworkPolicy(
                        new NetworkCapabilities(), new LinkProperties());
                mVcnMgmtSvc.getUnderlyingNetworkPolicy(nc, new LinkProperties());

        assertFalse(policy.isTeardownRequested());
        assertNotNull(policy.getMergedNetworkCapabilities());
        assertEquals(nc, policy.getMergedNetworkCapabilities());
    }

    @Test(expected = SecurityException.class)