From 567dafb881493818346e65ba6dbd971a499dab1a Mon Sep 17 00:00:00 2001 From: Rhed Jao Date: Tue, 1 Nov 2022 18:04:06 +0800 Subject: [PATCH] Enforce package visibility rules on switch input method apis Bug: 227207653 Test: atest InputMethodSubtypeTest Test: atest InputMethodServiceLifecycleTest Change-Id: Ib5ba67f708b8ebe12b5120c126022eb84ce720cb --- .../InputMethodService.java | 4 +++ .../view/inputmethod/InputMethodManager.java | 4 +++ .../InputMethodManagerService.java | 25 ++++++++++++++++--- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 39d362b17d977..78a9fe5b92a7d 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -2272,6 +2272,8 @@ public class InputMethodService extends AbstractInputMethodService { * current input field. * * @param id Unique identifier of the new input method to start. + * @throws IllegalArgumentException if the input method is unknown or filtered + * by the rules of package visibility. */ public void switchInputMethod(String id) { mPrivOps.setInputMethod(id); @@ -2284,6 +2286,8 @@ public class InputMethodService extends AbstractInputMethodService { * * @param id Unique identifier of the new input method to start. * @param subtype The new subtype of the new input method to be switched to. + * @throws IllegalArgumentException if the input method is unknown or filtered + * by the rules of package visibility. */ public final void switchInputMethod(String id, InputMethodSubtype subtype) { mPrivOps.setInputMethodAndSubtype(id, subtype); diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index 1697bf8bcf7be..23eac36c29997 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -3096,6 +3096,8 @@ public final class InputMethodManager { * when it was started, which allows it to perform this operation on * itself. * @param id The unique identifier for the new input method to be switched to. + * @throws IllegalArgumentException if the input method is unknown or filtered by the rules of + * package visibility. * @deprecated Use {@link InputMethodService#switchInputMethod(String)} * instead. This method was intended for IME developers who should be accessing APIs through * the service. APIs in this class are intended for app developers interacting with the IME. @@ -3166,6 +3168,8 @@ public final class InputMethodManager { * itself. * @param id The unique identifier for the new input method to be switched to. * @param subtype The new subtype of the new input method to be switched to. + * @throws IllegalArgumentException if the input method is unknown or filtered by the rules of + * package visibility. * @deprecated Use * {@link InputMethodService#switchInputMethod(String, InputMethodSubtype)} * instead. This method was intended for IME developers who should be accessing APIs through diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index 0eaa5e452a582..ad2fcf888956d 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -3204,7 +3204,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub void setInputMethodLocked(String id, int subtypeId) { InputMethodInfo info = mMethodMap.get(id); if (info == null) { - throw new IllegalArgumentException("Unknown id: " + id); + throw getExceptionForUnknownImeId(id); } // See if we need to notify a subtype change within the same IME. @@ -3943,12 +3943,25 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } } + @NonNull + private static IllegalArgumentException getExceptionForUnknownImeId( + @Nullable String imeId) { + return new IllegalArgumentException("Unknown id: " + imeId); + } + @BinderThread private void setInputMethod(@NonNull IBinder token, String id) { + final int callingUid = Binder.getCallingUid(); + final int userId = UserHandle.getUserId(callingUid); synchronized (ImfLock.class) { if (!calledWithValidTokenLocked(token)) { return; } + final InputMethodInfo imi = mMethodMap.get(id); + if (imi == null || !canCallerAccessInputMethod( + imi.getPackageName(), callingUid, userId, mSettings)) { + throw getExceptionForUnknownImeId(id); + } setInputMethodWithSubtypeIdLocked(token, id, NOT_A_SUBTYPE_ID); } } @@ -3956,14 +3969,20 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub @BinderThread private void setInputMethodAndSubtype(@NonNull IBinder token, String id, InputMethodSubtype subtype) { + final int callingUid = Binder.getCallingUid(); + final int userId = UserHandle.getUserId(callingUid); synchronized (ImfLock.class) { if (!calledWithValidTokenLocked(token)) { return; } + final InputMethodInfo imi = mMethodMap.get(id); + if (imi == null || !canCallerAccessInputMethod( + imi.getPackageName(), callingUid, userId, mSettings)) { + throw getExceptionForUnknownImeId(id); + } if (subtype != null) { setInputMethodWithSubtypeIdLocked(token, id, - SubtypeUtils.getSubtypeIdFromHashCode(mMethodMap.get(id), - subtype.hashCode())); + SubtypeUtils.getSubtypeIdFromHashCode(imi, subtype.hashCode())); } else { setInputMethod(token, id); }