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

Commit a633a86a authored by Xiang Wang's avatar Xiang Wang Committed by Android (Google) Code Review
Browse files

Merge "Add unit test for AidlPowerHalWrapper" into tm-dev

parents bc9e42db e12b4fa9
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ cc_defaults {
        "android.hardware.graphics.composer3-V1-ndk",
        "android.hardware.power@1.0",
        "android.hardware.power@1.3",
        "android.hardware.power-V2-cpp",
        "libbase",
        "libcutils",
        "libgui",
+181 −211
Original line number Diff line number Diff line
@@ -32,7 +32,6 @@
#include <utils/Trace.h>

#include <android/hardware/power/1.3/IPower.h>
#include <android/hardware/power/IPower.h>
#include <android/hardware/power/IPowerHintSession.h>
#include <android/hardware/power/WorkDuration.h>

@@ -62,8 +61,6 @@ using android::hardware::power::WorkDuration;

using scheduler::OneShotTimer;

class AidlPowerHalWrapper;

PowerAdvisor::~PowerAdvisor() = default;

namespace {
@@ -294,16 +291,13 @@ private:
    const sp<V1_3::IPower> mPowerHal = nullptr;
};

class AidlPowerHalWrapper : public PowerAdvisor::HalWrapper {
public:
    AidlPowerHalWrapper(sp<IPower> powerHal) : mPowerHal(std::move(powerHal)) {
AidlPowerHalWrapper::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);
    ret = mPowerHal->isBoostSupported(Boost::DISPLAY_UPDATE_IMMINENT, &mHasDisplayUpdateImminent);
    if (!ret.isOk()) {
        mHasDisplayUpdateImminent = false;
    }
@@ -311,14 +305,14 @@ public:
    mSupportsPowerHint = checkPowerHintSessionSupported();
}

    ~AidlPowerHalWrapper() override {
AidlPowerHalWrapper::~AidlPowerHalWrapper() {
    if (mPowerHintSession != nullptr) {
        mPowerHintSession->close();
        mPowerHintSession = nullptr;
    }
};

    static std::unique_ptr<HalWrapper> connect() {
std::unique_ptr<PowerAdvisor::HalWrapper> AidlPowerHalWrapper::connect() {
    // This only waits if the service is actually declared
    sp<IPower> powerHal = waitForVintfService<IPower>();
    if (powerHal == nullptr) {
@@ -329,7 +323,7 @@ public:
    return std::make_unique<AidlPowerHalWrapper>(std::move(powerHal));
}

    bool setExpensiveRendering(bool enabled) override {
bool AidlPowerHalWrapper::setExpensiveRendering(bool enabled) {
    ALOGV("AIDL setExpensiveRendering %s", enabled ? "T" : "F");
    if (!mHasExpensiveRendering) {
        ALOGV("Skipped sending EXPENSIVE_RENDERING because HAL doesn't support it");
@@ -343,7 +337,7 @@ public:
    return ret.isOk();
}

    bool notifyDisplayUpdateImminent() override {
bool AidlPowerHalWrapper::notifyDisplayUpdateImminent() {
    ALOGV("AIDL notifyDisplayUpdateImminent");
    if (!mHasDisplayUpdateImminent) {
        ALOGV("Skipped sending DISPLAY_UPDATE_IMMINENT because HAL doesn't support it");
@@ -355,30 +349,34 @@ public:
}

// only version 2+ of the aidl supports power hint sessions, hidl has no support
    bool supportsPowerHintSession() override { return mSupportsPowerHint; }
bool AidlPowerHalWrapper::supportsPowerHintSession() {
    return mSupportsPowerHint;
}

    bool checkPowerHintSessionSupported() {
bool AidlPowerHalWrapper::checkPowerHintSessionSupported() {
    int64_t unused;
    // Try to get preferred rate to determine if hint sessions are supported
        // We check for isOk not EX_UNSUPPORTED_OPERATION to lump other errors
    // We check for isOk not EX_UNSUPPORTED_OPERATION to lump together errors
    return mPowerHal->getHintSessionPreferredRate(&unused).isOk();
}

    bool isPowerHintSessionRunning() override { return mPowerHintSession != nullptr; }
bool AidlPowerHalWrapper::isPowerHintSessionRunning() {
    return mPowerHintSession != nullptr;
}

    void closePowerHintSession() {
void AidlPowerHalWrapper::closePowerHintSession() {
    if (mPowerHintSession != nullptr) {
        mPowerHintSession->close();
        mPowerHintSession = nullptr;
    }
}

    void restartPowerHintSession() {
void AidlPowerHalWrapper::restartPowerHintSession() {
    closePowerHintSession();
    startPowerHintSession();
}

    void setPowerHintSessionThreadIds(const std::vector<int32_t>& threadIds) override {
void AidlPowerHalWrapper::setPowerHintSessionThreadIds(const std::vector<int32_t>& threadIds) {
    if (threadIds != mPowerHintThreadIds) {
        mPowerHintThreadIds = threadIds;
        if (isPowerHintSessionRunning()) {
@@ -387,14 +385,14 @@ public:
    }
}

    bool startPowerHintSession() override {
bool AidlPowerHalWrapper::startPowerHintSession() {
    if (mPowerHintSession != nullptr || mPowerHintThreadIds.empty()) {
        ALOGV("Cannot start power hint session, skipping");
        return false;
    }
        auto ret = mPowerHal->createHintSession(getpid(), static_cast<int32_t>(getuid()),
                                                mPowerHintThreadIds, mTargetDuration,
                                                &mPowerHintSession);
    auto ret =
            mPowerHal->createHintSession(getpid(), static_cast<int32_t>(getuid()),
                                         mPowerHintThreadIds, mTargetDuration, &mPowerHintSession);
    if (!ret.isOk()) {
        ALOGW("Failed to start power hint session with error: %s",
              ret.exceptionToString(ret.exceptionCode()).c_str());
@@ -404,27 +402,28 @@ public:
    return isPowerHintSessionRunning();
}

    bool shouldSetTargetDuration(int64_t targetDurationNanos) {
bool AidlPowerHalWrapper::shouldSetTargetDuration(int64_t targetDurationNanos) {
    if (targetDurationNanos <= 0) {
        return false;
    }
    // report if the change in target from our last submission to now exceeds the threshold
    return abs(1.0 -
               static_cast<double>(mLastTargetDurationSent) /
                           static_cast<double>(targetDurationNanos)) >=
                kAllowedTargetDeviationPercent;
                       static_cast<double>(targetDurationNanos)) >= kAllowedTargetDeviationPercent;
}

    void setTargetWorkDuration(int64_t targetDurationNanos) override {
void AidlPowerHalWrapper::setTargetWorkDuration(int64_t targetDurationNanos) {
    ATRACE_CALL();
    mTargetDuration = targetDurationNanos;
    if (sTraceHintSessionData) ATRACE_INT64("Time target", targetDurationNanos);
        if (!sNormalizeTarget && shouldSetTargetDuration(targetDurationNanos) &&
            isPowerHintSessionRunning()) {
    if (!sNormalizeTarget && isPowerHintSessionRunning() &&
        shouldSetTargetDuration(targetDurationNanos)) {
        if (mLastActualDurationSent.has_value()) {
            // update the error term here since we are actually sending an update to powerhal
            if (sTraceHintSessionData)
                    ATRACE_INT64("Target error term",
                                 targetDurationNanos - *mLastActualDurationSent);
                ATRACE_INT64("Target error term", targetDurationNanos - *mLastActualDurationSent);
        }
            ALOGV("Sending target time: %lld ns", static_cast<long long>(targetDurationNanos));
        ALOGV("Sending target time: %" PRId64 "ns", targetDurationNanos);
        mLastTargetDurationSent = targetDurationNanos;
        auto ret = mPowerHintSession->updateTargetWorkDuration(targetDurationNanos);
        if (!ret.isOk()) {
@@ -435,7 +434,7 @@ public:
    }
}

    bool shouldReportActualDurationsNow() {
bool AidlPowerHalWrapper::shouldReportActualDurationsNow() {
    // report if we have never reported before or are approaching a stale session
    if (!mLastActualDurationSent.has_value() ||
        (systemTime() - mLastActualReportTimestamp) > kStaleTimeout.count()) {
@@ -456,7 +455,8 @@ public:
            kAllowedActualDeviationPercent;
}

    void sendActualWorkDuration(int64_t actualDurationNanos, nsecs_t timeStampNanos) override {
void AidlPowerHalWrapper::sendActualWorkDuration(int64_t actualDurationNanos,
                                                 nsecs_t timeStampNanos) {
    ATRACE_CALL();

    if (actualDurationNanos < 0 || !isPowerHintSessionRunning()) {
@@ -475,15 +475,16 @@ public:
    duration.timeStampNanos = timeStampNanos;
    mPowerHintQueue.push_back(duration);

        long long targetNsec = mTargetDuration;
        long long durationNsec = actualDurationNanos;
    nsecs_t targetNsec = mTargetDuration;
    nsecs_t durationNsec = actualDurationNanos;

    if (sTraceHintSessionData) {
        ATRACE_INT64("Measured duration", durationNsec);
        ATRACE_INT64("Target error term", targetNsec - durationNsec);
    }

        ALOGV("Sending actual work duration of: %lld on target: %lld with error: %lld",
    ALOGV("Sending actual work duration of: %" PRId64 " on target: %" PRId64
          " with error: %" PRId64,
          durationNsec, targetNsec, targetNsec - durationNsec);

    // This rate limiter queues similar duration reports to the powerhal into
@@ -504,48 +505,17 @@ public:
    }
}

    bool shouldReconnectHAL() override { return mShouldReconnectHal; }

    std::vector<int32_t> getPowerHintSessionThreadIds() override { return mPowerHintThreadIds; }
bool AidlPowerHalWrapper::shouldReconnectHAL() {
    return mShouldReconnectHal;
}

    std::optional<int64_t> getTargetWorkDuration() override { return mTargetDuration; }
std::vector<int32_t> AidlPowerHalWrapper::getPowerHintSessionThreadIds() {
    return mPowerHintThreadIds;
}

private:
    const sp<IPower> mPowerHal = nullptr;
    bool mHasExpensiveRendering = false;
    bool mHasDisplayUpdateImminent = false;
    // Used to indicate an error state and need for reconstruction
    bool mShouldReconnectHal = false;
    // This is not thread safe, but is currently protected by mPowerHalMutex so it needs no lock
    sp<IPowerHintSession> mPowerHintSession = nullptr;
    // Queue of actual durations saved to report
    std::vector<WorkDuration> mPowerHintQueue;
    // The latest un-normalized values we have received for target and actual
    int64_t mTargetDuration = kDefaultTarget.count();
    std::optional<int64_t> mActualDuration;
    // The list of thread ids, stored so we can restart the session from this class if needed
    std::vector<int32_t> mPowerHintThreadIds;
    bool mSupportsPowerHint;
    // Keep track of the last messages sent for rate limiter change detection
    std::optional<int64_t> mLastActualDurationSent;
    // timestamp of the last report we sent, used to avoid stale sessions
    int64_t mLastActualReportTimestamp = 0;
    int64_t mLastTargetDurationSent = kDefaultTarget.count();
    // Whether to normalize all the actual values as error terms relative to a constant target
    // This saves a binder call by not setting the target, and should not affect the pid values
    static const bool sNormalizeTarget;
    // Whether we should emit ATRACE_INT data for hint sessions
    static const bool sTraceHintSessionData;
    // Max percent the actual duration can vary without causing a report (eg: 0.1 = 10%)
    static constexpr double kAllowedActualDeviationPercent = 0.1;
    // Max percent the target duration can vary without causing a report (eg: 0.05 = 5%)
    static constexpr double kAllowedTargetDeviationPercent = 0.05;
    // Target used for init and normalization, the actual value does not really matter
    static constexpr const std::chrono::nanoseconds kDefaultTarget = 50ms;
    // Amount of time after the last message was sent before the session goes stale
    // actually 100ms but we use 80 here to ideally avoid going stale
    static constexpr const std::chrono::nanoseconds kStaleTimeout = 80ms;
};
std::optional<int64_t> AidlPowerHalWrapper::getTargetWorkDuration() {
    return mTargetDuration;
}

const bool AidlPowerHalWrapper::sTraceHintSessionData =
        base::GetBoolProperty(std::string("debug.sf.trace_hint_sessions"), false);
+64 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@

#include <utils/Mutex.h>

#include <android/hardware/power/IPower.h>
#include <ui/DisplayIdentification.h>
#include "../Scheduler/OneShotTimer.h"

@@ -118,6 +119,69 @@ private:
    scheduler::OneShotTimer mScreenUpdateTimer;
};

class AidlPowerHalWrapper : public PowerAdvisor::HalWrapper {
public:
    explicit AidlPowerHalWrapper(sp<hardware::power::IPower> powerHal);
    ~AidlPowerHalWrapper() override;

    static std::unique_ptr<HalWrapper> connect();

    bool setExpensiveRendering(bool enabled) override;
    bool notifyDisplayUpdateImminent() override;
    bool supportsPowerHintSession() override;
    bool isPowerHintSessionRunning() override;
    void restartPowerHintSession() override;
    void setPowerHintSessionThreadIds(const std::vector<int32_t>& threadIds) override;
    bool startPowerHintSession() override;
    void setTargetWorkDuration(int64_t targetDurationNanos) override;
    void sendActualWorkDuration(int64_t actualDurationNanos, nsecs_t timeStampNanos) override;
    bool shouldReconnectHAL() override;
    std::vector<int32_t> getPowerHintSessionThreadIds() override;
    std::optional<int64_t> getTargetWorkDuration() override;

private:
    bool checkPowerHintSessionSupported();
    void closePowerHintSession();
    bool shouldReportActualDurationsNow();
    bool shouldSetTargetDuration(int64_t targetDurationNanos);

    const sp<hardware::power::IPower> mPowerHal = nullptr;
    bool mHasExpensiveRendering = false;
    bool mHasDisplayUpdateImminent = false;
    // Used to indicate an error state and need for reconstruction
    bool mShouldReconnectHal = false;
    // This is not thread safe, but is currently protected by mPowerHalMutex so it needs no lock
    sp<hardware::power::IPowerHintSession> mPowerHintSession = nullptr;
    // Queue of actual durations saved to report
    std::vector<hardware::power::WorkDuration> mPowerHintQueue;
    // The latest un-normalized values we have received for target and actual
    int64_t mTargetDuration = kDefaultTarget.count();
    std::optional<int64_t> mActualDuration;
    // The list of thread ids, stored so we can restart the session from this class if needed
    std::vector<int32_t> mPowerHintThreadIds;
    bool mSupportsPowerHint;
    // Keep track of the last messages sent for rate limiter change detection
    std::optional<int64_t> mLastActualDurationSent;
    // timestamp of the last report we sent, used to avoid stale sessions
    int64_t mLastActualReportTimestamp = 0;
    int64_t mLastTargetDurationSent = kDefaultTarget.count();
    // Whether to normalize all the actual values as error terms relative to a constant target
    // This saves a binder call by not setting the target, and should not affect the pid values
    static const bool sNormalizeTarget;
    // Whether we should emit ATRACE_INT data for hint sessions
    static const bool sTraceHintSessionData;

    // Max percent the actual duration can vary without causing a report (eg: 0.1 = 10%)
    static constexpr double kAllowedActualDeviationPercent = 0.1;
    // Max percent the target duration can vary without causing a report (eg: 0.05 = 5%)
    static constexpr double kAllowedTargetDeviationPercent = 0.05;
    // Target used for init and normalization, the actual value does not really matter
    static constexpr const std::chrono::nanoseconds kDefaultTarget = 50ms;
    // Amount of time after the last message was sent before the session goes stale
    // actually 100ms but we use 80 here to ideally avoid going stale
    static constexpr const std::chrono::nanoseconds kStaleTimeout = 80ms;
};

} // namespace impl
} // namespace Hwc2
} // namespace android
+3 −1
Original line number Diff line number Diff line
@@ -681,7 +681,9 @@ void SurfaceFlinger::bootFinished() {
            if (renderEngineTid.has_value()) {
                tidList.emplace_back(*renderEngineTid);
            }
            mPowerAdvisor.startPowerHintSession(tidList);
            if (!mPowerAdvisor.startPowerHintSession(tidList)) {
                ALOGW("Cannot start power hint session");
            }
        }

        mBootStage = BootStage::FINISHED;
+1 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ cc_test {
        "android.hardware.graphics.mapper@3.0",
        "android.hardware.graphics.mapper@4.0",
        "android.hardware.power@1.3",
        "android.hardware.power-V2-cpp",
        "libbase",
        "libbinder",
        "libbinder_ndk",
Loading