diff options
| -rw-r--r-- | core/java/android/view/InsetsController.java | 26 | ||||
| -rw-r--r-- | core/tests/coretests/src/android/view/InsetsControllerTest.java | 41 |
2 files changed, 60 insertions, 7 deletions
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index c6be91fa1bf5..a679b3740fd9 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -737,7 +737,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } } - final boolean hasControl = mTmpControlArray.size() > 0; + boolean requestedStateStale = false; final int[] showTypes = new int[1]; final int[] hideTypes = new int[1]; @@ -754,9 +754,26 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation // Ensure to create source consumers if not available yet. for (int i = mTmpControlArray.size() - 1; i >= 0; i--) { final InsetsSourceControl control = mTmpControlArray.valueAt(i); - InsetsSourceConsumer consumer = getSourceConsumer(control.getType()); + final @InternalInsetsType int type = control.getType(); + final InsetsSourceConsumer consumer = getSourceConsumer(type); consumer.setControl(control, showTypes, hideTypes); + if (!requestedStateStale) { + final boolean requestedVisible = consumer.isRequestedVisible(); + + // We might have changed our requested visibilities while we don't have the control, + // so we need to update our requested state once we have control. Otherwise, our + // requested state at the server side might be incorrect. + final boolean requestedVisibilityChanged = + requestedVisible != mRequestedState.getSourceOrDefaultVisibility(type); + + // The IME client visibility will be reset by insets source provider while updating + // control, so if IME is requested visible, we need to send the request to server. + final boolean imeRequestedVisible = type == ITYPE_IME && requestedVisible; + + requestedStateStale = requestedVisibilityChanged || imeRequestedVisible; + } + } mTmpControlArray.clear(); @@ -772,10 +789,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation if (hideTypes[0] != 0) { applyAnimation(hideTypes[0], false /* show */, false /* fromIme */); } - if (hasControl && mRequestedState.hasSources()) { - // We might have changed our requested visibilities while we don't have the control, - // so we need to update our requested state once we have control. Otherwise, our - // requested state at the server side might be incorrect. + if (requestedStateStale) { updateRequestedState(); } } diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java index 702f2fa65487..c36f1067149e 100644 --- a/core/tests/coretests/src/android/view/InsetsControllerTest.java +++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java @@ -691,18 +691,57 @@ public class InsetsControllerTest { @Test public void testRequestedState() { InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { + + // The modified state can be controlled when we have control. mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR)); mController.hide(statusBars()); assertFalse(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible()); - mController.onControlsChanged(new InsetsSourceControl[0]); + + // The modified state won't be changed while losing control. + mController.onControlsChanged(null /* activeControls */); assertFalse(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible()); + + // The modified state won't be changed while state changed while we don't have control. InsetsState newState = new InsetsState(mController.getState(), true /* copySource */); mController.onStateChanged(newState); assertFalse(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible()); + + // The modified state won't be changed while controlling an insets without having the + // control. mController.show(statusBars()); assertFalse(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible()); + + // The modified state can be updated while gaining control. mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR)); assertTrue(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible()); + + // The modified state can still be updated if the local state and the requested state + // are the same. + mController.onControlsChanged(null /* activeControls */); + mController.hide(statusBars()); + newState = new InsetsState(mController.getState(), true /* copySource */); + newState.getSource(ITYPE_STATUS_BAR).setVisible(false); + mController.onStateChanged(newState); + mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR)); + assertFalse(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible()); + + // The modified state will always be updated while receiving IME control if IME is + // requested visible. + mController.getSourceConsumer(ITYPE_IME).show(false /* fromIme */); + newState = new InsetsState(mController.getState(), true /* copySource */); + newState.getSource(ITYPE_IME).setVisible(true); + newState.getSource(ITYPE_IME).setFrame(1, 2, 3, 4); + mController.onStateChanged(newState); + mController.onControlsChanged(createSingletonControl(ITYPE_IME)); + assertEquals(newState.getSource(ITYPE_IME), + mTestHost.getModifiedState().peekSource(ITYPE_IME)); + newState = new InsetsState(mController.getState(), true /* copySource */); + newState.getSource(ITYPE_IME).setVisible(true); + newState.getSource(ITYPE_IME).setFrame(5, 6, 7, 8); + mController.onStateChanged(newState); + mController.onControlsChanged(createSingletonControl(ITYPE_IME)); + assertEquals(newState.getSource(ITYPE_IME), + mTestHost.getModifiedState().peekSource(ITYPE_IME)); }); } |