• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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_interactive_implict_animator.h"
17 
18 #include "modifier/rs_extended_modifier.h"
19 #include "platform/common/rs_log.h"
20 #include "sandbox_utils.h"
21 
22 namespace OHOS {
23 namespace Rosen {
24 enum class StartAnimationErrorCode : int32_t {
25     SUCCESS = 0,
26     INVALID_STATUS,
27     INVALID_ANIMATIONS,
28     INVALID_PROXY,
29     INVALID_CONTEXT,
30 };
31 
32 static bool g_isUniRenderEnabled = false;
33 
GenerateId()34 InteractiveImplictAnimatorId RSInteractiveImplictAnimator::GenerateId()
35 {
36     static pid_t pid_ = GetRealPid();
37     static std::atomic<uint32_t> currentId_ = 0;
38 
39     auto currentId = currentId_.fetch_add(1, std::memory_order_relaxed);
40     if (currentId == UINT32_MAX) {
41         ROSEN_LOGE("InteractiveImplictAnimatorId Id overflow");
42     }
43 
44     // concat two 32-bit numbers to one 64-bit number
45     return ((InteractiveImplictAnimatorId)pid_ << 32) | (currentId);
46 }
47 
Create(const RSAnimationTimingProtocol & timingProtocol,const RSAnimationTimingCurve & timingCurve)48 std::shared_ptr<RSInteractiveImplictAnimator> RSInteractiveImplictAnimator::Create(
49     const RSAnimationTimingProtocol& timingProtocol, const RSAnimationTimingCurve& timingCurve)
50 {
51     return std::shared_ptr<RSInteractiveImplictAnimator>(
52         new RSInteractiveImplictAnimator(nullptr, timingProtocol, timingCurve));
53 }
54 
Create(const std::shared_ptr<RSUIContext> rsUIContext,const RSAnimationTimingProtocol & timingProtocol,const RSAnimationTimingCurve & timingCurve)55 std::shared_ptr<RSInteractiveImplictAnimator> RSInteractiveImplictAnimator::Create(
56     const std::shared_ptr<RSUIContext> rsUIContext, const RSAnimationTimingProtocol& timingProtocol,
57     const RSAnimationTimingCurve& timingCurve)
58 {
59     return std::shared_ptr<RSInteractiveImplictAnimator>(
60         new RSInteractiveImplictAnimator(rsUIContext, timingProtocol, timingCurve));
61 }
62 
RSInteractiveImplictAnimator(const std::shared_ptr<RSUIContext> rsUIContext,const RSAnimationTimingProtocol & timingProtocol,const RSAnimationTimingCurve & timingCurve)63 RSInteractiveImplictAnimator::RSInteractiveImplictAnimator(const std::shared_ptr<RSUIContext> rsUIContext,
64     const RSAnimationTimingProtocol& timingProtocol, const RSAnimationTimingCurve& timingCurve)
65     : id_(GenerateId()), rsUIContext_(rsUIContext), timingProtocol_(timingProtocol), timingCurve_(timingCurve)
66 {
67     InitUniRenderEnabled();
68 }
69 
~RSInteractiveImplictAnimator()70 RSInteractiveImplictAnimator::~RSInteractiveImplictAnimator()
71 {
72     std::unique_ptr<RSCommand> command = std::make_unique<RSInteractiveAnimatorDestory>(id_);
73     AddCommand(command, IsUniRenderEnabled());
74     if (!IsUniRenderEnabled()) {
75         std::unique_ptr<RSCommand> commandForRemote = std::make_unique<RSInteractiveAnimatorDestory>(id_);
76         AddCommand(commandForRemote, true);
77     }
78 }
79 
IsUniRenderEnabled() const80 bool RSInteractiveImplictAnimator::IsUniRenderEnabled() const
81 {
82     return g_isUniRenderEnabled;
83 }
84 
InitUniRenderEnabled()85 void RSInteractiveImplictAnimator::InitUniRenderEnabled()
86 {
87     static bool inited = false;
88     if (!inited) {
89         inited = true;
90         g_isUniRenderEnabled = RSSystemProperties::GetUniRenderEnabled();
91         ROSEN_LOGD("RSInteractiveImplictAnimator::InitUniRenderEnabled:%{public}d", g_isUniRenderEnabled);
92     }
93 }
94 
GetAnimatorFinishCallback()95 std::shared_ptr<InteractiveAnimatorFinishCallback> RSInteractiveImplictAnimator::GetAnimatorFinishCallback()
96 {
97     auto callback = animatorCallback_.lock();
98     if (callback) {
99         return callback;
100     }
101     auto animatorCallback = std::make_shared<InteractiveAnimatorFinishCallback>([weak = weak_from_this()]() {
102         auto self = weak.lock();
103         if (self) {
104             self->CallFinishCallback();
105         }
106     });
107     animatorCallback_ = animatorCallback;
108     return animatorCallback;
109 }
110 
AddImplictAnimation(std::function<void ()> callback)111 size_t RSInteractiveImplictAnimator::AddImplictAnimation(std::function<void()> callback)
112 {
113     if (state_ != RSInteractiveAnimationState::INACTIVE && state_ != RSInteractiveAnimationState::ACTIVE) {
114         ROSEN_LOGE("AddAnimation failed, state_ is error");
115         return 0;
116     }
117 
118     auto rsUIContext = rsUIContext_.lock();
119     auto implicitAnimator = rsUIContext ? rsUIContext->GetRSImplicitAnimator() :
120         RSImplicitAnimatorMap::Instance().GetAnimator(gettid());
121     if (implicitAnimator == nullptr) {
122         ROSEN_LOGE("Failed to open implicit animation, implicit animator is null!");
123         return 0;
124     }
125 
126     if (timingProtocol_.GetDuration() <= 0) {
127         return 0;
128     }
129 
130     implicitAnimator->OpenInterActiveImplicitAnimation(true, timingProtocol_, timingCurve_, nullptr);
131     callback();
132     auto animations = implicitAnimator->CloseInterActiveImplicitAnimation(true);
133 
134     for (auto& [animation, nodeId] : animations) {
135         if (fractionAnimationId_ == 0 && animation->IsSupportInteractiveAnimator()) {
136             fractionAnimationId_ = animation->GetId();
137             fractionNodeId_ = nodeId;
138         }
139         std::weak_ptr<RSAnimation> weakAnimation = animation;
140         animation->SetInteractiveFinishCallback(GetAnimatorFinishCallback());
141         animations_.emplace_back(weakAnimation, nodeId);
142     }
143     state_ = RSInteractiveAnimationState::ACTIVE;
144     return animations.size();
145 }
146 
AddAnimation(std::function<void ()> callback)147 size_t RSInteractiveImplictAnimator::AddAnimation(std::function<void()> callback)
148 {
149     if (state_ != RSInteractiveAnimationState::INACTIVE && state_ != RSInteractiveAnimationState::ACTIVE) {
150         ROSEN_LOGE("AddAnimation failed, state_ is error");
151         return 0;
152     }
153     auto rsUIContext = rsUIContext_.lock();
154     auto implicitAnimator = rsUIContext ? rsUIContext->GetRSImplicitAnimator() :
155         RSImplicitAnimatorMap::Instance().GetAnimator(gettid());
156     if (implicitAnimator == nullptr) {
157         ROSEN_LOGE("Failed to open implicit animation, implicit animator is null!");
158         return 0;
159     }
160 
161     implicitAnimator->OpenInterActiveImplicitAnimation(false, timingProtocol_, timingCurve_, nullptr);
162     callback();
163     auto animations = implicitAnimator->CloseInterActiveImplicitAnimation(false);
164 
165     for (auto& [animation, nodeId] : animations) {
166         if (fractionAnimationId_ == 0 && animation->IsSupportInteractiveAnimator()) {
167             fractionAnimationId_ = animation->GetId();
168             fractionNodeId_ = nodeId;
169         }
170         std::weak_ptr<RSAnimation> weakAnimation = animation;
171         animation->SetInteractiveFinishCallback(GetAnimatorFinishCallback());
172         animations_.emplace_back(weakAnimation, nodeId);
173     }
174     state_ = RSInteractiveAnimationState::ACTIVE;
175     return animations.size();
176 }
177 
StartAnimation()178 int32_t RSInteractiveImplictAnimator::StartAnimation()
179 {
180     if (state_ != RSInteractiveAnimationState::ACTIVE) {
181         ROSEN_LOGE("StartAnimation failed, state_ is error");
182         return static_cast<int32_t>(StartAnimationErrorCode::INVALID_STATUS);
183     }
184 
185     if (animations_.empty()) {
186         ROSEN_LOGE("StartAnimation failed, animations size is error");
187         return static_cast<int32_t>(StartAnimationErrorCode::INVALID_ANIMATIONS);
188     }
189     auto rsUIContext = rsUIContext_.lock();
190     std::vector<std::pair<NodeId, AnimationId>> renderAnimations;
191     for (auto& [item, nodeId] : animations_) {
192         auto animation = item.lock();
193         auto target = rsUIContext ? rsUIContext->GetNodeMap().GetNode<RSNode>(nodeId) :
194             RSNodeMap::Instance().GetNode<RSNode>(nodeId);
195         if (target != nullptr && animation != nullptr) {
196             animation->InteractiveContinue();
197             if (!animation->IsUiAnimation()) {
198                 renderAnimations.emplace_back(nodeId, animation->GetId());
199             }
200         }
201     }
202     state_ = RSInteractiveAnimationState::RUNNING;
203 
204     auto transactionProxy = RSTransactionProxy::GetInstance();
205     if (transactionProxy == nullptr) {
206         ROSEN_LOGE("Failed to start interactive animation, transaction proxy is null!");
207         return static_cast<int32_t>(StartAnimationErrorCode::INVALID_PROXY);
208     }
209     std::unique_ptr<RSCommand> command = std::make_unique<RSInteractiveAnimatorCreate>(id_, renderAnimations, true);
210     AddCommand(command, IsUniRenderEnabled());
211     if (!IsUniRenderEnabled()) {
212         std::unique_ptr<RSCommand> commandForRemote =
213             std::make_unique<RSInteractiveAnimatorCreate>(id_, renderAnimations, true);
214         AddCommand(commandForRemote, true);
215     }
216     return static_cast<int32_t>(StartAnimationErrorCode::SUCCESS);
217 }
218 
PauseAnimation()219 void RSInteractiveImplictAnimator::PauseAnimation()
220 {
221     if (state_ != RSInteractiveAnimationState::RUNNING) {
222         ROSEN_LOGE("PauseAnimation failed, state_ is error");
223         return;
224     }
225     state_ = RSInteractiveAnimationState::PAUSED;
226 
227     auto rsUIContext = rsUIContext_.lock();
228     for (auto& [item, nodeId] : animations_) {
229         auto animation = item.lock();
230         auto target = rsUIContext ? rsUIContext->GetNodeMap().GetNode<RSNode>(nodeId) :
231             RSNodeMap::Instance().GetNode<RSNode>(nodeId);
232         if (target != nullptr && animation != nullptr) {
233             animation->InteractivePause();
234         }
235     }
236     auto transactionProxy = RSTransactionProxy::GetInstance();
237     if (transactionProxy == nullptr) {
238         ROSEN_LOGE("RSTransactionProxy is nullptr");
239         return;
240     }
241     std::unique_ptr<RSCommand> command = std::make_unique<RSInteractiveAnimatorPause>(id_);
242     AddCommand(command, IsUniRenderEnabled());
243     if (!IsUniRenderEnabled()) {
244         std::unique_ptr<RSCommand> commandForRemote = std::make_unique<RSInteractiveAnimatorPause>(id_);
245         AddCommand(commandForRemote, true);
246     }
247 }
248 
ContinueAnimation()249 void RSInteractiveImplictAnimator::ContinueAnimation()
250 {
251     if (state_ != RSInteractiveAnimationState::PAUSED) {
252         ROSEN_LOGE("ContinueAnimation failed, state_ is error");
253         return;
254     }
255 
256     state_ = RSInteractiveAnimationState::RUNNING;
257 
258     auto rsUIContext = rsUIContext_.lock();
259     for (auto& [item, nodeId] : animations_) {
260         auto animation = item.lock();
261         auto target = rsUIContext ? rsUIContext->GetNodeMap().GetNode<RSNode>(nodeId) :
262             RSNodeMap::Instance().GetNode<RSNode>(nodeId);
263         if (target != nullptr && animation != nullptr) {
264             animation->InteractiveContinue();
265         }
266     }
267 
268     auto transactionProxy = RSTransactionProxy::GetInstance();
269     if (transactionProxy == nullptr) {
270         ROSEN_LOGE("RSTransactionProxy is nullptr");
271         return;
272     }
273     std::unique_ptr<RSCommand> command = std::make_unique<RSInteractiveAnimatorContinue>(id_);
274     AddCommand(command, IsUniRenderEnabled());
275     if (!IsUniRenderEnabled()) {
276         std::unique_ptr<RSCommand> commandForRemote = std::make_unique<RSInteractiveAnimatorContinue>(id_);
277         AddCommand(commandForRemote, true);
278     }
279 }
280 
FinishAnimation(RSInteractiveAnimationPosition position)281 void RSInteractiveImplictAnimator::FinishAnimation(RSInteractiveAnimationPosition position)
282 {
283     if (state_ != RSInteractiveAnimationState::RUNNING && state_ != RSInteractiveAnimationState::PAUSED) {
284         ROSEN_LOGE("FinishAnimation failed, state_ is error");
285         return;
286     }
287     state_ = RSInteractiveAnimationState::INACTIVE;
288 
289     auto rsUIContext = rsUIContext_.lock();
290     if (position == RSInteractiveAnimationPosition::START || position == RSInteractiveAnimationPosition::END) {
291         for (auto& [item, nodeId] : animations_) {
292             auto animation = item.lock();
293             auto target = rsUIContext ? rsUIContext->GetNodeMap().GetNode<RSNode>(nodeId) :
294                 RSNodeMap::Instance().GetNode<RSNode>(nodeId);
295             if (target == nullptr || animation == nullptr) {
296                 continue;
297             }
298             animation->InteractiveFinish(position);
299         }
300         auto transactionProxy = RSTransactionProxy::GetInstance();
301         if (transactionProxy == nullptr) {
302             ROSEN_LOGE("RSTransactionProxy is nullptr");
303             return;
304         }
305         std::unique_ptr<RSCommand> command = std::make_unique<RSInteractiveAnimatorFinish>(id_, position);
306         AddCommand(command, IsUniRenderEnabled());
307         if (!IsUniRenderEnabled()) {
308             std::unique_ptr<RSCommand> commandForRemote =
309                 std::make_unique<RSInteractiveAnimatorFinish>(id_, position);
310             AddCommand(commandForRemote, true);
311         }
312     } else if (position == RSInteractiveAnimationPosition::CURRENT) {
313         FinishOnCurrent();
314     }
315 }
316 
FinishOnCurrent()317 void RSInteractiveImplictAnimator::FinishOnCurrent()
318 {
319     auto rsUIContext = rsUIContext_.lock();
320     RSNodeGetShowingPropertiesAndCancelAnimation::PropertiesMap propertiesMap;
321     for (auto& [item, nodeId] : animations_) {
322         auto animation = item.lock();
323         auto node = rsUIContext ? rsUIContext->GetNodeMap().GetNode<RSNode>(nodeId) :
324             RSNodeMap::Instance().GetNode<RSNode>(nodeId);
325         if (node == nullptr || animation == nullptr) {
326             continue;
327         }
328         if (!node->HasPropertyAnimation(animation->GetPropertyId()) || animation->IsUiAnimation()) {
329             continue;
330         }
331         propertiesMap.emplace(std::make_pair<NodeId, PropertyId>(node->GetId(), animation->GetPropertyId()),
332             std::make_pair<std::shared_ptr<RSRenderPropertyBase>, std::vector<AnimationId>>(
333                 nullptr, {animation->GetId()}));
334     }
335     if (propertiesMap.size() == 0) {
336         return;
337     }
338     auto task = std::make_shared<RSNodeGetShowingPropertiesAndCancelAnimation>(1e8, std::move(propertiesMap));
339     RSTransactionProxy::GetInstance()->ExecuteSynchronousTask(task, IsUniRenderEnabled());
340     if (!task || !task->IsSuccess()) {
341         return;
342     }
343     for (const auto& [key, value] : task->GetProperties()) {
344         const auto& [nodeId, propertyId] = key;
345         auto node = rsUIContext ? rsUIContext->GetNodeMap().GetNode<RSNode>(nodeId) :
346             RSNodeMap::Instance().GetNode<RSNode>(nodeId);
347         if (node == nullptr) {
348             continue;
349         }
350         auto modifier = node->GetModifier(propertyId);
351         if (modifier == nullptr) {
352             continue;
353         }
354         auto property = modifier->GetProperty();
355         if (property == nullptr) {
356             continue;
357         }
358         const auto& [propertyValue, animations] = value;
359         if (propertyValue != nullptr) {
360             property->SetValueFromRender(propertyValue);
361         }
362     }
363 }
364 
ReverseAnimation()365 void RSInteractiveImplictAnimator::ReverseAnimation()
366 {
367     if (state_ != RSInteractiveAnimationState::PAUSED) {
368         ROSEN_LOGE("ReverseAnimation failed, state_ is error");
369         return;
370     }
371 
372     state_ = RSInteractiveAnimationState::RUNNING;
373 
374     auto rsUIContext = rsUIContext_.lock();
375     for (auto& [item, nodeId] : animations_) {
376         auto animation = item.lock();
377         auto target = rsUIContext ? rsUIContext->GetNodeMap().GetNode<RSNode>(nodeId) :
378             RSNodeMap::Instance().GetNode<RSNode>(nodeId);
379         if (target != nullptr && animation != nullptr) {
380             animation->InteractiveReverse();
381         }
382     }
383 
384     auto transactionProxy = RSTransactionProxy::GetInstance();
385     if (transactionProxy == nullptr) {
386         ROSEN_LOGE("RSTransactionProxy is nullptr");
387         return;
388     }
389     std::unique_ptr<RSCommand> command = std::make_unique<RSInteractiveAnimatorReverse>(id_);
390     AddCommand(command, IsUniRenderEnabled());
391     if (!IsUniRenderEnabled()) {
392         std::unique_ptr<RSCommand> commandForRemote = std::make_unique<RSInteractiveAnimatorReverse>(id_);
393         AddCommand(commandForRemote, true);
394     }
395 }
396 
SetFraction(float fraction)397 void RSInteractiveImplictAnimator::SetFraction(float fraction)
398 {
399     if (state_ != RSInteractiveAnimationState::PAUSED) {
400         ROSEN_LOGE("SetFraction failed, state_ is error");
401         return;
402     }
403 
404     auto rsUIContext = rsUIContext_.lock();
405     for (auto& [item, nodeId] : animations_) {
406         auto animation = item.lock();
407         auto target = rsUIContext ? rsUIContext->GetNodeMap().GetNode<RSNode>(nodeId) :
408             RSNodeMap::Instance().GetNode<RSNode>(nodeId);
409         if (target != nullptr && animation != nullptr) {
410             animation->InteractiveSetFraction(fraction);
411         }
412     }
413 
414     auto transactionProxy = RSTransactionProxy::GetInstance();
415     if (transactionProxy == nullptr) {
416         ROSEN_LOGE("RSTransactionProxy is nullptr");
417         return;
418     }
419     std::unique_ptr<RSCommand> command = std::make_unique<RSInteractiveAnimatorSetFraction>(id_, fraction);
420     AddCommand(command, IsUniRenderEnabled());
421     if (!IsUniRenderEnabled()) {
422         std::unique_ptr<RSCommand> commandForRemote =
423             std::make_unique<RSInteractiveAnimatorSetFraction>(id_, fraction);
424         AddCommand(commandForRemote, true);
425     }
426 }
427 
GetFraction()428 float RSInteractiveImplictAnimator::GetFraction()
429 {
430     if (state_ != RSInteractiveAnimationState::PAUSED) {
431         ROSEN_LOGE("GetFraction failed, state_ is error");
432         return 0.0f;
433     }
434     if (fractionAnimationId_ == 0 || fractionNodeId_ == 0) {
435         ROSEN_LOGE("GetFraction failed, id is error");
436         return 0.0f;
437     }
438     auto task = std::make_shared<RSNodeGetAnimationsValueFraction>(1e8, fractionNodeId_, fractionAnimationId_);
439     RSTransactionProxy::GetInstance()->ExecuteSynchronousTask(task, IsUniRenderEnabled());
440 
441     if (!task || !task->IsSuccess()) {
442         ROSEN_LOGE("RSInteractiveImplictAnimator::ExecuteSyncGetFractionTask failed to execute task.");
443         return 0.0f;
444     }
445     return task->GetFraction();
446 }
447 
SetFinishCallBack(const std::function<void ()> & finishCallback)448 void RSInteractiveImplictAnimator::SetFinishCallBack(const std::function<void()>& finishCallback)
449 {
450     finishCallback_ = finishCallback;
451 }
452 
CallFinishCallback()453 void RSInteractiveImplictAnimator::CallFinishCallback()
454 {
455     animations_.clear();
456     fractionAnimationId_ = 0;
457     fractionNodeId_ = 0;
458     if (finishCallback_) {
459         finishCallback_();
460     }
461 }
462 
AddCommand(std::unique_ptr<RSCommand> & command,bool isRenderServiceCommand,FollowType followType,NodeId nodeId) const463 void RSInteractiveImplictAnimator::AddCommand(
464     std::unique_ptr<RSCommand>& command, bool isRenderServiceCommand, FollowType followType, NodeId nodeId) const
465 {
466     if (rsUIContext_.lock() != nullptr) {
467         auto rsTransaction = rsUIContext_.lock()->GetRSTransaction();
468         if (rsTransaction == nullptr) {
469             RS_LOGE("multi-instance: RSInteractiveImplictAnimator::AddCommand, transaction is nullptr");
470             return;
471         }
472         rsTransaction->AddCommand(command, isRenderServiceCommand, followType, nodeId);
473     } else {
474         auto transactionProxy = RSTransactionProxy::GetInstance();
475         if (transactionProxy == nullptr) {
476             RS_LOGE("RSInteractiveImplictAnimator::AddCommand transactionProxy is nullptr");
477             return;
478         }
479         transactionProxy->AddCommand(command, isRenderServiceCommand, followType, nodeId);
480     }
481 }
482 } // namespace Rosen
483 } // namespace OHOS
484