1 /*
2  * Copyright (c) 2021-2023 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 "animation/rs_animation.h"
17 
18 #include "animation/rs_animation_callback.h"
19 #include "animation/rs_animation_common.h"
20 #include "animation/rs_animation_trace_utils.h"
21 #include "animation/rs_render_animation.h"
22 #include "command/rs_animation_command.h"
23 #include "modifier/rs_modifier_manager.h"
24 #include "modifier/rs_modifier_manager_map.h"
25 #include "platform/common/rs_log.h"
26 #include "transaction/rs_transaction_proxy.h"
27 #include "ui/rs_node.h"
28 #include "sandbox_utils.h"
29 
30 namespace OHOS {
31 namespace Rosen {
32 
GenerateId()33 AnimationId RSAnimation::GenerateId()
34 {
35     static pid_t pid_ = GetRealPid();
36     static std::atomic<uint32_t> currentId_ = 0;
37 
38     auto currentId = currentId_.fetch_add(1, std::memory_order_relaxed);
39     if (currentId == UINT32_MAX) {
40         ROSEN_LOGE("Animation Id overflow");
41     }
42 
43     // concat two 32-bit numbers to one 64-bit number
44     return ((AnimationId)pid_ << 32) | (currentId);
45 }
46 
RSAnimation()47 RSAnimation::RSAnimation() : id_(GenerateId()) {}
48 
~RSAnimation()49 RSAnimation::~RSAnimation()
50 {
51     RSNodeMap::MutableInstance().UnregisterAnimation(id_);
52 }
53 
SetFinishCallback(const std::function<void ()> & finishCallback)54 void RSAnimation::SetFinishCallback(const std::function<void()>& finishCallback)
55 {
56     if (finishCallback == nullptr) {
57         ROSEN_LOGE("Failed to set finish callback, callback is null!");
58         return;
59     }
60 
61     SetFinishCallback(std::make_shared<AnimationFinishCallback>(finishCallback));
62 }
63 
SetFinishCallback(const std::shared_ptr<AnimationFinishCallback> & finishCallback)64 void RSAnimation::SetFinishCallback(const std::shared_ptr<AnimationFinishCallback>& finishCallback)
65 {
66     finishCallback_ = finishCallback;
67     auto target = target_.lock();
68     if (target != nullptr) {
69         RSAnimationTraceUtils::GetInstance().addAnimationFinishTrace(
70             "Animation Set FinishCallback", target->GetId(), id_, true);
71     }
72 }
73 
SetRepeatCallback(const std::shared_ptr<AnimationRepeatCallback> & repeatCallback)74 void RSAnimation::SetRepeatCallback(const std::shared_ptr<AnimationRepeatCallback>& repeatCallback)
75 {
76     repeatCallback_ = repeatCallback;
77 }
78 
SetInteractiveFinishCallback(const std::shared_ptr<InteractiveAnimatorFinishCallback> & finishCallback)79 void RSAnimation::SetInteractiveFinishCallback(
80     const std::shared_ptr<InteractiveAnimatorFinishCallback>& finishCallback)
81 {
82     interactiveFinishCallback_ = finishCallback;
83 }
84 
CallFinishCallback()85 void RSAnimation::CallFinishCallback()
86 {
87     finishCallback_.reset();
88     interactiveFinishCallback_.reset();
89     state_ = AnimationState::FINISHED;
90     OnCallFinishCallback();
91     auto target = target_.lock();
92     if (target != nullptr) {
93         RSAnimationTraceUtils::GetInstance().addAnimationFinishTrace(
94             "Animation Call FinishCallback", target->GetId(), id_, true);
95     }
96 }
97 
CallRepeatCallback()98 void RSAnimation::CallRepeatCallback()
99 {
100     if (repeatCallback_ == nullptr) {
101         return;
102     }
103     repeatCallback_->Execute();
104 }
105 
CallLogicallyFinishCallback()106 void RSAnimation::CallLogicallyFinishCallback()
107 {
108     finishCallback_.reset();
109 }
110 
GetId() const111 AnimationId RSAnimation::GetId() const
112 {
113     return id_;
114 }
115 
IsStarted() const116 bool RSAnimation::IsStarted() const
117 {
118     return state_ != AnimationState::INITIALIZED;
119 }
120 
IsRunning() const121 bool RSAnimation::IsRunning() const
122 {
123     return state_ == AnimationState::RUNNING;
124 }
125 
IsPaused() const126 bool RSAnimation::IsPaused() const
127 {
128     return state_ == AnimationState::PAUSED;
129 }
130 
IsFinished() const131 bool RSAnimation::IsFinished() const
132 {
133     return state_ == AnimationState::FINISHED;
134 }
135 
Start(const std::shared_ptr<RSNode> & target)136 void RSAnimation::Start(const std::shared_ptr<RSNode>& target)
137 {
138     if (state_ != AnimationState::INITIALIZED) {
139         ROSEN_LOGD("State error, animation is in [%{public}d] when start.", state_);
140         return;
141     }
142 
143     if (target == nullptr) {
144         ROSEN_LOGE("Failed to start animation, target is null!");
145         return;
146     }
147 
148     target->AddAnimation(shared_from_this());
149 }
150 
StartInner(const std::shared_ptr<RSNode> & target)151 void RSAnimation::StartInner(const std::shared_ptr<RSNode>& target)
152 {
153     if (target == nullptr) {
154         ROSEN_LOGE("Failed to start animation, target is null!");
155         return;
156     }
157 
158     target_ = target;
159     state_ = AnimationState::RUNNING;
160     OnStart();
161     UpdateStagingValue(true);
162 }
163 
IsReversed() const164 bool RSAnimation::IsReversed() const
165 {
166     return isReversed_;
167 }
168 
GetTarget() const169 const std::weak_ptr<RSNode> RSAnimation::GetTarget() const
170 {
171     return target_;
172 }
173 
Pause()174 void RSAnimation::Pause()
175 {
176     if (state_ != AnimationState::RUNNING) {
177         ROSEN_LOGD("State error, animation is in [%{public}d] when pause", state_);
178         return;
179     }
180 
181     auto target = target_.lock();
182     if (target == nullptr) {
183         ROSEN_LOGE("Failed to pause animation, target is null!");
184         return;
185     }
186 
187     state_ = AnimationState::PAUSED;
188     OnPause();
189 }
190 
OnPause()191 void RSAnimation::OnPause()
192 {
193     if (uiAnimation_ != nullptr) {
194         uiAnimation_->Pause();
195         return;
196     }
197 
198     auto target = target_.lock();
199     if (target == nullptr) {
200         ROSEN_LOGE("Failed to pause animation, target is null!");
201         return;
202     }
203 
204     std::unique_ptr<RSCommand> command = std::make_unique<RSAnimationPause>(target->GetId(), id_);
205     auto transactionProxy = RSTransactionProxy::GetInstance();
206     if (transactionProxy != nullptr) {
207         transactionProxy->AddCommand(command, target->IsRenderServiceNode(), target->GetFollowType(), target->GetId());
208         if (target->NeedForcedSendToRemote()) {
209             std::unique_ptr<RSCommand> commandForRemote =
210                 std::make_unique<RSAnimationPause>(target->GetId(), id_);
211             transactionProxy->AddCommand(commandForRemote, true, target->GetFollowType(), target->GetId());
212         }
213     }
214 }
215 
IsUiAnimation() const216 bool RSAnimation::IsUiAnimation() const
217 {
218     return uiAnimation_ != nullptr;
219 }
220 
InteractivePause()221 void RSAnimation::InteractivePause()
222 {
223     if (state_ != AnimationState::RUNNING) {
224         ROSEN_LOGD("State error, animation is in [%{public}d] when pause", state_);
225         return;
226     }
227 
228     auto target = target_.lock();
229     if (target == nullptr) {
230         ROSEN_LOGE("Failed to interactive pause animation, target is null!");
231         return;
232     }
233 
234     state_ = AnimationState::PAUSED;
235 
236     if (uiAnimation_ != nullptr) {
237         uiAnimation_->Pause();
238     }
239 }
240 
InteractiveContinue()241 void RSAnimation::InteractiveContinue()
242 {
243     if (state_ != AnimationState::PAUSED) {
244         ROSEN_LOGD("State error, animation is in [%{public}d] when continue", state_);
245         return;
246     }
247 
248     auto target = target_.lock();
249     if (target == nullptr) {
250         ROSEN_LOGE("Failed to interactive continue animation, target is null!");
251         return;
252     }
253 
254     state_ = AnimationState::RUNNING;
255 
256     if (uiAnimation_ != nullptr) {
257         uiAnimation_->Resume();
258     }
259 }
260 
InteractiveFinish(RSInteractiveAnimationPosition pos)261 void RSAnimation::InteractiveFinish(RSInteractiveAnimationPosition pos)
262 {
263     if (state_ != AnimationState::RUNNING && state_ != AnimationState::PAUSED) {
264         ROSEN_LOGD("Animation is in [%{public}d] when Finish", state_);
265         return;
266     }
267     auto target = target_.lock();
268     if (target == nullptr) {
269         ROSEN_LOGE("Failed to interactive finish animation, target is null!");
270         return;
271     }
272     state_ = AnimationState::FINISHED;
273 
274     if (uiAnimation_ != nullptr) {
275         uiAnimation_->FinishOnPosition(pos);
276     }
277     UpdateStagingValueOnInteractiveFinish(pos);
278 }
279 
InteractiveReverse()280 void RSAnimation::InteractiveReverse()
281 {
282     if (state_ != AnimationState::PAUSED) {
283         ROSEN_LOGD("Animation is in [%{public}d] when Reverse", state_);
284         return;
285     }
286 
287     auto target = target_.lock();
288     if (target == nullptr) {
289         ROSEN_LOGE("Failed to pause animation, target is null!");
290         return;
291     }
292     isReversed_ = true;
293     state_ = AnimationState::RUNNING;
294 
295     OnUpdateStagingValue(false);
296 
297     if (uiAnimation_ != nullptr) {
298         uiAnimation_->SetReversedAndContinue();
299         return;
300     }
301 }
302 
InteractiveSetFraction(float fraction)303 void RSAnimation::InteractiveSetFraction(float fraction)
304 {
305     if (state_ != AnimationState::PAUSED) {
306         ROSEN_LOGD("State error, animation is in [%{public}d] when pause", state_);
307         return;
308     }
309 
310     auto target = target_.lock();
311     if (target == nullptr) {
312         ROSEN_LOGE("Failed to pause animation, target is null!");
313         return;
314     }
315 
316     if (uiAnimation_ != nullptr) {
317         uiAnimation_->SetFraction(fraction);
318     }
319 }
320 
Resume()321 void RSAnimation::Resume()
322 {
323     if (state_ != AnimationState::PAUSED) {
324         ROSEN_LOGD("State error, animation is in [%{public}d] when Resume", state_);
325         return;
326     }
327 
328     auto target = target_.lock();
329     if (target == nullptr) {
330         ROSEN_LOGE("Failed to resume animation, target is null!");
331         return;
332     }
333 
334     state_ = AnimationState::RUNNING;
335     OnResume();
336 }
337 
OnResume()338 void RSAnimation::OnResume()
339 {
340     if (uiAnimation_ != nullptr) {
341         uiAnimation_->Resume();
342         return;
343     }
344 
345     auto target = target_.lock();
346     if (target == nullptr) {
347         ROSEN_LOGE("Failed to resume animation, target is null!");
348         return;
349     }
350 
351     std::unique_ptr<RSCommand> command = std::make_unique<RSAnimationResume>(target->GetId(), id_);
352     auto transactionProxy = RSTransactionProxy::GetInstance();
353     if (transactionProxy != nullptr) {
354         transactionProxy->AddCommand(command, target->IsRenderServiceNode(), target->GetFollowType(), target->GetId());
355         if (target->NeedForcedSendToRemote()) {
356             std::unique_ptr<RSCommand> commandForRemote =
357                 std::make_unique<RSAnimationResume>(target->GetId(), id_);
358             transactionProxy->AddCommand(commandForRemote, true, target->GetFollowType(), target->GetId());
359         }
360     }
361 }
362 
Finish()363 void RSAnimation::Finish()
364 {
365     if (state_ != AnimationState::RUNNING && state_ != AnimationState::PAUSED) {
366         ROSEN_LOGD("Animation is in [%{public}d] when Finish", state_);
367         return;
368     }
369 
370     auto target = target_.lock();
371     if (target == nullptr) {
372         ROSEN_LOGE("Failed to finish animation, target is null!");
373         return;
374     }
375 
376     state_ = AnimationState::FINISHED;
377     OnFinish();
378 }
379 
OnFinish()380 void RSAnimation::OnFinish()
381 {
382     if (uiAnimation_ != nullptr) {
383         uiAnimation_->Finish();
384         return;
385     }
386 
387     auto target = target_.lock();
388     if (target == nullptr) {
389         ROSEN_LOGE("Failed to finish animation, target is null!");
390         return;
391     }
392 
393     std::unique_ptr<RSCommand> command = std::make_unique<RSAnimationFinish>(target->GetId(), id_);
394     auto transactionProxy = RSTransactionProxy::GetInstance();
395     if (transactionProxy != nullptr) {
396         transactionProxy->AddCommand(command, target->IsRenderServiceNode(), target->GetFollowType(), target->GetId());
397         if (target->NeedForcedSendToRemote()) {
398             std::unique_ptr<RSCommand> commandForRemote =
399                 std::make_unique<RSAnimationFinish>(target->GetId(), id_);
400             transactionProxy->AddCommand(commandForRemote, true, target->GetFollowType(), target->GetId());
401         }
402     }
403 }
404 
Reverse()405 void RSAnimation::Reverse()
406 {
407     if (state_ != AnimationState::RUNNING && state_ != AnimationState::PAUSED) {
408         ROSEN_LOGD("State error, animation is in [%{public}d] when Reverse", state_);
409         return;
410     }
411 
412     auto target = target_.lock();
413     if (target == nullptr) {
414         ROSEN_LOGE("Failed to reverse animation, target is null!");
415         return;
416     }
417 
418     isReversed_ = !isReversed_;
419     OnReverse();
420     UpdateStagingValue(false);
421 }
422 
OnReverse()423 void RSAnimation::OnReverse()
424 {
425     if (uiAnimation_ != nullptr) {
426         uiAnimation_->SetReversed(isReversed_);
427         return;
428     }
429 
430     auto target = target_.lock();
431     if (target == nullptr) {
432         ROSEN_LOGE("Failed to reverse animation, target is null!");
433         return;
434     }
435 
436     std::unique_ptr<RSCommand> command = std::make_unique<RSAnimationReverse>(target->GetId(), id_, isReversed_);
437     auto transactionProxy = RSTransactionProxy::GetInstance();
438     if (transactionProxy != nullptr) {
439         transactionProxy->AddCommand(command, target->IsRenderServiceNode(), target->GetFollowType(), target->GetId());
440         if (target->NeedForcedSendToRemote()) {
441             std::unique_ptr<RSCommand> commandForRemote =
442                 std::make_unique<RSAnimationReverse>(target->GetId(), id_, isReversed_);
443             transactionProxy->AddCommand(commandForRemote, true, target->GetFollowType(), target->GetId());
444         }
445     }
446 }
447 
SetFraction(float fraction)448 void RSAnimation::SetFraction(float fraction)
449 {
450     if (fraction < FRACTION_MIN || fraction > FRACTION_MAX) {
451         ROSEN_LOGE("Fraction[%{public}f] is invalid!", fraction);
452         return;
453     }
454 
455     if (state_ != AnimationState::PAUSED) {
456         ROSEN_LOGD("State error, animation is in [%{public}d] when SetFraction", state_);
457         return;
458     }
459 
460     auto target = target_.lock();
461     if (target == nullptr) {
462         ROSEN_LOGE("Failed to set fraction, target is null!");
463         return;
464     }
465 
466     OnSetFraction(fraction);
467 }
468 
OnSetFraction(float fraction)469 void RSAnimation::OnSetFraction(float fraction)
470 {
471     if (uiAnimation_ != nullptr) {
472         uiAnimation_->SetFraction(fraction);
473         return;
474     }
475 
476     auto target = target_.lock();
477     if (target == nullptr) {
478         ROSEN_LOGE("Failed to set fraction, target is null!");
479         return;
480     }
481 
482     std::unique_ptr<RSCommand> command = std::make_unique<RSAnimationSetFraction>(target->GetId(), id_, fraction);
483     auto transactionProxy = RSTransactionProxy::GetInstance();
484     if (transactionProxy != nullptr) {
485         transactionProxy->AddCommand(command, target->IsRenderServiceNode(), target->GetFollowType(), target->GetId());
486         if (target->NeedForcedSendToRemote()) {
487             std::unique_ptr<RSCommand> commandForRemote =
488                 std::make_unique<RSAnimationSetFraction>(target->GetId(), id_, fraction);
489             transactionProxy->AddCommand(commandForRemote, true, target->GetFollowType(), target->GetId());
490         }
491     }
492 }
493 
GetPropertyId() const494 PropertyId RSAnimation::GetPropertyId() const
495 {
496     return 0;
497 }
498 
UpdateStagingValue(bool isFirstStart)499 void RSAnimation::UpdateStagingValue(bool isFirstStart)
500 {
501     OnUpdateStagingValue(isFirstStart);
502 }
503 
UpdateParamToRenderAnimation(const std::shared_ptr<RSRenderAnimation> & animation)504 void RSAnimation::UpdateParamToRenderAnimation(const std::shared_ptr<RSRenderAnimation>& animation)
505 {
506     if (animation == nullptr) {
507         ROSEN_LOGD("Animation is null, failed to update param.");
508         return;
509     }
510     animation->SetDuration(GetDuration());
511     animation->SetStartDelay(GetStartDelay());
512     animation->SetRepeatCount(GetRepeatCount());
513     animation->SetAutoReverse(GetAutoReverse());
514     animation->SetSpeed(GetSpeed());
515     animation->SetDirection(GetDirection());
516     animation->SetFillMode(GetFillMode());
517     animation->SetRepeatCallbackEnable(repeatCallback_ != nullptr);
518     // only process FrameRateRange(rs) here
519     if (uiAnimation_ == nullptr) {
520         auto range = GetFrameRateRange();
521         if (range.IsValid()) {
522             animation->SetFrameRateRange(range);
523         }
524     }
525 }
526 
StartCustomAnimation(const std::shared_ptr<RSRenderAnimation> & animation)527 void RSAnimation::StartCustomAnimation(const std::shared_ptr<RSRenderAnimation>& animation)
528 {
529     auto modifierManager = RSModifierManagerMap::Instance()->GetModifierManager(gettid());
530     if (modifierManager == nullptr || animation == nullptr) {
531         ROSEN_LOGE("Failed to start custom animation, modifier manager is null  animationId: %{public}" PRIu64 "!",
532             GetId());
533         return;
534     }
535 
536     uiAnimation_ = animation;
537     if (auto target = target_.lock()) {
538         animation->targetId_ = target->GetId();
539     }
540     animation->Start();
541     modifierManager->AddAnimation(animation);
542 }
543 } // namespace Rosen
544 } // namespace OHOS
545