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 30 static void detach(sp<BaseRenderNodeAnimator>& animator) { 31 animator->detach(); 32 } 33 34 AnimatorManager::AnimatorManager(RenderNode& parent) 35 : mParent(parent) 36 , mAnimationHandle(nullptr) { 37 } 38 39 AnimatorManager::~AnimatorManager() { 40 for_each(mNewAnimators.begin(), mNewAnimators.end(), detach); 41 for_each(mAnimators.begin(), mAnimators.end(), detach); 42 } 43 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 59 void AnimatorManager::removeAnimator(const sp<BaseRenderNodeAnimator>& animator) { 60 mNewAnimators.erase(std::remove(mNewAnimators.begin(), mNewAnimators.end(), animator), 61 mNewAnimators.end()); 62 } 63 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 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 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: 98 AnimateFunctor(TreeInfo& info, AnimationContext& context, uint32_t* outDirtyMask) 99 : mInfo(info), mContext(context), mDirtyMask(outDirtyMask) {} 100 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 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 140 void AnimatorManager::animateNoDamage(TreeInfo& info) { 141 animateCommon(info); 142 } 143 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 154 static void endStagingAnimator(sp<BaseRenderNodeAnimator>& animator) { 155 animator->cancel(); 156 if (animator->listener()) { 157 animator->listener()->onAnimationFinished(animator.get()); 158 } 159 } 160 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: 171 EndActiveAnimatorsFunctor(AnimationContext& context) : mContext(context) {} 172 173 void operator() (sp<BaseRenderNodeAnimator>& animator) { 174 animator->forceEndNow(mContext); 175 } 176 177 private: 178 AnimationContext& mContext; 179 }; 180 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