1 /*
2  * Copyright (c) 2023-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 "light_lux_buffer.h"
17 
18 #include <cerrno>
19 #include <cstdlib>
20 #include <new>
21 #include <string>
22 #include <securec.h>
23 #include <securectype.h>
24 
25 #include "display_log.h"
26 
27 namespace OHOS {
28 namespace DisplayPowerMgr {
29 
30 namespace {
31 const unsigned int BUFFER_SIZE_INCREASE = 2;
32 const unsigned int LUX_BUFFER_SIZE_MAX = 512;
33 }
34 
LightLuxBuffer(unsigned int initialCapacity)35 LightLuxBuffer::LightLuxBuffer(unsigned int initialCapacity)
36 {
37     if (initialCapacity == 0 || initialCapacity >= LUX_BUFFER_SIZE_MAX) {
38         DISPLAY_HILOGE(FEAT_BRIGHTNESS, "initialCapacity=%{public}d out of range, Reset to %{public}d",
39             initialCapacity, LUX_BUFFER_SIZE_DEFAULT);
40         mCapacity = LUX_BUFFER_SIZE_DEFAULT;
41     } else {
42         mCapacity = initialCapacity;
43     }
44 }
45 
~LightLuxBuffer()46 LightLuxBuffer::~LightLuxBuffer()
47 {
48     if (mBufferData != nullptr) {
49         delete[] mBufferData;
50         mBufferData = nullptr;
51     }
52 
53     if (mBufferTime != nullptr) {
54         delete[] mBufferTime;
55         mBufferTime = nullptr;
56     }
57 }
58 
LuxBufferCheck()59 int LightLuxBuffer::LuxBufferCheck()
60 {
61     if (mBufferData == nullptr) {
62         mBufferData = new(std::nothrow) float[mCapacity];
63         if (mBufferData == nullptr) {
64             DISPLAY_HILOGE(FEAT_BRIGHTNESS, "new mBufferData failed!");
65             return -1;
66         }
67     }
68     if (mBufferTime == nullptr) {
69         mBufferTime = new(std::nothrow) int64_t[mCapacity];
70         if (mBufferTime == nullptr) {
71             DISPLAY_HILOGE(FEAT_BRIGHTNESS, "new mBufferTime failed!");
72             delete[] mBufferData;
73             mBufferData = nullptr;
74             return -1;
75         }
76     }
77     return 0;
78 }
79 
CopyLuxBuffer(int newSize)80 int LightLuxBuffer::CopyLuxBuffer(int newSize)
81 {
82     auto newBufferData = new(std::nothrow) float[newSize];
83     if (newBufferData == nullptr) {
84         DISPLAY_HILOGE(FEAT_BRIGHTNESS, "newBufferData id null");
85         return -1;
86     }
87     auto newBufferTime = new(std::nothrow) int64_t[newSize];
88     if (newBufferTime == nullptr) {
89         DISPLAY_HILOGE(FEAT_BRIGHTNESS, "newBufferTime id null");
90         delete[] newBufferData;
91         return -1;
92     }
93     unsigned int length = mCapacity - mStart;
94     bool isError = false;
95     isError = isError || (memcpy_s(newBufferData, newSize * sizeof(newBufferData[0]),
96         mBufferData + mStart, length * sizeof(mBufferData[0])) != EOK);
97     isError = isError || (memcpy_s(newBufferTime, newSize * sizeof(newBufferTime[0]),
98         mBufferTime + mStart, length * sizeof(mBufferTime[0])) != EOK);
99     if (mStart != 0) {
100         isError = isError || (memcpy_s(newBufferData + length, (newSize - length) * sizeof(newBufferData[0]),
101             mBufferData, mStart * sizeof(mBufferData[0])) != EOK);
102         isError = isError || (memcpy_s(newBufferTime + length, (newSize - length) * sizeof(newBufferTime[0]),
103             mBufferTime, mStart * sizeof(mBufferTime[0])) != EOK);
104     }
105     if (isError) {
106         DISPLAY_HILOGE(FEAT_BRIGHTNESS, "memcpy_s error, mCapacity=%{public}d, mStart=%{public}d", mCapacity, mStart);
107         delete[] newBufferData;
108         delete[] newBufferTime;
109         return -1;
110     }
111     delete[] mBufferData;
112     mBufferData = newBufferData;
113     delete[] mBufferTime;
114     mBufferTime = newBufferTime;
115 
116     return 0;
117 }
118 
Push(const int64_t timestamp,const float data)119 void LightLuxBuffer::Push(const int64_t timestamp, const float data)
120 {
121     if (LuxBufferCheck() != 0) {
122         return;
123     }
124 
125     unsigned int next = mEnd;
126     if (mCount == mCapacity) {
127         unsigned long newSize = mCapacity * static_cast<unsigned long>(BUFFER_SIZE_INCREASE);
128         if (newSize > static_cast<unsigned long>(LUX_BUFFER_SIZE_MAX)) {
129             DISPLAY_HILOGW(FEAT_BRIGHTNESS, "buffer size larger than max value %{public}d already, stop expand",
130                 LUX_BUFFER_SIZE_MAX);
131             return;
132         }
133         if (mStart >= mCapacity) {
134             DISPLAY_HILOGE(FEAT_BRIGHTNESS, "mStart error! mStart(%{public}d) >= mCapacity(%{public}d)",
135                 mStart, mCapacity);
136             return;
137         }
138 
139         if (CopyLuxBuffer(newSize) != 0) {
140             return;
141         }
142 
143         next = mCapacity;
144         mCapacity = static_cast<unsigned int>(newSize);
145         mStart = 0;
146     }
147 
148     if (mBufferTime != nullptr) {
149         mBufferTime[next] = timestamp;
150     }
151 
152     if (mBufferData != nullptr) {
153         mBufferData[next] = data;
154     }
155 
156     mEnd = next + 1;
157     if (mEnd == mCapacity) {
158         mEnd = 0;
159     }
160     mCount++;
161 }
162 
Prune(const int64_t horizon)163 void LightLuxBuffer::Prune(const int64_t horizon)
164 {
165     if (mCount == 0 || mBufferTime == nullptr) {
166         return;
167     }
168 
169     while (mCount > 1) {
170         unsigned int next = mStart + 1;
171         if (next >= mCapacity) {
172             next -= mCapacity;
173         }
174         if (mBufferTime[next] > horizon) {
175             break;
176         }
177         mStart = next;
178         mCount--;
179     }
180     if (mBufferTime[mStart] < horizon) {
181         mBufferTime[mStart] = horizon;
182     }
183 }
184 
Clear()185 void LightLuxBuffer::Clear()
186 {
187     mStart = 0;
188     mEnd = 0;
189     mCount = 0;
190 }
191 
GetData(const unsigned int index) const192 float LightLuxBuffer::GetData(const unsigned int index) const
193 {
194     if (mBufferData == nullptr) {
195         DISPLAY_HILOGE(FEAT_BRIGHTNESS, "mBufferData is nullptr.");
196         return 0;
197     }
198     if (index >= mCount) {
199         DISPLAY_HILOGE(FEAT_BRIGHTNESS, "error! index = %{public}d, out of range mCount = %{public}d", index, mCount);
200         return 0;
201     }
202     return mBufferData[OffsetOf(index)];
203 }
204 
GetTime(const unsigned int index) const205 int64_t LightLuxBuffer::GetTime(const unsigned int index) const
206 {
207     if (mBufferTime == nullptr) {
208         DISPLAY_HILOGE(FEAT_BRIGHTNESS, "mBufferTime is nullptr");
209         return 0;
210     }
211 
212     if (index >= mCount) {
213         DISPLAY_HILOGE(FEAT_BRIGHTNESS, "error! index = %{public}d, out of range mCount = %{public}d", index, mCount);
214         return 0;
215     }
216     return mBufferTime[OffsetOf(index)];
217 }
218 
GetSize() const219 unsigned int LightLuxBuffer::GetSize() const
220 {
221     return mCount;
222 }
223 
OffsetOf(const unsigned int index) const224 unsigned int LightLuxBuffer::OffsetOf(const unsigned int index) const
225 {
226     unsigned actualIndex = index + mStart;
227     if (actualIndex >= mCapacity) {
228         actualIndex -= mCapacity;
229     }
230     return actualIndex;
231 }
232 
ToString(unsigned int n)233 std::string LightLuxBuffer::ToString(unsigned int n)
234 {
235     std::ostringstream result;
236     if (n > mCount) {
237         n = mCount;
238     }
239     result << "[";
240     for (unsigned int i = mCount-n; i>=0 && i < mCount;i++) {
241         result << GetData(i);
242         result << "/";
243         result << GetTime(i);
244         result << ", ";
245     }
246     result << "]";
247     return result.str();
248 }
249 } // namespace DisplayPowerMgr
250 } // namespace OHOS