blob: 8645995e3df1b5bc35be11984cc0f49fe4e28d77 [file] [log] [blame]
John Reck68bfe0a2014-06-24 15:34:58 -07001/*
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
John Reck119907c2014-08-14 09:02:01 -070020#include "AnimationContext.h"
John Reck1bcacfd2017-11-03 10:12:19 -070021#include "Animator.h"
Tom Hudson2dc236b2014-10-15 15:46:42 -040022#include "DamageAccumulator.h"
John Reck68bfe0a2014-06-24 15:34:58 -070023#include "RenderNode.h"
24
25namespace android {
26namespace uirenderer {
27
28using namespace std;
29
Doris Liuc4bb1852016-02-19 21:39:21 +000030static void detach(sp<BaseRenderNodeAnimator>& animator) {
John Reck8d8af3c2014-07-01 15:23:45 -070031 animator->detach();
John Reck68bfe0a2014-06-24 15:34:58 -070032}
33
Nader Jawad528b0d22022-05-10 13:58:36 -070034AnimatorManager::AnimatorManager(RenderNode& parent)
35 : mParent(parent), mAnimationHandle(nullptr), mCancelAllAnimators(false) {}
John Reck68bfe0a2014-06-24 15:34:58 -070036
37AnimatorManager::~AnimatorManager() {
Doris Liuc4bb1852016-02-19 21:39:21 +000038 for_each(mNewAnimators.begin(), mNewAnimators.end(), detach);
39 for_each(mAnimators.begin(), mAnimators.end(), detach);
John Reck68bfe0a2014-06-24 15:34:58 -070040}
41
42void AnimatorManager::addAnimator(const sp<BaseRenderNodeAnimator>& animator) {
Doris Liu8b083202016-02-19 21:46:06 +000043 RenderNode* stagingTarget = animator->stagingTarget();
44 if (stagingTarget == &mParent) {
45 return;
46 }
Doris Liuc4bb1852016-02-19 21:39:21 +000047 mNewAnimators.emplace_back(animator.get());
Doris Liu8b083202016-02-19 21:46:06 +000048 // If the animator is already attached to other RenderNode, remove it from that RenderNode's
49 // new animator list. This ensures one animator only ends up in one newAnimatorList during one
50 // frame, even when it's added multiple times to multiple targets.
51 if (stagingTarget) {
52 stagingTarget->removeAnimator(animator);
53 }
54 animator->attach(&mParent);
55}
56
57void AnimatorManager::removeAnimator(const sp<BaseRenderNodeAnimator>& animator) {
58 mNewAnimators.erase(std::remove(mNewAnimators.begin(), mNewAnimators.end(), animator),
John Reck1bcacfd2017-11-03 10:12:19 -070059 mNewAnimators.end());
John Reck68bfe0a2014-06-24 15:34:58 -070060}
61
John Reck119907c2014-08-14 09:02:01 -070062void AnimatorManager::setAnimationHandle(AnimationHandle* handle) {
63 LOG_ALWAYS_FATAL_IF(mAnimationHandle && handle, "Already have an AnimationHandle!");
64 mAnimationHandle = handle;
John Recke2478d42014-09-03 16:46:05 -070065 LOG_ALWAYS_FATAL_IF(!mAnimationHandle && mAnimators.size(),
John Reck1bcacfd2017-11-03 10:12:19 -070066 "Lost animation handle on %p (%s) with outstanding animators!", &mParent,
67 mParent.getName());
John Reck119907c2014-08-14 09:02:01 -070068}
69
John Reck119907c2014-08-14 09:02:01 -070070void AnimatorManager::pushStaging() {
John Reck68bfe0a2014-06-24 15:34:58 -070071 if (mNewAnimators.size()) {
John Reckd2080d52017-09-25 14:22:40 -070072 if (CC_UNLIKELY(!mAnimationHandle)) {
John Reck1bcacfd2017-11-03 10:12:19 -070073 ALOGW("Trying to start new animators on %p (%s) without an animation handle!", &mParent,
74 mParent.getName());
John Reckd2080d52017-09-25 14:22:40 -070075 return;
76 }
Doris Liuc4bb1852016-02-19 21:39:21 +000077
Doris Liu8b083202016-02-19 21:46:06 +000078 // 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));
Doris Liuc4bb1852016-02-19 21:39:21 +000082 }
Doris Liuc4bb1852016-02-19 21:39:21 +000083 }
84 mNewAnimators.clear();
John Reck68bfe0a2014-06-24 15:34:58 -070085 }
Nader Jawad528b0d22022-05-10 13:58:36 -070086
87 if (mCancelAllAnimators) {
88 for (auto& animator : mAnimators) {
89 animator->forceEndNow(mAnimationHandle->context());
90 }
91 mCancelAllAnimators = false;
92 } else {
Sally Qif3a0ee52024-03-15 13:07:40 -070093 // create a copy of mAnimators as onAnimatorTargetChanged can erase mAnimators.
94 FatVector<sp<BaseRenderNodeAnimator>> animators;
95 animators.reserve(mAnimators.size());
96 for (const auto& animator : mAnimators) {
97 animators.push_back(animator);
98 }
99 for (auto& animator : animators) {
Nader Jawad528b0d22022-05-10 13:58:36 -0700100 animator->pushStaging(mAnimationHandle->context());
101 }
John Reck68bfe0a2014-06-24 15:34:58 -0700102 }
103}
104
Doris Liu8b083202016-02-19 21:46:06 +0000105void AnimatorManager::onAnimatorTargetChanged(BaseRenderNodeAnimator* animator) {
106 LOG_ALWAYS_FATAL_IF(animator->target() == &mParent, "Target has not been changed");
107 mAnimators.erase(std::remove(mAnimators.begin(), mAnimators.end(), animator), mAnimators.end());
108}
109
John Reck68bfe0a2014-06-24 15:34:58 -0700110class AnimateFunctor {
111public:
John Reck9e066cb2016-02-29 13:40:52 -0800112 AnimateFunctor(TreeInfo& info, AnimationContext& context, uint32_t* outDirtyMask)
113 : mInfo(info), mContext(context), mDirtyMask(outDirtyMask) {}
John Reck68bfe0a2014-06-24 15:34:58 -0700114
John Reck1bcacfd2017-11-03 10:12:19 -0700115 bool operator()(sp<BaseRenderNodeAnimator>& animator) {
John Reck9e066cb2016-02-29 13:40:52 -0800116 *mDirtyMask |= animator->dirtyMask();
John Reck119907c2014-08-14 09:02:01 -0700117 bool remove = animator->animate(mContext);
John Reck68bfe0a2014-06-24 15:34:58 -0700118 if (remove) {
Doris Liuc4bb1852016-02-19 21:39:21 +0000119 animator->detach();
John Reck119907c2014-08-14 09:02:01 -0700120 } else {
121 if (animator->isRunning()) {
122 mInfo.out.hasAnimations = true;
123 }
John Reckf5945a02014-09-05 15:57:47 -0700124 if (CC_UNLIKELY(!animator->mayRunAsync())) {
125 mInfo.out.requiresUiRedraw = true;
126 }
John Reck68bfe0a2014-06-24 15:34:58 -0700127 }
128 return remove;
129 }
John Recka7c2ea22014-08-08 13:21:00 -0700130
John Reck68bfe0a2014-06-24 15:34:58 -0700131private:
John Reck68bfe0a2014-06-24 15:34:58 -0700132 TreeInfo& mInfo;
John Reck119907c2014-08-14 09:02:01 -0700133 AnimationContext& mContext;
John Reck9e066cb2016-02-29 13:40:52 -0800134 uint32_t* mDirtyMask;
John Reck68bfe0a2014-06-24 15:34:58 -0700135};
136
John Recka7c2ea22014-08-08 13:21:00 -0700137uint32_t AnimatorManager::animate(TreeInfo& info) {
138 if (!mAnimators.size()) return 0;
John Reck68bfe0a2014-06-24 15:34:58 -0700139
140 // TODO: Can we target this better? For now treat it like any other staging
141 // property push and just damage self before and after animators are run
142
143 mParent.damageSelf(info);
144 info.damageAccumulator->popTransform();
145
John Reck119907c2014-08-14 09:02:01 -0700146 uint32_t dirty = animateCommon(info);
John Reck68bfe0a2014-06-24 15:34:58 -0700147
John Reck68bfe0a2014-06-24 15:34:58 -0700148 info.damageAccumulator->pushTransform(&mParent);
149 mParent.damageSelf(info);
John Recka7c2ea22014-08-08 13:21:00 -0700150
John Reck119907c2014-08-14 09:02:01 -0700151 return dirty;
152}
153
154void AnimatorManager::animateNoDamage(TreeInfo& info) {
John Reck119907c2014-08-14 09:02:01 -0700155 animateCommon(info);
156}
157
158uint32_t AnimatorManager::animateCommon(TreeInfo& info) {
George Burgess IVa4831732017-01-10 15:33:57 -0800159 uint32_t dirtyMask = 0;
John Reck9e066cb2016-02-29 13:40:52 -0800160 AnimateFunctor functor(info, mAnimationHandle->context(), &dirtyMask);
Doris Liuc4bb1852016-02-19 21:39:21 +0000161 auto newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
John Reck119907c2014-08-14 09:02:01 -0700162 mAnimators.erase(newEnd, mAnimators.end());
163 mAnimationHandle->notifyAnimationsRan();
John Reck49dec432015-07-23 15:33:12 -0700164 mParent.mProperties.updateMatrix();
John Reck9e066cb2016-02-29 13:40:52 -0800165 return dirtyMask;
John Reck68bfe0a2014-06-24 15:34:58 -0700166}
167
Doris Liuc4bb1852016-02-19 21:39:21 +0000168static void endStagingAnimator(sp<BaseRenderNodeAnimator>& animator) {
169 animator->cancel();
John Reck119907c2014-08-14 09:02:01 -0700170 if (animator->listener()) {
Doris Liuc4bb1852016-02-19 21:39:21 +0000171 animator->listener()->onAnimationFinished(animator.get());
John Reck119907c2014-08-14 09:02:01 -0700172 }
John Reck119907c2014-08-14 09:02:01 -0700173}
174
John Recke2478d42014-09-03 16:46:05 -0700175void AnimatorManager::endAllStagingAnimators() {
176 ALOGD("endAllStagingAnimators on %p (%s)", &mParent, mParent.getName());
177 // This works because this state can only happen on the UI thread,
178 // which means we're already on the right thread to invoke listeners
179 for_each(mNewAnimators.begin(), mNewAnimators.end(), endStagingAnimator);
180 mNewAnimators.clear();
181}
182
183class EndActiveAnimatorsFunctor {
184public:
Chih-Hung Hsiehc6baf562016-04-27 11:29:23 -0700185 explicit EndActiveAnimatorsFunctor(AnimationContext& context) : mContext(context) {}
John Recke2478d42014-09-03 16:46:05 -0700186
John Reck1bcacfd2017-11-03 10:12:19 -0700187 void operator()(sp<BaseRenderNodeAnimator>& animator) { animator->forceEndNow(mContext); }
John Recke2478d42014-09-03 16:46:05 -0700188
189private:
190 AnimationContext& mContext;
191};
192
193void AnimatorManager::endAllActiveAnimators() {
John Reck1bcacfd2017-11-03 10:12:19 -0700194 ALOGD("endAllActiveAnimators on %p (%s) with handle %p", &mParent, mParent.getName(),
195 mAnimationHandle);
John Recke2478d42014-09-03 16:46:05 -0700196 EndActiveAnimatorsFunctor functor(mAnimationHandle->context());
197 for_each(mAnimators.begin(), mAnimators.end(), functor);
198 mAnimators.clear();
199 mAnimationHandle->release();
John Reck119907c2014-08-14 09:02:01 -0700200}
201
Nader Jawad528b0d22022-05-10 13:58:36 -0700202void AnimatorManager::forceEndAnimators() {
203 mCancelAllAnimators = true;
204}
205
John Reck68bfe0a2014-06-24 15:34:58 -0700206} /* namespace uirenderer */
207} /* namespace android */