InputConnection mStartedInputConnection;
EditorInfo mInputEditorInfo;
- /**
- * A token to keep tracking the last IPC that triggered
- * {@link #doStartInput(InputConnection, EditorInfo, boolean)}. If
- * {@link #doStartInput(InputConnection, EditorInfo, boolean)} was not caused by IPCs from
- * {@link com.android.server.InputMethodManagerService}, this needs to remain unchanged.
- *
- * <p>Some IPCs to {@link com.android.server.InputMethodManagerService} require this token to
- * disentangle event flows for various purposes such as better window animation and providing
- * fine-grained debugging information.</p>
- */
- @Nullable
- private IBinder mStartInputToken;
-
int mShowInputFlags;
boolean mShowInputRequested;
boolean mLastShowInputRequested;
public void dispatchStartInputWithToken(@Nullable InputConnection inputConnection,
@NonNull EditorInfo editorInfo, boolean restarting,
@NonNull IBinder startInputToken) {
- mStartInputToken = startInputToken;
+ mImm.reportStartInput(mToken, startInputToken);
// This needs to be dispatched to interface methods rather than doStartInput().
// Otherwise IME developers who have overridden those interface methods will lose
}
clearInsetOfPreviousIme();
// If user uses hard keyboard, IME button should always be shown.
- mImm.setImeWindowStatus(mToken, mStartInputToken,
- mapToImeWindowStatus(isInputViewShown()), mBackDisposition);
+ mImm.setImeWindowStatus(mToken, mapToImeWindowStatus(isInputViewShown()),
+ mBackDisposition);
if (resultReceiver != null) {
resultReceiver.send(wasVis != isInputViewShown()
? InputMethodManager.RESULT_SHOWN
}
// If user uses hard keyboard, IME button should always be shown.
boolean showing = onEvaluateInputViewShown();
- mImm.setImeWindowStatus(mToken, mStartInputToken,
- IME_ACTIVE | (showing ? IME_VISIBLE : 0), mBackDisposition);
+ mImm.setImeWindowStatus(mToken, IME_ACTIVE | (showing ? IME_VISIBLE : 0),
+ mBackDisposition);
}
}
return;
}
mBackDisposition = disposition;
- mImm.setImeWindowStatus(mToken, mStartInputToken, mapToImeWindowStatus(isInputViewShown()),
- mBackDisposition);
+ mImm.setImeWindowStatus(mToken, mapToImeWindowStatus(isInputViewShown()), mBackDisposition);
}
/**
final int nextImeWindowStatus = mapToImeWindowStatus(isInputViewShown());
if (previousImeWindowStatus != nextImeWindowStatus) {
- mImm.setImeWindowStatus(mToken, mStartInputToken, nextImeWindowStatus,
- mBackDisposition);
+ mImm.setImeWindowStatus(mToken, nextImeWindowStatus, mBackDisposition);
}
if ((previousImeWindowStatus & IME_ACTIVE) == 0) {
if (DEBUG) Log.v(TAG, "showWindow: showing!");
}
private void doHideWindow() {
- mImm.setImeWindowStatus(mToken, mStartInputToken, 0, mBackDisposition);
+ mImm.setImeWindowStatus(mToken, 0, mBackDisposition);
hideWindow();
}
p.println(" mInputStarted=" + mInputStarted
+ " mInputViewStarted=" + mInputViewStarted
+ " mCandidatesViewStarted=" + mCandidatesViewStarted);
- p.println(" mStartInputToken=" + mStartInputToken);
if (mInputEditorInfo != null) {
p.println(" mInputEditorInfo:");
}
/** @hide */
- public void setImeWindowStatus(IBinder imeToken, IBinder startInputToken, int vis,
- int backDisposition) {
+ public void setImeWindowStatus(IBinder imeToken, int vis, int backDisposition) {
try {
- mService.setImeWindowStatus(imeToken, startInputToken, vis, backDisposition);
+ mService.setImeWindowStatus(imeToken, vis, backDisposition);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /** @hide */
+ public void reportStartInput(IBinder imeToken, IBinder startInputToken) {
+ try {
+ mService.reportStartInput(imeToken, startInputToken);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
void hideMySoftInput(in IBinder token, int flags);
void showMySoftInput(in IBinder token, int flags);
void updateStatusIcon(in IBinder token, String packageName, int iconId);
- void setImeWindowStatus(in IBinder token, in IBinder startInputToken, int vis,
- int backDisposition);
+ void setImeWindowStatus(in IBinder token, int vis, int backDisposition);
+ void reportStartInput(in IBinder token, in IBinder startInputToken);
void registerSuggestionSpansForNotification(in SuggestionSpan[] spans);
boolean notifySuggestionPicked(in SuggestionSpan span, String originalString, int index);
InputMethodSubtype getCurrentInputMethodSubtype();
IBinder mCurFocusedWindow;
/**
+ * The last window token that we confirmed that IME started talking to. This is always updated
+ * upon reports from the input method. If the window state is already changed before the report
+ * is handled, this field just keeps the last value.
+ */
+ IBinder mLastImeTargetWindow;
+
+ /**
* {@link WindowManager.LayoutParams#softInputMode} of {@link #mCurFocusedWindow}.
*
* @see #mCurFocusedWindow
}
@GuardedBy("mMethodMap")
- private final WeakHashMap<IBinder, StartInputInfo> mStartInputMap = new WeakHashMap<>();
+ private final WeakHashMap<IBinder, IBinder> mImeTargetWindowMap = new WeakHashMap<>();
/**
* A ring buffer to store the history of {@link StartInputInfo}.
final StartInputInfo info = new StartInputInfo(mCurToken, mCurId, startInputReason,
!initial, mCurFocusedWindow, mCurAttribute, mCurFocusedWindowSoftInputMode,
mCurSeq);
- mStartInputMap.put(startInputToken, info);
+ mImeTargetWindowMap.put(startInputToken, mCurFocusedWindow);
mStartInputHistory.addEntry(info);
final SessionState session = mCurClient.curSession;
@BinderThread
@SuppressWarnings("deprecation")
@Override
- public void setImeWindowStatus(IBinder token, IBinder startInputToken, int vis,
- int backDisposition) {
+ public void setImeWindowStatus(IBinder token, int vis, int backDisposition) {
if (!calledWithValidToken(token)) {
return;
}
- final StartInputInfo info;
synchronized (mMethodMap) {
- info = mStartInputMap.get(startInputToken);
mImeWindowVis = vis;
mBackDisposition = backDisposition;
updateSystemUiLocked(token, vis, backDisposition);
break;
}
mWindowManagerInternal.updateInputMethodWindowStatus(token,
- (vis & InputMethodService.IME_VISIBLE) != 0,
- dismissImeOnBackKeyPressed, info != null ? info.mTargetWindow : null);
+ (vis & InputMethodService.IME_VISIBLE) != 0, dismissImeOnBackKeyPressed);
}
private void updateSystemUi(IBinder token, int vis, int backDisposition) {
}
}
+ @BinderThread
+ @Override
+ public void reportStartInput(IBinder token, IBinder startInputToken) {
+ if (!calledWithValidToken(token)) {
+ return;
+ }
+
+ synchronized (mMethodMap) {
+ final IBinder targetWindow = mImeTargetWindowMap.get(startInputToken);
+ if (targetWindow != null && mLastImeTargetWindow != targetWindow) {
+ mWindowManagerInternal.updateInputMethodTargetWindow(token, targetWindow);
+ }
+ mLastImeTargetWindow = targetWindow;
+ }
+ }
+
// Caution! This method is called in this class. Handle multi-user carefully
private void updateSystemUiLocked(IBinder token, int vis, int backDisposition) {
if (!calledWithValidToken(token)) {
* to be synchronized with state in WindowManagerService.
* @param dismissImeOnBackKeyPressed {@code true} if the software keyboard is shown and the back
* key is expected to dismiss the software keyboard.
- * @param targetWindowToken token to identify the target window that the IME is associated with.
- * {@code null} when application, system, or the IME itself decided to
- * change its window visibility before being associated with any target
- * window.
*/
public abstract void updateInputMethodWindowStatus(@NonNull IBinder imeToken,
- boolean imeWindowVisible, boolean dismissImeOnBackKeyPressed,
- @Nullable IBinder targetWindowToken);
+ boolean imeWindowVisible, boolean dismissImeOnBackKeyPressed);
+
+ /**
+ * Notifies WindowManagerService that the current IME window status is being changed.
+ *
+ * <p>Only {@link com.android.server.InputMethodManagerService} is the expected and tested
+ * caller of this method.</p>
+ *
+ * @param imeToken token to track the active input method. Corresponding IME windows can be
+ * identified by checking {@link android.view.WindowManager.LayoutParams#token}.
+ * Note that there is no guarantee that the corresponding window is already
+ * created
+ * @param imeTargetWindowToken token to identify the target window that the IME is associated
+ * with
+ */
+ public abstract void updateInputMethodTargetWindow(@NonNull IBinder imeToken,
+ @NonNull IBinder imeTargetWindowToken);
/**
* Returns true when the hardware keyboard is available.
@Override
public void updateInputMethodWindowStatus(@NonNull IBinder imeToken,
- boolean imeWindowVisible, boolean dismissImeOnBackKeyPressed,
- @Nullable IBinder targetWindowToken) {
+ boolean imeWindowVisible, boolean dismissImeOnBackKeyPressed) {
+ mPolicy.setDismissImeOnBackKeyPressed(dismissImeOnBackKeyPressed);
+ }
+
+ @Override
+ public void updateInputMethodTargetWindow(@NonNull IBinder imeToken,
+ @NonNull IBinder imeTargetWindowToken) {
// TODO (b/34628091): Use this method to address the window animation issue.
if (DEBUG_INPUT_METHOD) {
- Slog.w(TAG_WM, "updateInputMethodWindowStatus: imeToken=" + imeToken
- + " dismissImeOnBackKeyPressed=" + dismissImeOnBackKeyPressed
- + " imeWindowVisible=" + imeWindowVisible
- + " targetWindowToken=" + targetWindowToken);
+ Slog.w(TAG_WM, "updateInputMethodTargetWindow: imeToken=" + imeToken
+ + " imeTargetWindowToken=" + imeTargetWindowToken);
}
- mPolicy.setDismissImeOnBackKeyPressed(dismissImeOnBackKeyPressed);
}
@Override