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_interpolator.h"
17
18 #include <algorithm>
19 #include <cmath>
20
21 #include "sandbox_utils.h"
22
23 #include "animation/rs_animation_common.h"
24 #include "animation/rs_cubic_bezier_interpolator.h"
25 #include "animation/rs_spring_interpolator.h"
26 #include "animation/rs_steps_interpolator.h"
27 #include "platform/common/rs_log.h"
28
29 namespace OHOS {
30 namespace Rosen {
31 static pid_t pid_ = GetRealPid();
32
33 const std::shared_ptr<RSInterpolator> RSInterpolator::DEFAULT =
34 std::make_shared<RSCubicBezierInterpolator>(0.42f, 0.0f, 0.58f, 1.0f);
35
RSInterpolator()36 RSInterpolator::RSInterpolator() : id_(GenerateId()) {}
37
Init()38 void RSInterpolator::Init()
39 {
40 pid_ = GetRealPid();
41 }
42
GenerateId()43 uint64_t RSInterpolator::GenerateId()
44 {
45 if (pid_ == 0) {
46 pid_ = GetRealPid();
47 }
48 static std::atomic<uint32_t> currentId_ = 0;
49
50 auto currentId = currentId_.fetch_add(1, std::memory_order_relaxed);
51 if (currentId == UINT32_MAX) {
52 ROSEN_LOGE("RSInterpolator Id overflow");
53 }
54
55 // concat two 32-bit numbers to one 64-bit number
56 return ((AnimationId)pid_ << 32) | (currentId);
57 }
58
Interpolate(float input)59 float RSInterpolator::Interpolate(float input)
60 {
61 if (input == prevInput_) {
62 return prevOutput_;
63 }
64 prevInput_ = input;
65 prevOutput_ = InterpolateImpl(input);
66 return prevOutput_;
67 }
68
Unmarshalling(Parcel & parcel)69 std::shared_ptr<RSInterpolator> RSInterpolator::Unmarshalling(Parcel& parcel)
70 {
71 uint16_t interpolatorType = 0;
72 if (!parcel.ReadUint16(interpolatorType)) {
73 ROSEN_LOGE("RSInterpolator::Unmarshalling read type failed");
74 return nullptr;
75 }
76 RSInterpolator* ret = nullptr;
77 switch (interpolatorType) {
78 case InterpolatorType::LINEAR:
79 ret = LinearInterpolator::Unmarshalling(parcel);
80 break;
81 case InterpolatorType::CUSTOM:
82 ret = RSCustomInterpolator::Unmarshalling(parcel);
83 break;
84 case InterpolatorType::CUBIC_BEZIER:
85 ret = RSCubicBezierInterpolator::Unmarshalling(parcel);
86 break;
87 case InterpolatorType::SPRING:
88 ret = RSSpringInterpolator::Unmarshalling(parcel);
89 break;
90 case InterpolatorType::STEPS:
91 ret = RSStepsInterpolator::Unmarshalling(parcel);
92 break;
93 default:
94 break;
95 }
96 if (ret == nullptr) {
97 return nullptr;
98 }
99
100 static std::mutex cachedInterpolatorsMutex_;
101 static std::unordered_map<uint64_t, std::weak_ptr<RSInterpolator>> cachedInterpolators_;
102 static const auto Destructor = [](RSInterpolator* ptr) {
103 if (ptr == nullptr) {
104 ROSEN_LOGE("RSInterpolator::Unmarshalling, sharePtr is nullptr.");
105 return;
106 }
107 std::unique_lock<std::mutex> lock(cachedInterpolatorsMutex_);
108 cachedInterpolators_.erase(ptr->id_); // Unregister interpolator from cache before destruction.
109 delete ptr;
110 ptr = nullptr;
111 };
112
113 {
114 // All cache operations should be performed under lock to prevent race conditions
115 std::unique_lock<std::mutex> lock(cachedInterpolatorsMutex_);
116 // Check if there is an existing valid interpolator in the cache, return it if found.
117 if (auto it = cachedInterpolators_.find(ret->id_); it != cachedInterpolators_.end()) {
118 if (auto sharedPtr = it->second.lock()) { // Check if weak pointer is valid
119 delete ret; // Destroy the newly created object
120 return sharedPtr;
121 } else { // If the weak pointer has expired, erase it from the cache. This should never happen.
122 ROSEN_LOGE("RSInterpolator::Unmarshalling, cached weak pointer expired.");
123 cachedInterpolators_.erase(it);
124 }
125 }
126 // No existing interpolator in the cache, create a new one and register it in the cache.
127 std::shared_ptr<RSInterpolator> sharedPtr(ret, Destructor);
128 cachedInterpolators_.emplace(ret->id_, sharedPtr);
129 return sharedPtr;
130 }
131 }
132
Marshalling(Parcel & parcel) const133 bool LinearInterpolator::Marshalling(Parcel& parcel) const
134 {
135 if (!parcel.WriteUint16(InterpolatorType::LINEAR)) {
136 return false;
137 }
138 if (!parcel.WriteUint64(id_)) {
139 return false;
140 }
141 return true;
142 }
143
Unmarshalling(Parcel & parcel)144 LinearInterpolator* LinearInterpolator::Unmarshalling(Parcel& parcel)
145 {
146 uint64_t id = parcel.ReadUint64();
147 if (id == 0) {
148 ROSEN_LOGE("Unmarshalling LinearInterpolator failed");
149 return nullptr;
150 }
151 return new LinearInterpolator(id);
152 }
153
RSCustomInterpolator(uint64_t id,const std::vector<float> && times,const std::vector<float> && values)154 RSCustomInterpolator::RSCustomInterpolator(
155 uint64_t id, const std::vector<float>&& times, const std::vector<float>&& values)
156 : RSInterpolator(id), times_(times), values_(values)
157 {}
158
RSCustomInterpolator(const std::function<float (float)> & func,int duration)159 RSCustomInterpolator::RSCustomInterpolator(const std::function<float(float)>& func, int duration)
160 : interpolateFunc_(func)
161 {
162 Convert(duration);
163 }
164
Marshalling(Parcel & parcel) const165 bool RSCustomInterpolator::Marshalling(Parcel& parcel) const
166 {
167 if (!parcel.WriteUint16(InterpolatorType::CUSTOM)) {
168 ROSEN_LOGE("RSCustomInterpolator::Marshalling, Write type failed");
169 return false;
170 }
171 if (!parcel.WriteUint64(id_)) {
172 ROSEN_LOGE("RSCustomInterpolator::Marshalling, Write id failed");
173 return false;
174 }
175 if (!parcel.WriteFloatVector(times_) || !parcel.WriteFloatVector(values_)) {
176 ROSEN_LOGE("RSCustomInterpolator::Marshalling, Write value failed");
177 return false;
178 }
179 return true;
180 }
181
Unmarshalling(Parcel & parcel)182 RSCustomInterpolator* RSCustomInterpolator::Unmarshalling(Parcel& parcel)
183 {
184 uint64_t id = parcel.ReadUint64();
185 std::vector<float> times, values;
186 if (!(parcel.ReadFloatVector(×) && parcel.ReadFloatVector(&values))) {
187 ROSEN_LOGE("Unmarshalling CustomInterpolator failed");
188 return nullptr;
189 }
190 return new RSCustomInterpolator(id, std::move(times), std::move(values));
191 }
192
Convert(int duration)193 void RSCustomInterpolator::Convert(int duration)
194 {
195 if (interpolateFunc_ == nullptr) {
196 ROSEN_LOGE("RSCustomInterpolator::Convert, interpolateFunc_ is nullptr");
197 return;
198 }
199 constexpr uint64_t frameInterval = 16666667;
200 int numAnim = static_cast<int>(std::ceil(static_cast<double>(duration * MS_TO_NS) / frameInterval));
201 const int maxSamplePoints = 300;
202 const int minSamplePoints = 2;
203 numAnim = std::min(std::max(minSamplePoints, numAnim), maxSamplePoints);
204 float lastAnimFrame = numAnim - 1;
205 if (lastAnimFrame <= 0.0f) {
206 ROSEN_LOGE("RSCustomInterpolator::Convert, lastAnimFrame is invalid.");
207 return;
208 }
209 for (int i = 0; i < numAnim; i++) {
210 float time = i / lastAnimFrame;
211 float value = interpolateFunc_(time);
212 times_.push_back(time);
213 values_.push_back(value);
214 }
215 }
216
InterpolateImpl(float input) const217 float RSCustomInterpolator::InterpolateImpl(float input) const
218 {
219 if (times_.size() <= 0) {
220 return 0.0f;
221 }
222 if (input < times_[0] + EPSILON) {
223 return times_[0];
224 }
225 if (input > times_[times_.size() - 1] - EPSILON) {
226 return times_[times_.size() - 1];
227 }
228 auto firstGreatValue = upper_bound(times_.begin(), times_.end(), input);
229 int endLocation = firstGreatValue - times_.begin();
230 int startLocation = endLocation - 1;
231 float number = times_[endLocation] - times_[startLocation];
232 if (number <= 0.0f) {
233 ROSEN_LOGE("RSCustomInterpolator::Interpolate, time between startLocation and endLocation is less than zero.");
234 return 0.0f;
235 }
236 float fraction = (input - times_[startLocation]) / number;
237 float ret = fraction * (values_[endLocation] - values_[startLocation]) + values_[startLocation];
238 return ret;
239 }
240 } // namespace Rosen
241 } // namespace OHOS
242