1 /*
2 * Copyright (c) 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 "screen_brightness_task.h"
17
18 #include <string>
19 #include <vector>
20
21 #ifdef FACE_USE_DISPLAY_MANAGER_COMPONENT
22 #include "display_power_mgr_client.h"
23 #endif
24 #include "parameter.h"
25 #ifdef FACE_USE_SENSOR_COMPONENT
26 #include "sensor_agent.h"
27 #endif
28
29 #include "iam_check.h"
30 #include "iam_logger.h"
31 #include "iam_ptr.h"
32
33 #include "finite_state_machine.h"
34 #include "screen_brightness_manager.h"
35
36 #define LOG_TAG "FACE_AUTH_SA"
37
38 namespace OHOS {
39 namespace UserIam {
40 namespace FaceAuth {
41 using ResultCode = UserAuth::ResultCode;
42 #ifdef FACE_USE_DISPLAY_MANAGER_COMPONENT
43 using namespace DisplayPowerMgr;
44 #endif
45 namespace {
46 #ifdef FACE_USE_SENSOR_COMPONENT
47 constexpr SensorUser SENSOR_USER = {
48 "FaceAuthService",
49 [](SensorEvent *event) {
50 IF_FALSE_LOGE_AND_RETURN(event != nullptr);
51 IF_FALSE_LOGE_AND_RETURN(event->sensorTypeId == SENSOR_TYPE_ID_AMBIENT_LIGHT);
52 auto data = static_cast<AmbientLightData *>(static_cast<void *>(event->data));
53 IF_FALSE_LOGE_AND_RETURN(data != nullptr);
54
55 auto manager = ScreenBrightnessManager::GetInstance();
56 IF_FALSE_LOGE_AND_RETURN(manager != nullptr);
57 auto task = manager->GetCurrentTask();
58 IF_FALSE_LOGE_AND_RETURN(task != nullptr);
59
60 task->SetAmbientLight(data->intensity);
61 },
62 };
63 #endif
64 constexpr uint32_t INVALID_BRIGHTNESS = -1;
65 constexpr uint32_t SENSOR_SAMPLE_AND_REPORT_INTERVAL = 100 * 1000 * 1000; // ns
66 constexpr uint32_t INCREASE_BRIGHTNESS_START_DELAY = 100; // ms
67 constexpr uint32_t DEFAULT_INCREASE_BRIGHTNESS_INTERVAL = 75; // ms
68 constexpr uint32_t DEFAULT_INCREASE_BRIGHTNESS_MAX = 30;
69 const std::vector<uint32_t> INCREASE_BRIGHTNESS_ARRAY = { 4, 4, 5, 5, 6, 6, 7, 8, 9, 9, 10, 11, 13, 14, 15, 17, 18, 20,
70 22, 24, 27, 30, 33, 36, 39, 43, 48, 52, 58, 63, 70, 77, 84, 93, 102, 112, 124, 136, 150, 166, 181, 199, 219, 241 };
71 constexpr float AMBIENT_LIGHT_THRESHOLD_FOR_BEGIN = 2.0; // lux
72 constexpr uint32_t MAX_BRIGHTNESS = 255;
73 constexpr uint32_t MAX_INT_STRING_LEN = 12;
74 constexpr float INVALID_AMBIENT_LIGHT_LUX = -1.0;
75 const char *INCREASE_BRIGHTNESS_MAX_KEY = "const.useriam.face_auth_increase_brightness_max";
76 const char *INCREASE_BRIGHTNESS_INTERVAL_KEY = "const.useriam.face_auth_increase_brightness_interval";
77
GetUInt32Param(const char *key, uint32_t defaultValue)78 uint32_t GetUInt32Param(const char *key, uint32_t defaultValue)
79 {
80 std::string defaultStr = std::to_string(defaultValue);
81 char str[MAX_INT_STRING_LEN] = { 0 };
82 int32_t ret = GetParameter(key, defaultStr.c_str(), str, MAX_INT_STRING_LEN - 1);
83 if (ret < 0) {
84 IAM_LOGE("failed to get param %{public}s, return default value", key);
85 return defaultValue;
86 }
87 uint32_t uintValue;
88 try {
89 unsigned long longValue = std::stoul(str);
90 if (longValue > std::numeric_limits<uint32_t>::max()) {
91 IAM_LOGE("value exceeds uint32");
92 return std::numeric_limits<uint32_t>::max();
93 }
94 uintValue = static_cast<uint32_t>(longValue);
95 } catch (const std::exception &e) {
96 IAM_LOGE("failed to convert %{public}s to int, return default value", str);
97 return defaultValue;
98 }
99
100 return uintValue;
101 }
102
GetIncreaseBrightnessInterval()103 uint32_t GetIncreaseBrightnessInterval()
104 {
105 uint32_t val = GetUInt32Param(INCREASE_BRIGHTNESS_INTERVAL_KEY, DEFAULT_INCREASE_BRIGHTNESS_INTERVAL);
106 if (val == 0) {
107 IAM_LOGE("interval cannot be 0");
108 return DEFAULT_INCREASE_BRIGHTNESS_INTERVAL;
109 }
110 IAM_LOGI("param interval %{public}u", val);
111 return val;
112 }
113
GetIncreaseBrightnessMax()114 uint32_t GetIncreaseBrightnessMax()
115 {
116 uint32_t val = GetUInt32Param(INCREASE_BRIGHTNESS_MAX_KEY, DEFAULT_INCREASE_BRIGHTNESS_MAX);
117 if (val > MAX_BRIGHTNESS) {
118 IAM_LOGE("val exceeds max brightness");
119 return MAX_BRIGHTNESS;
120 }
121 IAM_LOGI("param increase brightness max %{public}u", val);
122 return val;
123 }
124
SubscribeSensor()125 ResultCode SubscribeSensor()
126 {
127 IAM_LOGI("start");
128 #ifdef FACE_USE_SENSOR_COMPONENT
129 int32_t subscribeSensorRet = SubscribeSensor(SENSOR_TYPE_ID_AMBIENT_LIGHT, &SENSOR_USER);
130 IF_FALSE_LOGE_AND_RETURN_VAL(subscribeSensorRet == 0, ResultCode::GENERAL_ERROR);
131 int32_t setBatchRet = SetBatch(SENSOR_TYPE_ID_AMBIENT_LIGHT, &SENSOR_USER, SENSOR_SAMPLE_AND_REPORT_INTERVAL,
132 SENSOR_SAMPLE_AND_REPORT_INTERVAL);
133 IF_FALSE_LOGE_AND_RETURN_VAL(setBatchRet == 0, ResultCode::GENERAL_ERROR);
134 int32_t activateSensorRet = ActivateSensor(SENSOR_TYPE_ID_AMBIENT_LIGHT, &SENSOR_USER);
135 IF_FALSE_LOGE_AND_RETURN_VAL(activateSensorRet == 0, ResultCode::GENERAL_ERROR);
136 int32_t setModeRet = SetMode(SENSOR_TYPE_ID_AMBIENT_LIGHT, &SENSOR_USER, SENSOR_ON_CHANGE);
137 IF_FALSE_LOGE_AND_RETURN_VAL(setModeRet == 0, ResultCode::GENERAL_ERROR);
138 return ResultCode::SUCCESS;
139 #else
140 IAM_LOGI("sensor component is not used");
141 return ResultCode::GENERAL_ERROR
142 #endif
143 }
144
145 void UnsubscribeSensor()
146 {
147 IAM_LOGI("start");
148 #ifdef FACE_USE_SENSOR_COMPONENT
149 DeactivateSensor(SENSOR_TYPE_ID_AMBIENT_LIGHT, &SENSOR_USER);
150 UnsubscribeSensor(SENSOR_TYPE_ID_AMBIENT_LIGHT, &SENSOR_USER);
151 return;
152 #else
153 IAM_LOGI("sensor component is not used");
154 return;
155 #endif
156 }
157
GetIncreaseBrightnessStartIndex(uint32_t currentBrightness)158 uint32_t GetIncreaseBrightnessStartIndex(uint32_t currentBrightness)
159 {
160 for (uint32_t i = 0; i < INCREASE_BRIGHTNESS_ARRAY.size(); i++) {
161 if (INCREASE_BRIGHTNESS_ARRAY[i] > currentBrightness) {
162 return i;
163 }
164 }
165 return INCREASE_BRIGHTNESS_ARRAY.size();
166 }
167
OverrideScreenBrightness(uint32_t brightness)168 void OverrideScreenBrightness(uint32_t brightness)
169 {
170 #ifdef FACE_USE_DISPLAY_MANAGER_COMPONENT
171 int32_t displayId = DisplayPowerMgrClient::GetInstance().GetMainDisplayId();
172 if (!DisplayPowerMgrClient::GetInstance().OverrideBrightness(brightness, displayId)) {
173 IAM_LOGE("override brightness fail");
174 return;
175 }
176 #else
177 IAM_LOGI("display_manager component is not used.");
178 return;
179 #endif
180 }
181
RestoreScreenBrightness()182 void RestoreScreenBrightness()
183 {
184 #ifdef FACE_USE_DISPLAY_MANAGER_COMPONENT
185 int32_t displayId = DisplayPowerMgrClient::GetInstance().GetMainDisplayId();
186 if (!DisplayPowerMgrClient::GetInstance().RestoreBrightness(displayId)) {
187 IAM_LOGE("restore brightness fail");
188 return;
189 }
190 #else
191 IAM_LOGI("display_manager component is not used.");
192 return;
193 #endif
194 }
195
GetCurrentScreenBrightness()196 uint32_t GetCurrentScreenBrightness()
197 {
198 #ifdef FACE_USE_DISPLAY_MANAGER_COMPONENT
199 return DisplayPowerMgrClient::GetInstance().GetDeviceBrightness();
200 #else
201 IAM_LOGI("display_manager component is not used.");
202 return INVALID_BRIGHTNESS;
203 #endif
204 }
205
ShouldBeginIncreaseBrightness(float currentAmbientLightLux)206 bool ShouldBeginIncreaseBrightness(float currentAmbientLightLux)
207 {
208 return currentAmbientLightLux < AMBIENT_LIGHT_THRESHOLD_FOR_BEGIN;
209 }
210 } // namespace
211
ScreenBrightnessTask()212 ScreenBrightnessTask::ScreenBrightnessTask() : timer_("screen_brightness_timer")
213 {
214 timer_.Setup();
215 increaseBrightnessIndex_ = 0;
216 increaseBrightnessInterval_ = GetIncreaseBrightnessInterval();
217 increaseBrightnessMax_ = GetIncreaseBrightnessMax();
218 currTimerId_ = 0;
219 currentBrightness_ = 0;
220 currentAmbientLightLux_ = INVALID_AMBIENT_LIGHT_LUX;
221 }
222
~ScreenBrightnessTask()223 ScreenBrightnessTask::~ScreenBrightnessTask()
224 {
225 timer_.Unregister(currTimerId_);
226 timer_.Shutdown();
227 if (machine_ != nullptr) {
228 // make sure state machine is stopped
229 uint32_t state = machine_->EnsureCurrentState();
230 if (state != S_END) {
231 IAM_LOGE("state is not STOP when destruct");
232 }
233 }
234 if (destructCallback_ != nullptr) {
235 destructCallback_();
236 }
237 }
238
Start()239 void ScreenBrightnessTask::Start()
240 {
241 machine_ = MakeFiniteStateMachine();
242 IF_FALSE_LOGE_AND_RETURN(machine_ != nullptr);
243
244 machine_->Schedule(E_START);
245 }
246
Stop()247 void ScreenBrightnessTask::Stop()
248 {
249 IF_FALSE_LOGE_AND_RETURN(machine_ != nullptr);
250 machine_->Schedule(E_STOP);
251 }
252
MakeFiniteStateMachine()253 std::shared_ptr<FiniteStateMachine> ScreenBrightnessTask::MakeFiniteStateMachine()
254 {
255 auto builder = FiniteStateMachine::Builder::New("ScreenBrightnessTask", State::S_INIT);
256 IF_FALSE_LOGE_AND_RETURN_VAL(builder != nullptr, nullptr);
257
258 // S_INIT
259 builder->MakeTransition(S_INIT, E_START, S_WAIT_AMBIENT_LIGHT_INFO_AND_START_DELAY,
260 [self = this](FiniteStateMachine &machine, uint32_t event) { self->StartProcess(); });
261
262 // S_WAIT_*
263 builder->MakeTransition(S_WAIT_AMBIENT_LIGHT_INFO_AND_START_DELAY, E_START_DELAY_EXPIRED,
264 S_WAIT_AMBIENT_LIGHT_INFO);
265 builder->MakeTransition(S_WAIT_AMBIENT_LIGHT_INFO_AND_START_DELAY, E_RECEIVE_AMBIENT_LIGHT_INFO,
266 S_WAIT_START_DELAY);
267 builder->MakeTransition(S_WAIT_AMBIENT_LIGHT_INFO, E_RECEIVE_AMBIENT_LIGHT_INFO, S_INCREASING_BRIGHTNESS);
268 builder->MakeTransition(S_WAIT_START_DELAY, E_START_DELAY_EXPIRED, S_INCREASING_BRIGHTNESS);
269
270 // S_INCREASING_BRIGHTNESS
271 builder->MakeOnStateEnter(S_INCREASING_BRIGHTNESS,
272 [self = this](FiniteStateMachine &machine, uint32_t event) { self->BeginIncreaseBrightness(); });
273
274 builder->MakeTransition(S_INCREASING_BRIGHTNESS, E_INCREASE_BRIGHTNESS, S_INCREASING_BRIGHTNESS,
275 [self = this](FiniteStateMachine &machine, uint32_t event) { self->DoIncreaseBrightness(); });
276
277 // S_END
278 builder->MakeOnStateEnter(S_END,
279 [self = this](FiniteStateMachine &machine, uint32_t event) { self->EndProcess(); });
280
281 // process E_STOP
282 builder->MakeTransition(S_WAIT_AMBIENT_LIGHT_INFO_AND_START_DELAY, E_STOP, S_END);
283 builder->MakeTransition(S_WAIT_AMBIENT_LIGHT_INFO, E_STOP, S_END);
284 builder->MakeTransition(S_WAIT_START_DELAY, E_STOP, S_END);
285 builder->MakeTransition(S_INCREASING_BRIGHTNESS, E_STOP, S_END);
286 builder->MakeTransition(S_END, E_STOP, S_END);
287
288 // ignore E_RECEIVE_AMBIENT_LIGHT_INFO
289 builder->MakeTransition(S_WAIT_START_DELAY, E_RECEIVE_AMBIENT_LIGHT_INFO, S_WAIT_START_DELAY);
290 builder->MakeTransition(S_INCREASING_BRIGHTNESS, E_RECEIVE_AMBIENT_LIGHT_INFO, S_INCREASING_BRIGHTNESS);
291 builder->MakeTransition(S_END, E_RECEIVE_AMBIENT_LIGHT_INFO, S_END);
292 return builder->Build();
293 }
294
SetAmbientLight(float lux)295 void ScreenBrightnessTask::SetAmbientLight(float lux)
296 {
297 IAM_LOGI("receive ambient light %{public}f", lux);
298 {
299 std::lock_guard<std::mutex> lock(currentAmbientLightLuxMutex_);
300 currentAmbientLightLux_ = lux;
301 }
302
303 IF_FALSE_LOGE_AND_RETURN(machine_ != nullptr);
304 machine_->Schedule(E_RECEIVE_AMBIENT_LIGHT_INFO);
305 }
306
OnStartDelayTimeout()307 void ScreenBrightnessTask::OnStartDelayTimeout()
308 {
309 IAM_LOGI("start");
310 IF_FALSE_LOGE_AND_RETURN(machine_ != nullptr);
311 machine_->Schedule(E_START_DELAY_EXPIRED);
312 }
313
OnIncreaseBrightness()314 void ScreenBrightnessTask::OnIncreaseBrightness()
315 {
316 IAM_LOGI("start");
317 IF_FALSE_LOGE_AND_RETURN(machine_ != nullptr);
318 machine_->Schedule(E_INCREASE_BRIGHTNESS);
319 }
320
StartProcess()321 void ScreenBrightnessTask::StartProcess()
322 {
323 IAM_LOGI("start");
324 IF_FALSE_LOGE_AND_RETURN(machine_ != nullptr);
325
326 ResultCode result = SubscribeSensor();
327 if (result != ResultCode::SUCCESS) {
328 IAM_LOGE("SubscribeSensor fail");
329 machine_->Schedule(E_STOP);
330 return;
331 }
332
333 timer_.Unregister(currTimerId_);
334 currTimerId_ = timer_.Register(
335 [weak_self = weak_from_this()]() {
336 auto self = weak_self.lock();
337 if (self == nullptr) {
338 IAM_LOGE("object is released");
339 return;
340 }
341 self->OnStartDelayTimeout();
342 },
343 INCREASE_BRIGHTNESS_START_DELAY, true);
344
345 IAM_LOGI("time id %{public}d", currTimerId_);
346 }
347
BeginIncreaseBrightness()348 void ScreenBrightnessTask::BeginIncreaseBrightness()
349 {
350 IAM_LOGI("start");
351 IF_FALSE_LOGE_AND_RETURN(machine_ != nullptr);
352
353 bool shouldIncrease = false;
354 {
355 std::lock_guard<std::mutex> lock(currentAmbientLightLuxMutex_);
356 shouldIncrease = ShouldBeginIncreaseBrightness(currentAmbientLightLux_);
357 }
358 if (!shouldIncrease) {
359 IAM_LOGI("no need increase");
360 machine_->Schedule(E_STOP);
361 return;
362 }
363
364 currentBrightness_ = GetCurrentScreenBrightness();
365 IF_FALSE_LOGE_AND_RETURN(currentBrightness_ != INVALID_BRIGHTNESS);
366 increaseBrightnessIndex_ = GetIncreaseBrightnessStartIndex(currentBrightness_);
367 IF_FALSE_LOGE_AND_RETURN(increaseBrightnessIndex_ < INCREASE_BRIGHTNESS_ARRAY.size());
368
369 IAM_LOGI("current brightness %{public}u array index %{public}u value %{public}u", currentBrightness_,
370 increaseBrightnessIndex_, INCREASE_BRIGHTNESS_ARRAY[increaseBrightnessIndex_]);
371 DoIncreaseBrightness();
372 }
373
374 void ScreenBrightnessTask::DoIncreaseBrightness()
375 {
376 IAM_LOGI("start");
377
378 auto timeCallback = [weak_self = weak_from_this()]() {
379 auto self = weak_self.lock();
380 if (self == nullptr) {
381 IAM_LOGE("object is released");
382 return;
383 }
384 self->OnIncreaseBrightness();
385 };
386
387 if (increaseBrightnessIndex_ < INCREASE_BRIGHTNESS_ARRAY.size()) {
388 if (INCREASE_BRIGHTNESS_ARRAY[increaseBrightnessIndex_] <= increaseBrightnessMax_) {
389 OverrideScreenBrightness(INCREASE_BRIGHTNESS_ARRAY[increaseBrightnessIndex_]);
390 IAM_LOGI("increase brightness index %{public}u value %{public}u", increaseBrightnessIndex_,
391 INCREASE_BRIGHTNESS_ARRAY[increaseBrightnessIndex_]);
392 timer_.Unregister(currTimerId_);
393 currTimerId_ = timer_.Register(timeCallback, increaseBrightnessInterval_, true);
394 }
395 increaseBrightnessIndex_++;
396 }
397 }
398
EndProcess()399 void ScreenBrightnessTask::EndProcess()
400 {
401 IAM_LOGI("start");
402 timer_.Unregister(currTimerId_);
403 UnsubscribeSensor();
404 RestoreScreenBrightness();
405 }
406
RegisterDestructCallback(DestructCallback destructCallback)407 void ScreenBrightnessTask::RegisterDestructCallback(DestructCallback destructCallback)
408 {
409 destructCallback_ = destructCallback;
410 }
411
GetScreenBrightnessTask()412 __attribute__((visibility("default"))) std::shared_ptr<IScreenBrightnessTask> GetScreenBrightnessTask()
413 {
414 return Common::MakeShared<ScreenBrightnessTask>();
415 }
416 } // namespace FaceAuth
417 } // namespace UserIam
418 } // namespace OHOS