diff --git a/core/api/test-current.txt b/core/api/test-current.txt index b4caa7ffa4e20..332c53cb224fb 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -536,6 +536,12 @@ package android.app.admin { field @NonNull public static final android.app.admin.DeviceAdminAuthority DEVICE_ADMIN_AUTHORITY; } + public final class DevicePolicyIdentifiers { + field public static final String PERMITTED_INPUT_METHODS_POLICY = "permittedInputMethods"; + field public static final String PERSONAL_APPS_SUSPENDED_POLICY = "personalAppsSuspended"; + field public static final String SCREEN_CAPTURE_DISABLED_POLICY = "screenCaptureDisabled"; + } + public class DevicePolicyManager { method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}) public void acknowledgeNewUserDisclaimer(); method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public void calculateHasIncompatibleAccounts(); diff --git a/core/java/android/app/admin/DevicePolicyIdentifiers.java b/core/java/android/app/admin/DevicePolicyIdentifiers.java index 9b0a70d65d6fe..aeac59b12a2e9 100644 --- a/core/java/android/app/admin/DevicePolicyIdentifiers.java +++ b/core/java/android/app/admin/DevicePolicyIdentifiers.java @@ -17,6 +17,7 @@ package android.app.admin; import android.annotation.NonNull; +import android.annotation.TestApi; import android.os.UserManager; import java.util.Objects; @@ -118,6 +119,7 @@ public final class DevicePolicyIdentifiers { * * @hide */ + @TestApi public static final String PERMITTED_INPUT_METHODS_POLICY = "permittedInputMethods"; /** @@ -125,6 +127,7 @@ public final class DevicePolicyIdentifiers { * * @hide */ + @TestApi public static final String PERSONAL_APPS_SUSPENDED_POLICY = "personalAppsSuspended"; /** @@ -132,6 +135,7 @@ public final class DevicePolicyIdentifiers { * * @hide */ + @TestApi public static final String SCREEN_CAPTURE_DISABLED_POLICY = "screenCaptureDisabled"; /** diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java index 415440b1f46dc..cf49dcf8004e6 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java @@ -130,12 +130,11 @@ final class DevicePolicyEngine { void setLocalPolicy( @NonNull PolicyDefinition policyDefinition, @NonNull EnforcingAdmin enforcingAdmin, - @NonNull PolicyValue value, + @Nullable PolicyValue value, int userId, boolean skipEnforcePolicy) { Objects.requireNonNull(policyDefinition); Objects.requireNonNull(enforcingAdmin); - Objects.requireNonNull(value); synchronized (mLock) { PolicyState localPolicyState = getLocalPolicyStateLocked(policyDefinition, userId); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 7d661eb1914b3..0a4cd7a9a8a42 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -12214,17 +12214,22 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } synchronized (getLockObject()) { - ActiveAdmin admin; - if (isPermissionCheckFlagEnabled()) { - admin = enforcePermissionAndGetEnforcingAdmin( - who, MANAGE_DEVICE_POLICY_INPUT_METHODS, - caller.getPackageName(), userId).getActiveAdmin(); + if (isPolicyEngineForFinanceFlagEnabled()) { + EnforcingAdmin admin = getEnforcingAdminForCaller(who, callerPackageName); + mDevicePolicyEngine.setLocalPolicy( + PolicyDefinition.PERMITTED_INPUT_METHODS, + admin, + packageList == null + ? null + : new StringSetPolicyValue(new HashSet<>(packageList)), + userId); } else { - admin = getParentOfAdminIfRequired( - getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()), calledOnParentInstance); + ActiveAdmin admin = getParentOfAdminIfRequired( + getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()), + calledOnParentInstance); + admin.permittedInputMethods = packageList; + saveSettingsLocked(caller.getUserId()); } - admin.permittedInputMethods = packageList; - saveSettingsLocked(caller.getUserId()); } DevicePolicyEventLogger @@ -12272,19 +12277,18 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } synchronized (getLockObject()) { - ActiveAdmin admin; - if (isPermissionCheckFlagEnabled()) { + if (isPolicyEngineForFinanceFlagEnabled()) { int affectedUser = calledOnParentInstance ? getProfileParentId( caller.getUserId()) : caller.getUserId(); - admin = enforcePermissionAndGetEnforcingAdmin( - who, MANAGE_DEVICE_POLICY_INPUT_METHODS, caller.getPackageName(), - affectedUser).getActiveAdmin(); + Set policy = mDevicePolicyEngine.getResolvedPolicy( + PolicyDefinition.PERMITTED_INPUT_METHODS, affectedUser); + return policy == null ? null : new ArrayList<>(policy); } else { - admin = getParentOfAdminIfRequired( + ActiveAdmin admin = getParentOfAdminIfRequired( getProfileOwnerOrDeviceOwnerLocked( caller.getUserId()), calledOnParentInstance); + return admin.permittedInputMethods; } - return admin.permittedInputMethods; } } @@ -12302,37 +12306,45 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } private @Nullable List getPermittedInputMethodsUnchecked(@UserIdInt int userId) { - synchronized (getLockObject()) { - List result = null; - // Only device or profile owners can have permitted lists set. - List admins = getActiveAdminsForAffectedUserInclPermissionBasedAdminLocked(userId); - for (ActiveAdmin admin: admins) { - List fromAdmin = admin.permittedInputMethods; - if (fromAdmin != null) { - if (result == null) { - result = new ArrayList(fromAdmin); - } else { - result.retainAll(fromAdmin); - } - } - } - - // If we have a permitted list add all system input methods. - if (result != null) { - List imes = InputMethodManagerInternal - .get().getInputMethodListAsUser(userId); - if (imes != null) { - for (InputMethodInfo ime : imes) { - ServiceInfo serviceInfo = ime.getServiceInfo(); - ApplicationInfo applicationInfo = serviceInfo.applicationInfo; - if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { - result.add(serviceInfo.packageName); + List result = null; + if (isPolicyEngineForFinanceFlagEnabled()) { + Set policy = mDevicePolicyEngine.getResolvedPolicy( + PolicyDefinition.PERMITTED_INPUT_METHODS, userId); + result = policy == null ? null : new ArrayList<>(policy); + } else { + synchronized (getLockObject()) { + // Only device or profile owners can have permitted lists set. + List admins = + getActiveAdminsForAffectedUserInclPermissionBasedAdminLocked( + userId); + for (ActiveAdmin admin : admins) { + List fromAdmin = admin.permittedInputMethods; + if (fromAdmin != null) { + if (result == null) { + result = new ArrayList(fromAdmin); + } else { + result.retainAll(fromAdmin); } } } } - return result; } + + // If we have a permitted list add all system input methods. + if (result != null) { + List imes = InputMethodManagerInternal + .get().getInputMethodListAsUser(userId); + if (imes != null) { + for (InputMethodInfo ime : imes) { + ServiceInfo serviceInfo = ime.getServiceInfo(); + ApplicationInfo applicationInfo = serviceInfo.applicationInfo; + if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { + result.add(serviceInfo.packageName); + } + } + } + } + return result; } @Override @@ -12347,17 +12359,38 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { String.format(NOT_SYSTEM_CALLER_MSG, "query if an input method is disabled by admin")); - synchronized (getLockObject()) { - ActiveAdmin admin = getParentOfAdminIfRequired( - getActiveAdminUncheckedLocked(who, userHandle), calledOnParentInstance); - if (admin == null) { - return false; + if (isPolicyEngineForFinanceFlagEnabled()) { + int affectedUser = calledOnParentInstance ? getProfileParentId(userHandle) : userHandle; + Map>> policies = + mDevicePolicyEngine.getLocalPoliciesSetByAdmins( + PolicyDefinition.PERMITTED_INPUT_METHODS, affectedUser); + EnforcingAdmin admin = null; + for (EnforcingAdmin a : policies.keySet()) { + if (a.getPackageName().equals(who.getPackageName())) { + if (policies.get(a).getValue() == null) { + return true; + } else { + return checkPackagesInPermittedListOrSystem( + Collections.singletonList(packageName), + new ArrayList<>(policies.get(a).getValue()), affectedUser); + } + } } - if (admin.permittedInputMethods == null) { - return true; + // Admin didn't set a policy + return false; + } else { + synchronized (getLockObject()) { + ActiveAdmin admin = getParentOfAdminIfRequired( + getActiveAdminUncheckedLocked(who, userHandle), calledOnParentInstance); + if (admin == null) { + return false; + } + if (admin.permittedInputMethods == null) { + return true; + } + return checkPackagesInPermittedListOrSystem(Collections.singletonList(packageName), + admin.permittedInputMethods, userHandle); } - return checkPackagesInPermittedListOrSystem(Collections.singletonList(packageName), - admin.permittedInputMethods, userHandle); } } @@ -23793,6 +23826,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { public DevicePolicyState getDevicePolicyState() { Preconditions.checkCallAuthorization( hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS)); + return mInjector.binderWithCleanCallingIdentity(mDevicePolicyEngine::getDevicePolicyState); } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java index 638596b5cc203..43a2c9bbf5c55 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java @@ -308,6 +308,13 @@ final class PolicyDefinition { DevicePolicyIdentifiers.ACCOUNT_MANAGEMENT_DISABLED_POLICY, accountType)); } + static PolicyDefinition> PERMITTED_INPUT_METHODS = new PolicyDefinition<>( + new NoArgsPolicyKey(DevicePolicyIdentifiers.PERMITTED_INPUT_METHODS_POLICY), + new MostRecent<>(), + POLICY_FLAG_LOCAL_ONLY_POLICY, + (Set value, Context context, Integer userId, PolicyKey policyKey) -> true, + new StringSetPolicySerializer()); + private static final Map> POLICY_DEFINITIONS = new HashMap<>(); private static Map USER_RESTRICTION_FLAGS = new HashMap<>(); @@ -333,6 +340,8 @@ final class PolicyDefinition { GENERIC_APPLICATION_HIDDEN); POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.ACCOUNT_MANAGEMENT_DISABLED_POLICY, GENERIC_ACCOUNT_MANAGEMENT_DISABLED); + POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.PERMITTED_INPUT_METHODS_POLICY, + PERMITTED_INPUT_METHODS); // User Restriction Policies USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_MODIFY_ACCOUNTS, /* flags= */ 0); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyState.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyState.java index 741f209a90c39..dd4c6afdcfb68 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyState.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyState.java @@ -67,9 +67,8 @@ final class PolicyState { /** * Returns {@code true} if the resolved policy has changed, {@code false} otherwise. */ - boolean addPolicy(@NonNull EnforcingAdmin admin, @NonNull PolicyValue policy) { + boolean addPolicy(@NonNull EnforcingAdmin admin, @Nullable PolicyValue policy) { Objects.requireNonNull(admin); - Objects.requireNonNull(policy); //LinkedHashMap doesn't update the insertion order of existing keys, removing the existing // key will cause it to update. @@ -89,9 +88,9 @@ final class PolicyState { * Returns {@code true} if the resolved policy has changed, {@code false} otherwise. */ boolean addPolicy( - @NonNull EnforcingAdmin admin, @NonNull PolicyValue policy, + @NonNull EnforcingAdmin admin, @Nullable PolicyValue policy, LinkedHashMap> globalPoliciesSetByAdmins) { - mPoliciesSetByAdmins.put(Objects.requireNonNull(admin), Objects.requireNonNull(policy)); + mPoliciesSetByAdmins.put(Objects.requireNonNull(admin), policy); return resolvePolicy(globalPoliciesSetByAdmins); } @@ -210,10 +209,12 @@ final class PolicyState { for (EnforcingAdmin admin : mPoliciesSetByAdmins.keySet()) { serializer.startTag(/* namespace= */ null, TAG_ADMIN_POLICY_ENTRY); - serializer.startTag(/* namespace= */ null, TAG_POLICY_VALUE_ENTRY); - mPolicyDefinition.savePolicyValueToXml( - serializer, mPoliciesSetByAdmins.get(admin).getValue()); - serializer.endTag(/* namespace= */ null, TAG_POLICY_VALUE_ENTRY); + if (mPoliciesSetByAdmins.get(admin) != null) { + serializer.startTag(/* namespace= */ null, TAG_POLICY_VALUE_ENTRY); + mPolicyDefinition.savePolicyValueToXml( + serializer, mPoliciesSetByAdmins.get(admin).getValue()); + serializer.endTag(/* namespace= */ null, TAG_POLICY_VALUE_ENTRY); + } serializer.startTag(/* namespace= */ null, TAG_ENFORCING_ADMIN_ENTRY); admin.saveToXml(serializer); @@ -250,7 +251,7 @@ final class PolicyState { break; } } - if (admin != null && value != null) { + if (admin != null) { policiesSetByAdmins.put(admin, value); } else { Log.e(TAG, "Error Parsing TAG_ADMIN_POLICY_ENTRY");