diff --git a/core/api/current.txt b/core/api/current.txt index a91607afbe9cb..978713abe84dd 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -7542,6 +7542,7 @@ package android.app.admin { method public boolean getBluetoothContactSharingDisabled(@NonNull android.content.ComponentName); method public boolean getCameraDisabled(@Nullable android.content.ComponentName); method @Deprecated @Nullable public String getCertInstallerPackage(@NonNull android.content.ComponentName) throws java.lang.SecurityException; + method @Nullable public android.app.admin.PackagePolicy getCredentialManagerPolicy(); method @Deprecated @Nullable public java.util.Set getCrossProfileCalendarPackages(@NonNull android.content.ComponentName); method @Deprecated public boolean getCrossProfileCallerIdDisabled(@NonNull android.content.ComponentName); method @Deprecated public boolean getCrossProfileContactsSearchDisabled(@NonNull android.content.ComponentName); @@ -7694,6 +7695,7 @@ package android.app.admin { method @Deprecated public void setCertInstallerPackage(@NonNull android.content.ComponentName, @Nullable String) throws java.lang.SecurityException; method public void setCommonCriteriaModeEnabled(@NonNull android.content.ComponentName, boolean); method public void setConfiguredNetworksLockdownState(@NonNull android.content.ComponentName, boolean); + method public void setCredentialManagerPolicy(@Nullable android.app.admin.PackagePolicy); method @Deprecated public void setCrossProfileCalendarPackages(@NonNull android.content.ComponentName, @Nullable java.util.Set); method @Deprecated public void setCrossProfileCallerIdDisabled(@NonNull android.content.ComponentName, boolean); method @Deprecated public void setCrossProfileContactsSearchDisabled(@NonNull android.content.ComponentName, boolean); diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 9843c8f2624f0..239111ebaab72 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -10041,6 +10041,58 @@ public class DevicePolicyManager { return false; } + /** + * Called by a device owner or profile owner of a managed profile to set the credential manager + * policy. + * + *

Affects APIs exposed by {@link android.credentials.CredentialManager}. + * + *

A {@link PackagePolicy#PACKAGE_POLICY_ALLOWLIST} policy type will limit the credential + * providers that the user can use to the list of packages in the policy. + * + *

A {@link PackagePolicy#PACKAGE_POLICY_ALLOWLIST_AND_SYSTEM} policy type + * allows access from the OEM default credential providers and the allowlist of credential + * providers. + * + *

A {@link PackagePolicy#PACKAGE_POLICY_BLOCKLIST} policy type will block the credential + * providers listed in the policy from being used by the user. + * + * @param policy the policy to set, setting this value to {@code null} will allow all packages + * @throws SecurityException if caller is not a device owner or profile owner of a + * managed profile + */ + public void setCredentialManagerPolicy(@Nullable PackagePolicy policy) { + throwIfParentInstance("setCredentialManagerPolicy"); + if (mService != null) { + try { + mService.setCredentialManagerPolicy(policy); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + } + + /** + * Called by a device owner or profile owner of a managed profile to retrieve the credential + * manager policy. + * + * @throws SecurityException if caller is not a device owner or profile owner of a + * managed profile. + * @return the current credential manager policy if null then this policy has not been + * configured. + */ + public @Nullable PackagePolicy getCredentialManagerPolicy() { + throwIfParentInstance("getCredentialManagerPolicy"); + if (mService != null) { + try { + return mService.getCredentialManagerPolicy(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + return null; + } + /** * Called by a profile owner of a managed profile to set the packages that are allowed to * lookup contacts in the managed profile based on caller id information. diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index aebeaf0897c86..70b63e40aa014 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -336,6 +336,9 @@ interface IDevicePolicyManager { PackagePolicy getManagedProfileCallerIdAccessPolicy(); boolean hasManagedProfileCallerIdAccess(int userId, String packageName); + void setCredentialManagerPolicy(in PackagePolicy policy); + PackagePolicy getCredentialManagerPolicy(); + void setManagedProfileContactsAccessPolicy(in PackagePolicy policy); PackagePolicy getManagedProfileContactsAccessPolicy(); boolean hasManagedProfileContactsAccess(int userId, String packageName); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java index 4c42791e48cc1..36cb89803f43c 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java @@ -174,6 +174,7 @@ class ActiveAdmin { private static final String ATTR_LAST_NETWORK_LOGGING_NOTIFICATION = "last-notification"; private static final String ATTR_NUM_NETWORK_LOGGING_NOTIFICATIONS = "num-notifications"; private static final String ATTR_PACKAGE_POLICY_MODE = "package-policy-type"; + private static final String TAG_CREDENTIAL_MANAGER_POLICY = "credential-manager-policy"; DeviceAdminInfo info; @@ -332,6 +333,9 @@ class ActiveAdmin { // The package policy for Cross Profile Contacts Search PackagePolicy mManagedProfileContactsAccess = null; + // The package policy for Credential Manager + PackagePolicy mCredentialManagerPolicy = null; + public String mAlwaysOnVpnPackage; public boolean mAlwaysOnVpnLockdown; boolean mCommonCriteriaMode; @@ -647,6 +651,8 @@ class ActiveAdmin { mManagedProfileCallerIdAccess); writePackagePolicy(out, TAG_CROSS_PROFILE_CONTACTS_SEARCH_POLICY, mManagedProfileContactsAccess); + writePackagePolicy(out, TAG_CREDENTIAL_MANAGER_POLICY, + mCredentialManagerPolicy); if (mManagedSubscriptionsPolicy != null) { out.startTag(null, TAG_MANAGED_SUBSCRIPTIONS_POLICY); mManagedSubscriptionsPolicy.saveToXml(out); @@ -958,6 +964,8 @@ class ActiveAdmin { mManagedProfileContactsAccess = readPackagePolicy(parser); } else if (TAG_MANAGED_SUBSCRIPTIONS_POLICY.equals(tag)) { mManagedSubscriptionsPolicy = ManagedSubscriptionsPolicy.readFromXml(parser); + } else if (TAG_CREDENTIAL_MANAGER_POLICY.equals(tag)) { + mCredentialManagerPolicy = readPackagePolicy(parser); } else { Slogf.w(LOG_TAG, "Unknown admin tag: %s", tag); XmlUtils.skipCurrentTag(parser); @@ -1332,6 +1340,9 @@ class ActiveAdmin { dumpPackagePolicy(pw, "managedProfileContactsPolicy", mManagedProfileContactsAccess); + dumpPackagePolicy(pw, "credentialManagerPolicy", + mCredentialManagerPolicy); + pw.print("isParent="); pw.println(isParent); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 3470b04c9e4f3..7d1b5ca4867ef 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -14315,6 +14315,46 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD); } + @Override + public void setCredentialManagerPolicy(PackagePolicy policy) { + if (!mHasFeature) { + return; + } + final CallerIdentity caller = getCallerIdentity(); + Preconditions.checkCallAuthorization(canWriteCredentialManagerPolicy(caller)); + + synchronized (getLockObject()) { + ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()); + if (Objects.equals(admin.mCredentialManagerPolicy, policy)) { + return; + } + + admin.mCredentialManagerPolicy = policy; + saveSettingsLocked(caller.getUserId()); + } + } + + private boolean canWriteCredentialManagerPolicy(CallerIdentity caller) { + return (isProfileOwner(caller) && isManagedProfile(caller.getUserId())) + || isDefaultDeviceOwner(caller) + || hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS); + } + + @Override + public PackagePolicy getCredentialManagerPolicy() { + if (!mHasFeature) { + return null; + } + final CallerIdentity caller = getCallerIdentity(); + Preconditions.checkCallAuthorization( + canWriteCredentialManagerPolicy(caller) || canQueryAdminPolicy(caller)); + + synchronized (getLockObject()) { + ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()); + return (admin != null) ? admin.mCredentialManagerPolicy : null; + } + } + @Override public void setSystemUpdatePolicy(ComponentName who, SystemUpdatePolicy policy) { if (policy != null) {