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