Loading services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java +87 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -149,6 +151,8 @@ final class DevicePolicyEngine { updateDeviceAdminServiceOnPolicyAddLocked(enforcingAdmin); write(); applyToInheritableProfiles(policyDefinition, enforcingAdmin, value, userId); } } Loading Loading @@ -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. */ Loading Loading @@ -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. */ Loading services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +5 −0 Original line number Diff line number Diff line Loading @@ -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)) { Loading services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java +10 −0 Original line number Diff line number Diff line Loading @@ -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)); Loading Loading @@ -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); Loading services/devicepolicy/java/com/android/server/devicepolicy/PolicyState.java +4 −0 Original line number Diff line number Diff line Loading @@ -216,4 +216,8 @@ final class PolicyState<V> { } return new PolicyState<V>(policyDefinition, policiesSetByAdmins, currentResolvedPolicy); } PolicyDefinition<V> getPolicyDefinition() { return mPolicyDefinition; } } Loading
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java +87 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -149,6 +151,8 @@ final class DevicePolicyEngine { updateDeviceAdminServiceOnPolicyAddLocked(enforcingAdmin); write(); applyToInheritableProfiles(policyDefinition, enforcingAdmin, value, userId); } } Loading Loading @@ -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. */ Loading Loading @@ -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. */ Loading
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +5 −0 Original line number Diff line number Diff line Loading @@ -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)) { Loading
services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java +10 −0 Original line number Diff line number Diff line Loading @@ -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)); Loading Loading @@ -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); Loading
services/devicepolicy/java/com/android/server/devicepolicy/PolicyState.java +4 −0 Original line number Diff line number Diff line Loading @@ -216,4 +216,8 @@ final class PolicyState<V> { } return new PolicyState<V>(policyDefinition, policiesSetByAdmins, currentResolvedPolicy); } PolicyDefinition<V> getPolicyDefinition() { return mPolicyDefinition; } }