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
This commit is contained in:
Adrian Roos
2020-06-05 17:06:07 +02:00
parent b0033693a8
commit 021f4a7140
2 changed files with 57 additions and 2 deletions

View File

@@ -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);

View File

@@ -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;
@@ -121,6 +128,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(() -> {