Merge changes I21aaab57,Ie174f7ec

* changes:
  Expose APIs to configure transports to be restricted by VCN
  Add restrictions on underlying networks with VcnConfig
This commit is contained in:
Yan Yan
2022-12-13 19:04:24 +00:00
committed by Gerrit Code Review
5 changed files with 254 additions and 30 deletions

View File

@@ -27285,6 +27285,7 @@ package android.net.vcn {
public final class VcnConfig implements android.os.Parcelable { public final class VcnConfig implements android.os.Parcelable {
method public int describeContents(); method public int describeContents();
method @NonNull public java.util.Set<android.net.vcn.VcnGatewayConnectionConfig> getGatewayConnectionConfigs(); method @NonNull public java.util.Set<android.net.vcn.VcnGatewayConnectionConfig> getGatewayConnectionConfigs();
method @NonNull public java.util.Set<java.lang.Integer> getRestrictedUnderlyingNetworkTransports();
method public void writeToParcel(@NonNull android.os.Parcel, int); method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.vcn.VcnConfig> CREATOR; field @NonNull public static final android.os.Parcelable.Creator<android.net.vcn.VcnConfig> CREATOR;
} }
@@ -27293,6 +27294,7 @@ package android.net.vcn {
ctor public VcnConfig.Builder(@NonNull android.content.Context); ctor public VcnConfig.Builder(@NonNull android.content.Context);
method @NonNull public android.net.vcn.VcnConfig.Builder addGatewayConnectionConfig(@NonNull android.net.vcn.VcnGatewayConnectionConfig); method @NonNull public android.net.vcn.VcnConfig.Builder addGatewayConnectionConfig(@NonNull android.net.vcn.VcnGatewayConnectionConfig);
method @NonNull public android.net.vcn.VcnConfig build(); method @NonNull public android.net.vcn.VcnConfig build();
method @NonNull public android.net.vcn.VcnConfig.Builder setRestrictedUnderlyingNetworkTransports(@NonNull java.util.Set<java.lang.Integer>);
} }
public final class VcnGatewayConnectionConfig { public final class VcnGatewayConnectionConfig {

View File

@@ -15,16 +15,23 @@
*/ */
package android.net.vcn; package android.net.vcn;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static com.android.internal.annotations.VisibleForTesting.Visibility; import static com.android.internal.annotations.VisibleForTesting.Visibility;
import static com.android.server.vcn.util.PersistableBundleUtils.INTEGER_DESERIALIZER;
import static com.android.server.vcn.util.PersistableBundleUtils.INTEGER_SERIALIZER;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.content.Context; import android.content.Context;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest; import android.net.NetworkRequest;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import android.os.PersistableBundle; import android.os.PersistableBundle;
import android.util.ArraySet; import android.util.ArraySet;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions; import com.android.internal.util.Preconditions;
@@ -32,6 +39,7 @@ import com.android.server.vcn.util.PersistableBundleUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
@@ -46,22 +54,36 @@ import java.util.Set;
public final class VcnConfig implements Parcelable { public final class VcnConfig implements Parcelable {
@NonNull private static final String TAG = VcnConfig.class.getSimpleName(); @NonNull private static final String TAG = VcnConfig.class.getSimpleName();
private static final Set<Integer> ALLOWED_TRANSPORTS = new ArraySet<>();
static {
ALLOWED_TRANSPORTS.add(TRANSPORT_WIFI);
ALLOWED_TRANSPORTS.add(TRANSPORT_CELLULAR);
}
private static final String PACKAGE_NAME_KEY = "mPackageName"; private static final String PACKAGE_NAME_KEY = "mPackageName";
@NonNull private final String mPackageName; @NonNull private final String mPackageName;
private static final String GATEWAY_CONNECTION_CONFIGS_KEY = "mGatewayConnectionConfigs"; private static final String GATEWAY_CONNECTION_CONFIGS_KEY = "mGatewayConnectionConfigs";
@NonNull private final Set<VcnGatewayConnectionConfig> mGatewayConnectionConfigs; @NonNull private final Set<VcnGatewayConnectionConfig> mGatewayConnectionConfigs;
private static final Set<Integer> RESTRICTED_TRANSPORTS_DEFAULT =
Collections.singleton(TRANSPORT_WIFI);
private static final String RESTRICTED_TRANSPORTS_KEY = "mRestrictedTransports";
@NonNull private final Set<Integer> mRestrictedTransports;
private static final String IS_TEST_MODE_PROFILE_KEY = "mIsTestModeProfile"; private static final String IS_TEST_MODE_PROFILE_KEY = "mIsTestModeProfile";
private final boolean mIsTestModeProfile; private final boolean mIsTestModeProfile;
private VcnConfig( private VcnConfig(
@NonNull String packageName, @NonNull String packageName,
@NonNull Set<VcnGatewayConnectionConfig> gatewayConnectionConfigs, @NonNull Set<VcnGatewayConnectionConfig> gatewayConnectionConfigs,
@NonNull Set<Integer> restrictedTransports,
boolean isTestModeProfile) { boolean isTestModeProfile) {
mPackageName = packageName; mPackageName = packageName;
mGatewayConnectionConfigs = mGatewayConnectionConfigs =
Collections.unmodifiableSet(new ArraySet<>(gatewayConnectionConfigs)); Collections.unmodifiableSet(new ArraySet<>(gatewayConnectionConfigs));
mRestrictedTransports = Collections.unmodifiableSet(new ArraySet<>(restrictedTransports));
mIsTestModeProfile = isTestModeProfile; mIsTestModeProfile = isTestModeProfile;
validate(); validate();
@@ -82,6 +104,20 @@ public final class VcnConfig implements Parcelable {
new ArraySet<>( new ArraySet<>(
PersistableBundleUtils.toList( PersistableBundleUtils.toList(
gatewayConnectionConfigsBundle, VcnGatewayConnectionConfig::new)); gatewayConnectionConfigsBundle, VcnGatewayConnectionConfig::new));
final PersistableBundle restrictedTransportsBundle =
in.getPersistableBundle(RESTRICTED_TRANSPORTS_KEY);
if (restrictedTransportsBundle == null) {
// RESTRICTED_TRANSPORTS_KEY was added in U and does not exist in VcnConfigs created in
// older platforms
mRestrictedTransports = RESTRICTED_TRANSPORTS_DEFAULT;
} else {
mRestrictedTransports =
new ArraySet<Integer>(
PersistableBundleUtils.toList(
restrictedTransportsBundle, INTEGER_DESERIALIZER));
}
mIsTestModeProfile = in.getBoolean(IS_TEST_MODE_PROFILE_KEY); mIsTestModeProfile = in.getBoolean(IS_TEST_MODE_PROFILE_KEY);
validate(); validate();
@@ -91,6 +127,19 @@ public final class VcnConfig implements Parcelable {
Objects.requireNonNull(mPackageName, "packageName was null"); Objects.requireNonNull(mPackageName, "packageName was null");
Preconditions.checkCollectionNotEmpty( Preconditions.checkCollectionNotEmpty(
mGatewayConnectionConfigs, "gatewayConnectionConfigs was empty"); mGatewayConnectionConfigs, "gatewayConnectionConfigs was empty");
final Iterator<Integer> iterator = mRestrictedTransports.iterator();
while (iterator.hasNext()) {
final int transport = iterator.next();
if (!ALLOWED_TRANSPORTS.contains(transport)) {
iterator.remove();
Log.w(
TAG,
"Found invalid transport "
+ transport
+ " which might be from a new version of VcnConfig");
}
}
} }
/** /**
@@ -109,6 +158,16 @@ public final class VcnConfig implements Parcelable {
return Collections.unmodifiableSet(mGatewayConnectionConfigs); return Collections.unmodifiableSet(mGatewayConnectionConfigs);
} }
/**
* Retrieve the transports that will be restricted by the VCN.
*
* @see Builder#setRestrictedUnderlyingNetworkTransports(Set)
*/
@NonNull
public Set<Integer> getRestrictedUnderlyingNetworkTransports() {
return Collections.unmodifiableSet(mRestrictedTransports);
}
/** /**
* Returns whether or not this VcnConfig is restricted to test networks. * Returns whether or not this VcnConfig is restricted to test networks.
* *
@@ -134,6 +193,12 @@ public final class VcnConfig implements Parcelable {
new ArrayList<>(mGatewayConnectionConfigs), new ArrayList<>(mGatewayConnectionConfigs),
VcnGatewayConnectionConfig::toPersistableBundle); VcnGatewayConnectionConfig::toPersistableBundle);
result.putPersistableBundle(GATEWAY_CONNECTION_CONFIGS_KEY, gatewayConnectionConfigsBundle); result.putPersistableBundle(GATEWAY_CONNECTION_CONFIGS_KEY, gatewayConnectionConfigsBundle);
final PersistableBundle restrictedTransportsBundle =
PersistableBundleUtils.fromList(
new ArrayList<>(mRestrictedTransports), INTEGER_SERIALIZER);
result.putPersistableBundle(RESTRICTED_TRANSPORTS_KEY, restrictedTransportsBundle);
result.putBoolean(IS_TEST_MODE_PROFILE_KEY, mIsTestModeProfile); result.putBoolean(IS_TEST_MODE_PROFILE_KEY, mIsTestModeProfile);
return result; return result;
@@ -141,7 +206,8 @@ public final class VcnConfig implements Parcelable {
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(mPackageName, mGatewayConnectionConfigs, mIsTestModeProfile); return Objects.hash(
mPackageName, mGatewayConnectionConfigs, mRestrictedTransports, mIsTestModeProfile);
} }
@Override @Override
@@ -153,6 +219,7 @@ public final class VcnConfig implements Parcelable {
final VcnConfig rhs = (VcnConfig) other; final VcnConfig rhs = (VcnConfig) other;
return mPackageName.equals(rhs.mPackageName) return mPackageName.equals(rhs.mPackageName)
&& mGatewayConnectionConfigs.equals(rhs.mGatewayConnectionConfigs) && mGatewayConnectionConfigs.equals(rhs.mGatewayConnectionConfigs)
&& mRestrictedTransports.equals(rhs.mRestrictedTransports)
&& mIsTestModeProfile == rhs.mIsTestModeProfile; && mIsTestModeProfile == rhs.mIsTestModeProfile;
} }
@@ -189,12 +256,15 @@ public final class VcnConfig implements Parcelable {
@NonNull @NonNull
private final Set<VcnGatewayConnectionConfig> mGatewayConnectionConfigs = new ArraySet<>(); private final Set<VcnGatewayConnectionConfig> mGatewayConnectionConfigs = new ArraySet<>();
@NonNull private final Set<Integer> mRestrictedTransports = new ArraySet<>();
private boolean mIsTestModeProfile = false; private boolean mIsTestModeProfile = false;
public Builder(@NonNull Context context) { public Builder(@NonNull Context context) {
Objects.requireNonNull(context, "context was null"); Objects.requireNonNull(context, "context was null");
mPackageName = context.getOpPackageName(); mPackageName = context.getOpPackageName();
mRestrictedTransports.addAll(RESTRICTED_TRANSPORTS_DEFAULT);
} }
/** /**
@@ -225,6 +295,36 @@ public final class VcnConfig implements Parcelable {
return this; return this;
} }
private void validateRestrictedTransportsOrThrow(Set<Integer> restrictedTransports) {
Objects.requireNonNull(restrictedTransports, "transports was null");
for (int transport : restrictedTransports) {
if (!ALLOWED_TRANSPORTS.contains(transport)) {
throw new IllegalArgumentException("Invalid transport " + transport);
}
}
}
/**
* Sets transports that will be restricted by the VCN.
*
* @param transports transports that will be restricted by VCN. Networks that include any
* of the transports will be marked as restricted. Only {@link
* NetworkCapabilities#TRANSPORT_WIFI} and {@link
* NetworkCapabilities#TRANSPORT_CELLULAR} are allowed. {@link
* NetworkCapabilities#TRANSPORT_WIFI} is marked restricted by default.
* @return this {@link Builder} instance, for chaining
* @throws IllegalArgumentException if the input contains unsupported transport types.
*/
@NonNull
public Builder setRestrictedUnderlyingNetworkTransports(@NonNull Set<Integer> transports) {
validateRestrictedTransportsOrThrow(transports);
mRestrictedTransports.clear();
mRestrictedTransports.addAll(transports);
return this;
}
/** /**
* Restricts this VcnConfig to matching with test networks (only). * Restricts this VcnConfig to matching with test networks (only).
* *
@@ -248,7 +348,11 @@ public final class VcnConfig implements Parcelable {
*/ */
@NonNull @NonNull
public VcnConfig build() { public VcnConfig build() {
return new VcnConfig(mPackageName, mGatewayConnectionConfigs, mIsTestModeProfile); return new VcnConfig(
mPackageName,
mGatewayConnectionConfigs,
mRestrictedTransports,
mIsTestModeProfile);
} }
} }
} }

View File

@@ -371,8 +371,9 @@ public class VcnManagementService extends IVcnManagementService.Stub {
return new LocationPermissionChecker(context); return new LocationPermissionChecker(context);
} }
/** Gets the transports that need to be marked as restricted by the VCN */ /** Gets transports that need to be marked as restricted by the VCN from CarrierConfig */
public Set<Integer> getRestrictedTransports( @VisibleForTesting(visibility = Visibility.PRIVATE)
public Set<Integer> getRestrictedTransportsFromCarrierConfig(
ParcelUuid subGrp, TelephonySubscriptionSnapshot lastSnapshot) { ParcelUuid subGrp, TelephonySubscriptionSnapshot lastSnapshot) {
if (!Build.IS_ENG && !Build.IS_USERDEBUG) { if (!Build.IS_ENG && !Build.IS_USERDEBUG) {
return RESTRICTED_TRANSPORTS_DEFAULT; return RESTRICTED_TRANSPORTS_DEFAULT;
@@ -398,6 +399,22 @@ public class VcnManagementService extends IVcnManagementService.Stub {
} }
return restrictedTransports; return restrictedTransports;
} }
/** Gets the transports that need to be marked as restricted by the VCN */
public Set<Integer> getRestrictedTransports(
ParcelUuid subGrp,
TelephonySubscriptionSnapshot lastSnapshot,
VcnConfig vcnConfig) {
final Set<Integer> restrictedTransports = new ArraySet<>();
restrictedTransports.addAll(vcnConfig.getRestrictedUnderlyingNetworkTransports());
// TODO: b/262269892 Remove the ability to configure restricted transports
// via CarrierConfig
restrictedTransports.addAll(
getRestrictedTransportsFromCarrierConfig(subGrp, lastSnapshot));
return restrictedTransports;
}
} }
/** Notifies the VcnManagementService that external dependencies can be set up. */ /** Notifies the VcnManagementService that external dependencies can be set up. */
@@ -719,6 +736,7 @@ public class VcnManagementService extends IVcnManagementService.Stub {
if (mVcns.containsKey(subscriptionGroup)) { if (mVcns.containsKey(subscriptionGroup)) {
final Vcn vcn = mVcns.get(subscriptionGroup); final Vcn vcn = mVcns.get(subscriptionGroup);
vcn.updateConfig(config); vcn.updateConfig(config);
notifyAllPolicyListenersLocked();
} else { } else {
// TODO(b/193687515): Support multiple VCNs active at the same time // TODO(b/193687515): Support multiple VCNs active at the same time
if (isActiveSubGroup(subscriptionGroup, mLastSnapshot)) { if (isActiveSubGroup(subscriptionGroup, mLastSnapshot)) {
@@ -936,7 +954,6 @@ public class VcnManagementService extends IVcnManagementService.Stub {
} }
/** Adds the provided listener for receiving VcnUnderlyingNetworkPolicy updates. */ /** Adds the provided listener for receiving VcnUnderlyingNetworkPolicy updates. */
@GuardedBy("mLock")
@Override @Override
public void addVcnUnderlyingNetworkPolicyListener( public void addVcnUnderlyingNetworkPolicyListener(
@NonNull IVcnUnderlyingNetworkPolicyListener listener) { @NonNull IVcnUnderlyingNetworkPolicyListener listener) {
@@ -963,16 +980,7 @@ 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")
@Override @Override
public void removeVcnUnderlyingNetworkPolicyListener( public void removeVcnUnderlyingNetworkPolicyListener(
@NonNull IVcnUnderlyingNetworkPolicyListener listener) { @NonNull IVcnUnderlyingNetworkPolicyListener listener) {
@@ -1062,8 +1070,8 @@ public class VcnManagementService extends IVcnManagementService.Stub {
isVcnManagedNetwork = true; isVcnManagedNetwork = true;
} }
final Set<Integer> restrictedTransports = final Set<Integer> restrictedTransports = mDeps.getRestrictedTransports(
mDeps.getRestrictedTransports(subGrp, mLastSnapshot); subGrp, mLastSnapshot, mConfigs.get(subGrp));
for (int restrictedTransport : restrictedTransports) { for (int restrictedTransport : restrictedTransports) {
if (ncCopy.hasTransport(restrictedTransport)) { if (ncCopy.hasTransport(restrictedTransport)) {
if (restrictedTransport == TRANSPORT_CELLULAR) { if (restrictedTransport == TRANSPORT_CELLULAR) {

View File

@@ -16,7 +16,12 @@
package android.net.vcn; package android.net.vcn;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
@@ -24,6 +29,7 @@ import static org.mockito.Mockito.mock;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.content.Context; import android.content.Context;
import android.os.Parcel; import android.os.Parcel;
import android.util.ArraySet;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4; import androidx.test.runner.AndroidJUnit4;
@@ -42,19 +48,36 @@ public class VcnConfigTest {
private static final Set<VcnGatewayConnectionConfig> GATEWAY_CONNECTION_CONFIGS = private static final Set<VcnGatewayConnectionConfig> GATEWAY_CONNECTION_CONFIGS =
Collections.singleton(VcnGatewayConnectionConfigTest.buildTestConfig()); Collections.singleton(VcnGatewayConnectionConfigTest.buildTestConfig());
private static final Set<Integer> RESTRICTED_TRANSPORTS = new ArraySet<>();
static {
RESTRICTED_TRANSPORTS.add(TRANSPORT_WIFI);
RESTRICTED_TRANSPORTS.add(TRANSPORT_CELLULAR);
}
private final Context mContext = mock(Context.class); private final Context mContext = mock(Context.class);
// Public visibility for VcnManagementServiceTest // Public visibility for VcnManagementServiceTest
public static VcnConfig buildTestConfig(@NonNull Context context) { public static VcnConfig buildTestConfig(
@NonNull Context context, Set<Integer> restrictedTransports) {
VcnConfig.Builder builder = new VcnConfig.Builder(context); VcnConfig.Builder builder = new VcnConfig.Builder(context);
for (VcnGatewayConnectionConfig gatewayConnectionConfig : GATEWAY_CONNECTION_CONFIGS) { for (VcnGatewayConnectionConfig gatewayConnectionConfig : GATEWAY_CONNECTION_CONFIGS) {
builder.addGatewayConnectionConfig(gatewayConnectionConfig); builder.addGatewayConnectionConfig(gatewayConnectionConfig);
} }
if (restrictedTransports != null) {
builder.setRestrictedUnderlyingNetworkTransports(restrictedTransports);
}
return builder.build(); return builder.build();
} }
// Public visibility for VcnManagementServiceTest
public static VcnConfig buildTestConfig(@NonNull Context context) {
return buildTestConfig(context, null);
}
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
doReturn(TEST_PACKAGE_NAME).when(mContext).getOpPackageName(); doReturn(TEST_PACKAGE_NAME).when(mContext).getOpPackageName();
@@ -91,11 +114,25 @@ public class VcnConfigTest {
} }
@Test @Test
public void testBuilderAndGetters() { public void testBuilderAndGettersDefaultValues() {
final VcnConfig config = buildTestConfig(mContext); final VcnConfig config = buildTestConfig(mContext);
assertEquals(TEST_PACKAGE_NAME, config.getProvisioningPackageName()); assertEquals(TEST_PACKAGE_NAME, config.getProvisioningPackageName());
assertEquals(GATEWAY_CONNECTION_CONFIGS, config.getGatewayConnectionConfigs()); assertEquals(GATEWAY_CONNECTION_CONFIGS, config.getGatewayConnectionConfigs());
assertFalse(config.isTestModeProfile());
assertEquals(
Collections.singleton(TRANSPORT_WIFI),
config.getRestrictedUnderlyingNetworkTransports());
}
@Test
public void testBuilderAndGettersConfigRestrictedTransports() {
final VcnConfig config = buildTestConfig(mContext, RESTRICTED_TRANSPORTS);
assertEquals(TEST_PACKAGE_NAME, config.getProvisioningPackageName());
assertEquals(GATEWAY_CONNECTION_CONFIGS, config.getGatewayConnectionConfigs());
assertFalse(config.isTestModeProfile());
assertEquals(RESTRICTED_TRANSPORTS, config.getRestrictedUnderlyingNetworkTransports());
} }
@Test @Test
@@ -105,6 +142,24 @@ public class VcnConfigTest {
assertEquals(config, new VcnConfig(config.toPersistableBundle())); assertEquals(config, new VcnConfig(config.toPersistableBundle()));
} }
@Test
public void testPersistableBundleWithRestrictedTransports() {
final VcnConfig config = buildTestConfig(mContext, RESTRICTED_TRANSPORTS);
assertEquals(config, new VcnConfig(config.toPersistableBundle()));
}
@Test
public void testEqualityWithRestrictedTransports() {
final VcnConfig config = buildTestConfig(mContext, RESTRICTED_TRANSPORTS);
final VcnConfig configEqual = buildTestConfig(mContext, RESTRICTED_TRANSPORTS);
final VcnConfig configNotEqual =
buildTestConfig(mContext, Collections.singleton(TRANSPORT_WIFI));
assertEquals(config, configEqual);
assertNotEquals(config, configNotEqual);
}
@Test @Test
public void testParceling() { public void testParceling() {
final VcnConfig config = buildTestConfig(mContext); final VcnConfig config = buildTestConfig(mContext);

View File

@@ -258,7 +258,7 @@ public class VcnManagementServiceTest {
doReturn(Collections.singleton(TRANSPORT_WIFI)) doReturn(Collections.singleton(TRANSPORT_WIFI))
.when(mMockDeps) .when(mMockDeps)
.getRestrictedTransports(any(), any()); .getRestrictedTransports(any(), any(), any());
} }
@@ -1038,18 +1038,18 @@ public class VcnManagementServiceTest {
new LinkProperties()); new LinkProperties());
} }
private void checkGetRestrictedTransports( private void checkGetRestrictedTransportsFromCarrierConfig(
ParcelUuid subGrp, ParcelUuid subGrp,
TelephonySubscriptionSnapshot lastSnapshot, TelephonySubscriptionSnapshot lastSnapshot,
Set<Integer> expectedTransports) { Set<Integer> expectedTransports) {
Set<Integer> result = Set<Integer> result =
new VcnManagementService.Dependencies() new VcnManagementService.Dependencies()
.getRestrictedTransports(subGrp, lastSnapshot); .getRestrictedTransportsFromCarrierConfig(subGrp, lastSnapshot);
assertEquals(expectedTransports, result); assertEquals(expectedTransports, result);
} }
@Test @Test
public void testGetRestrictedTransports() { public void testGetRestrictedTransportsFromCarrierConfig() {
final Set<Integer> restrictedTransports = new ArraySet<>(); final Set<Integer> restrictedTransports = new ArraySet<>();
restrictedTransports.add(TRANSPORT_CELLULAR); restrictedTransports.add(TRANSPORT_CELLULAR);
restrictedTransports.add(TRANSPORT_WIFI); restrictedTransports.add(TRANSPORT_WIFI);
@@ -1065,11 +1065,12 @@ public class VcnManagementServiceTest {
mock(TelephonySubscriptionSnapshot.class); mock(TelephonySubscriptionSnapshot.class);
doReturn(carrierConfig).when(lastSnapshot).getCarrierConfigForSubGrp(eq(TEST_UUID_2)); doReturn(carrierConfig).when(lastSnapshot).getCarrierConfigForSubGrp(eq(TEST_UUID_2));
checkGetRestrictedTransports(TEST_UUID_2, lastSnapshot, restrictedTransports); checkGetRestrictedTransportsFromCarrierConfig(
TEST_UUID_2, lastSnapshot, restrictedTransports);
} }
@Test @Test
public void testGetRestrictedTransports_noRestrictPolicyConfigured() { public void testGetRestrictedTransportsFromCarrierConfig_noRestrictPolicyConfigured() {
final Set<Integer> restrictedTransports = Collections.singleton(TRANSPORT_WIFI); final Set<Integer> restrictedTransports = Collections.singleton(TRANSPORT_WIFI);
final PersistableBundleWrapper carrierConfig = final PersistableBundleWrapper carrierConfig =
@@ -1078,17 +1079,54 @@ public class VcnManagementServiceTest {
mock(TelephonySubscriptionSnapshot.class); mock(TelephonySubscriptionSnapshot.class);
doReturn(carrierConfig).when(lastSnapshot).getCarrierConfigForSubGrp(eq(TEST_UUID_2)); doReturn(carrierConfig).when(lastSnapshot).getCarrierConfigForSubGrp(eq(TEST_UUID_2));
checkGetRestrictedTransports(TEST_UUID_2, lastSnapshot, restrictedTransports); checkGetRestrictedTransportsFromCarrierConfig(
TEST_UUID_2, lastSnapshot, restrictedTransports);
} }
@Test @Test
public void testGetRestrictedTransports_noCarrierConfig() { public void testGetRestrictedTransportsFromCarrierConfig_noCarrierConfig() {
final Set<Integer> restrictedTransports = Collections.singleton(TRANSPORT_WIFI); final Set<Integer> restrictedTransports = Collections.singleton(TRANSPORT_WIFI);
final TelephonySubscriptionSnapshot lastSnapshot = final TelephonySubscriptionSnapshot lastSnapshot =
mock(TelephonySubscriptionSnapshot.class); mock(TelephonySubscriptionSnapshot.class);
checkGetRestrictedTransports(TEST_UUID_2, lastSnapshot, restrictedTransports); checkGetRestrictedTransportsFromCarrierConfig(
TEST_UUID_2, lastSnapshot, restrictedTransports);
}
@Test
public void testGetRestrictedTransportsFromCarrierConfigAndVcnConfig() {
// Configure restricted transport in CarrierConfig
final Set<Integer> restrictedTransportInCarrierConfig =
Collections.singleton(TRANSPORT_WIFI);
PersistableBundle carrierConfigBundle = new PersistableBundle();
carrierConfigBundle.putIntArray(
VCN_RESTRICTED_TRANSPORTS_INT_ARRAY_KEY,
restrictedTransportInCarrierConfig.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));
// Configure restricted transport in VcnConfig
final Context mockContext = mock(Context.class);
doReturn(TEST_PACKAGE_NAME).when(mockContext).getOpPackageName();
final VcnConfig vcnConfig =
VcnConfigTest.buildTestConfig(
mockContext, Collections.singleton(TRANSPORT_CELLULAR));
// Verifications
final Set<Integer> expectedTransports = new ArraySet<>();
expectedTransports.add(TRANSPORT_CELLULAR);
expectedTransports.add(TRANSPORT_WIFI);
Set<Integer> result =
new VcnManagementService.Dependencies()
.getRestrictedTransports(TEST_UUID_2, lastSnapshot, vcnConfig);
assertEquals(expectedTransports, result);
} }
private void checkGetUnderlyingNetworkPolicy( private void checkGetUnderlyingNetworkPolicy(
@@ -1103,7 +1141,7 @@ public class VcnManagementServiceTest {
if (isTransportRestricted) { if (isTransportRestricted) {
restrictedTransports.add(transportType); restrictedTransports.add(transportType);
} }
doReturn(restrictedTransports).when(mMockDeps).getRestrictedTransports(any(), any()); doReturn(restrictedTransports).when(mMockDeps).getRestrictedTransports(any(), any(), any());
final VcnUnderlyingNetworkPolicy policy = final VcnUnderlyingNetworkPolicy policy =
startVcnAndGetPolicyForTransport( startVcnAndGetPolicyForTransport(
@@ -1201,7 +1239,7 @@ public class VcnManagementServiceTest {
public void testGetUnderlyingNetworkPolicyCell_restrictWifi() throws Exception { public void testGetUnderlyingNetworkPolicyCell_restrictWifi() throws Exception {
doReturn(Collections.singleton(TRANSPORT_WIFI)) doReturn(Collections.singleton(TRANSPORT_WIFI))
.when(mMockDeps) .when(mMockDeps)
.getRestrictedTransports(any(), any()); .getRestrictedTransports(any(), any(), any());
setupSubscriptionAndStartVcn(TEST_SUBSCRIPTION_ID, TEST_UUID_2, true /* isVcnActive */); setupSubscriptionAndStartVcn(TEST_SUBSCRIPTION_ID, TEST_UUID_2, true /* isVcnActive */);
@@ -1343,6 +1381,23 @@ public class VcnManagementServiceTest {
verify(mMockPolicyListener).onPolicyChanged(); verify(mMockPolicyListener).onPolicyChanged();
} }
@Test
public void testVcnConfigChangeUpdatesPolicyListener() throws Exception {
setupActiveSubscription(TEST_UUID_2);
mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME);
mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
final Context mockContext = mock(Context.class);
doReturn(TEST_PACKAGE_NAME).when(mockContext).getOpPackageName();
final VcnConfig vcnConfig =
VcnConfigTest.buildTestConfig(
mockContext, Collections.singleton(TRANSPORT_CELLULAR));
mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, vcnConfig, TEST_PACKAGE_NAME);
verify(mMockPolicyListener).onPolicyChanged();
}
@Test @Test
public void testRemoveVcnUpdatesPolicyListener() throws Exception { public void testRemoveVcnUpdatesPolicyListener() throws Exception {
setupActiveSubscription(TEST_UUID_2); setupActiveSubscription(TEST_UUID_2);
@@ -1375,7 +1430,7 @@ public class VcnManagementServiceTest {
setupActiveSubscription(TEST_UUID_2); setupActiveSubscription(TEST_UUID_2);
mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME);
mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListenerForTest(mMockPolicyListener); mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
final TelephonySubscriptionSnapshot snapshot = final TelephonySubscriptionSnapshot snapshot =
buildSubscriptionSnapshot( buildSubscriptionSnapshot(