diff options
7 files changed, 62 insertions, 143 deletions
diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java index 91e9230cdc6a..6568912a82c0 100644 --- a/core/java/android/view/InsetsAnimationControlImpl.java +++ b/core/java/android/view/InsetsAnimationControlImpl.java @@ -35,8 +35,8 @@ import static android.view.InsetsController.LAYOUT_INSETS_DURING_ANIMATION_SHOWN import static android.view.InsetsController.LayoutInsetsDuringAnimation; import static android.view.InsetsSource.ID_IME; import static android.view.InsetsSource.SIDE_BOTTOM; -import static android.view.InsetsSource.SIDE_LEFT; import static android.view.InsetsSource.SIDE_NONE; +import static android.view.InsetsSource.SIDE_LEFT; import static android.view.InsetsSource.SIDE_RIGHT; import static android.view.InsetsSource.SIDE_TOP; import static android.view.WindowInsets.Type.ime; @@ -100,8 +100,6 @@ public class InsetsAnimationControlImpl implements InternalInsetsAnimationContro private @InsetsType int mControllingTypes; private final InsetsAnimationControlCallbacks mController; private final WindowInsetsAnimation mAnimation; - private final long mDurationMs; - private final Interpolator mInterpolator; /** @see WindowInsetsAnimationController#hasZeroInsetsIme */ private final boolean mHasZeroInsetsIme; private final CompatibilityInfo.Translator mTranslator; @@ -122,8 +120,8 @@ public class InsetsAnimationControlImpl implements InternalInsetsAnimationContro @VisibleForTesting public InsetsAnimationControlImpl(SparseArray<InsetsSourceControl> controls, @Nullable Rect frame, InsetsState state, WindowInsetsAnimationControlListener listener, - @InsetsType int types, InsetsAnimationControlCallbacks controller, - InsetsAnimationSpec insetsAnimationSpec, @AnimationType int animationType, + @InsetsType int types, InsetsAnimationControlCallbacks controller, long durationMs, + Interpolator interpolator, @AnimationType int animationType, @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation, CompatibilityInfo.Translator translator, @Nullable ImeTracker.Token statsToken) { mControls = controls; @@ -157,10 +155,8 @@ public class InsetsAnimationControlImpl implements InternalInsetsAnimationContro } mPendingInsets = mCurrentInsets; - mDurationMs = insetsAnimationSpec.getDurationMs(mHasZeroInsetsIme); - mInterpolator = insetsAnimationSpec.getInsetsInterpolator(mHasZeroInsetsIme); - - mAnimation = new WindowInsetsAnimation(mTypes, mInterpolator, mDurationMs); + mAnimation = new WindowInsetsAnimation(mTypes, interpolator, + durationMs); mAnimation.setAlpha(getCurrentAlpha()); mAnimationType = animationType; mLayoutInsetsDuringAnimation = layoutInsetsDuringAnimation; @@ -190,16 +186,6 @@ public class InsetsAnimationControlImpl implements InternalInsetsAnimationContro } @Override - public long getDurationMs() { - return mDurationMs; - } - - @Override - public Interpolator getInsetsInterpolator() { - return mInterpolator; - } - - @Override public void setReadyDispatched(boolean dispatched) { mReadyDispatched = dispatched; } diff --git a/core/java/android/view/InsetsAnimationSpec.java b/core/java/android/view/InsetsAnimationSpec.java deleted file mode 100644 index 7ad6661abffd..000000000000 --- a/core/java/android/view/InsetsAnimationSpec.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.view; - -import android.view.animation.Interpolator; - -import com.android.internal.annotations.VisibleForTesting; - -/** - * Used by {@link InsetsAnimationControlImpl} - * @hide - */ -@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) -public interface InsetsAnimationSpec { - /** - * @param hasZeroInsetsIme whether IME has no insets (floating, fullscreen or non-overlapping). - * @return Duration of animation in {@link java.util.concurrent.TimeUnit#MILLISECONDS} - */ - long getDurationMs(boolean hasZeroInsetsIme); - /** - * @param hasZeroInsetsIme whether IME has no insets (floating, fullscreen or non-overlapping). - * @return The interpolator used for the animation - */ - Interpolator getInsetsInterpolator(boolean hasZeroInsetsIme); -} diff --git a/core/java/android/view/InsetsAnimationThreadControlRunner.java b/core/java/android/view/InsetsAnimationThreadControlRunner.java index fc185bc73735..1b3b3ebbecfc 100644 --- a/core/java/android/view/InsetsAnimationThreadControlRunner.java +++ b/core/java/android/view/InsetsAnimationThreadControlRunner.java @@ -33,6 +33,7 @@ import android.view.InsetsController.LayoutInsetsDuringAnimation; import android.view.SyncRtSurfaceTransactionApplier.SurfaceParams; import android.view.WindowInsets.Type.InsetsType; import android.view.WindowInsetsAnimation.Bounds; +import android.view.animation.Interpolator; import android.view.inputmethod.ImeTracker; /** @@ -109,15 +110,15 @@ public class InsetsAnimationThreadControlRunner implements InsetsAnimationContro @UiThread public InsetsAnimationThreadControlRunner(SparseArray<InsetsSourceControl> controls, @Nullable Rect frame, InsetsState state, WindowInsetsAnimationControlListener listener, - @InsetsType int types, InsetsAnimationControlCallbacks controller, - InsetsAnimationSpec insetsAnimationSpec, @AnimationType int animationType, + @InsetsType int types, InsetsAnimationControlCallbacks controller, long durationMs, + Interpolator interpolator, @AnimationType int animationType, @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation, CompatibilityInfo.Translator translator, Handler mainThreadHandler, @Nullable ImeTracker.Token statsToken) { mMainThreadHandler = mainThreadHandler; mOuterCallbacks = controller; mControl = new InsetsAnimationControlImpl(controls, frame, state, listener, types, - mCallbacks, insetsAnimationSpec, animationType, layoutInsetsDuringAnimation, + mCallbacks, durationMs, interpolator, animationType, layoutInsetsDuringAnimation, translator, statsToken); InsetsAnimationThread.getHandler().post(() -> { if (mControl.isCancelled()) { diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index b1df51f7affa..7896cbde678a 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -366,7 +366,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation * animate insets. */ public static class InternalAnimationControlListener - implements WindowInsetsAnimationControlListener, InsetsAnimationSpec { + implements WindowInsetsAnimationControlListener { private WindowInsetsAnimationController mController; private ValueAnimator mAnimator; @@ -374,6 +374,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation private final boolean mHasAnimationCallbacks; private final @InsetsType int mRequestedTypes; private final @Behavior int mBehavior; + private final long mDurationMs; private final boolean mDisable; private final int mFloatingImeBottomInset; private final WindowInsetsAnimationControlListener mLoggingListener; @@ -387,6 +388,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation mHasAnimationCallbacks = hasAnimationCallbacks; mRequestedTypes = requestedTypes; mBehavior = behavior; + mDurationMs = calculateDurationMs(); mDisable = disable; mFloatingImeBottomInset = floatingImeBottomInset; mLoggingListener = loggingListener; @@ -405,14 +407,13 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation onAnimationFinish(); return; } - final boolean hasZeroInsetsIme = controller.hasZeroInsetsIme(); mAnimator = ValueAnimator.ofFloat(0f, 1f); - mAnimator.setDuration(controller.getDurationMs()); + mAnimator.setDuration(mDurationMs); mAnimator.setInterpolator(new LinearInterpolator()); Insets hiddenInsets = controller.getHiddenStateInsets(); // IME with zero insets is a special case: it will animate-in from offscreen and end // with final insets of zero and vice-versa. - hiddenInsets = hasZeroInsetsIme + hiddenInsets = controller.hasZeroInsetsIme() ? Insets.of(hiddenInsets.left, hiddenInsets.top, hiddenInsets.right, mFloatingImeBottomInset) : hiddenInsets; @@ -422,7 +423,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation Insets end = mShow ? controller.getShownStateInsets() : hiddenInsets; - Interpolator insetsInterpolator = controller.getInsetsInterpolator(); + Interpolator insetsInterpolator = getInsetsInterpolator(); Interpolator alphaInterpolator = getAlphaInterpolator(); mAnimator.addUpdateListener(animation -> { float rawFraction = animation.getAnimatedFraction(); @@ -485,10 +486,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } } - @Override - public Interpolator getInsetsInterpolator(boolean hasZeroInsetsIme) { + protected Interpolator getInsetsInterpolator() { if ((mRequestedTypes & ime()) != 0) { - if (mHasAnimationCallbacks && hasZeroInsetsIme) { + if (mHasAnimationCallbacks) { return SYNC_IME_INTERPOLATOR; } else if (mShow) { return LINEAR_OUT_SLOW_IN_INTERPOLATOR; @@ -507,9 +507,10 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation Interpolator getAlphaInterpolator() { if ((mRequestedTypes & ime()) != 0) { - if (mHasAnimationCallbacks && !mController.hasZeroInsetsIme()) { + if (mHasAnimationCallbacks) { return input -> 1f; } else if (mShow) { + // Alpha animation takes half the time with linear interpolation; return input -> Math.min(1f, 2 * input); } else { @@ -533,10 +534,16 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation if (DEBUG) Log.d(TAG, "onAnimationFinish showOnFinish: " + mShow); } - @Override - public long getDurationMs(boolean hasZeroInsetsIme) { + /** + * To get the animation duration in MS. + */ + public long getDurationMs() { + return mDurationMs; + } + + private long calculateDurationMs() { if ((mRequestedTypes & ime()) != 0) { - if (mHasAnimationCallbacks && hasZeroInsetsIme) { + if (mHasAnimationCallbacks) { return ANIMATION_DURATION_SYNC_IME_MS; } else { return ANIMATION_DURATION_UNSYNC_IME_MS; @@ -586,13 +593,13 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation private static class PendingControlRequest { PendingControlRequest(@InsetsType int types, WindowInsetsAnimationControlListener listener, - InsetsAnimationSpec insetsAnimationSpec, - @AnimationType int animationType, + long durationMs, Interpolator interpolator, @AnimationType int animationType, @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation, CancellationSignal cancellationSignal, boolean useInsetsAnimationThread) { this.types = types; this.listener = listener; - this.mInsetsAnimationSpec = insetsAnimationSpec; + this.durationMs = durationMs; + this.interpolator = interpolator; this.animationType = animationType; this.layoutInsetsDuringAnimation = layoutInsetsDuringAnimation; this.cancellationSignal = cancellationSignal; @@ -601,7 +608,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation @InsetsType int types; final WindowInsetsAnimationControlListener listener; - final InsetsAnimationSpec mInsetsAnimationSpec; + final long durationMs; + final Interpolator interpolator; final @AnimationType int animationType; final @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation; final CancellationSignal cancellationSignal; @@ -1193,10 +1201,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation // We are about to playing the default animation. Passing a null frame indicates the // controlled types should be animated regardless of the frame. - controlAnimationUnchecked(pendingRequest.types, pendingRequest.cancellationSignal, - pendingRequest.listener, null /* frame */, true /* fromIme */, - pendingRequest.mInsetsAnimationSpec, - pendingRequest.animationType, pendingRequest.layoutInsetsDuringAnimation, + controlAnimationUnchecked( + pendingRequest.types, pendingRequest.cancellationSignal, + pendingRequest.listener, null /* frame */, + true /* fromIme */, pendingRequest.durationMs, pendingRequest.interpolator, + pendingRequest.animationType, + pendingRequest.layoutInsetsDuringAnimation, pendingRequest.useInsetsAnimationThread, statsToken); } @@ -1317,26 +1327,18 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation mHost.getInputMethodManager(), null /* icProto */); } - InsetsAnimationSpec spec = new InsetsAnimationSpec() { - @Override - public long getDurationMs(boolean hasZeroInsetsIme) { - return durationMs; - } - @Override - public Interpolator getInsetsInterpolator(boolean hasZeroInsetsIme) { - return interpolator; - } - }; // TODO(b/342111149): Create statsToken here once ImeTracker#onStart becomes async. - controlAnimationUnchecked(types, cancellationSignal, listener, mFrame, fromIme, spec, - animationType, getLayoutInsetsDuringAnimationMode(types, fromPredictiveBack), + controlAnimationUnchecked(types, cancellationSignal, listener, mFrame, fromIme, durationMs, + interpolator, animationType, + getLayoutInsetsDuringAnimationMode(types, fromPredictiveBack), false /* useInsetsAnimationThread */, null); } private void controlAnimationUnchecked(@InsetsType int types, @Nullable CancellationSignal cancellationSignal, WindowInsetsAnimationControlListener listener, @Nullable Rect frame, boolean fromIme, - InsetsAnimationSpec insetsAnimationSpec, @AnimationType int animationType, + long durationMs, Interpolator interpolator, + @AnimationType int animationType, @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation, boolean useInsetsAnimationThread, @Nullable ImeTracker.Token statsToken) { final boolean visible = layoutInsetsDuringAnimation == LAYOUT_INSETS_DURING_ANIMATION_SHOWN; @@ -1347,7 +1349,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation // However, we might reject the request in some cases, such as delaying showing IME or // rejecting showing IME. controlAnimationUncheckedInner(types, cancellationSignal, listener, frame, fromIme, - insetsAnimationSpec, animationType, layoutInsetsDuringAnimation, + durationMs, interpolator, animationType, layoutInsetsDuringAnimation, useInsetsAnimationThread, statsToken); // We are finishing setting the requested visible types. Report them to the server @@ -1358,7 +1360,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation private void controlAnimationUncheckedInner(@InsetsType int types, @Nullable CancellationSignal cancellationSignal, WindowInsetsAnimationControlListener listener, @Nullable Rect frame, boolean fromIme, - InsetsAnimationSpec insetsAnimationSpec, @AnimationType int animationType, + long durationMs, Interpolator interpolator, + @AnimationType int animationType, @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation, boolean useInsetsAnimationThread, @Nullable ImeTracker.Token statsToken) { if ((types & mTypesBeingCancelled) != 0) { @@ -1415,8 +1418,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation // TODO (b/323319146) remove layoutInsetsDuringAnimation from // PendingControlRequest, as it is now only used for showing final PendingControlRequest request = new PendingControlRequest(types, - listener, insetsAnimationSpec, animationType, - LAYOUT_INSETS_DURING_ANIMATION_SHOWN, + listener, durationMs, + interpolator, animationType, LAYOUT_INSETS_DURING_ANIMATION_SHOWN, cancellationSignal, false /* useInsetsAnimationThread */); mPendingImeControlRequest = request; // only add a timeout when the control is not currently showing @@ -1457,9 +1460,11 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation if (!imeReady) { // IME isn't ready, all requested types will be animated once IME is ready abortPendingImeControlRequest(); - final PendingControlRequest request = new PendingControlRequest(types, listener, - insetsAnimationSpec, animationType, layoutInsetsDuringAnimation, - cancellationSignal, useInsetsAnimationThread); + final PendingControlRequest request = new PendingControlRequest(types, + listener, durationMs, + interpolator, animationType, layoutInsetsDuringAnimation, + cancellationSignal, + useInsetsAnimationThread); mPendingImeControlRequest = request; mHandler.postDelayed(mPendingControlTimeout, PENDING_CONTROL_TIMEOUT_MS); if (DEBUG) Log.d(TAG, "Ime not ready. Create pending request"); @@ -1515,11 +1520,11 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation final InsetsAnimationControlRunner runner = useInsetsAnimationThread ? new InsetsAnimationThreadControlRunner(controls, - frame, mState, listener, typesReady, this, - insetsAnimationSpec, animationType, layoutInsetsDuringAnimation, - mHost.getTranslator(), mHost.getHandler(), statsToken) + frame, mState, listener, typesReady, this, durationMs, interpolator, + animationType, layoutInsetsDuringAnimation, mHost.getTranslator(), + mHost.getHandler(), statsToken) : new InsetsAnimationControlImpl(controls, - frame, mState, listener, typesReady, this, insetsAnimationSpec, + frame, mState, listener, typesReady, this, durationMs, interpolator, animationType, layoutInsetsDuringAnimation, mHost.getTranslator(), statsToken); if ((typesReady & WindowInsets.Type.ime()) != 0) { @@ -2018,7 +2023,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation // the controlled types should be animated regardless of the frame. controlAnimationUnchecked( types, null /* cancellationSignal */, listener, null /* frame */, fromIme, - listener /* insetsAnimationSpec */, + listener.getDurationMs(), listener.getInsetsInterpolator(), show ? ANIMATION_TYPE_SHOW : ANIMATION_TYPE_HIDE, show ? LAYOUT_INSETS_DURING_ANIMATION_SHOWN : LAYOUT_INSETS_DURING_ANIMATION_HIDDEN, !hasAnimationCallbacks /* useInsetsAnimationThread */, statsToken); diff --git a/core/java/android/view/InsetsResizeAnimationRunner.java b/core/java/android/view/InsetsResizeAnimationRunner.java index f90b8411e333..6e6222187e49 100644 --- a/core/java/android/view/InsetsResizeAnimationRunner.java +++ b/core/java/android/view/InsetsResizeAnimationRunner.java @@ -233,16 +233,6 @@ public class InsetsResizeAnimationRunner implements InsetsAnimationControlRunner } @Override - public long getDurationMs() { - return 0; - } - - @Override - public Interpolator getInsetsInterpolator() { - return null; - } - - @Override public void setReadyDispatched(boolean dispatched) { } diff --git a/core/java/android/view/WindowInsetsAnimationController.java b/core/java/android/view/WindowInsetsAnimationController.java index d3ea9829c680..6578e9b6c20c 100644 --- a/core/java/android/view/WindowInsetsAnimationController.java +++ b/core/java/android/view/WindowInsetsAnimationController.java @@ -23,7 +23,6 @@ import android.annotation.SuppressLint; import android.graphics.Insets; import android.view.WindowInsets.Type.InsetsType; import android.view.WindowInsetsAnimation.Bounds; -import android.view.animation.Interpolator; /** * Controller for app-driven animation of system windows. @@ -189,16 +188,4 @@ public interface WindowInsetsAnimationController { * fullscreen or non-overlapping). */ boolean hasZeroInsetsIme(); - - /** - * @hide - * @return The duration of the animation in {@link java.util.concurrent.TimeUnit#MILLISECONDS}. - */ - long getDurationMs(); - - /** - * @hide - * @return The interpolator of the animation. - */ - Interpolator getInsetsInterpolator(); } diff --git a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java index 786f1e84728d..668487dcc490 100644 --- a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java +++ b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java @@ -40,7 +40,6 @@ import android.platform.test.annotations.Presubmit; import android.util.SparseArray; import android.view.SurfaceControl.Transaction; import android.view.SyncRtSurfaceTransactionApplier.SurfaceParams; -import android.view.animation.Interpolator; import android.view.animation.LinearInterpolator; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -118,21 +117,11 @@ public class InsetsAnimationControlImplTest { SparseArray<InsetsSourceControl> controls = new SparseArray<>(); controls.put(ID_STATUS_BAR, topConsumer.getControl()); controls.put(ID_NAVIGATION_BAR, navConsumer.getControl()); - InsetsAnimationSpec spec = new InsetsAnimationSpec() { - @Override - public long getDurationMs(boolean hasZeroInsetsIme) { - return 10; - } - @Override - public Interpolator getInsetsInterpolator(boolean hasZeroInsetsIme) { - return new LinearInterpolator(); - } - }; - mController = new InsetsAnimationControlImpl(controls, new Rect(0, 0, 500, 500), mInsetsState, mMockListener, systemBars(), - mMockController, spec /* insetsAnimationSpecCreator */, 0 /* animationType */, - 0 /* layoutInsetsDuringAnimation */, null /* translator */, null /* statsToken */); + mMockController, 10 /* durationMs */, new LinearInterpolator(), + 0 /* animationType */, 0 /* layoutInsetsDuringAnimation */, null /* translator */, + null /* statsToken */); mController.setReadyDispatched(true); } |