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_manager.h"
17
18 #include <algorithm>
19 #include <string>
20
21 #include "animation/rs_animation_trace_utils.h"
22 #include "animation/rs_render_animation.h"
23 #include "command/rs_animation_command.h"
24 #include "command/rs_message_processor.h"
25 #include "common/rs_optional_trace.h"
26 #include "pipeline/rs_dirty_region_manager.h"
27 #include "pipeline/rs_paint_filter_canvas.h"
28 #include "pipeline/rs_render_node.h"
29 #include "platform/common/rs_log.h"
30 #include "rs_trace.h"
31
32 namespace OHOS {
33 namespace Rosen {
34 class RSRootRenderNode;
35
DumpAnimations(std::string & out) const36 void RSAnimationManager::DumpAnimations(std::string& out) const
37 {
38 RS_TRACE_NAME_FMT("DumpAnimations, size: %zu", animations_.size());
39 if (animations_.empty()) {
40 return;
41 }
42 const auto lengthTwo = 2;
43 out.append(", RSAnimationManager: [");
44 for (auto[id, animation]: animations_) {
45 animation->DumpAnimation(out);
46 out.append(", ");
47 }
48 out.erase(out.end() - lengthTwo, out.end());
49 out.append("]");
50 }
51
AddAnimation(const std::shared_ptr<RSRenderAnimation> & animation)52 void RSAnimationManager::AddAnimation(const std::shared_ptr<RSRenderAnimation>& animation)
53 {
54 if (animation == nullptr) {
55 ROSEN_LOGE("RSAnimationManager::AddAnimation, The animation is nullptr");
56 return;
57 }
58 AnimationId key = animation->GetAnimationId();
59 if (animations_.find(key) != animations_.end()) {
60 ROSEN_LOGE("RSAnimationManager::AddAnimation, The animation already exists when is added");
61 return;
62 }
63 auto it = std::find(pendingCancelAnimation_.begin(), pendingCancelAnimation_.end(), key);
64 if (it != pendingCancelAnimation_.end()) {
65 pendingCancelAnimation_.erase(it);
66 ROSEN_LOGE("RSAnimationManager::AddAnimation, animation is a pendingCancelAnimation");
67 return;
68 }
69 animations_.emplace(key, animation);
70 }
71
RemoveAnimation(AnimationId keyId)72 void RSAnimationManager::RemoveAnimation(AnimationId keyId)
73 {
74 auto animationItr = animations_.find(keyId);
75 if (animationItr == animations_.end()) {
76 ROSEN_LOGE("RSAnimationManager::RemoveAnimation, The Animation does not exist when is deleted");
77 return;
78 }
79 animationItr->second->Finish();
80 animationItr->second->Detach();
81 animations_.erase(animationItr);
82 }
83
CancelAnimationByPropertyId(PropertyId id)84 void RSAnimationManager::CancelAnimationByPropertyId(PropertyId id)
85 {
86 EraseIf(animations_, [id, this](const auto& pair) {
87 if (pair.second && (pair.second->GetPropertyId() == id)) {
88 OnAnimationFinished(pair.second);
89 return true;
90 }
91 return false;
92 });
93 }
94
AttemptCancelAnimationByAnimationId(const std::vector<AnimationId> & animations)95 void RSAnimationManager::AttemptCancelAnimationByAnimationId(const std::vector<AnimationId>& animations)
96 {
97 for (auto& animationId : animations) {
98 bool isErased = EraseIf(animations_, [animationId, this](const auto& pair) {
99 if (pair.second && (pair.first == animationId)) {
100 OnAnimationFinished(pair.second);
101 return true;
102 }
103 return false;
104 });
105 if (!isErased) {
106 pendingCancelAnimation_.emplace_back(animationId);
107 }
108 }
109 }
110
FilterAnimationByPid(pid_t pid)111 void RSAnimationManager::FilterAnimationByPid(pid_t pid)
112 {
113 ROSEN_LOGD("RSAnimationManager::FilterAnimationByPid removing all animations belong to pid %{public}llu",
114 (unsigned long long)pid);
115 // remove all animations belong to given pid (by matching higher 32 bits of animation id)
116 EraseIf(animations_, [pid, this](const auto& pair) -> bool {
117 if (ExtractPid(pair.first) != pid) {
118 return false;
119 }
120 if (!pair.second) {
121 return false;
122 }
123 pair.second->Finish();
124 pair.second->Detach();
125 return true;
126 });
127 }
128
GetAnimationsSize()129 uint32_t RSAnimationManager::GetAnimationsSize()
130 {
131 return animations_.size();
132 }
133
GetAnimationPid() const134 pid_t RSAnimationManager::GetAnimationPid() const
135 {
136 if (animations_.size() > 0) {
137 // shift right 32-bit numbers to get pid
138 return animations_.begin()->first >> 32;
139 }
140 return 0;
141 }
142
Animate(int64_t time,int64_t & minLeftDelayTime,bool nodeIsOnTheTree,RSSurfaceNodeAbilityState abilityState)143 std::tuple<bool, bool, bool> RSAnimationManager::Animate(
144 int64_t time, int64_t& minLeftDelayTime, bool nodeIsOnTheTree, RSSurfaceNodeAbilityState abilityState)
145 {
146 // process animation
147 bool hasRunningAnimation = false;
148 bool needRequestNextVsync = false;
149 // isCalculateAnimationValue is embedded modify for stat animate frame drop
150 bool isCalculateAnimationValue = false;
151 rsRange_.Reset();
152 rateDecider_.Reset();
153 // iterate and execute all animations, remove finished animations
154 EraseIf(animations_, [this, &hasRunningAnimation, time, &needRequestNextVsync, nodeIsOnTheTree,
155 &isCalculateAnimationValue, abilityState, &minLeftDelayTime](auto& iter) -> bool {
156 auto& animation = iter.second;
157 // infinite iteration animation out of the tree or in the background does not request vsync
158 if ((!nodeIsOnTheTree || abilityState == RSSurfaceNodeAbilityState::BACKGROUND) &&
159 animation->GetRepeatCount() == -1) {
160 hasRunningAnimation = animation->IsRunning() || hasRunningAnimation;
161 return false;
162 }
163 // finite iteration animation in the background finished immediately
164 if (abilityState == RSSurfaceNodeAbilityState::BACKGROUND) {
165 RSAnimationTraceUtils::GetInstance().AddAnimationFinishTrace(
166 "Animation finish background", animation->GetTargetId(), animation->GetAnimationId(), false);
167 animation->Finish();
168 }
169 bool isFinished = animation->Animate(time, minLeftDelayTime);
170 if (isFinished) {
171 isCalculateAnimationValue = true;
172 OnAnimationFinished(animation);
173 } else {
174 hasRunningAnimation = animation->IsRunning() || hasRunningAnimation;
175 needRequestNextVsync = animation->IsRunning() || needRequestNextVsync;
176 isCalculateAnimationValue = animation->IsCalculateAniamtionValue() || isCalculateAnimationValue;
177
178 auto range = animation->GetFrameRateRange();
179 if (range.IsValid()) {
180 rsRange_.Merge(range);
181 }
182 RS_OPTIONAL_TRACE_BEGIN("AddDecisionElement property id: [" + std::to_string(animation->GetPropertyId()) +
183 "], animation id: [" + std::to_string(animation->GetAnimationId()) + "]");
184 rateDecider_.AddDecisionElement(animation->GetPropertyId(), animation->GetAnimateVelocity(), range);
185 RS_OPTIONAL_TRACE_END();
186 }
187 return isFinished;
188 });
189 rateDecider_.MakeDecision(frameRateGetFunc_);
190 isCalculateAnimationValue = isCalculateAnimationValue && nodeIsOnTheTree;
191
192 return { hasRunningAnimation, needRequestNextVsync, isCalculateAnimationValue };
193 }
194
SetRateDeciderEnable(bool enabled,const FrameRateGetFunc & func)195 void RSAnimationManager::SetRateDeciderEnable(bool enabled, const FrameRateGetFunc& func)
196 {
197 rateDecider_.SetEnable(enabled);
198 frameRateGetFunc_ = func;
199 }
200
SetRateDeciderSize(float width,float height)201 void RSAnimationManager::SetRateDeciderSize(float width, float height)
202 {
203 rateDecider_.SetNodeSize(width, height);
204 }
205
SetRateDeciderScale(float scaleX,float scaleY)206 void RSAnimationManager::SetRateDeciderScale(float scaleX, float scaleY)
207 {
208 rateDecider_.SetNodeScale(scaleX, scaleY);
209 }
210
SetRateDeciderAbsRect(int32_t width,int32_t height)211 void RSAnimationManager::SetRateDeciderAbsRect(int32_t width, int32_t height)
212 {
213 rateDecider_.SetAbsRect(width, height);
214 }
215
GetDecideFrameRateRange() const216 const FrameRateRange& RSAnimationManager::GetDecideFrameRateRange() const
217 {
218 return rateDecider_.GetFrameRateRange();
219 }
220
GetFrameRateRange() const221 const FrameRateRange& RSAnimationManager::GetFrameRateRange() const
222 {
223 return rsRange_;
224 }
225
GetAnimation(AnimationId id) const226 const std::shared_ptr<RSRenderAnimation> RSAnimationManager::GetAnimation(AnimationId id) const
227 {
228 auto animationItr = animations_.find(id);
229 if (animationItr == animations_.end()) {
230 ROSEN_LOGD("RSAnimationManager::GetAnimation, animation [%{public}" PRIu64 "] not found", id);
231 return nullptr;
232 }
233 return animationItr->second;
234 }
235
OnAnimationFinished(const std::shared_ptr<RSRenderAnimation> & animation)236 void RSAnimationManager::OnAnimationFinished(const std::shared_ptr<RSRenderAnimation>& animation)
237 {
238 NodeId targetId = animation->GetTargetId();
239 AnimationId animationId = animation->GetAnimationId();
240 uint64_t token = animation->GetToken();
241
242 RSAnimationTraceUtils::GetInstance().AddAnimationFinishTrace(
243 "Animation Send Finish", targetId, animationId, false);
244 std::unique_ptr<RSCommand> command =
245 std::make_unique<RSAnimationCallback>(targetId, animationId, token, FINISHED);
246 RSMessageProcessor::Instance().AddUIMessage(ExtractPid(animationId), command);
247 animation->Detach();
248 }
249
RegisterSpringAnimation(PropertyId propertyId,AnimationId animId)250 void RSAnimationManager::RegisterSpringAnimation(PropertyId propertyId, AnimationId animId)
251 {
252 springAnimations_[propertyId] = animId;
253 }
254
UnregisterSpringAnimation(PropertyId propertyId,AnimationId animId)255 void RSAnimationManager::UnregisterSpringAnimation(PropertyId propertyId, AnimationId animId)
256 {
257 auto it = springAnimations_.find(propertyId);
258 if (it != springAnimations_.end() && it->second == animId) {
259 springAnimations_.erase(it);
260 }
261 }
262
QuerySpringAnimation(PropertyId propertyId)263 std::shared_ptr<RSRenderAnimation> RSAnimationManager::QuerySpringAnimation(PropertyId propertyId)
264 {
265 auto it = springAnimations_.find(propertyId);
266 if (it == springAnimations_.end() || it->second == 0) {
267 return nullptr;
268 }
269 return GetAnimation(it->second);
270 }
271
RegisterPathAnimation(PropertyId propertyId,AnimationId animId)272 void RSAnimationManager::RegisterPathAnimation(PropertyId propertyId, AnimationId animId)
273 {
274 pathAnimations_[propertyId] = animId;
275 }
276
UnregisterPathAnimation(PropertyId propertyId,AnimationId animId)277 void RSAnimationManager::UnregisterPathAnimation(PropertyId propertyId, AnimationId animId)
278 {
279 auto it = pathAnimations_.find(propertyId);
280 if (it != pathAnimations_.end() && it->second == animId) {
281 pathAnimations_.erase(it);
282 }
283 }
284
QueryPathAnimation(PropertyId propertyId)285 std::shared_ptr<RSRenderAnimation> RSAnimationManager::QueryPathAnimation(PropertyId propertyId)
286 {
287 auto it = pathAnimations_.find(propertyId);
288 if (it == pathAnimations_.end() || it->second == 0) {
289 return nullptr;
290 }
291 return GetAnimation(it->second);
292 }
293
RegisterParticleAnimation(PropertyId propertyId,AnimationId animId)294 void RSAnimationManager::RegisterParticleAnimation(PropertyId propertyId, AnimationId animId)
295 {
296 particleAnimations_[propertyId] = animId;
297 }
298
UnregisterParticleAnimation(PropertyId propertyId,AnimationId animId)299 void RSAnimationManager::UnregisterParticleAnimation(PropertyId propertyId, AnimationId animId)
300 {
301 auto it = particleAnimations_.find(propertyId);
302 if (it != particleAnimations_.end() && it->second == animId) {
303 particleAnimations_.erase(it);
304 }
305 }
306
GetParticleAnimations()307 const std::unordered_map<PropertyId, AnimationId>& RSAnimationManager::GetParticleAnimations()
308 {
309 return particleAnimations_;
310 }
311
GetParticleAnimation()312 std::shared_ptr<RSRenderAnimation> RSAnimationManager::GetParticleAnimation()
313 {
314 if (particleAnimations_.empty()) {
315 return nullptr;
316 }
317 return GetAnimation(particleAnimations_.begin()->second);
318 }
319 } // namespace Rosen
320 } // namespace OHOS
321