diff options
8 files changed, 362 insertions, 35 deletions
diff --git a/core/java/com/android/internal/inputmethod/InputMethodDebug.java b/core/java/com/android/internal/inputmethod/InputMethodDebug.java index 382a254b67a6..3876976575ae 100644 --- a/core/java/com/android/internal/inputmethod/InputMethodDebug.java +++ b/core/java/com/android/internal/inputmethod/InputMethodDebug.java @@ -16,6 +16,8 @@ package com.android.internal.inputmethod; +import android.annotation.AnyThread; +import android.annotation.NonNull; import android.view.WindowManager; import android.view.WindowManager.LayoutParams.SoftInputModeFlags; @@ -25,6 +27,7 @@ import java.util.StringJoiner; * Provides useful methods for debugging. */ public final class InputMethodDebug { + /** * Not intended to be instantiated. */ @@ -174,4 +177,71 @@ public final class InputMethodDebug { return joiner.setEmptyValue("(none)").toString(); } + + + /** + * Converts {@link SoftInputShowHideReason} to {@link String} for history dump. + */ + public static String softInputDisplayReasonToString(@SoftInputShowHideReason int reason) { + switch (reason) { + case SoftInputShowHideReason.SHOW_SOFT_INPUT: + return "SHOW_SOFT_INPUT"; + case SoftInputShowHideReason.ATTACH_NEW_INPUT: + return "ATTACH_NEW_INPUT"; + case SoftInputShowHideReason.SHOW_MY_SOFT_INPUT: + return "SHOW_MY_SOFT_INPUT"; + case SoftInputShowHideReason.HIDE_SOFT_INPUT: + return "HIDE_SOFT_INPUT"; + case SoftInputShowHideReason.HIDE_MY_SOFT_INPUT: + return "HIDE_MY_SOFT_INPUT"; + case SoftInputShowHideReason.SHOW_AUTO_EDITOR_FORWARD_NAV: + return "SHOW_AUTO_EDITOR_FORWARD_NAV"; + case SoftInputShowHideReason.SHOW_STATE_VISIBLE_FORWARD_NAV: + return "SHOW_STATE_VISIBLE_FORWARD_NAV"; + case SoftInputShowHideReason.SHOW_STATE_ALWAYS_VISIBLE: + return "SHOW_STATE_ALWAYS_VISIBLE"; + case SoftInputShowHideReason.SHOW_SETTINGS_ON_CHANGE: + return "SHOW_SETTINGS_ON_CHANGE"; + case SoftInputShowHideReason.HIDE_SWITCH_USER: + return "HIDE_SWITCH_USER"; + case SoftInputShowHideReason.HIDE_INVALID_USER: + return "HIDE_INVALID_USER"; + case SoftInputShowHideReason.HIDE_UNSPECIFIED_WINDOW: + return "HIDE_UNSPECIFIED_WINDOW"; + case SoftInputShowHideReason.HIDE_STATE_HIDDEN_FORWARD_NAV: + return "HIDE_STATE_HIDDEN_FORWARD_NAV"; + case SoftInputShowHideReason.HIDE_ALWAYS_HIDDEN_STATE: + return "HIDE_ALWAYS_HIDDEN_STATE"; + case SoftInputShowHideReason.HIDE_RESET_SHELL_COMMAND: + return "HIDE_RESET_SHELL_COMMAND"; + case SoftInputShowHideReason.HIDE_SETTINGS_ON_CHANGE: + return "HIDE_SETTINGS_ON_CHANGE"; + case SoftInputShowHideReason.HIDE_POWER_BUTTON_GO_HOME: + return "HIDE_POWER_BUTTON_GO_HOME"; + case SoftInputShowHideReason.HIDE_DOCKED_STACK_ATTACHED: + return "HIDE_DOCKED_STACK_ATTACHED"; + case SoftInputShowHideReason.HIDE_RECENTS_ANIMATION: + return "HIDE_RECENTS_ANIMATION"; + default: + return "Unknown=" + reason; + } + } + + /** + * Return a fixed size string of the object. + * TODO(b/141738570): Take & return with StringBuilder to make more memory efficient. + */ + @NonNull + @AnyThread + public static String objToString(Object obj) { + if (obj == null) { + return "null"; + } + StringBuilder sb = new StringBuilder(64); + sb.setLength(0); + sb.append(obj.getClass().getName()); + sb.append("@"); + sb.append(Integer.toHexString(obj.hashCode())); + return sb.toString(); + } } diff --git a/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java b/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java new file mode 100644 index 000000000000..79397b81ace7 --- /dev/null +++ b/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.inputmethod; + +import static java.lang.annotation.RetentionPolicy.SOURCE; + +import android.annotation.IntDef; +import android.view.WindowManager.LayoutParams; + +import java.lang.annotation.Retention; + +/** + * Describes the reason why Soft input window visible / hidden. + */ +@Retention(SOURCE) +@IntDef(value = { + SoftInputShowHideReason.SHOW_SOFT_INPUT, + SoftInputShowHideReason.ATTACH_NEW_INPUT, + SoftInputShowHideReason.SHOW_MY_SOFT_INPUT, + SoftInputShowHideReason.HIDE_SOFT_INPUT, + SoftInputShowHideReason.HIDE_MY_SOFT_INPUT, + SoftInputShowHideReason.SHOW_AUTO_EDITOR_FORWARD_NAV, + SoftInputShowHideReason.SHOW_STATE_VISIBLE_FORWARD_NAV, + SoftInputShowHideReason.SHOW_STATE_ALWAYS_VISIBLE, + SoftInputShowHideReason.SHOW_SETTINGS_ON_CHANGE, + SoftInputShowHideReason.HIDE_SWITCH_USER, + SoftInputShowHideReason.HIDE_INVALID_USER, + SoftInputShowHideReason.HIDE_UNSPECIFIED_WINDOW, + SoftInputShowHideReason.HIDE_STATE_HIDDEN_FORWARD_NAV, + SoftInputShowHideReason.HIDE_ALWAYS_HIDDEN_STATE, + SoftInputShowHideReason.HIDE_RESET_SHELL_COMMAND, + SoftInputShowHideReason.HIDE_SETTINGS_ON_CHANGE, + SoftInputShowHideReason.HIDE_POWER_BUTTON_GO_HOME, + SoftInputShowHideReason.HIDE_DOCKED_STACK_ATTACHED, + SoftInputShowHideReason.HIDE_RECENTS_ANIMATION}) +public @interface SoftInputShowHideReason { + /** Show soft input by {@link android.view.inputmethod.InputMethodManager#showSoftInput}. */ + int SHOW_SOFT_INPUT = 0; + + /** Show soft input when {@code InputMethodManagerService#attachNewInputLocked} called. */ + int ATTACH_NEW_INPUT = 1; + + /** Show soft input by {@code InputMethodManagerService#showMySoftInput}. */ + int SHOW_MY_SOFT_INPUT = 2; + + /** + * Hide soft input by + * {@link android.view.inputmethod.InputMethodManager#hideSoftInputFromWindow}. + */ + int HIDE_SOFT_INPUT = 3; + + /** Hide soft input by {@code InputMethodManagerService#hideMySoftInput}. */ + int HIDE_MY_SOFT_INPUT = 4; + + /** + * Show soft input when navigated forward to the window (with + * {@link LayoutParams#SOFT_INPUT_IS_FORWARD_NAVIGATION}} which the focused view is text + * editor and system will auto-show the IME when the window can resize or running on a large + * screen. + */ + int SHOW_AUTO_EDITOR_FORWARD_NAV = 5; + + /** + * Show soft input when navigated forward to the window with + * {@link LayoutParams#SOFT_INPUT_IS_FORWARD_NAVIGATION} and + * {@link LayoutParams#SOFT_INPUT_STATE_VISIBLE}. + */ + int SHOW_STATE_VISIBLE_FORWARD_NAV = 6; + + /** + * Show soft input when the window with {@link LayoutParams#SOFT_INPUT_STATE_ALWAYS_VISIBLE}. + */ + int SHOW_STATE_ALWAYS_VISIBLE = 7; + + /** + * Show soft input during {@code InputMethodManagerService} receive changes from + * {@code SettingsProvider}. + */ + int SHOW_SETTINGS_ON_CHANGE = 8; + + /** Hide soft input during switching user. */ + int HIDE_SWITCH_USER = 9; + + /** Hide soft input when the user is invalid. */ + int HIDE_INVALID_USER = 10; + + /** + * Hide soft input when the window with {@link LayoutParams#SOFT_INPUT_STATE_UNSPECIFIED} which + * the focused view is not text editor. + */ + int HIDE_UNSPECIFIED_WINDOW = 11; + + /** + * Hide soft input when navigated forward to the window with + * {@link LayoutParams#SOFT_INPUT_IS_FORWARD_NAVIGATION} and + * {@link LayoutParams#SOFT_INPUT_STATE_HIDDEN}. + */ + int HIDE_STATE_HIDDEN_FORWARD_NAV = 12; + + /** + * Hide soft input when the window with {@link LayoutParams#SOFT_INPUT_STATE_ALWAYS_HIDDEN}. + */ + int HIDE_ALWAYS_HIDDEN_STATE = 13; + + /** Hide soft input when "adb shell ime <command>" called. */ + int HIDE_RESET_SHELL_COMMAND = 14; + + /** + * Hide soft input during {@code InputMethodManagerService} receive changes from + * {@code SettingsProvider}. + */ + int HIDE_SETTINGS_ON_CHANGE = 15; + + /** + * Hide soft input from {@link com.android.server.policy.PhoneWindowManager} when setting + * {@link com.android.internal.R.integer#config_shortPressOnPowerBehavior} in config.xml as + * dismiss IME. + */ + int HIDE_POWER_BUTTON_GO_HOME = 16; + + /** Hide soft input when attaching docked stack. */ + int HIDE_DOCKED_STACK_ATTACHED = 17; + + /** + * Hide soft input when {@link com.android.server.wm.RecentsAnimationController} starts + * intercept touch from app window. + */ + int HIDE_RECENTS_ANIMATION = 18; +} diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java index eac2d24c3dab..f24699a6ae64 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java @@ -21,6 +21,7 @@ import android.annotation.UserIdInt; import android.view.inputmethod.InlineSuggestionsRequest; import android.view.inputmethod.InputMethodInfo; +import com.android.internal.inputmethod.SoftInputShowHideReason; import com.android.internal.view.IInlineSuggestionsRequestCallback; import com.android.internal.view.InlineSuggestionsRequestInfo; import com.android.server.LocalServices; @@ -51,7 +52,7 @@ public abstract class InputMethodManagerInternal { /** * Hides the current input method, if visible. */ - public abstract void hideCurrentInputMethod(); + public abstract void hideCurrentInputMethod(@SoftInputShowHideReason int reason); /** * Returns the list of installed input methods for the specified user. @@ -106,7 +107,7 @@ public abstract class InputMethodManagerInternal { } @Override - public void hideCurrentInputMethod() { + public void hideCurrentInputMethod(@SoftInputShowHideReason int reason) { } @Override diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index 6f04af608e14..e3c545c3cf28 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -131,6 +131,7 @@ import com.android.internal.content.PackageMonitor; import com.android.internal.inputmethod.IInputContentUriToken; import com.android.internal.inputmethod.IInputMethodPrivilegedOperations; import com.android.internal.inputmethod.InputMethodDebug; +import com.android.internal.inputmethod.SoftInputShowHideReason; import com.android.internal.inputmethod.StartInputFlags; import com.android.internal.inputmethod.StartInputReason; import com.android.internal.inputmethod.UnbindReason; @@ -767,6 +768,75 @@ public class InputMethodManagerService extends IInputMethodManager.Stub @GuardedBy("mMethodMap") private final WeakHashMap<IBinder, IBinder> mImeTargetWindowMap = new WeakHashMap<>(); + private static final class SoftInputShowHideHistory { + private Entry[] mEntries = new Entry[16]; + private int mNextIndex = 0; + private static final AtomicInteger sSequenceNumber = new AtomicInteger(0); + + // TODO(b/141738570): add requestWindowToken to track who request show / hide softInput. + private static final class Entry { + ClientState mClientState; + String mFocusedWindowString; + @SoftInputModeFlags + int mFocusedWindowSoftInputMode; + @SoftInputShowHideReason + int mReason; + boolean mRequestShowKeyboard; + // The timing of handling MSG_SHOW_SOFT_INPUT or MSG_HIDE_SOFT_INPUT. + long mTimestamp; + long mWallTime; + int mTargetDisplayId; + + Entry(ClientState client, String focusedWindow, @SoftInputModeFlags int softInputMode, + @SoftInputShowHideReason int reason, boolean show) { + mClientState = client; + mFocusedWindowString = focusedWindow; + mFocusedWindowSoftInputMode = softInputMode; + mReason = reason; + mRequestShowKeyboard = show; + mTimestamp = SystemClock.uptimeMillis(); + mWallTime = System.currentTimeMillis(); + } + } + + void addEntry(@NonNull Entry entry) { + final int index = mNextIndex; + mEntries[index] = entry; + mNextIndex = (mNextIndex + 1) % mEntries.length; + } + + void dump(@NonNull PrintWriter pw, @NonNull String prefix) { + final SimpleDateFormat dataFormat = + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.US); + + for (int i = 0; i < mEntries.length; ++i) { + final Entry entry = mEntries[(i + mNextIndex) % mEntries.length]; + if (entry == null) { + continue; + } + pw.print(prefix); + pw.println("SoftInputShowHideHistory #" + sSequenceNumber.getAndIncrement() + ":"); + + pw.print(prefix); + pw.println(" time=" + dataFormat.format(new Date(entry.mWallTime)) + + " (timestamp=" + entry.mTimestamp + ")"); + + pw.print(prefix); + pw.print(" requestShowKeyboard=" + entry.mRequestShowKeyboard); + pw.print(" targetDisplayId=" + entry.mTargetDisplayId); + pw.println(" reason=" + entry.mReason); + + pw.print(prefix); + pw.print(" requestClient=" + entry.mClientState); + pw.println(" focusedWindow=" + entry.mFocusedWindowString); + + pw.print(prefix); + pw.println(" focusedWindowSoftInputMode=" + InputMethodDebug.softInputModeToString( + entry.mFocusedWindowSoftInputMode)); + } + } + } + /** * Map of generated token to windowToken that is requesting * {@link InputMethodManager#showSoftInput(View, int)}. @@ -933,6 +1003,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub @NonNull private final StartInputHistory mStartInputHistory = new StartInputHistory(); + @GuardedBy("mMethodMap") + @NonNull + private final SoftInputShowHideHistory mSoftInputShowHideHistory = + new SoftInputShowHideHistory(); + class SettingsObserver extends ContentObserver { int mUserId; boolean mRegistered = false; @@ -989,11 +1064,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub == AccessibilityService.SHOW_MODE_HIDDEN; if (mAccessibilityRequestingNoSoftKeyboard) { final boolean showRequested = mShowRequested; - hideCurrentInputLocked(0, null); + hideCurrentInputLocked(0, null, + SoftInputShowHideReason.HIDE_SETTINGS_ON_CHANGE); mShowRequested = showRequested; } else if (mShowRequested) { - showCurrentInputLocked( - mCurFocusedWindow, InputMethodManager.SHOW_IMPLICIT, null); + showCurrentInputLocked(mCurFocusedWindow, + InputMethodManager.SHOW_IMPLICIT, null, + SoftInputShowHideReason.SHOW_SETTINGS_ON_CHANGE); } } else { boolean enabledChanged = false; @@ -1618,7 +1695,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // TODO: Is it really possible that switchUserLocked() happens before system ready? if (mSystemReady) { - hideCurrentInputLocked(0, null); + hideCurrentInputLocked(0, null, SoftInputShowHideReason.HIDE_SWITCH_USER); resetCurrentMethodAndClient(UnbindReason.SWITCH_USER); buildInputMethodListLocked(initialUserSwitch); if (TextUtils.isEmpty(mSettings.getSelectedInputMethod())) { @@ -2158,7 +2235,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub startInputToken, session, mCurInputContext, mCurAttribute)); if (mShowRequested) { if (DEBUG) Slog.v(TAG, "Attach new input asks to show input"); - showCurrentInputLocked(mCurFocusedWindow, getAppShowFlags(), null); + showCurrentInputLocked(mCurFocusedWindow, getAppShowFlags(), null, + SoftInputShowHideReason.ATTACH_NEW_INPUT); } return new InputBindResult(InputBindResult.ResultCode.SUCCESS_WITH_IME_SESSION, session.session, (session.channel != null ? session.channel.dup() : null), @@ -2897,7 +2975,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } if (DEBUG) Slog.v(TAG, "Client requesting input be shown"); - return showCurrentInputLocked(windowToken, flags, resultReceiver); + return showCurrentInputLocked(windowToken, flags, resultReceiver, + SoftInputShowHideReason.SHOW_SOFT_INPUT); } finally { Binder.restoreCallingIdentity(ident); } @@ -2905,7 +2984,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } @GuardedBy("mMethodMap") - boolean showCurrentInputLocked(IBinder windowToken, int flags, ResultReceiver resultReceiver) { + boolean showCurrentInputLocked(IBinder windowToken, int flags, ResultReceiver resultReceiver, + @SoftInputShowHideReason int reason) { mShowRequested = true; if (mAccessibilityRequestingNoSoftKeyboard) { return false; @@ -2928,9 +3008,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // create a dummy token for IMS so that IMS cannot inject windows into client app. Binder showInputToken = new Binder(); mShowRequestWindowMap.put(showInputToken, windowToken); - executeOrSendMessage(mCurMethod, mCaller.obtainMessageIOOO( - MSG_SHOW_SOFT_INPUT, getImeShowFlags(), mCurMethod, - resultReceiver, showInputToken)); + executeOrSendMessage(mCurMethod, mCaller.obtainMessageIIOOO( + MSG_SHOW_SOFT_INPUT, getImeShowFlags(), reason, mCurMethod, resultReceiver, + showInputToken)); mInputShown = true; if (mHaveConnection && !mVisibleBound) { bindCurrentInputMethodServiceLocked( @@ -2988,14 +3068,16 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } if (DEBUG) Slog.v(TAG, "Client requesting input be hidden"); - return hideCurrentInputLocked(flags, resultReceiver); + return hideCurrentInputLocked(flags, resultReceiver, + SoftInputShowHideReason.HIDE_SOFT_INPUT); } finally { Binder.restoreCallingIdentity(ident); } } } - boolean hideCurrentInputLocked(int flags, ResultReceiver resultReceiver) { + boolean hideCurrentInputLocked(int flags, ResultReceiver resultReceiver, + @SoftInputShowHideReason int reason) { if ((flags&InputMethodManager.HIDE_IMPLICIT_ONLY) != 0 && (mShowExplicitlyRequested || mShowForced)) { if (DEBUG) Slog.v(TAG, "Not hiding: explicit show not cancelled by non-explicit hide"); @@ -3022,8 +3104,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // delivered to the IME process as an IPC. Hence the inconsistency between // IMMS#mInputShown and IMMS#mImeWindowVis should be resolved spontaneously in // the final state. - executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO( - MSG_HIDE_SOFT_INPUT, mCurMethod, resultReceiver)); + executeOrSendMessage(mCurMethod, mCaller.obtainMessageIOO(MSG_HIDE_SOFT_INPUT, + reason, mCurMethod, resultReceiver)); res = true; } else { res = false; @@ -3160,7 +3242,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub Slog.w(TAG, "If you need to impersonate a foreground user/profile from" + " a background user, use EditorInfo.targetInputMethodUser with" + " INTERACT_ACROSS_USERS_FULL permission."); - hideCurrentInputLocked(0, null); + hideCurrentInputLocked(0, null, SoftInputShowHideReason.HIDE_INVALID_USER); return InputBindResult.INVALID_USER; } @@ -3223,7 +3305,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // be behind any soft input window, so hide the // soft input window if it is shown. if (DEBUG) Slog.v(TAG, "Unspecified window will hide input"); - hideCurrentInputLocked(InputMethodManager.HIDE_NOT_ALWAYS, null); + hideCurrentInputLocked(InputMethodManager.HIDE_NOT_ALWAYS, null, + SoftInputShowHideReason.HIDE_UNSPECIFIED_WINDOW); // If focused display changed, we should unbind current method // to make app window in previous display relayout after Ime @@ -3249,7 +3332,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub attribute, startInputFlags, startInputReason); didStart = true; } - showCurrentInputLocked(windowToken, InputMethodManager.SHOW_IMPLICIT, null); + showCurrentInputLocked(windowToken, InputMethodManager.SHOW_IMPLICIT, null, + SoftInputShowHideReason.SHOW_AUTO_EDITOR_FORWARD_NAV); } break; case LayoutParams.SOFT_INPUT_STATE_UNCHANGED: @@ -3258,12 +3342,14 @@ public class InputMethodManagerService extends IInputMethodManager.Stub case LayoutParams.SOFT_INPUT_STATE_HIDDEN: if ((softInputMode & LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) { if (DEBUG) Slog.v(TAG, "Window asks to hide input going forward"); - hideCurrentInputLocked(0, null); + hideCurrentInputLocked(0, null, + SoftInputShowHideReason.HIDE_STATE_HIDDEN_FORWARD_NAV); } break; case LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN: if (DEBUG) Slog.v(TAG, "Window asks to hide input"); - hideCurrentInputLocked(0, null); + hideCurrentInputLocked(0, null, + SoftInputShowHideReason.HIDE_ALWAYS_HIDDEN_STATE); break; case LayoutParams.SOFT_INPUT_STATE_VISIBLE: if ((softInputMode & LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) { @@ -3275,7 +3361,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub attribute, startInputFlags, startInputReason); didStart = true; } - showCurrentInputLocked(windowToken, InputMethodManager.SHOW_IMPLICIT, null); + showCurrentInputLocked(windowToken, InputMethodManager.SHOW_IMPLICIT, null, + SoftInputShowHideReason.SHOW_STATE_VISIBLE_FORWARD_NAV); } else { Slog.e(TAG, "SOFT_INPUT_STATE_VISIBLE is ignored because" + " there is no focused view that also returns true from" @@ -3292,7 +3379,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub attribute, startInputFlags, startInputReason); didStart = true; } - showCurrentInputLocked(windowToken, InputMethodManager.SHOW_IMPLICIT, null); + showCurrentInputLocked(windowToken, InputMethodManager.SHOW_IMPLICIT, null, + SoftInputShowHideReason.SHOW_STATE_ALWAYS_VISIBLE); } else { Slog.e(TAG, "SOFT_INPUT_STATE_ALWAYS_VISIBLE is ignored because" + " there is no focused view that also returns true from" @@ -3784,7 +3872,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } long ident = Binder.clearCallingIdentity(); try { - hideCurrentInputLocked(flags, null); + hideCurrentInputLocked(flags, null, SoftInputShowHideReason.HIDE_MY_SOFT_INPUT); } finally { Binder.restoreCallingIdentity(ident); } @@ -3799,7 +3887,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } long ident = Binder.clearCallingIdentity(); try { - showCurrentInputLocked(mLastImeTargetWindow, flags, null); + showCurrentInputLocked(mLastImeTargetWindow, flags, null, + SoftInputShowHideReason.SHOW_MY_SOFT_INPUT); } finally { Binder.restoreCallingIdentity(ident); } @@ -3882,10 +3971,16 @@ public class InputMethodManagerService extends IInputMethodManager.Stub case MSG_SHOW_SOFT_INPUT: args = (SomeArgs)msg.obj; try { + final @SoftInputShowHideReason int reason = msg.arg2; if (DEBUG) Slog.v(TAG, "Calling " + args.arg1 + ".showSoftInput(" - + msg.arg1 + ", " + args.arg2 + ")"); + + msg.arg1 + ", " + args.arg2 + ") for reason: " + + InputMethodDebug.softInputDisplayReasonToString(reason)); ((IInputMethod) args.arg1).showSoftInput( (IBinder) args.arg3, msg.arg1, (ResultReceiver) args.arg2); + mSoftInputShowHideHistory.addEntry( + new SoftInputShowHideHistory.Entry(mCurClient, + InputMethodDebug.objToString(mCurFocusedWindow), + mCurFocusedWindowSoftInputMode, reason, true /* show */)); } catch (RemoteException e) { } args.recycle(); @@ -3893,16 +3988,23 @@ public class InputMethodManagerService extends IInputMethodManager.Stub case MSG_HIDE_SOFT_INPUT: args = (SomeArgs)msg.obj; try { + final @SoftInputShowHideReason int reason = msg.arg1; if (DEBUG) Slog.v(TAG, "Calling " + args.arg1 + ".hideSoftInput(0, " - + args.arg2 + ")"); + + args.arg2 + ") for reason: " + + InputMethodDebug.softInputDisplayReasonToString(reason)); ((IInputMethod)args.arg1).hideSoftInput(0, (ResultReceiver)args.arg2); + mSoftInputShowHideHistory.addEntry( + new SoftInputShowHideHistory.Entry(mCurClient, + InputMethodDebug.objToString(mCurFocusedWindow), + mCurFocusedWindowSoftInputMode, reason, false /* show */)); } catch (RemoteException e) { } args.recycle(); return true; case MSG_HIDE_CURRENT_INPUT_METHOD: synchronized (mMethodMap) { - hideCurrentInputLocked(0, null); + final @SoftInputShowHideReason int reason = (int) msg.obj; + hideCurrentInputLocked(0, null, reason); } return true; case MSG_INITIALIZE_IME: @@ -4686,9 +4788,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } @Override - public void hideCurrentInputMethod() { + public void hideCurrentInputMethod(@SoftInputShowHideReason int reason) { mService.mHandler.removeMessages(MSG_HIDE_CURRENT_INPUT_METHOD); - mService.mHandler.sendEmptyMessage(MSG_HIDE_CURRENT_INPUT_METHOD); + mService.mHandler.obtainMessage(MSG_HIDE_CURRENT_INPUT_METHOD, reason).sendToTarget(); } @Override @@ -4845,6 +4947,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub p.println(" mStartInputHistory:"); mStartInputHistory.dump(pw, " "); + + p.println(" mSoftInputShowHideHistory:"); + mSoftInputShowHideHistory.dump(pw, " "); } p.println(" "); @@ -5304,7 +5409,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub final String nextIme; final List<InputMethodInfo> nextEnabledImes; if (userId == mSettings.getCurrentUserId()) { - hideCurrentInputLocked(0, null); + hideCurrentInputLocked(0, null, + SoftInputShowHideReason.HIDE_RESET_SHELL_COMMAND); unbindCurrentMethodLocked(); // Reset the current IME resetSelectedInputMethodAndSubtypeLocked(null); diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java index 4904061ec1af..1aff23b09c0f 100644 --- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java @@ -73,6 +73,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.inputmethod.IMultiClientInputMethod; import com.android.internal.inputmethod.IMultiClientInputMethodPrivilegedOperations; import com.android.internal.inputmethod.IMultiClientInputMethodSession; +import com.android.internal.inputmethod.SoftInputShowHideReason; import com.android.internal.inputmethod.StartInputFlags; import com.android.internal.inputmethod.StartInputReason; import com.android.internal.inputmethod.UnbindReason; @@ -174,7 +175,7 @@ public final class MultiClientInputMethodManagerService { } @Override - public void hideCurrentInputMethod() { + public void hideCurrentInputMethod(@SoftInputShowHideReason int reason) { reportNotSupported(); } diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 5081b0f13e0f..b40c2c1d343b 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -186,6 +186,7 @@ import android.view.autofill.AutofillManagerInternal; import com.android.internal.R; import com.android.internal.accessibility.AccessibilityShortcutController; +import com.android.internal.inputmethod.SoftInputShowHideReason; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto; import com.android.internal.os.RoSystemProperties; @@ -1106,7 +1107,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { LocalServices.getService(InputMethodManagerInternal.class); } if (mInputMethodManagerInternal != null) { - mInputMethodManagerInternal.hideCurrentInputMethod(); + mInputMethodManagerInternal.hideCurrentInputMethod( + SoftInputShowHideReason.HIDE_POWER_BUTTON_GO_HOME); } } else { shortPressPowerGoHome(); diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java index 6431e117c4e6..958c8ae94e47 100644 --- a/services/core/java/com/android/server/wm/DockedStackDividerController.java +++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java @@ -53,6 +53,7 @@ import android.view.animation.Interpolator; import android.view.animation.PathInterpolator; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.inputmethod.SoftInputShowHideReason; import com.android.internal.policy.DividerSnapAlgorithm; import com.android.internal.policy.DockedDividerUtils; import com.android.server.LocalServices; @@ -517,7 +518,8 @@ public class DockedStackDividerController { // Hide the current IME to avoid problems with animations from IME adjustment when // attaching the docked stack. - inputMethodManagerInternal.hideCurrentInputMethod(); + inputMethodManagerInternal.hideCurrentInputMethod( + SoftInputShowHideReason.HIDE_DOCKED_STACK_ATTACHED); mImeHideRequested = true; } diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java index 4399d6519363..e69551a0fde4 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimationController.java +++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java @@ -54,6 +54,7 @@ import android.view.SurfaceControl; import android.view.SurfaceControl.Transaction; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.inputmethod.SoftInputShowHideReason; import com.android.internal.util.function.pooled.PooledConsumer; import com.android.internal.util.function.pooled.PooledFunction; import com.android.internal.util.function.pooled.PooledLambda; @@ -299,7 +300,8 @@ public class RecentsAnimationController implements DeathRecipient { final InputMethodManagerInternal inputMethodManagerInternal = LocalServices.getService(InputMethodManagerInternal.class); if (inputMethodManagerInternal != null) { - inputMethodManagerInternal.hideCurrentInputMethod(); + inputMethodManagerInternal.hideCurrentInputMethod( + SoftInputShowHideReason.HIDE_RECENTS_ANIMATION); } } finally { Binder.restoreCallingIdentity(token); |