sf: Update PowerAdvisor to talk to AIDL Power HAL
Updates the PowerAdvisor to talk to the AIDL Power HAL, and hooks up
the new DISPLAY_UPDATE_IMMINENT Boost present in that HAL.
Test: libsurfaceflinger_unittest
Test: libcompositionengine_test
Test: Manual with ALOGV
Bug: 132390048
Bug: 146453294
Change-Id: I3cb3e8d04303373de24b6dc150ce724aac89407c
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
index 039db73..550ec61 100644
--- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
@@ -14,14 +14,23 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+
#undef LOG_TAG
#define LOG_TAG "PowerAdvisor"
#include <cinttypes>
+#include <android-base/properties.h>
#include <utils/Log.h>
#include <utils/Mutex.h>
+#include <android/hardware/power/1.3/IPower.h>
+#include <android/hardware/power/IPower.h>
+#include <binder/IServiceManager.h>
+
+#include "../SurfaceFlingerProperties.h"
+
#include "PowerAdvisor.h"
namespace android {
@@ -32,11 +41,36 @@
namespace impl {
namespace V1_0 = android::hardware::power::V1_0;
+namespace V1_3 = android::hardware::power::V1_3;
using V1_3::PowerHint;
+using android::hardware::power::Boost;
+using android::hardware::power::IPower;
+using android::hardware::power::Mode;
+using base::GetIntProperty;
+using scheduler::OneShotTimer;
+
PowerAdvisor::~PowerAdvisor() = default;
-PowerAdvisor::PowerAdvisor() = default;
+namespace {
+int32_t getUpdateTimeout() {
+ // Default to a timeout of 80ms if nothing else is specified
+ static int32_t timeout = sysprop::display_update_imminent_timeout_ms(80);
+ return timeout;
+}
+
+} // namespace
+
+PowerAdvisor::PowerAdvisor()
+ : mUseUpdateImminentTimer(getUpdateTimeout() > 0),
+ mUpdateImminentTimer(
+ OneShotTimer::Interval(getUpdateTimeout()),
+ /* resetCallback */ [this] { mSendUpdateImminent.store(false); },
+ /* timeoutCallback */ [this] { mSendUpdateImminent.store(true); }) {
+ if (mUseUpdateImminentTimer) {
+ mUpdateImminentTimer.start();
+ }
+}
void PowerAdvisor::setExpensiveRenderingExpected(DisplayId displayId, bool expected) {
if (expected) {
@@ -47,51 +81,170 @@
const bool expectsExpensiveRendering = !mExpensiveDisplays.empty();
if (mNotifiedExpensiveRendering != expectsExpensiveRendering) {
- const sp<V1_3::IPower> powerHal = getPowerHal();
- if (powerHal == nullptr) {
+ HalWrapper* const halWrapper = getPowerHal();
+ if (halWrapper == nullptr) {
return;
}
- auto ret = powerHal->powerHintAsync_1_3(PowerHint::EXPENSIVE_RENDERING,
- expectsExpensiveRendering);
- // If Power HAL 1.3 was available previously but now fails,
- // it may restart, so attempt to reconnect next time
- if (!ret.isOk()) {
+
+ if (!halWrapper->setExpensiveRendering(expectsExpensiveRendering)) {
+ // The HAL has become unavailable; attempt to reconnect later
mReconnectPowerHal = true;
return;
}
+
mNotifiedExpensiveRendering = expectsExpensiveRendering;
}
}
-sp<V1_3::IPower> PowerAdvisor::getPowerHal() {
- static sp<V1_3::IPower> sPowerHal_1_3 = nullptr;
- static bool sHasPowerHal_1_3 = true;
+void PowerAdvisor::notifyDisplayUpdateImminent() {
+ if (mSendUpdateImminent.load()) {
+ HalWrapper* const halWrapper = getPowerHal();
+ if (halWrapper == nullptr) {
+ return;
+ }
+
+ if (!halWrapper->notifyDisplayUpdateImminent()) {
+ // The HAL has become unavailable; attempt to reconnect later
+ mReconnectPowerHal = true;
+ return;
+ }
+ }
+
+ if (mUseUpdateImminentTimer) {
+ mUpdateImminentTimer.reset();
+ }
+}
+
+class HidlPowerHalWrapper : public PowerAdvisor::HalWrapper {
+public:
+ HidlPowerHalWrapper(sp<V1_3::IPower> powerHal) : mPowerHal(std::move(powerHal)) {}
+
+ ~HidlPowerHalWrapper() override = default;
+
+ static std::unique_ptr<HalWrapper> connect() {
+ // Power HAL 1.3 is not guaranteed to be available, thus we need to query
+ // Power HAL 1.0 first and try to cast it to Power HAL 1.3.
+ // Power HAL 1.0 is always available, thus if we fail to query it, it means
+ // Power HAL is not available temporarily and we should retry later. However,
+ // if Power HAL 1.0 is available and we can't cast it to Power HAL 1.3,
+ // it means Power HAL 1.3 is not available at all, so we should stop trying.
+ sp<V1_3::IPower> powerHal = nullptr;
+ if (sHasPowerHal_1_3) {
+ sp<V1_0::IPower> powerHal_1_0 = V1_0::IPower::getService();
+ if (powerHal_1_0 != nullptr) {
+ // Try to cast to Power HAL 1.3
+ powerHal = V1_3::IPower::castFrom(powerHal_1_0);
+ if (powerHal == nullptr) {
+ ALOGW("No Power HAL 1.3 service in system");
+ sHasPowerHal_1_3 = false;
+ } else {
+ ALOGI("Loaded Power HAL 1.3 service");
+ }
+ }
+ }
+ if (powerHal == nullptr) {
+ return nullptr;
+ }
+
+ return std::make_unique<HidlPowerHalWrapper>(std::move(powerHal));
+ }
+
+ bool setExpensiveRendering(bool enabled) override {
+ ALOGV("HIDL setExpensiveRendering %s", enabled ? "T" : "F");
+ auto ret = mPowerHal->powerHintAsync_1_3(PowerHint::EXPENSIVE_RENDERING, enabled);
+ return ret.isOk();
+ }
+
+ bool notifyDisplayUpdateImminent() override {
+ // Power HAL 1.x doesn't have a notification for this
+ ALOGV("HIDL notifyUpdateImminent received but can't send");
+ return true;
+ }
+
+private:
+ static bool sHasPowerHal_1_3;
+ const sp<V1_3::IPower> mPowerHal = nullptr;
+};
+
+bool HidlPowerHalWrapper::sHasPowerHal_1_3 = true;
+
+class AidlPowerHalWrapper : public PowerAdvisor::HalWrapper {
+public:
+ AidlPowerHalWrapper(sp<IPower> powerHal) : mPowerHal(std::move(powerHal)) {
+ auto ret = mPowerHal->isModeSupported(Mode::EXPENSIVE_RENDERING, &mHasExpensiveRendering);
+ if (!ret.isOk()) {
+ mHasExpensiveRendering = false;
+ }
+
+ ret = mPowerHal->isBoostSupported(Boost::DISPLAY_UPDATE_IMMINENT,
+ &mHasDisplayUpdateImminent);
+ if (!ret.isOk()) {
+ mHasDisplayUpdateImminent = false;
+ }
+ }
+
+ ~AidlPowerHalWrapper() override = default;
+
+ static std::unique_ptr<HalWrapper> connect() {
+ // This only waits if the service is actually declared
+ sp<IPower> powerHal = waitForVintfService<IPower>();
+ if (powerHal == nullptr) {
+ return nullptr;
+ }
+ ALOGI("Loaded AIDL Power HAL service");
+
+ return std::make_unique<AidlPowerHalWrapper>(std::move(powerHal));
+ }
+
+ bool setExpensiveRendering(bool enabled) override {
+ ALOGV("AIDL setExpensiveRendering %s", enabled ? "T" : "F");
+ if (!mHasExpensiveRendering) {
+ ALOGV("Skipped sending EXPENSIVE_RENDERING because HAL doesn't support it");
+ return true;
+ }
+
+ auto ret = mPowerHal->setMode(Mode::EXPENSIVE_RENDERING, enabled);
+ return ret.isOk();
+ }
+
+ bool notifyDisplayUpdateImminent() override {
+ ALOGV("AIDL notifyDisplayUpdateImminent");
+ if (!mHasDisplayUpdateImminent) {
+ ALOGV("Skipped sending DISPLAY_UPDATE_IMMINENT because HAL doesn't support it");
+ return true;
+ }
+
+ auto ret = mPowerHal->setBoost(Boost::DISPLAY_UPDATE_IMMINENT, 0);
+ return ret.isOk();
+ }
+
+private:
+ const sp<IPower> mPowerHal = nullptr;
+ bool mHasExpensiveRendering = false;
+ bool mHasDisplayUpdateImminent = false;
+};
+
+PowerAdvisor::HalWrapper* PowerAdvisor::getPowerHal() {
+ static std::unique_ptr<HalWrapper> sHalWrapper = nullptr;
if (mReconnectPowerHal) {
- sPowerHal_1_3 = nullptr;
+ sHalWrapper = nullptr;
mReconnectPowerHal = false;
}
- // Power HAL 1.3 is not guaranteed to be available, thus we need to query
- // Power HAL 1.0 first and try to cast it to Power HAL 1.3.
- // Power HAL 1.0 is always available, thus if we fail to query it, it means
- // Power HAL is not available temporarily and we should retry later. However,
- // if Power HAL 1.0 is available and we can't cast it to Power HAL 1.3,
- // it means Power HAL 1.3 is not available at all, so we should stop trying.
- if (sHasPowerHal_1_3 && sPowerHal_1_3 == nullptr) {
- sp<V1_0::IPower> powerHal_1_0 = V1_0::IPower::getService();
- if (powerHal_1_0 != nullptr) {
- // Try to cast to Power HAL 1.3
- sPowerHal_1_3 = V1_3::IPower::castFrom(powerHal_1_0);
- if (sPowerHal_1_3 == nullptr) {
- ALOGW("No Power HAL 1.3 service in system");
- sHasPowerHal_1_3 = false;
- } else {
- ALOGI("Loaded Power HAL 1.3 service");
- }
- }
+ if (sHalWrapper != nullptr) {
+ return sHalWrapper.get();
}
- return sPowerHal_1_3;
+
+ // First attempt to connect to the AIDL Power HAL
+ sHalWrapper = AidlPowerHalWrapper::connect();
+
+ // If that didn't succeed, attempt to connect to the HIDL Power HAL
+ if (sHalWrapper == nullptr) {
+ sHalWrapper = HidlPowerHalWrapper::connect();
+ }
+
+ return sHalWrapper.get();
}
} // namespace impl