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
This commit is contained in:
Cody Kesting
2021-01-19 15:19:15 -08:00
parent f029daa404
commit 07979a07cc
2 changed files with 125 additions and 13 deletions

View File

@@ -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);
}

View File

@@ -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(
new NetworkCapabilities(), new LinkProperties());
mVcnMgmtSvc.getUnderlyingNetworkPolicy(nc, new LinkProperties());
assertFalse(policy.isTeardownRequested());
assertNotNull(policy.getMergedNetworkCapabilities());
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(nc, new LinkProperties());
assertFalse(policy.isTeardownRequested());
assertEquals(nc, policy.getMergedNetworkCapabilities());
}
@Test(expected = SecurityException.class)