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