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 22 namespace android { 23 namespace uirenderer { 24 25 void PropertyValuesAnimatorSet::addPropertyAnimator(PropertyValuesHolder* propertyValuesHolder, 26 Interpolator* interpolator, nsecs_t startDelay, 27 nsecs_t duration, int repeatCount, 28 RepeatMode repeatMode) { 29 PropertyAnimator* animator = new PropertyAnimator( 30 propertyValuesHolder, 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 39 PropertyValuesAnimatorSet::PropertyValuesAnimatorSet() : BaseRenderNodeAnimator(1.0f) { 40 setStartValue(0); 41 mLastFraction = 0.0f; 42 setInterpolator(new LinearInterpolator()); 43 setListener(new PropertyAnimatorSetListener(this)); 44 } 45 46 void PropertyValuesAnimatorSet::onFinished(BaseRenderNodeAnimator* animator) { 47 if (mOneShotListener.get()) { 48 sp<AnimationListener> listener = std::move(mOneShotListener); 49 // Set the listener to nullptr before the onAnimationFinished callback, rather than after, 50 // for two reasons: 51 // 1) We need to prevent changes to mOneShotListener during the onAnimationFinished 52 // callback (specifically in AnimationListenerBridge::onAnimationFinished(...) from 53 // triggering dtor of the bridge and potentially unsafely re-entering 54 // AnimationListenerBridge::onAnimationFinished(...). 55 // 2) It's possible that there are changes to the listener during the callback, therefore 56 // we need to reset the listener before the callback rather than afterwards. 57 mOneShotListener = nullptr; 58 listener->onAnimationFinished(animator); 59 } 60 } 61 62 float PropertyValuesAnimatorSet::getValue(RenderNode* target) const { 63 return mLastFraction; 64 } 65 66 void PropertyValuesAnimatorSet::setValue(RenderNode* target, float value) { 67 mLastFraction = value; 68 } 69 70 void PropertyValuesAnimatorSet::onPlayTimeChanged(nsecs_t playTime) { 71 if (playTime == 0 && mDuration > 0) { 72 // Reset all the animators 73 for (auto it = mAnimators.rbegin(); it != mAnimators.rend(); it++) { 74 // Note that this set may containing animators modifying the same property, so when we 75 // reset the animators, we need to make sure the animators that end the first will 76 // have the final say on what the property value should be. 77 (*it)->setFraction(0, 0); 78 } 79 } else { 80 for (auto& anim : mAnimators) { 81 anim->setCurrentPlayTime(playTime); 82 } 83 } 84 } 85 86 void PropertyValuesAnimatorSet::start(AnimationListener* listener) { 87 init(); 88 mOneShotListener = listener; 89 mRequestId++; 90 BaseRenderNodeAnimator::start(); 91 } 92 93 void PropertyValuesAnimatorSet::reverse(AnimationListener* listener) { 94 init(); 95 mOneShotListener = listener; 96 mRequestId++; 97 BaseRenderNodeAnimator::reverse(); 98 } 99 100 void PropertyValuesAnimatorSet::reset() { 101 mRequestId++; 102 BaseRenderNodeAnimator::reset(); 103 } 104 105 void PropertyValuesAnimatorSet::end() { 106 mRequestId++; 107 BaseRenderNodeAnimator::end(); 108 } 109 110 void PropertyValuesAnimatorSet::init() { 111 if (mInitialized) { 112 return; 113 } 114 115 // Sort the animators by their total duration. Note that all the animators in the set start at 116 // the same time, so the ones with longer total duration (which includes start delay) will 117 // be the ones that end later. 118 std::sort(mAnimators.begin(), mAnimators.end(), 119 [](auto& a, auto& b) { return a->getTotalDuration() < b->getTotalDuration(); }); 120 mDuration = mAnimators.empty() ? 0 : mAnimators[mAnimators.size() - 1]->getTotalDuration(); 121 mInitialized = true; 122 } 123 124 uint32_t PropertyValuesAnimatorSet::dirtyMask() { 125 return RenderNode::DISPLAY_LIST; 126 } 127 128 PropertyAnimator::PropertyAnimator(PropertyValuesHolder* holder, Interpolator* interpolator, 129 nsecs_t startDelay, nsecs_t duration, int repeatCount, 130 RepeatMode repeatMode) 131 : mPropertyValuesHolder(holder) 132 , mInterpolator(interpolator) 133 , 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 144 void 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 163 void 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 182 void PropertyAnimatorSetListener::onAnimationFinished(BaseRenderNodeAnimator* animator) { 183 mSet->onFinished(animator); 184 } 185 } 186 } 187