Merge "Allow provisioning package to retrieve subGrp, clear it's own config" am: 1428215bee am: 6b6f825b26

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/2056512

Change-Id: I45ec1d4039ab2945db497f07d8cc91b364c7a4e9
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Benedict Wong
2022-04-14 19:24:59 +00:00
committed by Automerger Merge Worker
3 changed files with 228 additions and 53 deletions

View File

@@ -172,11 +172,11 @@ public class VcnManager {
* *
* <p>An app that has carrier privileges for any of the subscriptions in the given group may * <p>An app that has carrier privileges for any of the subscriptions in the given group may
* clear a VCN configuration. This API is ONLY permitted for callers running as the primary * clear a VCN configuration. This API is ONLY permitted for callers running as the primary
* user. Any active VCN will be torn down. * user. Any active VCN associated with this configuration will be torn down.
* *
* @param subscriptionGroup the subscription group that the configuration should be applied to * @param subscriptionGroup the subscription group that the configuration should be applied to
* @throws SecurityException if the caller does not have carrier privileges, or is not running * @throws SecurityException if the caller does not have carrier privileges, is not the owner of
* as the primary user * the associated configuration, or is not running as the primary user
* @throws IOException if the configuration failed to be cleared from disk. This may occur due * @throws IOException if the configuration failed to be cleared from disk. This may occur due
* to temporary disk errors, or more permanent conditions such as a full disk. * to temporary disk errors, or more permanent conditions such as a full disk.
*/ */
@@ -196,8 +196,13 @@ public class VcnManager {
/** /**
* Retrieves the list of Subscription Groups for which a VCN Configuration has been set. * Retrieves the list of Subscription Groups for which a VCN Configuration has been set.
* *
* <p>The returned list will include only subscription groups for which the carrier app is * <p>The returned list will include only subscription groups for which an associated {@link
* privileged, and which have an associated {@link VcnConfig}. * VcnConfig} exists, and the app is either:
*
* <ul>
* <li>Carrier privileged for that subscription group, or
* <li>Is the provisioning package of the config
* </ul>
* *
* @throws SecurityException if the caller is not running as the primary user * @throws SecurityException if the caller is not running as the primary user
*/ */

View File

@@ -87,6 +87,7 @@ import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
@@ -172,7 +173,7 @@ public class VcnManagementService extends IVcnManagementService.Stub {
@NonNull private final VcnNetworkProvider mNetworkProvider; @NonNull private final VcnNetworkProvider mNetworkProvider;
@NonNull private final TelephonySubscriptionTrackerCallback mTelephonySubscriptionTrackerCb; @NonNull private final TelephonySubscriptionTrackerCallback mTelephonySubscriptionTrackerCb;
@NonNull private final TelephonySubscriptionTracker mTelephonySubscriptionTracker; @NonNull private final TelephonySubscriptionTracker mTelephonySubscriptionTracker;
@NonNull private final BroadcastReceiver mPkgChangeReceiver; @NonNull private final BroadcastReceiver mVcnBroadcastReceiver;
@NonNull @NonNull
private final TrackingNetworkCallback mTrackingNetworkCallback = new TrackingNetworkCallback(); private final TrackingNetworkCallback mTrackingNetworkCallback = new TrackingNetworkCallback();
@@ -217,28 +218,17 @@ public class VcnManagementService extends IVcnManagementService.Stub {
mConfigDiskRwHelper = mDeps.newPersistableBundleLockingReadWriteHelper(VCN_CONFIG_FILE); mConfigDiskRwHelper = mDeps.newPersistableBundleLockingReadWriteHelper(VCN_CONFIG_FILE);
mPkgChangeReceiver = new BroadcastReceiver() { mVcnBroadcastReceiver = new VcnBroadcastReceiver();
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (Intent.ACTION_PACKAGE_ADDED.equals(action)
|| Intent.ACTION_PACKAGE_REPLACED.equals(action)
|| Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
mTelephonySubscriptionTracker.handleSubscriptionsChanged();
} else {
Log.wtf(TAG, "received unexpected intent: " + action);
}
}
};
final IntentFilter intentFilter = new IntentFilter(); final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED); intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED); intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
intentFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
intentFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED);
intentFilter.addDataScheme("package"); intentFilter.addDataScheme("package");
mContext.registerReceiver( mContext.registerReceiver(
mPkgChangeReceiver, intentFilter, null /* broadcastPermission */, mHandler); mVcnBroadcastReceiver, intentFilter, null /* broadcastPermission */, mHandler);
// Run on handler to ensure I/O does not block system server startup // Run on handler to ensure I/O does not block system server startup
mHandler.post(() -> { mHandler.post(() -> {
@@ -443,6 +433,53 @@ public class VcnManagementService extends IVcnManagementService.Stub {
return Objects.equals(subGrp, snapshot.getActiveDataSubscriptionGroup()); return Objects.equals(subGrp, snapshot.getActiveDataSubscriptionGroup());
} }
private class VcnBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
switch (action) {
case Intent.ACTION_PACKAGE_ADDED: // Fallthrough
case Intent.ACTION_PACKAGE_REPLACED: // Fallthrough
case Intent.ACTION_PACKAGE_REMOVED:
// Reevaluate subscriptions
mTelephonySubscriptionTracker.handleSubscriptionsChanged();
break;
case Intent.ACTION_PACKAGE_FULLY_REMOVED:
case Intent.ACTION_PACKAGE_DATA_CLEARED:
final String pkgName = intent.getData().getSchemeSpecificPart();
if (pkgName == null || pkgName.isEmpty()) {
logWtf("Package name was empty or null for intent with action" + action);
return;
}
// Clear configs for the packages that had data cleared, or removed.
synchronized (mLock) {
final List<ParcelUuid> toRemove = new ArrayList<>();
for (Entry<ParcelUuid, VcnConfig> entry : mConfigs.entrySet()) {
if (pkgName.equals(entry.getValue().getProvisioningPackageName())) {
toRemove.add(entry.getKey());
}
}
for (ParcelUuid subGrp : toRemove) {
stopAndClearVcnConfigInternalLocked(subGrp);
}
if (!toRemove.isEmpty()) {
writeConfigsToDiskLocked();
}
}
break;
default:
Slog.wtf(TAG, "received unexpected intent: " + action);
}
}
}
private class VcnSubscriptionTrackerCallback implements TelephonySubscriptionTrackerCallback { private class VcnSubscriptionTrackerCallback implements TelephonySubscriptionTrackerCallback {
/** /**
* Handles subscription group changes, as notified by {@link TelephonySubscriptionTracker} * Handles subscription group changes, as notified by {@link TelephonySubscriptionTracker}
@@ -504,6 +541,7 @@ public class VcnManagementService extends IVcnManagementService.Stub {
final Map<ParcelUuid, Set<Integer>> currSubGrpMappings = final Map<ParcelUuid, Set<Integer>> currSubGrpMappings =
getSubGroupToSubIdMappings(mLastSnapshot); getSubGroupToSubIdMappings(mLastSnapshot);
if (!currSubGrpMappings.equals(oldSubGrpMappings)) { if (!currSubGrpMappings.equals(oldSubGrpMappings)) {
garbageCollectAndWriteVcnConfigsLocked();
notifyAllPolicyListenersLocked(); notifyAllPolicyListenersLocked();
} }
} }
@@ -645,6 +683,39 @@ public class VcnManagementService extends IVcnManagementService.Stub {
}); });
} }
private void enforceCarrierPrivilegeOrProvisioningPackage(
@NonNull ParcelUuid subscriptionGroup, @NonNull String pkg) {
// Only apps running in the primary (system) user are allowed to configure the VCN. This is
// in line with Telephony's behavior with regards to binding to a Carrier App provided
// CarrierConfigService.
enforcePrimaryUser();
if (isProvisioningPackageForConfig(subscriptionGroup, pkg)) {
return;
}
// Must NOT be called from cleared binder identity, since this checks user calling identity
enforceCallingUserAndCarrierPrivilege(subscriptionGroup, pkg);
}
private boolean isProvisioningPackageForConfig(
@NonNull ParcelUuid subscriptionGroup, @NonNull String pkg) {
// Try-finally to return early if matching owned subscription found.
final long identity = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
final VcnConfig config = mConfigs.get(subscriptionGroup);
if (config != null && pkg.equals(config.getProvisioningPackageName())) {
return true;
}
}
} finally {
Binder.restoreCallingIdentity(identity);
}
return false;
}
/** /**
* Clears the VcnManagementService for a given subscription group. * Clears the VcnManagementService for a given subscription group.
* *
@@ -658,31 +729,56 @@ public class VcnManagementService extends IVcnManagementService.Stub {
mContext.getSystemService(AppOpsManager.class) mContext.getSystemService(AppOpsManager.class)
.checkPackage(mDeps.getBinderCallingUid(), opPkgName); .checkPackage(mDeps.getBinderCallingUid(), opPkgName);
enforceCallingUserAndCarrierPrivilege(subscriptionGroup, opPkgName); enforceCarrierPrivilegeOrProvisioningPackage(subscriptionGroup, opPkgName);
Binder.withCleanCallingIdentity(() -> { Binder.withCleanCallingIdentity(() -> {
synchronized (mLock) { synchronized (mLock) {
mConfigs.remove(subscriptionGroup); stopAndClearVcnConfigInternalLocked(subscriptionGroup);
final boolean vcnExists = mVcns.containsKey(subscriptionGroup);
stopVcnLocked(subscriptionGroup);
if (vcnExists) {
// TODO(b/181789060): invoke asynchronously after Vcn notifies through
// VcnCallback
notifyAllPermissionedStatusCallbacksLocked(
subscriptionGroup, VCN_STATUS_CODE_NOT_CONFIGURED);
}
writeConfigsToDiskLocked(); writeConfigsToDiskLocked();
} }
}); });
} }
private void stopAndClearVcnConfigInternalLocked(@NonNull ParcelUuid subscriptionGroup) {
mConfigs.remove(subscriptionGroup);
final boolean vcnExists = mVcns.containsKey(subscriptionGroup);
stopVcnLocked(subscriptionGroup);
if (vcnExists) {
// TODO(b/181789060): invoke asynchronously after Vcn notifies through
// VcnCallback
notifyAllPermissionedStatusCallbacksLocked(
subscriptionGroup, VCN_STATUS_CODE_NOT_CONFIGURED);
}
}
private void garbageCollectAndWriteVcnConfigsLocked() {
final SubscriptionManager subMgr = mContext.getSystemService(SubscriptionManager.class);
boolean shouldWrite = false;
final Iterator<ParcelUuid> configsIterator = mConfigs.keySet().iterator();
while (configsIterator.hasNext()) {
final ParcelUuid subGrp = configsIterator.next();
final List<SubscriptionInfo> subscriptions = subMgr.getSubscriptionsInGroup(subGrp);
if (subscriptions == null || subscriptions.isEmpty()) {
// Trim subGrps with no more subscriptions; must have moved to another subGrp
configsIterator.remove();
shouldWrite = true;
}
}
if (shouldWrite) {
writeConfigsToDiskLocked();
}
}
/** /**
* Retrieves the list of subscription groups with configured VcnConfigs * Retrieves the list of subscription groups with configured VcnConfigs
* *
* <p>Limited to subscription groups for which the caller is carrier privileged. * <p>Limited to subscription groups for which the caller had configured.
* *
* <p>Implements the IVcnManagementService Binder interface. * <p>Implements the IVcnManagementService Binder interface.
*/ */
@@ -698,7 +794,8 @@ public class VcnManagementService extends IVcnManagementService.Stub {
final List<ParcelUuid> result = new ArrayList<>(); final List<ParcelUuid> result = new ArrayList<>();
synchronized (mLock) { synchronized (mLock) {
for (ParcelUuid subGrp : mConfigs.keySet()) { for (ParcelUuid subGrp : mConfigs.keySet()) {
if (mLastSnapshot.packageHasPermissionsForSubscriptionGroup(subGrp, opPkgName)) { if (mLastSnapshot.packageHasPermissionsForSubscriptionGroup(subGrp, opPkgName)
|| isProvisioningPackageForConfig(subGrp, opPkgName)) {
result.add(subGrp); result.add(subGrp);
} }
} }

View File

@@ -65,6 +65,7 @@ import android.net.Network;
import android.net.NetworkCapabilities; import android.net.NetworkCapabilities;
import android.net.NetworkRequest; import android.net.NetworkRequest;
import android.net.TelephonyNetworkSpecifier; import android.net.TelephonyNetworkSpecifier;
import android.net.Uri;
import android.net.vcn.IVcnStatusCallback; import android.net.vcn.IVcnStatusCallback;
import android.net.vcn.IVcnUnderlyingNetworkPolicyListener; import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
import android.net.vcn.VcnConfig; import android.net.vcn.VcnConfig;
@@ -114,18 +115,24 @@ import java.util.UUID;
public class VcnManagementServiceTest { public class VcnManagementServiceTest {
private static final String TEST_PACKAGE_NAME = private static final String TEST_PACKAGE_NAME =
VcnManagementServiceTest.class.getPackage().getName(); VcnManagementServiceTest.class.getPackage().getName();
private static final String TEST_PACKAGE_NAME_2 = "TEST_PKG_2";
private static final String TEST_CB_PACKAGE_NAME = private static final String TEST_CB_PACKAGE_NAME =
VcnManagementServiceTest.class.getPackage().getName() + ".callback"; VcnManagementServiceTest.class.getPackage().getName() + ".callback";
private static final ParcelUuid TEST_UUID_1 = new ParcelUuid(new UUID(0, 0)); private static final ParcelUuid TEST_UUID_1 = new ParcelUuid(new UUID(0, 0));
private static final ParcelUuid TEST_UUID_2 = new ParcelUuid(new UUID(1, 1)); private static final ParcelUuid TEST_UUID_2 = new ParcelUuid(new UUID(1, 1));
private static final ParcelUuid TEST_UUID_3 = new ParcelUuid(new UUID(2, 2));
private static final VcnConfig TEST_VCN_CONFIG; private static final VcnConfig TEST_VCN_CONFIG;
private static final VcnConfig TEST_VCN_CONFIG_PKG_2;
private static final int TEST_UID = Process.FIRST_APPLICATION_UID; private static final int TEST_UID = Process.FIRST_APPLICATION_UID;
static { static {
final Context mockConfigContext = mock(Context.class); final Context mockConfigContext = mock(Context.class);
doReturn(TEST_PACKAGE_NAME).when(mockConfigContext).getOpPackageName();
doReturn(TEST_PACKAGE_NAME).when(mockConfigContext).getOpPackageName();
TEST_VCN_CONFIG = VcnConfigTest.buildTestConfig(mockConfigContext); TEST_VCN_CONFIG = VcnConfigTest.buildTestConfig(mockConfigContext);
doReturn(TEST_PACKAGE_NAME_2).when(mockConfigContext).getOpPackageName();
TEST_VCN_CONFIG_PKG_2 = VcnConfigTest.buildTestConfig(mockConfigContext);
} }
private static final Map<ParcelUuid, VcnConfig> TEST_VCN_CONFIG_MAP = private static final Map<ParcelUuid, VcnConfig> TEST_VCN_CONFIG_MAP =
@@ -246,18 +253,24 @@ public class VcnManagementServiceTest {
eq(android.Manifest.permission.NETWORK_FACTORY), any()); eq(android.Manifest.permission.NETWORK_FACTORY), any());
} }
private void setupMockedCarrierPrivilege(boolean isPrivileged) { private void setupMockedCarrierPrivilege(boolean isPrivileged) {
setupMockedCarrierPrivilege(isPrivileged, TEST_PACKAGE_NAME);
}
private void setupMockedCarrierPrivilege(boolean isPrivileged, String pkg) {
doReturn(Collections.singletonList(TEST_SUBSCRIPTION_INFO)) doReturn(Collections.singletonList(TEST_SUBSCRIPTION_INFO))
.when(mSubMgr) .when(mSubMgr)
.getSubscriptionsInGroup(any()); .getSubscriptionsInGroup(any());
doReturn(mTelMgr) doReturn(mTelMgr)
.when(mTelMgr) .when(mTelMgr)
.createForSubscriptionId(eq(TEST_SUBSCRIPTION_INFO.getSubscriptionId())); .createForSubscriptionId(eq(TEST_SUBSCRIPTION_INFO.getSubscriptionId()));
doReturn(isPrivileged doReturn(
? CARRIER_PRIVILEGE_STATUS_HAS_ACCESS isPrivileged
: CARRIER_PRIVILEGE_STATUS_NO_ACCESS) ? CARRIER_PRIVILEGE_STATUS_HAS_ACCESS
: CARRIER_PRIVILEGE_STATUS_NO_ACCESS)
.when(mTelMgr) .when(mTelMgr)
.checkCarrierPrivilegesForPackage(eq(TEST_PACKAGE_NAME)); .checkCarrierPrivilegesForPackage(eq(pkg));
} }
@Test @Test
@@ -414,7 +427,13 @@ public class VcnManagementServiceTest {
private BroadcastReceiver getPackageChangeReceiver() { private BroadcastReceiver getPackageChangeReceiver() {
final ArgumentCaptor<BroadcastReceiver> captor = final ArgumentCaptor<BroadcastReceiver> captor =
ArgumentCaptor.forClass(BroadcastReceiver.class); ArgumentCaptor.forClass(BroadcastReceiver.class);
verify(mMockContext).registerReceiver(captor.capture(), any(), any(), any()); verify(mMockContext).registerReceiver(captor.capture(), argThat(filter -> {
return filter.hasAction(Intent.ACTION_PACKAGE_ADDED)
&& filter.hasAction(Intent.ACTION_PACKAGE_REPLACED)
&& filter.hasAction(Intent.ACTION_PACKAGE_REMOVED)
&& filter.hasAction(Intent.ACTION_PACKAGE_DATA_CLEARED)
&& filter.hasAction(Intent.ACTION_PACKAGE_FULLY_REMOVED);
}), any(), any());
return captor.getValue(); return captor.getValue();
} }
@@ -538,6 +557,44 @@ public class VcnManagementServiceTest {
verify(mSubscriptionTracker).handleSubscriptionsChanged(); verify(mSubscriptionTracker).handleSubscriptionsChanged();
} }
@Test
public void testPackageChangeListener_packageDataCleared() throws Exception {
triggerSubscriptionTrackerCbAndGetSnapshot(TEST_UUID_1, Collections.singleton(TEST_UUID_1));
final Vcn vcn = mVcnMgmtSvc.getAllVcns().get(TEST_UUID_1);
final BroadcastReceiver receiver = getPackageChangeReceiver();
assertEquals(TEST_VCN_CONFIG_MAP, mVcnMgmtSvc.getConfigs());
final Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED);
intent.setData(Uri.parse("package:" + TEST_PACKAGE_NAME));
intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(TEST_UID));
receiver.onReceive(mMockContext, intent);
mTestLooper.dispatchAll();
verify(vcn).teardownAsynchronously();
assertTrue(mVcnMgmtSvc.getConfigs().isEmpty());
verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class));
}
@Test
public void testPackageChangeListener_packageFullyRemoved() throws Exception {
triggerSubscriptionTrackerCbAndGetSnapshot(TEST_UUID_1, Collections.singleton(TEST_UUID_1));
final Vcn vcn = mVcnMgmtSvc.getAllVcns().get(TEST_UUID_1);
final BroadcastReceiver receiver = getPackageChangeReceiver();
assertEquals(TEST_VCN_CONFIG_MAP, mVcnMgmtSvc.getConfigs());
final Intent intent = new Intent(Intent.ACTION_PACKAGE_FULLY_REMOVED);
intent.setData(Uri.parse("package:" + TEST_PACKAGE_NAME));
intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(TEST_UID));
receiver.onReceive(mMockContext, intent);
mTestLooper.dispatchAll();
verify(vcn).teardownAsynchronously();
assertTrue(mVcnMgmtSvc.getConfigs().isEmpty());
verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class));
}
@Test @Test
public void testSetVcnConfigRequiresNonSystemServer() throws Exception { public void testSetVcnConfigRequiresNonSystemServer() throws Exception {
doReturn(Process.SYSTEM_UID).when(mMockDeps).getBinderCallingUid(); doReturn(Process.SYSTEM_UID).when(mMockDeps).getBinderCallingUid();
@@ -578,7 +635,7 @@ public class VcnManagementServiceTest {
@Test @Test
public void testSetVcnConfigMismatchedPackages() throws Exception { public void testSetVcnConfigMismatchedPackages() throws Exception {
try { try {
mVcnMgmtSvc.setVcnConfig(TEST_UUID_1, TEST_VCN_CONFIG, "IncorrectPackage"); mVcnMgmtSvc.setVcnConfig(TEST_UUID_1, TEST_VCN_CONFIG, TEST_PACKAGE_NAME_2);
fail("Expected exception due to mismatched packages in config and method call"); fail("Expected exception due to mismatched packages in config and method call");
} catch (IllegalArgumentException expected) { } catch (IllegalArgumentException expected) {
verify(mMockPolicyListener, never()).onPolicyChanged(); verify(mMockPolicyListener, never()).onPolicyChanged();
@@ -678,11 +735,12 @@ public class VcnManagementServiceTest {
} }
@Test @Test
public void testClearVcnConfigRequiresCarrierPrivileges() throws Exception { public void testClearVcnConfigRequiresCarrierPrivilegesOrProvisioningPackage()
throws Exception {
setupMockedCarrierPrivilege(false); setupMockedCarrierPrivilege(false);
try { try {
mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, TEST_PACKAGE_NAME); mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, TEST_PACKAGE_NAME_2);
fail("Expected security exception for missing carrier privileges"); fail("Expected security exception for missing carrier privileges");
} catch (SecurityException expected) { } catch (SecurityException expected) {
} }
@@ -691,19 +749,31 @@ public class VcnManagementServiceTest {
@Test @Test
public void testClearVcnConfigMismatchedPackages() throws Exception { public void testClearVcnConfigMismatchedPackages() throws Exception {
try { try {
mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, "IncorrectPackage"); mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, TEST_PACKAGE_NAME_2);
fail("Expected security exception due to mismatched packages"); fail("Expected security exception due to mismatched packages");
} catch (SecurityException expected) { } catch (SecurityException expected) {
} }
} }
@Test @Test
public void testClearVcnConfig() throws Exception { public void testClearVcnConfig_callerIsProvisioningPackage() throws Exception {
// Lose carrier privileges to test that provisioning package is sufficient.
setupMockedCarrierPrivilege(false);
mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, TEST_PACKAGE_NAME); mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, TEST_PACKAGE_NAME);
assertTrue(mVcnMgmtSvc.getConfigs().isEmpty()); assertTrue(mVcnMgmtSvc.getConfigs().isEmpty());
verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class)); verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class));
} }
@Test
public void testClearVcnConfig_callerIsCarrierPrivileged() throws Exception {
setupMockedCarrierPrivilege(true, TEST_PACKAGE_NAME_2);
mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, TEST_PACKAGE_NAME_2);
assertTrue(mVcnMgmtSvc.getConfigs().isEmpty());
verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class));
}
@Test @Test
public void testClearVcnConfigNotifiesStatusCallback() throws Exception { public void testClearVcnConfigNotifiesStatusCallback() throws Exception {
setupSubscriptionAndStartVcn(TEST_SUBSCRIPTION_ID, TEST_UUID_2, true /* isActive */); setupSubscriptionAndStartVcn(TEST_SUBSCRIPTION_ID, TEST_UUID_2, true /* isActive */);
@@ -755,11 +825,12 @@ public class VcnManagementServiceTest {
@Test @Test
public void testGetConfiguredSubscriptionGroupsMismatchedPackages() throws Exception { public void testGetConfiguredSubscriptionGroupsMismatchedPackages() throws Exception {
final String badPackage = "IncorrectPackage"; doThrow(new SecurityException())
doThrow(new SecurityException()).when(mAppOpsMgr).checkPackage(TEST_UID, badPackage); .when(mAppOpsMgr)
.checkPackage(TEST_UID, TEST_PACKAGE_NAME_2);
try { try {
mVcnMgmtSvc.getConfiguredSubscriptionGroups(badPackage); mVcnMgmtSvc.getConfiguredSubscriptionGroups(TEST_PACKAGE_NAME_2);
fail("Expected security exception due to mismatched packages"); fail("Expected security exception due to mismatched packages");
} catch (SecurityException expected) { } catch (SecurityException expected) {
} }
@@ -767,14 +838,16 @@ public class VcnManagementServiceTest {
@Test @Test
public void testGetConfiguredSubscriptionGroups() throws Exception { public void testGetConfiguredSubscriptionGroups() throws Exception {
setupMockedCarrierPrivilege(true, TEST_PACKAGE_NAME_2);
mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME);
mVcnMgmtSvc.setVcnConfig(TEST_UUID_3, TEST_VCN_CONFIG_PKG_2, TEST_PACKAGE_NAME_2);
// Assert that if both UUID 1 and 2 are provisioned, the caller only gets ones that they are // Assert that if UUIDs 1, 2 and 3 are provisioned, the caller only gets ones that they are
// privileged for. // privileged for, or are the provisioning package of.
triggerSubscriptionTrackerCbAndGetSnapshot(TEST_UUID_1, Collections.singleton(TEST_UUID_1)); triggerSubscriptionTrackerCbAndGetSnapshot(TEST_UUID_1, Collections.singleton(TEST_UUID_1));
final List<ParcelUuid> subGrps = final List<ParcelUuid> subGrps =
mVcnMgmtSvc.getConfiguredSubscriptionGroups(TEST_PACKAGE_NAME); mVcnMgmtSvc.getConfiguredSubscriptionGroups(TEST_PACKAGE_NAME);
assertEquals(Collections.singletonList(TEST_UUID_1), subGrps); assertEquals(Arrays.asList(new ParcelUuid[] {TEST_UUID_1, TEST_UUID_2}), subGrps);
} }
@Test @Test