diff options
| author | 2020-06-05 17:06:07 +0200 | |
|---|---|---|
| committer | 2020-06-05 17:15:26 +0200 | |
| commit | 021f4a71402a9e0dba34dcbb8e56cf851b74fd2e (patch) | |
| tree | 03418082f9f6b97f967197f78a16b8dbfaa86571 | |
| parent | b0033693a89923a80f9973e41b45ddcef2ec7ae9 (diff) | |
Insets: Fix stuck mPendingFrame
Fixes an issue where the mPendingFrame was not properly cleared
if we re-applied the current frame.
Fixes: 156762386
Test: InsetsSourceConsumerTest
Change-Id: I9f0ebfafac44e1b4b87ea9d3408e64ba34bca2ec
| -rw-r--r-- | core/java/android/view/InsetsSourceConsumer.java | 10 | ||||
| -rw-r--r-- | core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java | 49 |
2 files changed, 57 insertions, 2 deletions
diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java index df3ac8787b57..eb1d50a6e48c 100644 --- a/core/java/android/view/InsetsSourceConsumer.java +++ b/core/java/android/view/InsetsSourceConsumer.java @@ -21,6 +21,8 @@ import static android.view.InsetsController.AnimationType; import static android.view.InsetsState.getDefaultVisibility; import static android.view.InsetsState.toPublicType; +import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE; + import android.annotation.IntDef; import android.annotation.Nullable; import android.graphics.Rect; @@ -253,10 +255,13 @@ public class InsetsSourceConsumer { // no-op for types that always return ShowResult#SHOW_IMMEDIATELY. } - void updateSource(InsetsSource newSource) { + @VisibleForTesting(visibility = PACKAGE) + public void updateSource(InsetsSource newSource) { InsetsSource source = mState.peekSource(mType); if (source == null || mController.getAnimationType(mType) == ANIMATION_TYPE_NONE || source.getFrame().equals(newSource.getFrame())) { + mPendingFrame = null; + mPendingVisibleFrame = null; mState.addSource(newSource); return; } @@ -273,7 +278,8 @@ public class InsetsSourceConsumer { mState.addSource(newSource); } - boolean notifyAnimationFinished() { + @VisibleForTesting(visibility = PACKAGE) + public boolean notifyAnimationFinished() { if (mPendingFrame != null) { InsetsSource source = mState.getSource(mType); source.setFrame(mPendingFrame); diff --git a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java index 25f94131f820..bf7f339a8484 100644 --- a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java +++ b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java @@ -16,6 +16,9 @@ package android.view; +import static android.view.InsetsController.ANIMATION_TYPE_NONE; +import static android.view.InsetsController.ANIMATION_TYPE_USER; +import static android.view.InsetsState.ITYPE_IME; import static android.view.InsetsState.ITYPE_STATUS_BAR; import static android.view.WindowInsets.Type.statusBars; @@ -23,14 +26,18 @@ import static junit.framework.Assert.assertEquals; import static junit.framework.TestCase.assertFalse; import static junit.framework.TestCase.assertTrue; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; import android.app.Instrumentation; import android.content.Context; import android.graphics.Point; +import android.graphics.Rect; import android.platform.test.annotations.Presubmit; import android.view.SurfaceControl.Transaction; import android.view.WindowManager.BadTokenException; @@ -122,6 +129,48 @@ public class InsetsSourceConsumerTest { } @Test + public void testPendingStates() { + InsetsState state = new InsetsState(); + InsetsController controller = mock(InsetsController.class); + InsetsSourceConsumer consumer = new InsetsSourceConsumer( + ITYPE_IME, state, null, controller); + + when(controller.getAnimationType(anyInt())).thenReturn(ANIMATION_TYPE_NONE); + + InsetsSource source = new InsetsSource(ITYPE_IME); + source.setFrame(0, 1, 2, 3); + consumer.updateSource(new InsetsSource(source)); + + when(controller.getAnimationType(anyInt())).thenReturn(ANIMATION_TYPE_USER); + + // While we're animating, updates are delayed + source.setFrame(4, 5, 6, 7); + consumer.updateSource(new InsetsSource(source)); + assertEquals(new Rect(0, 1, 2, 3), state.peekSource(ITYPE_IME).getFrame()); + + // Finish the animation, now the pending frame should be applied + when(controller.getAnimationType(anyInt())).thenReturn(ANIMATION_TYPE_NONE); + assertTrue(consumer.notifyAnimationFinished()); + assertEquals(new Rect(4, 5, 6, 7), state.peekSource(ITYPE_IME).getFrame()); + + when(controller.getAnimationType(anyInt())).thenReturn(ANIMATION_TYPE_USER); + + // Animating again, updates are delayed + source.setFrame(8, 9, 10, 11); + consumer.updateSource(new InsetsSource(source)); + assertEquals(new Rect(4, 5, 6, 7), state.peekSource(ITYPE_IME).getFrame()); + + // Updating with the current frame triggers a different code path, verify this clears + // the pending 8, 9, 10, 11 frame: + source.setFrame(4, 5, 6, 7); + consumer.updateSource(new InsetsSource(source)); + + when(controller.getAnimationType(anyInt())).thenReturn(ANIMATION_TYPE_NONE); + assertFalse(consumer.notifyAnimationFinished()); + assertEquals(new Rect(4, 5, 6, 7), state.peekSource(ITYPE_IME).getFrame()); + } + + @Test public void testRestore() { InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { mConsumer.setControl(null, new int[1], new int[1]); |