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