From 1fb13c59dea3c29aaed5d3e2155ce4acba7b7f7c Mon Sep 17 00:00:00 2001 From: Yohei Yukawa Date: Tue, 5 Feb 2019 07:55:28 -0800 Subject: Query right user's enabled IMEs in KeyguardPasswordView This CL fixes a regression introduced by my previous CL [1], which enabled InputMethodManager#getEnabledInputMethodList() to return the result based on the caller's user ID, not based on the current IME user, even when it gets called from background users. Since Keyguard always runs as user 0 currently, it is now Keyguard's responsibility for querying enabled IMEs with an explicit user ID. To do so this CL adds a @hide API IMM#getEnabledInputMethodListAsUser() and lets KeyguardPasswordView use it. [1]: I192a0f5a1375170d17a4c08af94f23966dbaea8b 7f8ee4b9ddd31ad36a12c5278b27990dc76011cc Bug: 122164939 Fix: 123904896 Test: Manually verified as follows. 1. Build aosp_taimen-userdebug and flash it. 2. make -j SoftKeyboard 3. adb install -r $OUT/system/app/SoftKeyboard/SoftKeyboard.apk 4. adb shell ime enable com.example.android.softkeyboard/.SoftKeyboard 5. adb shell pm create-user test_user 6. adb shell am switch-user 10 7. adb shell locksettings set-password aaaa 8. adb shell wm dismiss-keyguard 9. Make sure that the IME switcher icon is not shown at the right end of the password field. Change-Id: I6e7d7353c2b5b1da5d460ae005fb2585f85fb1c4 --- .../view/inputmethod/InputMethodManager.java | 24 +++++++++++++++++++++- .../android/internal/view/IInputMethodManager.aidl | 2 +- .../com/android/keyguard/KeyguardPasswordView.java | 3 ++- .../inputmethod/InputMethodManagerService.java | 8 +++++--- .../MultiClientInputMethodManagerService.java | 10 +++++++-- 5 files changed, 39 insertions(+), 8 deletions(-) diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index 8c770adcf2b5..18f757c07369 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -16,6 +16,7 @@ package android.view.inputmethod; +import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL; import static android.Manifest.permission.WRITE_SECURE_SETTINGS; import android.annotation.DrawableRes; @@ -26,6 +27,7 @@ import android.annotation.RequiresPermission; import android.annotation.SystemService; import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; +import android.annotation.UserIdInt; import android.app.ActivityThread; import android.content.ComponentName; import android.content.ContentResolver; @@ -46,6 +48,7 @@ import android.os.ResultReceiver; import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; import android.os.Trace; +import android.os.UserHandle; import android.provider.Settings; import android.text.style.SuggestionSpan; import android.util.Log; @@ -978,7 +981,26 @@ public final class InputMethodManager { */ public List getEnabledInputMethodList() { try { - return mService.getEnabledInputMethodList(); + // We intentionally do not use UserHandle.getCallingUserId() here because for system + // services InputMethodManagerInternal.getEnabledInputMethodListAsUser() should be used + // instead. + return mService.getEnabledInputMethodList(UserHandle.myUserId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Returns the list of enabled input methods for the specified user. + * + * @param userId user ID to query + * @return {@link List} of {@link InputMethodInfo}. + * @hide + */ + @RequiresPermission(INTERACT_ACROSS_USERS_FULL) + public List getEnabledInputMethodListAsUser(@UserIdInt int userId) { + try { + return mService.getEnabledInputMethodList(userId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl index 0752efe562a9..98e854cc40a2 100644 --- a/core/java/com/android/internal/view/IInputMethodManager.aidl +++ b/core/java/com/android/internal/view/IInputMethodManager.aidl @@ -36,7 +36,7 @@ interface IInputMethodManager { // TODO: Use ParceledListSlice instead List getInputMethodList(); // TODO: Use ParceledListSlice instead - List getEnabledInputMethodList(); + List getEnabledInputMethodList(int userId); List getEnabledInputMethodSubtypeList(in String imiId, boolean allowsImplicitlySelectedSubtypes); InputMethodSubtype getLastInputMethodSubtype(); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java index 64c5b1754fa8..261f391839b3 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java @@ -264,7 +264,8 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView */ private boolean hasMultipleEnabledIMEsOrSubtypes(InputMethodManager imm, final boolean shouldIncludeAuxiliarySubtypes) { - final List enabledImis = imm.getEnabledInputMethodList(); + final List enabledImis = + imm.getEnabledInputMethodListAsUser(KeyguardUpdateMonitor.getCurrentUser()); // Number of the filtered IMEs int filteredImisCount = 0; diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index 9d9721d5d402..f0dce78722a2 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -1645,10 +1645,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } @Override - public List getEnabledInputMethodList() { - final int callingUserId = UserHandle.getCallingUserId(); + public List getEnabledInputMethodList(@UserIdInt int userId) { + if (UserHandle.getCallingUserId() != userId) { + mContext.enforceCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL, null); + } synchronized (mMethodMap) { - final int[] resolvedUserIds = InputMethodUtils.resolveUserId(callingUserId, + final int[] resolvedUserIds = InputMethodUtils.resolveUserId(userId, mSettings.getCurrentUserId(), null); if (resolvedUserIds.length != 1) { return Collections.emptyList(); diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java index 3222143fc89f..109024d0d2f7 100644 --- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java @@ -16,6 +16,7 @@ package com.android.server.inputmethod; +import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static java.lang.annotation.RetentionPolicy.SOURCE; @@ -1195,6 +1196,7 @@ public final class MultiClientInputMethodManagerService { * Takes care of IPCs exposed to the IME client. */ private static final class ApiCallbacks extends IInputMethodManager.Stub { + private final Context mContext; private final UserDataMap mUserDataMap; private final UserToInputMethodInfoMap mInputMethodInfoMap; private final AppOpsManager mAppOpsManager; @@ -1202,6 +1204,7 @@ public final class MultiClientInputMethodManagerService { ApiCallbacks(Context context, UserDataMap userDataMap, UserToInputMethodInfoMap inputMethodInfoMap) { + mContext = context; mUserDataMap = userDataMap; mInputMethodInfoMap = inputMethodInfoMap; mAppOpsManager = context.getSystemService(AppOpsManager.class); @@ -1239,8 +1242,11 @@ public final class MultiClientInputMethodManagerService { @BinderThread @Override - public List getEnabledInputMethodList() { - return mInputMethodInfoMap.getAsList(UserHandle.getUserId(Binder.getCallingUid())); + public List getEnabledInputMethodList(@UserIdInt int userId) { + if (UserHandle.getCallingUserId() != userId) { + mContext.enforceCallingPermission(INTERACT_ACROSS_USERS_FULL, null); + } + return mInputMethodInfoMap.getAsList(userId); } @BinderThread -- cgit v1.2.3-59-g8ed1b