Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 35e0c6ab authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add getEnforcingAdminsForPolicy method to DPM" into main

parents 30f743f3 ab582514
Loading
Loading
Loading
Loading
+44 −0
Original line number Diff line number Diff line
@@ -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
+1 −0
Original line number Diff line number Diff line
@@ -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);

+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);
    }
}
+2 −6
Original line number Diff line number Diff line
@@ -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;
@@ -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);
@@ -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;
        }
+55 −3
Original line number Diff line number Diff line
@@ -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;
@@ -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.
@@ -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();
@@ -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