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