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 
36 namespace android {
37 namespace Hwc2 {
38 
39 PowerAdvisor::~PowerAdvisor() = default;
40 
41 namespace impl {
42 
43 namespace V1_0 = android::hardware::power::V1_0;
44 namespace V1_3 = android::hardware::power::V1_3;
45 using V1_3::PowerHint;
46 
47 using android::hardware::power::Boost;
48 using android::hardware::power::IPower;
49 using android::hardware::power::Mode;
50 using base::GetIntProperty;
51 using scheduler::OneShotTimer;
52 
53 PowerAdvisor::~PowerAdvisor() = default;
54 
55 namespace {
getUpdateTimeout()56 int32_t getUpdateTimeout() {
57     // Default to a timeout of 80ms if nothing else is specified
58     static int32_t timeout = sysprop::display_update_imminent_timeout_ms(80);
59     return timeout;
60 }
61 
62 } // namespace
63 
PowerAdvisor()64 PowerAdvisor::PowerAdvisor()
65       : mUseUpdateImminentTimer(getUpdateTimeout() > 0),
66         mUpdateImminentTimer(
67                 OneShotTimer::Interval(getUpdateTimeout()),
68                 /* resetCallback */ [this] { mSendUpdateImminent.store(false); },
__anon9e6cd5400302null69                 /* timeoutCallback */ [this] { mSendUpdateImminent.store(true); }) {
70     if (mUseUpdateImminentTimer) {
71         mUpdateImminentTimer.start();
72     }
73 }
74 
onBootFinished()75 void PowerAdvisor::onBootFinished() {
76     mBootFinished.store(true);
77 }
78 
setExpensiveRenderingExpected(DisplayId displayId,bool expected)79 void PowerAdvisor::setExpensiveRenderingExpected(DisplayId displayId, bool expected) {
80     if (expected) {
81         mExpensiveDisplays.insert(displayId);
82     } else {
83         mExpensiveDisplays.erase(displayId);
84     }
85 
86     const bool expectsExpensiveRendering = !mExpensiveDisplays.empty();
87     if (mNotifiedExpensiveRendering != expectsExpensiveRendering) {
88         std::lock_guard lock(mPowerHalMutex);
89         HalWrapper* const halWrapper = getPowerHal();
90         if (halWrapper == nullptr) {
91             return;
92         }
93 
94         if (!halWrapper->setExpensiveRendering(expectsExpensiveRendering)) {
95             // The HAL has become unavailable; attempt to reconnect later
96             mReconnectPowerHal = true;
97             return;
98         }
99 
100         mNotifiedExpensiveRendering = expectsExpensiveRendering;
101     }
102 }
103 
notifyDisplayUpdateImminent()104 void PowerAdvisor::notifyDisplayUpdateImminent() {
105     // Only start sending this notification once the system has booted so we don't introduce an
106     // early-boot dependency on Power HAL
107     if (!mBootFinished.load()) {
108         return;
109     }
110 
111     if (mSendUpdateImminent.load()) {
112         std::lock_guard lock(mPowerHalMutex);
113         HalWrapper* const halWrapper = getPowerHal();
114         if (halWrapper == nullptr) {
115             return;
116         }
117 
118         if (!halWrapper->notifyDisplayUpdateImminent()) {
119             // The HAL has become unavailable; attempt to reconnect later
120             mReconnectPowerHal = true;
121             return;
122         }
123     }
124 
125     if (mUseUpdateImminentTimer) {
126         mUpdateImminentTimer.reset();
127     }
128 }
129 
130 class HidlPowerHalWrapper : public PowerAdvisor::HalWrapper {
131 public:
HidlPowerHalWrapper(sp<V1_3::IPower> powerHal)132     HidlPowerHalWrapper(sp<V1_3::IPower> powerHal) : mPowerHal(std::move(powerHal)) {}
133 
134     ~HidlPowerHalWrapper() override = default;
135 
connect()136     static std::unique_ptr<HalWrapper> connect() {
137         // Power HAL 1.3 is not guaranteed to be available, thus we need to query
138         // Power HAL 1.0 first and try to cast it to Power HAL 1.3.
139         sp<V1_3::IPower> powerHal = nullptr;
140         sp<V1_0::IPower> powerHal_1_0 = V1_0::IPower::getService();
141         if (powerHal_1_0 != nullptr) {
142             // Try to cast to Power HAL 1.3
143             powerHal = V1_3::IPower::castFrom(powerHal_1_0);
144             if (powerHal == nullptr) {
145                 ALOGW("No Power HAL 1.3 service in system, disabling PowerAdvisor");
146             } else {
147                 ALOGI("Loaded Power HAL 1.3 service");
148             }
149         } else {
150             ALOGW("No Power HAL found, disabling PowerAdvisor");
151         }
152 
153         if (powerHal == nullptr) {
154             return nullptr;
155         }
156 
157         return std::make_unique<HidlPowerHalWrapper>(std::move(powerHal));
158     }
159 
setExpensiveRendering(bool enabled)160     bool setExpensiveRendering(bool enabled) override {
161         ALOGV("HIDL setExpensiveRendering %s", enabled ? "T" : "F");
162         auto ret = mPowerHal->powerHintAsync_1_3(PowerHint::EXPENSIVE_RENDERING, enabled);
163         return ret.isOk();
164     }
165 
notifyDisplayUpdateImminent()166     bool notifyDisplayUpdateImminent() override {
167         // Power HAL 1.x doesn't have a notification for this
168         ALOGV("HIDL notifyUpdateImminent received but can't send");
169         return true;
170     }
171 
172 private:
173     const sp<V1_3::IPower> mPowerHal = nullptr;
174 };
175 
176 class AidlPowerHalWrapper : public PowerAdvisor::HalWrapper {
177 public:
AidlPowerHalWrapper(sp<IPower> powerHal)178     AidlPowerHalWrapper(sp<IPower> powerHal) : mPowerHal(std::move(powerHal)) {
179         auto ret = mPowerHal->isModeSupported(Mode::EXPENSIVE_RENDERING, &mHasExpensiveRendering);
180         if (!ret.isOk()) {
181             mHasExpensiveRendering = false;
182         }
183 
184         ret = mPowerHal->isBoostSupported(Boost::DISPLAY_UPDATE_IMMINENT,
185                                           &mHasDisplayUpdateImminent);
186         if (!ret.isOk()) {
187             mHasDisplayUpdateImminent = false;
188         }
189     }
190 
191     ~AidlPowerHalWrapper() override = default;
192 
connect()193     static std::unique_ptr<HalWrapper> connect() {
194         // This only waits if the service is actually declared
195         sp<IPower> powerHal = waitForVintfService<IPower>();
196         if (powerHal == nullptr) {
197             return nullptr;
198         }
199         ALOGI("Loaded AIDL Power HAL service");
200 
201         return std::make_unique<AidlPowerHalWrapper>(std::move(powerHal));
202     }
203 
setExpensiveRendering(bool enabled)204     bool setExpensiveRendering(bool enabled) override {
205         ALOGV("AIDL setExpensiveRendering %s", enabled ? "T" : "F");
206         if (!mHasExpensiveRendering) {
207             ALOGV("Skipped sending EXPENSIVE_RENDERING because HAL doesn't support it");
208             return true;
209         }
210 
211         auto ret = mPowerHal->setMode(Mode::EXPENSIVE_RENDERING, enabled);
212         return ret.isOk();
213     }
214 
notifyDisplayUpdateImminent()215     bool notifyDisplayUpdateImminent() override {
216         ALOGV("AIDL notifyDisplayUpdateImminent");
217         if (!mHasDisplayUpdateImminent) {
218             ALOGV("Skipped sending DISPLAY_UPDATE_IMMINENT because HAL doesn't support it");
219             return true;
220         }
221 
222         auto ret = mPowerHal->setBoost(Boost::DISPLAY_UPDATE_IMMINENT, 0);
223         return ret.isOk();
224     }
225 
226 private:
227     const sp<IPower> mPowerHal = nullptr;
228     bool mHasExpensiveRendering = false;
229     bool mHasDisplayUpdateImminent = false;
230 };
231 
getPowerHal()232 PowerAdvisor::HalWrapper* PowerAdvisor::getPowerHal() {
233     static std::unique_ptr<HalWrapper> sHalWrapper = nullptr;
234     static bool sHasHal = true;
235 
236     if (!sHasHal) {
237         return nullptr;
238     }
239 
240     // If we used to have a HAL, but it stopped responding, attempt to reconnect
241     if (mReconnectPowerHal) {
242         sHalWrapper = nullptr;
243         mReconnectPowerHal = false;
244     }
245 
246     if (sHalWrapper != nullptr) {
247         return sHalWrapper.get();
248     }
249 
250     // First attempt to connect to the AIDL Power HAL
251     sHalWrapper = AidlPowerHalWrapper::connect();
252 
253     // If that didn't succeed, attempt to connect to the HIDL Power HAL
254     if (sHalWrapper == nullptr) {
255         sHalWrapper = HidlPowerHalWrapper::connect();
256     }
257 
258     // If we make it to this point and still don't have a HAL, it's unlikely we
259     // will, so stop trying
260     if (sHalWrapper == nullptr) {
261         sHasHal = false;
262     }
263 
264     return sHalWrapper.get();
265 }
266 
267 } // namespace impl
268 } // namespace Hwc2
269 } // namespace android
270