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

Commit 4783f846 authored by Kholoud Mohamed's avatar Kholoud Mohamed Committed by Automerger Merge Worker
Browse files

Merge "Use DPMS lock for the policy engine" into udc-dev am: 98c8c131

parents d4eb86b1 98c8c131
Loading
Loading
Loading
Loading
+119 −106
Original line number Original line Diff line number Diff line
@@ -101,7 +101,7 @@ final class DevicePolicyEngine {
    private final UserManager mUserManager;
    private final UserManager mUserManager;


    // TODO(b/256849338): add more granular locks
    // TODO(b/256849338): add more granular locks
    private final Object mLock = new Object();
    private final Object mLock;


    /**
    /**
     * Map of <userId, Map<policyKey, policyState>>
     * Map of <userId, Map<policyKey, policyState>>
@@ -122,9 +122,11 @@ final class DevicePolicyEngine {


    DevicePolicyEngine(
    DevicePolicyEngine(
            @NonNull Context context,
            @NonNull Context context,
            @NonNull DeviceAdminServiceController deviceAdminServiceController) {
            @NonNull DeviceAdminServiceController deviceAdminServiceController,
            @NonNull Object lock) {
        mContext = Objects.requireNonNull(context);
        mContext = Objects.requireNonNull(context);
        mDeviceAdminServiceController = Objects.requireNonNull(deviceAdminServiceController);
        mDeviceAdminServiceController = Objects.requireNonNull(deviceAdminServiceController);
        mLock = Objects.requireNonNull(lock);
        mUserManager = mContext.getSystemService(UserManager.class);
        mUserManager = mContext.getSystemService(UserManager.class);
        mLocalPolicies = new SparseArray<>();
        mLocalPolicies = new SparseArray<>();
        mGlobalPolicies = new HashMap<>();
        mGlobalPolicies = new HashMap<>();
@@ -152,8 +154,8 @@ final class DevicePolicyEngine {
            PolicyState<V> localPolicyState = getLocalPolicyStateLocked(policyDefinition, userId);
            PolicyState<V> localPolicyState = getLocalPolicyStateLocked(policyDefinition, userId);


            if (policyDefinition.isNonCoexistablePolicy()) {
            if (policyDefinition.isNonCoexistablePolicy()) {
                setNonCoexistableLocalPolicy(policyDefinition, localPolicyState, enforcingAdmin,
                setNonCoexistableLocalPolicyLocked(policyDefinition, localPolicyState,
                        value, userId, skipEnforcePolicy);
                        enforcingAdmin, value, userId, skipEnforcePolicy);
                return;
                return;
            }
            }


@@ -173,7 +175,7 @@ final class DevicePolicyEngine {
            // the data structures.
            // the data structures.
            if (!skipEnforcePolicy) {
            if (!skipEnforcePolicy) {
                if (policyChanged) {
                if (policyChanged) {
                    onLocalPolicyChanged(policyDefinition, enforcingAdmin, userId);
                    onLocalPolicyChangedLocked(policyDefinition, enforcingAdmin, userId);
                }
                }
                boolean policyEnforced = Objects.equals(
                boolean policyEnforced = Objects.equals(
                        localPolicyState.getCurrentResolvedPolicy(), value);
                        localPolicyState.getCurrentResolvedPolicy(), value);
@@ -211,7 +213,7 @@ final class DevicePolicyEngine {
     *
     *
     * <p>Passing a {@code null} value means the policy set by this admin should be removed.
     * <p>Passing a {@code null} value means the policy set by this admin should be removed.
     */
     */
    private <V> void setNonCoexistableLocalPolicy(
    private <V> void setNonCoexistableLocalPolicyLocked(
            PolicyDefinition<V> policyDefinition,
            PolicyDefinition<V> policyDefinition,
            PolicyState<V> localPolicyState,
            PolicyState<V> localPolicyState,
            EnforcingAdmin enforcingAdmin,
            EnforcingAdmin enforcingAdmin,
@@ -266,8 +268,8 @@ final class DevicePolicyEngine {
            PolicyState<V> localPolicyState = getLocalPolicyStateLocked(policyDefinition, userId);
            PolicyState<V> localPolicyState = getLocalPolicyStateLocked(policyDefinition, userId);


            if (policyDefinition.isNonCoexistablePolicy()) {
            if (policyDefinition.isNonCoexistablePolicy()) {
                setNonCoexistableLocalPolicy(policyDefinition, localPolicyState, enforcingAdmin,
                setNonCoexistableLocalPolicyLocked(policyDefinition, localPolicyState,
                        /* value= */ null, userId, /* skipEnforcePolicy= */ false);
                        enforcingAdmin, /* value= */ null, userId, /* skipEnforcePolicy= */ false);
                return;
                return;
            }
            }


@@ -282,7 +284,7 @@ final class DevicePolicyEngine {
            }
            }


            if (policyChanged) {
            if (policyChanged) {
                onLocalPolicyChanged(policyDefinition, enforcingAdmin, userId);
                onLocalPolicyChangedLocked(policyDefinition, enforcingAdmin, userId);
            }
            }


            // For a removePolicy to be enforced, it means no current policy exists
            // For a removePolicy to be enforced, it means no current policy exists
@@ -348,7 +350,7 @@ final class DevicePolicyEngine {
    /**
    /**
     * Enforces the new policy and notifies relevant admins.
     * Enforces the new policy and notifies relevant admins.
     */
     */
    private <V> void onLocalPolicyChanged(
    private <V> void onLocalPolicyChangedLocked(
            @NonNull PolicyDefinition<V> policyDefinition,
            @NonNull PolicyDefinition<V> policyDefinition,
            @NonNull EnforcingAdmin enforcingAdmin,
            @NonNull EnforcingAdmin enforcingAdmin,
            int userId) {
            int userId) {
@@ -358,7 +360,7 @@ final class DevicePolicyEngine {
                policyDefinition, localPolicyState.getCurrentResolvedPolicy(), userId);
                policyDefinition, localPolicyState.getCurrentResolvedPolicy(), userId);


        // Send policy updates to admins who've set it locally
        // Send policy updates to admins who've set it locally
        sendPolicyChangedToAdmins(
        sendPolicyChangedToAdminsLocked(
                localPolicyState,
                localPolicyState,
                enforcingAdmin,
                enforcingAdmin,
                policyDefinition,
                policyDefinition,
@@ -369,7 +371,7 @@ final class DevicePolicyEngine {
        // Send policy updates to admins who've set it globally
        // Send policy updates to admins who've set it globally
        if (hasGlobalPolicyLocked(policyDefinition)) {
        if (hasGlobalPolicyLocked(policyDefinition)) {
            PolicyState<V> globalPolicyState = getGlobalPolicyStateLocked(policyDefinition);
            PolicyState<V> globalPolicyState = getGlobalPolicyStateLocked(policyDefinition);
            sendPolicyChangedToAdmins(
            sendPolicyChangedToAdminsLocked(
                    globalPolicyState,
                    globalPolicyState,
                    enforcingAdmin,
                    enforcingAdmin,
                    policyDefinition,
                    policyDefinition,
@@ -424,7 +426,7 @@ final class DevicePolicyEngine {
            // the data structures.
            // the data structures.
            if (!skipEnforcePolicy) {
            if (!skipEnforcePolicy) {
                if (policyChanged) {
                if (policyChanged) {
                    onGlobalPolicyChanged(policyDefinition, enforcingAdmin);
                    onGlobalPolicyChangedLocked(policyDefinition, enforcingAdmin);
                }
                }


                boolean policyAppliedGlobally = Objects.equals(
                boolean policyAppliedGlobally = Objects.equals(
@@ -473,7 +475,7 @@ final class DevicePolicyEngine {
            boolean policyChanged = policyState.removePolicy(enforcingAdmin);
            boolean policyChanged = policyState.removePolicy(enforcingAdmin);


            if (policyChanged) {
            if (policyChanged) {
                onGlobalPolicyChanged(policyDefinition, enforcingAdmin);
                onGlobalPolicyChangedLocked(policyDefinition, enforcingAdmin);
            }
            }


            applyGlobalPolicyOnUsersWithLocalPoliciesLocked(policyDefinition, enforcingAdmin,
            applyGlobalPolicyOnUsersWithLocalPoliciesLocked(policyDefinition, enforcingAdmin,
@@ -499,7 +501,7 @@ final class DevicePolicyEngine {
    /**
    /**
     * Enforces the new policy globally and notifies relevant admins.
     * Enforces the new policy globally and notifies relevant admins.
     */
     */
    private <V> void onGlobalPolicyChanged(
    private <V> void onGlobalPolicyChangedLocked(
            @NonNull PolicyDefinition<V> policyDefinition,
            @NonNull PolicyDefinition<V> policyDefinition,
            @NonNull EnforcingAdmin enforcingAdmin) {
            @NonNull EnforcingAdmin enforcingAdmin) {
        PolicyState<V> policyState = getGlobalPolicyStateLocked(policyDefinition);
        PolicyState<V> policyState = getGlobalPolicyStateLocked(policyDefinition);
@@ -507,7 +509,7 @@ final class DevicePolicyEngine {
        enforcePolicy(policyDefinition, policyState.getCurrentResolvedPolicy(),
        enforcePolicy(policyDefinition, policyState.getCurrentResolvedPolicy(),
                UserHandle.USER_ALL);
                UserHandle.USER_ALL);


        sendPolicyChangedToAdmins(
        sendPolicyChangedToAdminsLocked(
                policyState,
                policyState,
                enforcingAdmin,
                enforcingAdmin,
                policyDefinition,
                policyDefinition,
@@ -552,7 +554,7 @@ final class DevicePolicyEngine {
                        policyDefinition,
                        policyDefinition,
                        localPolicyState.getCurrentResolvedPolicy(),
                        localPolicyState.getCurrentResolvedPolicy(),
                        userId);
                        userId);
                sendPolicyChangedToAdmins(
                sendPolicyChangedToAdminsLocked(
                        localPolicyState,
                        localPolicyState,
                        enforcingAdmin,
                        enforcingAdmin,
                        policyDefinition,
                        policyDefinition,
@@ -745,6 +747,7 @@ final class DevicePolicyEngine {
    }
    }


    <V> void transferPolicies(EnforcingAdmin oldAdmin, EnforcingAdmin newAdmin) {
    <V> void transferPolicies(EnforcingAdmin oldAdmin, EnforcingAdmin newAdmin) {
        synchronized (mLock) {
            Set<PolicyKey> globalPolicies = new HashSet<>(mGlobalPolicies.keySet());
            Set<PolicyKey> globalPolicies = new HashSet<>(mGlobalPolicies.keySet());
            for (PolicyKey policy : globalPolicies) {
            for (PolicyKey policy : globalPolicies) {
                PolicyState<?> policyState = mGlobalPolicies.get(policy);
                PolicyState<?> policyState = mGlobalPolicies.get(policy);
@@ -772,7 +775,7 @@ final class DevicePolicyEngine {
                    }
                    }
                }
                }
            }
            }

        }
        removePoliciesForAdmin(oldAdmin);
        removePoliciesForAdmin(oldAdmin);
    }
    }


@@ -836,7 +839,7 @@ final class DevicePolicyEngine {
            mLocalPolicies.get(userId).put(
            mLocalPolicies.get(userId).put(
                    policyDefinition.getPolicyKey(), new PolicyState<>(policyDefinition));
                    policyDefinition.getPolicyKey(), new PolicyState<>(policyDefinition));
        }
        }
        return getPolicyState(mLocalPolicies.get(userId), policyDefinition);
        return getPolicyStateLocked(mLocalPolicies.get(userId), policyDefinition);
    }
    }


    private <V> void removeLocalPolicyStateLocked(
    private <V> void removeLocalPolicyStateLocked(
@@ -858,14 +861,14 @@ final class DevicePolicyEngine {
            mGlobalPolicies.put(
            mGlobalPolicies.put(
                    policyDefinition.getPolicyKey(), new PolicyState<>(policyDefinition));
                    policyDefinition.getPolicyKey(), new PolicyState<>(policyDefinition));
        }
        }
        return getPolicyState(mGlobalPolicies, policyDefinition);
        return getPolicyStateLocked(mGlobalPolicies, policyDefinition);
    }
    }


    private <V> void removeGlobalPolicyStateLocked(PolicyDefinition<V> policyDefinition) {
    private <V> void removeGlobalPolicyStateLocked(PolicyDefinition<V> policyDefinition) {
        mGlobalPolicies.remove(policyDefinition.getPolicyKey());
        mGlobalPolicies.remove(policyDefinition.getPolicyKey());
    }
    }


    private static <V> PolicyState<V> getPolicyState(
    private static <V> PolicyState<V> getPolicyStateLocked(
            Map<PolicyKey, PolicyState<?>> policies, PolicyDefinition<V> policyDefinition) {
            Map<PolicyKey, PolicyState<?>> policies, PolicyDefinition<V> policyDefinition) {
        try {
        try {
            // This will not throw an exception because policyDefinition is of type V, so unless
            // This will not throw an exception because policyDefinition is of type V, so unless
@@ -935,7 +938,7 @@ final class DevicePolicyEngine {
    }
    }


    // TODO(b/261430877): Finalise the decision on which admins to send the updates to.
    // TODO(b/261430877): Finalise the decision on which admins to send the updates to.
    private <V> void sendPolicyChangedToAdmins(
    private <V> void sendPolicyChangedToAdminsLocked(
            PolicyState<V> policyState,
            PolicyState<V> policyState,
            EnforcingAdmin callingAdmin,
            EnforcingAdmin callingAdmin,
            PolicyDefinition<V> policyDefinition,
            PolicyDefinition<V> policyDefinition,
@@ -1210,17 +1213,19 @@ final class DevicePolicyEngine {
            if (parentInfo == null || parentInfo.getUserHandle().getIdentifier() == userId) {
            if (parentInfo == null || parentInfo.getUserHandle().getIdentifier() == userId) {
                return;
                return;
            }
            }
            synchronized (mLock) {
                if (!mLocalPolicies.contains(parentInfo.getUserHandle().getIdentifier())) {
                if (!mLocalPolicies.contains(parentInfo.getUserHandle().getIdentifier())) {
                    return;
                    return;
                }
                }
                for (Map.Entry<PolicyKey, PolicyState<?>> entry : mLocalPolicies.get(
                for (Map.Entry<PolicyKey, PolicyState<?>> entry : mLocalPolicies.get(
                        parentInfo.getUserHandle().getIdentifier()).entrySet()) {
                        parentInfo.getUserHandle().getIdentifier()).entrySet()) {
                enforcePolicyOnUser(userId, entry.getValue());
                    enforcePolicyOnUserLocked(userId, entry.getValue());
                }
            }
            }
        });
        });
    }
    }


    private <V> void enforcePolicyOnUser(int userId, PolicyState<V> policyState) {
    private <V> void enforcePolicyOnUserLocked(int userId, PolicyState<V> policyState) {
        if (!policyState.getPolicyDefinition().isInheritable()) {
        if (!policyState.getPolicyDefinition().isInheritable()) {
            return;
            return;
        }
        }
@@ -1239,6 +1244,7 @@ final class DevicePolicyEngine {
     */
     */
    @NonNull
    @NonNull
    DevicePolicyState getDevicePolicyState() {
    DevicePolicyState getDevicePolicyState() {
        synchronized (mLock) {
            Map<UserHandle, Map<PolicyKey, android.app.admin.PolicyState<?>>> policies =
            Map<UserHandle, Map<PolicyKey, android.app.admin.PolicyState<?>>> policies =
                    new HashMap<>();
                    new HashMap<>();
            for (int i = 0; i < mLocalPolicies.size(); i++) {
            for (int i = 0; i < mLocalPolicies.size(); i++) {
@@ -1260,12 +1266,14 @@ final class DevicePolicyEngine {
            }
            }
            return new DevicePolicyState(policies);
            return new DevicePolicyState(policies);
        }
        }
    }




    /**
    /**
     * Removes all local and global policies set by that admin.
     * Removes all local and global policies set by that admin.
     */
     */
    void removePoliciesForAdmin(EnforcingAdmin admin) {
    void removePoliciesForAdmin(EnforcingAdmin admin) {
        synchronized (mLock) {
            Set<PolicyKey> globalPolicies = new HashSet<>(mGlobalPolicies.keySet());
            Set<PolicyKey> globalPolicies = new HashSet<>(mGlobalPolicies.keySet());
            for (PolicyKey policy : globalPolicies) {
            for (PolicyKey policy : globalPolicies) {
                PolicyState<?> policyState = mGlobalPolicies.get(policy);
                PolicyState<?> policyState = mGlobalPolicies.get(policy);
@@ -1287,11 +1295,13 @@ final class DevicePolicyEngine {
                }
                }
            }
            }
        }
        }
    }


    /**
    /**
     * Removes all local policies for the provided {@code userId}.
     * Removes all local policies for the provided {@code userId}.
     */
     */
    private void removeLocalPoliciesForUser(int userId) {
    private void removeLocalPoliciesForUser(int userId) {
        synchronized (mLock) {
            if (!mLocalPolicies.contains(userId)) {
            if (!mLocalPolicies.contains(userId)) {
                // No policies on user
                // No policies on user
                return;
                return;
@@ -1310,6 +1320,7 @@ final class DevicePolicyEngine {


            mLocalPolicies.remove(userId);
            mLocalPolicies.remove(userId);
        }
        }
    }


    /**
    /**
     * Removes all local and global policies for admins installed in the provided
     * Removes all local and global policies for admins installed in the provided
@@ -1376,7 +1387,7 @@ final class DevicePolicyEngine {
     */
     */
    private void updateDeviceAdminServiceOnPolicyRemoveLocked(
    private void updateDeviceAdminServiceOnPolicyRemoveLocked(
            @NonNull EnforcingAdmin enforcingAdmin) {
            @NonNull EnforcingAdmin enforcingAdmin) {
        if (doesAdminHavePolicies(enforcingAdmin)) {
        if (doesAdminHavePoliciesLocked(enforcingAdmin)) {
            return;
            return;
        }
        }
        int userId = enforcingAdmin.getUserId();
        int userId = enforcingAdmin.getUserId();
@@ -1399,7 +1410,7 @@ final class DevicePolicyEngine {
                /* actionForLog= */ "policy-removed");
                /* actionForLog= */ "policy-removed");
    }
    }


    private boolean doesAdminHavePolicies(@NonNull EnforcingAdmin enforcingAdmin) {
    private boolean doesAdminHavePoliciesLocked(@NonNull EnforcingAdmin enforcingAdmin) {
        for (PolicyKey policy : mGlobalPolicies.keySet()) {
        for (PolicyKey policy : mGlobalPolicies.keySet()) {
            PolicyState<?> policyState = mGlobalPolicies.get(policy);
            PolicyState<?> policyState = mGlobalPolicies.get(policy);
            if (policyState.getPoliciesSetByAdmins().containsKey(enforcingAdmin)) {
            if (policyState.getPoliciesSetByAdmins().containsKey(enforcingAdmin)) {
@@ -1420,14 +1431,18 @@ final class DevicePolicyEngine {


    @NonNull
    @NonNull
    private Set<EnforcingAdmin> getEnforcingAdminsOnUser(int userId) {
    private Set<EnforcingAdmin> getEnforcingAdminsOnUser(int userId) {
        synchronized (mLock) {
            return mEnforcingAdmins.contains(userId)
            return mEnforcingAdmins.contains(userId)
                    ? mEnforcingAdmins.get(userId) : Collections.emptySet();
                    ? mEnforcingAdmins.get(userId) : Collections.emptySet();
        }
        }
    }


    private void write() {
    private void write() {
        synchronized (mLock) {
            Log.d(TAG, "Writing device policies to file.");
            Log.d(TAG, "Writing device policies to file.");
            new DevicePoliciesReaderWriter().writeToFileLocked();
            new DevicePoliciesReaderWriter().writeToFileLocked();
        }
        }
    }


    // TODO(b/256852787): trigger resolving logic after loading policies as roles are recalculated
    // TODO(b/256852787): trigger resolving logic after loading policies as roles are recalculated
    //  and could result in a different enforced policy
    //  and could result in a different enforced policy
@@ -1436,11 +1451,11 @@ final class DevicePolicyEngine {
        synchronized (mLock) {
        synchronized (mLock) {
            clear();
            clear();
            new DevicePoliciesReaderWriter().readFromFileLocked();
            new DevicePoliciesReaderWriter().readFromFileLocked();
            reapplyAllPolicies();
            reapplyAllPoliciesLocked();
        }
        }
    }
    }


    private <V> void reapplyAllPolicies() {
    private <V> void reapplyAllPoliciesLocked() {
        for (PolicyKey policy : mGlobalPolicies.keySet()) {
        for (PolicyKey policy : mGlobalPolicies.keySet()) {
            PolicyState<?> policyState = mGlobalPolicies.get(policy);
            PolicyState<?> policyState = mGlobalPolicies.get(policy);
            // Policy definition and value will always be of the same type
            // Policy definition and value will always be of the same type
@@ -1470,11 +1485,9 @@ final class DevicePolicyEngine {
     * <p>Note that this doesn't clear any enforcements, it only clears the data structures.
     * <p>Note that this doesn't clear any enforcements, it only clears the data structures.
     */
     */
    void clearAllPolicies() {
    void clearAllPolicies() {
        synchronized (mLock) {
        clear();
        clear();
        write();
        write();
    }
    }
    }
    private void clear() {
    private void clear() {
        synchronized (mLock) {
        synchronized (mLock) {
            mGlobalPolicies.clear();
            mGlobalPolicies.clear();
+2 −1
Original line number Original line Diff line number Diff line
@@ -2093,7 +2093,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        mUserData = new SparseArray<>();
        mUserData = new SparseArray<>();
        mOwners = makeOwners(injector, pathProvider);
        mOwners = makeOwners(injector, pathProvider);
        mDevicePolicyEngine = new DevicePolicyEngine(mContext, mDeviceAdminServiceController);
        mDevicePolicyEngine = new DevicePolicyEngine(
                mContext, mDeviceAdminServiceController, getLockObject());
        if (!mHasFeature) {
        if (!mHasFeature) {
            // Skip the rest of the initialization
            // Skip the rest of the initialization