• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include "AnimatorManager.h"
17 
18 #include <algorithm>
19 
20 #include "AnimationContext.h"
21 #include "Animator.h"
22 #include "DamageAccumulator.h"
23 #include "RenderNode.h"
24 
25 namespace android {
26 namespace uirenderer {
27 
28 using namespace std;
29 
detach(sp<BaseRenderNodeAnimator> & animator)30 static void detach(sp<BaseRenderNodeAnimator>& animator) {
31     animator->detach();
32 }
33 
AnimatorManager(RenderNode & parent)34 AnimatorManager::AnimatorManager(RenderNode& parent)
35         : mParent(parent), mAnimationHandle(nullptr), mCancelAllAnimators(false) {}
36 
~AnimatorManager()37 AnimatorManager::~AnimatorManager() {
38     for_each(mNewAnimators.begin(), mNewAnimators.end(), detach);
39     for_each(mAnimators.begin(), mAnimators.end(), detach);
40 }
41 
addAnimator(const sp<BaseRenderNodeAnimator> & animator)42 void AnimatorManager::addAnimator(const sp<BaseRenderNodeAnimator>& animator) {
43     RenderNode* stagingTarget = animator->stagingTarget();
44     if (stagingTarget == &mParent) {
45         return;
46     }
47     mNewAnimators.emplace_back(animator.get());
48     // If the animator is already attached to other RenderNode, remove it from that RenderNode's
49     // new animator list. This ensures one animator only ends up in one newAnimatorList during one
50     // frame, even when it's added multiple times to multiple targets.
51     if (stagingTarget) {
52         stagingTarget->removeAnimator(animator);
53     }
54     animator->attach(&mParent);
55 }
56 
removeAnimator(const sp<BaseRenderNodeAnimator> & animator)57 void AnimatorManager::removeAnimator(const sp<BaseRenderNodeAnimator>& animator) {
58     mNewAnimators.erase(std::remove(mNewAnimators.begin(), mNewAnimators.end(), animator),
59                         mNewAnimators.end());
60 }
61 
setAnimationHandle(AnimationHandle * handle)62 void AnimatorManager::setAnimationHandle(AnimationHandle* handle) {
63     LOG_ALWAYS_FATAL_IF(mAnimationHandle && handle, "Already have an AnimationHandle!");
64     mAnimationHandle = handle;
65     LOG_ALWAYS_FATAL_IF(!mAnimationHandle && mAnimators.size(),
66                         "Lost animation handle on %p (%s) with outstanding animators!", &mParent,
67                         mParent.getName());
68 }
69 
pushStaging()70 void AnimatorManager::pushStaging() {
71     if (mNewAnimators.size()) {
72         if (CC_UNLIKELY(!mAnimationHandle)) {
73             ALOGW("Trying to start new animators on %p (%s) without an animation handle!", &mParent,
74                   mParent.getName());
75             return;
76         }
77 
78         // Only add new animators that are not already in the mAnimators list
79         for (auto& anim : mNewAnimators) {
80             if (anim->target() != &mParent) {
81                 mAnimators.push_back(std::move(anim));
82             }
83         }
84         mNewAnimators.clear();
85     }
86 
87     if (mCancelAllAnimators) {
88         for (auto& animator : mAnimators) {
89             animator->forceEndNow(mAnimationHandle->context());
90         }
91         mCancelAllAnimators = false;
92     } else {
93         // create a copy of mAnimators as onAnimatorTargetChanged can erase mAnimators.
94         FatVector<sp<BaseRenderNodeAnimator>> animators;
95         animators.reserve(mAnimators.size());
96         for (const auto& animator : mAnimators) {
97             animators.push_back(animator);
98         }
99         for (auto& animator : animators) {
100             animator->pushStaging(mAnimationHandle->context());
101         }
102     }
103 }
104 
onAnimatorTargetChanged(BaseRenderNodeAnimator * animator)105 void AnimatorManager::onAnimatorTargetChanged(BaseRenderNodeAnimator* animator) {
106     LOG_ALWAYS_FATAL_IF(animator->target() == &mParent, "Target has not been changed");
107     mAnimators.erase(std::remove(mAnimators.begin(), mAnimators.end(), animator), mAnimators.end());
108 }
109 
110 class AnimateFunctor {
111 public:
AnimateFunctor(TreeInfo & info,AnimationContext & context,uint32_t * outDirtyMask)112     AnimateFunctor(TreeInfo& info, AnimationContext& context, uint32_t* outDirtyMask)
113             : mInfo(info), mContext(context), mDirtyMask(outDirtyMask) {}
114 
operator ()(sp<BaseRenderNodeAnimator> & animator)115     bool operator()(sp<BaseRenderNodeAnimator>& animator) {
116         *mDirtyMask |= animator->dirtyMask();
117         bool remove = animator->animate(mContext);
118         if (remove) {
119             animator->detach();
120         } else {
121             if (animator->isRunning()) {
122                 mInfo.out.hasAnimations = true;
123             }
124             if (CC_UNLIKELY(!animator->mayRunAsync())) {
125                 mInfo.out.requiresUiRedraw = true;
126             }
127         }
128         return remove;
129     }
130 
131 private:
132     TreeInfo& mInfo;
133     AnimationContext& mContext;
134     uint32_t* mDirtyMask;
135 };
136 
animate(TreeInfo & info)137 uint32_t AnimatorManager::animate(TreeInfo& info) {
138     if (!mAnimators.size()) return 0;
139 
140     // TODO: Can we target this better? For now treat it like any other staging
141     // property push and just damage self before and after animators are run
142 
143     mParent.damageSelf(info);
144     info.damageAccumulator->popTransform();
145 
146     uint32_t dirty = animateCommon(info);
147 
148     info.damageAccumulator->pushTransform(&mParent);
149     mParent.damageSelf(info);
150 
151     return dirty;
152 }
153 
animateNoDamage(TreeInfo & info)154 void AnimatorManager::animateNoDamage(TreeInfo& info) {
155     animateCommon(info);
156 }
157 
animateCommon(TreeInfo & info)158 uint32_t AnimatorManager::animateCommon(TreeInfo& info) {
159     uint32_t dirtyMask = 0;
160     AnimateFunctor functor(info, mAnimationHandle->context(), &dirtyMask);
161     auto newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
162     mAnimators.erase(newEnd, mAnimators.end());
163     mAnimationHandle->notifyAnimationsRan();
164     mParent.mProperties.updateMatrix();
165     return dirtyMask;
166 }
167 
endStagingAnimator(sp<BaseRenderNodeAnimator> & animator)168 static void endStagingAnimator(sp<BaseRenderNodeAnimator>& animator) {
169     animator->cancel();
170     if (animator->listener()) {
171         animator->listener()->onAnimationFinished(animator.get());
172     }
173 }
174 
endAllStagingAnimators()175 void AnimatorManager::endAllStagingAnimators() {
176     ALOGD("endAllStagingAnimators on %p (%s)", &mParent, mParent.getName());
177     // This works because this state can only happen on the UI thread,
178     // which means we're already on the right thread to invoke listeners
179     for_each(mNewAnimators.begin(), mNewAnimators.end(), endStagingAnimator);
180     mNewAnimators.clear();
181 }
182 
183 class EndActiveAnimatorsFunctor {
184 public:
EndActiveAnimatorsFunctor(AnimationContext & context)185     explicit EndActiveAnimatorsFunctor(AnimationContext& context) : mContext(context) {}
186 
operator ()(sp<BaseRenderNodeAnimator> & animator)187     void operator()(sp<BaseRenderNodeAnimator>& animator) { animator->forceEndNow(mContext); }
188 
189 private:
190     AnimationContext& mContext;
191 };
192 
endAllActiveAnimators()193 void AnimatorManager::endAllActiveAnimators() {
194     ALOGD("endAllActiveAnimators on %p (%s) with handle %p", &mParent, mParent.getName(),
195           mAnimationHandle);
196     EndActiveAnimatorsFunctor functor(mAnimationHandle->context());
197     for_each(mAnimators.begin(), mAnimators.end(), functor);
198     mAnimators.clear();
199     mAnimationHandle->release();
200 }
201 
forceEndAnimators()202 void AnimatorManager::forceEndAnimators() {
203     mCancelAllAnimators = true;
204 }
205 
206 } /* namespace uirenderer */
207 } /* namespace android */
208