Loading services/surfaceflinger/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ cc_defaults { "android.hardware.graphics.composer@2.4", "android.hardware.power@1.0", "android.hardware.power@1.3", "android.hardware.power-cpp", "libbase", "libbinder", "libbufferhubqueue", Loading services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h +1 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ public: ~PowerAdvisor() override; MOCK_METHOD2(setExpensiveRenderingExpected, void(DisplayId displayId, bool expected)); MOCK_METHOD0(notifyDisplayUpdateImminent, void()); }; } // namespace mock Loading services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp +184 −31 Original line number Diff line number Diff line Loading @@ -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 { Loading @@ -32,11 +41,36 @@ PowerAdvisor::~PowerAdvisor() = default; 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) { Loading @@ -47,43 +81,60 @@ void PowerAdvisor::setExpensiveRenderingExpected(DisplayId displayId, bool expec 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 (mReconnectPowerHal) { sPowerHal_1_3 = nullptr; mReconnectPowerHal = false; 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. if (sHasPowerHal_1_3 && sPowerHal_1_3 == nullptr) { 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 sPowerHal_1_3 = V1_3::IPower::castFrom(powerHal_1_0); if (sPowerHal_1_3 == nullptr) { 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 { Loading @@ -91,7 +142,109 @@ sp<V1_3::IPower> PowerAdvisor::getPowerHal() { } } } return sPowerHal_1_3; 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) { sHalWrapper = nullptr; mReconnectPowerHal = false; } if (sHalWrapper != nullptr) { return sHalWrapper.get(); } // 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 Loading services/surfaceflinger/DisplayHardware/PowerAdvisor.h +19 −7 Original line number Diff line number Diff line Loading @@ -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 { Loading @@ -37,27 +36,40 @@ public: 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 Loading services/surfaceflinger/SurfaceFlinger.cpp +3 −0 Original line number Diff line number Diff line Loading @@ -1493,11 +1493,13 @@ void SurfaceFlinger::waitForEvent() { void SurfaceFlinger::signalTransaction() { mScheduler->resetIdleTimer(); mPowerAdvisor.notifyDisplayUpdateImminent(); mEventQueue->invalidate(); } void SurfaceFlinger::signalLayerUpdate() { mScheduler->resetIdleTimer(); mPowerAdvisor.notifyDisplayUpdateImminent(); mEventQueue->invalidate(); } Loading Loading @@ -5100,6 +5102,7 @@ void SurfaceFlinger::repaintEverything() { void SurfaceFlinger::repaintEverythingForHWC() { mRepaintEverything = true; mPowerAdvisor.notifyDisplayUpdateImminent(); mEventQueue->invalidate(); } Loading Loading
services/surfaceflinger/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ cc_defaults { "android.hardware.graphics.composer@2.4", "android.hardware.power@1.0", "android.hardware.power@1.3", "android.hardware.power-cpp", "libbase", "libbinder", "libbufferhubqueue", Loading
services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h +1 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ public: ~PowerAdvisor() override; MOCK_METHOD2(setExpensiveRenderingExpected, void(DisplayId displayId, bool expected)); MOCK_METHOD0(notifyDisplayUpdateImminent, void()); }; } // namespace mock Loading
services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp +184 −31 Original line number Diff line number Diff line Loading @@ -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 { Loading @@ -32,11 +41,36 @@ PowerAdvisor::~PowerAdvisor() = default; 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) { Loading @@ -47,43 +81,60 @@ void PowerAdvisor::setExpensiveRenderingExpected(DisplayId displayId, bool expec 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 (mReconnectPowerHal) { sPowerHal_1_3 = nullptr; mReconnectPowerHal = false; 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. if (sHasPowerHal_1_3 && sPowerHal_1_3 == nullptr) { 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 sPowerHal_1_3 = V1_3::IPower::castFrom(powerHal_1_0); if (sPowerHal_1_3 == nullptr) { 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 { Loading @@ -91,7 +142,109 @@ sp<V1_3::IPower> PowerAdvisor::getPowerHal() { } } } return sPowerHal_1_3; 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) { sHalWrapper = nullptr; mReconnectPowerHal = false; } if (sHalWrapper != nullptr) { return sHalWrapper.get(); } // 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 Loading
services/surfaceflinger/DisplayHardware/PowerAdvisor.h +19 −7 Original line number Diff line number Diff line Loading @@ -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 { Loading @@ -37,27 +36,40 @@ public: 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 Loading
services/surfaceflinger/SurfaceFlinger.cpp +3 −0 Original line number Diff line number Diff line Loading @@ -1493,11 +1493,13 @@ void SurfaceFlinger::waitForEvent() { void SurfaceFlinger::signalTransaction() { mScheduler->resetIdleTimer(); mPowerAdvisor.notifyDisplayUpdateImminent(); mEventQueue->invalidate(); } void SurfaceFlinger::signalLayerUpdate() { mScheduler->resetIdleTimer(); mPowerAdvisor.notifyDisplayUpdateImminent(); mEventQueue->invalidate(); } Loading Loading @@ -5100,6 +5102,7 @@ void SurfaceFlinger::repaintEverything() { void SurfaceFlinger::repaintEverythingForHWC() { mRepaintEverything = true; mPowerAdvisor.notifyDisplayUpdateImminent(); mEventQueue->invalidate(); } Loading