diff options
7 files changed, 83 insertions, 38 deletions
diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java index 9247f4a29bdd..44ecb545c37f 100644 --- a/core/java/android/view/InsetsAnimationControlImpl.java +++ b/core/java/android/view/InsetsAnimationControlImpl.java @@ -76,8 +76,8 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll private boolean mFinished; private boolean mCancelled; private boolean mShownOnFinish; - private float mCurrentAlpha; - private float mPendingAlpha; + private float mCurrentAlpha = 1.0f; + private float mPendingAlpha = 1.0f; @VisibleForTesting public InsetsAnimationControlImpl(SparseArray<InsetsSourceControl> controls, Rect frame, @@ -153,7 +153,7 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll } mPendingFraction = sanitize(fraction); mPendingInsets = sanitize(insets); - mPendingAlpha = 1 - sanitize(alpha); + mPendingAlpha = sanitize(alpha); mController.scheduleApplyChangeInsets(); } @@ -182,7 +182,8 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll mController.applySurfaceParams(params.toArray(new SurfaceParams[params.size()])); mCurrentInsets = mPendingInsets; mAnimation.setFraction(mPendingFraction); - mCurrentAlpha = 1 - alphaOffset; + mCurrentAlpha = mPendingAlpha; + mAnimation.setAlpha(mPendingAlpha); if (mFinished) { mController.notifyFinished(this, mShownOnFinish); } @@ -238,7 +239,8 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll private Insets getInsetsFromState(InsetsState state, Rect frame, @Nullable @InternalInsetsSide SparseIntArray typeSideMap) { - return state.calculateInsets(frame, false /* isScreenRound */, + return state.calculateInsets(frame, null /* ignoringVisibilityState */, + false /* isScreenRound */, false /* alwaysConsumeSystemBars */, null /* displayCutout */, null /* legacyContentInsets */, null /* legacyStableInsets */, LayoutParams.SOFT_INPUT_ADJUST_RESIZE /* legacySoftInputMode*/, @@ -257,8 +259,8 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll return alpha >= 1 ? 1 : (alpha <= 0 ? 0 : alpha); } - private void updateLeashesForSide(@InternalInsetsSide int side, int offset, int inset, - int maxInset, ArrayList<SurfaceParams> surfaceParams, InsetsState state, Float alpha) { + private void updateLeashesForSide(@InternalInsetsSide int side, int offset, int maxInset, + int inset, ArrayList<SurfaceParams> surfaceParams, InsetsState state, Float alpha) { ArraySet<InsetsSourceControl> items = mSideSourceMap.get(side); if (items == null) { return; @@ -273,6 +275,7 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll mTmpFrame.set(source.getFrame()); addTranslationToMatrix(side, offset, mTmpMatrix, mTmpFrame); + state.getSource(source.getType()).setVisible(side == ISIDE_FLOATING || inset != 0); state.getSource(source.getType()).setFrame(mTmpFrame); // If the system is controlling the insets source, the leash can be null. diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index 4cb8e1388858..573d8fc65c84 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -233,6 +233,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation final InsetsAnimationControlImpl control; final @AnimationType int type; + + /** + * Whether {@link WindowInsetsAnimation.Callback#onStart(WindowInsetsAnimation, Bounds)} has + * been dispatched already for this animation. + */ + boolean startDispatched; } /** @@ -276,9 +282,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation private final SparseArray<InsetsSourceControl> mTmpControlArray = new SparseArray<>(); private final ArrayList<RunningAnimation> mRunningAnimations = new ArrayList<>(); - private final ArrayList<WindowInsetsAnimation> mRunningInsetsAnimations = new ArrayList<>(); - private final List<WindowInsetsAnimation> mUnmodifiableRunningInsetsAnimations = - Collections.unmodifiableList(mRunningInsetsAnimations); + private final ArrayList<WindowInsetsAnimation> mTmpRunningAnims = new ArrayList<>(); + private final List<WindowInsetsAnimation> mUnmodifiableTmpRunningAnims = + Collections.unmodifiableList(mTmpRunningAnims); private final ArrayList<InsetsAnimationControlImpl> mTmpFinishedControls = new ArrayList<>(); private WindowInsets mLastInsets; @@ -294,6 +300,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation private int mLastLegacySoftInputMode; private int mLastLegacySystemUiFlags; + private DisplayCutout mLastDisplayCutout; private boolean mStartingAnimation; private SyncRtSurfaceTransactionApplier mApplier; @@ -329,20 +336,28 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } mTmpFinishedControls.clear(); + mTmpRunningAnims.clear(); InsetsState state = new InsetsState(mState, true /* copySources */); for (int i = mRunningAnimations.size() - 1; i >= 0; i--) { - InsetsAnimationControlImpl control = mRunningAnimations.get(i).control; + RunningAnimation runningAnimation = mRunningAnimations.get(i); + InsetsAnimationControlImpl control = runningAnimation.control; + + // Keep track of running animation to be dispatched. Aggregate it here such that if + // it gets finished within applyChangeInsets we still dispatch it to onProgress. + if (runningAnimation.startDispatched) { + mTmpRunningAnims.add(control.getAnimation()); + } if (control.applyChangeInsets(state)) { mTmpFinishedControls.add(control); } } - WindowInsets insets = state.calculateInsets(mFrame, mLastInsets.isRound(), - mLastInsets.shouldAlwaysConsumeSystemBars(), mLastInsets.getDisplayCutout(), - mLastLegacyContentInsets, mLastLegacyStableInsets, mLastLegacySoftInputMode, - mLastLegacySystemUiFlags, null /* typeSideMap */); + WindowInsets insets = state.calculateInsets(mFrame, mState /* ignoringVisibilityState*/, + mLastInsets.isRound(), mLastInsets.shouldAlwaysConsumeSystemBars(), + mLastDisplayCutout, mLastLegacyContentInsets, mLastLegacyStableInsets, + mLastLegacySoftInputMode, mLastLegacySystemUiFlags, null /* typeSideMap */); mViewRoot.mView.dispatchWindowInsetsAnimationProgress(insets, - mUnmodifiableRunningInsetsAnimations); + mUnmodifiableTmpRunningAnims); for (int i = mTmpFinishedControls.size() - 1; i >= 0; i--) { dispatchAnimationEnd(mTmpFinishedControls.get(i).getAnimation()); @@ -394,8 +409,10 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation mLastLegacyStableInsets.set(legacyStableInsets); mLastLegacySoftInputMode = legacySoftInputMode; mLastLegacySystemUiFlags = legacySystemUiFlags; - mLastInsets = mState.calculateInsets(mFrame, isScreenRound, alwaysConsumeSystemBars, cutout, - legacyContentInsets, legacyStableInsets, legacySoftInputMode, legacySystemUiFlags, + mLastDisplayCutout = cutout; + mLastInsets = mState.calculateInsets(mFrame, null /* ignoringVisibilityState*/, + isScreenRound, alwaysConsumeSystemBars, cutout, legacyContentInsets, + legacyStableInsets, legacySoftInputMode, legacySystemUiFlags, null /* typeSideMap */); return mLastInsets; } @@ -584,7 +601,6 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation frame, mState, listener, typesReady, this, durationMs, interpolator, fade, layoutInsetsDuringAnimation, animationType); mRunningAnimations.add(new RunningAnimation(controller, animationType)); - mRunningInsetsAnimations.add(controller.getAnimation()); cancellationSignal.setOnCancelListener(controller::onCancelled); return cancellationSignal; } @@ -736,7 +752,6 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation for (int i = mRunningAnimations.size() - 1; i >= 0; i--) { if (mRunningAnimations.get(i).control == control) { mRunningAnimations.remove(i); - mRunningInsetsAnimations.remove(i); break; } } @@ -903,6 +918,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation if (controller.isCancelled()) { return true; } + for (int i = mRunningAnimations.size() - 1; i >= 0; i--) { + RunningAnimation runningAnimation = mRunningAnimations.get(i); + if (runningAnimation.control == controller) { + runningAnimation.startDispatched = true; + } + } mViewRoot.mView.dispatchWindowInsetsAnimationStart(animation, bounds); mStartingAnimation = true; listener.onReady(controller, types); diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java index 6d07a13091bd..92ac4259c349 100644 --- a/core/java/android/view/InsetsSourceConsumer.java +++ b/core/java/android/view/InsetsSourceConsumer.java @@ -160,7 +160,8 @@ public class InsetsSourceConsumer { } boolean applyLocalVisibilityOverride() { - final boolean isVisible = mState.getSource(mType).isVisible(); + InsetsSource source = mState.peekSource(mType); + final boolean isVisible = source != null && source.isVisible(); final boolean hasControl = mSourceControl != null; // We still need to let the legacy app know the visibility change even if we don't have the diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java index c877c454be91..b740c58ec15f 100644 --- a/core/java/android/view/InsetsState.java +++ b/core/java/android/view/InsetsState.java @@ -147,10 +147,13 @@ public class InsetsState implements Parcelable { * Calculates {@link WindowInsets} based on the current source configuration. * * @param frame The frame to calculate the insets relative to. + * @param ignoringVisibilityState {@link InsetsState} used to calculate + * {@link WindowInsets#getInsetsIgnoringVisibility(int)} information, or pass + * {@code null} to use this state to calculate that information. * @return The calculated insets. */ - public WindowInsets calculateInsets(Rect frame, boolean isScreenRound, - boolean alwaysConsumeSystemBars, DisplayCutout cutout, + public WindowInsets calculateInsets(Rect frame, @Nullable InsetsState ignoringVisibilityState, + boolean isScreenRound, boolean alwaysConsumeSystemBars, DisplayCutout cutout, @Nullable Rect legacyContentInsets, @Nullable Rect legacyStableInsets, int legacySoftInputMode, int legacySystemUiFlags, @Nullable @InternalInsetsSide SparseIntArray typeSideMap) { @@ -188,8 +191,15 @@ public class InsetsState implements Parcelable { // IME won't be reported in max insets as the size depends on the EditorInfo of the IME // target. if (source.getType() != ITYPE_IME) { - processSource(source, relativeFrameMax, true /* ignoreVisibility */, - typeMaxInsetsMap, null /* typeSideMap */, null /* typeVisibilityMap */); + InsetsSource ignoringVisibilitySource = ignoringVisibilityState != null + ? ignoringVisibilityState.getSource(type) + : source; + if (ignoringVisibilitySource == null) { + continue; + } + processSource(ignoringVisibilitySource, relativeFrameMax, + true /* ignoreVisibility */, typeMaxInsetsMap, null /* typeSideMap */, + null /* typeVisibilityMap */); } } final int softInputAdjustMode = legacySoftInputMode & SOFT_INPUT_MASK_ADJUST; @@ -297,6 +307,10 @@ public class InsetsState implements Parcelable { return mSources.computeIfAbsent(type, InsetsSource::new); } + public @Nullable InsetsSource peekSource(@InternalInsetsType int type) { + return mSources.get(type); + } + public void setDisplayFrame(Rect frame) { mDisplayFrame.set(frame); } diff --git a/core/java/android/view/WindowInsetsAnimation.java b/core/java/android/view/WindowInsetsAnimation.java index 396da4acb5bc..e32648809f8f 100644 --- a/core/java/android/view/WindowInsetsAnimation.java +++ b/core/java/android/view/WindowInsetsAnimation.java @@ -264,6 +264,11 @@ public final class WindowInsetsAnimation { WindowInsets.insetInsets( mUpperBound, insets.left, insets.top, insets.right, insets.bottom)); } + + @Override + public String toString() { + return "Bounds{lower=" + mLowerBound + " upper=" + mUpperBound + "}"; + } } /** diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java index 79ac2b77dda5..1d8e0a3186e8 100644 --- a/core/tests/coretests/src/android/view/InsetsStateTest.java +++ b/core/tests/coretests/src/android/view/InsetsStateTest.java @@ -72,8 +72,8 @@ public class InsetsStateTest { mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300)); mState.getSource(ITYPE_IME).setVisible(true); SparseIntArray typeSideMap = new SparseIntArray(); - WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false, - DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_RESIZE, 0, typeSideMap); + WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, + false, DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_RESIZE, 0, typeSideMap); assertEquals(Insets.of(0, 100, 0, 100), insets.getSystemWindowInsets()); assertEquals(Insets.of(0, 100, 0, 100), insets.getInsets(Type.all())); assertEquals(ISIDE_TOP, typeSideMap.get(ITYPE_STATUS_BAR)); @@ -91,8 +91,8 @@ public class InsetsStateTest { mState.getSource(ITYPE_NAVIGATION_BAR).setVisible(true); mState.getSource(ITYPE_IME).setFrame(new Rect(0, 100, 100, 300)); mState.getSource(ITYPE_IME).setVisible(true); - WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false, - DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_RESIZE, 0, null); + WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, + false, DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_RESIZE, 0, null); assertEquals(100, insets.getStableInsetBottom()); assertEquals(Insets.of(0, 0, 0, 100), insets.getInsetsIgnoringVisibility(Type.systemBars())); assertEquals(Insets.of(0, 0, 0, 200), insets.getSystemWindowInsets()); @@ -110,8 +110,8 @@ public class InsetsStateTest { mState.getSource(ITYPE_STATUS_BAR).setVisible(true); mState.getSource(ITYPE_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300)); mState.getSource(ITYPE_NAVIGATION_BAR).setVisible(true); - WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false, - DisplayCutout.NO_CUTOUT, null, null, 0, 0, null); + WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, + false, DisplayCutout.NO_CUTOUT, null, null, 0, 0, null); assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets()); assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(Type.statusBars())); assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(Type.navigationBars())); @@ -126,8 +126,8 @@ public class InsetsStateTest { mState.getSource(ITYPE_STATUS_BAR).setVisible(true); mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300)); mState.getSource(ITYPE_IME).setVisible(true); - WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false, - DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_NOTHING, 0, null); + WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, + false, DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_NOTHING, 0, null); assertEquals(0, insets.getSystemWindowInsetBottom()); assertEquals(100, insets.getInsets(ime()).bottom); assertTrue(insets.isVisible(ime())); @@ -142,11 +142,11 @@ public class InsetsStateTest { mState.getSource(ITYPE_STATUS_BAR).setVisible(false); mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300)); mState.getSource(ITYPE_IME).setVisible(true); - WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false, - DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_NOTHING, + WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, + false, DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_NOTHING, SYSTEM_UI_FLAG_LAYOUT_STABLE, null); assertEquals(100, insets.getSystemWindowInsetTop()); - insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false, + insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, false, DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_NOTHING, 0 /* legacySystemUiFlags */, null); assertEquals(0, insets.getSystemWindowInsetTop()); @@ -160,7 +160,7 @@ public class InsetsStateTest { mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300)); mState.getSource(ITYPE_IME).setVisible(true); mState.removeSource(ITYPE_IME); - WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false, + WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, false, DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_RESIZE, 0, null); assertEquals(0, insets.getSystemWindowInsetBottom()); } diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java index 375d9bbbd4fe..be9fcbf19f12 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java @@ -328,7 +328,8 @@ public class DividerView extends FrameLayout implements OnTouchListener, // Our window doesn't cover entire display, so we use the display frame to re-calculate // the insets. final InsetsState state = getWindowInsetsController().getState(); - insets = state.calculateInsets(state.getDisplayFrame(), insets.isRound(), + insets = state.calculateInsets(state.getDisplayFrame(), + null /* ignoringVisibilityState */, insets.isRound(), insets.shouldAlwaysConsumeSystemBars(), insets.getDisplayCutout(), null /* legacyContentInsets */, null /* legacyStableInsets */, 0 /* legacySystemUiFlags */, |