diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 7e09e63781815..bf05f5067328a 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -3536,7 +3536,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp if (updateImeTarget) { if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + mImeLayeringTarget + " to null since mInputMethodWindow is null"); - setImeLayeringTarget(null, mImeLayeringTargetWaitingAnim); + setImeLayeringTargetInner(null); } return null; } @@ -3553,41 +3553,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp mUpdateImeTarget = updateImeTarget; WindowState target = getWindow(mComputeImeTargetPredicate); - // Keeps the IME target with the last window while swiping up to recents to prevent - // flickering due to IME hide animation on top of recents. - // TODO(b/166736352): This logic should go away once we switch over target immediately - // and do the screenshot to preserve IME on disappearing target - if (target != null && curTarget != null && target.isActivityTypeHome() - && curTarget.getInsetsState().getSource(ITYPE_IME).isVisible()) { - return curTarget; - } - - // Yet more tricksyness! If this window is a "starting" window, we do actually want - // to be on top of it, but it is not -really- where input will go. So look down below - // for a real window to target... - if (target != null && target.mAttrs.type == TYPE_APPLICATION_STARTING) { - final ActivityRecord activity = target.mActivityRecord; - if (activity != null) { - final WindowState betterTarget = activity.getImeTargetBelowWindow(target); - if (betterTarget != null) { - target = betterTarget; - } - } - } - if (DEBUG_INPUT_METHOD && updateImeTarget) Slog.v(TAG_WM, "Proposed new IME target: " + target + " for display: " + getDisplayId()); - // Now, a special case -- if the last target's window is in the process of exiting, but - // not removed, keep on the last target to avoid IME flicker. The exception is if the - // current target is home since we want opening apps to become the IME target right away. - if (curTarget != null && !curTarget.mRemoved && curTarget.isDisplayed() - && curTarget.isClosing() && !curTarget.isActivityTypeHome()) { - if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Not changing target till current window is" - + " closing and not removed"); - return curTarget; - } - if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Desired input method target=" + target + " updateImeTarget=" + updateImeTarget); @@ -3596,42 +3564,16 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to null." + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : "")); - setImeLayeringTarget(null, mImeLayeringTargetWaitingAnim); + setImeLayeringTargetInner(null); } return null; } if (updateImeTarget) { - ActivityRecord activity = curTarget == null ? null : curTarget.mActivityRecord; - if (activity != null) { - - // Now some fun for dealing with window animations that modify the Z order. We need - // to look at all windows below the current target that are in this app, finding the - // highest visible one in layering. - WindowState highestTarget = null; - if (activity.isAnimating(PARENTS | TRANSITION)) { - highestTarget = activity.getHighestAnimLayerWindow(curTarget); - } - - if (highestTarget != null) { - if (DEBUG_INPUT_METHOD) { - Slog.v(TAG_WM, mAppTransition + " " + highestTarget + " animating=" - + highestTarget.isAnimating(TRANSITION | PARENTS)); - } - - if (mAppTransition.isTransitionSet()) { - // If we are currently setting up for an animation, hold everything until we - // can find out what will happen. - setImeLayeringTarget(highestTarget, true); - return highestTarget; - } - } - } - if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to " + target + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : "")); - setImeLayeringTarget(target, false); + setImeLayeringTargetInner(target); } return target; @@ -3733,11 +3675,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp * Sets the window the IME is on top of. * @param target window to place the IME surface on top of. If {@code null}, the IME will be * placed at its parent's surface. - * @param targetWaitingAnim if {@code true}, hold off on modifying the animation layer of - * the target. */ - private void setImeLayeringTarget(@Nullable WindowState target, boolean targetWaitingAnim) { - if (target == mImeLayeringTarget && mImeLayeringTargetWaitingAnim == targetWaitingAnim) { + private void setImeLayeringTargetInner(@Nullable WindowState target) { + if (target == mImeLayeringTarget) { return; } // Prepare the IME screenshot for the last IME target when its task is applying app @@ -3750,7 +3690,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp ProtoLog.i(WM_DEBUG_IME, "setInputMethodTarget %s", target); mImeLayeringTarget = target; - mImeLayeringTargetWaitingAnim = targetWaitingAnim; // 1. Reparent the IME container window to the target root DA to get the correct bounds and // config. (Only happens when the target window is in a different root DA) @@ -3762,13 +3701,12 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp targetRoot.placeImeContainer(mImeWindowsContainer); } } - // 2. Reparent the IME container surface to either the input target app, or the IME window - // parent. - updateImeParent(); - // 3. Assign window layers based on the IME surface parent to make sure it is on top of the + // 2. Assign window layers based on the IME surface parent to make sure it is on top of the // app. assignWindowLayers(true /* setLayoutNeeded */); - // 4. Update the IME control target to apply any inset change and animation. + // 3. Update the IME control target to apply any inset change and animation. + // 4. Reparent the IME container surface to either the input target app, or the IME window + // parent. updateImeControlTarget(); } @@ -3898,8 +3836,14 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } void updateImeControlTarget() { + InsetsControlTarget prevImeControlTarget = mImeControlTarget; mImeControlTarget = computeImeControlTarget(); mInsetsStateController.onImeControlTargetChanged(mImeControlTarget); + // Update Ime parent when IME insets leash created, which is the best time that default + // IME visibility has been settled down after IME control target changed. + if (prevImeControlTarget != mImeControlTarget) { + updateImeParent(); + } final WindowState win = InsetsControlTarget.asWindowOrNull(mImeControlTarget); final IBinder token = win != null ? win.mClient.asBinder() : null; diff --git a/services/core/java/com/android/server/wm/InputConsumerImpl.java b/services/core/java/com/android/server/wm/InputConsumerImpl.java index e35621a84b37d..4d0c75c61aabd 100644 --- a/services/core/java/com/android/server/wm/InputConsumerImpl.java +++ b/services/core/java/com/android/server/wm/InputConsumerImpl.java @@ -132,7 +132,7 @@ class InputConsumerImpl implements IBinder.DeathRecipient { t.hide(mInputSurface); } - void show(SurfaceControl.Transaction t, WindowState w) { + void show(SurfaceControl.Transaction t, WindowContainer w) { t.show(mInputSurface); t.setInputWindowInfo(mInputSurface, mWindowHandle); t.setRelativeLayer(mInputSurface, w.getSurfaceControl(), 1); diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java index cc77cfa1e8e5b..c2331a00193a6 100644 --- a/services/core/java/com/android/server/wm/InputMonitor.java +++ b/services/core/java/com/android/server/wm/InputMonitor.java @@ -516,7 +516,7 @@ final class InputMonitor { if (mAddRecentsAnimationInputConsumerHandle && shouldApplyRecentsInputConsumer) { if (recentsAnimationController.updateInputConsumerForApp( mRecentsAnimationInputConsumer.mWindowHandle)) { - mRecentsAnimationInputConsumer.show(mInputTransaction, w); + mRecentsAnimationInputConsumer.show(mInputTransaction, w.mActivityRecord); mAddRecentsAnimationInputConsumerHandle = false; } } diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java index 00b6cebbe32db..9b92a811892ea 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimationController.java +++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java @@ -282,6 +282,25 @@ public class RecentsAnimationController implements DeathRecipient { task.setCanAffectSystemUiFlags(behindSystemBars); } } + if (!behindSystemBars) { + // Make sure to update the correct IME parent in case that the IME parent + // may be computed as display layer when re-layout window happens during + // rotation but there is intermediate state that the bounds of task and + // the IME target's activity is not the same during rotating. + mDisplayContent.updateImeParent(); + + // Hiding IME if IME window is not attached to app. + // Since some windowing mode is not proper to snapshot Task with IME window + // while the app transitioning to the next task (e.g. split-screen mode) + if (!mDisplayContent.isImeAttachedToApp()) { + final InputMethodManagerInternal inputMethodManagerInternal = + LocalServices.getService(InputMethodManagerInternal.class); + if (inputMethodManagerInternal != null) { + inputMethodManagerInternal.hideCurrentInputMethod( + SoftInputShowHideReason.HIDE_RECENTS_ANIMATION); + } + } + } mService.mWindowPlacerLocked.requestTraversal(); } } finally { @@ -299,7 +318,6 @@ public class RecentsAnimationController implements DeathRecipient { if (mCanceled) { return; } - mInputConsumerEnabled = enabled; final InputMonitor inputMonitor = mDisplayContent.getInputMonitor(); inputMonitor.updateInputWindowsLw(true /*force*/); @@ -310,34 +328,9 @@ public class RecentsAnimationController implements DeathRecipient { } } + // TODO(b/166736352): Remove this method without the need to expose to launcher. @Override - public void hideCurrentInputMethod() { - final long token = Binder.clearCallingIdentity(); - try { - synchronized (mService.getWindowManagerLock()) { - // Make sure to update the correct IME parent in case that the IME parent may - // be computed as display layer when re-layout window happens during rotation - // but there is intermediate state that the bounds of task and the IME - // target's activity is not the same during rotating. - mDisplayContent.updateImeParent(); - - // Ignore hiding IME if IME window is attached to app. - // Since we would like to snapshot Task with IME window while transitioning - // to recents. - if (mDisplayContent.isImeAttachedToApp()) { - return; - } - } - final InputMethodManagerInternal inputMethodManagerInternal = - LocalServices.getService(InputMethodManagerInternal.class); - if (inputMethodManagerInternal != null) { - inputMethodManagerInternal.hideCurrentInputMethod( - SoftInputShowHideReason.HIDE_RECENTS_ANIMATION); - } - } finally { - Binder.restoreCallingIdentity(token); - } - } + public void hideCurrentInputMethod() { } @Override public void setDeferCancelUntilNextTransition(boolean defer, boolean screenshot) { diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index b27d016beb8d9..83282a5b8e5ab 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -304,22 +304,24 @@ public class DisplayContentTests extends WindowTestsBase { assertEquals(startingWin, imeTarget); startingWin.mHidden = false; - // Verify that an app window launching behind the starting window becomes the target + // Verify that the starting window still be an ime target even an app window launching + // behind it. final WindowState appWin = createWindow(null, TYPE_BASE_APPLICATION, activity, "appWin"); appWin.setHasSurface(true); assertTrue(appWin.canBeImeTarget()); imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */); - assertEquals(appWin, imeTarget); + assertEquals(startingWin, imeTarget); appWin.mHidden = false; - // Verify that an child window can be an ime target even behind a launching app window + // Verify that the starting window still be an ime target even the child window behind a + // launching app window final WindowState childWin = createWindow(appWin, TYPE_APPLICATION_ATTACHED_DIALOG, "childWin"); childWin.setHasSurface(true); assertTrue(childWin.canBeImeTarget()); imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */); - assertEquals(childWin, imeTarget); + assertEquals(startingWin, imeTarget); } @UseTestDisplay(addAllCommonWindows = true)