Loading core/java/android/app/admin/DevicePolicyManager.java +39 −7 Original line number Diff line number Diff line Loading @@ -8675,6 +8675,19 @@ public class DevicePolicyManager { * Called by a profile or device owner to set the permitted input methods services for this * user. By default, the user can use any input method. * <p> * This method can be called on the {@link DevicePolicyManager} instance, * returned by {@link #getParentProfileInstance(ComponentName)}, where the caller must be * a profile owner of an organization-owned device. * <p> * If called on the parent instance: * <ul> * <li>The permitted input methods will be applied on the personal profile</li> * <li>Can only permit all input methods (calling this method with a {@code null} package * list) or only permit system input methods (calling this method with an empty package * list). This is to prevent the caller from learning which packages are installed on * the personal side</li> * </ul> * <p> * When zero or more packages have been added, input method that are not in the list and not * part of the system can not be enabled by the user. This method will fail if it is called for * a admin that is not for the foreground user or a profile of the foreground user. Any Loading @@ -8689,14 +8702,18 @@ public class DevicePolicyManager { * @param packageNames List of input method package names. * @return {@code true} if the operation succeeded, or {@code false} if the list didn't * contain every enabled non-system input method service. * @throws SecurityException if {@code admin} is not a device or profile owner. * @throws SecurityException if {@code admin} is not a device, profile owner or if called on * the parent profile and the {@code admin} is not a profile owner * of an organization-owned managed profile. * @throws IllegalArgumentException if called on the parent profile, the {@code admin} is a * profile owner of an organization-owned managed profile and the * list of permitted input method package names is not null or empty. */ public boolean setPermittedInputMethods( @NonNull ComponentName admin, List<String> packageNames) { throwIfParentInstance("setPermittedInputMethods"); if (mService != null) { try { return mService.setPermittedInputMethods(admin, packageNames); return mService.setPermittedInputMethods(admin, packageNames, mParentInstance); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading @@ -8708,18 +8725,25 @@ public class DevicePolicyManager { /** * Returns the list of permitted input methods set by this device or profile owner. * <p> * This method can be called on the {@link DevicePolicyManager} instance, * returned by {@link #getParentProfileInstance(ComponentName)}, where the caller must be * a profile owner of an organization-owned managed profile. If called on the parent instance, * then the returned list of permitted input methods are those which are applied on the * personal profile. * <p> * An empty list means no input methods except system input methods are allowed. Null means all * input methods are allowed. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @return List of input method package names. * @throws SecurityException if {@code admin} is not a device or profile owner. * @throws SecurityException if {@code admin} is not a device, profile owner or if called on * the parent profile and the {@code admin} is not a profile owner * of an organization-owned managed profile. */ public @Nullable List<String> getPermittedInputMethods(@NonNull ComponentName admin) { throwIfParentInstance("getPermittedInputMethods"); if (mService != null) { try { return mService.getPermittedInputMethods(admin); return mService.getPermittedInputMethods(admin, mParentInstance); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading @@ -8729,6 +8753,11 @@ public class DevicePolicyManager { /** * Called by the system to check if a specific input method is disabled by admin. * <p> * This method can be called on the {@link DevicePolicyManager} instance, * returned by {@link #getParentProfileInstance(ComponentName)}. If called on the parent * instance, this method will check whether the given input method is permitted on * the personal profile. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param packageName Input method package name that needs to be checked. Loading @@ -8741,7 +8770,8 @@ public class DevicePolicyManager { @NonNull String packageName, int userHandle) { if (mService != null) { try { return mService.isInputMethodPermittedByAdmin(admin, packageName, userHandle); return mService.isInputMethodPermittedByAdmin(admin, packageName, userHandle, mParentInstance); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading Loading @@ -10828,6 +10858,8 @@ public class DevicePolicyManager { * <li>{@link #setCameraDisabled}</li> * <li>{@link #getCameraDisabled}</li> * <li>{@link #setAccountManagementDisabled(ComponentName, String, boolean)}</li> * <li>{@link #setPermittedInputMethods}</li> * <li>{@link #getPermittedInputMethods}</li> * </ul> * * <p>The following methods can be called by the profile owner of a managed profile Loading core/java/android/app/admin/IDevicePolicyManager.aidl +3 −3 Original line number Diff line number Diff line Loading @@ -232,10 +232,10 @@ interface IDevicePolicyManager { List getPermittedAccessibilityServicesForUser(int userId); boolean isAccessibilityServicePermittedByAdmin(in ComponentName admin, String packageName, int userId); boolean setPermittedInputMethods(in ComponentName admin,in List packageList); List getPermittedInputMethods(in ComponentName admin); boolean setPermittedInputMethods(in ComponentName admin,in List packageList, boolean parent); List getPermittedInputMethods(in ComponentName admin, boolean parent); List getPermittedInputMethodsForCurrentUser(); boolean isInputMethodPermittedByAdmin(in ComponentName admin, String packageName, int userId); boolean isInputMethodPermittedByAdmin(in ComponentName admin, String packageName, int userId, boolean parent); boolean setPermittedCrossProfileNotificationListeners(in ComponentName admin, in List<String> packageList); List<String> getPermittedCrossProfileNotificationListeners(in ComponentName admin); Loading packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java +17 −8 Original line number Diff line number Diff line Loading @@ -267,19 +267,28 @@ public class RestrictedLockUtilsInternal extends RestrictedLockUtils { permitted = dpm.isInputMethodPermittedByAdmin(admin.component, packageName, userId); } boolean permittedByParentAdmin = true; EnforcedAdmin profileAdmin = null; int managedProfileId = getManagedProfileId(context, userId); EnforcedAdmin profileAdmin = getProfileOrDeviceOwner(context, getUserHandleOf(managedProfileId)); boolean permittedByProfileAdmin = true; if (profileAdmin != null) { permittedByProfileAdmin = dpm.isInputMethodPermittedByAdmin(profileAdmin.component, packageName, managedProfileId); if (managedProfileId != UserHandle.USER_NULL) { profileAdmin = getProfileOrDeviceOwner(context, getUserHandleOf(managedProfileId)); // If the device is an organization-owned device with a managed profile, the // managedProfileId will be used instead of the affected userId. This is because // isInputMethodPermittedByAdmin is called on the parent DPM instance, which will // return results affecting the personal profile. if (profileAdmin != null && dpm.isOrganizationOwnedDeviceWithManagedProfile()) { DevicePolicyManager parentDpm = sProxy.getParentProfileInstance(dpm, UserManager.get(context).getUserInfo(managedProfileId)); permittedByParentAdmin = parentDpm.isInputMethodPermittedByAdmin( profileAdmin.component, packageName, managedProfileId); } if (!permitted && !permittedByProfileAdmin) { } if (!permitted && !permittedByParentAdmin) { return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN; } else if (!permitted) { return admin; } else if (!permittedByProfileAdmin) { } else if (!permittedByParentAdmin) { return profileAdmin; } return null; Loading services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +48 −19 Original line number Diff line number Diff line Loading @@ -378,6 +378,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { private static final String CREDENTIAL_MANAGEMENT_APP = "credentialManagementApp"; private static final String NOT_CREDENTIAL_MANAGEMENT_APP = "notCredentialManagementApp"; private static final String NULL_STRING_ARRAY = "nullStringArray"; // Comprehensive list of delegations. private static final String DELEGATIONS[] = { DELEGATION_CERT_INSTALL, Loading Loading @@ -9577,59 +9579,86 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } @Override public boolean setPermittedInputMethods(ComponentName who, List packageList) { public boolean setPermittedInputMethods(ComponentName who, List packageList, boolean calledOnParentInstance) { if (!mHasFeature) { return false; } Objects.requireNonNull(who, "ComponentName is null"); final CallerIdentity caller = getCallerIdentity(who); final int userId = getProfileParentUserIfRequested( caller.getUserId(), calledOnParentInstance); if (calledOnParentInstance) { Preconditions.checkCallAuthorization(isProfileOwnerOfOrganizationOwnedDevice(caller)); Preconditions.checkArgument(packageList == null || packageList.isEmpty(), "Permitted input methods must allow all input methods or only " + "system input methods when called on the parent instance of an " + "organization-owned device"); } else { Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller)); } if (packageList != null) { List<InputMethodInfo> enabledImes = InputMethodManagerInternal.get() .getEnabledInputMethodListAsUser(caller.getUserId()); List<InputMethodInfo> enabledImes = mInjector.binderWithCleanCallingIdentity(() -> InputMethodManagerInternal.get().getEnabledInputMethodListAsUser(userId)); if (enabledImes != null) { List<String> enabledPackages = new ArrayList<String>(); for (InputMethodInfo ime : enabledImes) { enabledPackages.add(ime.getPackageName()); } if (!checkPackagesInPermittedListOrSystem(enabledPackages, packageList, caller.getUserId())) { Slog.e(LOG_TAG, "Cannot set permitted input methods, " + "because it contains already enabled input method."); userId)) { Slog.e(LOG_TAG, "Cannot set permitted input methods, because the list of " + "permitted input methods excludes an already-enabled input method."); return false; } } } synchronized (getLockObject()) { ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller); final ActiveAdmin admin = getParentOfAdminIfRequired( getProfileOwnerOrDeviceOwnerLocked(caller), calledOnParentInstance); admin.permittedInputMethods = packageList; saveSettingsLocked(caller.getUserId()); } final String[] packageArray = packageList != null ? ((List<String>) packageList).toArray(new String[0]) : null; DevicePolicyEventLogger .createEvent(DevicePolicyEnums.SET_PERMITTED_INPUT_METHODS) .setAdmin(who) .setStrings(packageArray) .setStrings(getStringArrayForLogging(packageList, calledOnParentInstance)) .write(); return true; } private String[] getStringArrayForLogging(List list, boolean calledOnParentInstance) { List<String> stringList = new ArrayList<String>(); stringList.add(calledOnParentInstance ? CALLED_FROM_PARENT : NOT_CALLED_FROM_PARENT); if (list == null) { stringList.add(NULL_STRING_ARRAY); } else { stringList.addAll((List<String>) list); } return stringList.toArray(new String[0]); } @Override public List getPermittedInputMethods(ComponentName who) { public List getPermittedInputMethods(ComponentName who, boolean calledOnParentInstance) { if (!mHasFeature) { return null; } Objects.requireNonNull(who, "ComponentName is null"); final CallerIdentity caller = getCallerIdentity(who); if (calledOnParentInstance) { Preconditions.checkCallAuthorization(isProfileOwnerOfOrganizationOwnedDevice(caller)); } else { Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller)); } synchronized (getLockObject()) { ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller); final ActiveAdmin admin = getParentOfAdminIfRequired( getProfileOwnerOrDeviceOwnerLocked(caller), calledOnParentInstance); return admin.permittedInputMethods; } } Loading @@ -9642,9 +9671,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { synchronized (getLockObject()) { List<String> result = null; // Only device or profile owners can have permitted lists set. DevicePolicyData policy = getUserDataUnchecked(caller.getUserId()); for (int i = 0; i < policy.mAdminList.size(); i++) { ActiveAdmin admin = policy.mAdminList.get(i); List<ActiveAdmin> admins = getActiveAdminsForAffectedUserLocked(caller.getUserId()); for (ActiveAdmin admin: admins) { List<String> fromAdmin = admin.permittedInputMethods; if (fromAdmin != null) { if (result == null) { Loading Loading @@ -9675,7 +9703,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public boolean isInputMethodPermittedByAdmin(ComponentName who, String packageName, int userHandle) { int userHandle, boolean calledOnParentInstance) { if (!mHasFeature) { return true; } Loading @@ -9684,7 +9712,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { enforceSystemCaller("query if an input method is disabled by admin"); synchronized (getLockObject()) { ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle); ActiveAdmin admin = getParentOfAdminIfRequired( getActiveAdminUncheckedLocked(who, userHandle), calledOnParentInstance); if (admin == null) { return false; } Loading services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +26 −0 Original line number Diff line number Diff line Loading @@ -2333,6 +2333,32 @@ public class DevicePolicyManagerTest extends DpmTestBase { assertThat(actualAccounts).containsExactlyElementsIn(expectedAccounts); } @Test public void testSetPermittedInputMethodsWithPOOfOrganizationOwnedDevice() throws Exception { String packageName = "com.google.pkg.one"; setupProfileOwner(); configureProfileOwnerOfOrgOwnedDevice(admin1, CALLER_USER_HANDLE); // Allow all input methods parentDpm.setPermittedInputMethods(admin1, null); assertThat(parentDpm.getPermittedInputMethods(admin1)).isNull(); // Allow only system input methods parentDpm.setPermittedInputMethods(admin1, new ArrayList<>()); assertThat(parentDpm.getPermittedInputMethods(admin1)).isEmpty(); // Don't allow specific third party input methods final List<String> inputMethods = Collections.singletonList(packageName); assertExpectException(IllegalArgumentException.class, /* messageRegex= */ "Permitted " + "input methods must allow all input methods or only system input methods " + "when called on the parent instance of an organization-owned device", () -> parentDpm.setPermittedInputMethods(admin1, inputMethods)); } @Test public void testSetKeyguardDisabledFeaturesWithDO() throws Exception { mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID; Loading Loading
core/java/android/app/admin/DevicePolicyManager.java +39 −7 Original line number Diff line number Diff line Loading @@ -8675,6 +8675,19 @@ public class DevicePolicyManager { * Called by a profile or device owner to set the permitted input methods services for this * user. By default, the user can use any input method. * <p> * This method can be called on the {@link DevicePolicyManager} instance, * returned by {@link #getParentProfileInstance(ComponentName)}, where the caller must be * a profile owner of an organization-owned device. * <p> * If called on the parent instance: * <ul> * <li>The permitted input methods will be applied on the personal profile</li> * <li>Can only permit all input methods (calling this method with a {@code null} package * list) or only permit system input methods (calling this method with an empty package * list). This is to prevent the caller from learning which packages are installed on * the personal side</li> * </ul> * <p> * When zero or more packages have been added, input method that are not in the list and not * part of the system can not be enabled by the user. This method will fail if it is called for * a admin that is not for the foreground user or a profile of the foreground user. Any Loading @@ -8689,14 +8702,18 @@ public class DevicePolicyManager { * @param packageNames List of input method package names. * @return {@code true} if the operation succeeded, or {@code false} if the list didn't * contain every enabled non-system input method service. * @throws SecurityException if {@code admin} is not a device or profile owner. * @throws SecurityException if {@code admin} is not a device, profile owner or if called on * the parent profile and the {@code admin} is not a profile owner * of an organization-owned managed profile. * @throws IllegalArgumentException if called on the parent profile, the {@code admin} is a * profile owner of an organization-owned managed profile and the * list of permitted input method package names is not null or empty. */ public boolean setPermittedInputMethods( @NonNull ComponentName admin, List<String> packageNames) { throwIfParentInstance("setPermittedInputMethods"); if (mService != null) { try { return mService.setPermittedInputMethods(admin, packageNames); return mService.setPermittedInputMethods(admin, packageNames, mParentInstance); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading @@ -8708,18 +8725,25 @@ public class DevicePolicyManager { /** * Returns the list of permitted input methods set by this device or profile owner. * <p> * This method can be called on the {@link DevicePolicyManager} instance, * returned by {@link #getParentProfileInstance(ComponentName)}, where the caller must be * a profile owner of an organization-owned managed profile. If called on the parent instance, * then the returned list of permitted input methods are those which are applied on the * personal profile. * <p> * An empty list means no input methods except system input methods are allowed. Null means all * input methods are allowed. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @return List of input method package names. * @throws SecurityException if {@code admin} is not a device or profile owner. * @throws SecurityException if {@code admin} is not a device, profile owner or if called on * the parent profile and the {@code admin} is not a profile owner * of an organization-owned managed profile. */ public @Nullable List<String> getPermittedInputMethods(@NonNull ComponentName admin) { throwIfParentInstance("getPermittedInputMethods"); if (mService != null) { try { return mService.getPermittedInputMethods(admin); return mService.getPermittedInputMethods(admin, mParentInstance); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading @@ -8729,6 +8753,11 @@ public class DevicePolicyManager { /** * Called by the system to check if a specific input method is disabled by admin. * <p> * This method can be called on the {@link DevicePolicyManager} instance, * returned by {@link #getParentProfileInstance(ComponentName)}. If called on the parent * instance, this method will check whether the given input method is permitted on * the personal profile. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param packageName Input method package name that needs to be checked. Loading @@ -8741,7 +8770,8 @@ public class DevicePolicyManager { @NonNull String packageName, int userHandle) { if (mService != null) { try { return mService.isInputMethodPermittedByAdmin(admin, packageName, userHandle); return mService.isInputMethodPermittedByAdmin(admin, packageName, userHandle, mParentInstance); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading Loading @@ -10828,6 +10858,8 @@ public class DevicePolicyManager { * <li>{@link #setCameraDisabled}</li> * <li>{@link #getCameraDisabled}</li> * <li>{@link #setAccountManagementDisabled(ComponentName, String, boolean)}</li> * <li>{@link #setPermittedInputMethods}</li> * <li>{@link #getPermittedInputMethods}</li> * </ul> * * <p>The following methods can be called by the profile owner of a managed profile Loading
core/java/android/app/admin/IDevicePolicyManager.aidl +3 −3 Original line number Diff line number Diff line Loading @@ -232,10 +232,10 @@ interface IDevicePolicyManager { List getPermittedAccessibilityServicesForUser(int userId); boolean isAccessibilityServicePermittedByAdmin(in ComponentName admin, String packageName, int userId); boolean setPermittedInputMethods(in ComponentName admin,in List packageList); List getPermittedInputMethods(in ComponentName admin); boolean setPermittedInputMethods(in ComponentName admin,in List packageList, boolean parent); List getPermittedInputMethods(in ComponentName admin, boolean parent); List getPermittedInputMethodsForCurrentUser(); boolean isInputMethodPermittedByAdmin(in ComponentName admin, String packageName, int userId); boolean isInputMethodPermittedByAdmin(in ComponentName admin, String packageName, int userId, boolean parent); boolean setPermittedCrossProfileNotificationListeners(in ComponentName admin, in List<String> packageList); List<String> getPermittedCrossProfileNotificationListeners(in ComponentName admin); Loading
packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java +17 −8 Original line number Diff line number Diff line Loading @@ -267,19 +267,28 @@ public class RestrictedLockUtilsInternal extends RestrictedLockUtils { permitted = dpm.isInputMethodPermittedByAdmin(admin.component, packageName, userId); } boolean permittedByParentAdmin = true; EnforcedAdmin profileAdmin = null; int managedProfileId = getManagedProfileId(context, userId); EnforcedAdmin profileAdmin = getProfileOrDeviceOwner(context, getUserHandleOf(managedProfileId)); boolean permittedByProfileAdmin = true; if (profileAdmin != null) { permittedByProfileAdmin = dpm.isInputMethodPermittedByAdmin(profileAdmin.component, packageName, managedProfileId); if (managedProfileId != UserHandle.USER_NULL) { profileAdmin = getProfileOrDeviceOwner(context, getUserHandleOf(managedProfileId)); // If the device is an organization-owned device with a managed profile, the // managedProfileId will be used instead of the affected userId. This is because // isInputMethodPermittedByAdmin is called on the parent DPM instance, which will // return results affecting the personal profile. if (profileAdmin != null && dpm.isOrganizationOwnedDeviceWithManagedProfile()) { DevicePolicyManager parentDpm = sProxy.getParentProfileInstance(dpm, UserManager.get(context).getUserInfo(managedProfileId)); permittedByParentAdmin = parentDpm.isInputMethodPermittedByAdmin( profileAdmin.component, packageName, managedProfileId); } if (!permitted && !permittedByProfileAdmin) { } if (!permitted && !permittedByParentAdmin) { return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN; } else if (!permitted) { return admin; } else if (!permittedByProfileAdmin) { } else if (!permittedByParentAdmin) { return profileAdmin; } return null; Loading
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +48 −19 Original line number Diff line number Diff line Loading @@ -378,6 +378,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { private static final String CREDENTIAL_MANAGEMENT_APP = "credentialManagementApp"; private static final String NOT_CREDENTIAL_MANAGEMENT_APP = "notCredentialManagementApp"; private static final String NULL_STRING_ARRAY = "nullStringArray"; // Comprehensive list of delegations. private static final String DELEGATIONS[] = { DELEGATION_CERT_INSTALL, Loading Loading @@ -9577,59 +9579,86 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } @Override public boolean setPermittedInputMethods(ComponentName who, List packageList) { public boolean setPermittedInputMethods(ComponentName who, List packageList, boolean calledOnParentInstance) { if (!mHasFeature) { return false; } Objects.requireNonNull(who, "ComponentName is null"); final CallerIdentity caller = getCallerIdentity(who); final int userId = getProfileParentUserIfRequested( caller.getUserId(), calledOnParentInstance); if (calledOnParentInstance) { Preconditions.checkCallAuthorization(isProfileOwnerOfOrganizationOwnedDevice(caller)); Preconditions.checkArgument(packageList == null || packageList.isEmpty(), "Permitted input methods must allow all input methods or only " + "system input methods when called on the parent instance of an " + "organization-owned device"); } else { Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller)); } if (packageList != null) { List<InputMethodInfo> enabledImes = InputMethodManagerInternal.get() .getEnabledInputMethodListAsUser(caller.getUserId()); List<InputMethodInfo> enabledImes = mInjector.binderWithCleanCallingIdentity(() -> InputMethodManagerInternal.get().getEnabledInputMethodListAsUser(userId)); if (enabledImes != null) { List<String> enabledPackages = new ArrayList<String>(); for (InputMethodInfo ime : enabledImes) { enabledPackages.add(ime.getPackageName()); } if (!checkPackagesInPermittedListOrSystem(enabledPackages, packageList, caller.getUserId())) { Slog.e(LOG_TAG, "Cannot set permitted input methods, " + "because it contains already enabled input method."); userId)) { Slog.e(LOG_TAG, "Cannot set permitted input methods, because the list of " + "permitted input methods excludes an already-enabled input method."); return false; } } } synchronized (getLockObject()) { ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller); final ActiveAdmin admin = getParentOfAdminIfRequired( getProfileOwnerOrDeviceOwnerLocked(caller), calledOnParentInstance); admin.permittedInputMethods = packageList; saveSettingsLocked(caller.getUserId()); } final String[] packageArray = packageList != null ? ((List<String>) packageList).toArray(new String[0]) : null; DevicePolicyEventLogger .createEvent(DevicePolicyEnums.SET_PERMITTED_INPUT_METHODS) .setAdmin(who) .setStrings(packageArray) .setStrings(getStringArrayForLogging(packageList, calledOnParentInstance)) .write(); return true; } private String[] getStringArrayForLogging(List list, boolean calledOnParentInstance) { List<String> stringList = new ArrayList<String>(); stringList.add(calledOnParentInstance ? CALLED_FROM_PARENT : NOT_CALLED_FROM_PARENT); if (list == null) { stringList.add(NULL_STRING_ARRAY); } else { stringList.addAll((List<String>) list); } return stringList.toArray(new String[0]); } @Override public List getPermittedInputMethods(ComponentName who) { public List getPermittedInputMethods(ComponentName who, boolean calledOnParentInstance) { if (!mHasFeature) { return null; } Objects.requireNonNull(who, "ComponentName is null"); final CallerIdentity caller = getCallerIdentity(who); if (calledOnParentInstance) { Preconditions.checkCallAuthorization(isProfileOwnerOfOrganizationOwnedDevice(caller)); } else { Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller)); } synchronized (getLockObject()) { ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller); final ActiveAdmin admin = getParentOfAdminIfRequired( getProfileOwnerOrDeviceOwnerLocked(caller), calledOnParentInstance); return admin.permittedInputMethods; } } Loading @@ -9642,9 +9671,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { synchronized (getLockObject()) { List<String> result = null; // Only device or profile owners can have permitted lists set. DevicePolicyData policy = getUserDataUnchecked(caller.getUserId()); for (int i = 0; i < policy.mAdminList.size(); i++) { ActiveAdmin admin = policy.mAdminList.get(i); List<ActiveAdmin> admins = getActiveAdminsForAffectedUserLocked(caller.getUserId()); for (ActiveAdmin admin: admins) { List<String> fromAdmin = admin.permittedInputMethods; if (fromAdmin != null) { if (result == null) { Loading Loading @@ -9675,7 +9703,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public boolean isInputMethodPermittedByAdmin(ComponentName who, String packageName, int userHandle) { int userHandle, boolean calledOnParentInstance) { if (!mHasFeature) { return true; } Loading @@ -9684,7 +9712,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { enforceSystemCaller("query if an input method is disabled by admin"); synchronized (getLockObject()) { ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle); ActiveAdmin admin = getParentOfAdminIfRequired( getActiveAdminUncheckedLocked(who, userHandle), calledOnParentInstance); if (admin == null) { return false; } Loading
services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +26 −0 Original line number Diff line number Diff line Loading @@ -2333,6 +2333,32 @@ public class DevicePolicyManagerTest extends DpmTestBase { assertThat(actualAccounts).containsExactlyElementsIn(expectedAccounts); } @Test public void testSetPermittedInputMethodsWithPOOfOrganizationOwnedDevice() throws Exception { String packageName = "com.google.pkg.one"; setupProfileOwner(); configureProfileOwnerOfOrgOwnedDevice(admin1, CALLER_USER_HANDLE); // Allow all input methods parentDpm.setPermittedInputMethods(admin1, null); assertThat(parentDpm.getPermittedInputMethods(admin1)).isNull(); // Allow only system input methods parentDpm.setPermittedInputMethods(admin1, new ArrayList<>()); assertThat(parentDpm.getPermittedInputMethods(admin1)).isEmpty(); // Don't allow specific third party input methods final List<String> inputMethods = Collections.singletonList(packageName); assertExpectException(IllegalArgumentException.class, /* messageRegex= */ "Permitted " + "input methods must allow all input methods or only system input methods " + "when called on the parent instance of an organization-owned device", () -> parentDpm.setPermittedInputMethods(admin1, inputMethods)); } @Test public void testSetKeyguardDisabledFeaturesWithDO() throws Exception { mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID; Loading