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);
}