Merge changes Iaeb1871b,I1687df02

* changes:
  Add restrictions on underlying networks with CarrierConfig
  Support configuring the VCN restriction policy
This commit is contained in:
Benedict Wong
2022-11-21 20:11:15 +00:00
committed by Gerrit Code Review
6 changed files with 393 additions and 62 deletions

View File

@@ -104,12 +104,23 @@ public class VcnManager {
// TODO: Add separate signal strength thresholds for 2.4 GHz and 5GHz // TODO: Add separate signal strength thresholds for 2.4 GHz and 5GHz
/**
* Key for transports that need to be marked as restricted by the VCN
*
* <p>Defaults to TRANSPORT_WIFI if the config does not exist
*
* @hide
*/
public static final String VCN_RESTRICTED_TRANSPORTS_INT_ARRAY_KEY =
"vcn_restricted_transports";
/** List of Carrier Config options to extract from Carrier Config bundles. @hide */ /** List of Carrier Config options to extract from Carrier Config bundles. @hide */
@NonNull @NonNull
public static final String[] VCN_RELATED_CARRIER_CONFIG_KEYS = public static final String[] VCN_RELATED_CARRIER_CONFIG_KEYS =
new String[] { new String[] {
VCN_NETWORK_SELECTION_WIFI_ENTRY_RSSI_THRESHOLD_KEY, VCN_NETWORK_SELECTION_WIFI_ENTRY_RSSI_THRESHOLD_KEY,
VCN_NETWORK_SELECTION_WIFI_EXIT_RSSI_THRESHOLD_KEY VCN_NETWORK_SELECTION_WIFI_EXIT_RSSI_THRESHOLD_KEY,
VCN_RESTRICTED_TRANSPORTS_INT_ARRAY_KEY
}; };
private static final Map< private static final Map<

View File

@@ -18,8 +18,11 @@ package com.android.server;
import static android.Manifest.permission.DUMP; import static android.Manifest.permission.DUMP;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_TEST; import static android.net.NetworkCapabilities.TRANSPORT_TEST;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.vcn.VcnGatewayConnectionConfig.ALLOWED_CAPABILITIES;
import static android.net.vcn.VcnManager.VCN_RESTRICTED_TRANSPORTS_INT_ARRAY_KEY;
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_ACTIVE; 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_INACTIVE;
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_NOT_CONFIGURED; import static android.net.vcn.VcnManager.VCN_STATUS_CODE_NOT_CONFIGURED;
@@ -53,6 +56,7 @@ import android.net.vcn.VcnManager.VcnStatusCode;
import android.net.vcn.VcnUnderlyingNetworkPolicy; import android.net.vcn.VcnUnderlyingNetworkPolicy;
import android.net.wifi.WifiInfo; import android.net.wifi.WifiInfo;
import android.os.Binder; import android.os.Binder;
import android.os.Build;
import android.os.Environment; import android.os.Environment;
import android.os.Handler; import android.os.Handler;
import android.os.HandlerThread; import android.os.HandlerThread;
@@ -68,6 +72,7 @@ import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager; import android.telephony.TelephonyManager;
import android.util.ArrayMap; import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.LocalLog; import android.util.LocalLog;
import android.util.Log; import android.util.Log;
import android.util.Slog; import android.util.Slog;
@@ -83,6 +88,7 @@ import com.android.server.vcn.Vcn;
import com.android.server.vcn.VcnContext; import com.android.server.vcn.VcnContext;
import com.android.server.vcn.VcnNetworkProvider; import com.android.server.vcn.VcnNetworkProvider;
import com.android.server.vcn.util.PersistableBundleUtils; import com.android.server.vcn.util.PersistableBundleUtils;
import com.android.server.vcn.util.PersistableBundleUtils.PersistableBundleWrapper;
import java.io.File; import java.io.File;
import java.io.FileDescriptor; import java.io.FileDescriptor;
@@ -159,6 +165,9 @@ public class VcnManagementService extends IVcnManagementService.Stub {
private static final long DUMP_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(5); private static final long DUMP_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(5);
private static final int LOCAL_LOG_LINE_COUNT = 512; private static final int LOCAL_LOG_LINE_COUNT = 512;
private static final Set<Integer> RESTRICTED_TRANSPORTS_DEFAULT =
Collections.singleton(TRANSPORT_WIFI);
// Public for use in all other VCN classes // Public for use in all other VCN classes
@NonNull public static final LocalLog LOCAL_LOG = new LocalLog(LOCAL_LOG_LINE_COUNT); @NonNull public static final LocalLog LOCAL_LOG = new LocalLog(LOCAL_LOG_LINE_COUNT);
@@ -361,6 +370,34 @@ public class VcnManagementService extends IVcnManagementService.Stub {
public LocationPermissionChecker newLocationPermissionChecker(@NonNull Context context) { public LocationPermissionChecker newLocationPermissionChecker(@NonNull Context context) {
return new LocationPermissionChecker(context); return new LocationPermissionChecker(context);
} }
/** Gets the transports that need to be marked as restricted by the VCN */
public Set<Integer> getRestrictedTransports(
ParcelUuid subGrp, TelephonySubscriptionSnapshot lastSnapshot) {
if (!Build.IS_ENG && !Build.IS_USERDEBUG) {
return RESTRICTED_TRANSPORTS_DEFAULT;
}
final PersistableBundleWrapper carrierConfig =
lastSnapshot.getCarrierConfigForSubGrp(subGrp);
if (carrierConfig == null) {
return RESTRICTED_TRANSPORTS_DEFAULT;
}
final int[] defaultValue =
RESTRICTED_TRANSPORTS_DEFAULT.stream().mapToInt(i -> i).toArray();
final int[] restrictedTransportsArray =
carrierConfig.getIntArray(
VCN_RESTRICTED_TRANSPORTS_INT_ARRAY_KEY,
defaultValue);
// Convert to a boxed set
final Set<Integer> restrictedTransports = new ArraySet<>();
for (int transport : restrictedTransportsArray) {
restrictedTransports.add(transport);
}
return restrictedTransports;
}
} }
/** Notifies the VcnManagementService that external dependencies can be set up. */ /** Notifies the VcnManagementService that external dependencies can be set up. */
@@ -517,6 +554,7 @@ public class VcnManagementService extends IVcnManagementService.Stub {
} }
} }
boolean needNotifyAllPolicyListeners = false;
// Schedule teardown of any VCN instances that have lost carrier privileges (after a // Schedule teardown of any VCN instances that have lost carrier privileges (after a
// delay) // delay)
for (Entry<ParcelUuid, Vcn> entry : mVcns.entrySet()) { for (Entry<ParcelUuid, Vcn> entry : mVcns.entrySet()) {
@@ -564,6 +602,10 @@ public class VcnManagementService extends IVcnManagementService.Stub {
} else { } else {
// If this VCN's status has not changed, update it with the new snapshot // If this VCN's status has not changed, update it with the new snapshot
entry.getValue().updateSubscriptionSnapshot(mLastSnapshot); entry.getValue().updateSubscriptionSnapshot(mLastSnapshot);
needNotifyAllPolicyListeners |=
!Objects.equals(
oldSnapshot.getCarrierConfigForSubGrp(subGrp),
mLastSnapshot.getCarrierConfigForSubGrp(subGrp));
} }
} }
@@ -573,6 +615,10 @@ public class VcnManagementService extends IVcnManagementService.Stub {
getSubGroupToSubIdMappings(mLastSnapshot); getSubGroupToSubIdMappings(mLastSnapshot);
if (!currSubGrpMappings.equals(oldSubGrpMappings)) { if (!currSubGrpMappings.equals(oldSubGrpMappings)) {
garbageCollectAndWriteVcnConfigsLocked(); garbageCollectAndWriteVcnConfigsLocked();
needNotifyAllPolicyListeners = true;
}
if (needNotifyAllPolicyListeners) {
notifyAllPolicyListenersLocked(); notifyAllPolicyListenersLocked();
} }
} }
@@ -917,6 +963,14 @@ public class VcnManagementService extends IVcnManagementService.Stub {
}); });
} }
@VisibleForTesting(visibility = Visibility.PRIVATE)
void addVcnUnderlyingNetworkPolicyListenerForTest(
@NonNull IVcnUnderlyingNetworkPolicyListener listener) {
synchronized (mLock) {
addVcnUnderlyingNetworkPolicyListener(listener);
}
}
/** Removes the provided listener from receiving VcnUnderlyingNetworkPolicy updates. */ /** Removes the provided listener from receiving VcnUnderlyingNetworkPolicy updates. */
@GuardedBy("mLock") @GuardedBy("mLock")
@Override @Override
@@ -1000,7 +1054,7 @@ public class VcnManagementService extends IVcnManagementService.Stub {
final ParcelUuid subGrp = getSubGroupForNetworkCapabilities(ncCopy); final ParcelUuid subGrp = getSubGroupForNetworkCapabilities(ncCopy);
boolean isVcnManagedNetwork = false; boolean isVcnManagedNetwork = false;
boolean isRestrictedCarrierWifi = false; boolean isRestricted = false;
synchronized (mLock) { synchronized (mLock) {
final Vcn vcn = mVcns.get(subGrp); final Vcn vcn = mVcns.get(subGrp);
if (vcn != null) { if (vcn != null) {
@@ -1008,9 +1062,19 @@ public class VcnManagementService extends IVcnManagementService.Stub {
isVcnManagedNetwork = true; isVcnManagedNetwork = true;
} }
if (ncCopy.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { final Set<Integer> restrictedTransports =
// Carrier WiFi always restricted if VCN exists (even in safe mode). mDeps.getRestrictedTransports(subGrp, mLastSnapshot);
isRestrictedCarrierWifi = true; for (int restrictedTransport : restrictedTransports) {
if (ncCopy.hasTransport(restrictedTransport)) {
if (restrictedTransport == TRANSPORT_CELLULAR) {
// Only make a cell network as restricted when the VCN is in
// active mode.
isRestricted |= (vcn.getStatus() == VCN_STATUS_CODE_ACTIVE);
} else {
isRestricted = true;
break;
}
}
} }
} }
} }
@@ -1024,14 +1088,16 @@ public class VcnManagementService extends IVcnManagementService.Stub {
ncBuilder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); ncBuilder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED);
} }
if (isRestrictedCarrierWifi) { if (isRestricted) {
ncBuilder.removeCapability( ncBuilder.removeCapability(
NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
} }
final NetworkCapabilities result = ncBuilder.build(); final NetworkCapabilities result = ncBuilder.build();
final VcnUnderlyingNetworkPolicy policy = new VcnUnderlyingNetworkPolicy( final VcnUnderlyingNetworkPolicy policy = new VcnUnderlyingNetworkPolicy(
mTrackingNetworkCallback.requiresRestartForCarrierWifi(result), result); mTrackingNetworkCallback
.requiresRestartForImmutableCapabilityChanges(result),
result);
logVdbg("getUnderlyingNetworkPolicy() called for caps: " + networkCapabilities logVdbg("getUnderlyingNetworkPolicy() called for caps: " + networkCapabilities
+ "; and lp: " + linkProperties + "; result = " + policy); + "; and lp: " + linkProperties + "; result = " + policy);
@@ -1296,15 +1362,38 @@ public class VcnManagementService extends IVcnManagementService.Stub {
} }
} }
private boolean requiresRestartForCarrierWifi(NetworkCapabilities caps) { private Set<Integer> getNonTestTransportTypes(NetworkCapabilities caps) {
if (!caps.hasTransport(TRANSPORT_WIFI) || caps.getSubscriptionIds() == null) { final Set<Integer> transportTypes = new ArraySet<>();
for (int t : caps.getTransportTypes()) {
transportTypes.add(t);
}
return transportTypes;
}
private boolean hasSameTransportsAndCapabilities(
NetworkCapabilities caps, NetworkCapabilities capsOther) {
if (!Objects.equals(
getNonTestTransportTypes(caps), getNonTestTransportTypes(capsOther))) {
return false;
}
for (int capability : ALLOWED_CAPABILITIES) {
if (caps.hasCapability(capability) != capsOther.hasCapability(capability)) {
return false;
}
}
return true;
}
private boolean requiresRestartForImmutableCapabilityChanges(NetworkCapabilities caps) {
if (caps.getSubscriptionIds() == null) {
return false; return false;
} }
synchronized (mCaps) { synchronized (mCaps) {
for (NetworkCapabilities existing : mCaps.values()) { for (NetworkCapabilities existing : mCaps.values()) {
if (existing.hasTransport(TRANSPORT_WIFI) if (caps.getSubscriptionIds().equals(existing.getSubscriptionIds())
&& caps.getSubscriptionIds().equals(existing.getSubscriptionIds())) { && hasSameTransportsAndCapabilities(caps, existing)) {
// Restart if any immutable capabilities have changed // Restart if any immutable capabilities have changed
return existing.hasCapability(NET_CAPABILITY_NOT_RESTRICTED) return existing.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)
!= caps.hasCapability(NET_CAPABILITY_NOT_RESTRICTED); != caps.hasCapability(NET_CAPABILITY_NOT_RESTRICTED);

View File

@@ -390,8 +390,13 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver {
Objects.requireNonNull(privilegedPackages, "privilegedPackages was null"); Objects.requireNonNull(privilegedPackages, "privilegedPackages was null");
Objects.requireNonNull(subIdToCarrierConfigMap, "subIdToCarrierConfigMap was null"); Objects.requireNonNull(subIdToCarrierConfigMap, "subIdToCarrierConfigMap was null");
mSubIdToInfoMap = Collections.unmodifiableMap(subIdToInfoMap); mSubIdToInfoMap =
mSubIdToCarrierConfigMap = Collections.unmodifiableMap(subIdToCarrierConfigMap); Collections.unmodifiableMap(
new HashMap<Integer, SubscriptionInfo>(subIdToInfoMap));
mSubIdToCarrierConfigMap =
Collections.unmodifiableMap(
new HashMap<Integer, PersistableBundleWrapper>(
subIdToCarrierConfigMap));
final Map<ParcelUuid, Set<String>> unmodifiableInnerSets = new ArrayMap<>(); final Map<ParcelUuid, Set<String>> unmodifiableInnerSets = new ArrayMap<>();
for (Entry<ParcelUuid, Set<String>> entry : privilegedPackages.entrySet()) { for (Entry<ParcelUuid, Set<String>> entry : privilegedPackages.entrySet()) {

View File

@@ -544,6 +544,20 @@ public class PersistableBundleUtils {
return mBundle.getInt(key, defaultValue); return mBundle.getInt(key, defaultValue);
} }
/**
* Returns the value associated with the given key, or null if no mapping of the desired
* type exists for the given key or a null value is explicitly associated with the key.
*
* @param key a String, or null
* @param defaultValue the value to return if key does not exist
* @return an int[] value, or null
*/
@Nullable
public int[] getIntArray(@Nullable String key, @Nullable int[] defaultValue) {
final int[] value = mBundle.getIntArray(key);
return value == null ? defaultValue : value;
}
@Override @Override
public int hashCode() { public int hashCode() {
return getHashCode(mBundle); return getHashCode(mBundle);

View File

@@ -17,10 +17,12 @@
package com.android.server; package com.android.server;
import static android.net.ConnectivityManager.NetworkCallback; import static android.net.ConnectivityManager.NetworkCallback;
import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.vcn.VcnManager.VCN_RESTRICTED_TRANSPORTS_INT_ARRAY_KEY;
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_ACTIVE; import static android.net.vcn.VcnManager.VCN_STATUS_CODE_ACTIVE;
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_SAFE_MODE; import static android.net.vcn.VcnManager.VCN_STATUS_CODE_SAFE_MODE;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -95,6 +97,7 @@ import com.android.server.vcn.Vcn;
import com.android.server.vcn.VcnContext; import com.android.server.vcn.VcnContext;
import com.android.server.vcn.VcnNetworkProvider; import com.android.server.vcn.VcnNetworkProvider;
import com.android.server.vcn.util.PersistableBundleUtils; import com.android.server.vcn.util.PersistableBundleUtils;
import com.android.server.vcn.util.PersistableBundleUtils.PersistableBundleWrapper;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@@ -252,6 +255,10 @@ public class VcnManagementServiceTest {
.when(mMockContext) .when(mMockContext)
.enforceCallingOrSelfPermission( .enforceCallingOrSelfPermission(
eq(android.Manifest.permission.NETWORK_FACTORY), any()); eq(android.Manifest.permission.NETWORK_FACTORY), any());
doReturn(Collections.singleton(TRANSPORT_WIFI))
.when(mMockDeps)
.getRestrictedTransports(any(), any());
} }
@@ -1031,63 +1038,188 @@ public class VcnManagementServiceTest {
new LinkProperties()); new LinkProperties());
} }
private void checkGetRestrictedTransports(
ParcelUuid subGrp,
TelephonySubscriptionSnapshot lastSnapshot,
Set<Integer> expectedTransports) {
Set<Integer> result =
new VcnManagementService.Dependencies()
.getRestrictedTransports(subGrp, lastSnapshot);
assertEquals(expectedTransports, result);
}
@Test @Test
public void testGetUnderlyingNetworkPolicyCellular() throws Exception { public void testGetRestrictedTransports() {
final Set<Integer> restrictedTransports = new ArraySet<>();
restrictedTransports.add(TRANSPORT_CELLULAR);
restrictedTransports.add(TRANSPORT_WIFI);
PersistableBundle carrierConfigBundle = new PersistableBundle();
carrierConfigBundle.putIntArray(
VCN_RESTRICTED_TRANSPORTS_INT_ARRAY_KEY,
restrictedTransports.stream().mapToInt(i -> i).toArray());
final PersistableBundleWrapper carrierConfig =
new PersistableBundleWrapper(carrierConfigBundle);
final TelephonySubscriptionSnapshot lastSnapshot =
mock(TelephonySubscriptionSnapshot.class);
doReturn(carrierConfig).when(lastSnapshot).getCarrierConfigForSubGrp(eq(TEST_UUID_2));
checkGetRestrictedTransports(TEST_UUID_2, lastSnapshot, restrictedTransports);
}
@Test
public void testGetRestrictedTransports_noRestrictPolicyConfigured() {
final Set<Integer> restrictedTransports = Collections.singleton(TRANSPORT_WIFI);
final PersistableBundleWrapper carrierConfig =
new PersistableBundleWrapper(new PersistableBundle());
final TelephonySubscriptionSnapshot lastSnapshot =
mock(TelephonySubscriptionSnapshot.class);
doReturn(carrierConfig).when(lastSnapshot).getCarrierConfigForSubGrp(eq(TEST_UUID_2));
checkGetRestrictedTransports(TEST_UUID_2, lastSnapshot, restrictedTransports);
}
@Test
public void testGetRestrictedTransports_noCarrierConfig() {
final Set<Integer> restrictedTransports = Collections.singleton(TRANSPORT_WIFI);
final TelephonySubscriptionSnapshot lastSnapshot =
mock(TelephonySubscriptionSnapshot.class);
checkGetRestrictedTransports(TEST_UUID_2, lastSnapshot, restrictedTransports);
}
private void checkGetUnderlyingNetworkPolicy(
int transportType,
boolean isTransportRestricted,
boolean isActive,
boolean expectVcnManaged,
boolean expectRestricted)
throws Exception {
final Set<Integer> restrictedTransports = new ArraySet();
if (isTransportRestricted) {
restrictedTransports.add(transportType);
}
doReturn(restrictedTransports).when(mMockDeps).getRestrictedTransports(any(), any());
final VcnUnderlyingNetworkPolicy policy = final VcnUnderlyingNetworkPolicy policy =
startVcnAndGetPolicyForTransport( startVcnAndGetPolicyForTransport(
TEST_SUBSCRIPTION_ID, TEST_UUID_2, true /* isActive */, TRANSPORT_CELLULAR); TEST_SUBSCRIPTION_ID, TEST_UUID_2, isActive, transportType);
assertFalse(policy.isTeardownRequested());
verifyMergedNetworkCapabilities(
policy.getMergedNetworkCapabilities(),
transportType,
expectVcnManaged,
expectRestricted);
}
@Test
public void testGetUnderlyingNetworkPolicy_unrestrictCell() throws Exception {
checkGetUnderlyingNetworkPolicy(
TRANSPORT_CELLULAR,
false /* isTransportRestricted */,
true /* isActive */,
true /* expectVcnManaged */,
false /* expectRestricted */);
}
@Test
public void testGetUnderlyingNetworkPolicy_unrestrictCellSafeMode() throws Exception {
checkGetUnderlyingNetworkPolicy(
TRANSPORT_CELLULAR,
false /* isTransportRestricted */,
false /* isActive */,
false /* expectVcnManaged */,
false /* expectRestricted */);
}
@Test
public void testGetUnderlyingNetworkPolicy_restrictCell() throws Exception {
checkGetUnderlyingNetworkPolicy(
TRANSPORT_CELLULAR,
true /* isTransportRestricted */,
true /* isActive */,
true /* expectVcnManaged */,
true /* expectRestricted */);
}
@Test
public void testGetUnderlyingNetworkPolicy_restrictCellSafeMode() throws Exception {
checkGetUnderlyingNetworkPolicy(
TRANSPORT_CELLULAR,
true /* isTransportRestricted */,
false /* isActive */,
false /* expectVcnManaged */,
false /* expectRestricted */);
}
@Test
public void testGetUnderlyingNetworkPolicy_unrestrictWifi() throws Exception {
checkGetUnderlyingNetworkPolicy(
TRANSPORT_WIFI,
false /* isTransportRestricted */,
true /* isActive */,
true /* expectVcnManaged */,
false /* expectRestricted */);
}
@Test
public void testGetUnderlyingNetworkPolicy_unrestrictWifiSafeMode() throws Exception {
checkGetUnderlyingNetworkPolicy(
TRANSPORT_WIFI,
false /* isTransportRestricted */,
false /* isActive */,
false /* expectVcnManaged */,
false /* expectRestricted */);
}
@Test
public void testGetUnderlyingNetworkPolicy_restrictWifi() throws Exception {
checkGetUnderlyingNetworkPolicy(
TRANSPORT_WIFI,
true /* isTransportRestricted */,
true /* isActive */,
true /* expectVcnManaged */,
true /* expectRestricted */);
}
@Test
public void testGetUnderlyingNetworkPolicy_restrictWifiSafeMode() throws Exception {
checkGetUnderlyingNetworkPolicy(
TRANSPORT_WIFI,
true /* isTransportRestricted */,
false /* isActive */,
false /* expectVcnManaged */,
true /* expectRestricted */);
}
@Test
public void testGetUnderlyingNetworkPolicyCell_restrictWifi() throws Exception {
doReturn(Collections.singleton(TRANSPORT_WIFI))
.when(mMockDeps)
.getRestrictedTransports(any(), any());
setupSubscriptionAndStartVcn(TEST_SUBSCRIPTION_ID, TEST_UUID_2, true /* isVcnActive */);
// Get the policy for a cellular network and expect it won't be affected by the wifi
// restriction policy
final VcnUnderlyingNetworkPolicy policy =
mVcnMgmtSvc.getUnderlyingNetworkPolicy(
getNetworkCapabilitiesBuilderForTransport(
TEST_SUBSCRIPTION_ID, TRANSPORT_CELLULAR)
.build(),
new LinkProperties());
assertFalse(policy.isTeardownRequested()); assertFalse(policy.isTeardownRequested());
verifyMergedNetworkCapabilities( verifyMergedNetworkCapabilities(
policy.getMergedNetworkCapabilities(), policy.getMergedNetworkCapabilities(),
TRANSPORT_CELLULAR, TRANSPORT_CELLULAR,
true /* isVcnManaged */, true /* expectVcnManaged */,
false /* isRestricted */); false /* expectRestricted */);
}
@Test
public void testGetUnderlyingNetworkPolicyCellular_safeMode() throws Exception {
final VcnUnderlyingNetworkPolicy policy =
startVcnAndGetPolicyForTransport(
TEST_SUBSCRIPTION_ID,
TEST_UUID_2,
false /* isActive */,
TRANSPORT_CELLULAR);
assertFalse(policy.isTeardownRequested());
verifyMergedNetworkCapabilities(
policy.getMergedNetworkCapabilities(),
NetworkCapabilities.TRANSPORT_CELLULAR,
false /* isVcnManaged */,
false /* isRestricted */);
}
@Test
public void testGetUnderlyingNetworkPolicyWifi() throws Exception {
final VcnUnderlyingNetworkPolicy policy =
startVcnAndGetPolicyForTransport(
TEST_SUBSCRIPTION_ID, TEST_UUID_2, true /* isActive */, TRANSPORT_WIFI);
assertFalse(policy.isTeardownRequested());
verifyMergedNetworkCapabilities(
policy.getMergedNetworkCapabilities(),
NetworkCapabilities.TRANSPORT_WIFI,
true /* isVcnManaged */,
true /* isRestricted */);
}
@Test
public void testGetUnderlyingNetworkPolicyVcnWifi_safeMode() throws Exception {
final VcnUnderlyingNetworkPolicy policy =
startVcnAndGetPolicyForTransport(
TEST_SUBSCRIPTION_ID, TEST_UUID_2, false /* isActive */, TRANSPORT_WIFI);
assertFalse(policy.isTeardownRequested());
verifyMergedNetworkCapabilities(
policy.getMergedNetworkCapabilities(),
NetworkCapabilities.TRANSPORT_WIFI,
false /* isVcnManaged */,
true /* isRestricted */);
} }
private void setupTrackedCarrierWifiNetwork(NetworkCapabilities caps) { private void setupTrackedCarrierWifiNetwork(NetworkCapabilities caps) {
@@ -1137,6 +1269,27 @@ public class VcnManagementServiceTest {
assertTrue(policy.isTeardownRequested()); assertTrue(policy.isTeardownRequested());
} }
@Test
public void testGetUnderlyingNetworkPolicyForRestrictedImsWhenUnrestrictingCell()
throws Exception {
final NetworkCapabilities existingNetworkCaps =
getNetworkCapabilitiesBuilderForTransport(TEST_SUBSCRIPTION_ID, TRANSPORT_CELLULAR)
.addCapability(NET_CAPABILITY_NOT_RESTRICTED)
.removeCapability(NET_CAPABILITY_IMS)
.build();
setupTrackedCarrierWifiNetwork(existingNetworkCaps);
final VcnUnderlyingNetworkPolicy policy =
mVcnMgmtSvc.getUnderlyingNetworkPolicy(
getNetworkCapabilitiesBuilderForTransport(
TEST_SUBSCRIPTION_ID, TRANSPORT_CELLULAR)
.addCapability(NET_CAPABILITY_IMS)
.removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
.build(),
new LinkProperties());
assertFalse(policy.isTeardownRequested());
}
@Test @Test
public void testGetUnderlyingNetworkPolicyNonVcnNetwork() throws Exception { public void testGetUnderlyingNetworkPolicyNonVcnNetwork() throws Exception {
setupSubscriptionAndStartVcn(TEST_SUBSCRIPTION_ID, TEST_UUID_1, true /* isActive */); setupSubscriptionAndStartVcn(TEST_SUBSCRIPTION_ID, TEST_UUID_1, true /* isActive */);
@@ -1217,6 +1370,30 @@ public class VcnManagementServiceTest {
verify(mMockPolicyListener).onPolicyChanged(); verify(mMockPolicyListener).onPolicyChanged();
} }
@Test
public void testVcnCarrierConfigChangeUpdatesPolicyListener() throws Exception {
setupActiveSubscription(TEST_UUID_2);
mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME);
mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListenerForTest(mMockPolicyListener);
final TelephonySubscriptionSnapshot snapshot =
buildSubscriptionSnapshot(
TEST_SUBSCRIPTION_ID,
TEST_UUID_2,
Collections.singleton(TEST_UUID_2),
Collections.emptyMap(),
true /* hasCarrierPrivileges */);
final PersistableBundleWrapper mockCarrierConfig = mock(PersistableBundleWrapper.class);
doReturn(mockCarrierConfig).when(snapshot).getCarrierConfigForSubGrp(eq(TEST_UUID_2));
final TelephonySubscriptionTrackerCallback cb = getTelephonySubscriptionTrackerCallback();
cb.onNewSnapshot(snapshot);
verify(mMockPolicyListener).onPolicyChanged();
}
private void triggerVcnSafeMode( private void triggerVcnSafeMode(
@NonNull ParcelUuid subGroup, @NonNull ParcelUuid subGroup,
@NonNull TelephonySubscriptionSnapshot snapshot, @NonNull TelephonySubscriptionSnapshot snapshot,

View File

@@ -16,6 +16,9 @@
package com.android.server.vcn; package com.android.server.vcn;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.vcn.VcnManager.VCN_RESTRICTED_TRANSPORTS_INT_ARRAY_KEY;
import static android.telephony.CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED; import static android.telephony.CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED;
import static android.telephony.CarrierConfigManager.EXTRA_SLOT_INDEX; import static android.telephony.CarrierConfigManager.EXTRA_SLOT_INDEX;
import static android.telephony.CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX; import static android.telephony.CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX;
@@ -39,6 +42,7 @@ import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -493,6 +497,37 @@ public class TelephonySubscriptionTrackerTest {
verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(emptyMap(), emptyMap()))); verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(emptyMap(), emptyMap())));
} }
@Test
public void testCarrierConfigUpdatedAfterValidTriggersCallbacks() throws Exception {
mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true));
mTestLooper.dispatchAll();
verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(TEST_PRIVILEGED_PACKAGES)));
reset(mCallback);
final PersistableBundle updatedConfig = new PersistableBundle();
updatedConfig.putIntArray(
VCN_RESTRICTED_TRANSPORTS_INT_ARRAY_KEY,
new int[] {TRANSPORT_WIFI, TRANSPORT_CELLULAR});
doReturn(updatedConfig)
.when(mCarrierConfigManager)
.getConfigForSubId(eq(TEST_SUBSCRIPTION_ID_1));
Map<Integer, PersistableBundleWrapper> subIdToCarrierConfigMap = new HashMap<>();
subIdToCarrierConfigMap.put(
TEST_SUBSCRIPTION_ID_1, new PersistableBundleWrapper(updatedConfig));
mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true));
mTestLooper.dispatchAll();
verify(mCallback)
.onNewSnapshot(
eq(
buildExpectedSnapshot(
0,
TEST_SUBID_TO_INFO_MAP,
subIdToCarrierConfigMap,
TEST_PRIVILEGED_PACKAGES)));
}
@Test @Test
public void testSlotClearedAfterValidTriggersCallbacks() throws Exception { public void testSlotClearedAfterValidTriggersCallbacks() throws Exception {
mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true)); mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true));