Loading services/core/java/com/android/server/wm/DisplayContent.java +5 −5 Original line number Diff line number Diff line Loading @@ -4270,17 +4270,17 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp */ @VisibleForTesting SurfaceControl computeImeParent() { if (mImeLayeringTarget != null && mImeInputTarget != null && mImeLayeringTarget.mActivityRecord != mImeInputTarget.getActivityRecord()) { // Do not change parent if the window hasn't requested IME. return null; } // Attach it to app if the target is part of an app and such app is covering the entire // screen. If it's not covering the entire screen the IME might extend beyond the apps // bounds. if (shouldImeAttachedToApp()) { if (mImeLayeringTarget.mActivityRecord != mImeInputTarget.getActivityRecord()) { // Do not change parent if the window hasn't requested IME. return null; } return mImeLayeringTarget.mActivityRecord.getSurfaceControl(); } // Otherwise, we just attach it to where the display area policy put it. return mImeWindowsContainer.getParent() != null ? mImeWindowsContainer.getParent().getSurfaceControl() : null; Loading services/core/java/com/android/server/wm/InsetsPolicy.java +4 −6 Original line number Diff line number Diff line Loading @@ -424,14 +424,12 @@ class InsetsPolicy { return state; } } else if (w.mActivityRecord != null && w.mActivityRecord.mImeInsetsFrozenUntilStartInput) { // During switching tasks with gestural navigation, if the IME is attached to // one app window on that time, even the next app window is behind the IME window, // conceptually the window should not receive the IME insets if the next window is // not eligible IME requester and ready to show IME on top of it. final boolean shouldImeAttachedToApp = mDisplayContent.shouldImeAttachedToApp(); // During switching tasks with gestural navigation, before the next IME input target // starts the input, we should adjust and freeze the last IME visibility of the window // in case delivering obsoleted IME insets state during transitioning. final InsetsSource originalImeSource = originalState.peekSource(ITYPE_IME); if (shouldImeAttachedToApp && originalImeSource != null) { if (originalImeSource != null) { final boolean imeVisibility = w.mActivityRecord.mLastImeShown || w.getRequestedVisibility(ITYPE_IME); final InsetsState state = copyState ? new InsetsState(originalState) Loading services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +2 −2 Original line number Diff line number Diff line Loading @@ -3101,11 +3101,11 @@ public class ActivityRecordTests extends WindowTestsBase { // Simulate app re-start input or turning screen off/on then unlocked by un-secure // keyguard to back to the app, expect IME insets is not frozen mDisplayContent.updateImeInputAndControlTarget(app); assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput); imeSource.setFrame(new Rect(100, 400, 500, 500)); app.getInsetsState().addSource(imeSource); app.getInsetsState().setSourceVisible(ITYPE_IME, true); mDisplayContent.updateImeInputAndControlTarget(app); assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput); // Verify when IME is visible and the app can receive the right IME insets from policy. makeWindowVisibleAndDrawn(app, mImeWindow); Loading services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +15 −0 Original line number Diff line number Diff line Loading @@ -1102,6 +1102,21 @@ public class DisplayContentTests extends WindowTestsBase { assertEquals(dc.getImeContainer().getParentSurfaceControl(), dc.computeImeParent()); } @UseTestDisplay(addWindows = W_ACTIVITY) @Test public void testComputeImeParent_inputTargetNotUpdate() throws Exception { WindowState app1 = createWindow(null, TYPE_BASE_APPLICATION, "app1"); WindowState app2 = createWindow(null, TYPE_BASE_APPLICATION, "app2"); doReturn(true).when(mDisplayContent).shouldImeAttachedToApp(); mDisplayContent.setImeLayeringTarget(app1); mDisplayContent.setImeInputTarget(app1); assertEquals(app1.mActivityRecord.getSurfaceControl(), mDisplayContent.computeImeParent()); mDisplayContent.setImeLayeringTarget(app2); // Expect null means no change IME parent when the IME layering target not yet // request IME to be the input target. assertNull(mDisplayContent.computeImeParent()); } @Test public void testInputMethodInputTarget_isClearedWhenWindowStateIsRemoved() throws Exception { final DisplayContent dc = createNewDisplay(); Loading services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +40 −0 Original line number Diff line number Diff line Loading @@ -945,6 +945,46 @@ public class WindowStateTests extends WindowTestsBase { assertFalse(app2.getInsetsState().getSource(ITYPE_IME).isVisible()); } @Test public void testAdjustImeInsetsVisibilityWhenSwitchingApps_toAppInMultiWindowMode() { final WindowState app = createWindow(null, TYPE_APPLICATION, "app"); final WindowState app2 = createWindow(null, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD, TYPE_APPLICATION, mDisplayContent, "app2"); final WindowState imeWindow = createWindow(null, TYPE_APPLICATION, "imeWindow"); spyOn(imeWindow); doReturn(true).when(imeWindow).isVisible(); mDisplayContent.mInputMethodWindow = imeWindow; final InsetsStateController controller = mDisplayContent.getInsetsStateController(); controller.getImeSourceProvider().setWindowContainer(imeWindow, null, null); // Simulate app2 in multi-window mode is going to background to switch to the fullscreen // app which requests IME with updating all windows Insets State when IME is above app. app2.mActivityRecord.mImeInsetsFrozenUntilStartInput = true; mDisplayContent.setImeLayeringTarget(app); mDisplayContent.setImeInputTarget(app); assertTrue(mDisplayContent.shouldImeAttachedToApp()); controller.getImeSourceProvider().scheduleShowImePostLayout(app); controller.getImeSourceProvider().getSource().setVisible(true); controller.updateAboveInsetsState(false); // Expect app windows behind IME can receive IME insets visible, // but not for app2 in background. assertTrue(app.getInsetsState().getSource(ITYPE_IME).isVisible()); assertFalse(app2.getInsetsState().getSource(ITYPE_IME).isVisible()); // Simulate app plays closing transition to app2. // And app2 is now IME layering target but not yet to be the IME input target. mDisplayContent.setImeLayeringTarget(app2); app.mActivityRecord.commitVisibility(false, false); assertTrue(app.mActivityRecord.mLastImeShown); assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput); // Verify the IME insets is still visible on app, but not for app2 during task switching. assertTrue(app.getInsetsState().getSource(ITYPE_IME).isVisible()); assertFalse(app2.getInsetsState().getSource(ITYPE_IME).isVisible()); } @UseTestDisplay(addWindows = {W_ACTIVITY}) @Test public void testUpdateImeControlTargetWhenLeavingMultiWindow() { Loading Loading
services/core/java/com/android/server/wm/DisplayContent.java +5 −5 Original line number Diff line number Diff line Loading @@ -4270,17 +4270,17 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp */ @VisibleForTesting SurfaceControl computeImeParent() { if (mImeLayeringTarget != null && mImeInputTarget != null && mImeLayeringTarget.mActivityRecord != mImeInputTarget.getActivityRecord()) { // Do not change parent if the window hasn't requested IME. return null; } // Attach it to app if the target is part of an app and such app is covering the entire // screen. If it's not covering the entire screen the IME might extend beyond the apps // bounds. if (shouldImeAttachedToApp()) { if (mImeLayeringTarget.mActivityRecord != mImeInputTarget.getActivityRecord()) { // Do not change parent if the window hasn't requested IME. return null; } return mImeLayeringTarget.mActivityRecord.getSurfaceControl(); } // Otherwise, we just attach it to where the display area policy put it. return mImeWindowsContainer.getParent() != null ? mImeWindowsContainer.getParent().getSurfaceControl() : null; Loading
services/core/java/com/android/server/wm/InsetsPolicy.java +4 −6 Original line number Diff line number Diff line Loading @@ -424,14 +424,12 @@ class InsetsPolicy { return state; } } else if (w.mActivityRecord != null && w.mActivityRecord.mImeInsetsFrozenUntilStartInput) { // During switching tasks with gestural navigation, if the IME is attached to // one app window on that time, even the next app window is behind the IME window, // conceptually the window should not receive the IME insets if the next window is // not eligible IME requester and ready to show IME on top of it. final boolean shouldImeAttachedToApp = mDisplayContent.shouldImeAttachedToApp(); // During switching tasks with gestural navigation, before the next IME input target // starts the input, we should adjust and freeze the last IME visibility of the window // in case delivering obsoleted IME insets state during transitioning. final InsetsSource originalImeSource = originalState.peekSource(ITYPE_IME); if (shouldImeAttachedToApp && originalImeSource != null) { if (originalImeSource != null) { final boolean imeVisibility = w.mActivityRecord.mLastImeShown || w.getRequestedVisibility(ITYPE_IME); final InsetsState state = copyState ? new InsetsState(originalState) Loading
services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +2 −2 Original line number Diff line number Diff line Loading @@ -3101,11 +3101,11 @@ public class ActivityRecordTests extends WindowTestsBase { // Simulate app re-start input or turning screen off/on then unlocked by un-secure // keyguard to back to the app, expect IME insets is not frozen mDisplayContent.updateImeInputAndControlTarget(app); assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput); imeSource.setFrame(new Rect(100, 400, 500, 500)); app.getInsetsState().addSource(imeSource); app.getInsetsState().setSourceVisible(ITYPE_IME, true); mDisplayContent.updateImeInputAndControlTarget(app); assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput); // Verify when IME is visible and the app can receive the right IME insets from policy. makeWindowVisibleAndDrawn(app, mImeWindow); Loading
services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +15 −0 Original line number Diff line number Diff line Loading @@ -1102,6 +1102,21 @@ public class DisplayContentTests extends WindowTestsBase { assertEquals(dc.getImeContainer().getParentSurfaceControl(), dc.computeImeParent()); } @UseTestDisplay(addWindows = W_ACTIVITY) @Test public void testComputeImeParent_inputTargetNotUpdate() throws Exception { WindowState app1 = createWindow(null, TYPE_BASE_APPLICATION, "app1"); WindowState app2 = createWindow(null, TYPE_BASE_APPLICATION, "app2"); doReturn(true).when(mDisplayContent).shouldImeAttachedToApp(); mDisplayContent.setImeLayeringTarget(app1); mDisplayContent.setImeInputTarget(app1); assertEquals(app1.mActivityRecord.getSurfaceControl(), mDisplayContent.computeImeParent()); mDisplayContent.setImeLayeringTarget(app2); // Expect null means no change IME parent when the IME layering target not yet // request IME to be the input target. assertNull(mDisplayContent.computeImeParent()); } @Test public void testInputMethodInputTarget_isClearedWhenWindowStateIsRemoved() throws Exception { final DisplayContent dc = createNewDisplay(); Loading
services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +40 −0 Original line number Diff line number Diff line Loading @@ -945,6 +945,46 @@ public class WindowStateTests extends WindowTestsBase { assertFalse(app2.getInsetsState().getSource(ITYPE_IME).isVisible()); } @Test public void testAdjustImeInsetsVisibilityWhenSwitchingApps_toAppInMultiWindowMode() { final WindowState app = createWindow(null, TYPE_APPLICATION, "app"); final WindowState app2 = createWindow(null, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD, TYPE_APPLICATION, mDisplayContent, "app2"); final WindowState imeWindow = createWindow(null, TYPE_APPLICATION, "imeWindow"); spyOn(imeWindow); doReturn(true).when(imeWindow).isVisible(); mDisplayContent.mInputMethodWindow = imeWindow; final InsetsStateController controller = mDisplayContent.getInsetsStateController(); controller.getImeSourceProvider().setWindowContainer(imeWindow, null, null); // Simulate app2 in multi-window mode is going to background to switch to the fullscreen // app which requests IME with updating all windows Insets State when IME is above app. app2.mActivityRecord.mImeInsetsFrozenUntilStartInput = true; mDisplayContent.setImeLayeringTarget(app); mDisplayContent.setImeInputTarget(app); assertTrue(mDisplayContent.shouldImeAttachedToApp()); controller.getImeSourceProvider().scheduleShowImePostLayout(app); controller.getImeSourceProvider().getSource().setVisible(true); controller.updateAboveInsetsState(false); // Expect app windows behind IME can receive IME insets visible, // but not for app2 in background. assertTrue(app.getInsetsState().getSource(ITYPE_IME).isVisible()); assertFalse(app2.getInsetsState().getSource(ITYPE_IME).isVisible()); // Simulate app plays closing transition to app2. // And app2 is now IME layering target but not yet to be the IME input target. mDisplayContent.setImeLayeringTarget(app2); app.mActivityRecord.commitVisibility(false, false); assertTrue(app.mActivityRecord.mLastImeShown); assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput); // Verify the IME insets is still visible on app, but not for app2 during task switching. assertTrue(app.getInsetsState().getSource(ITYPE_IME).isVisible()); assertFalse(app2.getInsetsState().getSource(ITYPE_IME).isVisible()); } @UseTestDisplay(addWindows = {W_ACTIVITY}) @Test public void testUpdateImeControlTargetWhenLeavingMultiWindow() { Loading