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