OSDN Git Service

DO NOT MERGE. KEY_INTENT shouldn't grant permissions. am: 1f2a5d3622 -s ours am...
[android-x86/frameworks-base.git] / libs / hwui / Animator.cpp
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
17 #include "Animator.h"
18
19 #include <inttypes.h>
20 #include <set>
21
22 #include "AnimationContext.h"
23 #include "Interpolator.h"
24 #include "RenderNode.h"
25 #include "RenderProperties.h"
26
27 namespace android {
28 namespace uirenderer {
29
30 /************************************************************
31  *  BaseRenderNodeAnimator
32  ************************************************************/
33
34 BaseRenderNodeAnimator::BaseRenderNodeAnimator(float finalValue)
35         : mTarget(nullptr)
36         , mStagingTarget(nullptr)
37         , mFinalValue(finalValue)
38         , mDeltaValue(0)
39         , mFromValue(0)
40         , mStagingPlayState(PlayState::NotStarted)
41         , mPlayState(PlayState::NotStarted)
42         , mHasStartValue(false)
43         , mStartTime(0)
44         , mDuration(300)
45         , mStartDelay(0)
46         , mMayRunAsync(true)
47         , mPlayTime(0) {
48 }
49
50 BaseRenderNodeAnimator::~BaseRenderNodeAnimator() {
51 }
52
53 void BaseRenderNodeAnimator::checkMutable() {
54     // Should be impossible to hit as the Java-side also has guards for this
55     LOG_ALWAYS_FATAL_IF(mStagingPlayState != PlayState::NotStarted,
56             "Animator has already been started!");
57 }
58
59 void BaseRenderNodeAnimator::setInterpolator(Interpolator* interpolator) {
60     checkMutable();
61     mInterpolator.reset(interpolator);
62 }
63
64 void BaseRenderNodeAnimator::setStartValue(float value) {
65     checkMutable();
66     doSetStartValue(value);
67 }
68
69 void BaseRenderNodeAnimator::doSetStartValue(float value) {
70     mFromValue = value;
71     mDeltaValue = (mFinalValue - mFromValue);
72     mHasStartValue = true;
73 }
74
75 void BaseRenderNodeAnimator::setDuration(nsecs_t duration) {
76     checkMutable();
77     mDuration = duration;
78 }
79
80 void BaseRenderNodeAnimator::setStartDelay(nsecs_t startDelay) {
81     checkMutable();
82     mStartDelay = startDelay;
83 }
84
85 void BaseRenderNodeAnimator::attach(RenderNode* target) {
86     mStagingTarget = target;
87     onAttached();
88 }
89
90 void BaseRenderNodeAnimator::start() {
91     mStagingPlayState = PlayState::Running;
92     mStagingRequests.push_back(Request::Start);
93     onStagingPlayStateChanged();
94 }
95
96 void BaseRenderNodeAnimator::cancel() {
97     mStagingPlayState = PlayState::Finished;
98     mStagingRequests.push_back(Request::Cancel);
99     onStagingPlayStateChanged();
100 }
101
102 void BaseRenderNodeAnimator::reset() {
103     mStagingPlayState = PlayState::Finished;
104     mStagingRequests.push_back(Request::Reset);
105     onStagingPlayStateChanged();
106 }
107
108 void BaseRenderNodeAnimator::reverse() {
109     mStagingPlayState = PlayState::Reversing;
110     mStagingRequests.push_back(Request::Reverse);
111     onStagingPlayStateChanged();
112 }
113
114 void BaseRenderNodeAnimator::end() {
115     mStagingPlayState = PlayState::Finished;
116     mStagingRequests.push_back(Request::End);
117     onStagingPlayStateChanged();
118 }
119
120 void BaseRenderNodeAnimator::resolveStagingRequest(Request request) {
121     switch (request) {
122     case Request::Start:
123         mPlayTime = (mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) ?
124                         mPlayTime : 0;
125         mPlayState = PlayState::Running;
126         break;
127     case Request::Reverse:
128         mPlayTime = (mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) ?
129                         mPlayTime : mDuration;
130         mPlayState = PlayState::Reversing;
131         break;
132     case Request::Reset:
133         mPlayTime = 0;
134         mPlayState = PlayState::Finished;
135         break;
136     case Request::Cancel:
137         mPlayState = PlayState::Finished;
138         break;
139     case Request::End:
140         mPlayTime = mPlayState == PlayState::Reversing ? 0 : mDuration;
141         mPlayState = PlayState::Finished;
142         break;
143     default:
144         LOG_ALWAYS_FATAL("Invalid staging request: %d", static_cast<int>(request));
145     };
146 }
147
148 void BaseRenderNodeAnimator::pushStaging(AnimationContext& context) {
149     if (mStagingTarget) {
150         RenderNode* oldTarget = mTarget;
151         mTarget = mStagingTarget;
152         mStagingTarget = nullptr;
153         if (oldTarget && oldTarget != mTarget) {
154             oldTarget->onAnimatorTargetChanged(this);
155         }
156     }
157
158     if (!mHasStartValue) {
159         doSetStartValue(getValue(mTarget));
160     }
161
162     if (!mStagingRequests.empty()) {
163         // No interpolator was set, use the default
164         if (mPlayState == PlayState::NotStarted && !mInterpolator) {
165             mInterpolator.reset(Interpolator::createDefaultInterpolator());
166         }
167         // Keep track of the play state and play time before they are changed when
168         // staging requests are resolved.
169         nsecs_t currentPlayTime = mPlayTime;
170         PlayState prevFramePlayState = mPlayState;
171
172         // Resolve staging requests one by one.
173         for (Request request : mStagingRequests) {
174             resolveStagingRequest(request);
175         }
176         mStagingRequests.clear();
177
178         if (mStagingPlayState == PlayState::Finished) {
179             // Set the staging play time and end the animation
180             updatePlayTime(mPlayTime);
181             callOnFinishedListener(context);
182         } else if (mStagingPlayState == PlayState::Running
183                 || mStagingPlayState == PlayState::Reversing) {
184             bool changed = currentPlayTime != mPlayTime || prevFramePlayState != mStagingPlayState;
185             if (prevFramePlayState != mStagingPlayState) {
186                 transitionToRunning(context);
187             }
188             if (changed) {
189                 // Now we need to seek to the stagingPlayTime (i.e. the animation progress that was
190                 // requested from UI thread). It is achieved by modifying mStartTime, such that
191                 // current time - mStartTime = stagingPlayTime (or mDuration -stagingPlayTime in the
192                 // case of reversing)
193                 nsecs_t currentFrameTime = context.frameTimeMs();
194                 if (mPlayState == PlayState::Reversing) {
195                     // Reverse is not supported for animations with a start delay, so here we
196                     // assume no start delay.
197                     mStartTime = currentFrameTime  - (mDuration - mPlayTime);
198                 } else {
199                     // Animation should play forward
200                     if (mPlayTime == 0) {
201                         // If the request is to start from the beginning, include start delay.
202                         mStartTime = currentFrameTime + mStartDelay;
203                     } else {
204                         // If the request is to seek to a non-zero play time, then we skip start
205                         // delay.
206                         mStartTime = currentFrameTime - mPlayTime;
207                     }
208                 }
209             }
210         }
211     }
212     onPushStaging();
213 }
214
215 void BaseRenderNodeAnimator::transitionToRunning(AnimationContext& context) {
216     nsecs_t frameTimeMs = context.frameTimeMs();
217     LOG_ALWAYS_FATAL_IF(frameTimeMs <= 0, "%" PRId64 " isn't a real frame time!", frameTimeMs);
218     if (mStartDelay < 0 || mStartDelay > 50000) {
219         ALOGW("Your start delay is strange and confusing: %" PRId64, mStartDelay);
220     }
221     mStartTime = frameTimeMs + mStartDelay;
222     if (mStartTime < 0) {
223         ALOGW("Ended up with a really weird start time of %" PRId64
224                 " with frame time %" PRId64 " and start delay %" PRId64,
225                 mStartTime, frameTimeMs, mStartDelay);
226         // Set to 0 so that the animate() basically instantly finishes
227         mStartTime = 0;
228     }
229     if (mDuration < 0) {
230         ALOGW("Your duration is strange and confusing: %" PRId64, mDuration);
231     }
232 }
233
234 bool BaseRenderNodeAnimator::animate(AnimationContext& context) {
235     if (mPlayState < PlayState::Running) {
236         return false;
237     }
238     if (mPlayState == PlayState::Finished) {
239         return true;
240     }
241
242     // This should be set before setValue() so animators can query this time when setValue
243     // is called.
244     nsecs_t currentPlayTime = context.frameTimeMs() - mStartTime;
245     bool finished = updatePlayTime(currentPlayTime);
246     if (finished && mPlayState != PlayState::Finished) {
247         mPlayState = PlayState::Finished;
248         callOnFinishedListener(context);
249     }
250     return finished;
251 }
252
253 bool BaseRenderNodeAnimator::updatePlayTime(nsecs_t playTime) {
254     mPlayTime = mPlayState == PlayState::Reversing ? mDuration - playTime : playTime;
255     onPlayTimeChanged(mPlayTime);
256     // If BaseRenderNodeAnimator is handling the delay (not typical), then
257     // because the staging properties reflect the final value, we always need
258     // to call setValue even if the animation isn't yet running or is still
259     // being delayed as we need to override the staging value
260     if (playTime < 0) {
261         setValue(mTarget, mFromValue);
262         return false;
263     }
264
265     float fraction = 1.0f;
266     if ((mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) && mDuration > 0) {
267         fraction = mPlayTime / (float) mDuration;
268     }
269     fraction = MathUtils::clamp(fraction, 0.0f, 1.0f);
270
271     fraction = mInterpolator->interpolate(fraction);
272     setValue(mTarget, mFromValue + (mDeltaValue * fraction));
273
274     return playTime >= mDuration;
275 }
276
277 void BaseRenderNodeAnimator::forceEndNow(AnimationContext& context) {
278     if (mPlayState < PlayState::Finished) {
279         mPlayState = PlayState::Finished;
280         callOnFinishedListener(context);
281     }
282 }
283
284 void BaseRenderNodeAnimator::callOnFinishedListener(AnimationContext& context) {
285     if (mListener.get()) {
286         context.callOnFinished(this, mListener.get());
287     }
288 }
289
290 /************************************************************
291  *  RenderPropertyAnimator
292  ************************************************************/
293
294 struct RenderPropertyAnimator::PropertyAccessors {
295    RenderNode::DirtyPropertyMask dirtyMask;
296    GetFloatProperty getter;
297    SetFloatProperty setter;
298 };
299
300 // Maps RenderProperty enum to accessors
301 const RenderPropertyAnimator::PropertyAccessors RenderPropertyAnimator::PROPERTY_ACCESSOR_LUT[] = {
302     {RenderNode::TRANSLATION_X, &RenderProperties::getTranslationX, &RenderProperties::setTranslationX },
303     {RenderNode::TRANSLATION_Y, &RenderProperties::getTranslationY, &RenderProperties::setTranslationY },
304     {RenderNode::TRANSLATION_X, &RenderProperties::getTranslationZ, &RenderProperties::setTranslationZ },
305     {RenderNode::SCALE_X, &RenderProperties::getScaleX, &RenderProperties::setScaleX },
306     {RenderNode::SCALE_Y, &RenderProperties::getScaleY, &RenderProperties::setScaleY },
307     {RenderNode::ROTATION, &RenderProperties::getRotation, &RenderProperties::setRotation },
308     {RenderNode::ROTATION_X, &RenderProperties::getRotationX, &RenderProperties::setRotationX },
309     {RenderNode::ROTATION_Y, &RenderProperties::getRotationY, &RenderProperties::setRotationY },
310     {RenderNode::X, &RenderProperties::getX, &RenderProperties::setX },
311     {RenderNode::Y, &RenderProperties::getY, &RenderProperties::setY },
312     {RenderNode::Z, &RenderProperties::getZ, &RenderProperties::setZ },
313     {RenderNode::ALPHA, &RenderProperties::getAlpha, &RenderProperties::setAlpha },
314 };
315
316 RenderPropertyAnimator::RenderPropertyAnimator(RenderProperty property, float finalValue)
317         : BaseRenderNodeAnimator(finalValue)
318         , mPropertyAccess(&(PROPERTY_ACCESSOR_LUT[property])) {
319 }
320
321 void RenderPropertyAnimator::onAttached() {
322     if (!mHasStartValue
323             && mStagingTarget->isPropertyFieldDirty(mPropertyAccess->dirtyMask)) {
324         setStartValue((mStagingTarget->stagingProperties().*mPropertyAccess->getter)());
325     }
326 }
327
328 void RenderPropertyAnimator::onStagingPlayStateChanged() {
329     if (mStagingPlayState == PlayState::Running) {
330         if (mStagingTarget) {
331             (mStagingTarget->mutateStagingProperties().*mPropertyAccess->setter)(finalValue());
332         } else {
333             // In the case of start delay where stagingTarget has been sync'ed over and null'ed
334             // we delay the properties update to push staging.
335             mShouldUpdateStagingProperties = true;
336         }
337     } else if (mStagingPlayState == PlayState::Finished) {
338         // We're being canceled, so make sure that whatever values the UI thread
339         // is observing for us is pushed over
340         mShouldSyncPropertyFields = true;
341     }
342 }
343
344 void RenderPropertyAnimator::onPushStaging() {
345     if (mShouldUpdateStagingProperties) {
346         (mTarget->mutateStagingProperties().*mPropertyAccess->setter)(finalValue());
347         mShouldUpdateStagingProperties = false;
348     }
349
350     if (mShouldSyncPropertyFields) {
351         mTarget->setPropertyFieldsDirty(dirtyMask());
352         mShouldSyncPropertyFields = false;
353     }
354 }
355
356 uint32_t RenderPropertyAnimator::dirtyMask() {
357     return mPropertyAccess->dirtyMask;
358 }
359
360 float RenderPropertyAnimator::getValue(RenderNode* target) const {
361     return (target->properties().*mPropertyAccess->getter)();
362 }
363
364 void RenderPropertyAnimator::setValue(RenderNode* target, float value) {
365     (target->animatorProperties().*mPropertyAccess->setter)(value);
366 }
367
368 /************************************************************
369  *  CanvasPropertyPrimitiveAnimator
370  ************************************************************/
371
372 CanvasPropertyPrimitiveAnimator::CanvasPropertyPrimitiveAnimator(
373                 CanvasPropertyPrimitive* property, float finalValue)
374         : BaseRenderNodeAnimator(finalValue)
375         , mProperty(property) {
376 }
377
378 float CanvasPropertyPrimitiveAnimator::getValue(RenderNode* target) const {
379     return mProperty->value;
380 }
381
382 void CanvasPropertyPrimitiveAnimator::setValue(RenderNode* target, float value) {
383     mProperty->value = value;
384 }
385
386 uint32_t CanvasPropertyPrimitiveAnimator::dirtyMask() {
387     return RenderNode::DISPLAY_LIST;
388 }
389
390 /************************************************************
391  *  CanvasPropertySkPaintAnimator
392  ************************************************************/
393
394 CanvasPropertyPaintAnimator::CanvasPropertyPaintAnimator(
395                 CanvasPropertyPaint* property, PaintField field, float finalValue)
396         : BaseRenderNodeAnimator(finalValue)
397         , mProperty(property)
398         , mField(field) {
399 }
400
401 float CanvasPropertyPaintAnimator::getValue(RenderNode* target) const {
402     switch (mField) {
403     case STROKE_WIDTH:
404         return mProperty->value.getStrokeWidth();
405     case ALPHA:
406         return mProperty->value.getAlpha();
407     }
408     LOG_ALWAYS_FATAL("Unknown field %d", (int) mField);
409     return -1;
410 }
411
412 static uint8_t to_uint8(float value) {
413     int c = (int) (value + .5f);
414     return static_cast<uint8_t>( c < 0 ? 0 : c > 255 ? 255 : c );
415 }
416
417 void CanvasPropertyPaintAnimator::setValue(RenderNode* target, float value) {
418     switch (mField) {
419     case STROKE_WIDTH:
420         mProperty->value.setStrokeWidth(value);
421         return;
422     case ALPHA:
423         mProperty->value.setAlpha(to_uint8(value));
424         return;
425     }
426     LOG_ALWAYS_FATAL("Unknown field %d", (int) mField);
427 }
428
429 uint32_t CanvasPropertyPaintAnimator::dirtyMask() {
430     return RenderNode::DISPLAY_LIST;
431 }
432
433 RevealAnimator::RevealAnimator(int centerX, int centerY,
434         float startValue, float finalValue)
435         : BaseRenderNodeAnimator(finalValue)
436         , mCenterX(centerX)
437         , mCenterY(centerY) {
438     setStartValue(startValue);
439 }
440
441 float RevealAnimator::getValue(RenderNode* target) const {
442     return target->properties().getRevealClip().getRadius();
443 }
444
445 void RevealAnimator::setValue(RenderNode* target, float value) {
446     target->animatorProperties().mutableRevealClip().set(true,
447             mCenterX, mCenterY, value);
448 }
449
450 uint32_t RevealAnimator::dirtyMask() {
451     return RenderNode::GENERIC;
452 }
453
454 } /* namespace uirenderer */
455 } /* namespace android */