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