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(&times) && 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