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