Merge "Allow provisioning package to retrieve subGrp, clear it's own config"
This commit is contained in:
@@ -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
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user