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