Merge changes I6adbf430,I6e137a6e,I9e15358a,I2aea907b,I12d99c15, ...

* changes:
  Migrate IMMS#shouldRestoreImeVisibility to ImeVisibilityStateComputer
  Migrate applyImeVsibility to ImeVisibilityApplier
  Migrate computeImeDisplayIdForTarget to ImeVisibilityStateComputer
  Migrate to IME visibility settings
  Introduce ImeVisibilityApplier
  Introduce ImeVisibilityStateComputer
This commit is contained in:
Ming-Shin Lu
2023-01-11 14:50:27 +00:00
committed by Android (Google) Code Review
4 changed files with 723 additions and 192 deletions

View File

@@ -0,0 +1,155 @@
/*
* Copyright (C) 2022 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.server.inputmethod;
import static android.view.inputmethod.ImeTracker.DEBUG_IME_VISIBILITY;
import static com.android.server.EventLogTags.IMF_HIDE_IME;
import static com.android.server.EventLogTags.IMF_SHOW_IME;
import static com.android.server.inputmethod.ImeVisibilityStateComputer.STATE_HIDE_IME;
import static com.android.server.inputmethod.ImeVisibilityStateComputer.STATE_SHOW_IME;
import android.annotation.Nullable;
import android.os.Binder;
import android.os.IBinder;
import android.os.ResultReceiver;
import android.util.EventLog;
import android.util.Slog;
import android.view.inputmethod.ImeTracker;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.inputmethod.InputMethodDebug;
import com.android.internal.inputmethod.SoftInputShowHideReason;
import com.android.server.LocalServices;
import com.android.server.wm.WindowManagerInternal;
import java.util.Objects;
/**
* The default implementation of {@link ImeVisibilityApplier} used in
* {@link InputMethodManagerService}.
*/
final class DefaultImeVisibilityApplier implements ImeVisibilityApplier {
private static final String TAG = "DefaultImeVisibilityApplier";
private static final boolean DEBUG = InputMethodManagerService.DEBUG;
private InputMethodManagerService mService;
private final WindowManagerInternal mWindowManagerInternal;
DefaultImeVisibilityApplier(InputMethodManagerService service) {
mService = service;
mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
}
@GuardedBy("ImfLock.class")
@Override
public void performShowIme(IBinder windowToken, @Nullable ImeTracker.Token statsToken,
int showFlags, ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
final IInputMethodInvoker curMethod = mService.getCurMethodLocked();
if (curMethod != null) {
// create a placeholder token for IMS so that IMS cannot inject windows into client app.
final IBinder showInputToken = new Binder();
mService.setRequestImeTokenToWindow(windowToken, showInputToken);
if (DEBUG) {
Slog.v(TAG, "Calling " + curMethod + ".showSoftInput(" + showInputToken
+ ", " + showFlags + ", " + resultReceiver + ") for reason: "
+ InputMethodDebug.softInputDisplayReasonToString(reason));
}
// TODO(b/192412909): Check if we can always call onShowHideSoftInputRequested() or not.
if (curMethod.showSoftInput(showInputToken, statsToken, showFlags, resultReceiver)) {
if (DEBUG_IME_VISIBILITY) {
EventLog.writeEvent(IMF_SHOW_IME, statsToken.getTag(),
Objects.toString(mService.mCurFocusedWindow),
InputMethodDebug.softInputDisplayReasonToString(reason),
InputMethodDebug.softInputModeToString(
mService.mCurFocusedWindowSoftInputMode));
}
mService.onShowHideSoftInputRequested(true /* show */, windowToken, reason,
statsToken);
}
}
}
@GuardedBy("ImfLock.class")
@Override
public void performHideIme(IBinder windowToken, @Nullable ImeTracker.Token statsToken,
ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
final IInputMethodInvoker curMethod = mService.getCurMethodLocked();
if (curMethod != null) {
final Binder hideInputToken = new Binder();
mService.setRequestImeTokenToWindow(windowToken, hideInputToken);
// The IME will report its visible state again after the following message finally
// 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.
if (DEBUG) {
Slog.v(TAG, "Calling " + curMethod + ".hideSoftInput(0, " + hideInputToken
+ ", " + resultReceiver + ") for reason: "
+ InputMethodDebug.softInputDisplayReasonToString(reason));
}
// TODO(b/192412909): Check if we can always call onShowHideSoftInputRequested() or not.
if (curMethod.hideSoftInput(hideInputToken, statsToken, 0, resultReceiver)) {
if (DEBUG_IME_VISIBILITY) {
EventLog.writeEvent(IMF_HIDE_IME, statsToken.getTag(),
Objects.toString(mService.mCurFocusedWindow),
InputMethodDebug.softInputDisplayReasonToString(reason),
InputMethodDebug.softInputModeToString(
mService.mCurFocusedWindowSoftInputMode));
}
mService.onShowHideSoftInputRequested(false /* show */, windowToken, reason,
statsToken);
}
}
}
@GuardedBy("ImfLock.class")
@Override
public void applyImeVisibility(IBinder windowToken, @Nullable ImeTracker.Token statsToken,
@ImeVisibilityStateComputer.VisibilityState int state) {
switch (state) {
case STATE_SHOW_IME:
ImeTracker.get().onProgress(statsToken,
ImeTracker.PHASE_SERVER_APPLY_IME_VISIBILITY);
// Send to window manager to show IME after IME layout finishes.
mWindowManagerInternal.showImePostLayout(windowToken, statsToken);
break;
case STATE_HIDE_IME:
if (mService.mCurFocusedWindowClient != null) {
ImeTracker.get().onProgress(statsToken,
ImeTracker.PHASE_SERVER_APPLY_IME_VISIBILITY);
// IMMS only knows of focused window, not the actual IME target.
// e.g. it isn't aware of any window that has both
// NOT_FOCUSABLE, ALT_FOCUSABLE_IM flags set and can the IME target.
// Send it to window manager to hide IME from IME target window.
// TODO(b/139861270): send to mCurClient.client once IMMS is aware of
// actual IME target.
mWindowManagerInternal.hideIme(windowToken,
mService.mCurFocusedWindowClient.mSelfReportedDisplayId, statsToken);
} else {
ImeTracker.get().onFailed(statsToken,
ImeTracker.PHASE_SERVER_APPLY_IME_VISIBILITY);
}
break;
default:
throw new IllegalArgumentException("Invalid IME visibility state: " + state);
}
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright (C) 2022 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.server.inputmethod;
import android.annotation.Nullable;
import android.os.IBinder;
import android.os.ResultReceiver;
import android.view.inputmethod.ImeTracker;
import com.android.internal.inputmethod.SoftInputShowHideReason;
/**
* Interface for IME visibility operations like show/hide and update Z-ordering relative to the IME
* targeted window.
*/
interface ImeVisibilityApplier {
/**
* Performs showing IME on top of the given window.
*
* @param windowToken The token of a window that currently has focus.
* @param statsToken A token that tracks the progress of an IME request.
* @param showFlags Provides additional operating flags to show IME.
* @param resultReceiver If non-null, this will be called back to the caller when
* it has processed request to tell what it has done.
* @param reason The reason for requesting to show IME.
*/
default void performShowIme(IBinder windowToken, @Nullable ImeTracker.Token statsToken,
int showFlags, ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {}
/**
* Performs hiding IME to the given window
*
* @param windowToken The token of a window that currently has focus.
* @param statsToken A token that tracks the progress of an IME request.
* @param resultReceiver If non-null, this will be called back to the caller when
* it has processed request to tell what it has done.
* @param reason The reason for requesting to hide IME.
*/
default void performHideIme(IBinder windowToken, @Nullable ImeTracker.Token statsToken,
ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {}
/**
* Applies the IME visibility from {@link android.inputmethodservice.InputMethodService} with
* according to the given visibility state.
*
* @param windowToken The token of a window for applying the IME visibility
* @param statsToken A token that tracks the progress of an IME request.
* @param state The new IME visibility state for the applier to handle
*/
default void applyImeVisibility(IBinder windowToken, @Nullable ImeTracker.Token statsToken,
@ImeVisibilityStateComputer.VisibilityState int state) {}
/**
* Updates the IME Z-ordering relative to the given window.
*
* This used to adjust the IME relative layer of the window during
* {@link InputMethodManagerService} is in switching IME clients.
*
* @param windowToken The token of a window to update the Z-ordering relative to the IME.
*/
default void updateImeLayeringByTarget(IBinder windowToken) {
// TODO: add a method in WindowManagerInternal to call DC#updateImeInputAndControlTarget
// here to end up updating IME layering after IMMS#attachNewInputLocked called.
}
}

View File

@@ -0,0 +1,424 @@
/*
* Copyright (C) 2022 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.server.inputmethod;
import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HIDDEN;
import static android.server.inputmethod.InputMethodManagerServiceProto.ACCESSIBILITY_REQUESTING_NO_SOFT_KEYBOARD;
import static android.server.inputmethod.InputMethodManagerServiceProto.SHOW_EXPLICITLY_REQUESTED;
import static android.server.inputmethod.InputMethodManagerServiceProto.SHOW_FORCED;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED;
import static android.view.WindowManager.LayoutParams.SoftInputModeFlags;
import static com.android.internal.inputmethod.InputMethodDebug.softInputModeToString;
import static com.android.server.inputmethod.InputMethodManagerService.computeImeDisplayIdForTarget;
import android.accessibilityservice.AccessibilityService;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.os.IBinder;
import android.util.PrintWriterPrinter;
import android.util.Printer;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import android.view.WindowManager;
import android.view.inputmethod.ImeTracker;
import android.view.inputmethod.InputMethod;
import android.view.inputmethod.InputMethodManager;
import com.android.server.LocalServices;
import com.android.server.wm.WindowManagerInternal;
import java.io.PrintWriter;
import java.util.WeakHashMap;
/**
* A computer used by {@link InputMethodManagerService} that computes the IME visibility state
* according the given {@link ImeTargetWindowState} from the focused window or the app requested IME
* visibility from {@link InputMethodManager}.
*/
public final class ImeVisibilityStateComputer {
private static final String TAG = "ImeVisibilityStateComputer";
private static final boolean DEBUG = InputMethodManagerService.DEBUG;
private final InputMethodManagerService mService;
private final WindowManagerInternal mWindowManagerInternal;
final InputMethodManagerService.ImeDisplayValidator mImeDisplayValidator;
/**
* A map used to track the requested IME target window and its state. The key represents the
* token of the window and the value is the corresponding IME window state.
*/
private final WeakHashMap<IBinder, ImeTargetWindowState> mRequestWindowStateMap =
new WeakHashMap<>();
/**
* Set if IME was explicitly told to show the input method.
*
* @see InputMethodManager#SHOW_IMPLICIT that we set the value is {@code false}.
* @see InputMethodManager#HIDE_IMPLICIT_ONLY that system will not hide IME when the value is
* {@code true}.
*/
boolean mRequestedShowExplicitly;
/**
* Set if we were forced to be shown.
*
* @see InputMethodManager#SHOW_FORCED
* @see InputMethodManager#HIDE_NOT_ALWAYS
*/
boolean mShowForced;
/** Represent the invalid IME visibility state */
public static final int STATE_INVALID = -1;
/** State to handle hiding the IME window requested by the app. */
public static final int STATE_HIDE_IME = 0;
/** State to handle showing the IME window requested by the app. */
public static final int STATE_SHOW_IME = 1;
/** State to handle showing the IME window with making the overlay window above it. */
public static final int STATE_SHOW_IME_ABOVE_OVERLAY = 2;
/** State to handle showing the IME window with making the overlay window behind it. */
public static final int STATE_SHOW_IME_BEHIND_OVERLAY = 3;
/** State to handle showing an IME preview surface during the app was loosing the IME focus */
public static final int STATE_SHOW_IME_SNAPSHOT = 4;
@IntDef({
STATE_INVALID,
STATE_HIDE_IME,
STATE_SHOW_IME,
STATE_SHOW_IME_ABOVE_OVERLAY,
STATE_SHOW_IME_BEHIND_OVERLAY,
STATE_SHOW_IME_SNAPSHOT,
})
@interface VisibilityState {}
/**
* The policy to configure the IME visibility.
*/
private final ImeVisibilityPolicy mPolicy;
public ImeVisibilityStateComputer(InputMethodManagerService service) {
mService = service;
mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
mImeDisplayValidator = mWindowManagerInternal::getDisplayImePolicy;
mPolicy = new ImeVisibilityPolicy();
}
/**
* Called when {@link InputMethodManagerService} is processing the show IME request.
* @param statsToken The token for tracking this show request
* @param showFlags The additional operation flags to indicate whether this show request mode is
* implicit or explicit.
* @return {@code true} when the computer has proceed this show request operation.
*/
boolean onImeShowFlags(@NonNull ImeTracker.Token statsToken, int showFlags) {
if (mPolicy.mA11yRequestingNoSoftKeyboard || mPolicy.mImeHiddenByDisplayPolicy) {
ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_ACCESSIBILITY);
return false;
}
ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_ACCESSIBILITY);
if ((showFlags & InputMethodManager.SHOW_FORCED) != 0) {
mRequestedShowExplicitly = true;
mShowForced = true;
} else if ((showFlags & InputMethodManager.SHOW_IMPLICIT) == 0) {
mRequestedShowExplicitly = true;
}
return true;
}
/**
* Called when {@link InputMethodManagerService} is processing the hide IME request.
* @param statsToken The token for tracking this hide request
* @param hideFlags The additional operation flags to indicate whether this hide request mode is
* implicit or explicit.
* @return {@code true} when the computer has proceed this hide request operations.
*/
boolean canHideIme(@NonNull ImeTracker.Token statsToken, int hideFlags) {
if ((hideFlags & InputMethodManager.HIDE_IMPLICIT_ONLY) != 0
&& (mRequestedShowExplicitly || mShowForced)) {
if (DEBUG) Slog.v(TAG, "Not hiding: explicit show not cancelled by non-explicit hide");
ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_HIDE_IMPLICIT);
return false;
}
if (mShowForced && (hideFlags & InputMethodManager.HIDE_NOT_ALWAYS) != 0) {
if (DEBUG) Slog.v(TAG, "Not hiding: forced show not cancelled by not-always hide");
ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_HIDE_NOT_ALWAYS);
return false;
}
ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_HIDE_NOT_ALWAYS);
return true;
}
int getImeShowFlags() {
int flags = 0;
if (mShowForced) {
flags |= InputMethod.SHOW_FORCED | InputMethod.SHOW_EXPLICIT;
} else if (mRequestedShowExplicitly) {
flags |= InputMethod.SHOW_EXPLICIT;
} else {
flags |= InputMethodManager.SHOW_IMPLICIT;
}
return flags;
}
void clearImeShowFlags() {
mRequestedShowExplicitly = false;
mShowForced = false;
}
int computeImeDisplayId(@NonNull ImeTargetWindowState state, int displayId) {
final int displayToShowIme = computeImeDisplayIdForTarget(displayId, mImeDisplayValidator);
state.setImeDisplayId(displayToShowIme);
final boolean imeHiddenByPolicy = displayToShowIme == INVALID_DISPLAY;
mPolicy.setImeHiddenByDisplayPolicy(imeHiddenByPolicy);
return displayToShowIme;
}
/**
* Request to show/hide IME from the given window.
*
* @param windowToken The window which requests to show/hide IME.
* @param showIme {@code true} means to show IME, {@code false} otherwise.
* Note that in the computer will take this option to compute the
* visibility state, it could be {@link #STATE_SHOW_IME} or
* {@link #STATE_HIDE_IME}.
*/
void requestImeVisibility(IBinder windowToken, boolean showIme) {
final ImeTargetWindowState state = getOrCreateWindowState(windowToken);
state.setRequestedImeVisible(showIme);
setWindowState(windowToken, state);
}
ImeTargetWindowState getOrCreateWindowState(IBinder windowToken) {
ImeTargetWindowState state = mRequestWindowStateMap.get(windowToken);
if (state == null) {
state = new ImeTargetWindowState(SOFT_INPUT_STATE_UNSPECIFIED, false, false);
}
return state;
}
ImeTargetWindowState getWindowStateOrNull(IBinder windowToken) {
ImeTargetWindowState state = mRequestWindowStateMap.get(windowToken);
return state;
}
void setRequestImeTokenToWindow(IBinder windowToken, IBinder token) {
ImeTargetWindowState state = getWindowStateOrNull(windowToken);
if (state != null) {
state.setRequestImeToken(token);
setWindowState(windowToken, state);
}
}
void setWindowState(IBinder windowToken, ImeTargetWindowState newState) {
if (DEBUG) Slog.d(TAG, "setWindowState, windowToken=" + windowToken
+ ", state=" + newState);
mRequestWindowStateMap.put(windowToken, newState);
}
IBinder getWindowTokenFrom(IBinder requestImeToken) {
for (IBinder windowToken : mRequestWindowStateMap.keySet()) {
final ImeTargetWindowState state = mRequestWindowStateMap.get(windowToken);
if (state.getRequestImeToken() == requestImeToken) {
return windowToken;
}
}
// Fallback to the focused window for some edge cases (e.g. relaunching the activity)
return mService.mCurFocusedWindow;
}
IBinder getWindowTokenFrom(ImeTargetWindowState windowState) {
for (IBinder windowToken : mRequestWindowStateMap.keySet()) {
final ImeTargetWindowState state = mRequestWindowStateMap.get(windowToken);
if (state == windowState) {
return windowToken;
}
}
return null;
}
boolean shouldRestoreImeVisibility(@NonNull ImeTargetWindowState state) {
final int softInputMode = state.getSoftInputModeState();
switch (softInputMode & WindowManager.LayoutParams.SOFT_INPUT_MASK_STATE) {
case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN:
return false;
case WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN:
if ((softInputMode & SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
return false;
}
}
return mWindowManagerInternal.shouldRestoreImeVisibility(getWindowTokenFrom(state));
}
void dumpDebug(ProtoOutputStream proto, long fieldId) {
proto.write(SHOW_EXPLICITLY_REQUESTED, mRequestedShowExplicitly);
proto.write(SHOW_FORCED, mShowForced);
proto.write(ACCESSIBILITY_REQUESTING_NO_SOFT_KEYBOARD,
mPolicy.isA11yRequestNoSoftKeyboard());
}
void dump(PrintWriter pw) {
final Printer p = new PrintWriterPrinter(pw);
p.println(" mRequestedShowExplicitly=" + mRequestedShowExplicitly
+ " mShowForced=" + mShowForced);
p.println(" mImeHiddenByDisplayPolicy=" + mPolicy.isImeHiddenByDisplayPolicy());
}
/**
* A settings class to manage all IME related visibility policies or settings.
*
* This is used for the visibility computer to manage and tell
* {@link InputMethodManagerService} if the requested IME visibility is valid from
* application call or the focus window.
*/
static class ImeVisibilityPolicy {
/**
* {@code true} if the Ime policy has been set to
* {@link WindowManager#DISPLAY_IME_POLICY_HIDE}.
*
* This prevents the IME from showing when it otherwise may have shown.
*/
private boolean mImeHiddenByDisplayPolicy;
/**
* Set when the accessibility service requests to hide IME by
* {@link AccessibilityService.SoftKeyboardController#setShowMode}
*/
private boolean mA11yRequestingNoSoftKeyboard;
void setImeHiddenByDisplayPolicy(boolean hideIme) {
mImeHiddenByDisplayPolicy = hideIme;
}
boolean isImeHiddenByDisplayPolicy() {
return mImeHiddenByDisplayPolicy;
}
void setA11yRequestNoSoftKeyboard(int keyboardShowMode) {
mA11yRequestingNoSoftKeyboard =
(keyboardShowMode & AccessibilityService.SHOW_MODE_MASK) == SHOW_MODE_HIDDEN;
}
boolean isA11yRequestNoSoftKeyboard() {
return mA11yRequestingNoSoftKeyboard;
}
}
ImeVisibilityPolicy getImePolicy() {
return mPolicy;
}
/**
* A class that represents the current state of the IME target window.
*/
static class ImeTargetWindowState {
ImeTargetWindowState(@SoftInputModeFlags int softInputModeState, boolean imeFocusChanged,
boolean hasFocusedEditor) {
mSoftInputModeState = softInputModeState;
mImeFocusChanged = imeFocusChanged;
mHasFocusedEditor = hasFocusedEditor;
}
/**
* Visibility state for this window. By default no state has been specified.
*/
private final @SoftInputModeFlags int mSoftInputModeState;
/**
* {@code true} means the IME focus changed from the previous window, {@code false}
* otherwise.
*/
private final boolean mImeFocusChanged;
/**
* {@code true} when the window has focused an editor, {@code false} otherwise.
*/
private final boolean mHasFocusedEditor;
/**
* Set if the client has asked for the input method to be shown.
*/
private boolean mRequestedImeVisible;
/**
* A identifier for knowing the requester of {@link InputMethodManager#showSoftInput} or
* {@link InputMethodManager#hideSoftInputFromWindow}.
*/
private IBinder mRequestImeToken;
/**
* The IME target display id for which the latest startInput was called.
*/
private int mImeDisplayId = DEFAULT_DISPLAY;
boolean hasImeFocusChanged() {
return mImeFocusChanged;
}
boolean hasEdiorFocused() {
return mHasFocusedEditor;
}
int getSoftInputModeState() {
return mSoftInputModeState;
}
private void setImeDisplayId(int imeDisplayId) {
mImeDisplayId = imeDisplayId;
}
int getImeDisplayId() {
return mImeDisplayId;
}
private void setRequestedImeVisible(boolean requestedImeVisible) {
mRequestedImeVisible = requestedImeVisible;
}
boolean isRequestedImeVisible() {
return mRequestedImeVisible;
}
void setRequestImeToken(IBinder token) {
mRequestImeToken = token;
}
IBinder getRequestImeToken() {
return mRequestImeToken;
}
@Override
public String toString() {
return "ImeTargetWindowState{ imeToken " + mRequestImeToken
+ " imeFocusChanged " + mImeFocusChanged
+ " hasEditorFocused " + mHasFocusedEditor
+ " requestedImeVisible " + mRequestedImeVisible
+ " imeDisplayId " + mImeDisplayId
+ " softInputModeState " + softInputModeToString(mSoftInputModeState)
+ "}";
}
}
}

