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_manager.h"
17 
18 #include <cinttypes>
19 
20 #include "display_log.h"
21 
22 namespace OHOS {
23 namespace DisplayPowerMgr {
24 namespace {
25 const int LIGHT_LUX_BUFFER_RANGE = 10000;
26 const int LIGHT_MAX_LUX = 40000;
27 const int LIGHT_LUX_BUFFER_MIN = 5;
28 const int INVALID_VALUE = -1;
29 const int LOG_INTERVAL_MS = 2000;
30 const int LUX_BUFFER_NUM_FOR_LOG = 6;
31 const std::string ScenceLabel[static_cast<int>(BrightnessSceneMode::SCENCE_END)] = {
32     "DefaultMode", "GameMode", "VideoMode" };
33 const std::string FilterLabel[static_cast<int>(BrightnessFilterMode::FITLER_END)] = {
34     "meanFilter", "weightFilter" };
35 }
36 
GetLux() const37 float LightLuxManager::GetLux() const
38 {
39     return mLux;
40 }
41 
SetLux(float lux)42 void LightLuxManager::SetLux(float lux)
43 {
44     lux = GetValidLux(lux);
45     mLux = lux;
46     int64_t currentTime = GetCurrentTimeMillis();
47     UpdateLuxBuffer(currentTime, lux);
48     IsUpdateLuxSuccess(currentTime);
49 }
50 
GetIsFirstLux()51 bool LightLuxManager::GetIsFirstLux()
52 {
53     return mIsFirstLux;
54 }
55 
UpdateLuxBuffer(int64_t timestamp, float lux)56 void LightLuxManager::UpdateLuxBuffer(int64_t timestamp, float lux)
57 {
58     mLuxBuffer.Prune(timestamp - LIGHT_LUX_BUFFER_RANGE);
59     mLuxBuffer.Push(timestamp, lux);
60 }
61 
IsUpdateLuxSuccess(int64_t timestamp)62 bool LightLuxManager::IsUpdateLuxSuccess(int64_t timestamp)
63 {
64     float smoothLux = CalcSmoothLux();
65     if (smoothLux < 0) {
66         return false;
67     }
68 
69     mSmoothedButNotStabledLux = smoothLux;
70     mIsFirstLux = false;
71     if (mLuxBuffer.GetSize() == 1) {
72         DISPLAY_HILOGI(FEAT_BRIGHTNESS, "fist sensor lux, smoothLux=%{public}f, "
73             "timestamp=%{public}" PRId64 ".", smoothLux, timestamp);
74         mIsFirstLux = true;
75     }
76     if (mLuxBuffer.GetSize() < LIGHT_LUX_BUFFER_MIN) {
77         DISPLAY_HILOGI(FEAT_BRIGHTNESS, "mLux=%{public}f, smoothLux=%{public}f", mLux, smoothLux);
78     }
79     mLuxBufferFilter.Prune(timestamp - LIGHT_LUX_BUFFER_RANGE);
80     mLuxBufferFilter.Push(timestamp, smoothLux);
81     int64_t nextBrightenTime = GetNextBrightenTime(timestamp);
82     int64_t nextDarkenTime = GetNextDarkenTime(timestamp);
83     PrintCurrentLuxLog(timestamp);
84 
85     if (nextBrightenTime <= timestamp || nextDarkenTime <= timestamp || mIsFirstLux) {
86         UpdateParam(smoothLux);
87         return true;
88     }
89     return false;
90 }
91 
CalcSmoothLux() const92 float LightLuxManager::CalcSmoothLux() const
93 {
94     auto size = mLuxBuffer.GetSize();
95     if (size == 0) {
96         DISPLAY_HILOGE(FEAT_BRIGHTNESS, "No ambient light readings available");
97         return INVALID_VALUE;
98     }
99     if (size < LIGHT_LUX_BUFFER_MIN) {
100         return mLuxBuffer.GetData(size - 1);
101     }
102 
103     float sum = 0;
104     float luxMin = mLuxBuffer.GetData(size - 1);
105     float luxMax = mLuxBuffer.GetData(size - 1);
106     for (unsigned int i = size; i >= size - (LIGHT_LUX_BUFFER_MIN - 1); i--) {
107         float lux = mLuxBuffer.GetData(i - 1);
108         if (luxMin > lux) {
109             luxMin = lux;
110         }
111         if (luxMax < lux) {
112             luxMax = lux;
113         }
114         sum += lux;
115     }
116     DISPLAY_HILOGD(FEAT_BRIGHTNESS, "sum - luxMin - luxMax  = %{public}f \n", sum - luxMin - luxMax);
117     return (sum - luxMin - luxMax) / 3.0f;
118 }
119 
GetNextBrightenTime(int64_t timestamp) const120 int64_t LightLuxManager::GetNextBrightenTime(int64_t timestamp) const
121 {
122     auto size = mLuxBufferFilter.GetSize();
123     if (size == 0) {
124         DISPLAY_HILOGE(FEAT_BRIGHTNESS, "mLuxBufferFilter is empty");
125         return timestamp;
126     }
127     int64_t debounceTime = (size == 1) ? 0 : GetBrightenResponseTime();
128     int64_t earliestValidTime = timestamp;
129     for (unsigned int i = size; i >= 1; i--) {
130         if ((mLuxBufferFilter.GetData(i - 1) - mFilteredLux) < mBrightenDelta) {
131             break;
132         }
133         earliestValidTime = mLuxBufferFilter.GetTime(i - 1);
134     }
135 
136     return earliestValidTime + debounceTime;
137 }
138 
GetNextDarkenTime(int64_t timestamp) const139 int64_t LightLuxManager::GetNextDarkenTime(int64_t timestamp) const
140 {
141     auto size = mLuxBufferFilter.GetSize();
142     if (size == 0) {
143         DISPLAY_HILOGE(FEAT_BRIGHTNESS, "mLuxBufferFilter is empty");
144         return timestamp;
145     }
146     int64_t debounceTime = (size == 1) ? 0 : GetDarkenResponseTime();
147     int64_t earliestValidTime = timestamp;
148     for (unsigned int i = size; i >= 1; i--) {
149         if ((mFilteredLux - mLuxBufferFilter.GetData(i - 1)) < mDarkenDelta) {
150             break;
151         }
152         earliestValidTime = mLuxBufferFilter.GetTime(i - 1);
153     }
154 
155     return earliestValidTime + debounceTime;
156 }
157 
UpdateParam(const float lux)158 void LightLuxManager::UpdateParam(const float lux)
159 {
160     mFilteredLux = lux;
161     std::vector<PointXy> brightenLinePointsList = GetBrightenLuxList();
162     float delta = CalcDelta(brightenLinePointsList);
163     if (delta >= 0) {
164         mBrightenDelta = delta;
165     }
166     std::vector<PointXy> darkenLinePointsList = GetDarkenLuxList();
167     delta = CalcDelta(darkenLinePointsList);
168     if (delta >= 0) {
169         mDarkenDelta = delta;
170     }
171     DISPLAY_HILOGI(FEAT_BRIGHTNESS, "mFilteredLux=%{public}f, "
172         "bDelta=%{public}f, dDelta=%{public}f", mFilteredLux, mBrightenDelta, mDarkenDelta);
173 }
174 
CalcDelta(const std::vector<PointXy>& pointsList) const175 float LightLuxManager::CalcDelta(const std::vector<PointXy>& pointsList) const
176 {
177     if (pointsList.empty()) {
178         DISPLAY_HILOGE(FEAT_BRIGHTNESS, "error! input vector is empty");
179         return INVALID_VALUE;
180     }
181     float delta = 0;
182     PointXy temp = pointsList.front();
183     std::vector<PointXy>::const_iterator it;
184     for (it = pointsList.begin(); it != pointsList.end(); it++) {
185         if (mFilteredLux < it->x) {
186             if (it->x < temp.x || IsEqualF(it->x, temp.x)) {
187                 delta = 1;
188             } else {
189                 delta = (it->y - temp.y) / (it->x - temp.x) * (mFilteredLux - temp.x) + temp.y;
190                 delta = (delta < 1 ? 1 : delta);
191             }
192             break;
193         } else {
194             temp = *it;
195             delta = it->y;
196         }
197     }
198     return delta;
199 }
200 
GetValidLux(float lux) const201 float LightLuxManager::GetValidLux(float lux) const
202 {
203     if (lux > LIGHT_MAX_LUX) {
204         DISPLAY_HILOGE(FEAT_BRIGHTNESS, "error lux = %{public}f > LIGHT_MAX_LUX", lux);
205         lux = LIGHT_MAX_LUX;
206     }
207     if (lux < 0) {
208         DISPLAY_HILOGE(FEAT_BRIGHTNESS, "error lux = %{public}f < 0", lux);
209         lux = 0;
210     }
211     return lux;
212 }
213 
InitParameters()214 void LightLuxManager::InitParameters()
215 {
216     int displayId = 0;
217     const std::unordered_map<int, Config>& brightnessConfig =
218         ConfigParse::Get().GetBrightnessConfig();
219     std::unordered_map<int, Config>::const_iterator itDisp = brightnessConfig.find(displayId);
220     if (itDisp == brightnessConfig.end()) {
221         DISPLAY_HILOGE(FEAT_BRIGHTNESS, "[%{public}d]Failed to find config", displayId);
222         return;
223     }
224     mBrightnessConfigData = itDisp->second;
225 }
226 
SetSceneMode(BrightnessSceneMode mode)227 void LightLuxManager::SetSceneMode(BrightnessSceneMode mode)
228 {
229     mCurrentSceneMode = mode;
230 }
231 
GetFilteredLux() const232 float LightLuxManager::GetFilteredLux() const
233 {
234     return mSmoothedButNotStabledLux;
235 }
236 
GetSmoothedLux() const237 float LightLuxManager::GetSmoothedLux() const
238 {
239     return static_cast<int>(mFilteredLux);
240 }
241 
UpdateSmoothedLux(float lux)242 void LightLuxManager::UpdateSmoothedLux(float lux)
243 {
244     DISPLAY_HILOGI(FEAT_BRIGHTNESS, "UpdateSmoothedLux mFilteredLux =%{public}f, lux = %{public}f", mFilteredLux, lux);
245     mFilteredLux = lux;
246 }
247 
ClearLuxData()248 void LightLuxManager::ClearLuxData()
249 {
250     mLuxBuffer.Clear();
251     mLuxBufferFilter.Clear();
252     DISPLAY_HILOGE(FEAT_BRIGHTNESS, "ClearLuxData, lux=%{public}f", mFilteredLux);
253 }
254 
GetDarkenResponseTime() const255 int LightLuxManager::GetDarkenResponseTime() const
256 {
257     auto& mode = GetCurrentModeData();
258     int DarkenTime = mode.darkenDebounceTime;
259     if (DarkenTime == INVALID_VALUE) {
260         DISPLAY_HILOGE(FEAT_BRIGHTNESS, "GetDarkenResponseTime Failed!");
261         return 0;
262     }
263     return DarkenTime;
264 }
265 
GetBrightenResponseTime() const266 int LightLuxManager::GetBrightenResponseTime() const
267 {
268     auto& mode = GetCurrentModeData();
269     int brightenTime = mode.brightenDebounceTime;
270     if (brightenTime == INVALID_VALUE) {
271         DISPLAY_HILOGE(FEAT_BRIGHTNESS, "GetBrightenResponseTime Failed!");
272         return 0;
273     }
274     return brightenTime;
275 }
276 
GetCurrentModeData() const277 const LuxThresholdConfig::Mode& LightLuxManager::GetCurrentModeData() const
278 {
279     return mBrightnessConfigData.luxThresholdConfig.modeArray.at(ScenceLabel[static_cast<int>(mCurrentSceneMode)]);
280 }
281 
GetBrightenLuxList()282 std::vector<PointXy> LightLuxManager::GetBrightenLuxList()
283 {
284     std::vector<PointXy> brightenPointsList;
285     auto& mode = GetCurrentModeData();
286     brightenPointsList = mode.brightenPoints;
287 
288     return brightenPointsList;
289 }
290 
GetDarkenLuxList()291 std::vector<PointXy> LightLuxManager::GetDarkenLuxList()
292 {
293     std::vector<PointXy> darkenPointsList;
294     auto& mode = GetCurrentModeData();
295     darkenPointsList = mode.darkenPoints;
296 
297     return darkenPointsList;
298 }
299 
GetFilterNum()300 int LightLuxManager::GetFilterNum()
301 {
302     std::string filterName = FilterLabel[static_cast<int>(mCurrentFilter)];
303     return mBrightnessConfigData.luxFilterConfig[filterName].filterNum;
304 }
305 
GetNoFilterNum()306 int LightLuxManager::GetNoFilterNum()
307 {
308     std::string filterName = FilterLabel[static_cast<int>(mCurrentFilter)];
309     return mBrightnessConfigData.luxFilterConfig[filterName].filterNoFilterNum;
310 }
311 
IsNeedUpdateBrightness(float lux)312 bool LightLuxManager::IsNeedUpdateBrightness(float lux)
313 {
314     float validLux = GetValidLux(lux);
315     mLux = validLux;
316     int64_t currentTime = GetCurrentTimeMillis();
317     UpdateLuxBuffer(currentTime, validLux);
318     return IsUpdateLuxSuccess(currentTime);
319 }
320 
PrintCurrentLuxLog(int64_t time)321 void LightLuxManager::PrintCurrentLuxLog(int64_t time)
322 {
323     if (time - mPrintLogTime > LOG_INTERVAL_MS) {
324         DISPLAY_HILOGI(FEAT_BRIGHTNESS, "lux=%{public}s, bDelta=%{public}f, dDelta=%{public}f, size=%{public}d",
325             mLuxBufferFilter.ToString(LUX_BUFFER_NUM_FOR_LOG).c_str(),
326             mBrightenDelta, mDarkenDelta, mLuxBufferFilter.GetSize());
327         mPrintLogTime = time;
328     }
329 }
330 } // namespace DisplayPowerMgr
331 } // namespace OHOS