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 "brightness_dimming.h"
17 
18 #include "brightness_dimming_callback.h"
19 #include "display_log.h"
20 #include "ffrt_utils.h"
21 
22 namespace OHOS {
23 namespace DisplayPowerMgr {
24 using namespace PowerMgr;
25 namespace {
26 FFRTHandle g_animatorTaskHandle;
27 }
28 
BrightnessDimming(const std::string & name,std::shared_ptr<BrightnessDimmingCallback> & callback)29 BrightnessDimming::BrightnessDimming(const std::string& name, std::shared_ptr<BrightnessDimmingCallback>& callback)
30     : mName(name), mCallback(callback)
31 {
32     mFromBrightness = 0;
33     mToBrightness = 0;
34     mCurrentBrightness = 0;
35     mDuration = 0;
36     mTotalSteps = 0;
37     mStride = 0;
38     mUpdateTime = DEFAULT_UPDATE_TIME;
39 }
40 
Init()41 bool BrightnessDimming::Init()
42 {
43     mQueue = std::make_shared<FFRTQueue> ("brightness_animator_queue");
44     if (mQueue == nullptr) {
45         return false;
46     }
47     return true;
48 }
49 
Reset()50 void BrightnessDimming::Reset()
51 {
52     DISPLAY_HILOGI(FEAT_BRIGHTNESS, "start dimming queue");
53     if (mQueue) {
54         mQueue.reset();
55         g_animatorTaskHandle = nullptr;
56         DISPLAY_HILOGI(FEAT_BRIGHTNESS, "destruct dimming_queue");
57     }
58 }
59 
StartDimming(uint32_t from,uint32_t to,uint32_t duration)60 void BrightnessDimming::StartDimming(uint32_t from, uint32_t to, uint32_t duration)
61 {
62     if (mDimming) {
63         DISPLAY_HILOGI(FEAT_BRIGHTNESS, "animation is running, no need to start again, from=%{public}u, "\
64             " to=%{public}u, duration=%{public}u", from, to, duration);
65         return;
66     }
67     DISPLAY_HILOGI(FEAT_BRIGHTNESS, "animation from=%{public}u, to=%{public}u, duration=%{public}u",
68         from, to, duration);
69     if (mCallback == nullptr) {
70         DISPLAY_HILOGW(FEAT_BRIGHTNESS, "mCallback is nullptr");
71         return;
72     }
73     mFromBrightness = from;
74     mToBrightness = to;
75     mCurrentBrightness = mFromBrightness.load();
76     mDuration = duration;
77     mTotalSteps = mDuration / mUpdateTime;
78     if (mTotalSteps < 1) {
79         mTotalSteps = 1;
80     }
81     int32_t changeBrightness = static_cast<int32_t>(mToBrightness) - static_cast<int32_t>(mFromBrightness);
82     if (changeBrightness == 0) {
83         return;
84     }
85     mStride = changeBrightness / static_cast<int32_t>(mTotalSteps);
86     if (abs(mStride) < STRIDE_ABSOLUTE_MIN) {
87         mStride = (changeBrightness / abs(changeBrightness)) * STRIDE_ABSOLUTE_MIN;
88     }
89     DISPLAY_HILOGI(FEAT_BRIGHTNESS, "animation orig mTotalSteps=%{public}d", static_cast<int32_t>(mTotalSteps));
90     if (mTotalSteps > 1 && abs(mStride) >= 1) {
91         mTotalSteps = static_cast<uint32_t>(static_cast<uint32_t>(abs(changeBrightness)) -
92             static_cast<uint32_t>(abs(mStride)) * mTotalSteps) / static_cast<uint32_t>(abs(mStride)) + mTotalSteps;
93         DISPLAY_HILOGI(FEAT_BRIGHTNESS, "animation update mTotalSteps=%{public}d", static_cast<int32_t>(mTotalSteps));
94     }
95     mCurrentStep = 0;
96     mDimming = true;
97     FFRTTask task = [this] { this->NextStep(); };
98     g_animatorTaskHandle = FFRTUtils::SubmitDelayTask(task, mUpdateTime, mQueue);
99 }
100 
StopDimming()101 void BrightnessDimming::StopDimming()
102 {
103     mDimming = false;
104     if (g_animatorTaskHandle == nullptr) {
105         DISPLAY_HILOGW(FEAT_BRIGHTNESS, "handle is nullptr");
106     } else {
107         FFRTUtils::CancelTask(g_animatorTaskHandle, mQueue);
108     }
109     if (mCallback == nullptr) {
110         DISPLAY_HILOGW(FEAT_BRIGHTNESS, "Callback is nullptr");
111         return;
112     }
113     mCallback->OnEnd();
114     DISPLAY_HILOGI(FEAT_BRIGHTNESS, "animation stopped");
115 }
116 
IsDimming() const117 bool BrightnessDimming::IsDimming() const
118 {
119     return mDimming;
120 }
121 
GetDimmingUpdateTime() const122 uint32_t BrightnessDimming::GetDimmingUpdateTime() const
123 {
124     return mUpdateTime;
125 }
126 
NextStep()127 void BrightnessDimming::NextStep()
128 {
129     if (!mDimming) {
130         DISPLAY_HILOGW(FEAT_BRIGHTNESS, "is not animating, return");
131         return;
132     }
133     if (mCallback == nullptr) {
134         DISPLAY_HILOGW(FEAT_BRIGHTNESS, "Callback is nullptr");
135         return;
136     }
137     mCurrentStep++;
138     if (mCurrentStep == 1) {
139         mCallback->OnStart();
140     }
141     if (mCurrentStep <= mTotalSteps) {
142         uint32_t nextBrightness = mCurrentBrightness + static_cast<uint32_t>(mStride);
143         bool isOutRange = (mStride > 0 ? (nextBrightness >= mToBrightness) : (nextBrightness <= mToBrightness));
144         if (isOutRange) {
145             DISPLAY_HILOGI(FEAT_BRIGHTNESS, "next step brightness is out range, brightness=%{public}u",
146                 nextBrightness);
147             mCurrentBrightness = mToBrightness.load();
148             mCallback->OnChanged(mCurrentBrightness);
149             mCallback->OnEnd();
150             mDimming = false;
151         } else {
152             DISPLAY_HILOGD(FEAT_BRIGHTNESS, "next step last mCurrentBrightness=%{public}u, next=%{public}d",
153                 mCurrentBrightness.load(), nextBrightness);
154             mCurrentBrightness = nextBrightness;
155             mCallback->OnChanged(mCurrentBrightness);
156             FFRTTask task = [this] { this->NextStep(); };
157             g_animatorTaskHandle = FFRTUtils::SubmitDelayTask(task, mUpdateTime, mQueue);
158         }
159     } else {
160         DISPLAY_HILOGD(FEAT_BRIGHTNESS, "next step last mCurrentBrightness=%{public}u, mToBrightness=%{public}u",
161             mCurrentBrightness.load(), mToBrightness.load());
162         mCurrentBrightness = mToBrightness.load();
163         mCallback->OnChanged(mCurrentBrightness);
164         mCallback->OnEnd();
165         mDimming = false;
166     }
167     DISPLAY_HILOGD(FEAT_BRIGHTNESS, "animating next step, step=%{public}u, brightness=%{public}u, stride=%{public}d",
168         mCurrentStep.load(), mCurrentBrightness.load(), mStride.load());
169 }
170 } // namespace DisplayPowerMgr
171 } // namespace OHOS
172