Merge "Prevent changing mFromState during insets resize animation" into main
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 1626924..8d884f2 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -713,11 +713,13 @@
new InsetsState.OnTraverseCallbacks() {
private @InsetsType int mTypes;
+ private InsetsState mFromState;
private InsetsState mToState;
@Override
public void onStart(InsetsState state1, InsetsState state2) {
mTypes = 0;
+ mFromState = null;
mToState = null;
}
@@ -734,9 +736,13 @@
return;
}
mTypes |= source1.getType();
+ if (mFromState == null) {
+ mFromState = new InsetsState();
+ }
if (mToState == null) {
mToState = new InsetsState();
}
+ mFromState.addSource(new InsetsSource(source1));
mToState.addSource(new InsetsSource(source2));
}
@@ -747,7 +753,7 @@
}
cancelExistingControllers(mTypes);
final InsetsAnimationControlRunner runner = new InsetsResizeAnimationRunner(
- mFrame, state1, mToState, RESIZE_INTERPOLATOR,
+ mFrame, mFromState, mToState, RESIZE_INTERPOLATOR,
ANIMATION_DURATION_RESIZE, mTypes, InsetsController.this);
if (mRunningAnimations.isEmpty()) {
mHost.notifyAnimationRunningStateChanged(true);
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index f05390d..ae7f465 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -32,6 +32,7 @@
import static android.view.WindowInsets.Type.navigationBars;
import static android.view.WindowInsets.Type.statusBars;
import static android.view.WindowInsets.Type.systemBars;
+import static android.view.WindowInsetsAnimation.Callback.DISPATCH_MODE_STOP;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
@@ -52,6 +53,9 @@
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+import android.annotation.NonNull;
import android.content.Context;
import android.graphics.Insets;
import android.graphics.Point;
@@ -80,6 +84,8 @@
import org.mockito.InOrder;
import org.mockito.Mockito;
+import java.util.ArrayList;
+import java.util.List;
import java.util.concurrent.CountDownLatch;
/**
@@ -668,30 +674,58 @@
}
@Test
- public void testResizeAnimation_withFlagAnimateResizing() {
+ public void testResizeAnimation_withFlagAnimateResizing() throws InterruptedException {
+ final int id = ID_NAVIGATION_BAR;
+ final @InsetsType int type = navigationBars();
+ final int fromInsetsHeight = 50;
+ final int toInsetsHeight = 60;
+ final ArrayList<WindowInsets> progressList = new ArrayList<>();
+ final CountDownLatch animationEndLatch = new CountDownLatch(1);
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
- final int id = ID_NAVIGATION_BAR;
- final @InsetsType int type = navigationBars();
final InsetsState state1 = new InsetsState();
state1.getOrCreateSource(id, type)
.setVisible(true)
- .setFrame(0, 0, 500, 50)
+ .setFrame(0, 0, 500, fromInsetsHeight)
.setFlags(FLAG_ANIMATE_RESIZING, FLAG_ANIMATE_RESIZING);
final InsetsState state2 = new InsetsState(state1, true /* copySources */);
- state2.peekSource(id).setFrame(0, 0, 500, 60);
+ state2.peekSource(id).setFrame(0, 0, 500, toInsetsHeight);
// New insets source won't cause the resize animation.
mController.onStateChanged(state1);
assertEquals("There must not be resize animation.", ANIMATION_TYPE_NONE,
mController.getAnimationType(type));
+ mViewRoot.getView().setWindowInsetsAnimationCallback(
+ new WindowInsetsAnimation.Callback(DISPATCH_MODE_STOP) {
+ @Override
+ public WindowInsets onProgress(
+ @NonNull WindowInsets insets,
+ @NonNull List<WindowInsetsAnimation> runningAnimations) {
+ progressList.add(insets);
+ return insets;
+ }
+
+ @Override
+ public void onEnd(@NonNull WindowInsetsAnimation animation) {
+ animationEndLatch.countDown();
+ }
+ });
+
// Changing frame of the source with FLAG_ANIMATE_RESIZING will cause the resize
// animation.
mController.onStateChanged(state2);
assertEquals("There must be resize animation.", ANIMATION_TYPE_RESIZE,
mController.getAnimationType(type));
+
+ mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw();
});
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+
+ assertTrue("Animation must be ended.", animationEndLatch.await(3, SECONDS));
+ assertEquals("The first insets height must be the same as `fromInsetsHeight`",
+ fromInsetsHeight, progressList.get(0).getInsets(type).top);
+ assertEquals("The last insets height must be the same as `toInsetsHeight`",
+ toInsetsHeight, progressList.get(progressList.size() - 1).getInsets(type).top);
}
@Test