summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config/boot-image-profile.txt3
-rw-r--r--core/java/android/inputmethodservice/IInputMethodWrapper.java8
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java23
-rw-r--r--core/java/android/view/inputmethod/InputMethod.java14
-rw-r--r--core/java/com/android/internal/view/IInputMethod.aidl2
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java52
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java4
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java28
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java21
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerInternal.java9
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java123
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java2
13 files changed, 202 insertions, 89 deletions
diff --git a/config/boot-image-profile.txt b/config/boot-image-profile.txt
index 04b33b18dce4..731440b2fdda 100644
--- a/config/boot-image-profile.txt
+++ b/config/boot-image-profile.txt
@@ -24288,7 +24288,6 @@ HSPLandroid/inputmethodservice/AbstractInputMethodService;->onCreateInputMethodS
HSPLandroid/inputmethodservice/IInputMethodSessionWrapper;->getInternalInputMethodSession()Landroid/view/inputmethod/InputMethodSession;
HSPLandroid/inputmethodservice/IInputMethodWrapper$InputMethodSessionCallbackWrapper;->sessionCreated(Landroid/view/inputmethod/InputMethodSession;)V
HSPLandroid/inputmethodservice/IInputMethodWrapper;-><init>(Landroid/inputmethodservice/AbstractInputMethodService;Landroid/view/inputmethod/InputMethod;)V
-HSPLandroid/inputmethodservice/IInputMethodWrapper;->attachToken(Landroid/os/IBinder;)V
HSPLandroid/inputmethodservice/IInputMethodWrapper;->bindInput(Landroid/view/inputmethod/InputBinding;)V
HSPLandroid/inputmethodservice/IInputMethodWrapper;->createSession(Landroid/view/InputChannel;Lcom/android/internal/view/IInputSessionCallback;)V
HSPLandroid/inputmethodservice/IInputMethodWrapper;->executeMessage(Landroid/os/Message;)V
@@ -42280,11 +42279,9 @@ HSPLcom/android/internal/view/IInputContextCallback;->setSelectedText(Ljava/lang
HSPLcom/android/internal/view/IInputContextCallback;->setTextAfterCursor(Ljava/lang/CharSequence;I)V
HSPLcom/android/internal/view/IInputContextCallback;->setTextBeforeCursor(Ljava/lang/CharSequence;I)V
HSPLcom/android/internal/view/IInputMethod$Stub$Proxy;->asBinder()Landroid/os/IBinder;
-HSPLcom/android/internal/view/IInputMethod$Stub$Proxy;->attachToken(Landroid/os/IBinder;)V
HSPLcom/android/internal/view/IInputMethod$Stub;-><init>()V
HSPLcom/android/internal/view/IInputMethod$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/view/IInputMethod;
HSPLcom/android/internal/view/IInputMethod$Stub;->onTransact(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z
-HSPLcom/android/internal/view/IInputMethod;->attachToken(Landroid/os/IBinder;)V
HSPLcom/android/internal/view/IInputMethod;->bindInput(Landroid/view/inputmethod/InputBinding;)V
HSPLcom/android/internal/view/IInputMethod;->changeInputMethodSubtype(Landroid/view/inputmethod/InputMethodSubtype;)V
HSPLcom/android/internal/view/IInputMethod;->createSession(Landroid/view/InputChannel;Lcom/android/internal/view/IInputSessionCallback;)V
diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java
index 4080ee625a0f..103069474445 100644
--- a/core/java/android/inputmethodservice/IInputMethodWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java
@@ -160,11 +160,10 @@ class IInputMethodWrapper extends IInputMethod.Stub
args.recycle();
return;
}
-
case DO_INITIALIZE_INTERNAL: {
SomeArgs args = (SomeArgs) msg.obj;
try {
- inputMethod.initializeInternal((IBinder) args.arg1,
+ inputMethod.initializeInternal((IBinder) args.arg1, msg.arg1,
(IInputMethodPrivilegedOperations) args.arg2);
} finally {
args.recycle();
@@ -253,9 +252,10 @@ class IInputMethodWrapper extends IInputMethod.Stub
@BinderThread
@Override
- public void initializeInternal(IBinder token, IInputMethodPrivilegedOperations privOps) {
+ public void initializeInternal(IBinder token, int displayId,
+ IInputMethodPrivilegedOperations privOps) {
mCaller.executeOrSendMessage(
- mCaller.obtainMessageOO(DO_INITIALIZE_INTERNAL, token, privOps));
+ mCaller.obtainMessageIOO(DO_INITIALIZE_INTERNAL, displayId, token, privOps));
}
@BinderThread
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 2d12b867949a..34fa5b6b9842 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -16,6 +16,7 @@
package android.inputmethodservice;
+import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
@@ -461,10 +462,11 @@ public class InputMethodService extends AbstractInputMethodService {
*/
@MainThread
@Override
- public final void initializeInternal(IBinder token,
+ public final void initializeInternal(IBinder token, int displayId,
IInputMethodPrivilegedOperations privilegedOperations) {
mPrivOps.set(privilegedOperations);
mImm.registerInputMethodPrivOps(token, mPrivOps);
+ updateInputMethodDisplay(displayId);
attachToken(token);
}
@@ -484,6 +486,22 @@ public class InputMethodService extends AbstractInputMethodService {
/**
* {@inheritDoc}
+ * @hide
+ */
+ @MainThread
+ @Override
+ public void updateInputMethodDisplay(int displayId) {
+ // Update display for adding IME window to the right display.
+ if (displayId != DEFAULT_DISPLAY) {
+ // TODO(b/111364446) Need to address context lifecycle issue if need to re-create
+ // for update resources & configuration correctly when show soft input
+ // in non-default display.
+ updateDisplay(displayId);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
*
* <p>Calls {@link InputMethodService#onBindInput()} when done.</p>
*/
@@ -930,6 +948,9 @@ public class InputMethodService extends AbstractInputMethodService {
// If the previous IME has occupied non-empty inset in the screen, we need to decide whether
// we continue to use the same size of the inset or update it
mShouldClearInsetOfPreviousIme = (mImm.getInputMethodWindowVisibleHeight() > 0);
+ // TODO(b/111364446) Need to address context lifecycle issue if need to re-create
+ // for update resources & configuration correctly when show soft input
+ // in non-default display.
mInflater = (LayoutInflater)getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
mWindow = new SoftInputWindow(this, "InputMethod", mTheme, null, null, mDispatcherState,
diff --git a/core/java/android/view/inputmethod/InputMethod.java b/core/java/android/view/inputmethod/InputMethod.java
index f45507c2b8b3..e1600c4a92c8 100644
--- a/core/java/android/view/inputmethod/InputMethod.java
+++ b/core/java/android/view/inputmethod/InputMethod.java
@@ -89,14 +89,17 @@ public interface InputMethod {
*
* @param token special token for the system to identify
* {@link InputMethodService}
+ * @param displayId The id of the display that current IME shown.
+ * Used for {{@link #updateInputMethodDisplay(int)}}
* @param privilegedOperations IPC endpoint to do some privileged
* operations that are allowed only to the
* current IME.
* @hide
*/
@MainThread
- default void initializeInternal(IBinder token,
+ default void initializeInternal(IBinder token, int displayId,
IInputMethodPrivilegedOperations privilegedOperations) {
+ updateInputMethodDisplay(displayId);
attachToken(token);
}
@@ -115,6 +118,15 @@ public interface InputMethod {
public void attachToken(IBinder token);
/**
+ * Update context display according to given displayId.
+ *
+ * @param displayId The id of the display that need to update for context.
+ * @hide
+ */
+ @MainThread
+ public void updateInputMethodDisplay(int displayId);
+
+ /**
* Bind a new application environment in to the input method, so that it
* can later start and stop input processing.
* Typically this method is called when this input method is enabled in an
diff --git a/core/java/com/android/internal/view/IInputMethod.aidl b/core/java/com/android/internal/view/IInputMethod.aidl
index b6a654aac563..97d5a657e5c4 100644
--- a/core/java/com/android/internal/view/IInputMethod.aidl
+++ b/core/java/com/android/internal/view/IInputMethod.aidl
@@ -33,7 +33,7 @@ import com.android.internal.view.IInputSessionCallback;
* {@hide}
*/
oneway interface IInputMethod {
- void initializeInternal(IBinder token, IInputMethodPrivilegedOperations privOps);
+ void initializeInternal(IBinder token, int displayId, IInputMethodPrivilegedOperations privOps);
void bindInput(in InputBinding binding);
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 49f33e09a724..44fb9ea91dee 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -16,6 +16,7 @@
package com.android.server.inputmethod;
import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.INVALID_DISPLAY;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
@@ -572,6 +573,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
IBinder mCurToken;
/**
+ * The displayId of current active input method.
+ */
+ int mCurTokenDisplayId = INVALID_DISPLAY;
+
+ /**
* If non-null, this is the input method service we are currently connected
* to.
*/
@@ -1866,7 +1872,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
mCurAttribute = attribute;
// Check if the input method is changing.
- if (mCurId != null && mCurId.equals(mCurMethodId)) {
+ final int displayId = mWindowManagerInternal.getDisplayIdForWindow(
+ mCurFocusedWindow);
+ if (mCurId != null && mCurId.equals(mCurMethodId) && displayId == mCurTokenDisplayId) {
if (cs.curSession != null) {
// Fast case: if we are already connected to the input method,
// then just return it.
@@ -1930,14 +1938,20 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
com.android.internal.R.string.input_method_binding_label);
mCurIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
mContext, 0, new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS), 0));
+ final int displayId = mWindowManagerInternal.getDisplayIdForWindow(mCurFocusedWindow);
+ mCurTokenDisplayId = (displayId != INVALID_DISPLAY) ? displayId : DEFAULT_DISPLAY;
+
if (bindCurrentInputMethodServiceLocked(mCurIntent, this, IME_CONNECTION_BIND_FLAGS)) {
mLastBindTime = SystemClock.uptimeMillis();
mHaveConnection = true;
mCurId = info.getId();
mCurToken = new Binder();
try {
- if (DEBUG) Slog.v(TAG, "Adding window token: " + mCurToken);
- mIWindowManager.addWindowToken(mCurToken, TYPE_INPUT_METHOD, DEFAULT_DISPLAY);
+ if (DEBUG) {
+ Slog.v(TAG, "Adding window token: " + mCurToken + " for display: "
+ + mCurTokenDisplayId);
+ }
+ mIWindowManager.addWindowToken(mCurToken, TYPE_INPUT_METHOD, mCurTokenDisplayId);
} catch (RemoteException e) {
}
return new InputBindResult(
@@ -1964,8 +1978,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
return;
}
if (DEBUG) Slog.v(TAG, "Initiating attach with token: " + mCurToken);
- executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
- MSG_INITIALIZE_IME, mCurMethod, mCurToken));
+ // Dispatch display id for InputMethodService to update context display.
+ executeOrSendMessage(mCurMethod, mCaller.obtainMessageIOO(
+ MSG_INITIALIZE_IME, mCurTokenDisplayId, mCurMethod, mCurToken));
if (mCurClient != null) {
clearClientSessionLocked(mCurClient);
requestClientSessionLocked(mCurClient);
@@ -2011,15 +2026,19 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
if (mCurToken != null) {
try {
- if (DEBUG) Slog.v(TAG, "Removing window token: " + mCurToken);
+ if (DEBUG) {
+ Slog.v(TAG, "Removing window token: " + mCurToken + " for display: "
+ + mCurTokenDisplayId);
+ }
if ((mImeWindowVis & InputMethodService.IME_ACTIVE) != 0 && savePosition) {
// The current IME is shown. Hence an IME switch (transition) is happening.
mWindowManagerInternal.saveLastInputMethodWindowForTransition();
}
- mIWindowManager.removeWindowToken(mCurToken, DEFAULT_DISPLAY);
+ mIWindowManager.removeWindowToken(mCurToken, mCurTokenDisplayId);
} catch (RemoteException e) {
}
mCurToken = null;
+ mCurTokenDisplayId = INVALID_DISPLAY;
}
mCurId = null;
@@ -2785,6 +2804,15 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
// soft input window if it is shown.
if (DEBUG) Slog.v(TAG, "Unspecified window will hide input");
hideCurrentInputLocked(InputMethodManager.HIDE_NOT_ALWAYS, null);
+
+ // If focused display changed, we should unbind current method
+ // to make app window in previous display relayout after Ime
+ // window token removed.
+ final int newFocusDisplayId =
+ mWindowManagerInternal.getDisplayIdForWindow(windowToken);
+ if (newFocusDisplayId != mCurTokenDisplayId) {
+ unbindCurrentMethodLocked(false);
+ }
}
} else if (isTextEditor && doAutoShow && (softInputMode &
WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
@@ -3151,7 +3179,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
*/
@Override
public int getInputMethodWindowVisibleHeight() {
- return mWindowManagerInternal.getInputMethodWindowVisibleHeight();
+ return mWindowManagerInternal.getInputMethodWindowVisibleHeight(mCurTokenDisplayId);
}
@BinderThread
@@ -3352,9 +3380,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
case MSG_INITIALIZE_IME:
args = (SomeArgs)msg.obj;
try {
- if (DEBUG) Slog.v(TAG, "Sending attach of token: " + args.arg2);
+ if (DEBUG) {
+ Slog.v(TAG, "Sending attach of token: " + args.arg2 + " for display: "
+ + msg.arg1);
+ }
final IBinder token = (IBinder) args.arg2;
- ((IInputMethod) args.arg1).initializeInternal(token,
+ ((IInputMethod) args.arg1).initializeInternal(token, msg.arg1,
new InputMethodPrivilegedOperationsImpl(this, token));
} catch (RemoteException e) {
}
@@ -4516,6 +4547,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
p.println(" mCurId=" + mCurId + " mHaveConnection=" + mHaveConnection
+ " mBoundToMethod=" + mBoundToMethod + " mVisibleBound=" + mVisibleBound);
p.println(" mCurToken=" + mCurToken);
+ p.println(" mCurTokenDisplayId=" + mCurTokenDisplayId);
p.println(" mCurIntent=" + mCurIntent);
method = mCurMethod;
p.println(" mCurMethod=" + mCurMethod);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 3e0429fd443e..350d6b66c1fb 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -4732,8 +4732,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
final WindowManager.LayoutParams attrs = win.getAttrs();
final boolean isDefaultDisplay = win.isDefaultDisplay();
- final boolean needsToOffsetInputMethodTarget = isDefaultDisplay &&
- (win == mLastInputMethodTargetWindow && mLastInputMethodWindow != null);
+ final boolean needsToOffsetInputMethodTarget =
+ (win == mLastInputMethodTargetWindow) && (mLastInputMethodWindow != null);
if (needsToOffsetInputMethodTarget) {
if (DEBUG_LAYOUT) Slog.i(TAG, "Offset ime target window by the last ime window state");
offsetInputMethodWindowLw(mLastInputMethodWindow, displayFrames);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index d3e534ce4522..5d0101f88c69 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -409,6 +409,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
private InputMonitor mInputMonitor;
+ /**
+ * The input method window for this display.
+ */
+ WindowState mInputMethodWindow;
+
private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> {
WindowStateAnimator winAnimator = w.mWinAnimator;
final AppWindowToken atoken = w.mAppToken;
@@ -2107,18 +2112,16 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
mTouchExcludeRegion.op(mTmpRect2, Region.Op.UNION);
}
}
- final WindowState inputMethod = mService.mInputMethodWindow;
- if (inputMethod != null && inputMethod.isVisibleLw()) {
+ if (mInputMethodWindow != null && mInputMethodWindow.isVisibleLw()) {
// If the input method is visible and the user is typing, we don't want these touch
// events to be intercepted and used to change focus. This would likely cause a
// disappearance of the input method.
- inputMethod.getTouchableRegion(mTmpRegion);
- if (inputMethod.getDisplayId() == mDisplayId) {
+ mInputMethodWindow.getTouchableRegion(mTmpRegion);
+ if (mInputMethodWindow.getDisplayId() == mDisplayId) {
mTouchExcludeRegion.op(mTmpRegion, Op.UNION);
} else {
// IME is on a different display, so we need to update its tap detector.
- // TODO(multidisplay): Remove when IME will always appear on same display.
- inputMethod.getDisplayContent().setTouchExcludeRegion(null /* focusedTask */);
+ setTouchExcludeRegion(null /* focusedTask */);
}
}
for (int i = mTapExcludedWindows.size() - 1; i >= 0; i--) {
@@ -2257,7 +2260,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
void adjustForImeIfNeeded() {
- final WindowState imeWin = mService.mInputMethodWindow;
+ final WindowState imeWin = mInputMethodWindow;
final boolean imeVisible = imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw()
&& !mDividerControllerLocked.isImeHideRequested();
final boolean dockVisible = isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
@@ -2640,12 +2643,21 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
/**
+ * Set input method window for the display.
+ * @param win Set when window added or Null when destroyed.
+ */
+ void setInputMethodWindowLocked(WindowState win) {
+ mInputMethodWindow = win;
+ computeImeTarget(true /* updateImeTarget */);
+ }
+
+ /**
* Determine and return the window that should be the IME target.
* @param updateImeTarget If true the system IME target will be updated to match what we found.
* @return The window that should be used as the IME target or null if there isn't any.
*/
WindowState computeImeTarget(boolean updateImeTarget) {
- if (mService.mInputMethodWindow == null) {
+ if (mInputMethodWindow == null) {
// There isn't an IME so there shouldn't be a target...That was easy!
if (updateImeTarget) {
if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from "
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 86b14337139e..d92818ac611c 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -681,10 +681,11 @@ class RootWindowContainer extends WindowContainer<DisplayContent> {
i--;
WindowState win = mService.mDestroySurface.get(i);
win.mDestroying = false;
- if (mService.mInputMethodWindow == win) {
- mService.setInputMethodWindowLocked(null);
+ final DisplayContent displayContent = win.getDisplayContent();
+ if (displayContent.mInputMethodWindow == win) {
+ displayContent.setInputMethodWindowLocked(null);
}
- if (win.getDisplayContent().mWallpaperController.isWallpaperTarget(win)) {
+ if (displayContent.mWallpaperController.isWallpaperTarget(win)) {
wallpaperDestroyed = true;
}
win.destroySurfaceUnchecked();
@@ -1113,4 +1114,18 @@ class RootWindowContainer extends WindowContainer<DisplayContent> {
callback.accept(mChildren.get(i));
}
}
+
+ /**
+ * Get current topmost focused IME window in system.
+ * Will look on all displays in current Z-order.
+ */
+ WindowState getCurrentInputMethodWindow() {
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ final DisplayContent displayContent = mChildren.get(i);
+ if (displayContent.mInputMethodWindow != null) {
+ return displayContent.mInputMethodWindow;
+ }
+ }
+ return null;
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index ac496a84f178..793ce6047323 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -335,9 +335,9 @@ public abstract class WindowManagerInternal {
public abstract void registerAppTransitionListener(AppTransitionListener listener);
/**
- * Retrieves a height of input method window.
+ * Retrieves a height of input method window for given display.
*/
- public abstract int getInputMethodWindowVisibleHeight();
+ public abstract int getInputMethodWindowVisibleHeight(int displayId);
/**
* Saves last input method window for transition.
@@ -447,4 +447,9 @@ public abstract class WindowManagerInternal {
* Returns {@code true} if a process that is identified by {@code client} has IME focus.
*/
public abstract boolean inputMethodClientHasFocus(IInputMethodClient client);
+
+ /**
+ * Return the display Id for given window.
+ */
+ public abstract int getDisplayIdForWindow(IBinder windowToken);
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 679e0d870d74..2ed09ae2daf3 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -650,8 +650,6 @@ public class WindowManagerService extends IWindowManager.Stub
/** If true hold off on modifying the animation layer of mInputMethodTarget */
boolean mInputMethodTargetWaitingAnim;
- WindowState mInputMethodWindow = null;
-
boolean mHardKeyboardAvailable;
WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
SettingsObserver mSettingsObserver;
@@ -1414,7 +1412,7 @@ public class WindowManagerService extends IWindowManager.Stub
win.mToken.addWindow(win);
if (type == TYPE_INPUT_METHOD) {
win.mGivenInsetsPending = true;
- setInputMethodWindowLocked(win);
+ displayContent.setInputMethodWindowLocked(win);
imMayMove = false;
} else if (type == TYPE_INPUT_METHOD_DIALOG) {
displayContent.computeImeTarget(true /* updateImeTarget */);
@@ -1687,8 +1685,9 @@ public class WindowManagerService extends IWindowManager.Stub
mWindowsChanged = true;
if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Final remove of window: " + win);
- if (mInputMethodWindow == win) {
- setInputMethodWindowLocked(null);
+ final DisplayContent displayContent = win.getDisplayContent();
+ if (displayContent.mInputMethodWindow == win) {
+ displayContent.setInputMethodWindowLocked(null);
}
final WindowToken token = win.mToken;
@@ -1733,13 +1732,6 @@ public class WindowManagerService extends IWindowManager.Stub
dc.getInputMonitor().updateInputWindowsLw(true /*force*/);
}
- void setInputMethodWindowLocked(WindowState win) {
- mInputMethodWindow = win;
- final DisplayContent dc = win != null
- ? win.getDisplayContent() : getDefaultDisplayContentLocked();
- dc.computeImeTarget(true /* updateImeTarget */);
- }
-
private void updateHiddenWhileSuspendedState(ArraySet<String> packages, boolean suspended) {
synchronized (mWindowMap) {
mRoot.updateHiddenWhileSuspendedState(packages, suspended);
@@ -2058,8 +2050,10 @@ public class WindowManagerService extends IWindowManager.Stub
if ((result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
focusMayChange = isDefaultDisplay;
}
- if (win.mAttrs.type == TYPE_INPUT_METHOD && mInputMethodWindow == null) {
- setInputMethodWindowLocked(win);
+ final DisplayContent displayContent = win.getDisplayContent();
+ if (win.mAttrs.type == TYPE_INPUT_METHOD
+ && displayContent.mInputMethodWindow == null) {
+ displayContent.setInputMethodWindowLocked(win);
imMayMove = true;
}
win.adjustStartingWindowFlags();
@@ -2222,8 +2216,9 @@ public class WindowManagerService extends IWindowManager.Stub
// of a transaction to avoid artifacts.
win.mAnimatingExit = true;
} else {
- if (mInputMethodWindow == win) {
- setInputMethodWindowLocked(null);
+ final DisplayContent displayContent = win.getDisplayContent();
+ if (displayContent.mInputMethodWindow == win) {
+ displayContent.setInputMethodWindowLocked(null);
}
boolean stopped = win.mAppToken != null ? win.mAppToken.mAppStopped : true;
// We set mDestroying=true so AppWindowToken#notifyAppStopped in-to destroy surfaces
@@ -2828,7 +2823,7 @@ public class WindowManagerService extends IWindowManager.Stub
@Override
public WindowManagerPolicy.WindowState getInputMethodWindowLw() {
- return mInputMethodWindow;
+ return mRoot.getCurrentInputMethodWindow();
}
@Override
@@ -5575,10 +5570,10 @@ public class WindowManagerService extends IWindowManager.Stub
// change message pending.
mH.removeMessages(H.REPORT_FOCUS_CHANGE);
mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
- // TODO(multidisplay): Focused windows on default display only.
- final DisplayContent displayContent = getDefaultDisplayContentLocked();
+ final DisplayContent displayContent = (newFocus != null) ? newFocus.getDisplayContent()
+ : getDefaultDisplayContentLocked();
boolean imWindowChanged = false;
- if (mInputMethodWindow != null) {
+ if (displayContent.mInputMethodWindow != null) {
final WindowState prevTarget = mInputMethodTarget;
final WindowState newTarget =
@@ -5587,10 +5582,11 @@ public class WindowManagerService extends IWindowManager.Stub
if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS
&& mode != UPDATE_FOCUS_WILL_PLACE_SURFACES) {
- final int prevImeAnimLayer = mInputMethodWindow.mWinAnimator.mAnimLayer;
+ final int prevImeAnimLayer =
+ displayContent.mInputMethodWindow.mWinAnimator.mAnimLayer;
displayContent.assignWindowLayers(false /* setLayoutNeeded */);
- imWindowChanged |=
- prevImeAnimLayer != mInputMethodWindow.mWinAnimator.mAnimLayer;
+ imWindowChanged |= prevImeAnimLayer
+ != displayContent.mInputMethodWindow.mWinAnimator.mAnimLayer;
}
}
@@ -5613,7 +5609,7 @@ public class WindowManagerService extends IWindowManager.Stub
int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
- if (imWindowChanged && oldFocus != mInputMethodWindow) {
+ if (imWindowChanged && oldFocus != displayContent.mInputMethodWindow) {
// Focus of the input method window changed. Perform layout if needed.
if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
displayContent.performLayout(true /*initial*/, updateInputWindows);
@@ -6033,8 +6029,15 @@ public class WindowManagerService extends IWindowManager.Stub
}
synchronized (mWindowMap) {
final Region r = new Region();
- if (mInputMethodWindow != null) {
- mInputMethodWindow.getTouchableRegion(r);
+ // TODO(b/111080190): this method is only return the recent focused IME touch region,
+ // For Multi-Session IME, will need to add API for given display Id to
+ // get the right IME touch region.
+ for (int i = mRoot.mChildren.size() - 1; i >= 0; --i) {
+ final DisplayContent displayContent = mRoot.mChildren.get(i);
+ if (displayContent.mInputMethodWindow != null) {
+ displayContent.mInputMethodWindow.getTouchableRegion(r);
+ return r;
+ }
}
return r;
}
@@ -6217,8 +6220,9 @@ public class WindowManagerService extends IWindowManager.Stub
if (mFocusedApp != null) {
mFocusedApp.writeNameToProto(proto, FOCUSED_APP);
}
- if (mInputMethodWindow != null) {
- mInputMethodWindow.writeIdentifierToProto(proto, INPUT_METHOD_WINDOW);
+ final WindowState imeWindow = mRoot.getCurrentInputMethodWindow();
+ if (imeWindow != null) {
+ imeWindow.writeIdentifierToProto(proto, INPUT_METHOD_WINDOW);
}
proto.write(DISPLAY_FROZEN, mDisplayFrozen);
final DisplayContent defaultDisplayContent = getDefaultDisplayContentLocked();
@@ -6388,8 +6392,9 @@ public class WindowManagerService extends IWindowManager.Stub
pw.print(" mLastStatusBarVisibility=0x");
pw.println(Integer.toHexString(mLastStatusBarVisibility));
}
- if (mInputMethodWindow != null) {
- pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow);
+ final WindowState imeWindow = mRoot.getCurrentInputMethodWindow();
+ if (imeWindow != null) {
+ pw.print(" mInputMethodWindow="); pw.println(imeWindow);
}
mWindowPlacerLocked.dump(pw, " ");
mRoot.mWallpaperController.dump(pw, " ");
@@ -7287,10 +7292,9 @@ public class WindowManagerService extends IWindowManager.Stub
}
@Override
- public int getInputMethodWindowVisibleHeight() {
+ public int getInputMethodWindowVisibleHeight(int displayId) {
synchronized (mWindowMap) {
- // TODO(multi-display): Have caller pass in the display they are interested in.
- final DisplayContent dc = getDefaultDisplayContentLocked();
+ final DisplayContent dc = mRoot.getDisplayContent(displayId);
return dc.mDisplayFrames.getInputMethodWindowVisibleHeight();
}
}
@@ -7298,8 +7302,9 @@ public class WindowManagerService extends IWindowManager.Stub
@Override
public void saveLastInputMethodWindowForTransition() {
synchronized (mWindowMap) {
- if (mInputMethodWindow != null) {
- mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget);
+ final WindowState imeWindow = mRoot.getCurrentInputMethodWindow();
+ if (imeWindow != null) {
+ mPolicy.setLastInputMethodWindowLw(imeWindow, mInputMethodTarget);
}
}
}
@@ -7406,28 +7411,42 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- @Override
- public boolean inputMethodClientHasFocus(IInputMethodClient client) {
- synchronized (mWindowMap) {
- // TODO: multi-display
- if (getDefaultDisplayContentLocked().inputMethodClientHasFocus(client)) {
+ public boolean inputMethodClientHasFocus(IInputMethodClient client) {
+ boolean hasFocus;
+ synchronized (mWindowMap) {
+ // Check all displays if any input method window has focus.
+ for (int i = mRoot.mChildren.size() - 1; i >= 0; --i) {
+ final DisplayContent displayContent = mRoot.mChildren.get(i);
+ if (displayContent.inputMethodClientHasFocus(client)) {
return true;
}
+ }
- // Okay, how about this... what is the current focus?
- // It seems in some cases we may not have moved the IM
- // target window, such as when it was in a pop-up window,
- // so let's also look at the current focus. (An example:
- // go to Gmail, start searching so the keyboard goes up,
- // press home. Sometimes the IME won't go down.)
- // Would be nice to fix this more correctly, but it's
- // way at the end of a release, and this should be good enough.
- if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null
- && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) {
- return true;
+ // Okay, how about this... what is the current focus?
+ // It seems in some cases we may not have moved the IM
+ // target window, such as when it was in a pop-up window,
+ // so let's also look at the current focus. (An example:
+ // go to Gmail, start searching so the keyboard goes up,
+ // press home. Sometimes the IME won't go down.)
+ // Would be nice to fix this more correctly, but it's
+ // way at the end of a release, and this should be good enough.
+ if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null
+ && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int getDisplayIdForWindow(IBinder windowToken) {
+ synchronized (mWindowMap) {
+ final WindowState window = mWindowMap.get(windowToken);
+ if (window != null) {
+ return window.getDisplayContent().getDisplayId();
}
+ return Display.INVALID_DISPLAY;
}
- return false;
}
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 110027962e72..5272b663c2aa 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -845,7 +845,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mWindowFrames.mContainingFrame.bottom =
mWindowFrames.mContainingFrame.top + frozen.height();
}
- final WindowState imeWin = mService.mInputMethodWindow;
+ final WindowState imeWin = mService.mRoot.getCurrentInputMethodWindow();
// IME is up and obscuring this window. Adjust the window position so it is visible.
if (imeWin != null && imeWin.isVisibleNow() && isInputMethodTarget()) {
if (inFreeformWindowingMode() && mWindowFrames.mContainingFrame.bottom
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index 5db0867298b0..70e4ce419e0a 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -125,7 +125,7 @@ class WindowTestsBase {
synchronized (sWm.mWindowMap) {
mWallpaperWindow = createCommonWindow(null, TYPE_WALLPAPER, "wallpaperWindow");
mImeWindow = createCommonWindow(null, TYPE_INPUT_METHOD, "mImeWindow");
- sWm.mInputMethodWindow = mImeWindow;
+ mDisplayContent.mInputMethodWindow = mImeWindow;
mImeDialogWindow = createCommonWindow(null, TYPE_INPUT_METHOD_DIALOG,
"mImeDialogWindow");
mStatusBarWindow = createCommonWindow(null, TYPE_STATUS_BAR, "mStatusBarWindow");