• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "core/animation/animator.h"
17 
18 #include "base/log/jank_frame_report.h"
19 #include "base/utils/system_properties.h"
20 #include "base/utils/utils.h"
21 #include "core/animation/scheduler.h"
22 #include "core/common/container.h"
23 #include "core/common/container_scope.h"
24 #include "core/common/thread_checker.h"
25 #include "core/pipeline/pipeline_base.h"
26 
27 namespace OHOS::Ace {
28 namespace {
29 
30 int32_t g_controllerId = 0;
AllocControllerId()31 int32_t AllocControllerId()
32 {
33     return ++g_controllerId;
34 }
35 
36 } // namespace
37 
38 // Static Functions.
39 float Animator::scale_ = 1.0f;
40 
SetDurationScale(float scale)41 void Animator::SetDurationScale(float scale)
42 {
43     if (scale < 0.0f) {
44         LOGE("Invalid scale value: %{public}f", scale);
45         return;
46     }
47     scale_ = scale;
48 }
49 
GetAnimationScale() const50 float Animator::GetAnimationScale() const
51 {
52 #ifdef OHOS_STANDARD_SYSTEM
53     // if rosen is enabled, animationScale should be set on Rosen.
54     return allowRunningAsynchronously_ ? 1.0 : SystemProperties::GetAnimationScale();
55 #else
56     return scale_;
57 #endif
58 }
59 
60 // Public Functions.
Animator(const char * name)61 Animator::Animator(const char* name)
62 {
63     controllerId_ = AllocControllerId();
64     if (name != nullptr) {
65         animatorName_ = name;
66     }
67 }
68 
Animator(const WeakPtr<PipelineBase> & context,const char * name)69 Animator::Animator(const WeakPtr<PipelineBase>& context, const char* name)
70 {
71     controllerId_ = AllocControllerId();
72     AttachScheduler(context);
73     if (name != nullptr) {
74         animatorName_ = name;
75     }
76 }
77 
~Animator()78 Animator::~Animator()
79 {
80     CHECK_RUN_ON(UI);
81     LOGD("Animator destructor. id:%{public}d", controllerId_);
82     // Clear all listeners first to make its destruction silently.
83     ClearAllListeners();
84     ClearInterpolators();
85     if (!IsStopped()) {
86         Stop();
87     }
88 }
89 
AttachScheduler(const WeakPtr<PipelineBase> & context)90 void Animator::AttachScheduler(const WeakPtr<PipelineBase>& context)
91 {
92     auto&& callback = [weak = AceType::WeakClaim(this)](uint64_t duration) {
93         auto controller = weak.Upgrade();
94         if (!controller) {
95             LOGE("controller is nullptr, skip frame callback.");
96             return;
97         }
98         controller->OnFrame(duration);
99     };
100     scheduler_ = SchedulerBuilder::Build(callback, context);
101 }
102 
AttachSchedulerOnContainer()103 void Animator::AttachSchedulerOnContainer()
104 {
105     auto pipeline = PipelineBase::GetCurrentContext();
106     CHECK_NULL_VOID(pipeline);
107     AttachScheduler(pipeline);
108 }
109 
HasScheduler() const110 bool Animator::HasScheduler() const
111 {
112     return scheduler_ != nullptr;
113 }
114 
AddInterpolator(const RefPtr<Interpolator> & animation)115 void Animator::AddInterpolator(const RefPtr<Interpolator>& animation)
116 {
117     CHECK_RUN_ON(UI);
118     if (animation) {
119         interpolators_.emplace_back(animation);
120     }
121 }
122 
RemoveInterpolator(const RefPtr<Interpolator> & animation)123 void Animator::RemoveInterpolator(const RefPtr<Interpolator>& animation)
124 {
125     CHECK_RUN_ON(UI);
126     interpolators_.remove(animation);
127 }
128 
ClearInterpolators()129 void Animator::ClearInterpolators()
130 {
131     CHECK_RUN_ON(UI);
132     interpolators_.clear();
133 }
134 
AddProxyController(const RefPtr<Animator> & proxy)135 void Animator::AddProxyController(const RefPtr<Animator>& proxy)
136 {
137     CHECK_RUN_ON(UI);
138     if (!proxy) {
139         LOGE("Add Proxy Controller failed. controller is null.");
140         return;
141     }
142     if (RawPtr(proxy) != this) {
143         proxyControllers_.emplace_back(proxy);
144         proxy->Copy(Claim(this));
145         proxy->scheduler_.Reset();
146     }
147 }
148 
RemoveProxyController(const RefPtr<Animator> & proxy)149 void Animator::RemoveProxyController(const RefPtr<Animator>& proxy)
150 {
151     CHECK_RUN_ON(UI);
152     proxyControllers_.remove(proxy);
153 }
154 
ClearProxyControllers()155 void Animator::ClearProxyControllers()
156 {
157     CHECK_RUN_ON(UI);
158     proxyControllers_.clear();
159 }
160 
GetStatus() const161 Animator::Status Animator::GetStatus() const
162 {
163     return status_;
164 }
165 
IsStopped() const166 bool Animator::IsStopped() const
167 {
168     return status_ == Status::STOPPED;
169 }
170 
IsRunning() const171 bool Animator::IsRunning() const
172 {
173     return status_ == Status::RUNNING;
174 }
175 
176 // When the animation is in the delayed start phase.
IsPending() const177 bool Animator::IsPending() const
178 {
179     if ((status_ == Status::RUNNING) || (status_ == Status::PAUSED)) {
180         return elapsedTime_ < startDelay_;
181     } else {
182         return false;
183     }
184 }
185 
GetDuration() const186 int32_t Animator::GetDuration() const
187 {
188     return duration_;
189 }
190 
SetDuration(int32_t duration)191 void Animator::SetDuration(int32_t duration)
192 {
193     CHECK_RUN_ON(UI);
194     if (duration < 0) {
195         LOGE("invalid duration time, keep the old. id: %{public}d", controllerId_);
196         return;
197     }
198     LOGD("set duration: %{public}d. id: %{public}d", duration, controllerId_);
199     if ((status_ == Status::RUNNING || status_ == Status::PAUSED) && duration != 0) {
200         // Need to update elapsedTime when animation running or paused.
201         elapsedTime_ = (duration_ / duration) * elapsedTime_;
202     }
203     duration_ = duration;
204     for (auto& controller : proxyControllers_) {
205         controller->SetDuration(duration);
206     }
207 }
208 
SetIteration(int32_t iteration)209 bool Animator::SetIteration(int32_t iteration)
210 {
211     CHECK_RUN_ON(UI);
212     if (iteration_ == iteration) {
213         return true;
214     }
215     if ((iteration < 0) && (iteration != ANIMATION_REPEAT_INFINITE)) {
216         LOGE("invalid iteration: %{public}d. id: %{public}d", iteration, controllerId_);
217         return false;
218     }
219     // if status is not idle, finish current animation and init animation
220     if (status_ != Status::IDLE) {
221         Finish();
222     }
223     LOGD("set iteration: %{public}d. id: %{public}d", iteration, controllerId_);
224     UpdateIteration(iteration);
225     repeatTimesLeft_ = repeatTimes_;
226     for (auto& controller : proxyControllers_) {
227         controller->SetIteration(iteration);
228     }
229     return true;
230 }
231 
GetIteration() const232 int32_t Animator::GetIteration() const
233 {
234     return iteration_;
235 }
236 
SetStartDelay(int32_t startDelay)237 void Animator::SetStartDelay(int32_t startDelay)
238 {
239     CHECK_RUN_ON(UI);
240     if (startDelay < 0) {
241         LOGE("invalid startDelay time, keep the old. id: %{public}d", controllerId_);
242         return;
243     }
244     LOGD("set start delay: %{public}d. id: %{public}d", startDelay, controllerId_);
245     startDelay_ = startDelay;
246     for (auto& controller : proxyControllers_) {
247         controller->SetStartDelay(startDelay);
248     }
249 }
250 
SetFillMode(FillMode fillMode)251 void Animator::SetFillMode(FillMode fillMode)
252 {
253     CHECK_RUN_ON(UI);
254     fillMode_ = fillMode;
255     for (auto& controller : proxyControllers_) {
256         controller->SetFillMode(fillMode);
257     }
258 }
259 
GetFillMode() const260 FillMode Animator::GetFillMode() const
261 {
262     return fillMode_;
263 }
264 
SetTempo(float tempo)265 void Animator::SetTempo(float tempo)
266 {
267     CHECK_RUN_ON(UI);
268     if (tempo < 0.0f) {
269         return;
270     }
271     if (NearZero(tempo)) {
272         scaledStartDelay_ = 0;
273         scaledDuration_ = 0;
274     }
275     tempo_ = tempo;
276 }
277 
ApplyOption(const AnimationOption & option)278 void Animator::ApplyOption(const AnimationOption& option)
279 {
280     SetDuration(option.GetDuration());
281     SetStartDelay(option.GetDelay());
282     SetIteration(option.GetIteration());
283     SetTempo(option.GetTempo());
284     SetAnimationDirection(option.GetAnimationDirection());
285 }
286 
SetAnimationDirection(AnimationDirection direction)287 void Animator::SetAnimationDirection(AnimationDirection direction)
288 {
289     CHECK_RUN_ON(UI);
290     direction_ = direction;
291     for (auto& controller : proxyControllers_) {
292         controller->SetAnimationDirection(direction);
293     }
294 }
295 
SetAllowRunningAsynchronously(bool runAsync)296 void Animator::SetAllowRunningAsynchronously(bool runAsync)
297 {
298     allowRunningAsynchronously_ = runAsync;
299     LOGD("Set allow running asynchronously. id: %{public}d, allow: %{public}d", controllerId_, runAsync);
300 }
301 
GetAllowRunningAsynchronously()302 bool Animator::GetAllowRunningAsynchronously()
303 {
304     return allowRunningAsynchronously_;
305 }
306 
307 // return true, the animation is played backward
308 // return false, the animation is played forward
GetInitAnimationDirection()309 bool Animator::GetInitAnimationDirection()
310 {
311     if (direction_ == AnimationDirection::NORMAL) {
312         return isReverse_;
313     }
314     if (direction_ == AnimationDirection::REVERSE) {
315         return !isReverse_;
316     }
317     // for Alternate and Alternate_Reverse
318     bool isOddRound = ((repeatTimes_ - repeatTimesLeft_ + 1) % 2) == 1;
319     bool oddRoundDirectionNormal = direction_ == AnimationDirection::ALTERNATE;
320     if (isOddRound ^ oddRoundDirectionNormal) {
321         // if isOddRound is different from oddRoundDirectionNormal, same with AnimationDirection::REVERSE
322         return !isReverse_;
323     }
324     return isReverse_;
325 }
326 
UpdatePlayedTime(int32_t playedTime,bool checkReverse)327 void Animator::UpdatePlayedTime(int32_t playedTime, bool checkReverse)
328 {
329     if (playedTime < 0 || playedTime > duration_) {
330         LOGE("UpdatePlayedTime failed. Invalid playedTime:%{public}d", playedTime);
331         return;
332     }
333     if (startDelay_ != 0 || motion_) {
334         LOGE("Unsupported UpdatePlayedTime when startDelay or motion");
335         return;
336     }
337     if (!checkReverse) {
338         // only support go forward.
339         isReverse_ = false;
340         isCurDirection_ = false;
341     }
342     float scale = GetAnimationScale();
343     if (!NearZero(tempo_)) {
344         int32_t scaledPlayedTime = playedTime * scale / tempo_;
345         elapsedTime_ = scaledPlayedTime;
346     }
347 }
348 
GetPlayedTime() const349 int64_t Animator::GetPlayedTime() const
350 {
351     return elapsedTime_;
352 }
353 
TriggerFrame(int32_t playedTime,bool checkReverse)354 void Animator::TriggerFrame(int32_t playedTime, bool checkReverse)
355 {
356     CHECK_RUN_ON(UI);
357     if (playedTime < 0 || playedTime > duration_) {
358         LOGE("TriggerFrame failed. Invalid playedTime:%{public}d", playedTime);
359         return;
360     }
361     if (startDelay_ != 0 || motion_) {
362         LOGE("Unsupported TriggerFrame when startDelay or motion");
363         return;
364     }
365     UpdatePlayedTime(playedTime, checkReverse);
366     UpdateScaledTime();
367     NotifyPrepareListener();
368     NotifyInterpolator(elapsedTime_);
369 }
370 
PlayMotion(const RefPtr<Motion> & motion)371 void Animator::PlayMotion(const RefPtr<Motion>& motion)
372 {
373     CHECK_RUN_ON(UI);
374     if (!motion) {
375         LOGE("PlayMotion failed, motion is null.");
376         return;
377     }
378     interpolators_.clear();
379     isReverse_ = false;
380     motion_ = motion;
381     StartInner(false);
382 }
383 
Play()384 void Animator::Play()
385 {
386     CHECK_RUN_ON(UI);
387     if (iteration_ == 0) {
388         LOGD("no need to play animation, iteration is zero.");
389         return;
390     }
391     LOGD("Play animation in current direction, id: %{public}d", controllerId_);
392     motion_ = nullptr;
393     StartInner(false);
394 }
395 
Reverse()396 void Animator::Reverse()
397 {
398     CHECK_RUN_ON(UI);
399     if (iteration_ == 0) {
400         LOGD("no need to reverse animation, iteration is zero.");
401         return;
402     }
403     LOGD("Play animation in opposite direction, id: %{public}d", controllerId_);
404     motion_ = nullptr;
405     ToggleDirection();
406     StartInner(true);
407 }
408 
Forward()409 void Animator::Forward()
410 {
411     CHECK_RUN_ON(UI);
412     if (iteration_ == 0) {
413         LOGD("no need to play animation forward, iteration is zero.");
414         return;
415     }
416     if (isReverse_) {
417         ToggleDirection();
418     }
419     Play();
420 }
421 
Backward()422 void Animator::Backward()
423 {
424     CHECK_RUN_ON(UI);
425     if (iteration_ == 0) {
426         LOGD("no need to play animation backward, iteration is zero.");
427         return;
428     }
429     if (isReverse_) {
430         ToggleDirection();
431     }
432     Reverse();
433 }
434 
Pause()435 void Animator::Pause()
436 {
437     CHECK_RUN_ON(UI);
438     if (iteration_ == 0) {
439         LOGD("no need to pause animation, iteration is zero.");
440         return;
441     }
442     if (status_ == Status::PAUSED) {
443         LOGW("Already paused, do not need pause again. id: %{public}d", controllerId_);
444         return;
445     }
446     if (status_ == Status::IDLE) {
447         Play();
448     }
449     LOGD("animation pause. id: %{public}d", controllerId_);
450     if (scheduler_ && scheduler_->IsActive()) {
451         scheduler_->Stop();
452     }
453     if (needFrameJankReport_) {
454         JankFrameReport::ClearFrameJankFlag(JANK_RUNNING_ANIMATOR);
455     }
456     status_ = Status::PAUSED;
457     asyncTrace_ = nullptr;
458     StatusListenable::NotifyPauseListener();
459     for (auto& controller : proxyControllers_) {
460         controller->Pause();
461     }
462 }
463 
Resume()464 void Animator::Resume()
465 {
466     CHECK_RUN_ON(UI);
467     if (iteration_ == 0) {
468         LOGD("no need to resume animation, iteration is zero.");
469         return;
470     }
471     if (status_ == Status::RUNNING) {
472         LOGW("Already running, do not need resume again. id: %{public}d", controllerId_);
473         return;
474     }
475     LOGD("animation resume. id: %{public}d", controllerId_);
476     if (scheduler_ && !scheduler_->IsActive()) {
477         scheduler_->Start();
478     }
479     if (needFrameJankReport_) {
480         JankFrameReport::SetFrameJankFlag(JANK_RUNNING_ANIMATOR);
481     }
482     status_ = Status::RUNNING;
483     if (!motion_) {
484         asyncTrace_ = std::make_shared<AceAsyncScopedTrace>(animatorName_.c_str());
485     } else {
486         if (motion_->GetMotionType() == "friction") {
487             asyncTrace_ = std::make_shared<AceAsyncScopedTrace>((animatorName_ + ": friction").c_str());
488         } else if (motion_->GetMotionType() == "spring") {
489             asyncTrace_ = std::make_shared<AceAsyncScopedTrace>((animatorName_ + ": spring").c_str());
490         } else {
491             asyncTrace_ = std::make_shared<AceAsyncScopedTrace>(animatorName_.c_str());
492         }
493     }
494     isResume_ = true;
495     StatusListenable::NotifyResumeListener();
496     for (auto& controller : proxyControllers_) {
497         controller->Resume();
498     }
499 }
500 
Stop()501 void Animator::Stop()
502 {
503     CHECK_RUN_ON(UI);
504     if (iteration_ == 0) {
505         LOGD("no need to stop animation, iteration is zero.");
506         return;
507     }
508     if (status_ == Status::STOPPED) {
509         LOGD("Already stop, do not need stop again. id: %{public}d", controllerId_);
510         return;
511     }
512     LOGD("animation stop. id: %{public}d", controllerId_);
513     if (needFrameJankReport_) {
514         JankFrameReport::ClearFrameJankFlag(JANK_RUNNING_ANIMATOR);
515     }
516 
517     elapsedTime_ = 0;
518     repeatTimesLeft_ = repeatTimes_;
519     isBothBackwards = false;
520     UpdateScaledTime();
521     if (scheduler_ && scheduler_->IsActive()) {
522         scheduler_->Stop();
523     }
524     status_ = Status::STOPPED;
525     asyncTrace_ = nullptr;
526     StatusListenable::NotifyStopListener();
527     for (auto& controller : proxyControllers_) {
528         controller->Stop();
529     }
530 }
531 
Finish()532 void Animator::Finish()
533 {
534     CHECK_RUN_ON(UI);
535     if (iteration_ == 0) {
536         LOGD("no need to finish animation, iteration is zero.");
537         return;
538     }
539     if (status_ == Status::STOPPED) {
540         LOGD("Already stop, do not need finish again. id: %{public}d", controllerId_);
541         return;
542     }
543     LOGD("animation finish. id: %{public}d", controllerId_);
544     if (motion_) {
545         LOGD("end action not supports for motion. just stop it. id: %{public}d", controllerId_);
546         Stop();
547         return;
548     }
549     repeatTimesLeft_ = 0;
550     UpdateScaledTime();
551     OnFrame(((int64_t)scaledStartDelay_) + scaledDuration_);
552 }
553 
Cancel()554 void Animator::Cancel()
555 {
556     CHECK_RUN_ON(UI);
557     if (iteration_ == 0) {
558         LOGD("no need to cancel animation, iteration is zero.");
559         return;
560     }
561     if (status_ == Status::IDLE) {
562         LOGW("Already in idle, do not need cancel again. id: %{public}d", controllerId_);
563         return;
564     }
565     status_ = Status::IDLE;
566     LOGE("animation cancel. id: %{public}d", controllerId_);
567     elapsedTime_ = 0;
568     repeatTimesLeft_ = repeatTimes_;
569     UpdateScaledTime();
570     NotifyPrepareListener();
571     float normalizedTime = GetNormalizedTime(0.0f, true);
572     for (auto& interpolator : interpolators_) {
573         interpolator->OnInitNotify(normalizedTime, isReverse_);
574     }
575     if (scheduler_ && scheduler_->IsActive()) {
576         scheduler_->Stop();
577     }
578     NotifyIdleListener();
579 }
580 
GetId() const581 int32_t Animator::GetId() const
582 {
583     return controllerId_;
584 }
585 
586 // Private Functions.
OnFrame(int64_t duration)587 void Animator::OnFrame(int64_t duration)
588 {
589     CHECK_RUN_ON(UI);
590     // notify child first
591     for (auto& controller : proxyControllers_) {
592         controller->OnFrame(duration);
593     }
594     if (duration > INT64_MAX - elapsedTime_) {
595         LOGW("duration is too big, skip it. id:%{public}d", controllerId_);
596         return;
597     }
598     elapsedTime_ += duration;
599     UpdateScaledTime();
600     // skip delay time
601     if (elapsedTime_ < scaledStartDelay_) {
602         if ((fillMode_ == FillMode::BACKWARDS || fillMode_ == FillMode::BOTH) && !isBothBackwards) {
603             for (const auto& interpolator : interpolators_) {
604                 interpolator->OnNormalizedTimestampChanged(isCurDirection_ ? 1.0f : 0.0f, isReverse_);
605             }
606             isBothBackwards = true;
607         }
608         return;
609     }
610     JankFrameReport::RecordFrameUpdate();
611     NotifyPrepareListener();
612     // get playedTime
613     auto playedTime = elapsedTime_ - scaledStartDelay_;
614     // make playedTime in range 0 ~ INT32_MAX(max duration value)
615     playedTime = std::clamp<int64_t>(playedTime, 0L, (int64_t)INT32_MAX);
616     if (!motion_) {
617         NotifyInterpolator(playedTime);
618     } else {
619         NotifyMotion(playedTime);
620     }
621 }
622 
NotifyInterpolator(int32_t playedTime)623 void Animator::NotifyInterpolator(int32_t playedTime)
624 {
625     CHECK_RUN_ON(UI);
626     bool needStop = false;
627     bool notifyRepeat = false;
628     // do not notify user when handling playedTime, because users may be change duration or repeat times in callback.
629     // if they change this parameter, it will take effect next tick.
630     if (playedTime >= scaledDuration_) {
631         notifyRepeat = true;
632         auto isAlternateDirection =
633             (direction_ == AnimationDirection::ALTERNATE) || (direction_ == AnimationDirection::ALTERNATE_REVERSE);
634         if ((scaledDuration_ == 0) && isAlternateDirection && (iteration_ % 2 == 0)) {
635             isCurDirection_ = !isCurDirection_;
636         }
637         // make playedTime in range 0 ~ INTERPOLATE_DURATION_MAX
638         if (repeatTimesLeft_ == 0 || scaledDuration_ == 0) {
639             LOGD("animation stop, repeatTimesLeft: %{public}d, duration: %{public}d, id: %{public}d", repeatTimesLeft_,
640                 scaledDuration_, controllerId_);
641             repeatTimesLeft_ = 0;
642             needStop = true;
643         } else {
644             auto playedLoops = GetPlayedLoopsAndRemaining(playedTime);
645             if (repeatTimesLeft_ != ANIMATION_REPEAT_INFINITE) {
646                 needStop = UpdateRepeatTimesLeftAndCheckFinished(playedLoops);
647             }
648             if (isAlternateDirection) {
649                 isCurDirection_ = !isCurDirection_;
650             }
651             LOGD("animation next loop. repeat times remaining: %{public}d. id: %{public}d", repeatTimesLeft_,
652                 controllerId_);
653         }
654 
655         // after the above branches, playedTime in range 0 ~ INTERPOLATE_DURATION_MAX
656         // make elapsedTime_ in range 0 ~ scaledStartDelay_ + INTERPOLATE_DURATION_MAX
657         elapsedTime_ = playedTime + scaledStartDelay_;
658     }
659 
660     float normalizedTime = GetNormalizedTime(playedTime, needStop);
661     // all calculation above is done, we can notify user from now.
662     // users can change controller's configuration, and it will take effect next tick.
663     if (notifyRepeat && !needStop) {
664         // notify repeat before on timestamp changed.
665         StatusListenable::NotifyRepeatListener();
666     }
667     auto interpolators = interpolators_;
668     for (const auto& interpolator : interpolators) {
669         if (needStop && (fillMode_ == FillMode::NONE || fillMode_ == FillMode::BACKWARDS)) {
670             // notify init value set by user.
671             interpolator->OnInitNotify(normalizedTime, isReverse_);
672         } else {
673             // interpolate animation accept normalized time.
674             interpolator->OnNormalizedTimestampChanged(normalizedTime, isReverse_);
675         }
676     }
677     if (needStop && (!IsStopped())) {
678         // notify stop after on timestamp changed.
679         LOGD("animation stop in tick callback.");
680         Stop();
681     }
682 }
683 
NotifyMotion(int32_t playedTime)684 void Animator::NotifyMotion(int32_t playedTime)
685 {
686     CHECK_RUN_ON(UI);
687     // motion do not have normalized time, because no exact duration in motion.
688     // just pass actual time to motion, normalized time always zero.
689     motion_->OnTimestampChanged(playedTime, 0.0f, false);
690     if (motion_->IsCompleted()) {
691         Stop();
692     }
693 }
694 
StartInner(bool alwaysNotify)695 void Animator::StartInner(bool alwaysNotify)
696 {
697     CHECK_RUN_ON(UI);
698     if (status_ == Status::RUNNING) {
699         LOGD("controller already running, do not need start again. skip it. id: %{public}d", controllerId_);
700         if (toggleDirectionPending_) {
701             toggleDirectionPending_ = false;
702             isCurDirection_ = !isCurDirection_;
703         }
704 
705         if (alwaysNotify) {
706             StatusListenable::NotifyStartListener();
707             for (auto& controller : proxyControllers_) {
708                 controller->StartInner(alwaysNotify);
709             }
710         }
711         return;
712     }
713     toggleDirectionPending_ = false;
714     if (scheduler_ && !scheduler_->IsActive()) {
715         if (!StartAsync()) {
716             scheduler_->Start();
717         }
718     }
719     StatusListenable::NotifyStartListener();
720     if (needFrameJankReport_) {
721         JankFrameReport::SetFrameJankFlag(JANK_RUNNING_ANIMATOR);
722     }
723     status_ = Status::RUNNING;
724     if (!motion_) {
725         asyncTrace_ = std::make_shared<AceAsyncScopedTrace>(animatorName_.c_str());
726     } else {
727         if (motion_->GetMotionType() == "friction") {
728             asyncTrace_ = std::make_shared<AceAsyncScopedTrace>((animatorName_ + ": friction").c_str());
729         } else if (motion_->GetMotionType() == "spring") {
730             asyncTrace_ = std::make_shared<AceAsyncScopedTrace>((animatorName_ + ": spring").c_str());
731         } else {
732             asyncTrace_ = std::make_shared<AceAsyncScopedTrace>(animatorName_.c_str());
733         }
734     }
735     isCurDirection_ = GetInitAnimationDirection();
736     for (auto& controller : proxyControllers_) {
737         controller->StartInner(alwaysNotify);
738     }
739 }
740 
GetAnimationOption()741 AnimationOption Animator::GetAnimationOption()
742 {
743     AnimationOption option;
744     option.SetDuration(duration_ * GetAnimationScale());
745     option.SetDelay(startDelay_ * GetAnimationScale());
746     option.SetIteration(iteration_);
747     option.SetTempo(tempo_);
748     option.SetFillMode(fillMode_);
749 
750     AnimationDirection direction = direction_;
751     if (GetInitAnimationDirection()) {
752         switch (direction_) {
753             case AnimationDirection::NORMAL:
754                 direction = AnimationDirection::REVERSE;
755                 break;
756             case AnimationDirection::ALTERNATE:
757                 direction = AnimationDirection::ALTERNATE_REVERSE;
758                 break;
759             case AnimationDirection::REVERSE:
760                 direction = AnimationDirection::NORMAL;
761                 break;
762             case AnimationDirection::ALTERNATE_REVERSE:
763                 direction = AnimationDirection::ALTERNATE;
764                 break;
765             default:
766                 direction = AnimationDirection::NORMAL;
767                 break;
768         }
769     }
770 
771     option.SetAnimationDirection(direction);
772     return option;
773 }
774 
IsSupportedRunningAsynchronously()775 bool Animator::IsSupportedRunningAsynchronously()
776 {
777     for (const auto& animation : interpolators_) {
778         if (!animation->IsSupportedRunningAsynchronously()) {
779             return false;
780         }
781     }
782 
783     return true;
784 }
785 
StartAsync()786 bool Animator::StartAsync()
787 {
788     if (!SystemProperties::GetRosenBackendEnabled()) {
789         return false;
790     }
791 
792     if (!allowRunningAsynchronously_) {
793         return false;
794     }
795 
796     if (interpolators_.empty()) {
797         LOGD("interpolators_ is empty, controller id: %{public}d", controllerId_);
798         return false;
799     }
800 
801     if (!IsSupportedRunningAsynchronously()) {
802         LOGW("not support running asynchronously, controller id: %{public}d", controllerId_);
803         return false;
804     }
805     if (scheduler_) {
806         auto context = scheduler_->GetContext().Upgrade();
807         if (context && !context->IsRebuildFinished()) {
808             context->SetBuildAfterCallback([weak = AceType::WeakClaim(this)]() {
809                 auto controller = weak.Upgrade();
810                 if (controller != nullptr) {
811                     controller->StartInnerAsync();
812                 }
813             });
814             return true;
815         }
816     }
817     StartInnerAsync();
818     return true;
819 }
820 
StartInnerAsync()821 bool Animator::StartInnerAsync()
822 {
823     LOGD("start inner async, controller id: %{public}d, interpolators size:%{public}zu", controllerId_,
824         interpolators_.size());
825 
826     auto prepareCallback = [weak = AceType::WeakClaim(this)]() -> void {
827         auto controller = weak.Upgrade();
828         if (controller != nullptr) {
829             controller->NotifyPrepareListener();
830         }
831     };
832 
833     auto stopCallback = [weak = AceType::WeakClaim(this), id = Container::CurrentId()]() -> void {
834         ContainerScope scope(id);
835         auto controller = weak.Upgrade();
836         if (controller == nullptr) {
837             LOGE("notify stop failed, controller is null");
838             return;
839         }
840         controller->StopInnerAsync();
841     };
842 
843     auto animations = std::move(interpolators_);
844     auto option = GetAnimationOption();
845     asyncRunningAnimationCount_ = 0;
846     for (const auto& animation : animations) {
847         if (animation->RunAsync(scheduler_, option, prepareCallback, stopCallback)) {
848             asyncRunningAnimationCount_++;
849         }
850     }
851 
852     LOGD("start animations async. controller id: %{public}d, count: %{public}d", controllerId_,
853         asyncRunningAnimationCount_);
854     return true;
855 }
856 
StopInnerAsync()857 void Animator::StopInnerAsync()
858 {
859     if (--asyncRunningAnimationCount_ > 0) {
860         LOGD("notify stop, controller id: %{public}d, running animations count %{public}d", controllerId_,
861             asyncRunningAnimationCount_);
862         return;
863     }
864 
865     if (status_ != Status::STOPPED && (!HasScheduler() || !scheduler_->IsActive())) {
866         Stop();
867         LOGD("native animations stop. controller id: %{public}d", controllerId_);
868     }
869 }
870 
GetPlayedLoopsAndRemaining(int32_t & playedTime)871 int32_t Animator::GetPlayedLoopsAndRemaining(int32_t& playedTime)
872 {
873     // when duration equals 0, played loop equals INT32_MAX, and playedTime remains unchanged.
874     int32_t playedLoop = INT32_MAX;
875     if (scaledDuration_ != 0) {
876         // in order to make playedTime in range of 0 ~ INTERPOLATE_DURATION_MAX, calc elapsed loop between two vsyncs
877         playedLoop = std::clamp(playedTime / scaledDuration_, 0, INT32_MAX);
878         playedTime = playedTime % scaledDuration_;
879     }
880     return playedLoop;
881 }
882 
UpdateRepeatTimesLeftAndCheckFinished(int32_t playedLoops)883 bool Animator::UpdateRepeatTimesLeftAndCheckFinished(int32_t playedLoops)
884 {
885     // get the remaining repeatTimesLeft_
886     repeatTimesLeft_ -= playedLoops;
887     if (playedLoops > 1) {
888         LOGW("too long time between neighbor vsync, elapsed loop count: %{public}d. id: %{public}d", playedLoops,
889             controllerId_);
890     }
891     if (repeatTimesLeft_ < 0) {
892         LOGD("elapse too long, no repeat remaining. Loop: %{public}d. id: %{public}d", playedLoops, controllerId_);
893         return true;
894     }
895     return false;
896 }
897 
ToggleDirection()898 void Animator::ToggleDirection()
899 {
900     isReverse_ = !isReverse_;
901     LOGD("change direction. isReverse change to: %{public}d, id: %{public}d", isReverse_, controllerId_);
902     // if toggleDirectionPending_ is true, it will be cleared in StartInner
903     toggleDirectionPending_ = !toggleDirectionPending_;
904     if (status_ == Status::IDLE || status_ == Status::STOPPED) {
905         LOGD("toggle an idle controller, do not change time related params. id: %{public}d", controllerId_);
906         return;
907     }
908     if (repeatTimes_ == ANIMATION_REPEAT_INFINITE) {
909         elapsedTime_ = (scaledStartDelay_ + scaledDuration_ - elapsedTime_) + scaledStartDelay_;
910         LOGI("duration is infinite, can not reverse time related params. id: %{public}d", controllerId_);
911         return;
912     }
913     repeatTimesLeft_ = repeatTimes_ - repeatTimesLeft_;
914     LOGD("change left repeat times: %{public}d. id: %{public}d", repeatTimesLeft_, controllerId_);
915     elapsedTime_ = (scaledStartDelay_ + scaledDuration_ - elapsedTime_) + scaledStartDelay_;
916 }
917 
GetNormalizedTime(float playedTime,bool needStop) const918 float Animator::GetNormalizedTime(float playedTime, bool needStop) const
919 {
920     float normalizedTime = 0.0f;
921     if (needStop) {
922         LOGD("animation stop. set played time to the end value according to fill mode. id: %{public}d", controllerId_);
923         switch (fillMode_) {
924             case FillMode::FORWARDS:
925                 // Fall through.
926             case FillMode::BOTH:
927                 LOGD("fill mode is FORWARDS or BOTH. id: %{public}d", controllerId_);
928                 normalizedTime = 1.0f;
929                 break;
930             case FillMode::NONE:
931                 // Fall through.
932             case FillMode::BACKWARDS:
933                 LOGD("fill mode is NONE or BACKWARDS. id: %{public}d", controllerId_);
934                 normalizedTime = 0.0f;
935                 break;
936             default:
937                 LOGD("unknown fill mode, use default mode. id: %{public}d", controllerId_);
938                 normalizedTime = 1.0f;
939                 break;
940         }
941     } else {
942         normalizedTime = scaledDuration_ == 0 ? 1.0f : (1.0f * playedTime) / scaledDuration_;
943     }
944     return isCurDirection_ ? 1.0f - normalizedTime : normalizedTime;
945 }
946 
UpdateScaledTime()947 void Animator::UpdateScaledTime()
948 {
949     float scale = GetAnimationScale();
950     if (!NearZero(tempo_)) {
951         scaledDuration_ = duration_ * scale / tempo_;
952         scaledStartDelay_ = startDelay_ * scale / tempo_;
953     }
954 }
955 
UpdateIteration(int32_t iteration)956 void Animator::UpdateIteration(int32_t iteration)
957 {
958     iteration_ = iteration;
959     if (iteration <= 0 && iteration != ANIMATION_REPEAT_INFINITE) {
960         repeatTimes_ = 0;
961     } else if (iteration == ANIMATION_REPEAT_INFINITE) {
962         repeatTimes_ = ANIMATION_REPEAT_INFINITE;
963     } else {
964         repeatTimes_ = iteration - 1;
965     }
966 }
967 
Copy(const RefPtr<Animator> & controller)968 void Animator::Copy(const RefPtr<Animator>& controller)
969 {
970     if (!controller) {
971         return;
972     }
973     fillMode_ = controller->fillMode_;
974     direction_ = controller->direction_;
975     isCurDirection_ = controller->isCurDirection_;
976     toggleDirectionPending_ = controller->toggleDirectionPending_;
977     duration_ = controller->duration_;
978     elapsedTime_ = controller->elapsedTime_;
979     startDelay_ = controller->startDelay_;
980     repeatTimes_ = controller->repeatTimes_;
981     iteration_ = controller->iteration_;
982     repeatTimesLeft_ = controller->repeatTimesLeft_;
983     isReverse_ = controller->isReverse_;
984     isResume_ = controller->isResume_;
985     status_ = controller->status_;
986     scaledDuration_ = controller->scaledDuration_;
987     scaledStartDelay_ = controller->scaledStartDelay_;
988 }
989 
ResetIsReverse()990 void Animator::ResetIsReverse()
991 {
992     isReverse_ = false;
993 }
994 
995 } // namespace OHOS::Ace
996