Revert "Revert "Revert "VectorDrawable native rendering - Step 5 of MANY"""
This reverts commit 0d20a275a5baf8579c8b9111cf2ce6615874a6b6.
Change-Id: I97c782f1164a5d39ab74dc098cca71d9e1b30cd8
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 3385a17..980329f 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -807,8 +807,6 @@
}
/**
- * 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 14badb7..7a3c598 100644
--- a/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp
+++ b/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp
@@ -43,13 +43,12 @@
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 @@
env->CallStaticVoidMethod(
gVectorDrawableAnimatorClassInfo.clazz,
gVectorDrawableAnimatorClassInfo.callOnFinished,
- mFinishListener, mId);
+ mFinishListener);
releaseJavaObject();
}
@@ -77,9 +76,8 @@
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 @@
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 @@
{"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 @@
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 c9eac79..0926e9b 100644
--- a/core/jni/android_view_RenderNodeAnimator.cpp
+++ b/core/jni/android_view_RenderNodeAnimator.cpp
@@ -184,7 +184,7 @@
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 99bc306..af8ccf5 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -238,6 +238,9 @@
mAnimatorSet.recordLastSeenTarget((DisplayListCanvas) canvas);
}
mAnimatedVectorState.mVectorDrawable.draw(canvas);
+ if (isStarted()) {
+ invalidateSelf();
+ }
}
@Override
@@ -608,6 +611,10 @@
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 @@
@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 @@
@Override
public void stop() {
mAnimatorSet.end();
- invalidateSelf();
}
/**
@@ -762,9 +774,6 @@
* @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 @@
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 @@
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 @@
mInitialized = true;
// Check reversible.
- mIsReversible = true;
if (mContainsSequentialAnimators) {
mIsReversible = false;
} else {
@@ -813,6 +821,7 @@
}
}
}
+ mIsReversible = true;
}
private void parseAnimatorSet(AnimatorSet set, long startTime) {
@@ -1033,22 +1042,27 @@
* 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 @@
return;
}
+ if (mStarted) {
+ return;
+ }
+
if (!useLastSeenTarget()) {
- mPendingAnimationAction = START_ANIMATION;
+ mAnimationPending = true;
return;
}
@@ -1076,45 +1094,38 @@
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) {
+ if (!mIsReversible) {
return;
}
- if (!useLastSeenTarget()) {
- mPendingAnimationAction = REVERSE_ANIMATION;
- 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 @@
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 @@
}
// 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 @@
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 372bcb3..7bd2b24 100644
--- a/libs/hwui/Animator.cpp
+++ b/libs/hwui/Animator.cpp
@@ -42,8 +42,7 @@
, mStartTime(0)
, mDuration(300)
, mStartDelay(0)
- , mMayRunAsync(true)
- , mPlayTime(0) {
+ , mMayRunAsync(true) {
}
BaseRenderNodeAnimator::~BaseRenderNodeAnimator() {
@@ -86,113 +85,20 @@
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 @@
// 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;
}
- fraction = MathUtils::clamp(fraction, 0.0f, 1.0f);
+ if (fraction >= 1.0f) {
+ fraction = 1.0f;
+ mPlayState = PlayState::Finished;
+ }
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 fcbc11b..2c9c9c3 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 @@
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 @@
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 @@
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 @@
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 2b49b47..cd30b18 100644
--- a/libs/hwui/AnimatorManager.cpp
+++ b/libs/hwui/AnimatorManager.cpp
@@ -27,8 +27,9 @@
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() {
- 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 @@
&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 @@
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 @@
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 @@
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 c24ef47..fb75eb8 100644
--- a/libs/hwui/AnimatorManager.h
+++ b/libs/hwui/AnimatorManager.h
@@ -62,17 +62,13 @@
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 b29f91f..eca1afcc 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::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::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 @@
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 c7ae7c0..4c7ce52 100644
--- a/libs/hwui/PropertyValuesAnimatorSet.h
+++ b/libs/hwui/PropertyValuesAnimatorSet.h
@@ -50,6 +50,7 @@
void start(AnimationListener* listener);
void reverse(AnimationListener* listener);
+ void reset();
void addPropertyAnimator(PropertyValuesHolder* propertyValuesHolder,
Interpolator* interpolators, int64_t startDelays,