Loading services/core/java/com/android/server/wm/DisplayContent.java +2 −0 Original line number Diff line number Diff line Loading @@ -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(); } } Loading services/core/java/com/android/server/wm/WindowState.java +19 −12 Original line number Diff line number Diff line Loading @@ -4967,21 +4967,28 @@ 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 // 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; // 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 (mDisplayContent.getDefaultTaskDisplayArea().isSplitScreenModeActivated() && getTask() != null) { 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, boolean traverseTopToBottom) { Loading services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java +47 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading Loading
services/core/java/com/android/server/wm/DisplayContent.java +2 −0 Original line number Diff line number Diff line Loading @@ -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(); } } Loading
services/core/java/com/android/server/wm/WindowState.java +19 −12 Original line number Diff line number Diff line Loading @@ -4967,21 +4967,28 @@ 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 // 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; // 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 (mDisplayContent.getDefaultTaskDisplayArea().isSplitScreenModeActivated() && getTask() != null) { 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, boolean traverseTopToBottom) { Loading
services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java +47 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading