Loading services/surfaceflinger/CompositionEngine/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -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", Loading services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp +181 −211 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -62,8 +61,6 @@ using android::hardware::power::WorkDuration; using scheduler::OneShotTimer; class AidlPowerHalWrapper; PowerAdvisor::~PowerAdvisor() = default; namespace { Loading Loading @@ -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; } Loading @@ -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) { Loading @@ -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"); Loading @@ -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"); Loading @@ -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()) { Loading @@ -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()); Loading @@ -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()) { Loading @@ -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()) { Loading @@ -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()) { Loading @@ -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 Loading @@ -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); Loading services/surfaceflinger/DisplayHardware/PowerAdvisor.h +64 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <utils/Mutex.h> #include <android/hardware/power/IPower.h> #include <ui/DisplayIdentification.h> #include "../Scheduler/OneShotTimer.h" Loading Loading @@ -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 services/surfaceflinger/SurfaceFlinger.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -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; Loading services/surfaceflinger/tests/fakehwc/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
services/surfaceflinger/CompositionEngine/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -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", Loading
services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp +181 −211 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -62,8 +61,6 @@ using android::hardware::power::WorkDuration; using scheduler::OneShotTimer; class AidlPowerHalWrapper; PowerAdvisor::~PowerAdvisor() = default; namespace { Loading Loading @@ -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; } Loading @@ -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) { Loading @@ -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"); Loading @@ -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"); Loading @@ -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()) { Loading @@ -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()); Loading @@ -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()) { Loading @@ -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()) { Loading @@ -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()) { Loading @@ -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 Loading @@ -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); Loading
services/surfaceflinger/DisplayHardware/PowerAdvisor.h +64 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <utils/Mutex.h> #include <android/hardware/power/IPower.h> #include <ui/DisplayIdentification.h> #include "../Scheduler/OneShotTimer.h" Loading Loading @@ -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
services/surfaceflinger/SurfaceFlinger.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -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; Loading
services/surfaceflinger/tests/fakehwc/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -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