Loading core/java/android/app/admin/DevicePolicyManager.java +44 −0 Original line number Diff line number Diff line Loading @@ -12720,6 +12720,50 @@ public class DevicePolicyManager { return null; } /** * Returns information about {@link EnforcingAdmin}s that are currently enforcing a specific * device policy for a given user. * * <p>The list includes only those admins whose set policy value is the one actively * applied on the device after policy resolution (i.e., considering policies from all * relevant admins). If no admin enforces the policy for the user, returns an empty list. * * <p><strong>Note:</strong> This method does not support policies that require additional * parameters when being set (e.g., policies that take a package name as an argument). * Attempting to query such policies will result in an {@link IllegalArgumentException}. * * @param policyIdentifier The identifier for the device policy. This must be one of the * constants defined in {@link DevicePolicyIdentifiers}. For user * restrictions, use * {@link DevicePolicyIdentifiers#getIdentifierForUserRestriction} * to obtain the correct identifier. * @param userId The identifier of the user for whom to retrieve the enforcing admins. * @return {@link PolicyEnforcementInfo} that contains the list of {@link EnforcingAdmin} * objects, or an empty list if no admin is enforcing the policy for the specified user. * @throws IllegalArgumentException if {@code devicePolicyIdentifier} is not a recognized policy * identifier or if it corresponds to a policy that requires additional parameters for * its enforcement. * @hide */ @RequiresPermission(QUERY_ADMIN_POLICY) @NonNull public PolicyEnforcementInfo getEnforcingAdminsForPolicy( @NonNull String policyIdentifier, int userId) { Objects.requireNonNull(policyIdentifier, "devicePolicyIdentifier can't be null"); if (mService != null) { try { return new PolicyEnforcementInfo( mService.getEnforcingAdminsForPolicy(policyIdentifier, userId)); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } return new PolicyEnforcementInfo(Collections.emptyList()); } /** * Hide or unhide packages. When a package is hidden it is unavailable for use, but the data and * actual package file remain. This function can be called by a device owner, profile owner, or core/java/android/app/admin/IDevicePolicyManager.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -284,6 +284,7 @@ interface IDevicePolicyManager { Intent createAdminSupportIntent(in String restriction); Bundle getEnforcingAdminAndUserDetails(int userId, String restriction); EnforcingAdmin getEnforcingAdmin(int userId, String identifier); List<EnforcingAdmin> getEnforcingAdminsForPolicy(String identifier, int userId); boolean setApplicationHidden(in ComponentName admin, in String callerPackage, in String packageName, boolean hidden, boolean parent); boolean isApplicationHidden(in ComponentName admin, in String callerPackage, in String packageName, boolean parent); Loading core/java/android/app/admin/PolicyEnforcementInfo.java 0 → 100644 +93 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.app.admin; import static java.util.function.Predicate.not; import android.annotation.Nullable; import android.app.role.RoleManager; import java.util.List; import java.util.stream.Stream; /** * Class that contains information about the admins that are enforcing a specific policy. * * @hide */ public class PolicyEnforcementInfo { // Contains all admins who has enforced the policy. The supervision admin will be first on // the list, if there's any. private final List<EnforcingAdmin> mAllAdmins; /** * @hide */ public PolicyEnforcementInfo(List<EnforcingAdmin> enforcingAdmins) { // Add any supervisor admins first. Stream<EnforcingAdmin> supervisorAdmins = enforcingAdmins.stream().filter( PolicyEnforcementInfo::isSupervisionRole); // Add all other admins afterwards. Only supervisor admin will be added first, for others // the order doesn't matter. Stream<EnforcingAdmin> otherAdmins = enforcingAdmins.stream().filter( not(PolicyEnforcementInfo::isSupervisionRole)); mAllAdmins = Stream.concat(supervisorAdmins, otherAdmins).toList(); } /** * @hide */ public List<EnforcingAdmin> getAllAdmins() { return mAllAdmins; } /** * @hide */ public boolean isOnlyEnforcedBySystem() { return mAllAdmins.stream().allMatch(PolicyEnforcementInfo::isSystemAuthority); } /** * Returns one EnforcingAdmin from all admins that enforced the policy. If there is a * supervision admin, returns that admin as supervision admins have higher priority due to * regulations (b/392057517). If there are no admins enforcing the particular policy on device, * will return null. * * @hide */ @Nullable public EnforcingAdmin getMostImportantEnforcingAdmin() { // Returns the first admin if the list is not empty. return mAllAdmins.isEmpty() ? null : mAllAdmins.getFirst(); } private static boolean isSystemAuthority(EnforcingAdmin enforcingAdmin) { // System authorities are implemented as UnknownAuthority. // TODO(b/414733570): Add SystemAuthority class to represent system authority properly. return enforcingAdmin.getAuthority() instanceof UnknownAuthority; } private static boolean isSupervisionRole(EnforcingAdmin enforcingAdmin) { if (!(enforcingAdmin.getAuthority() instanceof RoleAuthority)) { return false; } return ((RoleAuthority) enforcingAdmin.getAuthority()).getRoles().contains( RoleManager.ROLE_SYSTEM_SUPERVISION); } } services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java +2 −6 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import static android.app.admin.PolicyUpdateResult.RESULT_FAILURE_UNKNOWN; import static android.app.admin.PolicyUpdateResult.RESULT_POLICY_CLEARED; import static android.app.admin.PolicyUpdateResult.RESULT_POLICY_SET; import static android.content.pm.UserProperties.INHERIT_DEVICE_POLICY_FROM_PARENT; import static android.app.role.RoleManager.ROLE_SYSTEM_FINANCED_DEVICE_CONTROLLER; import android.Manifest; import android.annotation.NonNull; Loading Loading @@ -108,11 +109,6 @@ import java.util.concurrent.TimeUnit; final class DevicePolicyEngine { static final String TAG = "DevicePolicyEngine"; static final String DEVICE_LOCK_CONTROLLER_ROLE = "android.app.role.SYSTEM_FINANCED_DEVICE_CONTROLLER"; static final String SYSTEM_SUPERVISION_ROLE = "android.app.role.SYSTEM_SUPERVISION"; private static final String CELLULAR_2G_USER_RESTRICTION_ID = DevicePolicyIdentifiers.getIdentifierForUserRestriction( UserManager.DISALLOW_CELLULAR_2G); Loading Loading @@ -1959,7 +1955,7 @@ final class DevicePolicyEngine { */ void handleRoleChanged(@NonNull String roleName, int userId) { // TODO(b/256852787): handle all roles changing. if (!DEVICE_LOCK_CONTROLLER_ROLE.equals(roleName)) { if (!ROLE_SYSTEM_FINANCED_DEVICE_CONTROLLER.equals(roleName)) { // We only support device lock controller role for now. return; } Loading services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +55 −3 Original line number Diff line number Diff line Loading @@ -279,7 +279,6 @@ import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STR import static com.android.server.SystemTimeZone.TIME_ZONE_CONFIDENCE_HIGH; import static com.android.server.am.ActivityManagerService.STOCK_PM_FLAGS; import static com.android.server.devicepolicy.DevicePolicyEngine.DEFAULT_POLICY_SIZE_LIMIT; import static com.android.server.devicepolicy.DevicePolicyEngine.SYSTEM_SUPERVISION_ROLE; import static com.android.server.devicepolicy.DevicePolicyStatsLog.DEVICE_POLICY_MANAGEMENT_MODE; import static com.android.server.devicepolicy.DevicePolicyStatsLog.DEVICE_POLICY_MANAGEMENT_MODE__MANAGEMENT_MODE__COPE; import static com.android.server.devicepolicy.DevicePolicyStatsLog.DEVICE_POLICY_MANAGEMENT_MODE__MANAGEMENT_MODE__DEVICE_OWNER; Loading Loading @@ -935,6 +934,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { private static final int BOOT_TO_HSU_FOR_PROVISIONED_DEVICE = 1; /** * For apps targeting U+ * Enable multiple admins to coexist on the same device. Loading Loading @@ -16671,8 +16671,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return admins.iterator().next().getParcelableAdmin(); } Optional<EnforcingAdmin> supervision = admins.stream() .filter(a -> a.hasAuthority( EnforcingAdmin.getRoleAuthorityOf(SYSTEM_SUPERVISION_ROLE))) .filter(EnforcingAdmin::isSupervisionAdmin) .findFirst(); if (supervision.isPresent()) { return supervision.get().getParcelableAdmin(); Loading Loading @@ -16841,6 +16840,59 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return intent; } @Override public List<android.app.admin.EnforcingAdmin> getEnforcingAdminsForPolicy( String policyIdentifier, int userId) { Preconditions.checkCallAuthorization(canQueryAdminPolicy(getCallerIdentity())); return Binder.withCleanCallingIdentity(() -> { // TODO(b/414733570): Handle legacy policies that are not stored in DPE first. PolicyDefinition<?> policyDefinition = PolicyDefinition.getPolicyDefinitionForIdentifier(policyIdentifier); if (policyDefinition == null) { throw new IllegalArgumentException( "Unknown policy identifier: " + policyIdentifier); } // Generic policy definitions are never set directly. They're set through // parameterized policy keys, thus the callers need to query them using the // corresponding {@code PolicyKey}. if (policyDefinition.isGenericDefinition()) { throw new IllegalArgumentException( "Generic policies are not supported. Call DPM" + ".getEnforcingAdminsForPolicyKey " + "instead."); } Set<EnforcingAdmin> admins = mDevicePolicyEngine.getEnforcingAdminsForResolvedPolicy(policyDefinition, userId); // The user restrictions that are set by the admins are already included in the // EnforcingAdmin set that DevicePolicyEngine returns in the previous line. if (policyDefinition.isUserRestrictionPolicy() && isUserRestrictionPolicyEnforcedBySystem(policyDefinition, userId)) { admins.add( EnforcingAdmin.createSystemEnforcingAdmin(PLATFORM_PACKAGE_NAME)); } // Convert the internal EnforcingAdmin instances to external parcelable EnforcingAdmin // list. return admins.stream().map(EnforcingAdmin::getParcelableAdmin).toList(); }); } private boolean isUserRestrictionPolicyEnforcedBySystem( PolicyDefinition<?> policyDefinition, int userId) { // User restriction can be enforced by the system aside from admins, until they're // migrated to DevicePolicyEngine, DPMS should read them from UserManager. UserRestrictionPolicyKey policyKey = (UserRestrictionPolicyKey) policyDefinition.getPolicyKey(); return mUserManager.hasBaseUserRestriction(policyKey.getRestriction(), UserHandle.of(userId)); } /** * Returns true if specified admin is allowed to limit passwords and has a * {@code mPasswordPolicy.quality} of at least {@code minPasswordQuality} Loading
core/java/android/app/admin/DevicePolicyManager.java +44 −0 Original line number Diff line number Diff line Loading @@ -12720,6 +12720,50 @@ public class DevicePolicyManager { return null; } /** * Returns information about {@link EnforcingAdmin}s that are currently enforcing a specific * device policy for a given user. * * <p>The list includes only those admins whose set policy value is the one actively * applied on the device after policy resolution (i.e., considering policies from all * relevant admins). If no admin enforces the policy for the user, returns an empty list. * * <p><strong>Note:</strong> This method does not support policies that require additional * parameters when being set (e.g., policies that take a package name as an argument). * Attempting to query such policies will result in an {@link IllegalArgumentException}. * * @param policyIdentifier The identifier for the device policy. This must be one of the * constants defined in {@link DevicePolicyIdentifiers}. For user * restrictions, use * {@link DevicePolicyIdentifiers#getIdentifierForUserRestriction} * to obtain the correct identifier. * @param userId The identifier of the user for whom to retrieve the enforcing admins. * @return {@link PolicyEnforcementInfo} that contains the list of {@link EnforcingAdmin} * objects, or an empty list if no admin is enforcing the policy for the specified user. * @throws IllegalArgumentException if {@code devicePolicyIdentifier} is not a recognized policy * identifier or if it corresponds to a policy that requires additional parameters for * its enforcement. * @hide */ @RequiresPermission(QUERY_ADMIN_POLICY) @NonNull public PolicyEnforcementInfo getEnforcingAdminsForPolicy( @NonNull String policyIdentifier, int userId) { Objects.requireNonNull(policyIdentifier, "devicePolicyIdentifier can't be null"); if (mService != null) { try { return new PolicyEnforcementInfo( mService.getEnforcingAdminsForPolicy(policyIdentifier, userId)); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } return new PolicyEnforcementInfo(Collections.emptyList()); } /** * Hide or unhide packages. When a package is hidden it is unavailable for use, but the data and * actual package file remain. This function can be called by a device owner, profile owner, or
core/java/android/app/admin/IDevicePolicyManager.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -284,6 +284,7 @@ interface IDevicePolicyManager { Intent createAdminSupportIntent(in String restriction); Bundle getEnforcingAdminAndUserDetails(int userId, String restriction); EnforcingAdmin getEnforcingAdmin(int userId, String identifier); List<EnforcingAdmin> getEnforcingAdminsForPolicy(String identifier, int userId); boolean setApplicationHidden(in ComponentName admin, in String callerPackage, in String packageName, boolean hidden, boolean parent); boolean isApplicationHidden(in ComponentName admin, in String callerPackage, in String packageName, boolean parent); Loading
core/java/android/app/admin/PolicyEnforcementInfo.java 0 → 100644 +93 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.app.admin; import static java.util.function.Predicate.not; import android.annotation.Nullable; import android.app.role.RoleManager; import java.util.List; import java.util.stream.Stream; /** * Class that contains information about the admins that are enforcing a specific policy. * * @hide */ public class PolicyEnforcementInfo { // Contains all admins who has enforced the policy. The supervision admin will be first on // the list, if there's any. private final List<EnforcingAdmin> mAllAdmins; /** * @hide */ public PolicyEnforcementInfo(List<EnforcingAdmin> enforcingAdmins) { // Add any supervisor admins first. Stream<EnforcingAdmin> supervisorAdmins = enforcingAdmins.stream().filter( PolicyEnforcementInfo::isSupervisionRole); // Add all other admins afterwards. Only supervisor admin will be added first, for others // the order doesn't matter. Stream<EnforcingAdmin> otherAdmins = enforcingAdmins.stream().filter( not(PolicyEnforcementInfo::isSupervisionRole)); mAllAdmins = Stream.concat(supervisorAdmins, otherAdmins).toList(); } /** * @hide */ public List<EnforcingAdmin> getAllAdmins() { return mAllAdmins; } /** * @hide */ public boolean isOnlyEnforcedBySystem() { return mAllAdmins.stream().allMatch(PolicyEnforcementInfo::isSystemAuthority); } /** * Returns one EnforcingAdmin from all admins that enforced the policy. If there is a * supervision admin, returns that admin as supervision admins have higher priority due to * regulations (b/392057517). If there are no admins enforcing the particular policy on device, * will return null. * * @hide */ @Nullable public EnforcingAdmin getMostImportantEnforcingAdmin() { // Returns the first admin if the list is not empty. return mAllAdmins.isEmpty() ? null : mAllAdmins.getFirst(); } private static boolean isSystemAuthority(EnforcingAdmin enforcingAdmin) { // System authorities are implemented as UnknownAuthority. // TODO(b/414733570): Add SystemAuthority class to represent system authority properly. return enforcingAdmin.getAuthority() instanceof UnknownAuthority; } private static boolean isSupervisionRole(EnforcingAdmin enforcingAdmin) { if (!(enforcingAdmin.getAuthority() instanceof RoleAuthority)) { return false; } return ((RoleAuthority) enforcingAdmin.getAuthority()).getRoles().contains( RoleManager.ROLE_SYSTEM_SUPERVISION); } }
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java +2 −6 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import static android.app.admin.PolicyUpdateResult.RESULT_FAILURE_UNKNOWN; import static android.app.admin.PolicyUpdateResult.RESULT_POLICY_CLEARED; import static android.app.admin.PolicyUpdateResult.RESULT_POLICY_SET; import static android.content.pm.UserProperties.INHERIT_DEVICE_POLICY_FROM_PARENT; import static android.app.role.RoleManager.ROLE_SYSTEM_FINANCED_DEVICE_CONTROLLER; import android.Manifest; import android.annotation.NonNull; Loading Loading @@ -108,11 +109,6 @@ import java.util.concurrent.TimeUnit; final class DevicePolicyEngine { static final String TAG = "DevicePolicyEngine"; static final String DEVICE_LOCK_CONTROLLER_ROLE = "android.app.role.SYSTEM_FINANCED_DEVICE_CONTROLLER"; static final String SYSTEM_SUPERVISION_ROLE = "android.app.role.SYSTEM_SUPERVISION"; private static final String CELLULAR_2G_USER_RESTRICTION_ID = DevicePolicyIdentifiers.getIdentifierForUserRestriction( UserManager.DISALLOW_CELLULAR_2G); Loading Loading @@ -1959,7 +1955,7 @@ final class DevicePolicyEngine { */ void handleRoleChanged(@NonNull String roleName, int userId) { // TODO(b/256852787): handle all roles changing. if (!DEVICE_LOCK_CONTROLLER_ROLE.equals(roleName)) { if (!ROLE_SYSTEM_FINANCED_DEVICE_CONTROLLER.equals(roleName)) { // We only support device lock controller role for now. return; } Loading
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +55 −3 Original line number Diff line number Diff line Loading @@ -279,7 +279,6 @@ import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STR import static com.android.server.SystemTimeZone.TIME_ZONE_CONFIDENCE_HIGH; import static com.android.server.am.ActivityManagerService.STOCK_PM_FLAGS; import static com.android.server.devicepolicy.DevicePolicyEngine.DEFAULT_POLICY_SIZE_LIMIT; import static com.android.server.devicepolicy.DevicePolicyEngine.SYSTEM_SUPERVISION_ROLE; import static com.android.server.devicepolicy.DevicePolicyStatsLog.DEVICE_POLICY_MANAGEMENT_MODE; import static com.android.server.devicepolicy.DevicePolicyStatsLog.DEVICE_POLICY_MANAGEMENT_MODE__MANAGEMENT_MODE__COPE; import static com.android.server.devicepolicy.DevicePolicyStatsLog.DEVICE_POLICY_MANAGEMENT_MODE__MANAGEMENT_MODE__DEVICE_OWNER; Loading Loading @@ -935,6 +934,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { private static final int BOOT_TO_HSU_FOR_PROVISIONED_DEVICE = 1; /** * For apps targeting U+ * Enable multiple admins to coexist on the same device. Loading Loading @@ -16671,8 +16671,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return admins.iterator().next().getParcelableAdmin(); } Optional<EnforcingAdmin> supervision = admins.stream() .filter(a -> a.hasAuthority( EnforcingAdmin.getRoleAuthorityOf(SYSTEM_SUPERVISION_ROLE))) .filter(EnforcingAdmin::isSupervisionAdmin) .findFirst(); if (supervision.isPresent()) { return supervision.get().getParcelableAdmin(); Loading Loading @@ -16841,6 +16840,59 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return intent; } @Override public List<android.app.admin.EnforcingAdmin> getEnforcingAdminsForPolicy( String policyIdentifier, int userId) { Preconditions.checkCallAuthorization(canQueryAdminPolicy(getCallerIdentity())); return Binder.withCleanCallingIdentity(() -> { // TODO(b/414733570): Handle legacy policies that are not stored in DPE first. PolicyDefinition<?> policyDefinition = PolicyDefinition.getPolicyDefinitionForIdentifier(policyIdentifier); if (policyDefinition == null) { throw new IllegalArgumentException( "Unknown policy identifier: " + policyIdentifier); } // Generic policy definitions are never set directly. They're set through // parameterized policy keys, thus the callers need to query them using the // corresponding {@code PolicyKey}. if (policyDefinition.isGenericDefinition()) { throw new IllegalArgumentException( "Generic policies are not supported. Call DPM" + ".getEnforcingAdminsForPolicyKey " + "instead."); } Set<EnforcingAdmin> admins = mDevicePolicyEngine.getEnforcingAdminsForResolvedPolicy(policyDefinition, userId); // The user restrictions that are set by the admins are already included in the // EnforcingAdmin set that DevicePolicyEngine returns in the previous line. if (policyDefinition.isUserRestrictionPolicy() && isUserRestrictionPolicyEnforcedBySystem(policyDefinition, userId)) { admins.add( EnforcingAdmin.createSystemEnforcingAdmin(PLATFORM_PACKAGE_NAME)); } // Convert the internal EnforcingAdmin instances to external parcelable EnforcingAdmin // list. return admins.stream().map(EnforcingAdmin::getParcelableAdmin).toList(); }); } private boolean isUserRestrictionPolicyEnforcedBySystem( PolicyDefinition<?> policyDefinition, int userId) { // User restriction can be enforced by the system aside from admins, until they're // migrated to DevicePolicyEngine, DPMS should read them from UserManager. UserRestrictionPolicyKey policyKey = (UserRestrictionPolicyKey) policyDefinition.getPolicyKey(); return mUserManager.hasBaseUserRestriction(policyKey.getRestriction(), UserHandle.of(userId)); } /** * Returns true if specified admin is allowed to limit passwords and has a * {@code mPasswordPolicy.quality} of at least {@code minPasswordQuality}