Loading services/surfaceflinger/Scheduler/IdleTimer.cpp +35 −11 Original line number Diff line number Diff line Loading @@ -22,8 +22,9 @@ namespace android { namespace scheduler { IdleTimer::IdleTimer(const Interval& interval, const TimeoutCallback& timeoutCallback) : mInterval(interval), mTimeoutCallback(timeoutCallback) {} IdleTimer::IdleTimer(const Interval& interval, const ResetCallback& resetCallback, const TimeoutCallback& timeoutCallback) : mInterval(interval), mResetCallback(resetCallback), mTimeoutCallback(timeoutCallback) {} IdleTimer::~IdleTimer() { stop(); Loading @@ -49,11 +50,34 @@ void IdleTimer::stop() { } void IdleTimer::loop() { while (true) { bool triggerReset = false; bool triggerTimeout = false; { std::lock_guard<std::mutex> lock(mMutex); while (mState != TimerState::STOPPED) { if (mState == TimerState::STOPPED) { break; } if (mState == TimerState::IDLE) { mCondition.wait(mMutex); } else if (mState == TimerState::RESET) { continue; } if (mState == TimerState::RESET) { triggerReset = true; } } if (triggerReset && mResetCallback) { mResetCallback(); } { // lock the mutex again. someone might have called stop meanwhile std::lock_guard<std::mutex> lock(mMutex); if (mState == TimerState::STOPPED) { break; } auto triggerTime = std::chrono::steady_clock::now() + mInterval; mState = TimerState::WAITING; while (mState == TimerState::WAITING) { Loading @@ -62,14 +86,14 @@ void IdleTimer::loop() { if (waitTime > zero) mCondition.wait_for(mMutex, waitTime); if (mState == TimerState::WAITING && (triggerTime - std::chrono::steady_clock::now()) <= zero) { if (mTimeoutCallback) { mTimeoutCallback(); } triggerTimeout = true; mState = TimerState::IDLE; } } } if (triggerTimeout && mTimeoutCallback) { mTimeoutCallback(); } } } // namespace scheduler Loading services/surfaceflinger/Scheduler/IdleTimer.h +6 −1 Original line number Diff line number Diff line Loading @@ -32,9 +32,11 @@ namespace scheduler { class IdleTimer { public: using Interval = std::chrono::milliseconds; using ResetCallback = std::function<void()>; using TimeoutCallback = std::function<void()>; IdleTimer(const Interval& interval, const TimeoutCallback& timeoutCallback); IdleTimer(const Interval& interval, const ResetCallback& resetCallback, const TimeoutCallback& timeoutCallback); ~IdleTimer(); void start(); Loading Loading @@ -62,6 +64,9 @@ private: // Interval after which timer expires. const Interval mInterval; // Callback that happens when timer resets. const ResetCallback mResetCallback; // Callback that happens when timer expires. const TimeoutCallback mTimeoutCallback; }; Loading services/surfaceflinger/Scheduler/Scheduler.cpp +19 −17 Original line number Diff line number Diff line Loading @@ -75,6 +75,7 @@ Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function) if (mSetIdleTimerMs > 0) { mIdleTimer = std::make_unique<scheduler::IdleTimer>(std::chrono::milliseconds(mSetIdleTimerMs), [this] { resetTimerCallback(); }, [this] { expiredTimerCallback(); }); mIdleTimer->start(); } Loading @@ -87,7 +88,6 @@ Scheduler::~Scheduler() { sp<Scheduler::ConnectionHandle> Scheduler::createConnection( const char* connectionName, int64_t phaseOffsetNs, ResyncCallback resyncCallback, ResetIdleTimerCallback resetIdleTimerCallback, impl::EventThread::InterceptVSyncsCallback interceptCallback) { const int64_t id = sNextId++; ALOGV("Creating a connection handle with ID: %" PRId64 "\n", id); Loading @@ -97,8 +97,7 @@ sp<Scheduler::ConnectionHandle> Scheduler::createConnection( std::move(interceptCallback)); auto eventThreadConnection = createConnectionInternal(eventThread.get(), std::move(resyncCallback), std::move(resetIdleTimerCallback)); createConnectionInternal(eventThread.get(), std::move(resyncCallback)); mConnections.emplace(id, std::make_unique<Connection>(new ConnectionHandle(id), eventThreadConnection, Loading @@ -115,26 +114,17 @@ std::unique_ptr<EventThread> Scheduler::makeEventThread( std::move(interceptCallback), connectionName); } sp<EventThreadConnection> Scheduler::createConnectionInternal( EventThread* eventThread, ResyncCallback&& resyncCallback, ResetIdleTimerCallback&& resetIdleTimerCallback) { sp<EventThreadConnection> Scheduler::createConnectionInternal(EventThread* eventThread, ResyncCallback&& resyncCallback) { return eventThread->createEventConnection(std::move(resyncCallback), [this, resetIdleTimerCallback = std::move(resetIdleTimerCallback)] { resetIdleTimer(); if (resetIdleTimerCallback) { resetIdleTimerCallback(); } }); [this] { resetIdleTimer(); }); } sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection( const sp<Scheduler::ConnectionHandle>& handle, ResyncCallback resyncCallback, ResetIdleTimerCallback resetIdleTimerCallback) { const sp<Scheduler::ConnectionHandle>& handle, ResyncCallback resyncCallback) { RETURN_VALUE_IF_INVALID(nullptr); return createConnectionInternal(mConnections[handle->id]->thread.get(), std::move(resyncCallback), std::move(resetIdleTimerCallback)); std::move(resyncCallback)); } EventThread* Scheduler::getEventThread(const sp<Scheduler::ConnectionHandle>& handle) { Loading Loading @@ -263,6 +253,11 @@ void Scheduler::setExpiredIdleTimerCallback(const ExpiredIdleTimerCallback& expi mExpiredTimerCallback = expiredTimerCallback; } void Scheduler::setResetIdleTimerCallback(const ResetIdleTimerCallback& resetTimerCallback) { std::lock_guard<std::mutex> lock(mCallbackLock); mResetTimerCallback = resetTimerCallback; } void Scheduler::updateFrameSkipping(const int64_t skipCount) { ATRACE_INT("FrameSkipCount", skipCount); if (mSkipCount != skipCount) { Loading Loading @@ -351,6 +346,13 @@ void Scheduler::determineTimestampAverage(bool isAutoTimestamp, const nsecs_t fr void Scheduler::resetIdleTimer() { if (mIdleTimer) { mIdleTimer->reset(); } } void Scheduler::resetTimerCallback() { std::lock_guard<std::mutex> lock(mCallbackLock); if (mResetTimerCallback) { mResetTimerCallback(); ATRACE_INT("ExpiredIdleTimer", 0); } } Loading services/surfaceflinger/Scheduler/Scheduler.h +9 −6 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ class EventControlThread; class Scheduler { public: using ExpiredIdleTimerCallback = std::function<void()>; using ResetIdleTimerCallback = std::function<void()>; // Enum to indicate whether to start the transaction early, or at vsync time. enum class TransactionStart { EARLY, NORMAL }; Loading Loading @@ -72,12 +73,11 @@ public: /** Creates an EventThread connection. */ sp<ConnectionHandle> createConnection(const char* connectionName, int64_t phaseOffsetNs, ResyncCallback, ResetIdleTimerCallback, ResyncCallback, impl::EventThread::InterceptVSyncsCallback); sp<IDisplayEventConnection> createDisplayEventConnection(const sp<ConnectionHandle>& handle, ResyncCallback, ResetIdleTimerCallback); ResyncCallback); // Getter methods. EventThread* getEventThread(const sp<ConnectionHandle>& handle); Loading Loading @@ -117,6 +117,8 @@ public: void incrementFrameCounter(); // Callback that gets invoked once the idle timer expires. void setExpiredIdleTimerCallback(const ExpiredIdleTimerCallback& expiredTimerCallback); // Callback that gets invoked once the idle timer is reset. void setResetIdleTimerCallback(const ResetIdleTimerCallback& resetTimerCallback); // Returns relevant information about Scheduler for dumpsys purposes. std::string doDump(); Loading @@ -127,8 +129,7 @@ protected: private: // Creates a connection on the given EventThread and forwards the given callbacks. sp<EventThreadConnection> createConnectionInternal(EventThread*, ResyncCallback&&, ResetIdleTimerCallback&&); sp<EventThreadConnection> createConnectionInternal(EventThread*, ResyncCallback&&); nsecs_t calculateAverage() const; void updateFrameSkipping(const int64_t skipCount); Loading @@ -140,10 +141,11 @@ private: void determineTimestampAverage(bool isAutoTimestamp, const nsecs_t framePresentTime); // Function that resets the idle timer. void resetIdleTimer(); // Function that is called when the timer resets. void resetTimerCallback(); // Function that is called when the timer expires. void expiredTimerCallback(); // If fences from sync Framework are supported. const bool mHasSyncFramework; Loading Loading @@ -184,6 +186,7 @@ private: std::mutex mCallbackLock; ExpiredIdleTimerCallback mExpiredTimerCallback GUARDED_BY(mCallbackLock); ExpiredIdleTimerCallback mResetTimerCallback GUARDED_BY(mCallbackLock); }; } // namespace android services/surfaceflinger/SurfaceFlinger.cpp +7 −13 Original line number Diff line number Diff line Loading @@ -635,17 +635,13 @@ void SurfaceFlinger::init() { mPhaseOffsets->setRefreshRateType( scheduler::RefreshRateConfigs::RefreshRateType::PERFORMANCE); auto resetIdleTimerCallback = std::bind(&SurfaceFlinger::setRefreshRateTo, this, RefreshRateType::PERFORMANCE); mAppConnectionHandle = mScheduler->createConnection("appConnection", mPhaseOffsets->getCurrentAppOffset(), resyncCallback, resetIdleTimerCallback, resyncCallback, impl::EventThread::InterceptVSyncsCallback()); mSfConnectionHandle = mScheduler->createConnection("sfConnection", mPhaseOffsets->getCurrentSfOffset(), resyncCallback, resetIdleTimerCallback, [this](nsecs_t timestamp) { resyncCallback, [this](nsecs_t timestamp) { mInterceptor->saveVSyncEvent(timestamp); }); Loading Loading @@ -749,6 +745,10 @@ void SurfaceFlinger::init() { Mutex::Autolock lock(mStateLock); setRefreshRateTo(RefreshRateType::DEFAULT); }); mScheduler->setResetIdleTimerCallback([this] { Mutex::Autolock lock(mStateLock); setRefreshRateTo(RefreshRateType::PERFORMANCE); }); mRefreshRateStats = std::make_unique<scheduler::RefreshRateStats>(getHwComposer().getConfigs( Loading Loading @@ -1345,16 +1345,10 @@ sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection( }); if (mUseScheduler) { auto resetIdleTimerCallback = [this] { Mutex::Autolock lock(mStateLock); setRefreshRateTo(RefreshRateType::PERFORMANCE); }; const auto& handle = vsyncSource == eVsyncSourceSurfaceFlinger ? mSfConnectionHandle : mAppConnectionHandle; return mScheduler->createDisplayEventConnection(handle, std::move(resyncCallback), std::move(resetIdleTimerCallback)); return mScheduler->createDisplayEventConnection(handle, std::move(resyncCallback)); } else { if (vsyncSource == eVsyncSourceSurfaceFlinger) { return mSFEventThread->createEventConnection(resyncCallback, ResetIdleTimerCallback()); Loading Loading
services/surfaceflinger/Scheduler/IdleTimer.cpp +35 −11 Original line number Diff line number Diff line Loading @@ -22,8 +22,9 @@ namespace android { namespace scheduler { IdleTimer::IdleTimer(const Interval& interval, const TimeoutCallback& timeoutCallback) : mInterval(interval), mTimeoutCallback(timeoutCallback) {} IdleTimer::IdleTimer(const Interval& interval, const ResetCallback& resetCallback, const TimeoutCallback& timeoutCallback) : mInterval(interval), mResetCallback(resetCallback), mTimeoutCallback(timeoutCallback) {} IdleTimer::~IdleTimer() { stop(); Loading @@ -49,11 +50,34 @@ void IdleTimer::stop() { } void IdleTimer::loop() { while (true) { bool triggerReset = false; bool triggerTimeout = false; { std::lock_guard<std::mutex> lock(mMutex); while (mState != TimerState::STOPPED) { if (mState == TimerState::STOPPED) { break; } if (mState == TimerState::IDLE) { mCondition.wait(mMutex); } else if (mState == TimerState::RESET) { continue; } if (mState == TimerState::RESET) { triggerReset = true; } } if (triggerReset && mResetCallback) { mResetCallback(); } { // lock the mutex again. someone might have called stop meanwhile std::lock_guard<std::mutex> lock(mMutex); if (mState == TimerState::STOPPED) { break; } auto triggerTime = std::chrono::steady_clock::now() + mInterval; mState = TimerState::WAITING; while (mState == TimerState::WAITING) { Loading @@ -62,14 +86,14 @@ void IdleTimer::loop() { if (waitTime > zero) mCondition.wait_for(mMutex, waitTime); if (mState == TimerState::WAITING && (triggerTime - std::chrono::steady_clock::now()) <= zero) { if (mTimeoutCallback) { mTimeoutCallback(); } triggerTimeout = true; mState = TimerState::IDLE; } } } if (triggerTimeout && mTimeoutCallback) { mTimeoutCallback(); } } } // namespace scheduler Loading
services/surfaceflinger/Scheduler/IdleTimer.h +6 −1 Original line number Diff line number Diff line Loading @@ -32,9 +32,11 @@ namespace scheduler { class IdleTimer { public: using Interval = std::chrono::milliseconds; using ResetCallback = std::function<void()>; using TimeoutCallback = std::function<void()>; IdleTimer(const Interval& interval, const TimeoutCallback& timeoutCallback); IdleTimer(const Interval& interval, const ResetCallback& resetCallback, const TimeoutCallback& timeoutCallback); ~IdleTimer(); void start(); Loading Loading @@ -62,6 +64,9 @@ private: // Interval after which timer expires. const Interval mInterval; // Callback that happens when timer resets. const ResetCallback mResetCallback; // Callback that happens when timer expires. const TimeoutCallback mTimeoutCallback; }; Loading
services/surfaceflinger/Scheduler/Scheduler.cpp +19 −17 Original line number Diff line number Diff line Loading @@ -75,6 +75,7 @@ Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function) if (mSetIdleTimerMs > 0) { mIdleTimer = std::make_unique<scheduler::IdleTimer>(std::chrono::milliseconds(mSetIdleTimerMs), [this] { resetTimerCallback(); }, [this] { expiredTimerCallback(); }); mIdleTimer->start(); } Loading @@ -87,7 +88,6 @@ Scheduler::~Scheduler() { sp<Scheduler::ConnectionHandle> Scheduler::createConnection( const char* connectionName, int64_t phaseOffsetNs, ResyncCallback resyncCallback, ResetIdleTimerCallback resetIdleTimerCallback, impl::EventThread::InterceptVSyncsCallback interceptCallback) { const int64_t id = sNextId++; ALOGV("Creating a connection handle with ID: %" PRId64 "\n", id); Loading @@ -97,8 +97,7 @@ sp<Scheduler::ConnectionHandle> Scheduler::createConnection( std::move(interceptCallback)); auto eventThreadConnection = createConnectionInternal(eventThread.get(), std::move(resyncCallback), std::move(resetIdleTimerCallback)); createConnectionInternal(eventThread.get(), std::move(resyncCallback)); mConnections.emplace(id, std::make_unique<Connection>(new ConnectionHandle(id), eventThreadConnection, Loading @@ -115,26 +114,17 @@ std::unique_ptr<EventThread> Scheduler::makeEventThread( std::move(interceptCallback), connectionName); } sp<EventThreadConnection> Scheduler::createConnectionInternal( EventThread* eventThread, ResyncCallback&& resyncCallback, ResetIdleTimerCallback&& resetIdleTimerCallback) { sp<EventThreadConnection> Scheduler::createConnectionInternal(EventThread* eventThread, ResyncCallback&& resyncCallback) { return eventThread->createEventConnection(std::move(resyncCallback), [this, resetIdleTimerCallback = std::move(resetIdleTimerCallback)] { resetIdleTimer(); if (resetIdleTimerCallback) { resetIdleTimerCallback(); } }); [this] { resetIdleTimer(); }); } sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection( const sp<Scheduler::ConnectionHandle>& handle, ResyncCallback resyncCallback, ResetIdleTimerCallback resetIdleTimerCallback) { const sp<Scheduler::ConnectionHandle>& handle, ResyncCallback resyncCallback) { RETURN_VALUE_IF_INVALID(nullptr); return createConnectionInternal(mConnections[handle->id]->thread.get(), std::move(resyncCallback), std::move(resetIdleTimerCallback)); std::move(resyncCallback)); } EventThread* Scheduler::getEventThread(const sp<Scheduler::ConnectionHandle>& handle) { Loading Loading @@ -263,6 +253,11 @@ void Scheduler::setExpiredIdleTimerCallback(const ExpiredIdleTimerCallback& expi mExpiredTimerCallback = expiredTimerCallback; } void Scheduler::setResetIdleTimerCallback(const ResetIdleTimerCallback& resetTimerCallback) { std::lock_guard<std::mutex> lock(mCallbackLock); mResetTimerCallback = resetTimerCallback; } void Scheduler::updateFrameSkipping(const int64_t skipCount) { ATRACE_INT("FrameSkipCount", skipCount); if (mSkipCount != skipCount) { Loading Loading @@ -351,6 +346,13 @@ void Scheduler::determineTimestampAverage(bool isAutoTimestamp, const nsecs_t fr void Scheduler::resetIdleTimer() { if (mIdleTimer) { mIdleTimer->reset(); } } void Scheduler::resetTimerCallback() { std::lock_guard<std::mutex> lock(mCallbackLock); if (mResetTimerCallback) { mResetTimerCallback(); ATRACE_INT("ExpiredIdleTimer", 0); } } Loading
services/surfaceflinger/Scheduler/Scheduler.h +9 −6 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ class EventControlThread; class Scheduler { public: using ExpiredIdleTimerCallback = std::function<void()>; using ResetIdleTimerCallback = std::function<void()>; // Enum to indicate whether to start the transaction early, or at vsync time. enum class TransactionStart { EARLY, NORMAL }; Loading Loading @@ -72,12 +73,11 @@ public: /** Creates an EventThread connection. */ sp<ConnectionHandle> createConnection(const char* connectionName, int64_t phaseOffsetNs, ResyncCallback, ResetIdleTimerCallback, ResyncCallback, impl::EventThread::InterceptVSyncsCallback); sp<IDisplayEventConnection> createDisplayEventConnection(const sp<ConnectionHandle>& handle, ResyncCallback, ResetIdleTimerCallback); ResyncCallback); // Getter methods. EventThread* getEventThread(const sp<ConnectionHandle>& handle); Loading Loading @@ -117,6 +117,8 @@ public: void incrementFrameCounter(); // Callback that gets invoked once the idle timer expires. void setExpiredIdleTimerCallback(const ExpiredIdleTimerCallback& expiredTimerCallback); // Callback that gets invoked once the idle timer is reset. void setResetIdleTimerCallback(const ResetIdleTimerCallback& resetTimerCallback); // Returns relevant information about Scheduler for dumpsys purposes. std::string doDump(); Loading @@ -127,8 +129,7 @@ protected: private: // Creates a connection on the given EventThread and forwards the given callbacks. sp<EventThreadConnection> createConnectionInternal(EventThread*, ResyncCallback&&, ResetIdleTimerCallback&&); sp<EventThreadConnection> createConnectionInternal(EventThread*, ResyncCallback&&); nsecs_t calculateAverage() const; void updateFrameSkipping(const int64_t skipCount); Loading @@ -140,10 +141,11 @@ private: void determineTimestampAverage(bool isAutoTimestamp, const nsecs_t framePresentTime); // Function that resets the idle timer. void resetIdleTimer(); // Function that is called when the timer resets. void resetTimerCallback(); // Function that is called when the timer expires. void expiredTimerCallback(); // If fences from sync Framework are supported. const bool mHasSyncFramework; Loading Loading @@ -184,6 +186,7 @@ private: std::mutex mCallbackLock; ExpiredIdleTimerCallback mExpiredTimerCallback GUARDED_BY(mCallbackLock); ExpiredIdleTimerCallback mResetTimerCallback GUARDED_BY(mCallbackLock); }; } // namespace android
services/surfaceflinger/SurfaceFlinger.cpp +7 −13 Original line number Diff line number Diff line Loading @@ -635,17 +635,13 @@ void SurfaceFlinger::init() { mPhaseOffsets->setRefreshRateType( scheduler::RefreshRateConfigs::RefreshRateType::PERFORMANCE); auto resetIdleTimerCallback = std::bind(&SurfaceFlinger::setRefreshRateTo, this, RefreshRateType::PERFORMANCE); mAppConnectionHandle = mScheduler->createConnection("appConnection", mPhaseOffsets->getCurrentAppOffset(), resyncCallback, resetIdleTimerCallback, resyncCallback, impl::EventThread::InterceptVSyncsCallback()); mSfConnectionHandle = mScheduler->createConnection("sfConnection", mPhaseOffsets->getCurrentSfOffset(), resyncCallback, resetIdleTimerCallback, [this](nsecs_t timestamp) { resyncCallback, [this](nsecs_t timestamp) { mInterceptor->saveVSyncEvent(timestamp); }); Loading Loading @@ -749,6 +745,10 @@ void SurfaceFlinger::init() { Mutex::Autolock lock(mStateLock); setRefreshRateTo(RefreshRateType::DEFAULT); }); mScheduler->setResetIdleTimerCallback([this] { Mutex::Autolock lock(mStateLock); setRefreshRateTo(RefreshRateType::PERFORMANCE); }); mRefreshRateStats = std::make_unique<scheduler::RefreshRateStats>(getHwComposer().getConfigs( Loading Loading @@ -1345,16 +1345,10 @@ sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection( }); if (mUseScheduler) { auto resetIdleTimerCallback = [this] { Mutex::Autolock lock(mStateLock); setRefreshRateTo(RefreshRateType::PERFORMANCE); }; const auto& handle = vsyncSource == eVsyncSourceSurfaceFlinger ? mSfConnectionHandle : mAppConnectionHandle; return mScheduler->createDisplayEventConnection(handle, std::move(resyncCallback), std::move(resetIdleTimerCallback)); return mScheduler->createDisplayEventConnection(handle, std::move(resyncCallback)); } else { if (vsyncSource == eVsyncSourceSurfaceFlinger) { return mSFEventThread->createEventConnection(resyncCallback, ResetIdleTimerCallback()); Loading