diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index fdbd85a77a5bc..3e6ce3f96acf3 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -819,6 +819,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action) && !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { handlePackagesChanged(intent.getData().getSchemeSpecificPart(), userHandle); + removeCredentialManagementApp(intent.getData().getSchemeSpecificPart()); } else if (Intent.ACTION_MANAGED_PROFILE_ADDED.equals(action)) { clearWipeProfileNotification(); } else if (Intent.ACTION_DATE_CHANGED.equals(action) @@ -949,6 +950,20 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } + private void removeCredentialManagementApp(String packageName) { + mBackgroundHandler.post(() -> { + try (KeyChainConnection connection = mInjector.keyChainBind()) { + IKeyChainService service = connection.getService(); + if (service.hasCredentialManagementApp() + && packageName.equals(service.getCredentialManagementAppPackageName())) { + service.removeCredentialManagementApp(); + } + } catch (RemoteException | InterruptedException | IllegalStateException e) { + Log.e(LOG_TAG, "Unable to remove the credential management app"); + } + }); + } + private boolean isRemovedPackage(String changedPackage, String targetPackage, int userHandle) { try { return targetPackage != null @@ -1419,6 +1434,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return SecurityLog.isLoggingEnabled(); } + KeyChainConnection keyChainBind() throws InterruptedException { + return KeyChain.bind(mContext); + } + KeyChainConnection keyChainBindAsUser(UserHandle user) throws InterruptedException { return KeyChain.bindAsUser(mContext, user); } diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java index 17324bab70d2f..9c28c99fcc071 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java @@ -459,6 +459,11 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi return services.buildMock.isDebuggable; } + @Override + KeyChain.KeyChainConnection keyChainBind() { + return services.keyChainConnection; + } + @Override KeyChain.KeyChainConnection keyChainBindAsUser(UserHandle user) { return services.keyChainConnection; diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java index 1c7da3b989306..3493599826599 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java @@ -1616,6 +1616,33 @@ public class DevicePolicyManagerTest extends DpmTestBase { )), eq(user)); } + @Test + public void testRemoveCredentialManagementApp() throws Exception { + final String packageName = "com.test.cred.mng"; + Intent intent = new Intent(Intent.ACTION_PACKAGE_REMOVED); + intent.setData(Uri.parse("package:" + packageName)); + dpms.mReceiver.setPendingResult( + new BroadcastReceiver.PendingResult(Activity.RESULT_OK, + "resultData", + /* resultExtras= */ null, + BroadcastReceiver.PendingResult.TYPE_UNREGISTERED, + /* ordered= */ true, + /* sticky= */ false, + /* token= */ null, + CALLER_USER_HANDLE, + /* flags= */ 0)); + when(getServices().keyChainConnection.getService().hasCredentialManagementApp()) + .thenReturn(true); + when(getServices().keyChainConnection.getService().getCredentialManagementAppPackageName()) + .thenReturn(packageName); + + dpms.mReceiver.onReceive(mContext, intent); + + flushTasks(dpms); + verify(getServices().keyChainConnection.getService()).hasCredentialManagementApp(); + verify(getServices().keyChainConnection.getService()).removeCredentialManagementApp(); + } + /** * Simple test for delegate set/get and general delegation. Tests verifying that delegated * privileges can acually be exercised by a delegate are not covered here.