Loading services/surfaceflinger/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -139,6 +139,7 @@ filegroup { "Scheduler/DispSyncSource.cpp", "Scheduler/EventControlThread.cpp", "Scheduler/EventThread.cpp", "Scheduler/IdleTimer.cpp", "Scheduler/LayerHistory.cpp", "Scheduler/MessageQueue.cpp", "Scheduler/Scheduler.cpp", Loading services/surfaceflinger/Scheduler/EventThread.cpp +10 −3 Original line number Diff line number Diff line Loading @@ -48,10 +48,14 @@ EventThread::~EventThread() = default; namespace impl { EventThread::EventThread(std::unique_ptr<VSyncSource> src, ResyncWithRateLimitCallback resyncWithRateLimitCallback, InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName) const ResyncWithRateLimitCallback& resyncWithRateLimitCallback, const InterceptVSyncsCallback& interceptVSyncsCallback, const ResetIdleTimerCallback& resetIdleTimerCallback, const char* threadName) : EventThread(nullptr, std::move(src), resyncWithRateLimitCallback, interceptVSyncsCallback, threadName) {} threadName) { mResetIdleTimer = resetIdleTimerCallback; } EventThread::EventThread(VSyncSource* src, ResyncWithRateLimitCallback resyncWithRateLimitCallback, InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName) Loading Loading @@ -150,6 +154,9 @@ void EventThread::setVsyncRate(uint32_t count, const sp<EventThread::Connection> void EventThread::requestNextVsync(const sp<EventThread::Connection>& connection) { std::lock_guard<std::mutex> lock(mMutex); if (mResetIdleTimer) { mResetIdleTimer(); } if (mResyncWithRateLimitCallback) { mResyncWithRateLimitCallback(); Loading services/surfaceflinger/Scheduler/EventThread.h +7 −2 Original line number Diff line number Diff line Loading @@ -107,13 +107,15 @@ class EventThread : public android::EventThread, private VSyncSource::Callback { public: using ResyncWithRateLimitCallback = std::function<void()>; using InterceptVSyncsCallback = std::function<void(nsecs_t)>; using ResetIdleTimerCallback = std::function<void()>; // TODO(b/113612090): Once the Scheduler is complete this constructor will become obsolete. EventThread(VSyncSource* src, ResyncWithRateLimitCallback resyncWithRateLimitCallback, InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName); EventThread(std::unique_ptr<VSyncSource> src, ResyncWithRateLimitCallback resyncWithRateLimitCallback, InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName); const ResyncWithRateLimitCallback& resyncWithRateLimitCallback, const InterceptVSyncsCallback& interceptVSyncsCallback, const ResetIdleTimerCallback& resetIdleTimerCallback, const char* threadName); ~EventThread(); sp<BnDisplayEventConnection> createEventConnection() const override; Loading Loading @@ -177,6 +179,9 @@ private: // for debugging bool mDebugVsyncEnabled GUARDED_BY(mMutex) = false; // Callback that resets the idle timer when the next vsync is received. ResetIdleTimerCallback mResetIdleTimer; }; // --------------------------------------------------------------------------- Loading services/surfaceflinger/Scheduler/IdleTimer.cpp 0 → 100644 +79 −0 Original line number Diff line number Diff line /* * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "IdleTimer.h" #include <chrono> #include <thread> namespace android { namespace scheduler { IdleTimer::IdleTimer(const Interval& interval, const TimeoutCallback& timeoutCallback) : mInterval(interval), mTimeoutCallback(timeoutCallback) {} IdleTimer::~IdleTimer() { stop(); } void IdleTimer::start() { { std::lock_guard<std::mutex> lock(mMutex); mState = TimerState::RESET; } mThread = std::thread(&IdleTimer::loop, this); } void IdleTimer::stop() { { std::lock_guard<std::mutex> lock(mMutex); mState = TimerState::STOPPED; } mCondition.notify_all(); if (mThread.joinable()) { mThread.join(); } } void IdleTimer::loop() { std::lock_guard<std::mutex> lock(mMutex); while (mState != TimerState::STOPPED) { if (mState == TimerState::IDLE) { mCondition.wait(mMutex); } else if (mState == TimerState::RESET) { mState = TimerState::WAITING; if (mCondition.wait_for(mMutex, mInterval) == std::cv_status::timeout) { if (mTimeoutCallback) { mTimeoutCallback(); } } if (mState == TimerState::WAITING) { mState = TimerState::IDLE; } } } } void IdleTimer::reset() { { std::lock_guard<std::mutex> lock(mMutex); mState = TimerState::RESET; } mCondition.notify_all(); } } // namespace scheduler } // namespace android services/surfaceflinger/Scheduler/IdleTimer.h 0 → 100644 +70 −0 Original line number Diff line number Diff line /* * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include <chrono> #include <condition_variable> #include <thread> #include <android-base/thread_annotations.h> namespace android { namespace scheduler { /* * Class that sets off a timer for a given interval, and fires a callback when the * interval expires. */ class IdleTimer { public: using Interval = std::chrono::milliseconds; using TimeoutCallback = std::function<void()>; IdleTimer(const Interval& interval, const TimeoutCallback& timeoutCallback); ~IdleTimer(); void start(); void stop(); void reset(); private: // Enum to track in what state is the timer. enum class TimerState { STOPPED = 0, RESET = 1, WAITING = 2, IDLE = 3 }; // Function that loops until the condition for stopping is met. void loop(); // Thread waiting for timer to expire. std::thread mThread; // Condition used to notify mThread. std::condition_variable_any mCondition; // Lock used for synchronizing the waiting thread with the application thread. std::mutex mMutex; TimerState mState GUARDED_BY(mMutex) = TimerState::RESET; // Interval after which timer expires. const Interval mInterval; // Callback that happens when timer expires. const TimeoutCallback mTimeoutCallback; }; } // namespace scheduler } // namespace android Loading
services/surfaceflinger/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -139,6 +139,7 @@ filegroup { "Scheduler/DispSyncSource.cpp", "Scheduler/EventControlThread.cpp", "Scheduler/EventThread.cpp", "Scheduler/IdleTimer.cpp", "Scheduler/LayerHistory.cpp", "Scheduler/MessageQueue.cpp", "Scheduler/Scheduler.cpp", Loading
services/surfaceflinger/Scheduler/EventThread.cpp +10 −3 Original line number Diff line number Diff line Loading @@ -48,10 +48,14 @@ EventThread::~EventThread() = default; namespace impl { EventThread::EventThread(std::unique_ptr<VSyncSource> src, ResyncWithRateLimitCallback resyncWithRateLimitCallback, InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName) const ResyncWithRateLimitCallback& resyncWithRateLimitCallback, const InterceptVSyncsCallback& interceptVSyncsCallback, const ResetIdleTimerCallback& resetIdleTimerCallback, const char* threadName) : EventThread(nullptr, std::move(src), resyncWithRateLimitCallback, interceptVSyncsCallback, threadName) {} threadName) { mResetIdleTimer = resetIdleTimerCallback; } EventThread::EventThread(VSyncSource* src, ResyncWithRateLimitCallback resyncWithRateLimitCallback, InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName) Loading Loading @@ -150,6 +154,9 @@ void EventThread::setVsyncRate(uint32_t count, const sp<EventThread::Connection> void EventThread::requestNextVsync(const sp<EventThread::Connection>& connection) { std::lock_guard<std::mutex> lock(mMutex); if (mResetIdleTimer) { mResetIdleTimer(); } if (mResyncWithRateLimitCallback) { mResyncWithRateLimitCallback(); Loading
services/surfaceflinger/Scheduler/EventThread.h +7 −2 Original line number Diff line number Diff line Loading @@ -107,13 +107,15 @@ class EventThread : public android::EventThread, private VSyncSource::Callback { public: using ResyncWithRateLimitCallback = std::function<void()>; using InterceptVSyncsCallback = std::function<void(nsecs_t)>; using ResetIdleTimerCallback = std::function<void()>; // TODO(b/113612090): Once the Scheduler is complete this constructor will become obsolete. EventThread(VSyncSource* src, ResyncWithRateLimitCallback resyncWithRateLimitCallback, InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName); EventThread(std::unique_ptr<VSyncSource> src, ResyncWithRateLimitCallback resyncWithRateLimitCallback, InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName); const ResyncWithRateLimitCallback& resyncWithRateLimitCallback, const InterceptVSyncsCallback& interceptVSyncsCallback, const ResetIdleTimerCallback& resetIdleTimerCallback, const char* threadName); ~EventThread(); sp<BnDisplayEventConnection> createEventConnection() const override; Loading Loading @@ -177,6 +179,9 @@ private: // for debugging bool mDebugVsyncEnabled GUARDED_BY(mMutex) = false; // Callback that resets the idle timer when the next vsync is received. ResetIdleTimerCallback mResetIdleTimer; }; // --------------------------------------------------------------------------- Loading
services/surfaceflinger/Scheduler/IdleTimer.cpp 0 → 100644 +79 −0 Original line number Diff line number Diff line /* * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "IdleTimer.h" #include <chrono> #include <thread> namespace android { namespace scheduler { IdleTimer::IdleTimer(const Interval& interval, const TimeoutCallback& timeoutCallback) : mInterval(interval), mTimeoutCallback(timeoutCallback) {} IdleTimer::~IdleTimer() { stop(); } void IdleTimer::start() { { std::lock_guard<std::mutex> lock(mMutex); mState = TimerState::RESET; } mThread = std::thread(&IdleTimer::loop, this); } void IdleTimer::stop() { { std::lock_guard<std::mutex> lock(mMutex); mState = TimerState::STOPPED; } mCondition.notify_all(); if (mThread.joinable()) { mThread.join(); } } void IdleTimer::loop() { std::lock_guard<std::mutex> lock(mMutex); while (mState != TimerState::STOPPED) { if (mState == TimerState::IDLE) { mCondition.wait(mMutex); } else if (mState == TimerState::RESET) { mState = TimerState::WAITING; if (mCondition.wait_for(mMutex, mInterval) == std::cv_status::timeout) { if (mTimeoutCallback) { mTimeoutCallback(); } } if (mState == TimerState::WAITING) { mState = TimerState::IDLE; } } } } void IdleTimer::reset() { { std::lock_guard<std::mutex> lock(mMutex); mState = TimerState::RESET; } mCondition.notify_all(); } } // namespace scheduler } // namespace android
services/surfaceflinger/Scheduler/IdleTimer.h 0 → 100644 +70 −0 Original line number Diff line number Diff line /* * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include <chrono> #include <condition_variable> #include <thread> #include <android-base/thread_annotations.h> namespace android { namespace scheduler { /* * Class that sets off a timer for a given interval, and fires a callback when the * interval expires. */ class IdleTimer { public: using Interval = std::chrono::milliseconds; using TimeoutCallback = std::function<void()>; IdleTimer(const Interval& interval, const TimeoutCallback& timeoutCallback); ~IdleTimer(); void start(); void stop(); void reset(); private: // Enum to track in what state is the timer. enum class TimerState { STOPPED = 0, RESET = 1, WAITING = 2, IDLE = 3 }; // Function that loops until the condition for stopping is met. void loop(); // Thread waiting for timer to expire. std::thread mThread; // Condition used to notify mThread. std::condition_variable_any mCondition; // Lock used for synchronizing the waiting thread with the application thread. std::mutex mMutex; TimerState mState GUARDED_BY(mMutex) = TimerState::RESET; // Interval after which timer expires. const Interval mInterval; // Callback that happens when timer expires. const TimeoutCallback mTimeoutCallback; }; } // namespace scheduler } // namespace android