1 /*
2  * Copyright 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //#define LOG_NDEBUG 0
18 
19 #undef LOG_TAG
20 #define LOG_TAG "PowerAdvisor"
21 
22 #include <cinttypes>
23 
24 #include <android-base/properties.h>
25 #include <utils/Log.h>
26 #include <utils/Mutex.h>
27 
28 #include <android/hardware/power/1.3/IPower.h>
29 #include <android/hardware/power/IPower.h>
30 #include <binder/IServiceManager.h>
31 
32 #include "../SurfaceFlingerProperties.h"
33 
34 #include "PowerAdvisor.h"
35 #include "SurfaceFlinger.h"
36 
37 namespace android {
38 namespace Hwc2 {
39 
40 PowerAdvisor::~PowerAdvisor() = default;
41 
42 namespace impl {
43 
44 namespace V1_0 = android::hardware::power::V1_0;
45 namespace V1_3 = android::hardware::power::V1_3;
46 using V1_3::PowerHint;
47 
48 using android::hardware::power::Boost;
49 using android::hardware::power::IPower;
50 using android::hardware::power::Mode;
51 using base::GetIntProperty;
52 using scheduler::OneShotTimer;
53 
54 PowerAdvisor::~PowerAdvisor() = default;
55 
56 namespace {
getUpdateTimeout()57 int32_t getUpdateTimeout() {
58     // Default to a timeout of 80ms if nothing else is specified
59     static int32_t timeout = sysprop::display_update_imminent_timeout_ms(80);
60     return timeout;
61 }
62 
63 } // namespace
64 
PowerAdvisor(SurfaceFlinger & flinger)65 PowerAdvisor::PowerAdvisor(SurfaceFlinger& flinger)
66       : mFlinger(flinger),
67         mUseScreenUpdateTimer(getUpdateTimeout() > 0),
68         mScreenUpdateTimer(
69                 "UpdateImminentTimer", OneShotTimer::Interval(getUpdateTimeout()),
70                 /* resetCallback */ [this] { mSendUpdateImminent.store(false); },
71                 /* timeoutCallback */
__anonb6262e2c0302null72                 [this] {
73                     mSendUpdateImminent.store(true);
74                     mFlinger.disableExpensiveRendering();
75                 }) {}
76 
init()77 void PowerAdvisor::init() {
78     // Defer starting the screen update timer until SurfaceFlinger finishes construction.
79     if (mUseScreenUpdateTimer) {
80         mScreenUpdateTimer.start();
81     }
82 }
83 
onBootFinished()84 void PowerAdvisor::onBootFinished() {
85     mBootFinished.store(true);
86 }
87 
setExpensiveRenderingExpected(DisplayId displayId,bool expected)88 void PowerAdvisor::setExpensiveRenderingExpected(DisplayId displayId, bool expected) {
89     if (expected) {
90         mExpensiveDisplays.insert(displayId);
91     } else {
92         mExpensiveDisplays.erase(displayId);
93     }
94 
95     const bool expectsExpensiveRendering = !mExpensiveDisplays.empty();
96     if (mNotifiedExpensiveRendering != expectsExpensiveRendering) {
97         std::lock_guard lock(mPowerHalMutex);
98         HalWrapper* const halWrapper = getPowerHal();
99         if (halWrapper == nullptr) {
100             return;
101         }
102 
103         if (!halWrapper->setExpensiveRendering(expectsExpensiveRendering)) {
104             // The HAL has become unavailable; attempt to reconnect later
105             mReconnectPowerHal = true;
106             return;
107         }
108 
109         mNotifiedExpensiveRendering = expectsExpensiveRendering;
110     }
111 }
112 
notifyDisplayUpdateImminent()113 void PowerAdvisor::notifyDisplayUpdateImminent() {
114     // Only start sending this notification once the system has booted so we don't introduce an
115     // early-boot dependency on Power HAL
116     if (!mBootFinished.load()) {
117         return;
118     }
119 
120     if (mSendUpdateImminent.load()) {
121         std::lock_guard lock(mPowerHalMutex);
122         HalWrapper* const halWrapper = getPowerHal();
123         if (halWrapper == nullptr) {
124             return;
125         }
126 
127         if (!halWrapper->notifyDisplayUpdateImminent()) {
128             // The HAL has become unavailable; attempt to reconnect later
129             mReconnectPowerHal = true;
130             return;
131         }
132     }
133 
134     if (mUseScreenUpdateTimer) {
135         mScreenUpdateTimer.reset();
136     }
137 }
138 
139 class HidlPowerHalWrapper : public PowerAdvisor::HalWrapper {
140 public:
HidlPowerHalWrapper(sp<V1_3::IPower> powerHal)141     HidlPowerHalWrapper(sp<V1_3::IPower> powerHal) : mPowerHal(std::move(powerHal)) {}
142 
143     ~HidlPowerHalWrapper() override = default;
144 
connect()145     static std::unique_ptr<HalWrapper> connect() {
146         // Power HAL 1.3 is not guaranteed to be available, thus we need to query
147         // Power HAL 1.0 first and try to cast it to Power HAL 1.3.
148         sp<V1_3::IPower> powerHal = nullptr;
149         sp<V1_0::IPower> powerHal_1_0 = V1_0::IPower::getService();
150         if (powerHal_1_0 != nullptr) {
151             // Try to cast to Power HAL 1.3
152             powerHal = V1_3::IPower::castFrom(powerHal_1_0);
153             if (powerHal == nullptr) {
154                 ALOGW("No Power HAL 1.3 service in system, disabling PowerAdvisor");
155             } else {
156                 ALOGI("Loaded Power HAL 1.3 service");
157             }
158         } else {
159             ALOGW("No Power HAL found, disabling PowerAdvisor");
160         }
161 
162         if (powerHal == nullptr) {
163             return nullptr;
164         }
165 
166         return std::make_unique<HidlPowerHalWrapper>(std::move(powerHal));
167     }
168 
setExpensiveRendering(bool enabled)169     bool setExpensiveRendering(bool enabled) override {
170         ALOGV("HIDL setExpensiveRendering %s", enabled ? "T" : "F");
171         auto ret = mPowerHal->powerHintAsync_1_3(PowerHint::EXPENSIVE_RENDERING, enabled);
172         return ret.isOk();
173     }
174 
notifyDisplayUpdateImminent()175     bool notifyDisplayUpdateImminent() override {
176         // Power HAL 1.x doesn't have a notification for this
177         ALOGV("HIDL notifyUpdateImminent received but can't send");
178         return true;
179     }
180 
181 private:
182     const sp<V1_3::IPower> mPowerHal = nullptr;
183 };
184 
185 class AidlPowerHalWrapper : public PowerAdvisor::HalWrapper {
186 public:
AidlPowerHalWrapper(sp<IPower> powerHal)187     AidlPowerHalWrapper(sp<IPower> powerHal) : mPowerHal(std::move(powerHal)) {
188         auto ret = mPowerHal->isModeSupported(Mode::EXPENSIVE_RENDERING, &mHasExpensiveRendering);
189         if (!ret.isOk()) {
190             mHasExpensiveRendering = false;
191         }
192 
193         ret = mPowerHal->isBoostSupported(Boost::DISPLAY_UPDATE_IMMINENT,
194                                           &mHasDisplayUpdateImminent);
195         if (!ret.isOk()) {
196             mHasDisplayUpdateImminent = false;
197         }
198     }
199 
200     ~AidlPowerHalWrapper() override = default;
201 
connect()202     static std::unique_ptr<HalWrapper> connect() {
203         // This only waits if the service is actually declared
204         sp<IPower> powerHal = waitForVintfService<IPower>();
205         if (powerHal == nullptr) {
206             return nullptr;
207         }
208         ALOGI("Loaded AIDL Power HAL service");
209 
210         return std::make_unique<AidlPowerHalWrapper>(std::move(powerHal));
211     }
212 
setExpensiveRendering(bool enabled)213     bool setExpensiveRendering(bool enabled) override {
214         ALOGV("AIDL setExpensiveRendering %s", enabled ? "T" : "F");
215         if (!mHasExpensiveRendering) {
216             ALOGV("Skipped sending EXPENSIVE_RENDERING because HAL doesn't support it");
217             return true;
218         }
219 
220         auto ret = mPowerHal->setMode(Mode::EXPENSIVE_RENDERING, enabled);
221         return ret.isOk();
222     }
223 
notifyDisplayUpdateImminent()224     bool notifyDisplayUpdateImminent() override {
225         ALOGV("AIDL notifyDisplayUpdateImminent");
226         if (!mHasDisplayUpdateImminent) {
227             ALOGV("Skipped sending DISPLAY_UPDATE_IMMINENT because HAL doesn't support it");
228             return true;
229         }
230 
231         auto ret = mPowerHal->setBoost(Boost::DISPLAY_UPDATE_IMMINENT, 0);
232         return ret.isOk();
233     }
234 
235 private:
236     const sp<IPower> mPowerHal = nullptr;
237     bool mHasExpensiveRendering = false;
238     bool mHasDisplayUpdateImminent = false;
239 };
240 
getPowerHal()241 PowerAdvisor::HalWrapper* PowerAdvisor::getPowerHal() {
242     static std::unique_ptr<HalWrapper> sHalWrapper = nullptr;
243     static bool sHasHal = true;
244 
245     if (!sHasHal) {
246         return nullptr;
247     }
248 
249     // If we used to have a HAL, but it stopped responding, attempt to reconnect
250     if (mReconnectPowerHal) {
251         sHalWrapper = nullptr;
252         mReconnectPowerHal = false;
253     }
254 
255     if (sHalWrapper != nullptr) {
256         return sHalWrapper.get();
257     }
258 
259     // First attempt to connect to the AIDL Power HAL
260     sHalWrapper = AidlPowerHalWrapper::connect();
261 
262     // If that didn't succeed, attempt to connect to the HIDL Power HAL
263     if (sHalWrapper == nullptr) {
264         sHalWrapper = HidlPowerHalWrapper::connect();
265     }
266 
267     // If we make it to this point and still don't have a HAL, it's unlikely we
268     // will, so stop trying
269     if (sHalWrapper == nullptr) {
270         sHasHal = false;
271     }
272 
273     return sHalWrapper.get();
274 }
275 
276 } // namespace impl
277 } // namespace Hwc2
278 } // namespace android
279