diff options
3 files changed, 68 insertions, 12 deletions
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 0de3fa3ad968..d168902b648a 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -4140,6 +4140,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp target.mActivityRecord.mImeInsetsFrozenUntilStartInput = false; } setImeInputTarget(target); + mInsetsStateController.updateAboveInsetsState(mInputMethodWindow, mInsetsStateController + .getRawInsetsState().getSourceOrDefaultVisibility(ITYPE_IME)); updateImeControlTarget(); } } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 8fafc7d64c29..ef0cba973e72 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -4967,20 +4967,27 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP private boolean applyImeWindowsIfNeeded(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) { - // If this window is the current IME target, so we need to process the IME windows - // directly above it. The exception is if we are in split screen - // in which case we process the IME at the DisplayContent level to + // No need to apply to IME window if the window is not the current IME layering target. + if (!isImeLayeringTarget()) { + return false; + } + // If we are in split screen which case we process the IME at the DisplayContent level to // ensure it is above the docked divider. - // (i.e. Like {@link DisplayContent.ImeContainer#skipImeWindowsDuringTraversal}, the IME - // window will be ignored to traverse when the IME target is still in split-screen mode). - if (isImeLayeringTarget() - && (!mDisplayContent.getDefaultTaskDisplayArea().isSplitScreenModeActivated() - || getTask() == null)) { - if (mDisplayContent.forAllImeWindows(callback, traverseTopToBottom)) { - return true; - } + // i.e. Like {@link DisplayContent.ImeContainer#skipImeWindowsDuringTraversal}, the IME + // window will be ignored to traverse when the IME target is still in split-screen mode. + if (mDisplayContent.getDefaultTaskDisplayArea().isSplitScreenModeActivated() + && getTask() != null) { + return false; } - return false; + // Note that we don't process IME window if the IME input target is not on the screen. + // In case some unexpected IME visibility cases happen like starting the remote + // animation on the keyguard but seeing the IME window that originally on the app + // which behinds the keyguard. + final WindowState imeInputTarget = getImeInputTarget(); + if (imeInputTarget != null && !(imeInputTarget.isDrawn() || imeInputTarget.isVisible())) { + return false; + } + return mDisplayContent.forAllImeWindows(callback, traverseTopToBottom); } private boolean applyInOrderWithImeWindows(ToBooleanFunction<WindowState> callback, diff --git a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java index 08312ef0b865..575e0820eca9 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java @@ -36,12 +36,14 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION; +import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.fail; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyFloat; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; @@ -699,6 +701,51 @@ public class RemoteAnimationControllerTest extends WindowTestsBase { } } + @UseTestDisplay(addWindows = W_INPUT_METHOD) + @Test + public void testLaunchRemoteAnimationWithoutImeBehind() { + final WindowState win1 = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin1"); + final WindowState win2 = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin2"); + + // Simulating win1 has shown IME and being IME layering/input target + mDisplayContent.setImeLayeringTarget(win1); + mDisplayContent.setImeInputTarget(win1); + mImeWindow.mWinAnimator.mSurfaceController = mock(WindowSurfaceController.class); + mImeWindow.mWinAnimator.hide(mDisplayContent.getPendingTransaction(), "test"); + spyOn(mDisplayContent); + doReturn(true).when(mImeWindow.mWinAnimator.mSurfaceController).hasSurface(); + doReturn(true).when(mImeWindow.mWinAnimator.mSurfaceController) + .prepareToShowInTransaction(any(), anyFloat()); + makeWindowVisibleAndDrawn(mImeWindow); + assertTrue(mImeWindow.isOnScreen()); + assertFalse(mImeWindow.isParentWindowHidden()); + + try { + // Simulating now win1 is being covered by the lockscreen which has no surface, + // and then launching an activity win2 with the remote animation + win1.mHasSurface = false; + mDisplayContent.mOpeningApps.add(win2.mActivityRecord); + final AnimationAdapter adapter = mController.createRemoteAnimationRecord( + win2.mActivityRecord, new Point(50, 100), null, + new Rect(50, 100, 150, 150), null).mAdapter; + adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION, + mFinishedCallback); + + mDisplayContent.applySurfaceChangesTransaction(); + mController.goodToGo(TRANSIT_OLD_TASK_OPEN); + mWm.mAnimator.executeAfterPrepareSurfacesRunnables(); + + verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_TASK_OPEN), + any(), any(), any(), any()); + // Verify the IME window won't apply surface change transaction with forAllImeWindows + verify(mDisplayContent, never()).forAllImeWindows(any(), eq(true)); + } catch (Exception e) { + // no-op + } finally { + mDisplayContent.mOpeningApps.clear(); + } + } + private AnimationAdapter setupForNonAppTargetNavBar(int transit, boolean shouldAttachNavBar) { final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin"); mDisplayContent.mOpeningApps.add(win.mActivityRecord); |