• 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 "RenderNode.h"
22 
23 namespace android {
24 namespace uirenderer {
25 
26 using namespace std;
27 
unref(BaseRenderNodeAnimator * animator)28 static void unref(BaseRenderNodeAnimator* animator) {
29     animator->detach();
30     animator->decStrong(0);
31 }
32 
AnimatorManager(RenderNode & parent)33 AnimatorManager::AnimatorManager(RenderNode& parent)
34         : mParent(parent)
35         , mAnimationHandle(NULL) {
36 }
37 
~AnimatorManager()38 AnimatorManager::~AnimatorManager() {
39     for_each(mNewAnimators.begin(), mNewAnimators.end(), unref);
40     for_each(mAnimators.begin(), mAnimators.end(), unref);
41 }
42 
addAnimator(const sp<BaseRenderNodeAnimator> & animator)43 void AnimatorManager::addAnimator(const sp<BaseRenderNodeAnimator>& animator) {
44     animator->incStrong(0);
45     animator->attach(&mParent);
46     mNewAnimators.push_back(animator.get());
47 }
48 
setAnimationHandle(AnimationHandle * handle)49 void AnimatorManager::setAnimationHandle(AnimationHandle* handle) {
50     LOG_ALWAYS_FATAL_IF(mAnimationHandle && handle, "Already have an AnimationHandle!");
51     mAnimationHandle = handle;
52     LOG_ALWAYS_FATAL_IF(!mAnimationHandle && mAnimators.size(),
53             "Lost animation handle on %p (%s) with outstanding animators!",
54             &mParent, mParent.getName());
55 }
56 
57 template<typename T>
move_all(T & source,T & dest)58 static void move_all(T& source, T& dest) {
59     dest.reserve(source.size() + dest.size());
60     for (typename T::iterator it = source.begin(); it != source.end(); it++) {
61         dest.push_back(*it);
62     }
63     source.clear();
64 }
65 
pushStaging()66 void AnimatorManager::pushStaging() {
67     if (mNewAnimators.size()) {
68         LOG_ALWAYS_FATAL_IF(!mAnimationHandle,
69                 "Trying to start new animators on %p (%s) without an animation handle!",
70                 &mParent, mParent.getName());
71         // Since this is a straight move, we don't need to inc/dec the ref count
72         move_all(mNewAnimators, mAnimators);
73     }
74     for (vector<BaseRenderNodeAnimator*>::iterator it = mAnimators.begin(); it != mAnimators.end(); it++) {
75         (*it)->pushStaging(mAnimationHandle->context());
76     }
77 }
78 
79 class AnimateFunctor {
80 public:
AnimateFunctor(TreeInfo & info,AnimationContext & context)81     AnimateFunctor(TreeInfo& info, AnimationContext& context)
82             : dirtyMask(0), mInfo(info), mContext(context) {}
83 
operator ()(BaseRenderNodeAnimator * animator)84     bool operator() (BaseRenderNodeAnimator* animator) {
85         dirtyMask |= animator->dirtyMask();
86         bool remove = animator->animate(mContext);
87         if (remove) {
88             animator->decStrong(0);
89         } else {
90             if (animator->isRunning()) {
91                 mInfo.out.hasAnimations = true;
92             }
93             if (CC_UNLIKELY(!animator->mayRunAsync())) {
94                 mInfo.out.requiresUiRedraw = true;
95             }
96         }
97         return remove;
98     }
99 
100     uint32_t dirtyMask;
101 
102 private:
103     TreeInfo& mInfo;
104     AnimationContext& mContext;
105 };
106 
animate(TreeInfo & info)107 uint32_t AnimatorManager::animate(TreeInfo& info) {
108     if (!mAnimators.size()) return 0;
109 
110     // TODO: Can we target this better? For now treat it like any other staging
111     // property push and just damage self before and after animators are run
112 
113     mParent.damageSelf(info);
114     info.damageAccumulator->popTransform();
115 
116     uint32_t dirty = animateCommon(info);
117 
118     mParent.mProperties.updateMatrix();
119     info.damageAccumulator->pushTransform(&mParent);
120     mParent.damageSelf(info);
121 
122     return dirty;
123 }
124 
animateNoDamage(TreeInfo & info)125 void AnimatorManager::animateNoDamage(TreeInfo& info) {
126     if (!mAnimators.size()) return;
127 
128     animateCommon(info);
129 }
130 
animateCommon(TreeInfo & info)131 uint32_t AnimatorManager::animateCommon(TreeInfo& info) {
132     AnimateFunctor functor(info, mAnimationHandle->context());
133     std::vector< BaseRenderNodeAnimator* >::iterator newEnd;
134     newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
135     mAnimators.erase(newEnd, mAnimators.end());
136     mAnimationHandle->notifyAnimationsRan();
137     return functor.dirtyMask;
138 }
139 
endStagingAnimator(BaseRenderNodeAnimator * animator)140 static void endStagingAnimator(BaseRenderNodeAnimator* animator) {
141     animator->end();
142     if (animator->listener()) {
143         animator->listener()->onAnimationFinished(animator);
144     }
145     animator->decStrong(0);
146 }
147 
endAllStagingAnimators()148 void AnimatorManager::endAllStagingAnimators() {
149     ALOGD("endAllStagingAnimators on %p (%s)", &mParent, mParent.getName());
150     // This works because this state can only happen on the UI thread,
151     // which means we're already on the right thread to invoke listeners
152     for_each(mNewAnimators.begin(), mNewAnimators.end(), endStagingAnimator);
153     mNewAnimators.clear();
154 }
155 
156 class EndActiveAnimatorsFunctor {
157 public:
EndActiveAnimatorsFunctor(AnimationContext & context)158     EndActiveAnimatorsFunctor(AnimationContext& context) : mContext(context) {}
159 
operator ()(BaseRenderNodeAnimator * animator)160     void operator() (BaseRenderNodeAnimator* animator) {
161         animator->forceEndNow(mContext);
162         animator->decStrong(0);
163     }
164 
165 private:
166     AnimationContext& mContext;
167 };
168 
endAllActiveAnimators()169 void AnimatorManager::endAllActiveAnimators() {
170     ALOGD("endAllStagingAnimators on %p (%s) with handle %p",
171             &mParent, mParent.getName(), mAnimationHandle);
172     EndActiveAnimatorsFunctor functor(mAnimationHandle->context());
173     for_each(mAnimators.begin(), mAnimators.end(), functor);
174     mAnimators.clear();
175     mAnimationHandle->release();
176 }
177 
178 } /* namespace uirenderer */
179 } /* namespace android */
180