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