1 /*
2  * Copyright (c) 2021-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_controller.h"
17 
18 #include "delayed_sp_singleton.h"
19 #include "display_common.h"
20 #include "display_log.h"
21 #include "display_param_helper.h"
22 #include "display_power_mgr_service.h"
23 #include "display_setting_helper.h"
24 #include "ffrt_utils.h"
25 #include "refbase.h"
26 #include "setting_provider.h"
27 #include "system_ability_definition.h"
28 #include "power_state_machine_info.h"
29 
30 using namespace std;
31 using namespace OHOS::PowerMgr;
32 
33 namespace OHOS {
34 namespace DisplayPowerMgr {
35 namespace {
36 FFRTQueue g_queue("screen_controller");
37 FFRTHandle g_cancelBoostTaskHandle;
38 }
39 
ScreenController(uint32_t displayId)40 ScreenController::ScreenController(uint32_t displayId)
41 {
42     DISPLAY_HILOGI(COMP_SVC, "ScreenController created for displayId=%{public}u", displayId);
43     action_ = make_shared<ScreenAction>(displayId);
44     state_ = action_->GetDisplayState();
45 
46     string name = "BrightnessController_" + to_string(displayId);
47     if (animateCallback_ == nullptr) {
48         animateCallback_ = make_shared<AnimateCallbackImpl>([this](uint32_t brightness) {
49             SetSettingBrightness(brightness);
50         });
51     }
52     animator_ = make_shared<GradualAnimator>(name, animateCallback_);
53 }
54 
AnimateCallbackImpl(std::function<void(uint32_t)> callback)55 ScreenController::AnimateCallbackImpl::AnimateCallbackImpl(std::function<void(uint32_t)> callback) : callback_(callback)
56 {
57 }
58 
OnStart()59 void ScreenController::AnimateCallbackImpl::OnStart()
60 {
61     DISPLAY_HILOGD(FEAT_BRIGHTNESS, "ScreenAnimatorCallback onStart");
62 }
63 
OnChanged(uint32_t currentValue)64 void ScreenController::AnimateCallbackImpl::OnChanged(uint32_t currentValue)
65 {
66     DISPLAY_HILOGD(FEAT_BRIGHTNESS, "OnChanged, no Update brightness");
67 }
68 
OnEnd()69 void ScreenController::AnimateCallbackImpl::OnEnd()
70 {
71     DISPLAY_HILOGD(FEAT_BRIGHTNESS, "ScreenAnimatorCallback OnEnd");
72 }
73 
DiscountBrightness(double discount)74 void ScreenController::AnimateCallbackImpl::DiscountBrightness(double discount)
75 {
76     discount_ = discount;
77 }
78 
GetState()79 DisplayState ScreenController::GetState()
80 {
81     return state_;
82 }
83 
SetDelayOffState()84 DisplayState ScreenController::SetDelayOffState()
85 {
86     DISPLAY_HILOGI(COMP_SVC, "Set the dispaly state is DELAY OFF when overriding display off delay");
87     state_ = DisplayState::DISPLAY_DELAY_OFF;
88     return state_;
89 }
90 
SetOnState()91 DisplayState ScreenController::SetOnState()
92 {
93     DISPLAY_HILOGI(COMP_SVC, "Set the dispaly state is ON after overriding display on delay");
94     state_ = DisplayState::DISPLAY_ON;
95     return state_;
96 }
97 
UpdateState(DisplayState state, uint32_t reason)98 bool ScreenController::UpdateState(DisplayState state, uint32_t reason)
99 {
100     DISPLAY_HILOGI(FEAT_STATE, "[UL_POWER] UpdateState, state=%{public}u, current state=%{public}u, reason=%{public}u",
101                    static_cast<uint32_t>(state), static_cast<uint32_t>(state_), reason);
102     if (reason != static_cast<uint32_t>
103         (PowerMgr::StateChangeReason::STATE_CHANGE_REASON_PRE_BRIGHT_AUTH_FAIL_SCREEN_OFF)) {
104         RETURN_IF_WITH_RET(state == state_, true);
105     }
106     if (state == DisplayState::DISPLAY_DIM && state_ == DisplayState::DISPLAY_OFF) {
107         DISPLAY_HILOGI(FEAT_STATE, "Not allowed to set DIM state.");
108         return true;
109     }
110     switch (state) {
111         case DisplayState::DISPLAY_ON:
112             if (state_ == DisplayState::DISPLAY_DIM) {
113                 break;
114             }
115             [[fallthrough]];
116         case DisplayState::DISPLAY_OFF: {
117             if (action_->EnableSkipSetDisplayState(reason)) {
118                 OnStateChanged(state, reason);
119             } else {
120                 function<void(DisplayState)> callback =
121                     bind(&ScreenController::OnStateChanged, this, placeholders::_1, reason);
122                 bool ret = action_->SetDisplayState(state, callback);
123                 if (!ret) {
124                     DISPLAY_HILOGW(FEAT_STATE, "Update display state failed, state=%{public}d", state);
125                     return ret;
126                 }
127             }
128             break;
129         }
130         case DisplayState::DISPLAY_DIM:
131         case DisplayState::DISPLAY_SUSPEND:
132         default:
133             break;
134     }
135 
136     if (IsNeedSkipNextProc(reason)) {
137         DISPLAY_HILOGI(FEAT_STATE,
138             "Need interrupt next process when updating state because of reason = %{public}d", reason);
139         return false;
140     }
141 
142     lock_guard lock(mutexState_);
143     state_ = state;
144     stateChangeReason_ = reason;
145 
146     DISPLAY_HILOGI(FEAT_STATE, "[UL_POWER] Update screen state to %{public}u", state);
147     return true;
148 }
149 
IsScreenOn()150 bool ScreenController::IsScreenOn()
151 {
152     lock_guard lock(mutexState_);
153     return (state_ == DisplayState::DISPLAY_ON || state_ == DisplayState::DISPLAY_DIM);
154 }
155 
SetBrightness(uint32_t value, uint32_t gradualDuration, bool continuous)156 bool ScreenController::SetBrightness(uint32_t value, uint32_t gradualDuration, bool continuous)
157 {
158     if (CanSetBrightness()) { // not set brightness
159         DISPLAY_HILOGW(FEAT_BRIGHTNESS, "Cannot set brightness, ignore the change,"\
160             "cachedSettingBrightness_ %{public}u -> %{public}u", cachedSettingBrightness_.load(), value);
161         cachedSettingBrightness_ = value;
162         return false;
163     }
164     return UpdateBrightness(value, gradualDuration, !continuous);
165 }
166 
GetBrightness()167 uint32_t ScreenController::GetBrightness()
168 {
169     return GetSettingBrightness();
170 }
171 
GetDeviceBrightness()172 uint32_t ScreenController::GetDeviceBrightness()
173 {
174     return action_->GetBrightness();
175 }
176 
GetCachedSettingBrightness() const177 uint32_t ScreenController::GetCachedSettingBrightness() const
178 {
179     return cachedSettingBrightness_;
180 }
181 
DiscountBrightness(double discount, uint32_t gradualDuration)182 bool ScreenController::DiscountBrightness(double discount, uint32_t gradualDuration)
183 {
184     if (!CanDiscountBrightness()) {
185         DISPLAY_HILOGW(FEAT_BRIGHTNESS, "Cannot discount brightness, ignore the change");
186         return false;
187     }
188     DISPLAY_HILOGI(FEAT_BRIGHTNESS, "Discount brightness, discount=%{public}lf", discount);
189     discount_ = discount;
190     if (animateCallback_) {
191         animateCallback_->DiscountBrightness(discount);
192     }
193     uint32_t screenOnBrightness = GetScreenOnBrightness();
194     return UpdateBrightness(screenOnBrightness, gradualDuration);
195 }
196 
OverrideBrightness(uint32_t value, uint32_t gradualDuration)197 bool ScreenController::OverrideBrightness(uint32_t value, uint32_t gradualDuration)
198 {
199     if (!CanOverrideBrightness()) {
200         DISPLAY_HILOGW(FEAT_BRIGHTNESS, "Cannot override brightness, ignore the change");
201         return false;
202     }
203     DISPLAY_HILOGI(FEAT_BRIGHTNESS, "Override brightness, value=%{public}u", value);
204     if (!isBrightnessOverridden_) {
205         isBrightnessOverridden_ = true;
206     }
207     overriddenBrightness_ = value;
208     return UpdateBrightness(value, gradualDuration);
209 }
210 
RestoreBrightness(uint32_t gradualDuration)211 bool ScreenController::RestoreBrightness(uint32_t gradualDuration)
212 {
213     if (!IsBrightnessOverridden()) {
214         DISPLAY_HILOGD(FEAT_BRIGHTNESS, "Brightness is not override, no need to restore");
215         return false;
216     }
217     isBrightnessOverridden_ = false;
218     return UpdateBrightness(cachedSettingBrightness_, gradualDuration, true);
219 }
220 
IsBrightnessOverridden() const221 bool ScreenController::IsBrightnessOverridden() const
222 {
223     return isBrightnessOverridden_;
224 }
225 
BoostBrightness(uint32_t timeoutMs, uint32_t gradualDuration)226 bool ScreenController::BoostBrightness(uint32_t timeoutMs, uint32_t gradualDuration)
227 {
228     if (!CanBoostBrightness()) {
229         DISPLAY_HILOGW(FEAT_BRIGHTNESS, "Cannot boost brightness, ignore the change");
230         return false;
231     }
232     bool ret = true;
233     if (!isBrightnessBoosted_) {
234         uint32_t maxBrightness = DisplayParamHelper::GetMaxBrightness();
235         DISPLAY_HILOGI(FEAT_BRIGHTNESS, "Boost brightness, maxBrightness: %{public}d", maxBrightness);
236         isBrightnessBoosted_ = true;
237         ret = UpdateBrightness(maxBrightness, gradualDuration);
238     }
239 
240     // If boost multi-times, we will resend the cancel boost event.
241     FFRTUtils::CancelTask(g_cancelBoostTaskHandle, g_queue);
242     FFRTTask task = [this, gradualDuration] { this->CancelBoostBrightness(gradualDuration); };
243     g_cancelBoostTaskHandle = FFRTUtils::SubmitDelayTask(task, timeoutMs, g_queue);
244     DISPLAY_HILOGD(FEAT_BRIGHTNESS, "BoostBrightness update timeout=%{public}u, ret=%{public}d", timeoutMs, ret);
245     return ret;
246 }
247 
CancelBoostBrightness(uint32_t gradualDuration)248 bool ScreenController::CancelBoostBrightness(uint32_t gradualDuration)
249 {
250     DISPLAY_HILOGD(FEAT_BRIGHTNESS, "Cancel boost brightness");
251     if (!IsBrightnessBoosted()) {
252         DISPLAY_HILOGD(FEAT_BRIGHTNESS, "Brightness is not boost, no need to restore");
253         return false;
254     }
255     FFRTUtils::CancelTask(g_cancelBoostTaskHandle, g_queue);
256     isBrightnessBoosted_ = false;
257     return UpdateBrightness(cachedSettingBrightness_, gradualDuration, true);
258 }
259 
IsBrightnessBoosted() const260 bool ScreenController::IsBrightnessBoosted() const
261 {
262     return isBrightnessBoosted_;
263 }
264 
IsNeedSkipNextProc(uint32_t reason)265 bool ScreenController::IsNeedSkipNextProc(uint32_t reason)
266 {
267     if (reason == static_cast<uint32_t>(PowerMgr::StateChangeReason::STATE_CHANGE_REASON_PRE_BRIGHT) ||
268         reason == static_cast<uint32_t>(
269             PowerMgr::StateChangeReason::STATE_CHANGE_REASON_PRE_BRIGHT_AUTH_FAIL_SCREEN_OFF)) {
270         return true;
271     }
272     return false;
273 }
274 
OnStateChanged(DisplayState state, uint32_t reason)275 void ScreenController::OnStateChanged(DisplayState state, uint32_t reason)
276 {
277     auto pms = DelayedSpSingleton<DisplayPowerMgrService>::GetInstance();
278     if (pms == nullptr) {
279         DISPLAY_HILOGW(FEAT_STATE, "pms is nullptr");
280         return;
281     }
282     DISPLAY_HILOGI(FEAT_BRIGHTNESS, "[UL_POWER] OnStateChanged state=%{public}d, reason=%{public}u",
283         static_cast<int>(state), reason);
284     bool ret = action_->SetDisplayPower(state, reason);
285     if (reason == static_cast<uint32_t>(PowerMgr::StateChangeReason::STATE_CHANGE_REASON_PRE_BRIGHT)) {
286         DISPLAY_HILOGI(FEAT_BRIGHTNESS, "No need to set brightness, reason=%{public}d", reason);
287         return;
288     }
289     if (state == DisplayState::DISPLAY_ON) {
290         pms->SetScreenOnBrightness();
291         // Restore the brightness before screen off
292         uint32_t screenOnBrightness = GetScreenOnBrightness();
293         DISPLAY_HILOGI(FEAT_BRIGHTNESS, "OnStateChanged set screenOnBrightness=%{public}d", screenOnBrightness);
294     }
295     if (state == DisplayState::DISPLAY_SUSPEND) {
296         state = DisplayState::DISPLAY_OFF;
297     }
298     if (ret) {
299         pms->NotifyStateChangeCallback(action_->GetDisplayId(), state, reason);
300     }
301 }
302 
CanSetBrightness()303 bool ScreenController::CanSetBrightness()
304 {
305     bool isScreenOn = IsScreenOn();
306     bool isOverridden = IsBrightnessOverridden();
307     bool isBoosted = IsBrightnessBoosted();
308     DISPLAY_HILOGD(FEAT_BRIGHTNESS, "isScreenOn: %{public}d, isOverridden: %{public}d, isBoosted: %{public}d",
309         isScreenOn, isOverridden, isBoosted);
310     return isScreenOn && !isOverridden && !isBoosted;
311 }
312 
CanDiscountBrightness()313 bool ScreenController::CanDiscountBrightness()
314 {
315     return IsScreenOn();
316 }
317 
CanOverrideBrightness()318 bool ScreenController::CanOverrideBrightness()
319 {
320     return IsScreenOn() && !IsBrightnessBoosted();
321 }
322 
CanBoostBrightness()323 bool ScreenController::CanBoostBrightness()
324 {
325     return IsScreenOn() && !IsBrightnessOverridden();
326 }
327 
UpdateBrightness(uint32_t value, uint32_t gradualDuration, bool updateSetting)328 bool ScreenController::UpdateBrightness(uint32_t value, uint32_t gradualDuration, bool updateSetting)
329 {
330     DISPLAY_HILOGI(FEAT_BRIGHTNESS, "Update brightness, value=%{public}u, discount=%{public}lf,"\
331                    " duration=%{public}u, updateSetting=%{public}d", value, discount_, gradualDuration, updateSetting);
332 
333     if (animator_->IsAnimating()) {
334         animator_->StopAnimation();
335     }
336     if (gradualDuration > 0) {
337         animator_->StartAnimation(GetSettingBrightness(), value, gradualDuration);
338         return true;
339     }
340     auto brightness = DisplayPowerMgrService::GetSafeBrightness(static_cast<uint32_t>(value * discount_));
341     bool isSucc = action_->SetBrightness(brightness);
342     DISPLAY_HILOGD(FEAT_BRIGHTNESS, "Updated brightness is %{public}s, brightness: %{public}u",
343                    isSucc ? "succ" : "failed", brightness);
344     if (isSucc && updateSetting) {
345         FFRTUtils::SubmitTask([this, value] { this->SetSettingBrightness(value); });
346     }
347     return isSucc;
348 }
349 
GetSettingBrightness(const std::string& key) const350 uint32_t ScreenController::GetSettingBrightness(const std::string& key) const
351 {
352     uint32_t settingBrightness;
353     auto ret = DisplaySettingHelper::GetSettingBrightness(settingBrightness, key);
354     if (ret != ERR_OK) {
355         DISPLAY_HILOGW(FEAT_BRIGHTNESS,
356             "get setting brightness failed, return cachedBrightness_=%{public}u, key=%{public}s, ret=%{public}d",
357             cachedSettingBrightness_.load(), key.c_str(), ret);
358         return cachedSettingBrightness_;
359     }
360     return settingBrightness;
361 }
362 
SetSettingBrightness(uint32_t value)363 void ScreenController::SetSettingBrightness(uint32_t value)
364 {
365     DisplaySettingHelper::SetSettingBrightness(value);
366     cachedSettingBrightness_ = value;
367     DISPLAY_HILOGD(FEAT_BRIGHTNESS, "set setting brightness=%{public}u", value);
368 }
369 
GetScreenOnBrightness() const370 uint32_t ScreenController::GetScreenOnBrightness() const
371 {
372     if (IsBrightnessBoosted()) {
373         DISPLAY_HILOGD(FEAT_BRIGHTNESS, "Brightness is boosted, return max brightness");
374         return DisplayParamHelper::GetMaxBrightness();
375     } else if (IsBrightnessOverridden()) {
376         DISPLAY_HILOGD(FEAT_BRIGHTNESS, "Brightness is overridden, return overridden brightness=%{public}u",
377                        overriddenBrightness_);
378         return overriddenBrightness_;
379     } else {
380         return GetSettingBrightness();
381     }
382 }
383 
RegisterSettingBrightnessObserver()384 void ScreenController::RegisterSettingBrightnessObserver()
385 {
386     SettingObserver::UpdateFunc updateFunc = [&](const std::string& key) { BrightnessSettingUpdateFunc(key); };
387     DisplaySettingHelper::RegisterSettingBrightnessObserver(updateFunc);
388 }
389 
BrightnessSettingUpdateFunc(const string& key)390 void ScreenController::BrightnessSettingUpdateFunc(const string& key)
391 {
392     if (animator_->IsAnimating() || !CanSetBrightness()) {
393         return;
394     }
395     uint32_t settingBrightness = GetSettingBrightness(key);
396     if (cachedSettingBrightness_ == settingBrightness) {
397         DISPLAY_HILOGD(FEAT_BRIGHTNESS, "no need to set setting brightness");
398         return;
399     }
400     DISPLAY_HILOGI(FEAT_BRIGHTNESS, "noset setting brightness updated, brightness %{public}u -> %{public}u",
401                    cachedSettingBrightness_.load(), settingBrightness);
402     cachedSettingBrightness_ = settingBrightness;
403 }
404 
UnregisterSettingBrightnessObserver()405 void ScreenController::UnregisterSettingBrightnessObserver()
406 {
407     DisplaySettingHelper::UnregisterSettingBrightnessObserver();
408 }
409 
GetDiscount() const410 double ScreenController::GetDiscount() const
411 {
412     return discount_;
413 }
414 
GetAnimationUpdateTime() const415 uint32_t ScreenController::GetAnimationUpdateTime() const
416 {
417     return animator_->GetAnimationUpdateTime();
418 }
419 
SetCoordinated(bool coordinated)420 void ScreenController::SetCoordinated(bool coordinated)
421 {
422     action_->SetCoordinated(coordinated);
423 }
424 } // namespace DisplayPowerMgr
425 } // namespace OHOS
426