Update requested state after applying pending frames

When there is an insets animation, we will stop updating insets source
frames until the animation is done. The previous logic didn't update the
frames within the requested state while the animation is done. And the
frames was relied by InsetsPolicy while playing transient bar animation.
If the frames don't match the display, the insets would be wrong, and
the animation wouldn't be played correctly.

Fix: 161134197
Test: atest InsetsControllerTest
Merged-In: Id8f3c1956fbfe3ad16f167ff76297dde6c634e81
Change-Id: Id8f3c1956fbfe3ad16f167ff76297dde6c634e81
(cherry picked from commit 23c75281ef)
This commit is contained in:
Tiger Huang
2020-08-13 22:43:52 +08:00
parent 2c0137794d
commit dfc8abb1ff
2 changed files with 21 additions and 3 deletions

View File

@@ -1134,15 +1134,14 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
if (invokeCallback) {
control.cancel();
}
boolean stateChanged = false;
for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
RunningAnimation runningAnimation = mRunningAnimations.get(i);
if (runningAnimation.runner == control) {
mRunningAnimations.remove(i);
ArraySet<Integer> types = toInternalType(control.getTypes());
for (int j = types.size() - 1; j >= 0; j--) {
if (getSourceConsumer(types.valueAt(j)).notifyAnimationFinished()) {
mHost.notifyInsetsChanged();
}
stateChanged |= getSourceConsumer(types.valueAt(j)).notifyAnimationFinished();
}
if (invokeCallback && runningAnimation.startDispatched) {
dispatchAnimationEnd(runningAnimation.runner.getAnimation());
@@ -1150,6 +1149,10 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
break;
}
}
if (stateChanged) {
mHost.notifyInsetsChanged();
updateRequestedState();
}
}
private void applyLocalVisibilityOverride() {

View File

@@ -27,6 +27,7 @@ import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
import static android.view.WindowInsets.Type.ime;
import static android.view.WindowInsets.Type.navigationBars;
import static android.view.WindowInsets.Type.statusBars;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
@@ -742,6 +743,20 @@ public class InsetsControllerTest {
mController.onControlsChanged(createSingletonControl(ITYPE_IME));
assertEquals(newState.getSource(ITYPE_IME),
mTestHost.getModifiedState().peekSource(ITYPE_IME));
// The modified frames cannot be updated if there is an animation.
mController.onControlsChanged(createSingletonControl(ITYPE_NAVIGATION_BAR));
mController.hide(navigationBars());
newState = new InsetsState(mController.getState(), true /* copySource */);
newState.getSource(ITYPE_NAVIGATION_BAR).getFrame().top--;
mController.onStateChanged(newState);
assertNotEquals(newState.getSource(ITYPE_NAVIGATION_BAR),
mTestHost.getModifiedState().peekSource(ITYPE_NAVIGATION_BAR));
// The modified frames can be updated while the animation is done.
mController.cancelExistingAnimations();
assertEquals(newState.getSource(ITYPE_NAVIGATION_BAR),
mTestHost.getModifiedState().peekSource(ITYPE_NAVIGATION_BAR));
});
}