1/* 2 * Copyright (C) 2016 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 17#include "PropertyValuesAnimatorSet.h" 18#include "RenderNode.h" 19 20#include <algorithm> 21 22namespace android { 23namespace uirenderer { 24 25void PropertyValuesAnimatorSet::addPropertyAnimator(PropertyValuesHolder* propertyValuesHolder, 26 Interpolator* interpolator, nsecs_t startDelay, nsecs_t duration, int repeatCount, 27 RepeatMode repeatMode) { 28 29 PropertyAnimator* animator = new PropertyAnimator(propertyValuesHolder, 30 interpolator, startDelay, duration, repeatCount, repeatMode); 31 mAnimators.emplace_back(animator); 32 33 // Check whether any child animator is infinite after adding it them to the set. 34 if (repeatCount == -1) { 35 mIsInfinite = true; 36 } 37} 38 39PropertyValuesAnimatorSet::PropertyValuesAnimatorSet() 40 : BaseRenderNodeAnimator(1.0f) { 41 setStartValue(0); 42 mLastFraction = 0.0f; 43 setInterpolator(new LinearInterpolator()); 44 setListener(new PropertyAnimatorSetListener(this)); 45} 46 47void PropertyValuesAnimatorSet::onFinished(BaseRenderNodeAnimator* animator) { 48 if (mOneShotListener.get()) { 49 sp<AnimationListener> listener = std::move(mOneShotListener); 50 // Set the listener to nullptr before the onAnimationFinished callback, rather than after, 51 // for two reasons: 52 // 1) We need to prevent changes to mOneShotListener during the onAnimationFinished 53 // callback (specifically in AnimationListenerBridge::onAnimationFinished(...) from 54 // triggering dtor of the bridge and potentially unsafely re-entering 55 // AnimationListenerBridge::onAnimationFinished(...). 56 // 2) It's possible that there are changes to the listener during the callback, therefore 57 // we need to reset the listener before the callback rather than afterwards. 58 mOneShotListener = nullptr; 59 listener->onAnimationFinished(animator); 60 } 61} 62 63float PropertyValuesAnimatorSet::getValue(RenderNode* target) const { 64 return mLastFraction; 65} 66 67void PropertyValuesAnimatorSet::setValue(RenderNode* target, float value) { 68 mLastFraction = value; 69} 70 71void PropertyValuesAnimatorSet::onPlayTimeChanged(nsecs_t playTime) { 72 if (playTime == 0 && mDuration > 0) { 73 // Reset all the animators 74 for (auto it = mAnimators.rbegin(); it != mAnimators.rend(); it++) { 75 // Note that this set may containing animators modifying the same property, so when we 76 // reset the animators, we need to make sure the animators that end the first will 77 // have the final say on what the property value should be. 78 (*it)->setFraction(0, 0); 79 } 80 } else { 81 for (auto& anim : mAnimators) { 82 anim->setCurrentPlayTime(playTime); 83 } 84 } 85} 86 87void PropertyValuesAnimatorSet::start(AnimationListener* listener) { 88 init(); 89 mOneShotListener = listener; 90 mRequestId++; 91 BaseRenderNodeAnimator::start(); 92} 93 94void PropertyValuesAnimatorSet::reverse(AnimationListener* listener) { 95 init(); 96 mOneShotListener = listener; 97 mRequestId++; 98 BaseRenderNodeAnimator::reverse(); 99} 100 101void PropertyValuesAnimatorSet::reset() { 102 mRequestId++; 103 BaseRenderNodeAnimator::reset(); 104} 105 106void PropertyValuesAnimatorSet::end() { 107 mRequestId++; 108 BaseRenderNodeAnimator::end(); 109} 110 111void PropertyValuesAnimatorSet::init() { 112 if (mInitialized) { 113 return; 114 } 115 116 // Sort the animators by their total duration. Note that all the animators in the set start at 117 // the same time, so the ones with longer total duration (which includes start delay) will 118 // be the ones that end later. 119 std::sort(mAnimators.begin(), mAnimators.end(), [](auto& a, auto&b) { 120 return a->getTotalDuration() < b->getTotalDuration(); 121 }); 122 mDuration = mAnimators.empty() ? 0 : mAnimators[mAnimators.size() - 1]->getTotalDuration(); 123 mInitialized = true; 124} 125 126uint32_t PropertyValuesAnimatorSet::dirtyMask() { 127 return RenderNode::DISPLAY_LIST; 128} 129 130PropertyAnimator::PropertyAnimator(PropertyValuesHolder* holder, Interpolator* interpolator, 131 nsecs_t startDelay, nsecs_t duration, int repeatCount, 132 RepeatMode repeatMode) 133 : mPropertyValuesHolder(holder), mInterpolator(interpolator), mStartDelay(startDelay), 134 mDuration(duration) { 135 if (repeatCount < 0) { 136 mRepeatCount = UINT32_MAX; 137 } else { 138 mRepeatCount = repeatCount; 139 } 140 mRepeatMode = repeatMode; 141 mTotalDuration = ((nsecs_t) mRepeatCount + 1) * mDuration + mStartDelay; 142} 143 144void PropertyAnimator::setCurrentPlayTime(nsecs_t playTime) { 145 if (playTime < mStartDelay) { 146 return; 147 } 148 149 float currentIterationFraction; 150 long iteration; 151 if (playTime >= mTotalDuration) { 152 // Reached the end of the animation. 153 iteration = mRepeatCount; 154 currentIterationFraction = 1.0f; 155 } else { 156 // play time here is in range [mStartDelay, mTotalDuration) 157 iteration = (playTime - mStartDelay) / mDuration; 158 currentIterationFraction = ((playTime - mStartDelay) % mDuration) / (float) mDuration; 159 } 160 setFraction(currentIterationFraction, iteration); 161} 162 163void PropertyAnimator::setFraction(float fraction, long iteration) { 164 double totalFraction = fraction + iteration; 165 // This makes sure we only set the fraction = repeatCount + 1 once. It is needed because there 166 // might be another animator modifying the same property after this animator finishes, we need 167 // to make sure we don't set conflicting values on the same property within one frame. 168 if ((mLatestFraction == mRepeatCount + 1.0) && (totalFraction >= mRepeatCount + 1.0)) { 169 return; 170 } 171 172 mLatestFraction = totalFraction; 173 // Check the play direction (i.e. reverse or restart) every other iteration, and calculate the 174 // fraction based on the play direction. 175 if (iteration % 2 && mRepeatMode == RepeatMode::Reverse) { 176 fraction = 1.0f - fraction; 177 } 178 float interpolatedFraction = mInterpolator->interpolate(fraction); 179 mPropertyValuesHolder->setFraction(interpolatedFraction); 180} 181 182void PropertyAnimatorSetListener::onAnimationFinished(BaseRenderNodeAnimator* animator) { 183 mSet->onFinished(animator); 184} 185 186} 187} 188