Loading core/java/android/app/admin/flags/flags.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -402,3 +402,13 @@ flag { description: "Add new API for secondary lockscreen" bug: "336297680" } flag { name: "remove_managed_esim_on_work_profile_deletion" namespace: "enterprise" description: "Remove managed eSIM when work profile is deleted" bug: "347925470" metadata { purpose: PURPOSE_BUGFIX } } services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +64 −0 Original line number Diff line number Diff line Loading @@ -245,6 +245,7 @@ import static android.app.admin.ProvisioningException.ERROR_REMOVE_NON_REQUIRED_ import static android.app.admin.ProvisioningException.ERROR_SETTING_PROFILE_OWNER_FAILED; import static android.app.admin.ProvisioningException.ERROR_SET_DEVICE_OWNER_FAILED; import static android.app.admin.ProvisioningException.ERROR_STARTING_PROFILE_FAILED; import static android.content.Context.RECEIVER_NOT_EXPORTED; import static android.content.Intent.ACTION_MANAGED_PROFILE_AVAILABLE; import static android.content.Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; Loading Loading @@ -486,6 +487,7 @@ import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.telephony.data.ApnSetting; import android.telephony.euicc.EuiccManager; import android.text.TextUtils; import android.text.format.DateUtils; import android.util.ArrayMap; Loading Loading @@ -643,6 +645,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { static final String ACTION_PROFILE_OFF_DEADLINE = "com.android.server.ACTION_PROFILE_OFF_DEADLINE"; /** Broadcast action invoked when a managed eSIM is removed while deleting work profile. */ private static final String ACTION_ESIM_REMOVED_WITH_MANAGED_PROFILE = "com.android.server.ACTION_ESIM_REMOVED_WITH_MANAGED_PROFILE"; /** Extra for the subscription ID of the managed eSIM removed while deleting work profile. */ private static final String EXTRA_REMOVED_ESIM_SUBSCRIPTION_ID = "com.android.server.EXTRA_ESIM_REMOVED_WITH_MANAGED_PROFILE_SUBSCRIPTION_ID"; private static final String CALLED_FROM_PARENT = "calledFromParent"; private static final String NOT_CALLED_FROM_PARENT = "notCalledFromParent"; Loading Loading @@ -1266,6 +1276,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { removeCredentialManagementApp(intent.getData().getSchemeSpecificPart()); } else if (Intent.ACTION_MANAGED_PROFILE_ADDED.equals(action)) { clearWipeProfileNotification(); } else if (Intent.ACTION_MANAGED_PROFILE_REMOVED.equals(action)) { removeManagedEmbeddedSubscriptionsForUser(userHandle); } else if (Intent.ACTION_DATE_CHANGED.equals(action) || Intent.ACTION_TIME_CHANGED.equals(action)) { // Update freeze period record when clock naturally progresses to the next day Loading Loading @@ -1298,6 +1310,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { triggerPolicyComplianceCheckIfNeeded(userHandle, suspended); } else if (LOGIN_ACCOUNTS_CHANGED_ACTION.equals(action)) { calculateHasIncompatibleAccounts(); } else if (ACTION_ESIM_REMOVED_WITH_MANAGED_PROFILE.equals(action)) { int removedSubscriptionId = intent.getIntExtra(EXTRA_REMOVED_ESIM_SUBSCRIPTION_ID, -1); Slogf.i(LOG_TAG, "Deleted subscription with ID %d because owning managed profile was " + "removed", removedSubscriptionId); } } Loading Loading @@ -2219,9 +2238,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler); filter = new IntentFilter(); filter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED); filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED); filter.addAction(Intent.ACTION_TIME_CHANGED); filter.addAction(Intent.ACTION_DATE_CHANGED); mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler); filter = new IntentFilter(); filter.addAction(ACTION_ESIM_REMOVED_WITH_MANAGED_PROFILE); mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler, RECEIVER_NOT_EXPORTED); LocalServices.addService(DevicePolicyManagerInternal.class, mLocalService); Loading Loading @@ -3970,6 +3994,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { deletedUsers.remove(userInfo.id); } for (Integer userId : deletedUsers) { removeManagedEmbeddedSubscriptionsForUser(userId); removeUserData(userId); mDevicePolicyEngine.handleUserRemoved(userId); } Loading Loading @@ -8099,6 +8124,45 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { mInjector.getNotificationManager().cancel(SystemMessage.NOTE_PROFILE_WIPED); } /** * Remove eSIM subscriptions that are managed by any of the admin packages of the given * userHandle. */ private void removeManagedEmbeddedSubscriptionsForUser(int userHandle) { if (!Flags.removeManagedEsimOnWorkProfileDeletion()) { return; } Slogf.i(LOG_TAG, "Managed profile with ID=%d deleted: going to remove managed embedded " + "subscriptions", userHandle); String profileOwnerPackage = mOwners.getProfileOwnerPackage(userHandle); if (profileOwnerPackage == null) { Slogf.wtf(LOG_TAG, "Profile owner package for managed profile is null"); return; } IntArray managedSubscriptionIds = getSubscriptionIdsInternal(profileOwnerPackage); deleteEmbeddedSubscriptions(managedSubscriptionIds); } private void deleteEmbeddedSubscriptions(IntArray subscriptionIds) { EuiccManager euiccManager = mContext.getSystemService(EuiccManager.class); for (int subscriptionId : subscriptionIds.toArray()) { Slogf.i(LOG_TAG, "Deleting embedded subscription with ID %d", subscriptionId); euiccManager.deleteSubscription(subscriptionId, createCallbackPendingIntentForRemovingManagedSubscription( subscriptionId)); } } private PendingIntent createCallbackPendingIntentForRemovingManagedSubscription( Integer subscriptionId) { Intent intent = new Intent(ACTION_ESIM_REMOVED_WITH_MANAGED_PROFILE); intent.putExtra(EXTRA_REMOVED_ESIM_SUBSCRIPTION_ID, subscriptionId); return PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_IMMUTABLE); } @Override public void setFactoryResetProtectionPolicy(ComponentName who, String callerPackageName, @Nullable FactoryResetProtectionPolicy policy) { services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +42 −0 Original line number Diff line number Diff line Loading @@ -143,6 +143,7 @@ import android.provider.DeviceConfig; import android.provider.Settings; import android.security.KeyChain; import android.security.keystore.AttestationUtils; import android.telephony.SubscriptionInfo; import android.telephony.TelephonyManager; import android.telephony.data.ApnSetting; import android.test.MoreAsserts; Loading Loading @@ -8715,6 +8716,47 @@ public class DevicePolicyManagerTest extends DpmTestBase { } } @RequiresFlagsEnabled(Flags.FLAG_REMOVE_MANAGED_ESIM_ON_WORK_PROFILE_DELETION) @Test public void testManagedProfileDeleted_managedEmbeddedSubscriptionDeleted() throws Exception { // Setup PO mode. setupProfileOwner(); // Mock SubscriptionManager to return a subscription managed by the profile owner package. int managedSubscriptionId = 42; SubscriptionInfo managedSubscription = new SubscriptionInfo.Builder().setCardId(1).setId( managedSubscriptionId).setGroupOwner(admin1.getPackageName()).build(); when(getServices().subscriptionManager.getAvailableSubscriptionInfoList()).thenReturn( List.of(managedSubscription)); // Send a ACTION_MANAGED_PROFILE_REMOVED broadcast to emulate a managed profile being // removed. sendBroadcastWithUser(dpms, Intent.ACTION_MANAGED_PROFILE_REMOVED, CALLER_USER_HANDLE); // Verify that EuiccManager was called to delete the subscription. verify(getServices().euiccManager).deleteSubscription(eq(managedSubscriptionId), any()); } @RequiresFlagsDisabled(Flags.FLAG_REMOVE_MANAGED_ESIM_ON_WORK_PROFILE_DELETION) @Test public void testManagedProfileDeleted_flagDisabled_managedEmbeddedSubscriptionDeleted() throws Exception { // Set up PO mode. setupProfileOwner(); // Mock SubscriptionManager to return a subscription managed by the profile owner package. int managedSubscriptionId = 42; SubscriptionInfo managedSubscription = new SubscriptionInfo.Builder().setCardId(1).setId( managedSubscriptionId).setGroupOwner(admin1.getPackageName()).build(); when(getServices().subscriptionManager.getAvailableSubscriptionInfoList()).thenReturn( List.of(managedSubscription)); // Send a ACTION_MANAGED_PROFILE_REMOVED broadcast to emulate a managed profile being // removed. sendBroadcastWithUser(dpms, Intent.ACTION_MANAGED_PROFILE_REMOVED, CALLER_USER_HANDLE); // Verify that EuiccManager was not called to delete the subscription. verifyZeroInteractions(getServices().euiccManager); } private void setupVpnAuthorization(String userVpnPackage, int userVpnUid) { final AppOpsManager.PackageOps vpnOp = new AppOpsManager.PackageOps(userVpnPackage, userVpnUid, List.of(new AppOpsManager.OpEntry( Loading services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java +10 −0 Original line number Diff line number Diff line Loading @@ -253,6 +253,8 @@ public class DpmMockContext extends MockContext { return mMockSystemServices.subscriptionManager; case Context.USB_SERVICE: return mMockSystemServices.usbManager; case Context.EUICC_SERVICE: return mMockSystemServices.euiccManager; } throw new UnsupportedOperationException(); } Loading Loading @@ -486,6 +488,14 @@ public class DpmMockContext extends MockContext { scheduler); } @Override public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user, IntentFilter filter, String broadcastPermission, Handler scheduler, int flags) { mMockSystemServices.registerReceiver(receiver, filter, scheduler); return spiedContext.registerReceiverAsUser(receiver, user, filter, broadcastPermission, scheduler, flags); } @Override public void unregisterReceiver(BroadcastReceiver receiver) { mMockSystemServices.unregisterReceiver(receiver); Loading services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java +3 −0 Original line number Diff line number Diff line Loading @@ -68,6 +68,7 @@ import android.provider.Settings; import android.security.KeyChain; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.telephony.euicc.EuiccManager; import android.test.mock.MockContentProvider; import android.test.mock.MockContentResolver; import android.util.ArrayMap; Loading Loading @@ -151,6 +152,7 @@ public class MockSystemServices { public final File dataDir; public final PolicyPathProvider pathProvider; public final SupervisionManagerInternal supervisionManagerInternal; public final EuiccManager euiccManager; private final Map<String, PackageState> mTestPackageStates = new ArrayMap<>(); Loading Loading @@ -206,6 +208,7 @@ public class MockSystemServices { roleManagerForMock = mock(RoleManagerForMock.class); subscriptionManager = mock(SubscriptionManager.class); supervisionManagerInternal = mock(SupervisionManagerInternal.class); euiccManager = mock(EuiccManager.class); // Package manager is huge, so we use a partial mock instead. packageManager = spy(realContext.getPackageManager()); Loading Loading
core/java/android/app/admin/flags/flags.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -402,3 +402,13 @@ flag { description: "Add new API for secondary lockscreen" bug: "336297680" } flag { name: "remove_managed_esim_on_work_profile_deletion" namespace: "enterprise" description: "Remove managed eSIM when work profile is deleted" bug: "347925470" metadata { purpose: PURPOSE_BUGFIX } }
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +64 −0 Original line number Diff line number Diff line Loading @@ -245,6 +245,7 @@ import static android.app.admin.ProvisioningException.ERROR_REMOVE_NON_REQUIRED_ import static android.app.admin.ProvisioningException.ERROR_SETTING_PROFILE_OWNER_FAILED; import static android.app.admin.ProvisioningException.ERROR_SET_DEVICE_OWNER_FAILED; import static android.app.admin.ProvisioningException.ERROR_STARTING_PROFILE_FAILED; import static android.content.Context.RECEIVER_NOT_EXPORTED; import static android.content.Intent.ACTION_MANAGED_PROFILE_AVAILABLE; import static android.content.Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; Loading Loading @@ -486,6 +487,7 @@ import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.telephony.data.ApnSetting; import android.telephony.euicc.EuiccManager; import android.text.TextUtils; import android.text.format.DateUtils; import android.util.ArrayMap; Loading Loading @@ -643,6 +645,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { static final String ACTION_PROFILE_OFF_DEADLINE = "com.android.server.ACTION_PROFILE_OFF_DEADLINE"; /** Broadcast action invoked when a managed eSIM is removed while deleting work profile. */ private static final String ACTION_ESIM_REMOVED_WITH_MANAGED_PROFILE = "com.android.server.ACTION_ESIM_REMOVED_WITH_MANAGED_PROFILE"; /** Extra for the subscription ID of the managed eSIM removed while deleting work profile. */ private static final String EXTRA_REMOVED_ESIM_SUBSCRIPTION_ID = "com.android.server.EXTRA_ESIM_REMOVED_WITH_MANAGED_PROFILE_SUBSCRIPTION_ID"; private static final String CALLED_FROM_PARENT = "calledFromParent"; private static final String NOT_CALLED_FROM_PARENT = "notCalledFromParent"; Loading Loading @@ -1266,6 +1276,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { removeCredentialManagementApp(intent.getData().getSchemeSpecificPart()); } else if (Intent.ACTION_MANAGED_PROFILE_ADDED.equals(action)) { clearWipeProfileNotification(); } else if (Intent.ACTION_MANAGED_PROFILE_REMOVED.equals(action)) { removeManagedEmbeddedSubscriptionsForUser(userHandle); } else if (Intent.ACTION_DATE_CHANGED.equals(action) || Intent.ACTION_TIME_CHANGED.equals(action)) { // Update freeze period record when clock naturally progresses to the next day Loading Loading @@ -1298,6 +1310,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { triggerPolicyComplianceCheckIfNeeded(userHandle, suspended); } else if (LOGIN_ACCOUNTS_CHANGED_ACTION.equals(action)) { calculateHasIncompatibleAccounts(); } else if (ACTION_ESIM_REMOVED_WITH_MANAGED_PROFILE.equals(action)) { int removedSubscriptionId = intent.getIntExtra(EXTRA_REMOVED_ESIM_SUBSCRIPTION_ID, -1); Slogf.i(LOG_TAG, "Deleted subscription with ID %d because owning managed profile was " + "removed", removedSubscriptionId); } } Loading Loading @@ -2219,9 +2238,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler); filter = new IntentFilter(); filter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED); filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED); filter.addAction(Intent.ACTION_TIME_CHANGED); filter.addAction(Intent.ACTION_DATE_CHANGED); mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler); filter = new IntentFilter(); filter.addAction(ACTION_ESIM_REMOVED_WITH_MANAGED_PROFILE); mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler, RECEIVER_NOT_EXPORTED); LocalServices.addService(DevicePolicyManagerInternal.class, mLocalService); Loading Loading @@ -3970,6 +3994,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { deletedUsers.remove(userInfo.id); } for (Integer userId : deletedUsers) { removeManagedEmbeddedSubscriptionsForUser(userId); removeUserData(userId); mDevicePolicyEngine.handleUserRemoved(userId); } Loading Loading @@ -8099,6 +8124,45 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { mInjector.getNotificationManager().cancel(SystemMessage.NOTE_PROFILE_WIPED); } /** * Remove eSIM subscriptions that are managed by any of the admin packages of the given * userHandle. */ private void removeManagedEmbeddedSubscriptionsForUser(int userHandle) { if (!Flags.removeManagedEsimOnWorkProfileDeletion()) { return; } Slogf.i(LOG_TAG, "Managed profile with ID=%d deleted: going to remove managed embedded " + "subscriptions", userHandle); String profileOwnerPackage = mOwners.getProfileOwnerPackage(userHandle); if (profileOwnerPackage == null) { Slogf.wtf(LOG_TAG, "Profile owner package for managed profile is null"); return; } IntArray managedSubscriptionIds = getSubscriptionIdsInternal(profileOwnerPackage); deleteEmbeddedSubscriptions(managedSubscriptionIds); } private void deleteEmbeddedSubscriptions(IntArray subscriptionIds) { EuiccManager euiccManager = mContext.getSystemService(EuiccManager.class); for (int subscriptionId : subscriptionIds.toArray()) { Slogf.i(LOG_TAG, "Deleting embedded subscription with ID %d", subscriptionId); euiccManager.deleteSubscription(subscriptionId, createCallbackPendingIntentForRemovingManagedSubscription( subscriptionId)); } } private PendingIntent createCallbackPendingIntentForRemovingManagedSubscription( Integer subscriptionId) { Intent intent = new Intent(ACTION_ESIM_REMOVED_WITH_MANAGED_PROFILE); intent.putExtra(EXTRA_REMOVED_ESIM_SUBSCRIPTION_ID, subscriptionId); return PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_IMMUTABLE); } @Override public void setFactoryResetProtectionPolicy(ComponentName who, String callerPackageName, @Nullable FactoryResetProtectionPolicy policy) {
services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +42 −0 Original line number Diff line number Diff line Loading @@ -143,6 +143,7 @@ import android.provider.DeviceConfig; import android.provider.Settings; import android.security.KeyChain; import android.security.keystore.AttestationUtils; import android.telephony.SubscriptionInfo; import android.telephony.TelephonyManager; import android.telephony.data.ApnSetting; import android.test.MoreAsserts; Loading Loading @@ -8715,6 +8716,47 @@ public class DevicePolicyManagerTest extends DpmTestBase { } } @RequiresFlagsEnabled(Flags.FLAG_REMOVE_MANAGED_ESIM_ON_WORK_PROFILE_DELETION) @Test public void testManagedProfileDeleted_managedEmbeddedSubscriptionDeleted() throws Exception { // Setup PO mode. setupProfileOwner(); // Mock SubscriptionManager to return a subscription managed by the profile owner package. int managedSubscriptionId = 42; SubscriptionInfo managedSubscription = new SubscriptionInfo.Builder().setCardId(1).setId( managedSubscriptionId).setGroupOwner(admin1.getPackageName()).build(); when(getServices().subscriptionManager.getAvailableSubscriptionInfoList()).thenReturn( List.of(managedSubscription)); // Send a ACTION_MANAGED_PROFILE_REMOVED broadcast to emulate a managed profile being // removed. sendBroadcastWithUser(dpms, Intent.ACTION_MANAGED_PROFILE_REMOVED, CALLER_USER_HANDLE); // Verify that EuiccManager was called to delete the subscription. verify(getServices().euiccManager).deleteSubscription(eq(managedSubscriptionId), any()); } @RequiresFlagsDisabled(Flags.FLAG_REMOVE_MANAGED_ESIM_ON_WORK_PROFILE_DELETION) @Test public void testManagedProfileDeleted_flagDisabled_managedEmbeddedSubscriptionDeleted() throws Exception { // Set up PO mode. setupProfileOwner(); // Mock SubscriptionManager to return a subscription managed by the profile owner package. int managedSubscriptionId = 42; SubscriptionInfo managedSubscription = new SubscriptionInfo.Builder().setCardId(1).setId( managedSubscriptionId).setGroupOwner(admin1.getPackageName()).build(); when(getServices().subscriptionManager.getAvailableSubscriptionInfoList()).thenReturn( List.of(managedSubscription)); // Send a ACTION_MANAGED_PROFILE_REMOVED broadcast to emulate a managed profile being // removed. sendBroadcastWithUser(dpms, Intent.ACTION_MANAGED_PROFILE_REMOVED, CALLER_USER_HANDLE); // Verify that EuiccManager was not called to delete the subscription. verifyZeroInteractions(getServices().euiccManager); } private void setupVpnAuthorization(String userVpnPackage, int userVpnUid) { final AppOpsManager.PackageOps vpnOp = new AppOpsManager.PackageOps(userVpnPackage, userVpnUid, List.of(new AppOpsManager.OpEntry( Loading
services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java +10 −0 Original line number Diff line number Diff line Loading @@ -253,6 +253,8 @@ public class DpmMockContext extends MockContext { return mMockSystemServices.subscriptionManager; case Context.USB_SERVICE: return mMockSystemServices.usbManager; case Context.EUICC_SERVICE: return mMockSystemServices.euiccManager; } throw new UnsupportedOperationException(); } Loading Loading @@ -486,6 +488,14 @@ public class DpmMockContext extends MockContext { scheduler); } @Override public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user, IntentFilter filter, String broadcastPermission, Handler scheduler, int flags) { mMockSystemServices.registerReceiver(receiver, filter, scheduler); return spiedContext.registerReceiverAsUser(receiver, user, filter, broadcastPermission, scheduler, flags); } @Override public void unregisterReceiver(BroadcastReceiver receiver) { mMockSystemServices.unregisterReceiver(receiver); Loading
services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java +3 −0 Original line number Diff line number Diff line Loading @@ -68,6 +68,7 @@ import android.provider.Settings; import android.security.KeyChain; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.telephony.euicc.EuiccManager; import android.test.mock.MockContentProvider; import android.test.mock.MockContentResolver; import android.util.ArrayMap; Loading Loading @@ -151,6 +152,7 @@ public class MockSystemServices { public final File dataDir; public final PolicyPathProvider pathProvider; public final SupervisionManagerInternal supervisionManagerInternal; public final EuiccManager euiccManager; private final Map<String, PackageState> mTestPackageStates = new ArrayMap<>(); Loading Loading @@ -206,6 +208,7 @@ public class MockSystemServices { roleManagerForMock = mock(RoleManagerForMock.class); subscriptionManager = mock(SubscriptionManager.class); supervisionManagerInternal = mock(SupervisionManagerInternal.class); euiccManager = mock(EuiccManager.class); // Package manager is huge, so we use a partial mock instead. packageManager = spy(realContext.getPackageManager()); Loading