Loading services/surfaceflinger/BufferLayer.cpp +9 −0 Original line number Diff line number Diff line Loading @@ -393,6 +393,15 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, nsecs_t expectedPresentTime) { ATRACE_CALL(); // If this is not a valid vsync for the layer's uid, return and try again later const bool isVsyncValidForUid = mFlinger->mScheduler->isVsyncValid(expectedPresentTime, mOwnerUid); if (!isVsyncValidForUid) { ATRACE_NAME("!isVsyncValidForUid"); mFlinger->setTransactionFlags(eTraversalNeeded); return false; } bool refreshRequired = latchSidebandStream(recomputeVisibleRegions); if (refreshRequired) { Loading services/surfaceflinger/Scheduler/EventThread.cpp +26 −5 Original line number Diff line number Diff line Loading @@ -31,6 +31,8 @@ #include <android-base/stringprintf.h> #include <binder/IPCThreadState.h> #include <cutils/compiler.h> #include <cutils/sched_policy.h> Loading Loading @@ -123,11 +125,12 @@ DisplayEventReceiver::Event makeConfigChanged(PhysicalDisplayId displayId, } // namespace EventThreadConnection::EventThreadConnection(EventThread* eventThread, EventThreadConnection::EventThreadConnection(EventThread* eventThread, uid_t callingUid, ResyncCallback resyncCallback, ISurfaceComposer::ConfigChanged configChanged) : resyncCallback(std::move(resyncCallback)), mConfigChanged(configChanged), mOwnerUid(callingUid), mEventThread(eventThread), mChannel(gui::BitTube::DefaultSize) {} Loading Loading @@ -170,10 +173,12 @@ namespace impl { EventThread::EventThread(std::unique_ptr<VSyncSource> vsyncSource, android::frametimeline::TokenManager* tokenManager, InterceptVSyncsCallback interceptVSyncsCallback) InterceptVSyncsCallback interceptVSyncsCallback, ThrottleVsyncCallback throttleVsyncCallback) : mVSyncSource(std::move(vsyncSource)), mTokenManager(tokenManager), mInterceptVSyncsCallback(std::move(interceptVSyncsCallback)), mThrottleVsyncCallback(std::move(throttleVsyncCallback)), mThreadName(mVSyncSource->getName()) { mVSyncSource->setCallback(this); Loading Loading @@ -216,8 +221,9 @@ void EventThread::setDuration(std::chrono::nanoseconds workDuration, sp<EventThreadConnection> EventThread::createEventConnection( ResyncCallback resyncCallback, ISurfaceComposer::ConfigChanged configChanged) const { return new EventThreadConnection(const_cast<EventThread*>(this), std::move(resyncCallback), configChanged); return new EventThreadConnection(const_cast<EventThread*>(this), IPCThreadState::self()->getCallingUid(), std::move(resyncCallback), configChanged); } status_t EventThread::registerDisplayEventConnection(const sp<EventThreadConnection>& connection) { Loading Loading @@ -443,6 +449,11 @@ void EventThread::threadMain(std::unique_lock<std::mutex>& lock) { bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event, const sp<EventThreadConnection>& connection) const { const auto throttleVsync = [&] { return mThrottleVsyncCallback && mThrottleVsyncCallback(event.vsync.expectedVSyncTimestamp, connection->mOwnerUid); }; switch (event.header.type) { case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG: return true; Loading @@ -458,12 +469,22 @@ bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event, case VSyncRequest::SingleSuppressCallback: connection->vsyncRequest = VSyncRequest::None; return false; case VSyncRequest::Single: case VSyncRequest::Single: { if (throttleVsync()) { return false; } connection->vsyncRequest = VSyncRequest::SingleSuppressCallback; return true; } case VSyncRequest::Periodic: if (throttleVsync()) { return false; } return true; default: // We don't throttle vsync if the app set a vsync request rate // since there is no easy way to do that and this is a very // rare case return event.vsync.count % vsyncPeriod(connection->vsyncRequest) == 0; } Loading services/surfaceflinger/Scheduler/EventThread.h +7 −3 Original line number Diff line number Diff line Loading @@ -81,7 +81,7 @@ public: class EventThreadConnection : public BnDisplayEventConnection { public: EventThreadConnection(EventThread*, ResyncCallback, EventThreadConnection(EventThread*, uid_t callingUid, ResyncCallback, ISurfaceComposer::ConfigChanged configChanged); virtual ~EventThreadConnection(); Loading @@ -98,6 +98,8 @@ public: const ISurfaceComposer::ConfigChanged mConfigChanged = ISurfaceComposer::ConfigChanged::eConfigChangedSuppress; const uid_t mOwnerUid; private: virtual void onFirstRef(); EventThread* const mEventThread; Loading Loading @@ -143,9 +145,10 @@ namespace impl { class EventThread : public android::EventThread, private VSyncSource::Callback { public: using InterceptVSyncsCallback = std::function<void(nsecs_t)>; using ThrottleVsyncCallback = std::function<bool(nsecs_t, uid_t)>; EventThread(std::unique_ptr<VSyncSource>, frametimeline::TokenManager*, InterceptVSyncsCallback); EventThread(std::unique_ptr<VSyncSource>, frametimeline::TokenManager*, InterceptVSyncsCallback, ThrottleVsyncCallback); ~EventThread(); sp<EventThreadConnection> createEventConnection( Loading Loading @@ -196,6 +199,7 @@ private: frametimeline::TokenManager* const mTokenManager; const InterceptVSyncsCallback mInterceptVSyncsCallback; const ThrottleVsyncCallback mThrottleVsyncCallback; const char* const mThreadName; std::thread mThread; Loading services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +32 −0 Original line number Diff line number Diff line Loading @@ -625,4 +625,36 @@ RefreshRateConfigs::KernelIdleTimerAction RefreshRateConfigs::getIdleTimerAction return RefreshRateConfigs::KernelIdleTimerAction::TurnOn; } void RefreshRateConfigs::setPreferredRefreshRateForUid(uid_t uid, float refreshRateHz) { if (refreshRateHz > 0 && refreshRateHz < 1) { return; } std::lock_guard lock(mLock); if (refreshRateHz != 0) { mPreferredRefreshRateForUid[uid] = refreshRateHz; } else { mPreferredRefreshRateForUid.erase(uid); } } int RefreshRateConfigs::getRefreshRateDividerForUid(uid_t uid) const { constexpr float kThreshold = 0.1f; std::lock_guard lock(mLock); const auto iter = mPreferredRefreshRateForUid.find(uid); if (iter == mPreferredRefreshRateForUid.end()) { return 1; } const auto refreshRateHz = iter->second; const auto numPeriods = mCurrentRefreshRate->getFps() / refreshRateHz; const auto numPeriodsRounded = std::round(numPeriods); if (std::abs(numPeriods - numPeriodsRounded) > kThreshold) { return 1; } return static_cast<int>(numPeriods); } } // namespace android::scheduler services/surfaceflinger/Scheduler/RefreshRateConfigs.h +9 −0 Original line number Diff line number Diff line Loading @@ -311,6 +311,13 @@ public: // refresh rates. KernelIdleTimerAction getIdleTimerAction() const; // Stores the preferred refresh rate that an app should run at. // refreshRate == 0 means no preference. void setPreferredRefreshRateForUid(uid_t, float refreshRateHz) EXCLUDES(mLock); // Returns a divider for the current refresh rate int getRefreshRateDividerForUid(uid_t) const EXCLUDES(mLock); private: friend class RefreshRateConfigsTest; Loading Loading @@ -368,6 +375,8 @@ private: Policy mDisplayManagerPolicy GUARDED_BY(mLock); std::optional<Policy> mOverridePolicy GUARDED_BY(mLock); std::unordered_map<uid_t, float> mPreferredRefreshRateForUid GUARDED_BY(mLock); // The min and max refresh rates supported by the device. // This will not change at runtime. const RefreshRate* mMinSupportedRefreshRate; Loading Loading
services/surfaceflinger/BufferLayer.cpp +9 −0 Original line number Diff line number Diff line Loading @@ -393,6 +393,15 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, nsecs_t expectedPresentTime) { ATRACE_CALL(); // If this is not a valid vsync for the layer's uid, return and try again later const bool isVsyncValidForUid = mFlinger->mScheduler->isVsyncValid(expectedPresentTime, mOwnerUid); if (!isVsyncValidForUid) { ATRACE_NAME("!isVsyncValidForUid"); mFlinger->setTransactionFlags(eTraversalNeeded); return false; } bool refreshRequired = latchSidebandStream(recomputeVisibleRegions); if (refreshRequired) { Loading
services/surfaceflinger/Scheduler/EventThread.cpp +26 −5 Original line number Diff line number Diff line Loading @@ -31,6 +31,8 @@ #include <android-base/stringprintf.h> #include <binder/IPCThreadState.h> #include <cutils/compiler.h> #include <cutils/sched_policy.h> Loading Loading @@ -123,11 +125,12 @@ DisplayEventReceiver::Event makeConfigChanged(PhysicalDisplayId displayId, } // namespace EventThreadConnection::EventThreadConnection(EventThread* eventThread, EventThreadConnection::EventThreadConnection(EventThread* eventThread, uid_t callingUid, ResyncCallback resyncCallback, ISurfaceComposer::ConfigChanged configChanged) : resyncCallback(std::move(resyncCallback)), mConfigChanged(configChanged), mOwnerUid(callingUid), mEventThread(eventThread), mChannel(gui::BitTube::DefaultSize) {} Loading Loading @@ -170,10 +173,12 @@ namespace impl { EventThread::EventThread(std::unique_ptr<VSyncSource> vsyncSource, android::frametimeline::TokenManager* tokenManager, InterceptVSyncsCallback interceptVSyncsCallback) InterceptVSyncsCallback interceptVSyncsCallback, ThrottleVsyncCallback throttleVsyncCallback) : mVSyncSource(std::move(vsyncSource)), mTokenManager(tokenManager), mInterceptVSyncsCallback(std::move(interceptVSyncsCallback)), mThrottleVsyncCallback(std::move(throttleVsyncCallback)), mThreadName(mVSyncSource->getName()) { mVSyncSource->setCallback(this); Loading Loading @@ -216,8 +221,9 @@ void EventThread::setDuration(std::chrono::nanoseconds workDuration, sp<EventThreadConnection> EventThread::createEventConnection( ResyncCallback resyncCallback, ISurfaceComposer::ConfigChanged configChanged) const { return new EventThreadConnection(const_cast<EventThread*>(this), std::move(resyncCallback), configChanged); return new EventThreadConnection(const_cast<EventThread*>(this), IPCThreadState::self()->getCallingUid(), std::move(resyncCallback), configChanged); } status_t EventThread::registerDisplayEventConnection(const sp<EventThreadConnection>& connection) { Loading Loading @@ -443,6 +449,11 @@ void EventThread::threadMain(std::unique_lock<std::mutex>& lock) { bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event, const sp<EventThreadConnection>& connection) const { const auto throttleVsync = [&] { return mThrottleVsyncCallback && mThrottleVsyncCallback(event.vsync.expectedVSyncTimestamp, connection->mOwnerUid); }; switch (event.header.type) { case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG: return true; Loading @@ -458,12 +469,22 @@ bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event, case VSyncRequest::SingleSuppressCallback: connection->vsyncRequest = VSyncRequest::None; return false; case VSyncRequest::Single: case VSyncRequest::Single: { if (throttleVsync()) { return false; } connection->vsyncRequest = VSyncRequest::SingleSuppressCallback; return true; } case VSyncRequest::Periodic: if (throttleVsync()) { return false; } return true; default: // We don't throttle vsync if the app set a vsync request rate // since there is no easy way to do that and this is a very // rare case return event.vsync.count % vsyncPeriod(connection->vsyncRequest) == 0; } Loading
services/surfaceflinger/Scheduler/EventThread.h +7 −3 Original line number Diff line number Diff line Loading @@ -81,7 +81,7 @@ public: class EventThreadConnection : public BnDisplayEventConnection { public: EventThreadConnection(EventThread*, ResyncCallback, EventThreadConnection(EventThread*, uid_t callingUid, ResyncCallback, ISurfaceComposer::ConfigChanged configChanged); virtual ~EventThreadConnection(); Loading @@ -98,6 +98,8 @@ public: const ISurfaceComposer::ConfigChanged mConfigChanged = ISurfaceComposer::ConfigChanged::eConfigChangedSuppress; const uid_t mOwnerUid; private: virtual void onFirstRef(); EventThread* const mEventThread; Loading Loading @@ -143,9 +145,10 @@ namespace impl { class EventThread : public android::EventThread, private VSyncSource::Callback { public: using InterceptVSyncsCallback = std::function<void(nsecs_t)>; using ThrottleVsyncCallback = std::function<bool(nsecs_t, uid_t)>; EventThread(std::unique_ptr<VSyncSource>, frametimeline::TokenManager*, InterceptVSyncsCallback); EventThread(std::unique_ptr<VSyncSource>, frametimeline::TokenManager*, InterceptVSyncsCallback, ThrottleVsyncCallback); ~EventThread(); sp<EventThreadConnection> createEventConnection( Loading Loading @@ -196,6 +199,7 @@ private: frametimeline::TokenManager* const mTokenManager; const InterceptVSyncsCallback mInterceptVSyncsCallback; const ThrottleVsyncCallback mThrottleVsyncCallback; const char* const mThreadName; std::thread mThread; Loading
services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +32 −0 Original line number Diff line number Diff line Loading @@ -625,4 +625,36 @@ RefreshRateConfigs::KernelIdleTimerAction RefreshRateConfigs::getIdleTimerAction return RefreshRateConfigs::KernelIdleTimerAction::TurnOn; } void RefreshRateConfigs::setPreferredRefreshRateForUid(uid_t uid, float refreshRateHz) { if (refreshRateHz > 0 && refreshRateHz < 1) { return; } std::lock_guard lock(mLock); if (refreshRateHz != 0) { mPreferredRefreshRateForUid[uid] = refreshRateHz; } else { mPreferredRefreshRateForUid.erase(uid); } } int RefreshRateConfigs::getRefreshRateDividerForUid(uid_t uid) const { constexpr float kThreshold = 0.1f; std::lock_guard lock(mLock); const auto iter = mPreferredRefreshRateForUid.find(uid); if (iter == mPreferredRefreshRateForUid.end()) { return 1; } const auto refreshRateHz = iter->second; const auto numPeriods = mCurrentRefreshRate->getFps() / refreshRateHz; const auto numPeriodsRounded = std::round(numPeriods); if (std::abs(numPeriods - numPeriodsRounded) > kThreshold) { return 1; } return static_cast<int>(numPeriods); } } // namespace android::scheduler
services/surfaceflinger/Scheduler/RefreshRateConfigs.h +9 −0 Original line number Diff line number Diff line Loading @@ -311,6 +311,13 @@ public: // refresh rates. KernelIdleTimerAction getIdleTimerAction() const; // Stores the preferred refresh rate that an app should run at. // refreshRate == 0 means no preference. void setPreferredRefreshRateForUid(uid_t, float refreshRateHz) EXCLUDES(mLock); // Returns a divider for the current refresh rate int getRefreshRateDividerForUid(uid_t) const EXCLUDES(mLock); private: friend class RefreshRateConfigsTest; Loading Loading @@ -368,6 +375,8 @@ private: Policy mDisplayManagerPolicy GUARDED_BY(mLock); std::optional<Policy> mOverridePolicy GUARDED_BY(mLock); std::unordered_map<uid_t, float> mPreferredRefreshRateForUid GUARDED_BY(mLock); // The min and max refresh rates supported by the device. // This will not change at runtime. const RefreshRate* mMinSupportedRefreshRate; Loading