summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/com/android/internal/inputmethod/InputMethodDebug.java70
-rw-r--r--core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java143
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java5
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java164
-rw-r--r--services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java3
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java4
-rw-r--r--services/core/java/com/android/server/wm/DockedStackDividerController.java4
-rw-r--r--services/core/java/com/android/server/wm/RecentsAnimationController.java4
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);