Here are the examples of the java api android.animation.AnimationHandler taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.
2 Examples
18
Source : BoundsAnimationController.java
with Apache License 2.0
from lulululbj
with Apache License 2.0
from lulululbj
/**
* Enables animating bounds of objects.
*
* In multi-window world bounds of both stack and tasks can change. When we need these bounds to
* change smoothly and not require the app to relaunch (e.g. because it handles resizes and
* relaunching it would cause poorer experience), these clreplaced provides a way to directly animate
* the bounds of the resized object.
*
* The object that is resized needs to implement {@link BoundsAnimationTarget} interface.
*
* NOTE: All calls to methods in this clreplaced should be done on the Animation thread
*/
public clreplaced BoundsAnimationController {
private static final boolean DEBUG_LOCAL = false;
private static final boolean DEBUG = DEBUG_LOCAL || DEBUG_ANIM;
private static final String TAG = TAG_WITH_CLreplaced_NAME || DEBUG_LOCAL ? "BoundsAnimationController" : TAG_WM;
private static final int DEBUG_ANIMATION_SLOW_DOWN_FACTOR = 1;
private static final int DEFAULT_TRANSITION_DURATION = 425;
@Retention(RetentionPolicy.SOURCE)
@IntDef({ NO_PIP_MODE_CHANGED_CALLBACKS, SCHEDULE_PIP_MODE_CHANGED_ON_START, SCHEDULE_PIP_MODE_CHANGED_ON_END })
public @interface SchedulePipModeChangedState {
}
/**
* Do not schedule any PiP mode changed callbacks as a part of this animation.
*/
public static final int NO_PIP_MODE_CHANGED_CALLBACKS = 0;
/**
* Schedule a PiP mode changed callback when this animation starts.
*/
public static final int SCHEDULE_PIP_MODE_CHANGED_ON_START = 1;
/**
* Schedule a PiP mode changed callback when this animation ends.
*/
public static final int SCHEDULE_PIP_MODE_CHANGED_ON_END = 2;
// Only accessed on UI thread.
private ArrayMap<BoundsAnimationTarget, BoundsAnimator> mRunningAnimations = new ArrayMap<>();
private final clreplaced AppTransitionNotifier extends WindowManagerInternal.AppTransitionListener implements Runnable {
public void onAppTransitionCancelledLocked() {
if (DEBUG)
Slog.d(TAG, "onAppTransitionCancelledLocked:" + " mFinishAnimationAfterTransition=" + mFinishAnimationAfterTransition);
animationFinished();
}
public void onAppTransitionFinishedLocked(IBinder token) {
if (DEBUG)
Slog.d(TAG, "onAppTransitionFinishedLocked:" + " mFinishAnimationAfterTransition=" + mFinishAnimationAfterTransition);
animationFinished();
}
private void animationFinished() {
if (mFinishAnimationAfterTransition) {
mHandler.removeCallbacks(this);
// This might end up calling into activity manager which will be bad since we have
// the window manager lock held at this point. Post a message to take care of the
// processing so we don't deadlock.
mHandler.post(this);
}
}
@Override
public void run() {
for (int i = 0; i < mRunningAnimations.size(); i++) {
final BoundsAnimator b = mRunningAnimations.valueAt(i);
b.onAnimationEnd(null);
}
}
}
private final Handler mHandler;
private final AppTransition mAppTransition;
private final AppTransitionNotifier mAppTransitionNotifier = new AppTransitionNotifier();
private final Interpolator mFastOutSlowInInterpolator;
private boolean mFinishAnimationAfterTransition = false;
private final AnimationHandler mAnimationHandler;
private Creplacedographer mCreplacedographer;
private static final int WAIT_FOR_DRAW_TIMEOUT_MS = 3000;
BoundsAnimationController(Context context, AppTransition transition, Handler handler, AnimationHandler animationHandler) {
mHandler = handler;
mAppTransition = transition;
mAppTransition.registerListenerLocked(mAppTransitionNotifier);
mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context, com.android.internal.R.interpolator.fast_out_slow_in);
mAnimationHandler = animationHandler;
if (animationHandler != null) {
// If an animation handler is provided, then ensure that it runs on the sf vsync tick
handler.runWithScissors(() -> mCreplacedographer = Creplacedographer.getSfInstance(), 0);
animationHandler.setProvider(new SfVsyncFrameCallbackProvider(mCreplacedographer));
}
}
@VisibleForTesting
final clreplaced BoundsAnimator extends ValueAnimator implements ValueAnimator.AnimatorUpdateListener, ValueAnimator.AnimatorListener {
private final BoundsAnimationTarget mTarget;
private final Rect mFrom = new Rect();
private final Rect mTo = new Rect();
private final Rect mTmpRect = new Rect();
private final Rect mTmpTaskBounds = new Rect();
// True if this this animation was canceled and will be replaced the another animation from
// the same {@link #BoundsAnimationTarget} target.
private boolean mSkipFinalResize;
// True if this animation was canceled by the user, not as a part of a replacing animation
private boolean mSkipAnimationEnd;
// True if the animation target is animating from the fullscreen. Only one of
// {@link mMoveToFullscreen} or {@link mMoveFromFullscreen} can be true at any time in the
// animation.
private boolean mMoveFromFullscreen;
// True if the animation target should be moved to the fullscreen stack at the end of this
// animation. Only one of {@link mMoveToFullscreen} or {@link mMoveFromFullscreen} can be
// true at any time in the animation.
private boolean mMoveToFullscreen;
// Whether to schedule PiP mode changes on animation start/end
@SchedulePipModeChangedState
private int mSchedulePipModeChangedState;
@SchedulePipModeChangedState
private int mPrevSchedulePipModeChangedState;
// Depending on whether we are animating from
// a smaller to a larger size
private final int mFrozenTaskWidth;
private final int mFrozenTaskHeight;
// Timeout callback to ensure we continue the animation if waiting for resuming or app
// windows drawn fails
private final Runnable mResumeRunnable = () -> {
if (DEBUG)
Slog.d(TAG, "pause: timed out waiting for windows drawn");
resume();
};
BoundsAnimator(BoundsAnimationTarget target, Rect from, Rect to, @SchedulePipModeChangedState int schedulePipModeChangedState, @SchedulePipModeChangedState int prevShedulePipModeChangedState, boolean moveFromFullscreen, boolean moveToFullscreen) {
super();
mTarget = target;
mFrom.set(from);
mTo.set(to);
mSchedulePipModeChangedState = schedulePipModeChangedState;
mPrevSchedulePipModeChangedState = prevShedulePipModeChangedState;
mMoveFromFullscreen = moveFromFullscreen;
mMoveToFullscreen = moveToFullscreen;
addUpdateListener(this);
addListener(this);
// If we are animating from smaller to larger, we want to change the task bounds
// to their final size immediately so we can use scaling to make the window
// larger. Likewise if we are going from bigger to smaller, we want to wait until
// the end so we don't have to upscale from the smaller finished size.
if (animatingToLargerSize()) {
mFrozenTaskWidth = mTo.width();
mFrozenTaskHeight = mTo.height();
} else {
mFrozenTaskWidth = mFrom.width();
mFrozenTaskHeight = mFrom.height();
}
}
@Override
public void onAnimationStart(Animator animation) {
if (DEBUG)
Slog.d(TAG, "onAnimationStart: mTarget=" + mTarget + " mPrevSchedulePipModeChangedState=" + mPrevSchedulePipModeChangedState + " mSchedulePipModeChangedState=" + mSchedulePipModeChangedState);
mFinishAnimationAfterTransition = false;
mTmpRect.set(mFrom.left, mFrom.top, mFrom.left + mFrozenTaskWidth, mFrom.top + mFrozenTaskHeight);
// Boost the thread priority of the animation thread while the bounds animation is
// running
updateBooster();
// Ensure that we have prepared the target for animation before we trigger any size
// changes, so it can swap surfaces in to appropriate modes, or do as it wishes
// otherwise.
if (mPrevSchedulePipModeChangedState == NO_PIP_MODE_CHANGED_CALLBACKS) {
mTarget.onAnimationStart(mSchedulePipModeChangedState == SCHEDULE_PIP_MODE_CHANGED_ON_START, false);
// When starting an animation from fullscreen, pause here and wait for the
// windows-drawn signal before we start the rest of the transition down into PiP.
if (mMoveFromFullscreen && mTarget.shouldDeferStartOnMoveToFullscreen()) {
pause();
}
} else if (mPrevSchedulePipModeChangedState == SCHEDULE_PIP_MODE_CHANGED_ON_END && mSchedulePipModeChangedState == SCHEDULE_PIP_MODE_CHANGED_ON_START) {
// We are replacing a running animation into PiP, but since it hasn't completed, the
// client will not currently receive any picture-in-picture mode change callbacks.
// However, we still need to report to them that they are leaving PiP, so this will
// force an update via a mode changed callback.
mTarget.onAnimationStart(true, /* schedulePipModeChangedCallback */
true);
}
// Immediately update the task bounds if they have to become larger, but preserve
// the starting position so we don't jump at the beginning of the animation.
if (animatingToLargerSize()) {
mTarget.setPinnedStackSize(mFrom, mTmpRect);
// We pause the animation until the app has drawn at the new size.
// The target will notify us via BoundsAnimationController#resume.
// We do this here and pause the animation, rather than just defer starting it
// so we can enter the animating state and have WindowStateAnimator apply the
// correct logic to make this resize seamless.
if (mMoveToFullscreen) {
pause();
}
}
}
@Override
public void pause() {
if (DEBUG)
Slog.d(TAG, "pause: waiting for windows drawn");
super.pause();
mHandler.postDelayed(mResumeRunnable, WAIT_FOR_DRAW_TIMEOUT_MS);
}
@Override
public void resume() {
if (DEBUG)
Slog.d(TAG, "resume:");
mHandler.removeCallbacks(mResumeRunnable);
super.resume();
}
@Override
public void onAnimationUpdate(ValueAnimator animation) {
final float value = (Float) animation.getAnimatedValue();
final float remains = 1 - value;
mTmpRect.left = (int) (mFrom.left * remains + mTo.left * value + 0.5f);
mTmpRect.top = (int) (mFrom.top * remains + mTo.top * value + 0.5f);
mTmpRect.right = (int) (mFrom.right * remains + mTo.right * value + 0.5f);
mTmpRect.bottom = (int) (mFrom.bottom * remains + mTo.bottom * value + 0.5f);
if (DEBUG)
Slog.d(TAG, "animateUpdate: mTarget=" + mTarget + " mBounds=" + mTmpRect + " from=" + mFrom + " mTo=" + mTo + " value=" + value + " remains=" + remains);
mTmpTaskBounds.set(mTmpRect.left, mTmpRect.top, mTmpRect.left + mFrozenTaskWidth, mTmpRect.top + mFrozenTaskHeight);
if (!mTarget.setPinnedStackSize(mTmpRect, mTmpTaskBounds)) {
// Whoops, the target doesn't feel like animating anymore. Let's immediately finish
// any further animation.
if (DEBUG)
Slog.d(TAG, "animateUpdate: cancelled");
// If we have already scheduled a PiP mode changed at the start of the animation,
// then we need to clean up and schedule one at the end, since we have canceled the
// animation to the final state.
if (mSchedulePipModeChangedState == SCHEDULE_PIP_MODE_CHANGED_ON_START) {
mSchedulePipModeChangedState = SCHEDULE_PIP_MODE_CHANGED_ON_END;
}
// Since we are cancelling immediately without a replacement animation, send the
// animation end to maintain callback parity, but also skip any further resizes
cancelAndCallAnimationEnd();
}
}
@Override
public void onAnimationEnd(Animator animation) {
if (DEBUG)
Slog.d(TAG, "onAnimationEnd: mTarget=" + mTarget + " mSkipFinalResize=" + mSkipFinalResize + " mFinishAnimationAfterTransition=" + mFinishAnimationAfterTransition + " mAppTransitionIsRunning=" + mAppTransition.isRunning() + " callers=" + Debug.getCallers(2));
// There could be another animation running. For example in the
// move to fullscreen case, recents will also be closing while the
// previous task will be taking its place in the fullscreen stack.
// we have to ensure this is completed before we finish the animation
// and take our place in the fullscreen stack.
if (mAppTransition.isRunning() && !mFinishAnimationAfterTransition) {
mFinishAnimationAfterTransition = true;
return;
}
if (!mSkipAnimationEnd) {
// If this animation has already scheduled the picture-in-picture mode on start, and
// we are not skipping the final resize due to being canceled, then move the PiP to
// fullscreen once the animation ends
if (DEBUG)
Slog.d(TAG, "onAnimationEnd: mTarget=" + mTarget + " moveToFullscreen=" + mMoveToFullscreen);
mTarget.onAnimationEnd(mSchedulePipModeChangedState == SCHEDULE_PIP_MODE_CHANGED_ON_END, !mSkipFinalResize ? mTo : null, mMoveToFullscreen);
}
// Clean up this animation
removeListener(this);
removeUpdateListener(this);
mRunningAnimations.remove(mTarget);
// Reset the thread priority of the animation thread after the bounds animation is done
updateBooster();
}
@Override
public void onAnimationCancel(Animator animation) {
// Always skip the final resize when the animation is canceled
mSkipFinalResize = true;
mMoveToFullscreen = false;
}
private void cancelAndCallAnimationEnd() {
if (DEBUG)
Slog.d(TAG, "cancelAndCallAnimationEnd: mTarget=" + mTarget);
mSkipAnimationEnd = false;
super.cancel();
}
@Override
public void cancel() {
if (DEBUG)
Slog.d(TAG, "cancel: mTarget=" + mTarget);
mSkipAnimationEnd = true;
super.cancel();
}
/**
* @return true if the animation target is the same as the input bounds.
*/
boolean isAnimatingTo(Rect bounds) {
return mTo.equals(bounds);
}
/**
* @return true if we are animating to a larger surface size
*/
@VisibleForTesting
boolean animatingToLargerSize() {
// TODO: Fix this check for aspect ratio changes
return (mFrom.width() * mFrom.height() <= mTo.width() * mTo.height());
}
@Override
public void onAnimationRepeat(Animator animation) {
// Do nothing
}
@Override
public AnimationHandler getAnimationHandler() {
if (mAnimationHandler != null) {
return mAnimationHandler;
}
return super.getAnimationHandler();
}
}
public void animateBounds(final BoundsAnimationTarget target, Rect from, Rect to, int animationDuration, @SchedulePipModeChangedState int schedulePipModeChangedState, boolean moveFromFullscreen, boolean moveToFullscreen) {
animateBoundsImpl(target, from, to, animationDuration, schedulePipModeChangedState, moveFromFullscreen, moveToFullscreen);
}
@VisibleForTesting
BoundsAnimator animateBoundsImpl(final BoundsAnimationTarget target, Rect from, Rect to, int animationDuration, @SchedulePipModeChangedState int schedulePipModeChangedState, boolean moveFromFullscreen, boolean moveToFullscreen) {
final BoundsAnimator existing = mRunningAnimations.get(target);
final boolean replacing = existing != null;
@SchedulePipModeChangedState
int prevSchedulePipModeChangedState = NO_PIP_MODE_CHANGED_CALLBACKS;
if (DEBUG)
Slog.d(TAG, "animateBounds: target=" + target + " from=" + from + " to=" + to + " schedulePipModeChangedState=" + schedulePipModeChangedState + " replacing=" + replacing);
if (replacing) {
if (existing.isAnimatingTo(to) && (!moveToFullscreen || existing.mMoveToFullscreen) && (!moveFromFullscreen || existing.mMoveFromFullscreen)) {
// Just let the current animation complete if it has the same destination as the
// one we are trying to start, and, if moveTo/FromFullscreen was requested, already
// has that flag set.
if (DEBUG)
Slog.d(TAG, "animateBounds: same destination and moveTo/From flags as " + "existing=" + existing + ", ignoring...");
return existing;
}
// Save the previous state
prevSchedulePipModeChangedState = existing.mSchedulePipModeChangedState;
// Update the PiP callback states if we are replacing the animation
if (existing.mSchedulePipModeChangedState == SCHEDULE_PIP_MODE_CHANGED_ON_START) {
if (schedulePipModeChangedState == SCHEDULE_PIP_MODE_CHANGED_ON_START) {
if (DEBUG)
Slog.d(TAG, "animateBounds: still animating to fullscreen, keep" + " existing deferred state");
} else {
if (DEBUG)
Slog.d(TAG, "animateBounds: fullscreen animation canceled, callback" + " on start already processed, schedule deferred update on end");
schedulePipModeChangedState = SCHEDULE_PIP_MODE_CHANGED_ON_END;
}
} else if (existing.mSchedulePipModeChangedState == SCHEDULE_PIP_MODE_CHANGED_ON_END) {
if (schedulePipModeChangedState == SCHEDULE_PIP_MODE_CHANGED_ON_START) {
if (DEBUG)
Slog.d(TAG, "animateBounds: non-fullscreen animation canceled," + " callback on start will be processed");
} else {
if (DEBUG)
Slog.d(TAG, "animateBounds: still animating from fullscreen, keep" + " existing deferred state");
schedulePipModeChangedState = SCHEDULE_PIP_MODE_CHANGED_ON_END;
}
}
// We need to keep the previous moveTo/FromFullscreen flag, unless the new animation
// specifies a direction.
if (!moveFromFullscreen && !moveToFullscreen) {
moveToFullscreen = existing.mMoveToFullscreen;
moveFromFullscreen = existing.mMoveFromFullscreen;
}
// Since we are replacing, we skip both animation start and end callbacks
existing.cancel();
}
final BoundsAnimator animator = new BoundsAnimator(target, from, to, schedulePipModeChangedState, prevSchedulePipModeChangedState, moveFromFullscreen, moveToFullscreen);
mRunningAnimations.put(target, animator);
animator.setFloatValues(0f, 1f);
animator.setDuration((animationDuration != -1 ? animationDuration : DEFAULT_TRANSITION_DURATION) * DEBUG_ANIMATION_SLOW_DOWN_FACTOR);
animator.setInterpolator(mFastOutSlowInInterpolator);
animator.start();
return animator;
}
public Handler getHandler() {
return mHandler;
}
public void onAllWindowsDrawn() {
if (DEBUG)
Slog.d(TAG, "onAllWindowsDrawn:");
mHandler.post(this::resume);
}
private void resume() {
for (int i = 0; i < mRunningAnimations.size(); i++) {
final BoundsAnimator b = mRunningAnimations.valueAt(i);
b.resume();
}
}
private void updateBooster() {
WindowManagerService.sThreadPriorityBooster.setBoundsAnimationRunning(!mRunningAnimations.isEmpty());
}
}
16
Source : SurfaceAnimationRunner.java
with Apache License 2.0
from lulululbj
with Apache License 2.0
from lulululbj
/**
* Clreplaced to run animations without holding the window manager lock.
*/
clreplaced SurfaceAnimationRunner {
private final Object mLock = new Object();
/**
* Lock for cancelling animations. Must be acquired on it's own, or after acquiring
* {@link #mLock}
*/
private final Object mCancelLock = new Object();
@VisibleForTesting
Creplacedographer mCreplacedographer;
private final Runnable mApplyTransactionRunnable = this::applyTransaction;
private final AnimationHandler mAnimationHandler;
private final Transaction mFrameTransaction;
private final AnimatorFactory mAnimatorFactory;
private final PowerManagerInternal mPowerManagerInternal;
private boolean mApplyScheduled;
@GuardedBy("mLock")
@VisibleForTesting
final ArrayMap<SurfaceControl, RunningAnimation> mPendingAnimations = new ArrayMap<>();
@GuardedBy("mLock")
@VisibleForTesting
final ArrayMap<SurfaceControl, RunningAnimation> mRunningAnimations = new ArrayMap<>();
@GuardedBy("mLock")
private boolean mAnimationStartDeferred;
SurfaceAnimationRunner(PowerManagerInternal powerManagerInternal) {
this(null, /* callbackProvider */
null, /* animatorFactory */
new Transaction(), powerManagerInternal);
}
@VisibleForTesting
SurfaceAnimationRunner(@Nullable AnimationFrameCallbackProvider callbackProvider, AnimatorFactory animatorFactory, Transaction frameTransaction, PowerManagerInternal powerManagerInternal) {
SurfaceAnimationThread.getHandler().runWithScissors(() -> mCreplacedographer = getSfInstance(), 0);
mFrameTransaction = frameTransaction;
mAnimationHandler = new AnimationHandler();
mAnimationHandler.setProvider(callbackProvider != null ? callbackProvider : new SfVsyncFrameCallbackProvider(mCreplacedographer));
mAnimatorFactory = animatorFactory != null ? animatorFactory : SfValueAnimator::new;
mPowerManagerInternal = powerManagerInternal;
}
/**
* Defers starting of animations until {@link #continueStartingAnimations} is called. This
* method is NOT nestable.
*
* @see #continueStartingAnimations
*/
void deferStartingAnimations() {
synchronized (mLock) {
mAnimationStartDeferred = true;
}
}
/**
* Continues starting of animations.
*
* @see #deferStartingAnimations
*/
void continueStartingAnimations() {
synchronized (mLock) {
mAnimationStartDeferred = false;
if (!mPendingAnimations.isEmpty()) {
mCreplacedographer.postFrameCallback(this::startAnimations);
}
}
}
void startAnimation(AnimationSpec a, SurfaceControl animationLeash, Transaction t, Runnable finishCallback) {
synchronized (mLock) {
final RunningAnimation runningAnim = new RunningAnimation(a, animationLeash, finishCallback);
mPendingAnimations.put(animationLeash, runningAnim);
if (!mAnimationStartDeferred) {
mCreplacedographer.postFrameCallback(this::startAnimations);
}
// Some animations (e.g. move animations) require the initial transform to be applied
// immediately.
applyTransformation(runningAnim, t, 0);
}
}
void onAnimationCancelled(SurfaceControl leash) {
synchronized (mLock) {
if (mPendingAnimations.containsKey(leash)) {
mPendingAnimations.remove(leash);
return;
}
final RunningAnimation anim = mRunningAnimations.get(leash);
if (anim != null) {
mRunningAnimations.remove(leash);
synchronized (mCancelLock) {
anim.mCancelled = true;
}
SurfaceAnimationThread.getHandler().post(() -> {
anim.mAnim.cancel();
applyTransaction();
});
}
}
}
@GuardedBy("mLock")
private void startPendingAnimationsLocked() {
for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
startAnimationLocked(mPendingAnimations.valueAt(i));
}
mPendingAnimations.clear();
}
@GuardedBy("mLock")
private void startAnimationLocked(RunningAnimation a) {
final ValueAnimator anim = mAnimatorFactory.makeAnimator();
// Animation length is already expected to be scaled.
anim.overrideDurationScale(1.0f);
anim.setDuration(a.mAnimSpec.getDuration());
anim.addUpdateListener(animation -> {
synchronized (mCancelLock) {
if (!a.mCancelled) {
final long duration = anim.getDuration();
long currentPlayTime = anim.getCurrentPlayTime();
if (currentPlayTime > duration) {
currentPlayTime = duration;
}
applyTransformation(a, mFrameTransaction, currentPlayTime);
}
}
// Transaction will be applied in the commit phase.
scheduleApplyTransaction();
});
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
synchronized (mCancelLock) {
if (!a.mCancelled) {
mFrameTransaction.show(a.mLeash);
}
}
}
@Override
public void onAnimationEnd(Animator animation) {
synchronized (mLock) {
mRunningAnimations.remove(a.mLeash);
synchronized (mCancelLock) {
if (!a.mCancelled) {
// Post on other thread that we can push final state without jank.
AnimationThread.getHandler().post(a.mFinishCallback);
}
}
}
}
});
a.mAnim = anim;
mRunningAnimations.put(a.mLeash, a);
anim.start();
if (a.mAnimSpec.canSkipFirstFrame()) {
// If we can skip the first frame, we start one frame later.
anim.setCurrentPlayTime(mCreplacedographer.getFrameIntervalNanos() / NANOS_PER_MS);
}
// Immediately start the animation by manually applying an animation frame. Otherwise, the
// start time would only be set in the next frame, leading to a delay.
anim.doAnimationFrame(mCreplacedographer.getFrameTime());
}
private void applyTransformation(RunningAnimation a, Transaction t, long currentPlayTime) {
if (a.mAnimSpec.needsEarlyWakeup()) {
t.setEarlyWakeup();
}
a.mAnimSpec.apply(t, a.mLeash, currentPlayTime);
}
private void startAnimations(long frameTimeNanos) {
synchronized (mLock) {
startPendingAnimationsLocked();
}
mPowerManagerInternal.powerHint(PowerHint.INTERACTION, 0);
}
private void scheduleApplyTransaction() {
if (!mApplyScheduled) {
mCreplacedographer.postCallback(CALLBACK_TRAVERSAL, mApplyTransactionRunnable, null);
mApplyScheduled = true;
}
}
private void applyTransaction() {
mFrameTransaction.setAnimationTransaction();
mFrameTransaction.apply();
mApplyScheduled = false;
}
private static final clreplaced RunningAnimation {
final AnimationSpec mAnimSpec;
final SurfaceControl mLeash;
final Runnable mFinishCallback;
ValueAnimator mAnim;
@GuardedBy("mCancelLock")
private boolean mCancelled;
RunningAnimation(AnimationSpec animSpec, SurfaceControl leash, Runnable finishCallback) {
mAnimSpec = animSpec;
mLeash = leash;
mFinishCallback = finishCallback;
}
}
@VisibleForTesting
interface AnimatorFactory {
ValueAnimator makeAnimator();
}
/**
* Value animator that uses sf-vsync signal to tick.
*/
private clreplaced SfValueAnimator extends ValueAnimator {
SfValueAnimator() {
setFloatValues(0f, 1f);
}
@Override
public AnimationHandler getAnimationHandler() {
return mAnimationHandler;
}
}
}