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