Loading services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java +32 −0 Original line number Diff line number Diff line Loading @@ -631,6 +631,38 @@ final class DevicePolicyEngine { } } /** * Returns all the {@code policyKeys} set by any admin that share the same * {@link PolicyKey#getIdentifier()} as the provided {@code policyDefinition}. * * <p>For example, getLocalPolicyKeysSetByAllAdmins(PERMISSION_GRANT) returns all permission * grants set by any admin. * * <p>Note that this will always return at most one item for policies that do not require * additional params (e.g. {@link PolicyDefinition#LOCK_TASK} vs * {@link PolicyDefinition#PERMISSION_GRANT(String, String)}). * */ @NonNull <V> Set<PolicyKey> getLocalPolicyKeysSetByAllAdmins( @NonNull PolicyDefinition<V> policyDefinition, int userId) { Objects.requireNonNull(policyDefinition); synchronized (mLock) { if (policyDefinition.isGlobalOnlyPolicy() || !mLocalPolicies.contains(userId)) { return Set.of(); } Set<PolicyKey> keys = new HashSet<>(); for (PolicyKey key : mLocalPolicies.get(userId).keySet()) { if (key.hasSameIdentifierAs(policyDefinition.getPolicyKey())) { keys.add(key); } } return keys; } } /** * Returns all user restriction policies set by the given admin. * Loading services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +66 −30 Original line number Diff line number Diff line Loading @@ -280,6 +280,7 @@ import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.StatusBarManager; import android.app.admin.AccountTypePolicyKey; import android.app.admin.BooleanPolicyValue; import android.app.admin.BundlePolicyValue; import android.app.admin.ComponentNamePolicyValue; Loading Loading @@ -14019,16 +14020,28 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { caller = getCallerIdentity(who); } synchronized (getLockObject()) { final ActiveAdmin ap; if (isPermissionCheckFlagEnabled()) { int affectedUser = getAffectedUser(parent); EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin( who, MANAGE_DEVICE_POLICY_ACCOUNT_MANAGEMENT, caller.getPackageName(), getAffectedUser(parent) affectedUser ); ap = enforcingAdmin.getActiveAdmin(); if (disabled) { mDevicePolicyEngine.setLocalPolicy( PolicyDefinition.ACCOUNT_MANAGEMENT_DISABLED(accountType), enforcingAdmin, new BooleanPolicyValue(disabled), affectedUser); } else { mDevicePolicyEngine.removeLocalPolicy( PolicyDefinition.ACCOUNT_MANAGEMENT_DISABLED(accountType), enforcingAdmin, affectedUser); } } else { final ActiveAdmin ap; Objects.requireNonNull(who, "ComponentName is null"); /* * When called on the parent DPM instance (parent == true), affects active admin Loading @@ -14045,7 +14058,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { ap = getParentOfAdminIfRequired( getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()), parent); } } if (disabled) { ap.accountTypesWithManagementDisabled.add(accountType); } else { Loading @@ -14054,6 +14066,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { saveSettingsLocked(UserHandle.getCallingUserId()); } } } @Override public String[] getAccountTypesWithManagementDisabled(String callerPackageName) { Loading @@ -14069,22 +14082,43 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } CallerIdentity caller; Preconditions.checkArgumentNonnegative(userId, "Invalid userId"); final ArraySet<String> resultSet = new ArraySet<>(); if (isPermissionCheckFlagEnabled()) { int affectedUser = parent ? getProfileParentId(userId) : userId; caller = getCallerIdentity(callerPackageName); if (!hasPermission(MANAGE_DEVICE_POLICY_ACCOUNT_MANAGEMENT, caller.getPackageName(), userId) callerPackageName, affectedUser) && !hasFullCrossUsersPermission(caller, userId)) { throw new SecurityException("Caller does not have permission to call this on user: " + userId); + affectedUser); } Set<PolicyKey> keys = mDevicePolicyEngine.getLocalPolicyKeysSetByAllAdmins( PolicyDefinition.GENERIC_ACCOUNT_MANAGEMENT_DISABLED, affectedUser); for (PolicyKey key : keys) { if (!(key instanceof AccountTypePolicyKey)) { throw new IllegalStateException("PolicyKey for " + "MANAGE_DEVICE_POLICY_ACCOUNT_MANAGEMENT is not of type " + "AccountTypePolicyKey"); } AccountTypePolicyKey parsedKey = (AccountTypePolicyKey) key; String accountType = Objects.requireNonNull(parsedKey.getAccountType()); Boolean disabled = mDevicePolicyEngine.getResolvedPolicy( PolicyDefinition.ACCOUNT_MANAGEMENT_DISABLED(accountType), affectedUser); if (disabled != null && disabled) { resultSet.add(accountType); } } } else { caller = getCallerIdentity(); Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userId)); } synchronized (getLockObject()) { final ArraySet<String> resultSet = new ArraySet<>(); if (!parent) { final DevicePolicyData policy = getUserData(userId); for (ActiveAdmin admin : policy.mAdminList) { Loading @@ -14092,18 +14126,20 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } // Check if there's a profile owner of an org-owned device and the method is called for // the parent user of this profile owner. // Check if there's a profile owner of an org-owned device and the method is called // for the parent user of this profile owner. final ActiveAdmin orgOwnedAdmin = getProfileOwnerOfOrganizationOwnedDeviceLocked(userId); final boolean shouldGetParentAccounts = orgOwnedAdmin != null && (parent || UserHandle.getUserId(orgOwnedAdmin.getUid()) != userId); if (shouldGetParentAccounts) { resultSet.addAll( orgOwnedAdmin.getParentActiveAdmin().accountTypesWithManagementDisabled); orgOwnedAdmin.getParentActiveAdmin() .accountTypesWithManagementDisabled); } } return resultSet.toArray(new String[resultSet.size()]); } return resultSet.toArray(new String[resultSet.size()]); } @Override services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java +29 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server.devicepolicy; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.admin.AccountTypePolicyKey; import android.app.admin.BooleanPolicyValue; import android.app.admin.DevicePolicyIdentifiers; import android.app.admin.DevicePolicyManager; Loading Loading @@ -281,6 +282,32 @@ final class PolicyDefinition<V> { DevicePolicyIdentifiers.APPLICATION_HIDDEN_POLICY, packageName)); } // This is saved in the static map sPolicyDefinitions so that we're able to reconstruct the // actual policy with the correct arguments (i.e. packageName) when reading the policies from // xml. static PolicyDefinition<Boolean> GENERIC_ACCOUNT_MANAGEMENT_DISABLED = new PolicyDefinition<>( new AccountTypePolicyKey( DevicePolicyIdentifiers.ACCOUNT_MANAGEMENT_DISABLED_POLICY), TRUE_MORE_RESTRICTIVE, POLICY_FLAG_LOCAL_ONLY_POLICY, // Nothing is enforced, we just need to store it (Boolean value, Context context, Integer userId, PolicyKey policyKey) -> true, new BooleanPolicySerializer()); /** * Passing in {@code null} for {@code accountType} will return * {@link #GENERIC_ACCOUNT_MANAGEMENT_DISABLED}. */ static PolicyDefinition<Boolean> ACCOUNT_MANAGEMENT_DISABLED(String accountType) { if (accountType == null) { return GENERIC_ACCOUNT_MANAGEMENT_DISABLED; } return GENERIC_ACCOUNT_MANAGEMENT_DISABLED.createPolicyDefinition( new AccountTypePolicyKey( DevicePolicyIdentifiers.ACCOUNT_MANAGEMENT_DISABLED_POLICY, accountType)); } private static final Map<String, PolicyDefinition<?>> POLICY_DEFINITIONS = new HashMap<>(); private static Map<String, Integer> USER_RESTRICTION_FLAGS = new HashMap<>(); Loading @@ -304,6 +331,8 @@ final class PolicyDefinition<V> { KEYGUARD_DISABLED_FEATURES); POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.APPLICATION_HIDDEN_POLICY, GENERIC_APPLICATION_HIDDEN); POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.ACCOUNT_MANAGEMENT_DISABLED_POLICY, GENERIC_ACCOUNT_MANAGEMENT_DISABLED); // User Restriction Policies USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_MODIFY_ACCOUNTS, /* flags= */ 0); Loading Loading
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java +32 −0 Original line number Diff line number Diff line Loading @@ -631,6 +631,38 @@ final class DevicePolicyEngine { } } /** * Returns all the {@code policyKeys} set by any admin that share the same * {@link PolicyKey#getIdentifier()} as the provided {@code policyDefinition}. * * <p>For example, getLocalPolicyKeysSetByAllAdmins(PERMISSION_GRANT) returns all permission * grants set by any admin. * * <p>Note that this will always return at most one item for policies that do not require * additional params (e.g. {@link PolicyDefinition#LOCK_TASK} vs * {@link PolicyDefinition#PERMISSION_GRANT(String, String)}). * */ @NonNull <V> Set<PolicyKey> getLocalPolicyKeysSetByAllAdmins( @NonNull PolicyDefinition<V> policyDefinition, int userId) { Objects.requireNonNull(policyDefinition); synchronized (mLock) { if (policyDefinition.isGlobalOnlyPolicy() || !mLocalPolicies.contains(userId)) { return Set.of(); } Set<PolicyKey> keys = new HashSet<>(); for (PolicyKey key : mLocalPolicies.get(userId).keySet()) { if (key.hasSameIdentifierAs(policyDefinition.getPolicyKey())) { keys.add(key); } } return keys; } } /** * Returns all user restriction policies set by the given admin. * Loading
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +66 −30 Original line number Diff line number Diff line Loading @@ -280,6 +280,7 @@ import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.StatusBarManager; import android.app.admin.AccountTypePolicyKey; import android.app.admin.BooleanPolicyValue; import android.app.admin.BundlePolicyValue; import android.app.admin.ComponentNamePolicyValue; Loading Loading @@ -14019,16 +14020,28 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { caller = getCallerIdentity(who); } synchronized (getLockObject()) { final ActiveAdmin ap; if (isPermissionCheckFlagEnabled()) { int affectedUser = getAffectedUser(parent); EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin( who, MANAGE_DEVICE_POLICY_ACCOUNT_MANAGEMENT, caller.getPackageName(), getAffectedUser(parent) affectedUser ); ap = enforcingAdmin.getActiveAdmin(); if (disabled) { mDevicePolicyEngine.setLocalPolicy( PolicyDefinition.ACCOUNT_MANAGEMENT_DISABLED(accountType), enforcingAdmin, new BooleanPolicyValue(disabled), affectedUser); } else { mDevicePolicyEngine.removeLocalPolicy( PolicyDefinition.ACCOUNT_MANAGEMENT_DISABLED(accountType), enforcingAdmin, affectedUser); } } else { final ActiveAdmin ap; Objects.requireNonNull(who, "ComponentName is null"); /* * When called on the parent DPM instance (parent == true), affects active admin Loading @@ -14045,7 +14058,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { ap = getParentOfAdminIfRequired( getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()), parent); } } if (disabled) { ap.accountTypesWithManagementDisabled.add(accountType); } else { Loading @@ -14054,6 +14066,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { saveSettingsLocked(UserHandle.getCallingUserId()); } } } @Override public String[] getAccountTypesWithManagementDisabled(String callerPackageName) { Loading @@ -14069,22 +14082,43 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } CallerIdentity caller; Preconditions.checkArgumentNonnegative(userId, "Invalid userId"); final ArraySet<String> resultSet = new ArraySet<>(); if (isPermissionCheckFlagEnabled()) { int affectedUser = parent ? getProfileParentId(userId) : userId; caller = getCallerIdentity(callerPackageName); if (!hasPermission(MANAGE_DEVICE_POLICY_ACCOUNT_MANAGEMENT, caller.getPackageName(), userId) callerPackageName, affectedUser) && !hasFullCrossUsersPermission(caller, userId)) { throw new SecurityException("Caller does not have permission to call this on user: " + userId); + affectedUser); } Set<PolicyKey> keys = mDevicePolicyEngine.getLocalPolicyKeysSetByAllAdmins( PolicyDefinition.GENERIC_ACCOUNT_MANAGEMENT_DISABLED, affectedUser); for (PolicyKey key : keys) { if (!(key instanceof AccountTypePolicyKey)) { throw new IllegalStateException("PolicyKey for " + "MANAGE_DEVICE_POLICY_ACCOUNT_MANAGEMENT is not of type " + "AccountTypePolicyKey"); } AccountTypePolicyKey parsedKey = (AccountTypePolicyKey) key; String accountType = Objects.requireNonNull(parsedKey.getAccountType()); Boolean disabled = mDevicePolicyEngine.getResolvedPolicy( PolicyDefinition.ACCOUNT_MANAGEMENT_DISABLED(accountType), affectedUser); if (disabled != null && disabled) { resultSet.add(accountType); } } } else { caller = getCallerIdentity(); Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userId)); } synchronized (getLockObject()) { final ArraySet<String> resultSet = new ArraySet<>(); if (!parent) { final DevicePolicyData policy = getUserData(userId); for (ActiveAdmin admin : policy.mAdminList) { Loading @@ -14092,18 +14126,20 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } // Check if there's a profile owner of an org-owned device and the method is called for // the parent user of this profile owner. // Check if there's a profile owner of an org-owned device and the method is called // for the parent user of this profile owner. final ActiveAdmin orgOwnedAdmin = getProfileOwnerOfOrganizationOwnedDeviceLocked(userId); final boolean shouldGetParentAccounts = orgOwnedAdmin != null && (parent || UserHandle.getUserId(orgOwnedAdmin.getUid()) != userId); if (shouldGetParentAccounts) { resultSet.addAll( orgOwnedAdmin.getParentActiveAdmin().accountTypesWithManagementDisabled); orgOwnedAdmin.getParentActiveAdmin() .accountTypesWithManagementDisabled); } } return resultSet.toArray(new String[resultSet.size()]); } return resultSet.toArray(new String[resultSet.size()]); } @Override
services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java +29 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server.devicepolicy; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.admin.AccountTypePolicyKey; import android.app.admin.BooleanPolicyValue; import android.app.admin.DevicePolicyIdentifiers; import android.app.admin.DevicePolicyManager; Loading Loading @@ -281,6 +282,32 @@ final class PolicyDefinition<V> { DevicePolicyIdentifiers.APPLICATION_HIDDEN_POLICY, packageName)); } // This is saved in the static map sPolicyDefinitions so that we're able to reconstruct the // actual policy with the correct arguments (i.e. packageName) when reading the policies from // xml. static PolicyDefinition<Boolean> GENERIC_ACCOUNT_MANAGEMENT_DISABLED = new PolicyDefinition<>( new AccountTypePolicyKey( DevicePolicyIdentifiers.ACCOUNT_MANAGEMENT_DISABLED_POLICY), TRUE_MORE_RESTRICTIVE, POLICY_FLAG_LOCAL_ONLY_POLICY, // Nothing is enforced, we just need to store it (Boolean value, Context context, Integer userId, PolicyKey policyKey) -> true, new BooleanPolicySerializer()); /** * Passing in {@code null} for {@code accountType} will return * {@link #GENERIC_ACCOUNT_MANAGEMENT_DISABLED}. */ static PolicyDefinition<Boolean> ACCOUNT_MANAGEMENT_DISABLED(String accountType) { if (accountType == null) { return GENERIC_ACCOUNT_MANAGEMENT_DISABLED; } return GENERIC_ACCOUNT_MANAGEMENT_DISABLED.createPolicyDefinition( new AccountTypePolicyKey( DevicePolicyIdentifiers.ACCOUNT_MANAGEMENT_DISABLED_POLICY, accountType)); } private static final Map<String, PolicyDefinition<?>> POLICY_DEFINITIONS = new HashMap<>(); private static Map<String, Integer> USER_RESTRICTION_FLAGS = new HashMap<>(); Loading @@ -304,6 +331,8 @@ final class PolicyDefinition<V> { KEYGUARD_DISABLED_FEATURES); POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.APPLICATION_HIDDEN_POLICY, GENERIC_APPLICATION_HIDDEN); POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.ACCOUNT_MANAGEMENT_DISABLED_POLICY, GENERIC_ACCOUNT_MANAGEMENT_DISABLED); // User Restriction Policies USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_MODIFY_ACCOUNTS, /* flags= */ 0); Loading