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