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
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)
36 , mAnimationHandle(nullptr) {
37 }
38
~AnimatorManager()39 AnimatorManager::~AnimatorManager() {
40 for_each(mNewAnimators.begin(), mNewAnimators.end(), detach);
41 for_each(mAnimators.begin(), mAnimators.end(), detach);
42 }
43
addAnimator(const sp<BaseRenderNodeAnimator> & animator)44 void AnimatorManager::addAnimator(const sp<BaseRenderNodeAnimator>& animator) {
45 RenderNode* stagingTarget = animator->stagingTarget();
46 if (stagingTarget == &mParent) {
47 return;
48 }
49 mNewAnimators.emplace_back(animator.get());
50 // If the animator is already attached to other RenderNode, remove it from that RenderNode's
51 // new animator list. This ensures one animator only ends up in one newAnimatorList during one
52 // frame, even when it's added multiple times to multiple targets.
53 if (stagingTarget) {
54 stagingTarget->removeAnimator(animator);
55 }
56 animator->attach(&mParent);
57 }
58
removeAnimator(const sp<BaseRenderNodeAnimator> & animator)59 void AnimatorManager::removeAnimator(const sp<BaseRenderNodeAnimator>& animator) {
60 mNewAnimators.erase(std::remove(mNewAnimators.begin(), mNewAnimators.end(), animator),
61 mNewAnimators.end());
62 }
63
setAnimationHandle(AnimationHandle * handle)64 void AnimatorManager::setAnimationHandle(AnimationHandle* handle) {
65 LOG_ALWAYS_FATAL_IF(mAnimationHandle && handle, "Already have an AnimationHandle!");
66 mAnimationHandle = handle;
67 LOG_ALWAYS_FATAL_IF(!mAnimationHandle && mAnimators.size(),
68 "Lost animation handle on %p (%s) with outstanding animators!",
69 &mParent, mParent.getName());
70 }
71
pushStaging()72 void AnimatorManager::pushStaging() {
73 if (mNewAnimators.size()) {
74 LOG_ALWAYS_FATAL_IF(!mAnimationHandle,
75 "Trying to start new animators on %p (%s) without an animation handle!",
76 &mParent, mParent.getName());
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 for (auto& animator : mAnimators) {
87 animator->pushStaging(mAnimationHandle->context());
88 }
89 }
90
onAnimatorTargetChanged(BaseRenderNodeAnimator * animator)91 void AnimatorManager::onAnimatorTargetChanged(BaseRenderNodeAnimator* animator) {
92 LOG_ALWAYS_FATAL_IF(animator->target() == &mParent, "Target has not been changed");
93 mAnimators.erase(std::remove(mAnimators.begin(), mAnimators.end(), animator), mAnimators.end());
94 }
95
96 class AnimateFunctor {
97 public:
AnimateFunctor(TreeInfo & info,AnimationContext & context,uint32_t * outDirtyMask)98 AnimateFunctor(TreeInfo& info, AnimationContext& context, uint32_t* outDirtyMask)
99 : mInfo(info), mContext(context), mDirtyMask(outDirtyMask) {}
100
operator ()(sp<BaseRenderNodeAnimator> & animator)101 bool operator() (sp<BaseRenderNodeAnimator>& animator) {
102 *mDirtyMask |= animator->dirtyMask();
103 bool remove = animator->animate(mContext);
104 if (remove) {
105 animator->detach();
106 } else {
107 if (animator->isRunning()) {
108 mInfo.out.hasAnimations = true;
109 }
110 if (CC_UNLIKELY(!animator->mayRunAsync())) {
111 mInfo.out.requiresUiRedraw = true;
112 }
113 }
114 return remove;
115 }
116
117 private:
118 TreeInfo& mInfo;
119 AnimationContext& mContext;
120 uint32_t* mDirtyMask;
121 };
122
animate(TreeInfo & info)123 uint32_t AnimatorManager::animate(TreeInfo& info) {
124 if (!mAnimators.size()) return 0;
125
126 // TODO: Can we target this better? For now treat it like any other staging
127 // property push and just damage self before and after animators are run
128
129 mParent.damageSelf(info);
130 info.damageAccumulator->popTransform();
131
132 uint32_t dirty = animateCommon(info);
133
134 info.damageAccumulator->pushTransform(&mParent);
135 mParent.damageSelf(info);
136
137 return dirty;
138 }
139
animateNoDamage(TreeInfo & info)140 void AnimatorManager::animateNoDamage(TreeInfo& info) {
141 animateCommon(info);
142 }
143
animateCommon(TreeInfo & info)144 uint32_t AnimatorManager::animateCommon(TreeInfo& info) {
145 uint32_t dirtyMask;
146 AnimateFunctor functor(info, mAnimationHandle->context(), &dirtyMask);
147 auto newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
148 mAnimators.erase(newEnd, mAnimators.end());
149 mAnimationHandle->notifyAnimationsRan();
150 mParent.mProperties.updateMatrix();
151 return dirtyMask;
152 }
153
endStagingAnimator(sp<BaseRenderNodeAnimator> & animator)154 static void endStagingAnimator(sp<BaseRenderNodeAnimator>& animator) {
155 animator->cancel();
156 if (animator->listener()) {
157 animator->listener()->onAnimationFinished(animator.get());
158 }
159 }
160
endAllStagingAnimators()161 void AnimatorManager::endAllStagingAnimators() {
162 ALOGD("endAllStagingAnimators on %p (%s)", &mParent, mParent.getName());
163 // This works because this state can only happen on the UI thread,
164 // which means we're already on the right thread to invoke listeners
165 for_each(mNewAnimators.begin(), mNewAnimators.end(), endStagingAnimator);
166 mNewAnimators.clear();
167 }
168
169 class EndActiveAnimatorsFunctor {
170 public:
EndActiveAnimatorsFunctor(AnimationContext & context)171 EndActiveAnimatorsFunctor(AnimationContext& context) : mContext(context) {}
172
operator ()(sp<BaseRenderNodeAnimator> & animator)173 void operator() (sp<BaseRenderNodeAnimator>& animator) {
174 animator->forceEndNow(mContext);
175 }
176
177 private:
178 AnimationContext& mContext;
179 };
180
endAllActiveAnimators()181 void AnimatorManager::endAllActiveAnimators() {
182 ALOGD("endAllActiveAnimators on %p (%s) with handle %p",
183 &mParent, mParent.getName(), mAnimationHandle);
184 EndActiveAnimatorsFunctor functor(mAnimationHandle->context());
185 for_each(mAnimators.begin(), mAnimators.end(), functor);
186 mAnimators.clear();
187 mAnimationHandle->release();
188 }
189
190 } /* namespace uirenderer */
191 } /* namespace android */
192