Merge changes Iaeb1871b,I1687df02
* changes: Add restrictions on underlying networks with CarrierConfig Support configuring the VCN restriction policy
This commit is contained in:
@@ -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<
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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()) {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|||||||
Reference in New Issue
Block a user