Loading core/java/android/view/InsetsSourceConsumer.java +3 −1 Original line number Diff line number Diff line Loading @@ -176,7 +176,9 @@ public class InsetsSourceConsumer { // If we have a new leash, make sure visibility is up-to-date, even though we // didn't want to run an animation above. if (mController.getAnimationType(control.getType()) == ANIMATION_TYPE_NONE) { applyRequestedVisibilityToControl(); } // Remove the surface that owned by last control when it lost. if (!requestedVisible && lastControl == null) { Loading core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java +43 −4 Original line number Diff line number Diff line Loading @@ -18,8 +18,10 @@ package android.view; import static android.view.InsetsController.ANIMATION_TYPE_NONE; import static android.view.InsetsController.ANIMATION_TYPE_USER; import static android.view.InsetsSourceConsumer.ShowResult.SHOW_IMMEDIATELY; import static android.view.InsetsState.ITYPE_IME; import static android.view.InsetsState.ITYPE_STATUS_BAR; import static android.view.WindowInsets.Type.ime; import static android.view.WindowInsets.Type.statusBars; import static junit.framework.Assert.assertEquals; Loading @@ -28,6 +30,7 @@ import static junit.framework.TestCase.assertTrue; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; Loading Loading @@ -75,6 +78,7 @@ public class InsetsSourceConsumerTest { private boolean mRemoveSurfaceCalled = false; private InsetsController mController; private InsetsState mState; private ViewRootImpl mViewRoot; @Before public void setup() { Loading @@ -86,10 +90,9 @@ public class InsetsSourceConsumerTest { instrumentation.runOnMainSync(() -> { final Context context = instrumentation.getTargetContext(); // cannot mock ViewRootImpl since it's final. final ViewRootImpl viewRootImpl = new ViewRootImpl(context, context.getDisplayNoVerify()); mViewRoot = new ViewRootImpl(context, context.getDisplayNoVerify()); try { viewRootImpl.setView(new TextView(context), new LayoutParams(), null); mViewRoot.setView(new TextView(context), new LayoutParams(), null); } catch (BadTokenException e) { // activity isn't running, lets ignore BadTokenException. } Loading @@ -97,7 +100,7 @@ public class InsetsSourceConsumerTest { mSpyInsetsSource = Mockito.spy(new InsetsSource(ITYPE_STATUS_BAR)); mState.addSource(mSpyInsetsSource); mController = new InsetsController(new ViewRootInsetsControllerHost(viewRootImpl)); mController = new InsetsController(new ViewRootInsetsControllerHost(mViewRoot)); mConsumer = new InsetsSourceConsumer(ITYPE_STATUS_BAR, mState, () -> mMockTransaction, mController) { @Override Loading Loading @@ -207,4 +210,40 @@ public class InsetsSourceConsumerTest { }); } @Test public void testWontUpdateImeLeashVisibility_whenAnimation() { InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { InsetsState state = new InsetsState(); ViewRootInsetsControllerHost host = new ViewRootInsetsControllerHost(mViewRoot); InsetsController insetsController = new InsetsController(host, (controller, type) -> { if (type == ITYPE_IME) { return new InsetsSourceConsumer(ITYPE_IME, state, () -> mMockTransaction, controller) { @Override public int requestShow(boolean fromController) { return SHOW_IMMEDIATELY; } }; } return new InsetsSourceConsumer(type, controller.getState(), Transaction::new, controller); }, host.getHandler()); InsetsSourceConsumer imeConsumer = insetsController.getSourceConsumer(ITYPE_IME); // Initial IME insets source control with its leash. imeConsumer.setControl(new InsetsSourceControl(ITYPE_IME, mLeash, false /* initialVisible */, new Point(), Insets.NONE), new int[1], new int[1]); reset(mMockTransaction); // Verify when the app requests controlling show IME animation, the IME leash // visibility won't be updated when the consumer received the same leash in setControl. insetsController.controlWindowInsetsAnimation(ime(), 0L, null /* interpolator */, null /* cancellationSignal */, null /* listener */); assertTrue(insetsController.getAnimationType(ITYPE_IME) == ANIMATION_TYPE_USER); imeConsumer.setControl(new InsetsSourceControl(ITYPE_IME, mLeash, true /* initialVisible */, new Point(), Insets.NONE), new int[1], new int[1]); verify(mMockTransaction, never()).show(mLeash); }); } } services/core/java/com/android/server/wm/DisplayContent.java +11 −4 Original line number Diff line number Diff line Loading @@ -4388,13 +4388,20 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp */ @VisibleForTesting InsetsControlTarget computeImeControlTarget() { if (mImeInputTarget == null) { // A special case that if there is no IME input target while the IME is being killed, // in case seeing unexpected IME surface visibility change when delivering the IME leash // to the remote insets target during the IME restarting, but the focus window is not in // multi-windowing mode, return null target until the next input target updated. return null; } final WindowState imeInputTarget = mImeInputTarget.getWindowState(); if (!isImeControlledByApp() && mRemoteInsetsControlTarget != null || (mImeInputTarget != null && getImeHostOrFallback(mImeInputTarget.getWindowState()) == mRemoteInsetsControlTarget)) { || getImeHostOrFallback(imeInputTarget) == mRemoteInsetsControlTarget) { return mRemoteInsetsControlTarget; } else { return mImeInputTarget != null ? mImeInputTarget.getWindowState() : null; return imeInputTarget; } } Loading services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +9 −1 Original line number Diff line number Diff line Loading @@ -1251,7 +1251,15 @@ public class DisplayContentTests extends WindowTestsBase { public void testComputeImeControlTarget() throws Exception { final DisplayContent dc = createNewDisplay(); dc.setRemoteInsetsController(createDisplayWindowInsetsController()); dc.setImeInputTarget(createWindow(null, TYPE_BASE_APPLICATION, "app")); dc.mCurrentFocus = createWindow(null, TYPE_BASE_APPLICATION, "app"); // Expect returning null IME control target when the focus window has not yet been the // IME input target (e.g. IME is restarting) in fullscreen windowing mode. dc.setImeInputTarget(null); assertFalse(dc.mCurrentFocus.inMultiWindowMode()); assertNull(dc.computeImeControlTarget()); dc.setImeInputTarget(dc.mCurrentFocus); dc.setImeLayeringTarget(dc.getImeInputTarget().getWindowState()); assertEquals(dc.getImeInputTarget().getWindowState(), dc.computeImeControlTarget()); } Loading Loading
core/java/android/view/InsetsSourceConsumer.java +3 −1 Original line number Diff line number Diff line Loading @@ -176,7 +176,9 @@ public class InsetsSourceConsumer { // If we have a new leash, make sure visibility is up-to-date, even though we // didn't want to run an animation above. if (mController.getAnimationType(control.getType()) == ANIMATION_TYPE_NONE) { applyRequestedVisibilityToControl(); } // Remove the surface that owned by last control when it lost. if (!requestedVisible && lastControl == null) { Loading
core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java +43 −4 Original line number Diff line number Diff line Loading @@ -18,8 +18,10 @@ package android.view; import static android.view.InsetsController.ANIMATION_TYPE_NONE; import static android.view.InsetsController.ANIMATION_TYPE_USER; import static android.view.InsetsSourceConsumer.ShowResult.SHOW_IMMEDIATELY; import static android.view.InsetsState.ITYPE_IME; import static android.view.InsetsState.ITYPE_STATUS_BAR; import static android.view.WindowInsets.Type.ime; import static android.view.WindowInsets.Type.statusBars; import static junit.framework.Assert.assertEquals; Loading @@ -28,6 +30,7 @@ import static junit.framework.TestCase.assertTrue; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; Loading Loading @@ -75,6 +78,7 @@ public class InsetsSourceConsumerTest { private boolean mRemoveSurfaceCalled = false; private InsetsController mController; private InsetsState mState; private ViewRootImpl mViewRoot; @Before public void setup() { Loading @@ -86,10 +90,9 @@ public class InsetsSourceConsumerTest { instrumentation.runOnMainSync(() -> { final Context context = instrumentation.getTargetContext(); // cannot mock ViewRootImpl since it's final. final ViewRootImpl viewRootImpl = new ViewRootImpl(context, context.getDisplayNoVerify()); mViewRoot = new ViewRootImpl(context, context.getDisplayNoVerify()); try { viewRootImpl.setView(new TextView(context), new LayoutParams(), null); mViewRoot.setView(new TextView(context), new LayoutParams(), null); } catch (BadTokenException e) { // activity isn't running, lets ignore BadTokenException. } Loading @@ -97,7 +100,7 @@ public class InsetsSourceConsumerTest { mSpyInsetsSource = Mockito.spy(new InsetsSource(ITYPE_STATUS_BAR)); mState.addSource(mSpyInsetsSource); mController = new InsetsController(new ViewRootInsetsControllerHost(viewRootImpl)); mController = new InsetsController(new ViewRootInsetsControllerHost(mViewRoot)); mConsumer = new InsetsSourceConsumer(ITYPE_STATUS_BAR, mState, () -> mMockTransaction, mController) { @Override Loading Loading @@ -207,4 +210,40 @@ public class InsetsSourceConsumerTest { }); } @Test public void testWontUpdateImeLeashVisibility_whenAnimation() { InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { InsetsState state = new InsetsState(); ViewRootInsetsControllerHost host = new ViewRootInsetsControllerHost(mViewRoot); InsetsController insetsController = new InsetsController(host, (controller, type) -> { if (type == ITYPE_IME) { return new InsetsSourceConsumer(ITYPE_IME, state, () -> mMockTransaction, controller) { @Override public int requestShow(boolean fromController) { return SHOW_IMMEDIATELY; } }; } return new InsetsSourceConsumer(type, controller.getState(), Transaction::new, controller); }, host.getHandler()); InsetsSourceConsumer imeConsumer = insetsController.getSourceConsumer(ITYPE_IME); // Initial IME insets source control with its leash. imeConsumer.setControl(new InsetsSourceControl(ITYPE_IME, mLeash, false /* initialVisible */, new Point(), Insets.NONE), new int[1], new int[1]); reset(mMockTransaction); // Verify when the app requests controlling show IME animation, the IME leash // visibility won't be updated when the consumer received the same leash in setControl. insetsController.controlWindowInsetsAnimation(ime(), 0L, null /* interpolator */, null /* cancellationSignal */, null /* listener */); assertTrue(insetsController.getAnimationType(ITYPE_IME) == ANIMATION_TYPE_USER); imeConsumer.setControl(new InsetsSourceControl(ITYPE_IME, mLeash, true /* initialVisible */, new Point(), Insets.NONE), new int[1], new int[1]); verify(mMockTransaction, never()).show(mLeash); }); } }
services/core/java/com/android/server/wm/DisplayContent.java +11 −4 Original line number Diff line number Diff line Loading @@ -4388,13 +4388,20 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp */ @VisibleForTesting InsetsControlTarget computeImeControlTarget() { if (mImeInputTarget == null) { // A special case that if there is no IME input target while the IME is being killed, // in case seeing unexpected IME surface visibility change when delivering the IME leash // to the remote insets target during the IME restarting, but the focus window is not in // multi-windowing mode, return null target until the next input target updated. return null; } final WindowState imeInputTarget = mImeInputTarget.getWindowState(); if (!isImeControlledByApp() && mRemoteInsetsControlTarget != null || (mImeInputTarget != null && getImeHostOrFallback(mImeInputTarget.getWindowState()) == mRemoteInsetsControlTarget)) { || getImeHostOrFallback(imeInputTarget) == mRemoteInsetsControlTarget) { return mRemoteInsetsControlTarget; } else { return mImeInputTarget != null ? mImeInputTarget.getWindowState() : null; return imeInputTarget; } } Loading
services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +9 −1 Original line number Diff line number Diff line Loading @@ -1251,7 +1251,15 @@ public class DisplayContentTests extends WindowTestsBase { public void testComputeImeControlTarget() throws Exception { final DisplayContent dc = createNewDisplay(); dc.setRemoteInsetsController(createDisplayWindowInsetsController()); dc.setImeInputTarget(createWindow(null, TYPE_BASE_APPLICATION, "app")); dc.mCurrentFocus = createWindow(null, TYPE_BASE_APPLICATION, "app"); // Expect returning null IME control target when the focus window has not yet been the // IME input target (e.g. IME is restarting) in fullscreen windowing mode. dc.setImeInputTarget(null); assertFalse(dc.mCurrentFocus.inMultiWindowMode()); assertNull(dc.computeImeControlTarget()); dc.setImeInputTarget(dc.mCurrentFocus); dc.setImeLayeringTarget(dc.getImeInputTarget().getWindowState()); assertEquals(dc.getImeInputTarget().getWindowState(), dc.computeImeControlTarget()); } Loading