summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Tiger Huang <tigerhuang@google.com> 2020-07-09 02:13:02 +0800
committer Tiger Huang <tigerhuang@google.com> 2020-07-10 18:04:57 +0800
commitff06666dbab2ed2f24e9b332308bb09190ac14bd (patch)
treeacc8f62a45c98425e7a43b0e2f8f6a114a08cfc8
parent31a8993720df291719712a0e489c50a84215f74f (diff)
Update requested state by comparing with source consumer
If the local state and mLastDispatchedState are the same, the logic in onStateChanged will skip updating the requested state. This could be an issue, for example, a new focused window requested to hide status bar, but status bar has already been hidden by the previous focused window, so the new focused window will never send the requested state to server. This can easily happen when an immersive activity is re-created due to the configuration change. This CL updates the requested state if any visibility within it is not the same as the requested visibility of the source consumer, while receiving controls. Fix: 160854328 Test: atest InsetsControllerTest Test: Swipe to show transient bars after rotating an immersive activity Change-Id: I5d9acb1b59252fa80e66070db86b2555764588da
-rw-r--r--core/java/android/view/InsetsController.java26
-rw-r--r--core/tests/coretests/src/android/view/InsetsControllerTest.java41
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));
});
}