diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index cea46f3363c4d..d902486faceda 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -2268,6 +2268,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); @@ -2280,6 +2282,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 d08816b7dafc9..74afced453fae 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -3115,6 +3115,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. @@ -3185,6 +3187,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 fcdb1f58f4581..4d1c5aede33df 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. @@ -3946,12 +3946,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); } } @@ -3959,14 +3972,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); }