1595d5899Sopenharmony_ci/*
2595d5899Sopenharmony_ci * Copyright (c) 2023-2023 Huawei Device Co., Ltd.
3595d5899Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4595d5899Sopenharmony_ci * you may not use this file except in compliance with the License.
5595d5899Sopenharmony_ci * You may obtain a copy of the License at
6595d5899Sopenharmony_ci *
7595d5899Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8595d5899Sopenharmony_ci *
9595d5899Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10595d5899Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11595d5899Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12595d5899Sopenharmony_ci * See the License for the specific language governing permissions and
13595d5899Sopenharmony_ci * limitations under the License.
14595d5899Sopenharmony_ci */
15595d5899Sopenharmony_ci
16595d5899Sopenharmony_ci#include "light_lux_buffer.h"
17595d5899Sopenharmony_ci
18595d5899Sopenharmony_ci#include <cerrno>
19595d5899Sopenharmony_ci#include <cstdlib>
20595d5899Sopenharmony_ci#include <new>
21595d5899Sopenharmony_ci#include <string>
22595d5899Sopenharmony_ci#include <securec.h>
23595d5899Sopenharmony_ci#include <securectype.h>
24595d5899Sopenharmony_ci
25595d5899Sopenharmony_ci#include "display_log.h"
26595d5899Sopenharmony_ci
27595d5899Sopenharmony_cinamespace OHOS {
28595d5899Sopenharmony_cinamespace DisplayPowerMgr {
29595d5899Sopenharmony_ci
30595d5899Sopenharmony_cinamespace {
31595d5899Sopenharmony_ciconst unsigned int BUFFER_SIZE_INCREASE = 2;
32595d5899Sopenharmony_ciconst unsigned int LUX_BUFFER_SIZE_MAX = 512;
33595d5899Sopenharmony_ci}
34595d5899Sopenharmony_ci
35595d5899Sopenharmony_ciLightLuxBuffer::LightLuxBuffer(unsigned int initialCapacity)
36595d5899Sopenharmony_ci{
37595d5899Sopenharmony_ci    if (initialCapacity == 0 || initialCapacity >= LUX_BUFFER_SIZE_MAX) {
38595d5899Sopenharmony_ci        DISPLAY_HILOGE(FEAT_BRIGHTNESS, "initialCapacity=%{public}d out of range, Reset to %{public}d",
39595d5899Sopenharmony_ci            initialCapacity, LUX_BUFFER_SIZE_DEFAULT);
40595d5899Sopenharmony_ci        mCapacity = LUX_BUFFER_SIZE_DEFAULT;
41595d5899Sopenharmony_ci    } else {
42595d5899Sopenharmony_ci        mCapacity = initialCapacity;
43595d5899Sopenharmony_ci    }
44595d5899Sopenharmony_ci}
45595d5899Sopenharmony_ci
46595d5899Sopenharmony_ciLightLuxBuffer::~LightLuxBuffer()
47595d5899Sopenharmony_ci{
48595d5899Sopenharmony_ci    if (mBufferData != nullptr) {
49595d5899Sopenharmony_ci        delete[] mBufferData;
50595d5899Sopenharmony_ci        mBufferData = nullptr;
51595d5899Sopenharmony_ci    }
52595d5899Sopenharmony_ci
53595d5899Sopenharmony_ci    if (mBufferTime != nullptr) {
54595d5899Sopenharmony_ci        delete[] mBufferTime;
55595d5899Sopenharmony_ci        mBufferTime = nullptr;
56595d5899Sopenharmony_ci    }
57595d5899Sopenharmony_ci}
58595d5899Sopenharmony_ci
59595d5899Sopenharmony_ciint LightLuxBuffer::LuxBufferCheck()
60595d5899Sopenharmony_ci{
61595d5899Sopenharmony_ci    if (mBufferData == nullptr) {
62595d5899Sopenharmony_ci        mBufferData = new(std::nothrow) float[mCapacity];
63595d5899Sopenharmony_ci        if (mBufferData == nullptr) {
64595d5899Sopenharmony_ci            DISPLAY_HILOGE(FEAT_BRIGHTNESS, "new mBufferData failed!");
65595d5899Sopenharmony_ci            return -1;
66595d5899Sopenharmony_ci        }
67595d5899Sopenharmony_ci    }
68595d5899Sopenharmony_ci    if (mBufferTime == nullptr) {
69595d5899Sopenharmony_ci        mBufferTime = new(std::nothrow) int64_t[mCapacity];
70595d5899Sopenharmony_ci        if (mBufferTime == nullptr) {
71595d5899Sopenharmony_ci            DISPLAY_HILOGE(FEAT_BRIGHTNESS, "new mBufferTime failed!");
72595d5899Sopenharmony_ci            delete[] mBufferData;
73595d5899Sopenharmony_ci            mBufferData = nullptr;
74595d5899Sopenharmony_ci            return -1;
75595d5899Sopenharmony_ci        }
76595d5899Sopenharmony_ci    }
77595d5899Sopenharmony_ci    return 0;
78595d5899Sopenharmony_ci}
79595d5899Sopenharmony_ci
80595d5899Sopenharmony_ciint LightLuxBuffer::CopyLuxBuffer(int newSize)
81595d5899Sopenharmony_ci{
82595d5899Sopenharmony_ci    auto newBufferData = new(std::nothrow) float[newSize];
83595d5899Sopenharmony_ci    if (newBufferData == nullptr) {
84595d5899Sopenharmony_ci        DISPLAY_HILOGE(FEAT_BRIGHTNESS, "newBufferData id null");
85595d5899Sopenharmony_ci        return -1;
86595d5899Sopenharmony_ci    }
87595d5899Sopenharmony_ci    auto newBufferTime = new(std::nothrow) int64_t[newSize];
88595d5899Sopenharmony_ci    if (newBufferTime == nullptr) {
89595d5899Sopenharmony_ci        DISPLAY_HILOGE(FEAT_BRIGHTNESS, "newBufferTime id null");
90595d5899Sopenharmony_ci        delete[] newBufferData;
91595d5899Sopenharmony_ci        return -1;
92595d5899Sopenharmony_ci    }
93595d5899Sopenharmony_ci    unsigned int length = mCapacity - mStart;
94595d5899Sopenharmony_ci    bool isError = false;
95595d5899Sopenharmony_ci    isError = isError || (memcpy_s(newBufferData, newSize * sizeof(newBufferData[0]),
96595d5899Sopenharmony_ci        mBufferData + mStart, length * sizeof(mBufferData[0])) != EOK);
97595d5899Sopenharmony_ci    isError = isError || (memcpy_s(newBufferTime, newSize * sizeof(newBufferTime[0]),
98595d5899Sopenharmony_ci        mBufferTime + mStart, length * sizeof(mBufferTime[0])) != EOK);
99595d5899Sopenharmony_ci    if (mStart != 0) {
100595d5899Sopenharmony_ci        isError = isError || (memcpy_s(newBufferData + length, (newSize - length) * sizeof(newBufferData[0]),
101595d5899Sopenharmony_ci            mBufferData, mStart * sizeof(mBufferData[0])) != EOK);
102595d5899Sopenharmony_ci        isError = isError || (memcpy_s(newBufferTime + length, (newSize - length) * sizeof(newBufferTime[0]),
103595d5899Sopenharmony_ci            mBufferTime, mStart * sizeof(mBufferTime[0])) != EOK);
104595d5899Sopenharmony_ci    }
105595d5899Sopenharmony_ci    if (isError) {
106595d5899Sopenharmony_ci        DISPLAY_HILOGE(FEAT_BRIGHTNESS, "memcpy_s error, mCapacity=%{public}d, mStart=%{public}d", mCapacity, mStart);
107595d5899Sopenharmony_ci        delete[] newBufferData;
108595d5899Sopenharmony_ci        delete[] newBufferTime;
109595d5899Sopenharmony_ci        return -1;
110595d5899Sopenharmony_ci    }
111595d5899Sopenharmony_ci    delete[] mBufferData;
112595d5899Sopenharmony_ci    mBufferData = newBufferData;
113595d5899Sopenharmony_ci    delete[] mBufferTime;
114595d5899Sopenharmony_ci    mBufferTime = newBufferTime;
115595d5899Sopenharmony_ci
116595d5899Sopenharmony_ci    return 0;
117595d5899Sopenharmony_ci}
118595d5899Sopenharmony_ci
119595d5899Sopenharmony_civoid LightLuxBuffer::Push(const int64_t timestamp, const float data)
120595d5899Sopenharmony_ci{
121595d5899Sopenharmony_ci    if (LuxBufferCheck() != 0) {
122595d5899Sopenharmony_ci        return;
123595d5899Sopenharmony_ci    }
124595d5899Sopenharmony_ci
125595d5899Sopenharmony_ci    unsigned int next = mEnd;
126595d5899Sopenharmony_ci    if (mCount == mCapacity) {
127595d5899Sopenharmony_ci        unsigned long newSize = mCapacity * static_cast<unsigned long>(BUFFER_SIZE_INCREASE);
128595d5899Sopenharmony_ci        if (newSize > static_cast<unsigned long>(LUX_BUFFER_SIZE_MAX)) {
129595d5899Sopenharmony_ci            DISPLAY_HILOGW(FEAT_BRIGHTNESS, "buffer size larger than max value %{public}d already, stop expand",
130595d5899Sopenharmony_ci                LUX_BUFFER_SIZE_MAX);
131595d5899Sopenharmony_ci            return;
132595d5899Sopenharmony_ci        }
133595d5899Sopenharmony_ci        if (mStart >= mCapacity) {
134595d5899Sopenharmony_ci            DISPLAY_HILOGE(FEAT_BRIGHTNESS, "mStart error! mStart(%{public}d) >= mCapacity(%{public}d)",
135595d5899Sopenharmony_ci                mStart, mCapacity);
136595d5899Sopenharmony_ci            return;
137595d5899Sopenharmony_ci        }
138595d5899Sopenharmony_ci
139595d5899Sopenharmony_ci        if (CopyLuxBuffer(newSize) != 0) {
140595d5899Sopenharmony_ci            return;
141595d5899Sopenharmony_ci        }
142595d5899Sopenharmony_ci
143595d5899Sopenharmony_ci        next = mCapacity;
144595d5899Sopenharmony_ci        mCapacity = static_cast<unsigned int>(newSize);
145595d5899Sopenharmony_ci        mStart = 0;
146595d5899Sopenharmony_ci    }
147595d5899Sopenharmony_ci
148595d5899Sopenharmony_ci    if (mBufferTime != nullptr) {
149595d5899Sopenharmony_ci        mBufferTime[next] = timestamp;
150595d5899Sopenharmony_ci    }
151595d5899Sopenharmony_ci
152595d5899Sopenharmony_ci    if (mBufferData != nullptr) {
153595d5899Sopenharmony_ci        mBufferData[next] = data;
154595d5899Sopenharmony_ci    }
155595d5899Sopenharmony_ci
156595d5899Sopenharmony_ci    mEnd = next + 1;
157595d5899Sopenharmony_ci    if (mEnd == mCapacity) {
158595d5899Sopenharmony_ci        mEnd = 0;
159595d5899Sopenharmony_ci    }
160595d5899Sopenharmony_ci    mCount++;
161595d5899Sopenharmony_ci}
162595d5899Sopenharmony_ci
163595d5899Sopenharmony_civoid LightLuxBuffer::Prune(const int64_t horizon)
164595d5899Sopenharmony_ci{
165595d5899Sopenharmony_ci    if (mCount == 0 || mBufferTime == nullptr) {
166595d5899Sopenharmony_ci        return;
167595d5899Sopenharmony_ci    }
168595d5899Sopenharmony_ci
169595d5899Sopenharmony_ci    while (mCount > 1) {
170595d5899Sopenharmony_ci        unsigned int next = mStart + 1;
171595d5899Sopenharmony_ci        if (next >= mCapacity) {
172595d5899Sopenharmony_ci            next -= mCapacity;
173595d5899Sopenharmony_ci        }
174595d5899Sopenharmony_ci        if (mBufferTime[next] > horizon) {
175595d5899Sopenharmony_ci            break;
176595d5899Sopenharmony_ci        }
177595d5899Sopenharmony_ci        mStart = next;
178595d5899Sopenharmony_ci        mCount--;
179595d5899Sopenharmony_ci    }
180595d5899Sopenharmony_ci    if (mBufferTime[mStart] < horizon) {
181595d5899Sopenharmony_ci        mBufferTime[mStart] = horizon;
182595d5899Sopenharmony_ci    }
183595d5899Sopenharmony_ci}
184595d5899Sopenharmony_ci
185595d5899Sopenharmony_civoid LightLuxBuffer::Clear()
186595d5899Sopenharmony_ci{
187595d5899Sopenharmony_ci    mStart = 0;
188595d5899Sopenharmony_ci    mEnd = 0;
189595d5899Sopenharmony_ci    mCount = 0;
190595d5899Sopenharmony_ci}
191595d5899Sopenharmony_ci
192595d5899Sopenharmony_cifloat LightLuxBuffer::GetData(const unsigned int index) const
193595d5899Sopenharmony_ci{
194595d5899Sopenharmony_ci    if (mBufferData == nullptr) {
195595d5899Sopenharmony_ci        DISPLAY_HILOGE(FEAT_BRIGHTNESS, "mBufferData is nullptr.");
196595d5899Sopenharmony_ci        return 0;
197595d5899Sopenharmony_ci    }
198595d5899Sopenharmony_ci    if (index >= mCount) {
199595d5899Sopenharmony_ci        DISPLAY_HILOGE(FEAT_BRIGHTNESS, "error! index = %{public}d, out of range mCount = %{public}d", index, mCount);
200595d5899Sopenharmony_ci        return 0;
201595d5899Sopenharmony_ci    }
202595d5899Sopenharmony_ci    return mBufferData[OffsetOf(index)];
203595d5899Sopenharmony_ci}
204595d5899Sopenharmony_ci
205595d5899Sopenharmony_ciint64_t LightLuxBuffer::GetTime(const unsigned int index) const
206595d5899Sopenharmony_ci{
207595d5899Sopenharmony_ci    if (mBufferTime == nullptr) {
208595d5899Sopenharmony_ci        DISPLAY_HILOGE(FEAT_BRIGHTNESS, "mBufferTime is nullptr");
209595d5899Sopenharmony_ci        return 0;
210595d5899Sopenharmony_ci    }
211595d5899Sopenharmony_ci
212595d5899Sopenharmony_ci    if (index >= mCount) {
213595d5899Sopenharmony_ci        DISPLAY_HILOGE(FEAT_BRIGHTNESS, "error! index = %{public}d, out of range mCount = %{public}d", index, mCount);
214595d5899Sopenharmony_ci        return 0;
215595d5899Sopenharmony_ci    }
216595d5899Sopenharmony_ci    return mBufferTime[OffsetOf(index)];
217595d5899Sopenharmony_ci}
218595d5899Sopenharmony_ci
219595d5899Sopenharmony_ciunsigned int LightLuxBuffer::GetSize() const
220595d5899Sopenharmony_ci{
221595d5899Sopenharmony_ci    return mCount;
222595d5899Sopenharmony_ci}
223595d5899Sopenharmony_ci
224595d5899Sopenharmony_ciunsigned int LightLuxBuffer::OffsetOf(const unsigned int index) const
225595d5899Sopenharmony_ci{
226595d5899Sopenharmony_ci    unsigned actualIndex = index + mStart;
227595d5899Sopenharmony_ci    if (actualIndex >= mCapacity) {
228595d5899Sopenharmony_ci        actualIndex -= mCapacity;
229595d5899Sopenharmony_ci    }
230595d5899Sopenharmony_ci    return actualIndex;
231595d5899Sopenharmony_ci}
232595d5899Sopenharmony_ci
233595d5899Sopenharmony_cistd::string LightLuxBuffer::ToString(unsigned int n)
234595d5899Sopenharmony_ci{
235595d5899Sopenharmony_ci    std::ostringstream result;
236595d5899Sopenharmony_ci    if (n > mCount) {
237595d5899Sopenharmony_ci        n = mCount;
238595d5899Sopenharmony_ci    }
239595d5899Sopenharmony_ci    result << "[";
240595d5899Sopenharmony_ci    for (unsigned int i = mCount-n; i>=0 && i < mCount;i++) {
241595d5899Sopenharmony_ci        result << GetData(i);
242595d5899Sopenharmony_ci        result << "/";
243595d5899Sopenharmony_ci        result << GetTime(i);
244595d5899Sopenharmony_ci        result << ", ";
245595d5899Sopenharmony_ci    }
246595d5899Sopenharmony_ci    result << "]";
247595d5899Sopenharmony_ci    return result.str();
248595d5899Sopenharmony_ci}
249595d5899Sopenharmony_ci} // namespace DisplayPowerMgr
250595d5899Sopenharmony_ci} // namespace OHOS