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