Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 030fbc11 authored by Dan Stoza's avatar Dan Stoza
Browse files

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
parent 0a588706
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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",
+1 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ public:
    ~PowerAdvisor() override;

    MOCK_METHOD2(setExpensiveRenderingExpected, void(DisplayId displayId, bool expected));
    MOCK_METHOD0(notifyDisplayUpdateImminent, void());
};

} // namespace mock
+184 −31
Original line number Diff line number Diff line
@@ -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 @@ 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) {
@@ -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 {
@@ -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
+19 −7
Original line number Diff line number Diff line
@@ -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 @@ 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
+3 −0
Original line number Diff line number Diff line
@@ -1491,11 +1491,13 @@ void SurfaceFlinger::waitForEvent() {

void SurfaceFlinger::signalTransaction() {
    mScheduler->resetIdleTimer();
    mPowerAdvisor.notifyDisplayUpdateImminent();
    mEventQueue->invalidate();
}

void SurfaceFlinger::signalLayerUpdate() {
    mScheduler->resetIdleTimer();
    mPowerAdvisor.notifyDisplayUpdateImminent();
    mEventQueue->invalidate();
}

@@ -5097,6 +5099,7 @@ void SurfaceFlinger::repaintEverything() {

void SurfaceFlinger::repaintEverythingForHWC() {
    mRepaintEverything = true;
    mPowerAdvisor.notifyDisplayUpdateImminent();
    mEventQueue->invalidate();
}

Loading