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
25namespace android {
26namespace uirenderer {
27
28using namespace std;
29
30static void unref(BaseRenderNodeAnimator* animator) {
31    animator->detach();
32    animator->decStrong(nullptr);
33}
34
35AnimatorManager::AnimatorManager(RenderNode& parent)
36        : mParent(parent)
37        , mAnimationHandle(nullptr) {
38}
39
40AnimatorManager::~AnimatorManager() {
41    for_each(mNewAnimators.begin(), mNewAnimators.end(), unref);
42    for_each(mAnimators.begin(), mAnimators.end(), unref);
43}
44
45void AnimatorManager::addAnimator(const sp<BaseRenderNodeAnimator>& animator) {
46    animator->incStrong(nullptr);
47    animator->attach(&mParent);
48    mNewAnimators.push_back(animator.get());
49}
50
51void 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
59template<typename T>
60static 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
68void 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
81class AnimateFunctor {
82public:
83    AnimateFunctor(TreeInfo& info, AnimationContext& context)
84            : dirtyMask(0), mInfo(info), mContext(context) {}
85
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
104private:
105    TreeInfo& mInfo;
106    AnimationContext& mContext;
107};
108
109uint32_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
126void AnimatorManager::animateNoDamage(TreeInfo& info) {
127    if (!mAnimators.size()) return;
128
129    animateCommon(info);
130}
131
132uint32_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
142static void endStagingAnimator(BaseRenderNodeAnimator* animator) {
143    animator->end();
144    if (animator->listener()) {
145        animator->listener()->onAnimationFinished(animator);
146    }
147    animator->decStrong(nullptr);
148}
149
150void 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
158class EndActiveAnimatorsFunctor {
159public:
160    EndActiveAnimatorsFunctor(AnimationContext& context) : mContext(context) {}
161
162    void operator() (BaseRenderNodeAnimator* animator) {
163        animator->forceEndNow(mContext);
164        animator->decStrong(nullptr);
165    }
166
167private:
168    AnimationContext& mContext;
169};
170
171void 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