From eb5706183f62b9230fb1ae9eb22254a062e7869c Mon Sep 17 00:00:00 2001 From: Tarandeep Singh Date: Mon, 29 Jan 2018 16:20:32 -0800 Subject: [PATCH] Fix checks for showing InputMethod picker When user tries to switch IME, IMMS.showInputMethodPickerFromClient() is called. The call fails to validate in newly introduced canShowInputMethodPickerLocked() in I4f0fc21268200c64d12b31ca54416acfbf62f37b because mCurClient.client != client. This is happening since the new client never started input ever since we prevented calls to startInputUncheckedLocked in Ibf9dab3d9c138b5f04e053d41ee4fd248c78e4da. The fix is to update mCurFocusedWindowClient.client instead of mCurclient.client in canShowInputMethodPickerLocked() Fixes: 72557082 Test: manually using the steps in bug Test: atest InputMethodManagerTest Change-Id: I4e21625c32a0ca1abc740229efb3c7fcd97141cc --- api/test-current.txt | 8 +++++++ .../view/inputmethod/InputMethodManager.java | 21 +++++++++++++++++++ .../internal/view/IInputMethodManager.aidl | 1 + .../server/InputMethodManagerService.java | 16 +++++++++++--- 4 files changed, 43 insertions(+), 3 deletions(-) diff --git a/api/test-current.txt b/api/test-current.txt index 4e8f904b96b7a..5ec0748beae30 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -1035,6 +1035,14 @@ package android.view.autofill { } +package android.view.inputmethod { + + public final class InputMethodManager { + method public boolean isInputMethodPickerShown(); + } + +} + package android.widget { public abstract class AbsListView extends android.widget.AdapterView implements android.widget.Filter.FilterListener android.text.TextWatcher android.view.ViewTreeObserver.OnGlobalLayoutListener android.view.ViewTreeObserver.OnTouchModeChangeListener { diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index 7db5c32072967..33c9f7a2671e8 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -22,6 +22,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemService; +import android.annotation.TestApi; import android.content.Context; import android.graphics.Rect; import android.inputmethodservice.InputMethodService; @@ -2136,6 +2137,26 @@ public final class InputMethodManager { } } + /** + * A test API for CTS to make sure that {@link #showInputMethodPicker()} works as expected. + * + *

When customizing the implementation of {@link #showInputMethodPicker()} API, make sure + * that this test API returns when and only while and only while + * {@link #showInputMethodPicker()} is showing UI. Otherwise your OS implementation may not + * pass CTS.

+ * + * @return {@code true} while and only while {@link #showInputMethodPicker()} is showing UI. + * @hide + */ + @TestApi + public boolean isInputMethodPickerShown() { + try { + return mService.isInputMethodPickerShownForTest(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * Show the settings for enabling subtypes of the specified input method. * @param imiId An input method, whose subtypes settings will be shown. If imiId is null, diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl index 5e0a986b432b4..02822869f4212 100644 --- a/core/java/com/android/internal/view/IInputMethodManager.aidl +++ b/core/java/com/android/internal/view/IInputMethodManager.aidl @@ -68,6 +68,7 @@ interface IInputMethodManager { void showInputMethodPickerFromClient(in IInputMethodClient client, int auxiliarySubtypeMode); void showInputMethodAndSubtypeEnablerFromClient(in IInputMethodClient client, String topId); + boolean isInputMethodPickerShownForTest(); void setInputMethod(in IBinder token, String id); void setInputMethodAndSubtype(in IBinder token, String id, in InputMethodSubtype subtype); void hideMySoftInput(in IBinder token, int flags); diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java index fc91d0d7abf10..2f425859fec4c 100644 --- a/services/core/java/com/android/server/InputMethodManagerService.java +++ b/services/core/java/com/android/server/InputMethodManagerService.java @@ -59,6 +59,7 @@ import android.annotation.MainThread; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; +import android.annotation.TestApi; import android.annotation.UserIdInt; import android.app.ActivityManager; import android.app.ActivityManagerInternal; @@ -468,7 +469,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub int mCurFocusedWindowSoftInputMode; /** - * The client by which {@link #mCurFocusedWindow} was reported. Used only for debugging. + * The client by which {@link #mCurFocusedWindow} was reported. */ ClientState mCurFocusedWindowClient; @@ -2989,8 +2990,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub final int uid = Binder.getCallingUid(); if (UserHandle.getAppId(uid) == Process.SYSTEM_UID) { return true; - } else if (mCurClient != null && client != null - && mCurClient.client.asBinder() == client.asBinder()) { + } else if (mCurFocusedWindowClient != null && client != null + && mCurFocusedWindowClient.client.asBinder() == client.asBinder()) { return true; } else if (mCurIntent != null && InputMethodUtils.checkIfPackageBelongsToUid( mAppOpsManager, @@ -3026,6 +3027,15 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } + public boolean isInputMethodPickerShownForTest() { + synchronized(mMethodMap) { + if (mSwitchingDialog == null) { + return false; + } + return mSwitchingDialog.isShowing(); + } + } + @Override public void setInputMethod(IBinder token, String id) { if (!calledFromValidUser()) {