Loading services/core/java/com/android/server/VcnManagementService.java +56 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import static android.net.vcn.VcnManager.VCN_STATUS_CODE_ACTIVE; import static android.net.vcn.VcnManager.VCN_STATUS_CODE_INACTIVE; import static android.net.vcn.VcnManager.VCN_STATUS_CODE_NOT_CONFIGURED; Loading @@ -35,7 +37,9 @@ import android.content.Intent; import android.content.IntentFilter; import android.net.ConnectivityManager; import android.net.LinkProperties; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkRequest; import android.net.vcn.IVcnManagementService; import android.net.vcn.IVcnStatusCallback; import android.net.vcn.IVcnUnderlyingNetworkPolicyListener; Loading Loading @@ -161,6 +165,9 @@ public class VcnManagementService extends IVcnManagementService.Stub { @NonNull private final VcnContext mVcnContext; @NonNull private final BroadcastReceiver mPkgChangeReceiver; @NonNull private final TrackingNetworkCallback mTrackingNetworkCallback = new TrackingNetworkCallback(); /** Can only be assigned when {@link #systemReady()} is called, since it uses AppOpsManager. */ @Nullable private LocationPermissionChecker mLocationPermissionChecker; Loading Loading @@ -357,6 +364,10 @@ public class VcnManagementService extends IVcnManagementService.Stub { public void systemReady() { mContext.getSystemService(ConnectivityManager.class) .registerNetworkProvider(mNetworkProvider); mContext.getSystemService(ConnectivityManager.class) .registerNetworkCallback( new NetworkRequest.Builder().clearCapabilities().build(), mTrackingNetworkCallback); mTelephonySubscriptionTracker.register(); mLocationPermissionChecker = mDeps.newLocationPermissionChecker(mVcnContext.getContext()); } Loading Loading @@ -792,8 +803,9 @@ public class VcnManagementService extends IVcnManagementService.Stub { NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); } final NetworkCapabilities result = ncBuilder.build(); return new VcnUnderlyingNetworkPolicy( false /* isTearDownRequested */, ncBuilder.build()); mTrackingNetworkCallback.requiresRestartForCarrierWifi(result), result); }); } Loading Loading @@ -940,6 +952,49 @@ public class VcnManagementService extends IVcnManagementService.Stub { @Nullable String exceptionMessage); } /** * TrackingNetworkCallback tracks all active networks * * <p>This is used to ensure that no underlying networks have immutable capabilities changed * without requiring a Network restart. */ private class TrackingNetworkCallback extends ConnectivityManager.NetworkCallback { private final Map<Network, NetworkCapabilities> mCaps = new ArrayMap<>(); @Override public void onCapabilitiesChanged(Network network, NetworkCapabilities caps) { synchronized (mCaps) { mCaps.put(network, caps); } } @Override public void onLost(Network network) { synchronized (mCaps) { mCaps.remove(network); } } private boolean requiresRestartForCarrierWifi(NetworkCapabilities caps) { if (!caps.hasTransport(TRANSPORT_WIFI) || caps.getSubIds() == null) { return false; } synchronized (mCaps) { for (NetworkCapabilities existing : mCaps.values()) { if (existing.hasTransport(TRANSPORT_WIFI) && caps.getSubIds().equals(existing.getSubIds())) { // Restart if any immutable capabilities have changed return existing.hasCapability(NET_CAPABILITY_NOT_RESTRICTED) != caps.hasCapability(NET_CAPABILITY_NOT_RESTRICTED); } } } return false; } } /** VcnCallbackImpl for Vcn signals sent up to VcnManagementService. */ private class VcnCallbackImpl implements VcnCallback { @NonNull private final ParcelUuid mSubGroup; Loading tests/vcn/java/com/android/server/VcnManagementServiceTest.java +67 −5 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server; import static android.net.ConnectivityManager.NetworkCallback; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; Loading Loading @@ -55,8 +57,10 @@ import android.content.Context; import android.content.Intent; import android.net.ConnectivityManager; import android.net.LinkProperties; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkCapabilities.Transport; import android.net.NetworkRequest; import android.net.TelephonyNetworkSpecifier; import android.net.vcn.IVcnStatusCallback; import android.net.vcn.IVcnUnderlyingNetworkPolicyListener; Loading Loading @@ -258,6 +262,10 @@ public class VcnManagementServiceTest { verify(mConnMgr).registerNetworkProvider(any(VcnNetworkProvider.class)); verify(mSubscriptionTracker).register(); verify(mConnMgr) .registerNetworkCallback( eq(new NetworkRequest.Builder().clearCapabilities().build()), any(NetworkCallback.class)); } @Test Loading Loading @@ -706,10 +714,8 @@ public class VcnManagementServiceTest { .checkLocationPermission(eq(TEST_PACKAGE_NAME), any(), eq(TEST_UID), any()); } private VcnUnderlyingNetworkPolicy startVcnAndGetPolicyForTransport( int subId, ParcelUuid subGrp, boolean isVcnActive, int transport) { setupSubscriptionAndStartVcn(subId, subGrp, isVcnActive); private NetworkCapabilities.Builder getNetworkCapabilitiesBuilderForTransport( int subId, int transport) { final NetworkCapabilities.Builder ncBuilder = new NetworkCapabilities.Builder() .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED) Loading @@ -718,7 +724,16 @@ public class VcnManagementServiceTest { ncBuilder.setSubIds(Collections.singleton(subId)); } return mVcnMgmtSvc.getUnderlyingNetworkPolicy(ncBuilder.build(), new LinkProperties()); return ncBuilder; } private VcnUnderlyingNetworkPolicy startVcnAndGetPolicyForTransport( int subId, ParcelUuid subGrp, boolean isVcnActive, int transport) { setupSubscriptionAndStartVcn(subId, subGrp, isVcnActive); return mVcnMgmtSvc.getUnderlyingNetworkPolicy( getNetworkCapabilitiesBuilderForTransport(subId, transport).build(), new LinkProperties()); } @Test Loading Loading @@ -780,6 +795,53 @@ public class VcnManagementServiceTest { true /* isRestricted */); } private void setupTrackedCarrierWifiNetwork(NetworkCapabilities caps) { mVcnMgmtSvc.systemReady(); final ArgumentCaptor<NetworkCallback> captor = ArgumentCaptor.forClass(NetworkCallback.class); verify(mConnMgr) .registerNetworkCallback( eq(new NetworkRequest.Builder().clearCapabilities().build()), captor.capture()); captor.getValue().onCapabilitiesChanged(new Network(0), caps); } @Test public void testGetUnderlyingNetworkPolicyVcnWifi_unrestrictingExistingNetworkRequiresRestart() throws Exception { final NetworkCapabilities existingNetworkCaps = getNetworkCapabilitiesBuilderForTransport(TEST_SUBSCRIPTION_ID, TRANSPORT_WIFI) .removeCapability(NET_CAPABILITY_NOT_RESTRICTED) .build(); setupTrackedCarrierWifiNetwork(existingNetworkCaps); // Trigger test without VCN instance alive; expect restart due to change of NOT_RESTRICTED // immutable capability final VcnUnderlyingNetworkPolicy policy = mVcnMgmtSvc.getUnderlyingNetworkPolicy( getNetworkCapabilitiesBuilderForTransport( TEST_SUBSCRIPTION_ID, TRANSPORT_WIFI) .build(), new LinkProperties()); assertTrue(policy.isTeardownRequested()); } @Test public void testGetUnderlyingNetworkPolicyVcnWifi_restrictingExistingNetworkRequiresRestart() throws Exception { final NetworkCapabilities existingNetworkCaps = getNetworkCapabilitiesBuilderForTransport(TEST_SUBSCRIPTION_ID, TRANSPORT_WIFI) .build(); setupTrackedCarrierWifiNetwork(existingNetworkCaps); final VcnUnderlyingNetworkPolicy policy = startVcnAndGetPolicyForTransport( TEST_SUBSCRIPTION_ID, TEST_UUID_2, false /* isActive */, TRANSPORT_WIFI); assertTrue(policy.isTeardownRequested()); } @Test public void testGetUnderlyingNetworkPolicyNonVcnNetwork() throws Exception { setupSubscriptionAndStartVcn(TEST_SUBSCRIPTION_ID, TEST_UUID_1, true /* isActive */); Loading Loading
services/core/java/com/android/server/VcnManagementService.java +56 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import static android.net.vcn.VcnManager.VCN_STATUS_CODE_ACTIVE; import static android.net.vcn.VcnManager.VCN_STATUS_CODE_INACTIVE; import static android.net.vcn.VcnManager.VCN_STATUS_CODE_NOT_CONFIGURED; Loading @@ -35,7 +37,9 @@ import android.content.Intent; import android.content.IntentFilter; import android.net.ConnectivityManager; import android.net.LinkProperties; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkRequest; import android.net.vcn.IVcnManagementService; import android.net.vcn.IVcnStatusCallback; import android.net.vcn.IVcnUnderlyingNetworkPolicyListener; Loading Loading @@ -161,6 +165,9 @@ public class VcnManagementService extends IVcnManagementService.Stub { @NonNull private final VcnContext mVcnContext; @NonNull private final BroadcastReceiver mPkgChangeReceiver; @NonNull private final TrackingNetworkCallback mTrackingNetworkCallback = new TrackingNetworkCallback(); /** Can only be assigned when {@link #systemReady()} is called, since it uses AppOpsManager. */ @Nullable private LocationPermissionChecker mLocationPermissionChecker; Loading Loading @@ -357,6 +364,10 @@ public class VcnManagementService extends IVcnManagementService.Stub { public void systemReady() { mContext.getSystemService(ConnectivityManager.class) .registerNetworkProvider(mNetworkProvider); mContext.getSystemService(ConnectivityManager.class) .registerNetworkCallback( new NetworkRequest.Builder().clearCapabilities().build(), mTrackingNetworkCallback); mTelephonySubscriptionTracker.register(); mLocationPermissionChecker = mDeps.newLocationPermissionChecker(mVcnContext.getContext()); } Loading Loading @@ -792,8 +803,9 @@ public class VcnManagementService extends IVcnManagementService.Stub { NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); } final NetworkCapabilities result = ncBuilder.build(); return new VcnUnderlyingNetworkPolicy( false /* isTearDownRequested */, ncBuilder.build()); mTrackingNetworkCallback.requiresRestartForCarrierWifi(result), result); }); } Loading Loading @@ -940,6 +952,49 @@ public class VcnManagementService extends IVcnManagementService.Stub { @Nullable String exceptionMessage); } /** * TrackingNetworkCallback tracks all active networks * * <p>This is used to ensure that no underlying networks have immutable capabilities changed * without requiring a Network restart. */ private class TrackingNetworkCallback extends ConnectivityManager.NetworkCallback { private final Map<Network, NetworkCapabilities> mCaps = new ArrayMap<>(); @Override public void onCapabilitiesChanged(Network network, NetworkCapabilities caps) { synchronized (mCaps) { mCaps.put(network, caps); } } @Override public void onLost(Network network) { synchronized (mCaps) { mCaps.remove(network); } } private boolean requiresRestartForCarrierWifi(NetworkCapabilities caps) { if (!caps.hasTransport(TRANSPORT_WIFI) || caps.getSubIds() == null) { return false; } synchronized (mCaps) { for (NetworkCapabilities existing : mCaps.values()) { if (existing.hasTransport(TRANSPORT_WIFI) && caps.getSubIds().equals(existing.getSubIds())) { // Restart if any immutable capabilities have changed return existing.hasCapability(NET_CAPABILITY_NOT_RESTRICTED) != caps.hasCapability(NET_CAPABILITY_NOT_RESTRICTED); } } } return false; } } /** VcnCallbackImpl for Vcn signals sent up to VcnManagementService. */ private class VcnCallbackImpl implements VcnCallback { @NonNull private final ParcelUuid mSubGroup; Loading
tests/vcn/java/com/android/server/VcnManagementServiceTest.java +67 −5 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server; import static android.net.ConnectivityManager.NetworkCallback; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; Loading Loading @@ -55,8 +57,10 @@ import android.content.Context; import android.content.Intent; import android.net.ConnectivityManager; import android.net.LinkProperties; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkCapabilities.Transport; import android.net.NetworkRequest; import android.net.TelephonyNetworkSpecifier; import android.net.vcn.IVcnStatusCallback; import android.net.vcn.IVcnUnderlyingNetworkPolicyListener; Loading Loading @@ -258,6 +262,10 @@ public class VcnManagementServiceTest { verify(mConnMgr).registerNetworkProvider(any(VcnNetworkProvider.class)); verify(mSubscriptionTracker).register(); verify(mConnMgr) .registerNetworkCallback( eq(new NetworkRequest.Builder().clearCapabilities().build()), any(NetworkCallback.class)); } @Test Loading Loading @@ -706,10 +714,8 @@ public class VcnManagementServiceTest { .checkLocationPermission(eq(TEST_PACKAGE_NAME), any(), eq(TEST_UID), any()); } private VcnUnderlyingNetworkPolicy startVcnAndGetPolicyForTransport( int subId, ParcelUuid subGrp, boolean isVcnActive, int transport) { setupSubscriptionAndStartVcn(subId, subGrp, isVcnActive); private NetworkCapabilities.Builder getNetworkCapabilitiesBuilderForTransport( int subId, int transport) { final NetworkCapabilities.Builder ncBuilder = new NetworkCapabilities.Builder() .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED) Loading @@ -718,7 +724,16 @@ public class VcnManagementServiceTest { ncBuilder.setSubIds(Collections.singleton(subId)); } return mVcnMgmtSvc.getUnderlyingNetworkPolicy(ncBuilder.build(), new LinkProperties()); return ncBuilder; } private VcnUnderlyingNetworkPolicy startVcnAndGetPolicyForTransport( int subId, ParcelUuid subGrp, boolean isVcnActive, int transport) { setupSubscriptionAndStartVcn(subId, subGrp, isVcnActive); return mVcnMgmtSvc.getUnderlyingNetworkPolicy( getNetworkCapabilitiesBuilderForTransport(subId, transport).build(), new LinkProperties()); } @Test Loading Loading @@ -780,6 +795,53 @@ public class VcnManagementServiceTest { true /* isRestricted */); } private void setupTrackedCarrierWifiNetwork(NetworkCapabilities caps) { mVcnMgmtSvc.systemReady(); final ArgumentCaptor<NetworkCallback> captor = ArgumentCaptor.forClass(NetworkCallback.class); verify(mConnMgr) .registerNetworkCallback( eq(new NetworkRequest.Builder().clearCapabilities().build()), captor.capture()); captor.getValue().onCapabilitiesChanged(new Network(0), caps); } @Test public void testGetUnderlyingNetworkPolicyVcnWifi_unrestrictingExistingNetworkRequiresRestart() throws Exception { final NetworkCapabilities existingNetworkCaps = getNetworkCapabilitiesBuilderForTransport(TEST_SUBSCRIPTION_ID, TRANSPORT_WIFI) .removeCapability(NET_CAPABILITY_NOT_RESTRICTED) .build(); setupTrackedCarrierWifiNetwork(existingNetworkCaps); // Trigger test without VCN instance alive; expect restart due to change of NOT_RESTRICTED // immutable capability final VcnUnderlyingNetworkPolicy policy = mVcnMgmtSvc.getUnderlyingNetworkPolicy( getNetworkCapabilitiesBuilderForTransport( TEST_SUBSCRIPTION_ID, TRANSPORT_WIFI) .build(), new LinkProperties()); assertTrue(policy.isTeardownRequested()); } @Test public void testGetUnderlyingNetworkPolicyVcnWifi_restrictingExistingNetworkRequiresRestart() throws Exception { final NetworkCapabilities existingNetworkCaps = getNetworkCapabilitiesBuilderForTransport(TEST_SUBSCRIPTION_ID, TRANSPORT_WIFI) .build(); setupTrackedCarrierWifiNetwork(existingNetworkCaps); final VcnUnderlyingNetworkPolicy policy = startVcnAndGetPolicyForTransport( TEST_SUBSCRIPTION_ID, TEST_UUID_2, false /* isActive */, TRANSPORT_WIFI); assertTrue(policy.isTeardownRequested()); } @Test public void testGetUnderlyingNetworkPolicyNonVcnNetwork() throws Exception { setupSubscriptionAndStartVcn(TEST_SUBSCRIPTION_ID, TEST_UUID_1, true /* isActive */); Loading