View File

@@ -20,7 +20,6 @@ import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL;
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL;
import static android.os.IServiceManager.DUMP_FLAG_PROTO;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.server.inputmethod.InputMethodManagerServiceProto.ACCESSIBILITY_REQUESTING_NO_SOFT_KEYBOARD;
import static android.server.inputmethod.InputMethodManagerServiceProto.BACK_DISPOSITION;
import static android.server.inputmethod.InputMethodManagerServiceProto.BOUND_TO_METHOD;
import static android.server.inputmethod.InputMethodManagerServiceProto.CUR_ATTRIBUTE;
@@ -39,8 +38,6 @@ import static android.server.inputmethod.InputMethodManagerServiceProto.IN_FULLS
import static android.server.inputmethod.InputMethodManagerServiceProto.IS_INTERACTIVE;
import static android.server.inputmethod.InputMethodManagerServiceProto.LAST_IME_TARGET_WINDOW_NAME;
import static android.server.inputmethod.InputMethodManagerServiceProto.LAST_SWITCH_USER_ID;
import static android.server.inputmethod.InputMethodManagerServiceProto.SHOW_EXPLICITLY_REQUESTED;
import static android.server.inputmethod.InputMethodManagerServiceProto.SHOW_FORCED;
import static android.server.inputmethod.InputMethodManagerServiceProto.SHOW_IME_WITH_HARD_KEYBOARD;
import static android.server.inputmethod.InputMethodManagerServiceProto.SHOW_REQUESTED;
import static android.server.inputmethod.InputMethodManagerServiceProto.SYSTEM_READY;
@@ -48,17 +45,14 @@ import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.WindowManager.DISPLAY_IME_POLICY_HIDE;
import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL;
import static android.view.inputmethod.ImeTracker.DEBUG_IME_VISIBILITY;
import static com.android.server.EventLogTags.IMF_HIDE_IME;
import static com.android.server.EventLogTags.IMF_SHOW_IME;
import static com.android.server.inputmethod.ImeVisibilityStateComputer.ImeTargetWindowState;
import static com.android.server.inputmethod.InputMethodBindingController.TIME_TO_RECONNECT;
import static com.android.server.inputmethod.InputMethodUtils.isSoftInputModeStateVisibleAllowed;
import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.Manifest;
import android.accessibilityservice.AccessibilityService;
import android.annotation.AnyThread;
import android.annotation.BinderThread;
import android.annotation.DrawableRes;
@@ -126,7 +120,6 @@ import android.view.DisplayInfo;
import android.view.InputChannel;
import android.view.InputDevice;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.WindowManager.DisplayImePolicy;
import android.view.WindowManager.LayoutParams;
@@ -299,6 +292,12 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
@NonNull private final InputMethodBindingController mBindingController;
@NonNull private final AutofillSuggestionsController mAutofillController;
@GuardedBy("ImfLock.class")
@NonNull private final ImeVisibilityStateComputer mVisibilityStateComputer;
@GuardedBy("ImfLock.class")
@NonNull private final DefaultImeVisibilityApplier mVisibilityApplier;
/**
* Cache the result of {@code LocalServices.getService(AudioManagerInternal.class)}.
*
@@ -529,13 +528,6 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
mBindingController.advanceSequenceNumber();
}
/**
* {@code true} if the Ime policy has been set to {@link WindowManager#DISPLAY_IME_POLICY_HIDE}.
*
* This prevents the IME from showing when it otherwise may have shown.
*/
boolean mImeHiddenByDisplayPolicy;
/**
* The client that is currently bound to an input method.
*/
@@ -637,16 +629,6 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
*/
private boolean mShowRequested;
/**
* Set if we were explicitly told to show the input method.
*/
boolean mShowExplicitlyRequested;
/**
* Set if we were forced to be shown.
*/
boolean mShowForced;
/**
* Set if we last told the input method to show itself.
*/
@@ -709,8 +691,6 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
*/
private static final int FALLBACK_DISPLAY_ID = DEFAULT_DISPLAY;
final ImeDisplayValidator mImeDisplayValidator;
/**
* If non-null, this is the input method service we are currently connected
* to.
@@ -786,7 +766,6 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
int mImeWindowVis;
private LocaleList mLastSystemLocales;
private boolean mAccessibilityRequestingNoSoftKeyboard;
private final MyPackageMonitor mMyPackageMonitor = new MyPackageMonitor();
private final String mSlotIme;
@@ -973,22 +952,6 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
}
}
/**
* Map of generated token to windowToken that is requesting
* {@link InputMethodManager#showSoftInput(View, int)}.
* This map tracks origin of showSoftInput requests.
*/
@GuardedBy("ImfLock.class")
private final WeakHashMap<IBinder, IBinder> mShowRequestWindowMap = new WeakHashMap<>();
/**
* Map of generated token to windowToken that is requesting
* {@link InputMethodManager#hideSoftInputFromWindow(IBinder, int)}.
* This map tracks origin of hideSoftInput requests.
*/
@GuardedBy("ImfLock.class")
private final WeakHashMap<IBinder, IBinder> mHideRequestWindowMap = new WeakHashMap<>();
/**
* A ring buffer to store the history of {@link StartInputInfo}.
*/
@@ -1207,11 +1170,10 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
} else if (accessibilityRequestingNoImeUri.equals(uri)) {
final int accessibilitySoftKeyboardSetting = Settings.Secure.getIntForUser(
mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0 /* def */, mUserId);
mAccessibilityRequestingNoSoftKeyboard =
(accessibilitySoftKeyboardSetting & AccessibilityService.SHOW_MODE_MASK)
== AccessibilityService.SHOW_MODE_HIDDEN;
if (mAccessibilityRequestingNoSoftKeyboard) {
Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0, mUserId);
mVisibilityStateComputer.getImePolicy().setA11yRequestNoSoftKeyboard(
accessibilitySoftKeyboardSetting);
if (mVisibilityStateComputer.getImePolicy().isA11yRequestNoSoftKeyboard()) {
final boolean showRequested = mShowRequested;
hideCurrentInputLocked(mCurFocusedWindow, null /* statsToken */,
0 /* flags */, null /* resultReceiver */,
@@ -1722,7 +1684,6 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
mImePlatformCompatUtils = new ImePlatformCompatUtils();
mInputMethodDeviceConfigs = new InputMethodDeviceConfigs();
mImeDisplayValidator = mWindowManagerInternal::getDisplayImePolicy;
mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
@@ -1747,6 +1708,10 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
? bindingControllerForTesting
: new InputMethodBindingController(this);
mAutofillController = new AutofillSuggestionsController(this);
mVisibilityStateComputer = new ImeVisibilityStateComputer(this);
mVisibilityApplier = new DefaultImeVisibilityApplier(this);
mPreventImeStartupUnlessTextEditor = mRes.getBoolean(
com.android.internal.R.bool.config_preventImeStartupUnlessTextEditor);
mNonPreemptibleInputMethods = mRes.getStringArray(
@@ -2339,29 +2304,6 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
mInputShown = false;
}
@GuardedBy("ImfLock.class")
private int getImeShowFlagsLocked() {
int flags = 0;
if (mShowForced) {
flags |= InputMethod.SHOW_FORCED
| InputMethod.SHOW_EXPLICIT;
} else if (mShowExplicitlyRequested) {
flags |= InputMethod.SHOW_EXPLICIT;
}
return flags;
}
@GuardedBy("ImfLock.class")
private int getAppShowFlagsLocked() {
int flags = 0;
if (mShowForced) {
flags |= InputMethodManager.SHOW_FORCED;
} else if (!mShowExplicitlyRequested) {
flags |= InputMethodManager.SHOW_IMPLICIT;
}
return flags;
}
@GuardedBy("ImfLock.class")
@NonNull
InputBindResult attachNewInputLocked(@StartInputReason int startInputReason, boolean initial) {
@@ -2403,7 +2345,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
// Re-use current statsToken, if it exists.
final ImeTracker.Token statsToken = mCurStatsToken;
mCurStatsToken = null;
showCurrentInputLocked(mCurFocusedWindow, statsToken, getAppShowFlagsLocked(),
showCurrentInputLocked(mCurFocusedWindow, statsToken,
mVisibilityStateComputer.getImeShowFlags(),
null /* resultReceiver */, SoftInputShowHideReason.ATTACH_NEW_INPUT);
}
@@ -2518,17 +2461,20 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
// Compute the final shown display ID with validated cs.selfReportedDisplayId for this
// session & other conditions.
mDisplayIdToShowIme = computeImeDisplayIdForTarget(cs.mSelfReportedDisplayId,
mImeDisplayValidator);
ImeTargetWindowState winState = mVisibilityStateComputer.getWindowStateOrNull(
mCurFocusedWindow);
if (winState == null) {
return InputBindResult.NOT_IME_TARGET_WINDOW;
}
final int csDisplayId = cs.mSelfReportedDisplayId;
mDisplayIdToShowIme = mVisibilityStateComputer.computeImeDisplayId(winState, csDisplayId);
if (mDisplayIdToShowIme == INVALID_DISPLAY) {
mImeHiddenByDisplayPolicy = true;
if (mVisibilityStateComputer.getImePolicy().isImeHiddenByDisplayPolicy()) {
hideCurrentInputLocked(mCurFocusedWindow, null /* statsToken */, 0 /* flags */,
null /* resultReceiver */,
SoftInputShowHideReason.HIDE_DISPLAY_IME_POLICY_HIDE);
return InputBindResult.NO_IME;
}
mImeHiddenByDisplayPolicy = false;
if (mCurClient != cs) {
prepareClientSwitchLocked(cs);
@@ -3385,6 +3331,11 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
}
}
@GuardedBy("ImfLock.class")
void setRequestImeTokenToWindow(IBinder windowToken, IBinder token) {
mVisibilityStateComputer.setRequestImeTokenToWindow(windowToken, token);
}
@BinderThread
@Override
public void reportPerceptibleAsync(IBinder windowToken, boolean perceptible) {
@@ -3419,18 +3370,11 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
ImeTracker.ORIGIN_SERVER_START_INPUT, reason);
}
// TODO(b/246309664): make mShowRequested as per-window state.
mShowRequested = true;
if (mAccessibilityRequestingNoSoftKeyboard || mImeHiddenByDisplayPolicy) {
ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_ACCESSIBILITY);
return false;
}
ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_ACCESSIBILITY);
if ((flags & InputMethodManager.SHOW_FORCED) != 0) {
mShowExplicitlyRequested = true;
mShowForced = true;
} else if ((flags & InputMethodManager.SHOW_IMPLICIT) == 0) {
mShowExplicitlyRequested = true;
if (!mVisibilityStateComputer.onImeShowFlags(statsToken, flags)) {
return false;
}
if (!mSystemReady) {
@@ -3439,39 +3383,25 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
}
ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_SYSTEM_READY);
mVisibilityStateComputer.requestImeVisibility(windowToken, true);
// Ensure binding the connection when IME is going to show.
mBindingController.setCurrentMethodVisible();
final IInputMethodInvoker curMethod = getCurMethodLocked();
ImeTracker.get().onCancelled(mCurStatsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
if (curMethod != null) {
// create a placeholder token for IMS so that IMS cannot inject windows into client app.
Binder showInputToken = new Binder();
mShowRequestWindowMap.put(showInputToken, windowToken);
ImeTracker.get().onCancelled(mCurStatsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_HAS_IME);
mCurStatsToken = null;
final int showFlags = getImeShowFlagsLocked();
if (DEBUG) {
Slog.v(TAG, "Calling " + curMethod + ".showSoftInput(" + showInputToken
+ ", " + showFlags + ", " + resultReceiver + ") for reason: "
+ InputMethodDebug.softInputDisplayReasonToString(reason));
}
if (lastClickToolType != MotionEvent.TOOL_TYPE_UNKNOWN) {
curMethod.updateEditorToolType(lastClickToolType);
}
// TODO(b/192412909): Check if we can always call onShowHideSoftInputRequested() or not.
if (curMethod.showSoftInput(showInputToken, statsToken, showFlags, resultReceiver)) {
if (DEBUG_IME_VISIBILITY) {
EventLog.writeEvent(IMF_SHOW_IME, statsToken.getTag(),
Objects.toString(mCurFocusedWindow),
InputMethodDebug.softInputDisplayReasonToString(reason),
InputMethodDebug.softInputModeToString(mCurFocusedWindowSoftInputMode));
}
onShowHideSoftInputRequested(true /* show */, windowToken, reason, statsToken);
}
mVisibilityApplier.performShowIme(windowToken, statsToken,
mVisibilityStateComputer.getImeShowFlags(), resultReceiver, reason);
// TODO(b/246309664): make mInputShown tracked by the Ime visibility computer.
mInputShown = true;
return true;
} else {
ImeTracker.get().onCancelled(mCurStatsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
mCurStatsToken = statsToken;
}
@@ -3527,20 +3457,9 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
ImeTracker.ORIGIN_SERVER_HIDE_INPUT, 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");
ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_HIDE_IMPLICIT);
if (!mVisibilityStateComputer.canHideIme(statsToken, flags)) {
return false;
}
ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_HIDE_IMPLICIT);
if (mShowForced && (flags & InputMethodManager.HIDE_NOT_ALWAYS) != 0) {
if (DEBUG) Slog.v(TAG, "Not hiding: forced show not cancelled by not-always hide");
ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_HIDE_NOT_ALWAYS);
return false;
}
ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_HIDE_NOT_ALWAYS);
// There is a chance that IMM#hideSoftInput() is called in a transient state where
// IMMS#InputShown is already updated to be true whereas IMMS#mImeWindowVis is still waiting
@@ -3549,49 +3468,30 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
// application process as a valid request, and have even promised such a behavior with CTS
// since Android Eclair. That's why we need to accept IMM#hideSoftInput() even when only
// IMMS#InputShown indicates that the software keyboard is shown.
// TODO: Clean up, IMMS#mInputShown, IMMS#mImeWindowVis and mShowRequested.
// TODO(b/246309664): Clean up, IMMS#mInputShown, IMMS#mImeWindowVis and mShowRequested.
IInputMethodInvoker curMethod = getCurMethodLocked();
final boolean shouldHideSoftInput = (curMethod != null)
&& (mInputShown || (mImeWindowVis & InputMethodService.IME_ACTIVE) != 0);
boolean res;
mVisibilityStateComputer.requestImeVisibility(windowToken, false);
if (shouldHideSoftInput) {
final Binder hideInputToken = new Binder();
mHideRequestWindowMap.put(hideInputToken, windowToken);
// The IME will report its visible state again after the following message finally
// 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.
ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_SHOULD_HIDE);
if (DEBUG) {
Slog.v(TAG, "Calling " + curMethod + ".hideSoftInput(0, " + hideInputToken
+ ", " + resultReceiver + ") for reason: "
+ InputMethodDebug.softInputDisplayReasonToString(reason));
}
// TODO(b/192412909): Check if we can always call onShowHideSoftInputRequested() or not.
if (curMethod.hideSoftInput(hideInputToken, statsToken, 0 /* flags */,
resultReceiver)) {
if (DEBUG_IME_VISIBILITY) {
EventLog.writeEvent(IMF_HIDE_IME, statsToken.getTag(),
Objects.toString(mCurFocusedWindow),
InputMethodDebug.softInputDisplayReasonToString(reason),
InputMethodDebug.softInputModeToString(mCurFocusedWindowSoftInputMode));
}
onShowHideSoftInputRequested(false /* show */, windowToken, reason, statsToken);
}
res = true;
mVisibilityApplier.performHideIme(windowToken, statsToken, resultReceiver, reason);
} else {
ImeTracker.get().onCancelled(statsToken, ImeTracker.PHASE_SERVER_SHOULD_HIDE);
res = false;
}
mBindingController.setCurrentMethodNotVisible();
mVisibilityStateComputer.clearImeShowFlags();
mInputShown = false;
mShowRequested = false;
mShowExplicitlyRequested = false;
mShowForced = false;
// Cancel existing statsToken for show IME as we got a hide request.
ImeTracker.get().onCancelled(mCurStatsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
mCurStatsToken = null;
return res;
return shouldHideSoftInput;
}
private boolean isImeClientFocused(IBinder windowToken, ClientState cs) {
@@ -3738,8 +3638,9 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
// In case mShowForced flag affects the next client to keep IME visible, when the current
// client is leaving due to the next focused client, we clear mShowForced flag when the
// next client's targetSdkVersion is T or higher.
if (mCurFocusedWindow != windowToken && mShowForced && shouldClearFlag) {
mShowForced = false;
final boolean showForced = mVisibilityStateComputer.mShowForced;
if (mCurFocusedWindow != windowToken && showForced && shouldClearFlag) {
mVisibilityStateComputer.mShowForced = false;
}
// cross-profile access is always allowed here to allow profile-switching.
@@ -3763,6 +3664,12 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
final boolean startInputByWinGainedFocus =
(startInputFlags & StartInputFlags.WINDOW_GAINED_FOCUS) != 0;
// Init the focused window state (e.g. whether the editor has focused or IME focus has
// changed from another window).
final ImeTargetWindowState windowState = new ImeTargetWindowState(
softInputMode, !sameWindowFocused, isTextEditor);
mVisibilityStateComputer.setWindowState(windowToken, windowState);
if (sameWindowFocused && isTextEditor) {
if (DEBUG) {
Slog.w(TAG, "Window already focused, ignoring focus gain of: " + client
@@ -3812,7 +3719,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
// Because the app might leverage these flags to hide soft-keyboard with showing their own
// UI for input.
if (isTextEditor && editorInfo != null
&& shouldRestoreImeVisibility(windowToken, softInputMode)) {
&& mVisibilityStateComputer.shouldRestoreImeVisibility(windowState)) {
if (DEBUG) Slog.v(TAG, "Will show input to restore visibility");
res = startInputUncheckedLocked(cs, inputContext, remoteAccessibilityInputConnection,
editorInfo, startInputFlags, startInputReason, unverifiedTargetSdkVersion,
@@ -4001,19 +3908,6 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
return true;
}
private boolean shouldRestoreImeVisibility(IBinder windowToken,
@SoftInputModeFlags int softInputMode) {
switch (softInputMode & LayoutParams.SOFT_INPUT_MASK_STATE) {
case LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN:
return false;
case LayoutParams.SOFT_INPUT_STATE_HIDDEN:
if ((softInputMode & LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
return false;
}
}
return mWindowManagerInternal.shouldRestoreImeVisibility(windowToken);
}
@GuardedBy("ImfLock.class")
private boolean canShowInputMethodPickerLocked(IInputMethodClient client) {
final int uid = Binder.getCallingUid();
@@ -4746,8 +4640,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
}
proto.write(CUR_ID, getCurIdLocked());
proto.write(SHOW_REQUESTED, mShowRequested);
proto.write(SHOW_EXPLICITLY_REQUESTED, mShowExplicitlyRequested);
proto.write(SHOW_FORCED, mShowForced);
mVisibilityStateComputer.dumpDebug(proto, fieldId);
proto.write(INPUT_SHOWN, mInputShown);
proto.write(IN_FULLSCREEN_MODE, mInFullscreenMode);
proto.write(CUR_TOKEN, Objects.toString(getCurTokenLocked()));
@@ -4760,8 +4653,6 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
proto.write(BACK_DISPOSITION, mBackDisposition);
proto.write(IME_WINDOW_VISIBILITY, mImeWindowVis);
proto.write(SHOW_IME_WITH_HARD_KEYBOARD, mMenuController.getShowImeWithHardKeyboard());
proto.write(ACCESSIBILITY_REQUESTING_NO_SOFT_KEYBOARD,
mAccessibilityRequestingNoSoftKeyboard);
proto.end(token);
}
}
@@ -4795,25 +4686,10 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_APPLY_IME_VISIBILITY);
return;
}
if (!setVisible) {
if (mCurClient != null) {
ImeTracker.get().onProgress(statsToken,
ImeTracker.PHASE_SERVER_APPLY_IME_VISIBILITY);
mWindowManagerInternal.hideIme(
mHideRequestWindowMap.get(windowToken),
mCurClient.mSelfReportedDisplayId, statsToken);
} else {
ImeTracker.get().onFailed(statsToken,
ImeTracker.PHASE_SERVER_APPLY_IME_VISIBILITY);
}
} else {
ImeTracker.get().onProgress(statsToken,
ImeTracker.PHASE_SERVER_APPLY_IME_VISIBILITY);
// Send to window manager to show IME after IME layout finishes.
mWindowManagerInternal.showImePostLayout(mShowRequestWindowMap.get(windowToken),
statsToken);
}
final IBinder requestToken = mVisibilityStateComputer.getWindowTokenFrom(windowToken);
mVisibilityApplier.applyImeVisibility(requestToken, statsToken,
setVisible ? ImeVisibilityStateComputer.STATE_SHOW_IME
: ImeVisibilityStateComputer.STATE_HIDE_IME);
}
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
@@ -4857,7 +4733,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
/** Called right after {@link com.android.internal.inputmethod.IInputMethod#showSoftInput}. */
@GuardedBy("ImfLock.class")
private void onShowHideSoftInputRequested(boolean show, IBinder requestToken,
void onShowHideSoftInputRequested(boolean show, IBinder requestToken,
@SoftInputShowHideReason int reason, @Nullable ImeTracker.Token statsToken) {
final WindowManagerInternal.ImeTargetInfo info =
mWindowManagerInternal.onToggleImeRequested(
@@ -5988,14 +5864,11 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
method = getCurMethodLocked();
p.println(" mCurMethod=" + getCurMethodLocked());
p.println(" mEnabledSession=" + mEnabledSession);
p.println(" mShowRequested=" + mShowRequested
+ " mShowExplicitlyRequested=" + mShowExplicitlyRequested
+ " mShowForced=" + mShowForced
+ " mInputShown=" + mInputShown);
p.println(" mShowRequested=" + mShowRequested + " mInputShown=" + mInputShown);
mVisibilityStateComputer.dump(pw);
p.println(" mInFullscreenMode=" + mInFullscreenMode);
p.println(" mSystemReady=" + mSystemReady + " mInteractive=" + mIsInteractive);
p.println(" mSettingsObserver=" + mSettingsObserver);
p.println(" mImeHiddenByDisplayPolicy=" + mImeHiddenByDisplayPolicy);
p.println(" mStylusIds=" + (mStylusIds != null
? Arrays.toString(mStylusIds.toArray()) : ""));
p.println(" mSwitchingController:");