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

Commit 0c6346a0 authored by Ankita Vyas's avatar Ankita Vyas Committed by Android (Google) Code Review
Browse files

Merge "Apply inheritable policies from parent to child profile."

parents 4c389024 ddbe98b0
Loading
Loading
Loading
Loading
+87 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static android.app.admin.PolicyUpdateResult.RESULT_FAILURE_CONFLICTING_AD
import static android.app.admin.PolicyUpdateResult.RESULT_SUCCESS;
import static android.app.admin.PolicyUpdatesReceiver.EXTRA_POLICY_TARGET_USER_ID;
import static android.app.admin.PolicyUpdatesReceiver.EXTRA_POLICY_UPDATE_RESULT_KEY;
import static android.content.pm.UserProperties.INHERIT_DEVICE_POLICY_FROM_PARENT;

import android.Manifest;
import android.annotation.NonNull;
@@ -32,6 +33,7 @@ import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.content.pm.UserProperties;
import android.os.Binder;
import android.os.Bundle;
import android.os.Environment;
@@ -149,6 +151,8 @@ final class DevicePolicyEngine {
            updateDeviceAdminServiceOnPolicyAddLocked(enforcingAdmin);

            write();

            applyToInheritableProfiles(policyDefinition, enforcingAdmin, value, userId);
        }
    }

@@ -200,9 +204,51 @@ final class DevicePolicyEngine {
            updateDeviceAdminServiceOnPolicyRemoveLocked(enforcingAdmin);

            write();

            applyToInheritableProfiles(policyDefinition, enforcingAdmin, /*value */ null, userId);
        }
    }

    /**
     * If any of child user has property {@link UserProperties#INHERIT_DEVICE_POLICY_FROM_PARENT}
     * set then propagate the policy to it if value is not null
     * else remove the policy from child.
     */
    private <V> void applyToInheritableProfiles(PolicyDefinition<V> policyDefinition,
            EnforcingAdmin enforcingAdmin, V value, int userId) {
        if (policyDefinition.isInheritable()) {
            Binder.withCleanCallingIdentity(() -> {
                List<UserInfo> userInfos = mUserManager.getProfiles(userId);
                for (UserInfo childUserInfo : userInfos) {
                    int childUserId = childUserInfo.getUserHandle().getIdentifier();
                    if (isProfileOfUser(childUserId, userId)
                            && isInheritDevicePolicyFromParent(childUserInfo)) {
                        if (value != null) {
                            setLocalPolicy(policyDefinition, enforcingAdmin, value, childUserId);
                        } else {
                            removeLocalPolicy(policyDefinition, enforcingAdmin, childUserId);
                        }
                    }
                }
            });
        }
    }

    /**
     * Checks if given parentUserId is direct parent of childUserId.
     */
    private boolean isProfileOfUser(int childUserId, int parentUserId) {
        UserInfo parentInfo = mUserManager.getProfileParent(childUserId);
        return childUserId != parentUserId && parentInfo != null
                && parentInfo.getUserHandle().getIdentifier() == parentUserId;
    }

    private boolean isInheritDevicePolicyFromParent(UserInfo userInfo) {
        UserProperties userProperties = mUserManager.getUserProperties(userInfo.getUserHandle());
        return userProperties != null && mUserManager.getUserProperties(userInfo.getUserHandle())
                .getInheritDevicePolicy() == INHERIT_DEVICE_POLICY_FROM_PARENT;
    }

    /**
     * Enforces the new policy and notifies relevant admins.
     */
@@ -688,6 +734,47 @@ final class DevicePolicyEngine {
        }
    }

    void handleUserCreated(UserInfo user) {
        enforcePoliciesOnInheritableProfilesIfApplicable(user);
    }

    private void enforcePoliciesOnInheritableProfilesIfApplicable(UserInfo user) {
        if (!user.isProfile()) {
            return;
        }

        Binder.withCleanCallingIdentity(() -> {
            UserProperties userProperties = mUserManager.getUserProperties(user.getUserHandle());
            if (userProperties == null || userProperties.getInheritDevicePolicy()
                    != INHERIT_DEVICE_POLICY_FROM_PARENT) {
                return;
            }

            int userId = user.id;
            // Apply local policies present on parent to newly created child profile.
            UserInfo parentInfo = mUserManager.getProfileParent(userId);
            if (parentInfo == null || parentInfo.getUserHandle().getIdentifier() == userId) return;

            for (Map.Entry<PolicyKey, PolicyState<?>> entry : mLocalPolicies.get(
                    parentInfo.getUserHandle().getIdentifier()).entrySet()) {
                enforcePolicyOnUser(userId, entry.getValue());
            }
        });
    }

    private <V> void enforcePolicyOnUser(int userId, PolicyState<V> policyState) {
        if (!policyState.getPolicyDefinition().isInheritable()) {
            return;
        }
        for (Map.Entry<EnforcingAdmin, V> enforcingAdminEntry :
                policyState.getPoliciesSetByAdmins().entrySet()) {
            setLocalPolicy(policyState.getPolicyDefinition(),
                    enforcingAdminEntry.getKey(),
                    enforcingAdminEntry.getValue(),
                    userId);
        }
    }

    /**
     * Handles internal state related to a user getting started.
     */
+5 −0
Original line number Diff line number Diff line
@@ -11339,6 +11339,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        }
        final int userId = user.id;
        if (isCoexistenceFlagEnabled()) {
            mDevicePolicyEngine.handleUserCreated(user);
        }
        if (token != null) {
            synchronized (getLockObject()) {
                if (mPendingUserCreatedCallbackTokens.contains(token)) {
+10 −0
Original line number Diff line number Diff line
@@ -44,6 +44,9 @@ final class PolicyDefinition<V> {
    // Only use this flag if a policy can not be applied globally.
    private static final int POLICY_FLAG_LOCAL_ONLY_POLICY = 1 << 1;

    // Only use this flag if a policy is inheritable by child profile from parent.
    private static final int POLICY_FLAG_INHERITABLE = 1 << 2;

    private static final MostRestrictive<Boolean> FALSE_MORE_RESTRICTIVE = new MostRestrictive<>(
            List.of(false, true));

@@ -210,6 +213,13 @@ final class PolicyDefinition<V> {
        return (mPolicyFlags & POLICY_FLAG_LOCAL_ONLY_POLICY) != 0;
    }

    /**
     * Returns {@code true} if the policy is inheritable by child profiles.
     */
    boolean isInheritable() {
        return (mPolicyFlags & POLICY_FLAG_INHERITABLE) != 0;
    }

    @Nullable
    V resolvePolicy(LinkedHashMap<EnforcingAdmin, V> adminsPolicy) {
        return mResolutionMechanism.resolve(adminsPolicy);
+4 −0
Original line number Diff line number Diff line
@@ -216,4 +216,8 @@ final class PolicyState<V> {
        }
        return new PolicyState<V>(policyDefinition, policiesSetByAdmins, currentResolvedPolicy);
    }

    PolicyDefinition<V> getPolicyDefinition() {
        return mPolicyDefinition;
    }
}