Introduce SoftInputShowHideHistory
Add SoftInputShowHideHistory class to monitor showSoftInput / hideSoftInput histories, each entry data contains: - ClientState: IME focused client process pid / uid who shows / hides soft input - Current focused window - Target display ID - Reason: describes why show / hide input - Request show or hide input - Timestamp Bug: 141738570 Test: manual by calling "adb shell dumpsys input_method" Change-Id: I21ad1708d68eae59dcd3d414248193fb130dadc2
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import android.view.autofill.AutofillId;
|
||||
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.server.LocalServices;
|
||||
|
||||
@@ -52,7 +53,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.
|
||||
@@ -109,7 +110,7 @@ public abstract class InputMethodManagerInternal {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideCurrentInputMethod() {
|
||||
public void hideCurrentInputMethod(@SoftInputShowHideReason int reason) {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -132,6 +132,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;
|
||||
@@ -1568,7 +1645,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())) {
|
||||
@@ -2094,7 +2171,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),
|
||||
@@ -2833,7 +2911,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);
|
||||
}
|
||||
@@ -2841,7 +2920,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;
|
||||
@@ -2864,9 +2944,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(
|
||||
@@ -2924,14 +3004,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");
|
||||
@@ -2958,8 +3040,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;
|
||||
@@ -3080,7 +3162,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;
|
||||
}
|
||||
|
||||
@@ -3141,7 +3223,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
|
||||
@@ -3167,7 +3250,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:
|
||||
@@ -3176,12 +3260,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) {
|
||||
@@ -3193,7 +3279,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"
|
||||
@@ -3210,7 +3297,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"
|
||||
@@ -3702,7 +3790,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);
|
||||
}
|
||||
@@ -3717,7 +3805,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);
|
||||
}
|
||||
@@ -3800,10 +3889,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();
|
||||
@@ -3811,16 +3906,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:
|
||||
@@ -4604,9 +4706,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
|
||||
@@ -4763,6 +4865,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
|
||||
p.println(" mStartInputHistory:");
|
||||
mStartInputHistory.dump(pw, " ");
|
||||
|
||||
p.println(" mSoftInputShowHideHistory:");
|
||||
mSoftInputShowHideHistory.dump(pw, " ");
|
||||
}
|
||||
|
||||
p.println(" ");
|
||||
@@ -5222,7 +5327,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);
|
||||
|
||||
@@ -74,6 +74,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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -1105,7 +1106,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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,6 +55,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;
|
||||
@@ -301,7 +302,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);
|
||||
|
||||
Reference in New Issue
Block a user