blob: 1765caf8474c92881f00e7abfded36884cff4557 [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"
Alec Mouridea1ac52021-06-23 18:12:18 -070035#include "SurfaceFlinger.h"
Michael Wright1509a232018-06-21 02:50:34 +010036
37namespace android {
38namespace Hwc2 {
39
40PowerAdvisor::~PowerAdvisor() = default;
41
42namespace impl {
43
44namespace V1_0 = android::hardware::power::V1_0;
Dan Stoza030fbc12020-02-19 15:32:01 -080045namespace V1_3 = android::hardware::power::V1_3;
Michael Wright1509a232018-06-21 02:50:34 +010046using V1_3::PowerHint;
47
Dan Stoza030fbc12020-02-19 15:32:01 -080048using android::hardware::power::Boost;
49using android::hardware::power::IPower;
50using android::hardware::power::Mode;
51using base::GetIntProperty;
52using scheduler::OneShotTimer;
53
Michael Wright1509a232018-06-21 02:50:34 +010054PowerAdvisor::~PowerAdvisor() = default;
55
Dan Stoza030fbc12020-02-19 15:32:01 -080056namespace {
57int32_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
Alec Mouridea1ac52021-06-23 18:12:18 -070065PowerAdvisor::PowerAdvisor(SurfaceFlinger& flinger)
66 : mFlinger(flinger),
67 mUseScreenUpdateTimer(getUpdateTimeout() > 0),
68 mScreenUpdateTimer(
Ady Abrahamdb3dfee2020-11-17 17:07:12 -080069 "UpdateImminentTimer", OneShotTimer::Interval(getUpdateTimeout()),
Dan Stoza030fbc12020-02-19 15:32:01 -080070 /* resetCallback */ [this] { mSendUpdateImminent.store(false); },
Alec Mouridea1ac52021-06-23 18:12:18 -070071 /* timeoutCallback */
72 [this] {
73 mSendUpdateImminent.store(true);
74 mFlinger.disableExpensiveRendering();
75 }) {}
76
77void PowerAdvisor::init() {
78 // Defer starting the screen update timer until SurfaceFlinger finishes construction.
79 if (mUseScreenUpdateTimer) {
80 mScreenUpdateTimer.start();
Dan Stoza030fbc12020-02-19 15:32:01 -080081 }
82}
Michael Wright1509a232018-06-21 02:50:34 +010083
Dan Stoza29e7bdf2020-03-23 14:43:09 -070084void PowerAdvisor::onBootFinished() {
85 mBootFinished.store(true);
86}
87
Peiyong Lin74ca2f42019-01-14 19:36:57 -080088void PowerAdvisor::setExpensiveRenderingExpected(DisplayId displayId, bool expected) {
Michael Wright1509a232018-06-21 02:50:34 +010089 if (expected) {
90 mExpensiveDisplays.insert(displayId);
91 } else {
92 mExpensiveDisplays.erase(displayId);
93 }
94
Michael Wright1509a232018-06-21 02:50:34 +010095 const bool expectsExpensiveRendering = !mExpensiveDisplays.empty();
96 if (mNotifiedExpensiveRendering != expectsExpensiveRendering) {
Dan Stoza20950002020-06-18 14:56:58 -070097 std::lock_guard lock(mPowerHalMutex);
Dan Stoza030fbc12020-02-19 15:32:01 -080098 HalWrapper* const halWrapper = getPowerHal();
99 if (halWrapper == nullptr) {
Peiyong Lin81934972018-07-02 11:00:54 -0700100 return;
101 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800102
103 if (!halWrapper->setExpensiveRendering(expectsExpensiveRendering)) {
104 // The HAL has become unavailable; attempt to reconnect later
Michael Wright1509a232018-06-21 02:50:34 +0100105 mReconnectPowerHal = true;
106 return;
107 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800108
Michael Wright1509a232018-06-21 02:50:34 +0100109 mNotifiedExpensiveRendering = expectsExpensiveRendering;
110 }
111}
112
Dan Stoza030fbc12020-02-19 15:32:01 -0800113void PowerAdvisor::notifyDisplayUpdateImminent() {
Dan Stoza29e7bdf2020-03-23 14:43:09 -0700114 // 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
Dan Stoza030fbc12020-02-19 15:32:01 -0800120 if (mSendUpdateImminent.load()) {
Dan Stoza20950002020-06-18 14:56:58 -0700121 std::lock_guard lock(mPowerHalMutex);
Dan Stoza030fbc12020-02-19 15:32:01 -0800122 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
Alec Mouridea1ac52021-06-23 18:12:18 -0700134 if (mUseScreenUpdateTimer) {
135 mScreenUpdateTimer.reset();
Dan Stoza030fbc12020-02-19 15:32:01 -0800136 }
137}
138
139class HidlPowerHalWrapper : public PowerAdvisor::HalWrapper {
140public:
141 HidlPowerHalWrapper(sp<V1_3::IPower> powerHal) : mPowerHal(std::move(powerHal)) {}
142
143 ~HidlPowerHalWrapper() override = default;
144
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.
Dan Stoza030fbc12020-02-19 15:32:01 -0800148 sp<V1_3::IPower> powerHal = nullptr;
Dan Stoza9c051c02020-02-28 10:19:07 -0800149 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");
Dan Stoza030fbc12020-02-19 15:32:01 -0800157 }
Dan Stoza9c051c02020-02-28 10:19:07 -0800158 } else {
159 ALOGW("No Power HAL found, disabling PowerAdvisor");
Dan Stoza030fbc12020-02-19 15:32:01 -0800160 }
Dan Stoza9c051c02020-02-28 10:19:07 -0800161
Dan Stoza030fbc12020-02-19 15:32:01 -0800162 if (powerHal == nullptr) {
163 return nullptr;
164 }
165
166 return std::make_unique<HidlPowerHalWrapper>(std::move(powerHal));
167 }
168
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
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
181private:
Dan Stoza030fbc12020-02-19 15:32:01 -0800182 const sp<V1_3::IPower> mPowerHal = nullptr;
183};
184
Dan Stoza030fbc12020-02-19 15:32:01 -0800185class AidlPowerHalWrapper : public PowerAdvisor::HalWrapper {
186public:
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
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
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
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
235private:
236 const sp<IPower> mPowerHal = nullptr;
237 bool mHasExpensiveRendering = false;
238 bool mHasDisplayUpdateImminent = false;
239};
240
241PowerAdvisor::HalWrapper* PowerAdvisor::getPowerHal() {
242 static std::unique_ptr<HalWrapper> sHalWrapper = nullptr;
Dan Stoza9c051c02020-02-28 10:19:07 -0800243 static bool sHasHal = true;
Michael Wright1509a232018-06-21 02:50:34 +0100244
Dan Stoza9c051c02020-02-28 10:19:07 -0800245 if (!sHasHal) {
246 return nullptr;
247 }
248
249 // If we used to have a HAL, but it stopped responding, attempt to reconnect
Michael Wright1509a232018-06-21 02:50:34 +0100250 if (mReconnectPowerHal) {
Dan Stoza030fbc12020-02-19 15:32:01 -0800251 sHalWrapper = nullptr;
Michael Wright1509a232018-06-21 02:50:34 +0100252 mReconnectPowerHal = false;
253 }
254
Dan Stoza030fbc12020-02-19 15:32:01 -0800255 if (sHalWrapper != nullptr) {
256 return sHalWrapper.get();
Michael Wright1509a232018-06-21 02:50:34 +0100257 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800258
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
Dan Stoza9c051c02020-02-28 10:19:07 -0800267 // 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
Dan Stoza030fbc12020-02-19 15:32:01 -0800273 return sHalWrapper.get();
Michael Wright1509a232018-06-21 02:50:34 +0100274}
275
276} // namespace impl
277} // namespace Hwc2
278} // namespace android