diff options
author | 2016-02-18 18:37:02 +0000 | |
---|---|---|
committer | 2016-02-18 18:37:02 +0000 | |
commit | df7fdb1e0bdb5c289bbc08047e5c710185503309 (patch) | |
tree | cb80f84a0aa8efd7ab68d74bcf818ea2eaaad34f | |
parent | 0d20a275a5baf8579c8b9111cf2ce6615874a6b6 (diff) |
Revert "Revert "Revert "VectorDrawable native rendering - Step 5 of MANY"""
This reverts commit 0d20a275a5baf8579c8b9111cf2ce6615874a6b6.
Change-Id: I97c782f1164a5d39ab74dc098cca71d9e1b30cd8
-rw-r--r-- | core/java/android/animation/AnimatorSet.java | 2 | ||||
-rw-r--r-- | core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp | 27 | ||||
-rw-r--r-- | core/jni/android_view_RenderNodeAnimator.cpp | 2 | ||||
-rw-r--r-- | graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java | 106 | ||||
-rw-r--r-- | libs/hwui/Animator.cpp | 144 | ||||
-rw-r--r-- | libs/hwui/Animator.h | 59 | ||||
-rw-r--r-- | libs/hwui/AnimatorManager.cpp | 64 | ||||
-rw-r--r-- | libs/hwui/AnimatorManager.h | 8 | ||||
-rw-r--r-- | libs/hwui/PropertyValuesAnimatorSet.cpp | 60 | ||||
-rw-r--r-- | libs/hwui/PropertyValuesAnimatorSet.h | 1 |
10 files changed, 169 insertions, 304 deletions
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java index 3385a17002bc..980329fe31c8 100644 --- a/core/java/android/animation/AnimatorSet.java +++ b/core/java/android/animation/AnimatorSet.java @@ -807,8 +807,6 @@ public final class AnimatorSet extends Animator { } /** - * AnimatorSet is only reversible when the set contains no sequential animation, and no child - * animators have a start delay. * @hide */ @Override diff --git a/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp b/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp index 14badb72a195..7a3c598e0aed 100644 --- a/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp +++ b/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp @@ -43,13 +43,12 @@ static JNIEnv* getEnv(JavaVM* vm) { return env; } -static AnimationListener* createAnimationListener(JNIEnv* env, jobject finishListener, jint id) { +static AnimationListener* createAnimationListener(JNIEnv* env, jobject finishListener) { class AnimationListenerBridge : public AnimationListener { public: - AnimationListenerBridge(JNIEnv* env, jobject finishListener, jint id) { + AnimationListenerBridge(JNIEnv* env, jobject finishListener) { mFinishListener = env->NewGlobalRef(finishListener); env->GetJavaVM(&mJvm); - mId = id; } virtual ~AnimationListenerBridge() { @@ -64,7 +63,7 @@ static AnimationListener* createAnimationListener(JNIEnv* env, jobject finishLis env->CallStaticVoidMethod( gVectorDrawableAnimatorClassInfo.clazz, gVectorDrawableAnimatorClassInfo.callOnFinished, - mFinishListener, mId); + mFinishListener); releaseJavaObject(); } @@ -77,9 +76,8 @@ static AnimationListener* createAnimationListener(JNIEnv* env, jobject finishLis JavaVM* mJvm; jobject mFinishListener; - jint mId; }; - return new AnimationListenerBridge(env, finishListener, id); + return new AnimationListenerBridge(env, finishListener); } static void addAnimator(JNIEnv*, jobject, jlong animatorSetPtr, jlong propertyHolderPtr, @@ -144,16 +142,15 @@ static void setPropertyHolderData(JNIEnv* env, jobject, jlong propertyHolderPtr, holder->setPropertyDataSource(propertyData, length); env->ReleaseFloatArrayElements(srcData, propertyData, JNI_ABORT); } -static void start(JNIEnv* env, jobject, jlong animatorSetPtr, jobject finishListener, jint id) { +static void start(JNIEnv* env, jobject, jlong animatorSetPtr, jobject finishListener) { PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr); - AnimationListener* listener = createAnimationListener(env, finishListener, id); + // TODO: keep a ref count in finish listener + AnimationListener* listener = createAnimationListener(env, finishListener); set->start(listener); } -static void reverse(JNIEnv* env, jobject, jlong animatorSetPtr, jobject finishListener, jint id) { - PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr); - AnimationListener* listener = createAnimationListener(env, finishListener, id); - set->reverse(listener); +static void reverse(JNIEnv* env, jobject, jlong animatorSetPtr, jobject finishListener) { + // TODO: implement reverse } static void end(JNIEnv*, jobject, jlong animatorSetPtr) { @@ -175,8 +172,8 @@ static const JNINativeMethod gMethods[] = { {"nCreatePathPropertyHolder", "!(JIFF)J", (void*)createPathPropertyHolder}, {"nCreateRootAlphaPropertyHolder", "!(JFF)J", (void*)createRootAlphaPropertyHolder}, {"nSetPropertyHolderData", "(J[FI)V", (void*)setPropertyHolderData}, - {"nStart", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;I)V", (void*)start}, - {"nReverse", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;I)V", (void*)reverse}, + {"nStart", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;)V", (void*)start}, + {"nReverse", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;)V", (void*)reverse}, {"nEnd", "!(J)V", (void*)end}, {"nReset", "!(J)V", (void*)reset}, }; @@ -189,7 +186,7 @@ int register_android_graphics_drawable_AnimatedVectorDrawable(JNIEnv* env) { gVectorDrawableAnimatorClassInfo.callOnFinished = GetStaticMethodIDOrDie( env, gVectorDrawableAnimatorClassInfo.clazz, "callOnFinished", - "(Landroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;I)V"); + "(Landroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;)V"); return RegisterMethodsOrDie(env, "android/graphics/drawable/AnimatedVectorDrawable", gMethods, NELEM(gMethods)); } diff --git a/core/jni/android_view_RenderNodeAnimator.cpp b/core/jni/android_view_RenderNodeAnimator.cpp index c9eac79ef9b6..0926e9b76691 100644 --- a/core/jni/android_view_RenderNodeAnimator.cpp +++ b/core/jni/android_view_RenderNodeAnimator.cpp @@ -184,7 +184,7 @@ static void start(JNIEnv* env, jobject clazz, jlong animatorPtr) { static void end(JNIEnv* env, jobject clazz, jlong animatorPtr) { BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr); - animator->cancel(); + animator->end(); } // ---------------------------------------------------------------------------- diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java index 99bc306821ef..af8ccf5018b9 100644 --- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java @@ -238,6 +238,9 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { mAnimatorSet.recordLastSeenTarget((DisplayListCanvas) canvas); } mAnimatedVectorState.mVectorDrawable.draw(canvas); + if (isStarted()) { + invalidateSelf(); + } } @Override @@ -608,6 +611,10 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { return mAnimatorSet.isRunning(); } + private boolean isStarted() { + return mAnimatorSet.isStarted(); + } + /** * Resets the AnimatedVectorDrawable to the start state as specified in the animators. */ @@ -619,6 +626,12 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { @Override public void start() { ensureAnimatorSet(); + + // If any one of the animator has not ended, do nothing. + if (isStarted()) { + return; + } + mAnimatorSet.start(); invalidateSelf(); } @@ -639,7 +652,6 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { @Override public void stop() { mAnimatorSet.end(); - invalidateSelf(); } /** @@ -762,9 +774,6 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { * @hide */ public static class VectorDrawableAnimator { - private static final int NONE = 0; - private static final int START_ANIMATION = 1; - private static final int REVERSE_ANIMATION = 2; private AnimatorListener mListener = null; private final LongArray mStartDelays = new LongArray(); private PropertyValuesHolder.PropertyValues mTmpValues = @@ -773,6 +782,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { private boolean mContainsSequentialAnimators = false; private boolean mStarted = false; private boolean mInitialized = false; + private boolean mAnimationPending = false; private boolean mIsReversible = false; // This needs to be set before parsing starts. private boolean mShouldIgnoreInvalidAnim; @@ -780,8 +790,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { private final VirtualRefBasePtr mSetRefBasePtr; private WeakReference<RenderNode> mTarget = null; private WeakReference<RenderNode> mLastSeenTarget = null; - private int mLastListenerId = 0; - private int mPendingAnimationAction = NONE; + VectorDrawableAnimator() { mSetPtr = nCreateAnimatorSet(); @@ -801,7 +810,6 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { mInitialized = true; // Check reversible. - mIsReversible = true; if (mContainsSequentialAnimators) { mIsReversible = false; } else { @@ -813,6 +821,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { } } } + mIsReversible = true; } private void parseAnimatorSet(AnimatorSet set, long startTime) { @@ -1033,22 +1042,27 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { * to the last seen RenderNode target and start right away. */ protected void recordLastSeenTarget(DisplayListCanvas canvas) { - mLastSeenTarget = new WeakReference<RenderNode>( - RenderNodeAnimatorSetHelper.getTarget(canvas)); - if (mPendingAnimationAction != NONE) { + if (mAnimationPending) { + mLastSeenTarget = new WeakReference<RenderNode>( + RenderNodeAnimatorSetHelper.getTarget(canvas)); if (DBG_ANIMATION_VECTOR_DRAWABLE) { Log.d(LOGTAG, "Target is set in the next frame"); } - if (mPendingAnimationAction == START_ANIMATION) { - start(); - } else if (mPendingAnimationAction == REVERSE_ANIMATION) { - reverse(); - } - mPendingAnimationAction = NONE; + mAnimationPending = false; + start(); + } else { + mLastSeenTarget = new WeakReference<RenderNode>( + RenderNodeAnimatorSetHelper.getTarget(canvas)); } + } private boolean setTarget(RenderNode node) { + if (mTarget != null && mTarget.get() != null) { + // TODO: Maybe we want to support target change. + throw new IllegalStateException("Target already set!"); + } + node.addAnimator(this); mTarget = new WeakReference<RenderNode>(node); return true; @@ -1067,8 +1081,12 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { return; } + if (mStarted) { + return; + } + if (!useLastSeenTarget()) { - mPendingAnimationAction = START_ANIMATION; + mAnimationPending = true; return; } @@ -1076,45 +1094,38 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { Log.d(LOGTAG, "Target is set. Starting VDAnimatorSet from java"); } - mStarted = true; - nStart(mSetPtr, this, ++mLastListenerId); + nStart(mSetPtr, this); if (mListener != null) { mListener.onAnimationStart(null); } + mStarted = true; } public void end() { - if (mInitialized && useLastSeenTarget()) { - // If no target has ever been set, no-op + if (mInitialized && mStarted) { nEnd(mSetPtr); + onAnimationEnd(); } } - public void reset() { - if (mInitialized && useLastSeenTarget()) { - // If no target has ever been set, no-op - nReset(mSetPtr); + void reset() { + if (!mInitialized) { + return; } + // TODO: Need to implement reset. + Log.w(LOGTAG, "Reset is yet to be implemented"); + nReset(mSetPtr); } // Current (imperfect) Java AnimatorSet cannot be reversed when the set contains sequential // animators or when the animator set has a start delay void reverse() { - if (!mIsReversible || !mInitialized) { - return; - } - if (!useLastSeenTarget()) { - mPendingAnimationAction = REVERSE_ANIMATION; + if (!mIsReversible) { return; } - if (DBG_ANIMATION_VECTOR_DRAWABLE) { - Log.d(LOGTAG, "Target is set. Reversing VDAnimatorSet from java"); - } - mStarted = true; - nReverse(mSetPtr, this, ++mLastListenerId); - if (mListener != null) { - mListener.onAnimationStart(null); - } + // TODO: Need to support reverse (non-public API) + Log.w(LOGTAG, "Reverse is yet to be implemented"); + nReverse(mSetPtr, this); } public long getAnimatorNativePtr() { @@ -1144,13 +1155,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { mListener = null; } - private void onAnimationEnd(int listenerId) { - if (listenerId != mLastListenerId) { - return; - } - if (DBG_ANIMATION_VECTOR_DRAWABLE) { - Log.d(LOGTAG, "on finished called from native"); - } + private void onAnimationEnd() { mStarted = false; if (mListener != null) { mListener.onAnimationEnd(null); @@ -1159,8 +1164,11 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { } // onFinished: should be called from native - private static void callOnFinished(VectorDrawableAnimator set, int id) { - set.onAnimationEnd(id); + private static void callOnFinished(VectorDrawableAnimator set) { + if (DBG_ANIMATION_VECTOR_DRAWABLE) { + Log.d(LOGTAG, "on finished called from native"); + } + set.onAnimationEnd(); } } @@ -1180,8 +1188,8 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { private static native long nCreateRootAlphaPropertyHolder(long nativePtr, float startValue, float endValue); private static native void nSetPropertyHolderData(long nativePtr, float[] data, int length); - private static native void nStart(long animatorSetPtr, VectorDrawableAnimator set, int id); - private static native void nReverse(long animatorSetPtr, VectorDrawableAnimator set, int id); + private static native void nStart(long animatorSetPtr, VectorDrawableAnimator set); + private static native void nReverse(long animatorSetPtr, VectorDrawableAnimator set); private static native void nEnd(long animatorSetPtr); private static native void nReset(long animatorSetPtr); } diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp index 372bcb3b2375..7bd2b24bf56b 100644 --- a/libs/hwui/Animator.cpp +++ b/libs/hwui/Animator.cpp @@ -42,8 +42,7 @@ BaseRenderNodeAnimator::BaseRenderNodeAnimator(float finalValue) , mStartTime(0) , mDuration(300) , mStartDelay(0) - , mMayRunAsync(true) - , mPlayTime(0) { + , mMayRunAsync(true) { } BaseRenderNodeAnimator::~BaseRenderNodeAnimator() { @@ -86,113 +85,20 @@ void BaseRenderNodeAnimator::attach(RenderNode* target) { onAttached(); } -void BaseRenderNodeAnimator::start() { - mStagingPlayState = PlayState::Running; - mStagingRequests.push_back(Request::Start); - onStagingPlayStateChanged(); -} - -void BaseRenderNodeAnimator::cancel() { - mStagingPlayState = PlayState::Finished; - mStagingRequests.push_back(Request::Cancel); - onStagingPlayStateChanged(); -} - -void BaseRenderNodeAnimator::reset() { - mStagingPlayState = PlayState::Finished; - mStagingRequests.push_back(Request::Reset); - onStagingPlayStateChanged(); -} - -void BaseRenderNodeAnimator::reverse() { - mStagingPlayState = PlayState::Reversing; - mStagingRequests.push_back(Request::Reverse); - onStagingPlayStateChanged(); -} - -void BaseRenderNodeAnimator::end() { - mStagingPlayState = PlayState::Finished; - mStagingRequests.push_back(Request::End); - onStagingPlayStateChanged(); -} - -void BaseRenderNodeAnimator::resolveStagingRequest(Request request) { - switch (request) { - case Request::Start: - mPlayTime = (mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) ? - mPlayTime : 0; - mPlayState = PlayState::Running; - break; - case Request::Reverse: - mPlayTime = (mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) ? - mPlayTime : mDuration; - mPlayState = PlayState::Reversing; - break; - case Request::Reset: - mPlayTime = 0; - mPlayState = PlayState::Finished; - break; - case Request::Cancel: - mPlayState = PlayState::Finished; - break; - case Request::End: - mPlayTime = mPlayState == PlayState::Reversing ? 0 : mDuration; - mPlayState = PlayState::Finished; - break; - default: - LOG_ALWAYS_FATAL("Invalid staging request: %d", static_cast<int>(request)); - }; -} - void BaseRenderNodeAnimator::pushStaging(AnimationContext& context) { if (!mHasStartValue) { doSetStartValue(getValue(mTarget)); } - - if (!mStagingRequests.empty()) { - // Keep track of the play state and play time before they are changed when - // staging requests are resolved. - nsecs_t currentPlayTime = mPlayTime; - PlayState prevFramePlayState = mPlayState; - - // Resolve staging requests one by one. - for (Request request : mStagingRequests) { - resolveStagingRequest(request); + if (mStagingPlayState > mPlayState) { + if (mStagingPlayState == PlayState::Restarted) { + mStagingPlayState = PlayState::Running; } - mStagingRequests.clear(); - - if (mStagingPlayState == PlayState::Finished) { - // Set the staging play time and end the animation - updatePlayTime(mPlayTime); + mPlayState = mStagingPlayState; + // Oh boy, we're starting! Man the battle stations! + if (mPlayState == PlayState::Running) { + transitionToRunning(context); + } else if (mPlayState == PlayState::Finished) { callOnFinishedListener(context); - } else if (mStagingPlayState == PlayState::Running - || mStagingPlayState == PlayState::Reversing) { - bool changed = currentPlayTime != mPlayTime || prevFramePlayState != mStagingPlayState; - if (prevFramePlayState != mStagingPlayState) { - transitionToRunning(context); - } - if (changed) { - // Now we need to seek to the stagingPlayTime (i.e. the animation progress that was - // requested from UI thread). It is achieved by modifying mStartTime, such that - // current time - mStartTime = stagingPlayTime (or mDuration -stagingPlayTime in the - // case of reversing) - nsecs_t currentFrameTime = context.frameTimeMs(); - if (mPlayState == PlayState::Reversing) { - // Reverse is not supported for animations with a start delay, so here we - // assume no start delay. - mStartTime = currentFrameTime - (mDuration - mPlayTime); - } else { - // Animation should play forward - if (mPlayTime == 0) { - // If the request is to start from the beginning, include start delay. - mStartTime = currentFrameTime + mStartDelay; - } else { - // If the request is to seek to a non-zero play time, then we skip start - // delay. - mStartTime = currentFrameTime - mPlayTime; - } - } - } } } } @@ -230,37 +136,37 @@ bool BaseRenderNodeAnimator::animate(AnimationContext& context) { // This should be set before setValue() so animators can query this time when setValue // is called. - nsecs_t currentPlayTime = context.frameTimeMs() - mStartTime; - bool finished = updatePlayTime(currentPlayTime); - if (finished && mPlayState != PlayState::Finished) { - mPlayState = PlayState::Finished; - callOnFinishedListener(context); - } - return finished; -} + nsecs_t currentFrameTime = context.frameTimeMs(); + onPlayTimeChanged(currentFrameTime - mStartTime); -bool BaseRenderNodeAnimator::updatePlayTime(nsecs_t playTime) { - mPlayTime = mPlayState == PlayState::Reversing ? mDuration - playTime : playTime; - onPlayTimeChanged(mPlayTime); // If BaseRenderNodeAnimator is handling the delay (not typical), then // because the staging properties reflect the final value, we always need // to call setValue even if the animation isn't yet running or is still // being delayed as we need to override the staging value - if (playTime < 0) { + if (mStartTime > context.frameTimeMs()) { setValue(mTarget, mFromValue); return false; } float fraction = 1.0f; - if ((mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) && mDuration > 0) { - fraction = mPlayTime / (float) mDuration; + + if (mPlayState == PlayState::Running && mDuration > 0) { + fraction = (float)(currentFrameTime - mStartTime) / mDuration; + } + if (fraction >= 1.0f) { + fraction = 1.0f; + mPlayState = PlayState::Finished; } - fraction = MathUtils::clamp(fraction, 0.0f, 1.0f); fraction = mInterpolator->interpolate(fraction); setValue(mTarget, mFromValue + (mDeltaValue * fraction)); - return playTime >= mDuration; + if (mPlayState == PlayState::Finished) { + callOnFinishedListener(context); + return true; + } + + return false; } void BaseRenderNodeAnimator::forceEndNow(AnimationContext& context) { diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h index fcbc11b0306c..2c9c9c3fe0f9 100644 --- a/libs/hwui/Animator.h +++ b/libs/hwui/Animator.h @@ -24,8 +24,6 @@ #include "utils/Macros.h" -#include <vector> - namespace android { namespace uirenderer { @@ -61,14 +59,14 @@ public: mMayRunAsync = mayRunAsync; } bool mayRunAsync() { return mMayRunAsync; } - ANDROID_API void start(); - ANDROID_API void reset(); - ANDROID_API void reverse(); - // Terminates the animation at its current progress. - ANDROID_API void cancel(); - - // Terminates the animation and skip to the end of the animation. - ANDROID_API void end(); + ANDROID_API void start() { + if (mStagingPlayState == PlayState::NotStarted) { + mStagingPlayState = PlayState::Running; + } else { + mStagingPlayState = PlayState::Restarted; + } + onStagingPlayStateChanged(); } + ANDROID_API void end() { mStagingPlayState = PlayState::Finished; onStagingPlayStateChanged(); } void attach(RenderNode* target); virtual void onAttached() {} @@ -76,41 +74,36 @@ public: void pushStaging(AnimationContext& context); bool animate(AnimationContext& context); - bool isRunning() { return mPlayState == PlayState::Running - || mPlayState == PlayState::Reversing; } + bool isRunning() { return mPlayState == PlayState::Running; } bool isFinished() { return mPlayState == PlayState::Finished; } float finalValue() { return mFinalValue; } ANDROID_API virtual uint32_t dirtyMask() = 0; void forceEndNow(AnimationContext& context); - RenderNode* target() { return mTarget; } protected: // PlayState is used by mStagingPlayState and mPlayState to track the state initiated from UI // thread and Render Thread animation state, respectively. // From the UI thread, mStagingPlayState transition looks like - // NotStarted -> Running/Reversing -> Finished - // ^ | - // | | - // ---------------------- + // NotStarted -> Running -> Finished + // ^ | + // | | + // Restarted <------ // Note: For mStagingState, the Finished state (optional) is only set when the animation is // terminated by user. // // On Render Thread, mPlayState transition: - // NotStart -> Running/Reversing-> Finished - // ^ | - // | | - // ------------------ - // Note that if the animation is in Running/Reversing state, calling start or reverse again - // would do nothing if the animation has the same play direction as the request; otherwise, - // the animation would start from where it is and change direction (i.e. Reversing <-> Running) + // NotStart -> Running -> Finished + // ^ | + // | | + // ------------- enum class PlayState { NotStarted, Running, - Reversing, Finished, + Restarted, }; BaseRenderNodeAnimator(float finalValue); @@ -118,6 +111,7 @@ protected: virtual float getValue(RenderNode* target) const = 0; virtual void setValue(RenderNode* target, float value) = 0; + RenderNode* target() { return mTarget; } void callOnFinishedListener(AnimationContext& context); @@ -138,28 +132,13 @@ protected: nsecs_t mDuration; nsecs_t mStartDelay; bool mMayRunAsync; - // Play Time tracks the progress of animation, it should always be [0, mDuration], 0 being - // the beginning of the animation, will reach mDuration at the end of an animation. - nsecs_t mPlayTime; sp<AnimationListener> mListener; private: - enum class Request { - Start, - Reverse, - Reset, - Cancel, - End - }; inline void checkMutable(); virtual void transitionToRunning(AnimationContext& context); void doSetStartValue(float value); - bool updatePlayTime(nsecs_t playTime); - void resolveStagingRequest(Request request); - - std::vector<Request> mStagingRequests; - }; class RenderPropertyAnimator : public BaseRenderNodeAnimator { diff --git a/libs/hwui/AnimatorManager.cpp b/libs/hwui/AnimatorManager.cpp index 2b49b4743d89..cd30b1859384 100644 --- a/libs/hwui/AnimatorManager.cpp +++ b/libs/hwui/AnimatorManager.cpp @@ -27,8 +27,9 @@ namespace uirenderer { using namespace std; -static void detach(sp<BaseRenderNodeAnimator>& animator) { +static void unref(BaseRenderNodeAnimator* animator) { animator->detach(); + animator->decStrong(nullptr); } AnimatorManager::AnimatorManager(RenderNode& parent) @@ -37,12 +38,14 @@ AnimatorManager::AnimatorManager(RenderNode& parent) } AnimatorManager::~AnimatorManager() { - for_each(mNewAnimators.begin(), mNewAnimators.end(), detach); - for_each(mAnimators.begin(), mAnimators.end(), detach); + for_each(mNewAnimators.begin(), mNewAnimators.end(), unref); + for_each(mAnimators.begin(), mAnimators.end(), unref); } void AnimatorManager::addAnimator(const sp<BaseRenderNodeAnimator>& animator) { - mNewAnimators.emplace_back(animator.get()); + animator->incStrong(nullptr); + animator->attach(&mParent); + mNewAnimators.push_back(animator.get()); } void AnimatorManager::setAnimationHandle(AnimationHandle* handle) { @@ -53,31 +56,25 @@ void AnimatorManager::setAnimationHandle(AnimationHandle* handle) { &mParent, mParent.getName()); } +template<typename T> +static void move_all(T& source, T& dest) { + dest.reserve(source.size() + dest.size()); + for (typename T::iterator it = source.begin(); it != source.end(); it++) { + dest.push_back(*it); + } + source.clear(); +} + void AnimatorManager::pushStaging() { if (mNewAnimators.size()) { LOG_ALWAYS_FATAL_IF(!mAnimationHandle, "Trying to start new animators on %p (%s) without an animation handle!", &mParent, mParent.getName()); - // Only add animators that are not already in the on-going animator list. - for (auto& animator : mNewAnimators) { - RenderNode* targetRenderNode = animator->target(); - if (targetRenderNode == &mParent) { - // Animator already in the animator list: skip adding again - continue; - } - - if (targetRenderNode){ - // If the animator is already in another RenderNode's animator list, remove animator from - // that list and add animator to current RenderNode's list. - targetRenderNode->animators().removeActiveAnimator(animator); - } - animator->attach(&mParent); - mAnimators.push_back(std::move(animator)); - } - mNewAnimators.clear(); + // Since this is a straight move, we don't need to inc/dec the ref count + move_all(mNewAnimators, mAnimators); } - for (auto& animator : mAnimators) { - animator->pushStaging(mAnimationHandle->context()); + for (vector<BaseRenderNodeAnimator*>::iterator it = mAnimators.begin(); it != mAnimators.end(); it++) { + (*it)->pushStaging(mAnimationHandle->context()); } } @@ -86,11 +83,11 @@ public: AnimateFunctor(TreeInfo& info, AnimationContext& context) : dirtyMask(0), mInfo(info), mContext(context) {} - bool operator() (sp<BaseRenderNodeAnimator>& animator) { + bool operator() (BaseRenderNodeAnimator* animator) { dirtyMask |= animator->dirtyMask(); bool remove = animator->animate(mContext); if (remove) { - animator->detach(); + animator->decStrong(nullptr); } else { if (animator->isRunning()) { mInfo.out.hasAnimations = true; @@ -132,18 +129,20 @@ void AnimatorManager::animateNoDamage(TreeInfo& info) { uint32_t AnimatorManager::animateCommon(TreeInfo& info) { AnimateFunctor functor(info, mAnimationHandle->context()); - auto newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor); + std::vector< BaseRenderNodeAnimator* >::iterator newEnd; + newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor); mAnimators.erase(newEnd, mAnimators.end()); mAnimationHandle->notifyAnimationsRan(); mParent.mProperties.updateMatrix(); return functor.dirtyMask; } -static void endStagingAnimator(sp<BaseRenderNodeAnimator>& animator) { - animator->cancel(); +static void endStagingAnimator(BaseRenderNodeAnimator* animator) { + animator->end(); if (animator->listener()) { - animator->listener()->onAnimationFinished(animator.get()); + animator->listener()->onAnimationFinished(animator); } + animator->decStrong(nullptr); } void AnimatorManager::endAllStagingAnimators() { @@ -154,16 +153,13 @@ void AnimatorManager::endAllStagingAnimators() { mNewAnimators.clear(); } -void AnimatorManager::removeActiveAnimator(const sp<BaseRenderNodeAnimator>& animator) { - std::remove(mAnimators.begin(), mAnimators.end(), animator); -} - class EndActiveAnimatorsFunctor { public: EndActiveAnimatorsFunctor(AnimationContext& context) : mContext(context) {} - void operator() (sp<BaseRenderNodeAnimator>& animator) { + void operator() (BaseRenderNodeAnimator* animator) { animator->forceEndNow(mContext); + animator->decStrong(nullptr); } private: diff --git a/libs/hwui/AnimatorManager.h b/libs/hwui/AnimatorManager.h index c24ef47a4644..fb75eb8599b4 100644 --- a/libs/hwui/AnimatorManager.h +++ b/libs/hwui/AnimatorManager.h @@ -62,17 +62,13 @@ public: private: uint32_t animateCommon(TreeInfo& info); - // This would remove the animator from mAnimators list. It should only be called during - // push staging. - void removeActiveAnimator(const sp<BaseRenderNodeAnimator>& animator); - RenderNode& mParent; AnimationHandle* mAnimationHandle; // To improve the efficiency of resizing & removing from the vector // use manual ref counting instead of sp<>. - std::vector< sp<BaseRenderNodeAnimator> > mNewAnimators; - std::vector< sp<BaseRenderNodeAnimator> > mAnimators; + std::vector<BaseRenderNodeAnimator*> mNewAnimators; + std::vector<BaseRenderNodeAnimator*> mAnimators; }; } /* namespace uirenderer */ diff --git a/libs/hwui/PropertyValuesAnimatorSet.cpp b/libs/hwui/PropertyValuesAnimatorSet.cpp index b29f91ff34aa..eca1afcc54dc 100644 --- a/libs/hwui/PropertyValuesAnimatorSet.cpp +++ b/libs/hwui/PropertyValuesAnimatorSet.cpp @@ -17,8 +17,6 @@ #include "PropertyValuesAnimatorSet.h" #include "RenderNode.h" -#include <algorithm> - namespace android { namespace uirenderer { @@ -55,26 +53,16 @@ void PropertyValuesAnimatorSet::setValue(RenderNode* target, float value) { } void PropertyValuesAnimatorSet::onPlayTimeChanged(nsecs_t playTime) { - if (playTime == 0 && mDuration > 0) { - // Reset all the animators - for (auto it = mAnimators.rbegin(); it != mAnimators.rend(); it++) { - // Note that this set may containing animators modifying the same property, so when we - // reset the animators, we need to make sure the animators that end the first will - // have the final say on what the property value should be. - (*it)->setFraction(0); - } - } else if (playTime >= mDuration) { - // Skip all the animators to end - for (auto& anim : mAnimators) { - anim->setFraction(1); - } - } else { - for (auto& anim : mAnimators) { - anim->setCurrentPlayTime(playTime); - } + for (size_t i = 0; i < mAnimators.size(); i++) { + mAnimators[i]->setCurrentPlayTime(playTime); } } +void PropertyValuesAnimatorSet::reset() { + // TODO: implement reset through adding a play state because we need to support reset() even + // during an animation run. +} + void PropertyValuesAnimatorSet::start(AnimationListener* listener) { init(); mOneShotListener = listener; @@ -82,23 +70,20 @@ void PropertyValuesAnimatorSet::start(AnimationListener* listener) { } void PropertyValuesAnimatorSet::reverse(AnimationListener* listener) { - init(); - mOneShotListener = listener; - BaseRenderNodeAnimator::reverse(); +// TODO: implement reverse } void PropertyValuesAnimatorSet::init() { if (mInitialized) { return; } - - // Sort the animators by their total duration. Note that all the animators in the set start at - // the same time, so the ones with longer total duration (which includes start delay) will - // be the ones that end later. - std::sort(mAnimators.begin(), mAnimators.end(), [](auto& a, auto&b) { - return a->getTotalDuration() < b->getTotalDuration(); - }); - mDuration = mAnimators[mAnimators.size() - 1]->getTotalDuration(); + nsecs_t maxDuration = 0; + for (size_t i = 0; i < mAnimators.size(); i++) { + if (maxDuration < mAnimators[i]->getTotalDuration()) { + maxDuration = mAnimators[i]->getTotalDuration(); + } + } + mDuration = maxDuration; mInitialized = true; } @@ -121,19 +106,18 @@ PropertyAnimator::PropertyAnimator(PropertyValuesHolder* holder, Interpolator* i void PropertyAnimator::setCurrentPlayTime(nsecs_t playTime) { if (playTime >= mStartDelay && playTime < mTotalDuration) { nsecs_t currentIterationPlayTime = (playTime - mStartDelay) % mDuration; - float fraction = currentIterationPlayTime / (float) mDuration; - setFraction(fraction); + mLatestFraction = currentIterationPlayTime / (float) mDuration; } else if (mLatestFraction < 1.0f && playTime >= mTotalDuration) { - // This makes sure we only set the fraction = 1 once. It is needed because there might - // be another animator modifying the same property after this animator finishes, we need - // to make sure we don't set conflicting values on the same property within one frame. - setFraction(1.0f); + mLatestFraction = 1.0f; + } else { + return; } + + setFraction(mLatestFraction); } void PropertyAnimator::setFraction(float fraction) { - mLatestFraction = fraction; - float interpolatedFraction = mInterpolator->interpolate(fraction); + float interpolatedFraction = mInterpolator->interpolate(mLatestFraction); mPropertyValuesHolder->setFraction(interpolatedFraction); } diff --git a/libs/hwui/PropertyValuesAnimatorSet.h b/libs/hwui/PropertyValuesAnimatorSet.h index c7ae7c0e8ce1..4c7ce528bb20 100644 --- a/libs/hwui/PropertyValuesAnimatorSet.h +++ b/libs/hwui/PropertyValuesAnimatorSet.h @@ -50,6 +50,7 @@ public: void start(AnimationListener* listener); void reverse(AnimationListener* listener); + void reset(); void addPropertyAnimator(PropertyValuesHolder* propertyValuesHolder, Interpolator* interpolators, int64_t startDelays, |