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/Android.bp b/services/surfaceflinger/Android.bp
index 4ffdf97..08d7d3f 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -33,6 +33,7 @@
"android.hardware.graphics.composer@2.4",
"android.hardware.power@1.0",
"android.hardware.power@1.3",
+ "android.hardware.power-cpp",
"libbase",
"libbinder",
"libbufferhubqueue",
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h b/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h
index c5a73f2..e740b13 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h
@@ -30,6 +30,7 @@
~PowerAdvisor() override;
MOCK_METHOD2(setExpensiveRenderingExpected, void(DisplayId displayId, bool expected));
+ MOCK_METHOD0(notifyDisplayUpdateImminent, void());
};
} // namespace mock
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
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
index 5aa1f22..957d289 100644
--- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
@@ -22,11 +22,10 @@
#undef HWC2_INCLUDE_STRINGIFICATION
#undef HWC2_USE_CPP11
+#include <atomic>
#include <unordered_set>
-#include <android/hardware/power/1.3/IPower.h>
-#include <utils/StrongPointer.h>
-
+#include "../Scheduler/OneShotTimer.h"
#include "DisplayIdentification.h"
namespace android {
@@ -37,27 +36,40 @@
virtual ~PowerAdvisor();
virtual void setExpensiveRenderingExpected(DisplayId displayId, bool expected) = 0;
+ virtual void notifyDisplayUpdateImminent() = 0;
};
namespace impl {
-namespace V1_3 = android::hardware::power::V1_3;
-
// PowerAdvisor is a wrapper around IPower HAL which takes into account the
// full state of the system when sending out power hints to things like the GPU.
class PowerAdvisor final : public Hwc2::PowerAdvisor {
public:
+ class HalWrapper {
+ public:
+ virtual ~HalWrapper() = default;
+
+ virtual bool setExpensiveRendering(bool enabled) = 0;
+ virtual bool notifyDisplayUpdateImminent() = 0;
+ };
+
PowerAdvisor();
~PowerAdvisor() override;
void setExpensiveRenderingExpected(DisplayId displayId, bool expected) override;
+ void notifyDisplayUpdateImminent() override;
private:
- sp<V1_3::IPower> getPowerHal();
+ HalWrapper* getPowerHal();
+
+ bool mReconnectPowerHal = false;
std::unordered_set<DisplayId> mExpensiveDisplays;
bool mNotifiedExpensiveRendering = false;
- bool mReconnectPowerHal = false;
+
+ const bool mUseUpdateImminentTimer;
+ std::atomic_bool mSendUpdateImminent = true;
+ scheduler::OneShotTimer mUpdateImminentTimer;
};
} // namespace impl
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index fbebea0..2acf084 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1491,11 +1491,13 @@
void SurfaceFlinger::signalTransaction() {
mScheduler->resetIdleTimer();
+ mPowerAdvisor.notifyDisplayUpdateImminent();
mEventQueue->invalidate();
}
void SurfaceFlinger::signalLayerUpdate() {
mScheduler->resetIdleTimer();
+ mPowerAdvisor.notifyDisplayUpdateImminent();
mEventQueue->invalidate();
}
@@ -5097,6 +5099,7 @@
void SurfaceFlinger::repaintEverythingForHWC() {
mRepaintEverything = true;
+ mPowerAdvisor.notifyDisplayUpdateImminent();
mEventQueue->invalidate();
}
diff --git a/services/surfaceflinger/SurfaceFlingerProperties.cpp b/services/surfaceflinger/SurfaceFlingerProperties.cpp
index 1a611f5..f3352a5 100644
--- a/services/surfaceflinger/SurfaceFlingerProperties.cpp
+++ b/services/surfaceflinger/SurfaceFlingerProperties.cpp
@@ -305,6 +305,14 @@
return defaultValue;
}
+int32_t display_update_imminent_timeout_ms(int32_t defaultValue) {
+ auto temp = SurfaceFlingerProperties::display_update_imminent_timeout_ms();
+ if (temp.has_value()) {
+ return *temp;
+ }
+ return defaultValue;
+}
+
#define DISPLAY_PRIMARY_SIZE 3
constexpr float kSrgbRedX = 0.4123f;
diff --git a/services/surfaceflinger/SurfaceFlingerProperties.h b/services/surfaceflinger/SurfaceFlingerProperties.h
index 4c6e191..12c711a 100644
--- a/services/surfaceflinger/SurfaceFlingerProperties.h
+++ b/services/surfaceflinger/SurfaceFlingerProperties.h
@@ -89,6 +89,8 @@
bool use_frame_rate_api(bool defaultValue);
+int32_t display_update_imminent_timeout_ms(int32_t defaultValue);
+
android::ui::DisplayPrimaries getDisplayNativePrimaries();
} // namespace sysprop
} // namespace android
diff --git a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
index b19eae6..155f718 100644
--- a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
+++ b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
@@ -403,3 +403,15 @@
access: Readonly
prop_name: "ro.surface_flinger.use_frame_rate_api"
}
+
+# Sets the timeout used to rate limit DISPLAY_UPDATE_IMMINENT Power HAL notifications.
+# SurfaceFlinger wakeups will trigger this boost whenever they are separated by more than this
+# duration (specified in milliseconds). A value of 0 disables the rate limit, and will result in
+# Power HAL notifications every time SF wakes up.
+prop {
+ api_name: "display_update_imminent_timeout_ms"
+ type: Integer
+ scope: Public
+ access: Readonly
+ prop_name: "ro.surface_flinger.display_update_imminent_timeout_ms"
+}
diff --git a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
index c66523a..e62c127 100644
--- a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
+++ b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
@@ -36,6 +36,11 @@
prop_name: "ro.surface_flinger.display_primary_white"
}
prop {
+ api_name: "display_update_imminent_timeout_ms"
+ type: Integer
+ prop_name: "ro.surface_flinger.display_update_imminent_timeout_ms"
+ }
+ prop {
api_name: "enable_protected_contents"
prop_name: "ro.surface_flinger.protected_contents"
}
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h
index 7c65f95..fe57c98 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h
@@ -30,6 +30,7 @@
~PowerAdvisor() override;
MOCK_METHOD2(setExpensiveRenderingExpected, void(DisplayId displayId, bool expected));
+ MOCK_METHOD0(notifyDisplayUpdateImminent, void());
};
} // namespace mock