blob: 1d8179c9ac1eb52084801a3eb1b1ccc4bd386f8d [file] [log] [blame]
Michael Wright1509a232018-06-21 02:50:34 +01001/*
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
Dan Stoza030fbc12020-02-19 15:32:01 -080017//#define LOG_NDEBUG 0
18
Michael Wright1509a232018-06-21 02:50:34 +010019#undef LOG_TAG
20#define LOG_TAG "PowerAdvisor"
21
22#include <cinttypes>
23
Dan Stoza030fbc12020-02-19 15:32:01 -080024#include <android-base/properties.h>
Michael Wright1509a232018-06-21 02:50:34 +010025#include <utils/Log.h>
26#include <utils/Mutex.h>
27
Dan Stoza030fbc12020-02-19 15:32:01 -080028#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
Michael Wright1509a232018-06-21 02:50:34 +010034#include "PowerAdvisor.h"
35
36namespace android {
37namespace Hwc2 {
38
39PowerAdvisor::~PowerAdvisor() = default;
40
41namespace impl {
42
43namespace V1_0 = android::hardware::power::V1_0;
Dan Stoza030fbc12020-02-19 15:32:01 -080044namespace V1_3 = android::hardware::power::V1_3;
Michael Wright1509a232018-06-21 02:50:34 +010045using V1_3::PowerHint;
46
Dan Stoza030fbc12020-02-19 15:32:01 -080047using android::hardware::power::Boost;
48using android::hardware::power::IPower;
49using android::hardware::power::Mode;
50using base::GetIntProperty;
51using scheduler::OneShotTimer;
52
Michael Wright1509a232018-06-21 02:50:34 +010053PowerAdvisor::~PowerAdvisor() = default;
54
Dan Stoza030fbc12020-02-19 15:32:01 -080055namespace {
56int32_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
64PowerAdvisor::PowerAdvisor()
65 : mUseUpdateImminentTimer(getUpdateTimeout() > 0),
66 mUpdateImminentTimer(
67 OneShotTimer::Interval(getUpdateTimeout()),
68 /* resetCallback */ [this] { mSendUpdateImminent.store(false); },
69 /* timeoutCallback */ [this] { mSendUpdateImminent.store(true); }) {
70 if (mUseUpdateImminentTimer) {
71 mUpdateImminentTimer.start();
72 }
73}
Michael Wright1509a232018-06-21 02:50:34 +010074
Dan Stoza29e7bdf2020-03-23 14:43:09 -070075void PowerAdvisor::onBootFinished() {
76 mBootFinished.store(true);
77}
78
Peiyong Lin74ca2f42019-01-14 19:36:57 -080079void PowerAdvisor::setExpensiveRenderingExpected(DisplayId displayId, bool expected) {
Michael Wright1509a232018-06-21 02:50:34 +010080 if (expected) {
81 mExpensiveDisplays.insert(displayId);
82 } else {
83 mExpensiveDisplays.erase(displayId);
84 }
85
Michael Wright1509a232018-06-21 02:50:34 +010086 const bool expectsExpensiveRendering = !mExpensiveDisplays.empty();
87 if (mNotifiedExpensiveRendering != expectsExpensiveRendering) {
Dan Stoza030fbc12020-02-19 15:32:01 -080088 HalWrapper* const halWrapper = getPowerHal();
89 if (halWrapper == nullptr) {
Peiyong Lin81934972018-07-02 11:00:54 -070090 return;
91 }
Dan Stoza030fbc12020-02-19 15:32:01 -080092
93 if (!halWrapper->setExpensiveRendering(expectsExpensiveRendering)) {
94 // The HAL has become unavailable; attempt to reconnect later
Michael Wright1509a232018-06-21 02:50:34 +010095 mReconnectPowerHal = true;
96 return;
97 }
Dan Stoza030fbc12020-02-19 15:32:01 -080098
Michael Wright1509a232018-06-21 02:50:34 +010099 mNotifiedExpensiveRendering = expectsExpensiveRendering;
100 }
101}
102
Dan Stoza030fbc12020-02-19 15:32:01 -0800103void PowerAdvisor::notifyDisplayUpdateImminent() {
Dan Stoza29e7bdf2020-03-23 14:43:09 -0700104 // Only start sending this notification once the system has booted so we don't introduce an
105 // early-boot dependency on Power HAL
106 if (!mBootFinished.load()) {
107 return;
108 }
109
Dan Stoza030fbc12020-02-19 15:32:01 -0800110 if (mSendUpdateImminent.load()) {
111 HalWrapper* const halWrapper = getPowerHal();
112 if (halWrapper == nullptr) {
113 return;
114 }
115
116 if (!halWrapper->notifyDisplayUpdateImminent()) {
117 // The HAL has become unavailable; attempt to reconnect later
118 mReconnectPowerHal = true;
119 return;
120 }
121 }
122
123 if (mUseUpdateImminentTimer) {
124 mUpdateImminentTimer.reset();
125 }
126}
127
128class HidlPowerHalWrapper : public PowerAdvisor::HalWrapper {
129public:
130 HidlPowerHalWrapper(sp<V1_3::IPower> powerHal) : mPowerHal(std::move(powerHal)) {}
131
132 ~HidlPowerHalWrapper() override = default;
133
134 static std::unique_ptr<HalWrapper> connect() {
135 // Power HAL 1.3 is not guaranteed to be available, thus we need to query
136 // Power HAL 1.0 first and try to cast it to Power HAL 1.3.
Dan Stoza030fbc12020-02-19 15:32:01 -0800137 sp<V1_3::IPower> powerHal = nullptr;
Dan Stoza9c051c02020-02-28 10:19:07 -0800138 sp<V1_0::IPower> powerHal_1_0 = V1_0::IPower::getService();
139 if (powerHal_1_0 != nullptr) {
140 // Try to cast to Power HAL 1.3
141 powerHal = V1_3::IPower::castFrom(powerHal_1_0);
142 if (powerHal == nullptr) {
143 ALOGW("No Power HAL 1.3 service in system, disabling PowerAdvisor");
144 } else {
145 ALOGI("Loaded Power HAL 1.3 service");
Dan Stoza030fbc12020-02-19 15:32:01 -0800146 }
Dan Stoza9c051c02020-02-28 10:19:07 -0800147 } else {
148 ALOGW("No Power HAL found, disabling PowerAdvisor");
Dan Stoza030fbc12020-02-19 15:32:01 -0800149 }
Dan Stoza9c051c02020-02-28 10:19:07 -0800150
Dan Stoza030fbc12020-02-19 15:32:01 -0800151 if (powerHal == nullptr) {
152 return nullptr;
153 }
154
155 return std::make_unique<HidlPowerHalWrapper>(std::move(powerHal));
156 }
157
158 bool setExpensiveRendering(bool enabled) override {
159 ALOGV("HIDL setExpensiveRendering %s", enabled ? "T" : "F");
160 auto ret = mPowerHal->powerHintAsync_1_3(PowerHint::EXPENSIVE_RENDERING, enabled);
161 return ret.isOk();
162 }
163
164 bool notifyDisplayUpdateImminent() override {
165 // Power HAL 1.x doesn't have a notification for this
166 ALOGV("HIDL notifyUpdateImminent received but can't send");
167 return true;
168 }
169
170private:
Dan Stoza030fbc12020-02-19 15:32:01 -0800171 const sp<V1_3::IPower> mPowerHal = nullptr;
172};
173
Dan Stoza030fbc12020-02-19 15:32:01 -0800174class AidlPowerHalWrapper : public PowerAdvisor::HalWrapper {
175public:
176 AidlPowerHalWrapper(sp<IPower> powerHal) : mPowerHal(std::move(powerHal)) {
177 auto ret = mPowerHal->isModeSupported(Mode::EXPENSIVE_RENDERING, &mHasExpensiveRendering);
178 if (!ret.isOk()) {
179 mHasExpensiveRendering = false;
180 }
181
182 ret = mPowerHal->isBoostSupported(Boost::DISPLAY_UPDATE_IMMINENT,
183 &mHasDisplayUpdateImminent);
184 if (!ret.isOk()) {
185 mHasDisplayUpdateImminent = false;
186 }
187 }
188
189 ~AidlPowerHalWrapper() override = default;
190
191 static std::unique_ptr<HalWrapper> connect() {
192 // This only waits if the service is actually declared
193 sp<IPower> powerHal = waitForVintfService<IPower>();
194 if (powerHal == nullptr) {
195 return nullptr;
196 }
197 ALOGI("Loaded AIDL Power HAL service");
198
199 return std::make_unique<AidlPowerHalWrapper>(std::move(powerHal));
200 }
201
202 bool setExpensiveRendering(bool enabled) override {
203 ALOGV("AIDL setExpensiveRendering %s", enabled ? "T" : "F");
204 if (!mHasExpensiveRendering) {
205 ALOGV("Skipped sending EXPENSIVE_RENDERING because HAL doesn't support it");
206 return true;
207 }
208
209 auto ret = mPowerHal->setMode(Mode::EXPENSIVE_RENDERING, enabled);
210 return ret.isOk();
211 }
212
213 bool notifyDisplayUpdateImminent() override {
214 ALOGV("AIDL notifyDisplayUpdateImminent");
215 if (!mHasDisplayUpdateImminent) {
216 ALOGV("Skipped sending DISPLAY_UPDATE_IMMINENT because HAL doesn't support it");
217 return true;
218 }
219
220 auto ret = mPowerHal->setBoost(Boost::DISPLAY_UPDATE_IMMINENT, 0);
221 return ret.isOk();
222 }
223
224private:
225 const sp<IPower> mPowerHal = nullptr;
226 bool mHasExpensiveRendering = false;
227 bool mHasDisplayUpdateImminent = false;
228};
229
230PowerAdvisor::HalWrapper* PowerAdvisor::getPowerHal() {
231 static std::unique_ptr<HalWrapper> sHalWrapper = nullptr;
Dan Stoza9c051c02020-02-28 10:19:07 -0800232 static bool sHasHal = true;
Michael Wright1509a232018-06-21 02:50:34 +0100233
Dan Stoza9c051c02020-02-28 10:19:07 -0800234 if (!sHasHal) {
235 return nullptr;
236 }
237
238 // If we used to have a HAL, but it stopped responding, attempt to reconnect
Michael Wright1509a232018-06-21 02:50:34 +0100239 if (mReconnectPowerHal) {
Dan Stoza030fbc12020-02-19 15:32:01 -0800240 sHalWrapper = nullptr;
Michael Wright1509a232018-06-21 02:50:34 +0100241 mReconnectPowerHal = false;
242 }
243
Dan Stoza030fbc12020-02-19 15:32:01 -0800244 if (sHalWrapper != nullptr) {
245 return sHalWrapper.get();
Michael Wright1509a232018-06-21 02:50:34 +0100246 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800247
248 // First attempt to connect to the AIDL Power HAL
249 sHalWrapper = AidlPowerHalWrapper::connect();
250
251 // If that didn't succeed, attempt to connect to the HIDL Power HAL
252 if (sHalWrapper == nullptr) {
253 sHalWrapper = HidlPowerHalWrapper::connect();
254 }
255
Dan Stoza9c051c02020-02-28 10:19:07 -0800256 // If we make it to this point and still don't have a HAL, it's unlikely we
257 // will, so stop trying
258 if (sHalWrapper == nullptr) {
259 sHasHal = false;
260 }
261
Dan Stoza030fbc12020-02-19 15:32:01 -0800262 return sHalWrapper.get();
Michael Wright1509a232018-06-21 02:50:34 +0100263}
264
265} // namespace impl
266} // namespace Hwc2
267} // namespace android