Loading services/core/java/com/android/server/wm/DisplayContent.java +8 −12 Original line number Diff line number Diff line Loading @@ -675,10 +675,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp private InsetsControlTarget mImeControlTarget; /** * The last {@link #mImeInputTarget} processed from {@link #setImeLayeringTargetInner}. This * enables updating the {@link #mImeControlTarget} when the {@link #mImeLayeringTarget} remains * the same, and only the {@link #mImeInputTarget} changes. For example, this can happen when * the IME is moving to a SurfaceControlViewHost backed EmbeddedWindow. * The last {@link #mImeInputTarget} processed from {@link #setImeLayeringTarget}. This enables * updating the {@link #mImeControlTarget} when the {@link #mImeLayeringTarget} remains the * same, and only the {@link #mImeInputTarget} changes. For example, this can happen when the * IME is moving to a SurfaceControlViewHost backed EmbeddedWindow. */ @Nullable private InputTarget mLastImeInputTarget; Loading Loading @@ -4165,7 +4165,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } if (update) { setImeLayeringTargetInner(target); setImeLayeringTarget(target); } return target; Loading Loading @@ -4306,11 +4306,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } } @VisibleForTesting void setImeLayeringTarget(@Nullable WindowState target) { mImeLayeringTarget = target; } /** * Sets the IME layering target, and updates the IME control target. Also updates the IME parent * if necessary. Loading @@ -4318,7 +4313,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp * @param target the window to place the IME on top of. If {@code null}, the IME will be placed * on top of its parent's surface. */ private void setImeLayeringTargetInner(@Nullable WindowState target) { @VisibleForTesting void setImeLayeringTarget(@Nullable WindowState target) { // This function is also responsible for updating the IME control target and so in the case // where the IME layering target does not change but the IME input target does (for example, // IME moving to a SurfaceControlViewHost) we have to continue executing this function, Loading @@ -4342,7 +4338,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } } ProtoLog.i(WM_DEBUG_IME, "setImeLayeringTargetInner %s", target); ProtoLog.i(WM_DEBUG_IME, "setImeLayeringTarget %s", target); boolean forceUpdateImeParent = target != mImeLayeringTarget; mImeLayeringTarget = target; Loading services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +28 −24 Original line number Diff line number Diff line Loading @@ -644,8 +644,8 @@ public class DisplayContentTests extends WindowTestsBase { final DisplayContent dc = mDisplayContent; final WindowState ws = newWindowBuilder("app window", TYPE_APPLICATION).setDisplay( dc).build(); dc.setImeLayeringTarget(ws); dc.setImeInputTarget(ws); dc.setImeLayeringTarget(ws); // Adjust bounds so that matchesRootDisplayAreaBounds() returns false. final Rect bounds = new Rect(dc.getBounds()); Loading Loading @@ -1230,8 +1230,9 @@ public class DisplayContentTests extends WindowTestsBase { @Test public void testComputeImeParent_app() { final DisplayContent dc = createNewDisplay(); dc.setImeLayeringTarget(newWindowBuilder("app", TYPE_BASE_APPLICATION).build()); dc.setImeInputTarget(dc.getImeLayeringTarget()); final var appWin = newWindowBuilder("appWin", TYPE_BASE_APPLICATION).setDisplay(dc).build(); dc.setImeInputTarget(appWin); dc.setImeLayeringTarget(appWin); assertEquals(dc.getImeLayeringTarget().mActivityRecord.getSurfaceControl(), dc.computeImeParent().getSurfaceControl()); } Loading @@ -1239,9 +1240,10 @@ public class DisplayContentTests extends WindowTestsBase { @Test public void testComputeImeParent_app_notFullscreen() { final DisplayContent dc = createNewDisplay(); dc.setImeLayeringTarget(newWindowBuilder("app", TYPE_STATUS_BAR).build()); dc.getImeLayeringTarget().setWindowingMode(WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW); dc.setImeInputTarget(dc.getImeLayeringTarget()); final var appWin = newWindowBuilder("appWin", TYPE_STATUS_BAR).setDisplay(dc) .setWindowingMode(WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW).build(); dc.setImeInputTarget(appWin); dc.setImeLayeringTarget(appWin); assertEquals(dc.getImeContainer().getParentSurfaceControl(), dc.computeImeParent().getSurfaceControl()); } Loading @@ -1260,8 +1262,9 @@ public class DisplayContentTests extends WindowTestsBase { @Test public void testComputeImeParent_noApp() { final DisplayContent dc = createNewDisplay(); dc.setImeLayeringTarget(newWindowBuilder("statusBar", TYPE_STATUS_BAR).build()); dc.setImeInputTarget(dc.getImeLayeringTarget()); final var statusBar = newWindowBuilder("statusBar", TYPE_STATUS_BAR).setDisplay(dc).build(); dc.setImeInputTarget(statusBar); dc.setImeLayeringTarget(statusBar); assertEquals(dc.getImeContainer().getParentSurfaceControl(), dc.computeImeParent().getSurfaceControl()); } Loading @@ -1272,8 +1275,8 @@ public class DisplayContentTests extends WindowTestsBase { WindowState app1 = newWindowBuilder("app1", TYPE_BASE_APPLICATION).build(); WindowState app2 = newWindowBuilder("app2", TYPE_BASE_APPLICATION).build(); doReturn(true).when(mDisplayContent).shouldImeAttachedToApp(); mDisplayContent.setImeLayeringTarget(app1); mDisplayContent.setImeInputTarget(app1); mDisplayContent.setImeLayeringTarget(app1); assertEquals(app1.mActivityRecord.getSurfaceControl(), mDisplayContent.computeImeParent().getSurfaceControl()); mDisplayContent.setImeLayeringTarget(app2); Loading @@ -1289,8 +1292,8 @@ public class DisplayContentTests extends WindowTestsBase { overlay.setBounds(100, 100, 200, 200); overlay.mAttrs.flags = FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM; WindowState app = newWindowBuilder("app", TYPE_BASE_APPLICATION).build(); mDisplayContent.setImeLayeringTarget(overlay); mDisplayContent.setImeInputTarget(app); mDisplayContent.setImeLayeringTarget(overlay); assertFalse(mDisplayContent.shouldImeAttachedToApp()); assertEquals(mDisplayContent.getImeContainer().getParentSurfaceControl(), mDisplayContent.computeImeParent().getSurfaceControl()); Loading @@ -1302,9 +1305,9 @@ public class DisplayContentTests extends WindowTestsBase { WindowState app1 = newWindowBuilder("app1", TYPE_BASE_APPLICATION).build(); WindowState app2 = newWindowBuilder("app2", TYPE_BASE_APPLICATION).build(); dc.setImeLayeringTarget(app1); dc.setImeInputTarget(app2); dc.setRemoteInsetsController(createDisplayWindowInsetsController()); dc.setImeInputTarget(app2); dc.setImeLayeringTarget(app1); dc.getImeLayeringTarget().setWindowingMode( WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW); dc.getImeInputTarget().getWindowState().setWindowingMode( Loading Loading @@ -1357,11 +1360,11 @@ public class DisplayContentTests extends WindowTestsBase { @Test public void testComputeImeControlTarget_splitscreen() { final DisplayContent dc = createNewDisplay(); dc.setImeInputTarget(newWindowBuilder("app", TYPE_BASE_APPLICATION).build()); dc.getImeInputTarget().getWindowState().setWindowingMode( WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW); dc.setImeLayeringTarget(dc.getImeInputTarget().getWindowState()); dc.setRemoteInsetsController(createDisplayWindowInsetsController()); final var appWin = newWindowBuilder("appWin", TYPE_BASE_APPLICATION).setDisplay(dc) .setWindowingMode(WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW).build(); dc.setImeInputTarget(appWin); dc.setImeLayeringTarget(appWin); assertNotEquals(dc.getImeInputTarget().getWindowState(), dc.computeImeControlTarget()); } Loading @@ -1384,9 +1387,9 @@ public class DisplayContentTests extends WindowTestsBase { public void testComputeImeControlTarget_notMatchParentBounds() { spyOn(mAppWindow.mActivityRecord); doReturn(false).when(mAppWindow.mActivityRecord).matchParentBounds(); mDisplayContent.setImeInputTarget(mAppWindow); mDisplayContent.setImeLayeringTarget(mDisplayContent.getImeInputTarget().getWindowState()); mDisplayContent.setRemoteInsetsController(createDisplayWindowInsetsController()); mDisplayContent.setImeInputTarget(mAppWindow); mDisplayContent.setImeLayeringTarget(mAppWindow); assertEquals(mAppWindow, mDisplayContent.computeImeControlTarget()); } Loading @@ -1400,9 +1403,9 @@ public class DisplayContentTests extends WindowTestsBase { spyOn(mAppWindow.mActivityRecord); doReturn(imeTargetBounds).when(mAppWindow).getBounds(); doReturn(true).when(mAppWindow.mActivityRecord).matchParentBounds(); mDisplayContent.setImeInputTarget(mAppWindow); mDisplayContent.setImeLayeringTarget(mDisplayContent.getImeInputTarget().getWindowState()); mDisplayContent.setRemoteInsetsController(createDisplayWindowInsetsController()); mDisplayContent.setImeInputTarget(mAppWindow); mDisplayContent.setImeLayeringTarget(mAppWindow); final DisplayArea.Tokens imeContainer = mDisplayContent.getImeContainer(); spyOn(imeContainer); doReturn(imeContainerBounds).when(imeContainer).getBounds(); Loading Loading @@ -2244,6 +2247,7 @@ public class DisplayContentTests extends WindowTestsBase { spyOn(child1); doReturn(false).when(mDisplayContent).shouldImeAttachedToApp(); mDisplayContent.setImeLayeringTarget(child1); verify(child1).needsRelativeLayeringToIme(); spyOn(nextImeTargetApp); spyOn(mAppWindow); Loading @@ -2255,7 +2259,8 @@ public class DisplayContentTests extends WindowTestsBase { verify(mDisplayContent).computeImeLayeringTarget(true /* update */); assertNull(mDisplayContent.getImeInputTarget()); verify(child1, never()).needsRelativeLayeringToIme(); // Still only one call, earlier when child1 was set as IME layering target. verify(child1).needsRelativeLayeringToIme(); } @SetupWindows(addWindows = W_INPUT_METHOD) Loading Loading @@ -2321,9 +2326,8 @@ public class DisplayContentTests extends WindowTestsBase { final WindowState win = newWindowBuilder("win", TYPE_BASE_APPLICATION).setWindowToken( activity).build(); mDisplayContent.setImeLayeringTarget(win); mDisplayContent.setImeInputTarget(win); spyOn(mDisplayContent); mDisplayContent.setImeLayeringTarget(win); spyOn(mDisplayContent.mInputMethodWindow); doReturn(true).when(mDisplayContent.mInputMethodWindow).isVisible(); mDisplayContent.getInsetsStateController().getImeSourceProvider().setImeShowing(true); Loading @@ -2349,8 +2353,8 @@ public class DisplayContentTests extends WindowTestsBase { activity).build(); makeWindowVisible(mDisplayContent.mInputMethodWindow); mDisplayContent.setImeLayeringTarget(win); mDisplayContent.setImeInputTarget(win); mDisplayContent.setImeLayeringTarget(win); mDisplayContent.getInsetsStateController().getImeSourceProvider().setImeShowing(true); mDisplayContent.showImeScreenshot(); assertNotNull(mDisplayContent.mImeScreenshot); Loading services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +3 −3 Original line number Diff line number Diff line Loading @@ -787,9 +787,9 @@ public class SizeCompatTests extends WindowTestsBase { assertFitted(); rotateDisplay(mActivity.mDisplayContent, ROTATION_90); mActivity.mDisplayContent.setImeLayeringTarget(addWindowToActivity(mActivity)); mActivity.mDisplayContent.setImeInputTarget( mActivity.mDisplayContent.getImeLayeringTarget()); final var appWindow = addWindowToActivity(mActivity); mActivity.mDisplayContent.setImeInputTarget(appWindow); mActivity.mDisplayContent.setImeLayeringTarget(appWindow); // Because the aspect ratio of display doesn't exceed the max aspect ratio of activity. // The activity should still fill its parent container and IME can attach to the activity. assertTrue(mActivity.matchParentBounds()); Loading services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java +1 −1 Original line number Diff line number Diff line Loading @@ -66,8 +66,8 @@ public class WindowContainerTraversalTests extends WindowTestsBase { @SetupWindows(addWindows = { W_ACTIVITY, W_INPUT_METHOD }) @Test public void testTraverseImeRegardlessOfImeTarget() { mDisplayContent.setImeLayeringTarget(mAppWindow); mDisplayContent.setImeInputTarget(mAppWindow); mDisplayContent.setImeLayeringTarget(mAppWindow); mAppWindow.mHasSurface = false; mAppWindow.mActivityRecord.setVisibleRequested(false); mAppWindow.mActivityRecord.setVisible(false); Loading services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +70 −65 Original line number Diff line number Diff line Loading @@ -113,7 +113,6 @@ import android.view.View; import android.view.WindowInsets; import android.view.WindowManager; import android.view.WindowRelayoutResult; import android.view.inputmethod.ImeTracker; import android.window.ClientWindowFrames; import android.window.ITaskFragmentOrganizer; import android.window.TaskFragmentOrganizer; Loading Loading @@ -1329,80 +1328,86 @@ public class WindowStateTests extends WindowTestsBase { assertTrue(mAppWindow.getInsetsState().isSourceOrDefaultVisible(navId, navigationBars())); } @SetupWindows(addWindows = { W_INPUT_METHOD }) @Test public void testAdjustImeInsetsVisibilityWhenSwitchingApps() { final WindowState app = newWindowBuilder("app", TYPE_APPLICATION).build(); final WindowState app2 = newWindowBuilder("app2", TYPE_APPLICATION).build(); final WindowState imeWindow = newWindowBuilder("imeWindow", TYPE_APPLICATION).build(); spyOn(imeWindow); doReturn(true).when(imeWindow).isVisible(); mDisplayContent.mInputMethodWindow = imeWindow; final var appWin1 = newWindowBuilder("appWin1", TYPE_APPLICATION).build(); final var appWin2 = newWindowBuilder("appWin2", TYPE_APPLICATION).build(); makeWindowVisibleAndDrawn(mImeWindow); final InsetsStateController controller = mDisplayContent.getInsetsStateController(); controller.getImeSourceProvider().setWindowContainer(imeWindow, null, null); // Simulate app requests IME with updating all windows Insets State when IME is above app. mDisplayContent.setImeLayeringTarget(app); mDisplayContent.setImeInputTarget(app); app.setRequestedVisibleTypes(ime(), ime()); assertTrue(mDisplayContent.shouldImeAttachedToApp()); controller.getImeSourceProvider().scheduleShowImePostLayout(app, ImeTracker.Token.empty()); controller.getImeSourceProvider().getSource().setVisible(true); controller.updateAboveInsetsState(false); // Expect all app windows behind IME can receive IME insets visible. assertTrue(app.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime())); assertTrue(app2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime())); // Simulate app plays closing transition to app2. app.mActivityRecord.commitVisibility(false, false); mDisplayContent.computeImeLayeringTarget(true /* update */); assertTrue(app.mActivityRecord.mLastImeShown); // Verify the IME insets is visible on app, but not for app2 during app task switching. assertTrue(app.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime())); assertFalse(app2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime())); controller.getImeSourceProvider().setWindowContainer(mImeWindow, null, null); // Simulate appWin2 requests IME. appWin2.setRequestedVisibleTypes(ime(), ime()); mDisplayContent.setImeInputTarget(appWin2); mDisplayContent.setImeLayeringTarget(appWin2); assertEquals("appWin2 is the IME control target", appWin2, mDisplayContent.getImeControlTarget()); controller.getImeSourceProvider().onPostLayout(); // Expect all windows behind IME can receive IME insets visible. assertTrue("appWin1 has IME insets visible", appWin1.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime())); assertTrue("appWin2 has IME insets visible", appWin2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime())); // Simulate appWin2 plays closing transition to appWin1. appWin2.mActivityRecord.commitVisibility(false /* visible */, false /* performLayout */); assertNull("appWin1 does not have frozen insets", appWin1.getFrozenInsetsState()); assertNotNull("appWin2 has frozen insets", appWin2.getFrozenInsetsState()); mDisplayContent.setImeInputTarget(appWin1); mDisplayContent.setImeLayeringTarget(appWin1); assertEquals("appWin1 is the IME control target", appWin1, mDisplayContent.getImeControlTarget()); assertFalse("appWin1 does not have IME insets visible", appWin1.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime())); assertTrue("appWin2 still has IME insets visible, as they were frozen", appWin2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime())); } @SetupWindows(addWindows = { W_INPUT_METHOD }) @Test public void testAdjustImeInsetsVisibilityWhenSwitchingApps_toAppInMultiWindowMode() { final WindowState app = newWindowBuilder("app", TYPE_APPLICATION).build(); final WindowState app2 = newWindowBuilder("app2", TYPE_APPLICATION).setWindowingMode( WINDOWING_MODE_MULTI_WINDOW).setActivityType(ACTIVITY_TYPE_STANDARD).setDisplay( mDisplayContent).build(); final WindowState imeWindow = newWindowBuilder("imeWindow", TYPE_APPLICATION).build(); spyOn(imeWindow); doReturn(true).when(imeWindow).isVisible(); mDisplayContent.mInputMethodWindow = imeWindow; final var appWin1 = newWindowBuilder("appWin1", TYPE_APPLICATION) .setWindowingMode(WINDOWING_MODE_MULTI_WINDOW).build(); final var appWin2 = newWindowBuilder("appWin2", TYPE_APPLICATION).build(); makeWindowVisibleAndDrawn(mImeWindow); mDisplayContent.setRemoteInsetsController(createDisplayWindowInsetsController()); 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.setVisibleRequested(false); mDisplayContent.setImeLayeringTarget(app); mDisplayContent.setImeInputTarget(app); app.setRequestedVisibleTypes(ime(), ime()); assertTrue(mDisplayContent.shouldImeAttachedToApp()); controller.getImeSourceProvider().scheduleShowImePostLayout(app, ImeTracker.Token.empty()); 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().isSourceOrDefaultVisible(ID_IME, ime())); assertFalse(app2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime())); // 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); // Verify the IME insets is still visible on app, but not for app2 during task switching. assertTrue(app.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime())); assertFalse(app2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime())); controller.getImeSourceProvider().setWindowContainer(mImeWindow, null, null); // Simulate appWin1 in multi-window mode is going to background to switch to the // fullscreen appWin2 which requests IME. appWin1.mActivityRecord.commitVisibility(false /* visible */, false /* performLayout */); assertNotNull("appWin1 has frozen insets", appWin1.getFrozenInsetsState()); assertNull("appWin2 does not have frozen insets", appWin2.getFrozenInsetsState()); appWin2.setRequestedVisibleTypes(ime(), ime()); mDisplayContent.setImeInputTarget(appWin2); mDisplayContent.setImeLayeringTarget(appWin2); controller.getImeSourceProvider().onPostLayout(); assertFalse("appWin1 does not have IME insets visible, as it is in background", appWin1.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime())); assertTrue("appWin2 has IME insets visible", appWin2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime())); // Simulate appWin2 plays closing transition to appWin1. appWin2.mActivityRecord.commitVisibility(false /* visible */, false /* performLayout */); appWin1.mActivityRecord.commitVisibility(true /* visible */, false /* performLayout */); assertNull("appWin1 does not have frozen insets", appWin1.getFrozenInsetsState()); assertNotNull("appWin2 has frozen insets", appWin2.getFrozenInsetsState()); mDisplayContent.setImeInputTarget(appWin1); mDisplayContent.setImeLayeringTarget(appWin1); assertEquals("RemoteInsetsControlTarget is the IME control target", mDisplayContent.mRemoteInsetsControlTarget, mDisplayContent.getImeControlTarget()); assertFalse("appWin1 does not have IME insets visible", appWin1.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime())); assertTrue("appWin2 still has IME insets visible, as they were frozen", appWin2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime())); } @SetupWindows(addWindows = W_ACTIVITY) Loading Loading
services/core/java/com/android/server/wm/DisplayContent.java +8 −12 Original line number Diff line number Diff line Loading @@ -675,10 +675,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp private InsetsControlTarget mImeControlTarget; /** * The last {@link #mImeInputTarget} processed from {@link #setImeLayeringTargetInner}. This * enables updating the {@link #mImeControlTarget} when the {@link #mImeLayeringTarget} remains * the same, and only the {@link #mImeInputTarget} changes. For example, this can happen when * the IME is moving to a SurfaceControlViewHost backed EmbeddedWindow. * The last {@link #mImeInputTarget} processed from {@link #setImeLayeringTarget}. This enables * updating the {@link #mImeControlTarget} when the {@link #mImeLayeringTarget} remains the * same, and only the {@link #mImeInputTarget} changes. For example, this can happen when the * IME is moving to a SurfaceControlViewHost backed EmbeddedWindow. */ @Nullable private InputTarget mLastImeInputTarget; Loading Loading @@ -4165,7 +4165,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } if (update) { setImeLayeringTargetInner(target); setImeLayeringTarget(target); } return target; Loading Loading @@ -4306,11 +4306,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } } @VisibleForTesting void setImeLayeringTarget(@Nullable WindowState target) { mImeLayeringTarget = target; } /** * Sets the IME layering target, and updates the IME control target. Also updates the IME parent * if necessary. Loading @@ -4318,7 +4313,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp * @param target the window to place the IME on top of. If {@code null}, the IME will be placed * on top of its parent's surface. */ private void setImeLayeringTargetInner(@Nullable WindowState target) { @VisibleForTesting void setImeLayeringTarget(@Nullable WindowState target) { // This function is also responsible for updating the IME control target and so in the case // where the IME layering target does not change but the IME input target does (for example, // IME moving to a SurfaceControlViewHost) we have to continue executing this function, Loading @@ -4342,7 +4338,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } } ProtoLog.i(WM_DEBUG_IME, "setImeLayeringTargetInner %s", target); ProtoLog.i(WM_DEBUG_IME, "setImeLayeringTarget %s", target); boolean forceUpdateImeParent = target != mImeLayeringTarget; mImeLayeringTarget = target; Loading
services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +28 −24 Original line number Diff line number Diff line Loading @@ -644,8 +644,8 @@ public class DisplayContentTests extends WindowTestsBase { final DisplayContent dc = mDisplayContent; final WindowState ws = newWindowBuilder("app window", TYPE_APPLICATION).setDisplay( dc).build(); dc.setImeLayeringTarget(ws); dc.setImeInputTarget(ws); dc.setImeLayeringTarget(ws); // Adjust bounds so that matchesRootDisplayAreaBounds() returns false. final Rect bounds = new Rect(dc.getBounds()); Loading Loading @@ -1230,8 +1230,9 @@ public class DisplayContentTests extends WindowTestsBase { @Test public void testComputeImeParent_app() { final DisplayContent dc = createNewDisplay(); dc.setImeLayeringTarget(newWindowBuilder("app", TYPE_BASE_APPLICATION).build()); dc.setImeInputTarget(dc.getImeLayeringTarget()); final var appWin = newWindowBuilder("appWin", TYPE_BASE_APPLICATION).setDisplay(dc).build(); dc.setImeInputTarget(appWin); dc.setImeLayeringTarget(appWin); assertEquals(dc.getImeLayeringTarget().mActivityRecord.getSurfaceControl(), dc.computeImeParent().getSurfaceControl()); } Loading @@ -1239,9 +1240,10 @@ public class DisplayContentTests extends WindowTestsBase { @Test public void testComputeImeParent_app_notFullscreen() { final DisplayContent dc = createNewDisplay(); dc.setImeLayeringTarget(newWindowBuilder("app", TYPE_STATUS_BAR).build()); dc.getImeLayeringTarget().setWindowingMode(WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW); dc.setImeInputTarget(dc.getImeLayeringTarget()); final var appWin = newWindowBuilder("appWin", TYPE_STATUS_BAR).setDisplay(dc) .setWindowingMode(WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW).build(); dc.setImeInputTarget(appWin); dc.setImeLayeringTarget(appWin); assertEquals(dc.getImeContainer().getParentSurfaceControl(), dc.computeImeParent().getSurfaceControl()); } Loading @@ -1260,8 +1262,9 @@ public class DisplayContentTests extends WindowTestsBase { @Test public void testComputeImeParent_noApp() { final DisplayContent dc = createNewDisplay(); dc.setImeLayeringTarget(newWindowBuilder("statusBar", TYPE_STATUS_BAR).build()); dc.setImeInputTarget(dc.getImeLayeringTarget()); final var statusBar = newWindowBuilder("statusBar", TYPE_STATUS_BAR).setDisplay(dc).build(); dc.setImeInputTarget(statusBar); dc.setImeLayeringTarget(statusBar); assertEquals(dc.getImeContainer().getParentSurfaceControl(), dc.computeImeParent().getSurfaceControl()); } Loading @@ -1272,8 +1275,8 @@ public class DisplayContentTests extends WindowTestsBase { WindowState app1 = newWindowBuilder("app1", TYPE_BASE_APPLICATION).build(); WindowState app2 = newWindowBuilder("app2", TYPE_BASE_APPLICATION).build(); doReturn(true).when(mDisplayContent).shouldImeAttachedToApp(); mDisplayContent.setImeLayeringTarget(app1); mDisplayContent.setImeInputTarget(app1); mDisplayContent.setImeLayeringTarget(app1); assertEquals(app1.mActivityRecord.getSurfaceControl(), mDisplayContent.computeImeParent().getSurfaceControl()); mDisplayContent.setImeLayeringTarget(app2); Loading @@ -1289,8 +1292,8 @@ public class DisplayContentTests extends WindowTestsBase { overlay.setBounds(100, 100, 200, 200); overlay.mAttrs.flags = FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM; WindowState app = newWindowBuilder("app", TYPE_BASE_APPLICATION).build(); mDisplayContent.setImeLayeringTarget(overlay); mDisplayContent.setImeInputTarget(app); mDisplayContent.setImeLayeringTarget(overlay); assertFalse(mDisplayContent.shouldImeAttachedToApp()); assertEquals(mDisplayContent.getImeContainer().getParentSurfaceControl(), mDisplayContent.computeImeParent().getSurfaceControl()); Loading @@ -1302,9 +1305,9 @@ public class DisplayContentTests extends WindowTestsBase { WindowState app1 = newWindowBuilder("app1", TYPE_BASE_APPLICATION).build(); WindowState app2 = newWindowBuilder("app2", TYPE_BASE_APPLICATION).build(); dc.setImeLayeringTarget(app1); dc.setImeInputTarget(app2); dc.setRemoteInsetsController(createDisplayWindowInsetsController()); dc.setImeInputTarget(app2); dc.setImeLayeringTarget(app1); dc.getImeLayeringTarget().setWindowingMode( WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW); dc.getImeInputTarget().getWindowState().setWindowingMode( Loading Loading @@ -1357,11 +1360,11 @@ public class DisplayContentTests extends WindowTestsBase { @Test public void testComputeImeControlTarget_splitscreen() { final DisplayContent dc = createNewDisplay(); dc.setImeInputTarget(newWindowBuilder("app", TYPE_BASE_APPLICATION).build()); dc.getImeInputTarget().getWindowState().setWindowingMode( WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW); dc.setImeLayeringTarget(dc.getImeInputTarget().getWindowState()); dc.setRemoteInsetsController(createDisplayWindowInsetsController()); final var appWin = newWindowBuilder("appWin", TYPE_BASE_APPLICATION).setDisplay(dc) .setWindowingMode(WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW).build(); dc.setImeInputTarget(appWin); dc.setImeLayeringTarget(appWin); assertNotEquals(dc.getImeInputTarget().getWindowState(), dc.computeImeControlTarget()); } Loading @@ -1384,9 +1387,9 @@ public class DisplayContentTests extends WindowTestsBase { public void testComputeImeControlTarget_notMatchParentBounds() { spyOn(mAppWindow.mActivityRecord); doReturn(false).when(mAppWindow.mActivityRecord).matchParentBounds(); mDisplayContent.setImeInputTarget(mAppWindow); mDisplayContent.setImeLayeringTarget(mDisplayContent.getImeInputTarget().getWindowState()); mDisplayContent.setRemoteInsetsController(createDisplayWindowInsetsController()); mDisplayContent.setImeInputTarget(mAppWindow); mDisplayContent.setImeLayeringTarget(mAppWindow); assertEquals(mAppWindow, mDisplayContent.computeImeControlTarget()); } Loading @@ -1400,9 +1403,9 @@ public class DisplayContentTests extends WindowTestsBase { spyOn(mAppWindow.mActivityRecord); doReturn(imeTargetBounds).when(mAppWindow).getBounds(); doReturn(true).when(mAppWindow.mActivityRecord).matchParentBounds(); mDisplayContent.setImeInputTarget(mAppWindow); mDisplayContent.setImeLayeringTarget(mDisplayContent.getImeInputTarget().getWindowState()); mDisplayContent.setRemoteInsetsController(createDisplayWindowInsetsController()); mDisplayContent.setImeInputTarget(mAppWindow); mDisplayContent.setImeLayeringTarget(mAppWindow); final DisplayArea.Tokens imeContainer = mDisplayContent.getImeContainer(); spyOn(imeContainer); doReturn(imeContainerBounds).when(imeContainer).getBounds(); Loading Loading @@ -2244,6 +2247,7 @@ public class DisplayContentTests extends WindowTestsBase { spyOn(child1); doReturn(false).when(mDisplayContent).shouldImeAttachedToApp(); mDisplayContent.setImeLayeringTarget(child1); verify(child1).needsRelativeLayeringToIme(); spyOn(nextImeTargetApp); spyOn(mAppWindow); Loading @@ -2255,7 +2259,8 @@ public class DisplayContentTests extends WindowTestsBase { verify(mDisplayContent).computeImeLayeringTarget(true /* update */); assertNull(mDisplayContent.getImeInputTarget()); verify(child1, never()).needsRelativeLayeringToIme(); // Still only one call, earlier when child1 was set as IME layering target. verify(child1).needsRelativeLayeringToIme(); } @SetupWindows(addWindows = W_INPUT_METHOD) Loading Loading @@ -2321,9 +2326,8 @@ public class DisplayContentTests extends WindowTestsBase { final WindowState win = newWindowBuilder("win", TYPE_BASE_APPLICATION).setWindowToken( activity).build(); mDisplayContent.setImeLayeringTarget(win); mDisplayContent.setImeInputTarget(win); spyOn(mDisplayContent); mDisplayContent.setImeLayeringTarget(win); spyOn(mDisplayContent.mInputMethodWindow); doReturn(true).when(mDisplayContent.mInputMethodWindow).isVisible(); mDisplayContent.getInsetsStateController().getImeSourceProvider().setImeShowing(true); Loading @@ -2349,8 +2353,8 @@ public class DisplayContentTests extends WindowTestsBase { activity).build(); makeWindowVisible(mDisplayContent.mInputMethodWindow); mDisplayContent.setImeLayeringTarget(win); mDisplayContent.setImeInputTarget(win); mDisplayContent.setImeLayeringTarget(win); mDisplayContent.getInsetsStateController().getImeSourceProvider().setImeShowing(true); mDisplayContent.showImeScreenshot(); assertNotNull(mDisplayContent.mImeScreenshot); Loading
services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +3 −3 Original line number Diff line number Diff line Loading @@ -787,9 +787,9 @@ public class SizeCompatTests extends WindowTestsBase { assertFitted(); rotateDisplay(mActivity.mDisplayContent, ROTATION_90); mActivity.mDisplayContent.setImeLayeringTarget(addWindowToActivity(mActivity)); mActivity.mDisplayContent.setImeInputTarget( mActivity.mDisplayContent.getImeLayeringTarget()); final var appWindow = addWindowToActivity(mActivity); mActivity.mDisplayContent.setImeInputTarget(appWindow); mActivity.mDisplayContent.setImeLayeringTarget(appWindow); // Because the aspect ratio of display doesn't exceed the max aspect ratio of activity. // The activity should still fill its parent container and IME can attach to the activity. assertTrue(mActivity.matchParentBounds()); Loading
services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java +1 −1 Original line number Diff line number Diff line Loading @@ -66,8 +66,8 @@ public class WindowContainerTraversalTests extends WindowTestsBase { @SetupWindows(addWindows = { W_ACTIVITY, W_INPUT_METHOD }) @Test public void testTraverseImeRegardlessOfImeTarget() { mDisplayContent.setImeLayeringTarget(mAppWindow); mDisplayContent.setImeInputTarget(mAppWindow); mDisplayContent.setImeLayeringTarget(mAppWindow); mAppWindow.mHasSurface = false; mAppWindow.mActivityRecord.setVisibleRequested(false); mAppWindow.mActivityRecord.setVisible(false); Loading
services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +70 −65 Original line number Diff line number Diff line Loading @@ -113,7 +113,6 @@ import android.view.View; import android.view.WindowInsets; import android.view.WindowManager; import android.view.WindowRelayoutResult; import android.view.inputmethod.ImeTracker; import android.window.ClientWindowFrames; import android.window.ITaskFragmentOrganizer; import android.window.TaskFragmentOrganizer; Loading Loading @@ -1329,80 +1328,86 @@ public class WindowStateTests extends WindowTestsBase { assertTrue(mAppWindow.getInsetsState().isSourceOrDefaultVisible(navId, navigationBars())); } @SetupWindows(addWindows = { W_INPUT_METHOD }) @Test public void testAdjustImeInsetsVisibilityWhenSwitchingApps() { final WindowState app = newWindowBuilder("app", TYPE_APPLICATION).build(); final WindowState app2 = newWindowBuilder("app2", TYPE_APPLICATION).build(); final WindowState imeWindow = newWindowBuilder("imeWindow", TYPE_APPLICATION).build(); spyOn(imeWindow); doReturn(true).when(imeWindow).isVisible(); mDisplayContent.mInputMethodWindow = imeWindow; final var appWin1 = newWindowBuilder("appWin1", TYPE_APPLICATION).build(); final var appWin2 = newWindowBuilder("appWin2", TYPE_APPLICATION).build(); makeWindowVisibleAndDrawn(mImeWindow); final InsetsStateController controller = mDisplayContent.getInsetsStateController(); controller.getImeSourceProvider().setWindowContainer(imeWindow, null, null); // Simulate app requests IME with updating all windows Insets State when IME is above app. mDisplayContent.setImeLayeringTarget(app); mDisplayContent.setImeInputTarget(app); app.setRequestedVisibleTypes(ime(), ime()); assertTrue(mDisplayContent.shouldImeAttachedToApp()); controller.getImeSourceProvider().scheduleShowImePostLayout(app, ImeTracker.Token.empty()); controller.getImeSourceProvider().getSource().setVisible(true); controller.updateAboveInsetsState(false); // Expect all app windows behind IME can receive IME insets visible. assertTrue(app.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime())); assertTrue(app2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime())); // Simulate app plays closing transition to app2. app.mActivityRecord.commitVisibility(false, false); mDisplayContent.computeImeLayeringTarget(true /* update */); assertTrue(app.mActivityRecord.mLastImeShown); // Verify the IME insets is visible on app, but not for app2 during app task switching. assertTrue(app.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime())); assertFalse(app2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime())); controller.getImeSourceProvider().setWindowContainer(mImeWindow, null, null); // Simulate appWin2 requests IME. appWin2.setRequestedVisibleTypes(ime(), ime()); mDisplayContent.setImeInputTarget(appWin2); mDisplayContent.setImeLayeringTarget(appWin2); assertEquals("appWin2 is the IME control target", appWin2, mDisplayContent.getImeControlTarget()); controller.getImeSourceProvider().onPostLayout(); // Expect all windows behind IME can receive IME insets visible. assertTrue("appWin1 has IME insets visible", appWin1.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime())); assertTrue("appWin2 has IME insets visible", appWin2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime())); // Simulate appWin2 plays closing transition to appWin1. appWin2.mActivityRecord.commitVisibility(false /* visible */, false /* performLayout */); assertNull("appWin1 does not have frozen insets", appWin1.getFrozenInsetsState()); assertNotNull("appWin2 has frozen insets", appWin2.getFrozenInsetsState()); mDisplayContent.setImeInputTarget(appWin1); mDisplayContent.setImeLayeringTarget(appWin1); assertEquals("appWin1 is the IME control target", appWin1, mDisplayContent.getImeControlTarget()); assertFalse("appWin1 does not have IME insets visible", appWin1.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime())); assertTrue("appWin2 still has IME insets visible, as they were frozen", appWin2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime())); } @SetupWindows(addWindows = { W_INPUT_METHOD }) @Test public void testAdjustImeInsetsVisibilityWhenSwitchingApps_toAppInMultiWindowMode() { final WindowState app = newWindowBuilder("app", TYPE_APPLICATION).build(); final WindowState app2 = newWindowBuilder("app2", TYPE_APPLICATION).setWindowingMode( WINDOWING_MODE_MULTI_WINDOW).setActivityType(ACTIVITY_TYPE_STANDARD).setDisplay( mDisplayContent).build(); final WindowState imeWindow = newWindowBuilder("imeWindow", TYPE_APPLICATION).build(); spyOn(imeWindow); doReturn(true).when(imeWindow).isVisible(); mDisplayContent.mInputMethodWindow = imeWindow; final var appWin1 = newWindowBuilder("appWin1", TYPE_APPLICATION) .setWindowingMode(WINDOWING_MODE_MULTI_WINDOW).build(); final var appWin2 = newWindowBuilder("appWin2", TYPE_APPLICATION).build(); makeWindowVisibleAndDrawn(mImeWindow); mDisplayContent.setRemoteInsetsController(createDisplayWindowInsetsController()); 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.setVisibleRequested(false); mDisplayContent.setImeLayeringTarget(app); mDisplayContent.setImeInputTarget(app); app.setRequestedVisibleTypes(ime(), ime()); assertTrue(mDisplayContent.shouldImeAttachedToApp()); controller.getImeSourceProvider().scheduleShowImePostLayout(app, ImeTracker.Token.empty()); 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().isSourceOrDefaultVisible(ID_IME, ime())); assertFalse(app2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime())); // 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); // Verify the IME insets is still visible on app, but not for app2 during task switching. assertTrue(app.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime())); assertFalse(app2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime())); controller.getImeSourceProvider().setWindowContainer(mImeWindow, null, null); // Simulate appWin1 in multi-window mode is going to background to switch to the // fullscreen appWin2 which requests IME. appWin1.mActivityRecord.commitVisibility(false /* visible */, false /* performLayout */); assertNotNull("appWin1 has frozen insets", appWin1.getFrozenInsetsState()); assertNull("appWin2 does not have frozen insets", appWin2.getFrozenInsetsState()); appWin2.setRequestedVisibleTypes(ime(), ime()); mDisplayContent.setImeInputTarget(appWin2); mDisplayContent.setImeLayeringTarget(appWin2); controller.getImeSourceProvider().onPostLayout(); assertFalse("appWin1 does not have IME insets visible, as it is in background", appWin1.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime())); assertTrue("appWin2 has IME insets visible", appWin2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime())); // Simulate appWin2 plays closing transition to appWin1. appWin2.mActivityRecord.commitVisibility(false /* visible */, false /* performLayout */); appWin1.mActivityRecord.commitVisibility(true /* visible */, false /* performLayout */); assertNull("appWin1 does not have frozen insets", appWin1.getFrozenInsetsState()); assertNotNull("appWin2 has frozen insets", appWin2.getFrozenInsetsState()); mDisplayContent.setImeInputTarget(appWin1); mDisplayContent.setImeLayeringTarget(appWin1); assertEquals("RemoteInsetsControlTarget is the IME control target", mDisplayContent.mRemoteInsetsControlTarget, mDisplayContent.getImeControlTarget()); assertFalse("appWin1 does not have IME insets visible", appWin1.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime())); assertTrue("appWin2 still has IME insets visible, as they were frozen", appWin2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime())); } @SetupWindows(addWindows = W_ACTIVITY) Loading