Loading services/surfaceflinger/Scheduler/EventThread.cpp +16 −28 Original line number Diff line number Diff line Loading @@ -171,10 +171,8 @@ DisplayEventReceiver::Event makeFrameRateOverrideFlushEvent(PhysicalDisplayId di } // namespace EventThreadConnection::EventThreadConnection(EventThread* eventThread, uid_t callingUid, ResyncCallback resyncCallback, EventRegistrationFlags eventRegistration) : resyncCallback(std::move(resyncCallback)), mOwnerUid(callingUid), : mOwnerUid(callingUid), mEventRegistration(eventRegistration), mEventThread(eventThread), mChannel(gui::BitTube::DefaultSize) {} Loading Loading @@ -250,9 +248,7 @@ namespace impl { EventThread::EventThread(const char* name, std::shared_ptr<scheduler::VsyncSchedule> vsyncSchedule, android::frametimeline::TokenManager* tokenManager, ThrottleVsyncCallback throttleVsyncCallback, GetVsyncPeriodFunction getVsyncPeriodFunction, std::chrono::nanoseconds workDuration, IEventThreadCallback& callback, std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration) : mThreadName(name), mVsyncTracer(base::StringPrintf("VSYNC-%s", name), 0), Loading @@ -261,11 +257,7 @@ EventThread::EventThread(const char* name, std::shared_ptr<scheduler::VsyncSched mVsyncSchedule(std::move(vsyncSchedule)), mVsyncRegistration(mVsyncSchedule->getDispatch(), createDispatchCallback(), name), mTokenManager(tokenManager), mThrottleVsyncCallback(std::move(throttleVsyncCallback)), mGetVsyncPeriodFunction(std::move(getVsyncPeriodFunction)) { LOG_ALWAYS_FATAL_IF(getVsyncPeriodFunction == nullptr, "getVsyncPeriodFunction must not be null"); mCallback(callback) { mThread = std::thread([this]() NO_THREAD_SAFETY_ANALYSIS { std::unique_lock<std::mutex> lock(mMutex); threadMain(lock); Loading Loading @@ -307,10 +299,10 @@ void EventThread::setDuration(std::chrono::nanoseconds workDuration, } sp<EventThreadConnection> EventThread::createEventConnection( ResyncCallback resyncCallback, EventRegistrationFlags eventRegistration) const { EventRegistrationFlags eventRegistration) const { return sp<EventThreadConnection>::make(const_cast<EventThread*>(this), IPCThreadState::self()->getCallingUid(), std::move(resyncCallback), eventRegistration); eventRegistration); } status_t EventThread::registerDisplayEventConnection(const sp<EventThreadConnection>& connection) { Loading Loading @@ -353,9 +345,7 @@ void EventThread::setVsyncRate(uint32_t rate, const sp<EventThreadConnection>& c } void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection) { if (connection->resyncCallback) { connection->resyncCallback(); } mCallback.resync(); std::lock_guard<std::mutex> lock(mMutex); Loading @@ -371,20 +361,18 @@ VsyncEventData EventThread::getLatestVsyncEventData( const sp<EventThreadConnection>& connection) const { // Resync so that the vsync is accurate with hardware. getLatestVsyncEventData is an alternate // way to get vsync data (instead of posting callbacks to Choreographer). if (connection->resyncCallback) { connection->resyncCallback(); } mCallback.resync(); VsyncEventData vsyncEventData; nsecs_t frameInterval = mGetVsyncPeriodFunction(connection->mOwnerUid); vsyncEventData.frameInterval = frameInterval; const Period frameInterval = mCallback.getVsyncPeriod(connection->mOwnerUid); vsyncEventData.frameInterval = frameInterval.ns(); const auto [presentTime, deadline] = [&]() -> std::pair<nsecs_t, nsecs_t> { std::lock_guard<std::mutex> lock(mMutex); const auto vsyncTime = mVsyncSchedule->getTracker().nextAnticipatedVSyncTimeFrom( systemTime() + mWorkDuration.get().count() + mReadyDuration.count()); return {vsyncTime, vsyncTime - mReadyDuration.count()}; }(); generateFrameTimeline(vsyncEventData, frameInterval, systemTime(SYSTEM_TIME_MONOTONIC), generateFrameTimeline(vsyncEventData, frameInterval.ns(), systemTime(SYSTEM_TIME_MONOTONIC), presentTime, deadline); return vsyncEventData; } Loading Loading @@ -549,9 +537,9 @@ bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event, connection->frameRate); } return mThrottleVsyncCallback && mThrottleVsyncCallback(event.vsync.vsyncData.preferredExpectedPresentationTime(), connection->mOwnerUid); const auto expectedPresentTime = TimePoint::fromNs(event.vsync.vsyncData.preferredExpectedPresentationTime()); return mCallback.throttleVsync(expectedPresentTime, connection->mOwnerUid); }; switch (event.header.type) { Loading Loading @@ -671,9 +659,9 @@ void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event, for (const auto& consumer : consumers) { DisplayEventReceiver::Event copy = event; if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) { const int64_t frameInterval = mGetVsyncPeriodFunction(consumer->mOwnerUid); copy.vsync.vsyncData.frameInterval = frameInterval; generateFrameTimeline(copy.vsync.vsyncData, frameInterval, copy.header.timestamp, const Period frameInterval = mCallback.getVsyncPeriod(consumer->mOwnerUid); copy.vsync.vsyncData.frameInterval = frameInterval.ns(); generateFrameTimeline(copy.vsync.vsyncData, frameInterval.ns(), copy.header.timestamp, event.vsync.vsyncData.preferredExpectedPresentationTime(), event.vsync.vsyncData.preferredDeadlineTimestamp()); } Loading services/surfaceflinger/Scheduler/EventThread.h +13 −13 Original line number Diff line number Diff line Loading @@ -54,7 +54,6 @@ using gui::VsyncEventData; // --------------------------------------------------------------------------- using ResyncCallback = std::function<void()>; using FrameRateOverride = DisplayEventReceiver::Event::FrameRateOverride; enum class VSyncRequest { Loading @@ -69,7 +68,7 @@ enum class VSyncRequest { class EventThreadConnection : public gui::BnDisplayEventConnection { public: EventThreadConnection(EventThread*, uid_t callingUid, ResyncCallback, EventThreadConnection(EventThread*, uid_t callingUid, EventRegistrationFlags eventRegistration = {}); virtual ~EventThreadConnection(); Loading @@ -80,9 +79,6 @@ public: binder::Status requestNextVsync() override; // asynchronous binder::Status getLatestVsyncEventData(ParcelableVsyncEventData* outVsyncEventData) override; // Called in response to requestNextVsync. const ResyncCallback resyncCallback; VSyncRequest vsyncRequest = VSyncRequest::None; const uid_t mOwnerUid; const EventRegistrationFlags mEventRegistration; Loading @@ -104,7 +100,7 @@ public: virtual ~EventThread(); virtual sp<EventThreadConnection> createEventConnection( ResyncCallback, EventRegistrationFlags eventRegistration = {}) const = 0; EventRegistrationFlags eventRegistration = {}) const = 0; // Feed clients with fake VSYNC, e.g. while the display is off. virtual void enableSyntheticVsync(bool) = 0; Loading Loading @@ -136,20 +132,25 @@ public: virtual void onNewVsyncSchedule(std::shared_ptr<scheduler::VsyncSchedule>) = 0; }; struct IEventThreadCallback { virtual ~IEventThreadCallback() = default; virtual bool throttleVsync(TimePoint, uid_t) = 0; virtual Period getVsyncPeriod(uid_t) = 0; virtual void resync() = 0; }; namespace impl { class EventThread : public android::EventThread { public: using ThrottleVsyncCallback = std::function<bool(nsecs_t, uid_t)>; using GetVsyncPeriodFunction = std::function<nsecs_t(uid_t)>; EventThread(const char* name, std::shared_ptr<scheduler::VsyncSchedule>, frametimeline::TokenManager*, ThrottleVsyncCallback, GetVsyncPeriodFunction, frametimeline::TokenManager*, IEventThreadCallback& callback, std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration); ~EventThread(); sp<EventThreadConnection> createEventConnection( ResyncCallback, EventRegistrationFlags eventRegistration = {}) const override; EventRegistrationFlags eventRegistration = {}) const override; status_t registerDisplayEventConnection(const sp<EventThreadConnection>& connection) override; void setVsyncRate(uint32_t rate, const sp<EventThreadConnection>& connection) override; Loading Loading @@ -214,8 +215,7 @@ private: scheduler::VSyncCallbackRegistration mVsyncRegistration GUARDED_BY(mMutex); frametimeline::TokenManager* const mTokenManager; const ThrottleVsyncCallback mThrottleVsyncCallback; const GetVsyncPeriodFunction mGetVsyncPeriodFunction; IEventThreadCallback& mCallback; std::thread mThread; mutable std::mutex mMutex; Loading services/surfaceflinger/Scheduler/Scheduler.cpp +27 −31 Original line number Diff line number Diff line Loading @@ -242,14 +242,11 @@ bool Scheduler::isVsyncInPhase(TimePoint expectedVsyncTime, Fps frameRate) const return getVsyncSchedule()->getTracker().isVSyncInPhase(expectedVsyncTime.ns(), frameRate); } impl::EventThread::ThrottleVsyncCallback Scheduler::makeThrottleVsyncCallback() const { return [this](nsecs_t expectedVsyncTime, uid_t uid) { return !isVsyncValid(TimePoint::fromNs(expectedVsyncTime), uid); }; bool Scheduler::throttleVsync(android::TimePoint expectedPresentTime, uid_t uid) { return !isVsyncValid(expectedPresentTime, uid); } impl::EventThread::GetVsyncPeriodFunction Scheduler::makeGetVsyncPeriodFunction() const { return [this](uid_t uid) { Period Scheduler::getVsyncPeriod(uid_t uid) { const auto [refreshRate, period] = [this] { std::scoped_lock lock(mDisplayLock); const auto pacesetterOpt = pacesetterDisplayLocked(); Loading @@ -263,15 +260,17 @@ impl::EventThread::GetVsyncPeriodFunction Scheduler::makeGetVsyncPeriodFunction( const auto frameRate = getFrameRateOverride(uid); if (!frameRate.has_value()) { return currentPeriod.ns(); return currentPeriod; } const auto divisor = RefreshRateSelector::getFrameRateDivisor(refreshRate, *frameRate); if (divisor <= 1) { return currentPeriod.ns(); return currentPeriod; } return currentPeriod.ns() * divisor; }; // TODO(b/299378819): the casting is not needed, but we need a flag as it might change // behaviour. return Period::fromNs(currentPeriod.ns() * divisor); } ConnectionHandle Scheduler::createEventThread(Cycle cycle, Loading @@ -279,9 +278,7 @@ ConnectionHandle Scheduler::createEventThread(Cycle cycle, std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration) { auto eventThread = std::make_unique<impl::EventThread>(cycle == Cycle::Render ? "app" : "appSf", getVsyncSchedule(), tokenManager, makeThrottleVsyncCallback(), makeGetVsyncPeriodFunction(), getVsyncSchedule(), tokenManager, *this, workDuration, readyDuration); auto& handle = cycle == Cycle::Render ? mAppConnectionHandle : mSfConnectionHandle; Loading @@ -293,7 +290,7 @@ ConnectionHandle Scheduler::createConnection(std::unique_ptr<EventThread> eventT const ConnectionHandle handle = ConnectionHandle{mNextConnectionHandleId++}; ALOGV("Creating a connection handle with ID %" PRIuPTR, handle.id); auto connection = eventThread->createEventConnection([&] { resync(); }); auto connection = eventThread->createEventConnection(); std::lock_guard<std::mutex> lock(mConnectionsLock); mConnections.emplace(handle, Connection{connection, std::move(eventThread)}); Loading @@ -307,8 +304,7 @@ sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection( std::scoped_lock lock(mConnectionsLock); RETURN_IF_INVALID_HANDLE(handle, nullptr); return mConnections[handle].thread->createEventConnection([&] { resync(); }, eventRegistration); return mConnections[handle].thread->createEventConnection(eventRegistration); }(); const auto layerId = static_cast<int32_t>(LayerHandle::getLayerId(layerHandle)); Loading services/surfaceflinger/Scheduler/Scheduler.h +5 −4 Original line number Diff line number Diff line Loading @@ -98,7 +98,7 @@ using GlobalSignals = RefreshRateSelector::GlobalSignals; class VsyncSchedule; class Scheduler : android::impl::MessageQueue { class Scheduler : public IEventThreadCallback, android::impl::MessageQueue { using Impl = android::impl::MessageQueue; public: Loading Loading @@ -217,7 +217,6 @@ public: ftl::FakeGuard guard(kMainThreadContext); resyncToHardwareVsyncLocked(id, allowToEnable, refreshRate); } void resync() EXCLUDES(mDisplayLock); void forceNextResync() { mLastResyncTime = 0; } // Passes a vsync sample to VsyncController. Returns true if Loading Loading @@ -420,8 +419,10 @@ private: void dispatchCachedReportedMode() REQUIRES(mPolicyLock) EXCLUDES(mDisplayLock); android::impl::EventThread::ThrottleVsyncCallback makeThrottleVsyncCallback() const; android::impl::EventThread::GetVsyncPeriodFunction makeGetVsyncPeriodFunction() const; // IEventThreadCallback overrides bool throttleVsync(TimePoint, uid_t) override; Period getVsyncPeriod(uid_t) override EXCLUDES(mDisplayLock); void resync() override EXCLUDES(mDisplayLock); // Stores EventThread associated with a given VSyncSource, and an initial EventThreadConnection. struct Connection { Loading services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp +9 −4 Original line number Diff line number Diff line Loading @@ -97,21 +97,26 @@ PhysicalDisplayId SchedulerFuzzer::getPhysicalDisplayId() { return displayId; } struct EventThreadCallback : public IEventThreadCallback { bool throttleVsync(TimePoint, uid_t) override { return false; } Period getVsyncPeriod(uid_t) override { return kSyncPeriod; } void resync() override {} }; void SchedulerFuzzer::fuzzEventThread() { mVsyncSchedule = std::shared_ptr<scheduler::VsyncSchedule>( new scheduler::VsyncSchedule(getPhysicalDisplayId(), std::make_shared<mock::VSyncTracker>(), std::make_shared<mock::VSyncDispatch>(), nullptr)); const auto getVsyncPeriod = [](uid_t /* uid */) { return kSyncPeriod.count(); }; EventThreadCallback callback; std::unique_ptr<android::impl::EventThread> thread = std::make_unique< android::impl::EventThread>("fuzzer", mVsyncSchedule, nullptr, nullptr, getVsyncPeriod, android::impl::EventThread>("fuzzer", mVsyncSchedule, nullptr, callback, (std::chrono::nanoseconds)mFdp.ConsumeIntegral<uint64_t>(), (std::chrono::nanoseconds)mFdp.ConsumeIntegral<uint64_t>()); thread->onHotplugReceived(getPhysicalDisplayId(), mFdp.ConsumeBool()); sp<EventThreadConnection> connection = sp<EventThreadConnection>::make(thread.get(), mFdp.ConsumeIntegral<uint16_t>(), nullptr); sp<EventThreadConnection>::make(thread.get(), mFdp.ConsumeIntegral<uint16_t>()); thread->requestNextVsync(connection); thread->setVsyncRate(mFdp.ConsumeIntegral<uint32_t>() /*rate*/, connection); Loading Loading
services/surfaceflinger/Scheduler/EventThread.cpp +16 −28 Original line number Diff line number Diff line Loading @@ -171,10 +171,8 @@ DisplayEventReceiver::Event makeFrameRateOverrideFlushEvent(PhysicalDisplayId di } // namespace EventThreadConnection::EventThreadConnection(EventThread* eventThread, uid_t callingUid, ResyncCallback resyncCallback, EventRegistrationFlags eventRegistration) : resyncCallback(std::move(resyncCallback)), mOwnerUid(callingUid), : mOwnerUid(callingUid), mEventRegistration(eventRegistration), mEventThread(eventThread), mChannel(gui::BitTube::DefaultSize) {} Loading Loading @@ -250,9 +248,7 @@ namespace impl { EventThread::EventThread(const char* name, std::shared_ptr<scheduler::VsyncSchedule> vsyncSchedule, android::frametimeline::TokenManager* tokenManager, ThrottleVsyncCallback throttleVsyncCallback, GetVsyncPeriodFunction getVsyncPeriodFunction, std::chrono::nanoseconds workDuration, IEventThreadCallback& callback, std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration) : mThreadName(name), mVsyncTracer(base::StringPrintf("VSYNC-%s", name), 0), Loading @@ -261,11 +257,7 @@ EventThread::EventThread(const char* name, std::shared_ptr<scheduler::VsyncSched mVsyncSchedule(std::move(vsyncSchedule)), mVsyncRegistration(mVsyncSchedule->getDispatch(), createDispatchCallback(), name), mTokenManager(tokenManager), mThrottleVsyncCallback(std::move(throttleVsyncCallback)), mGetVsyncPeriodFunction(std::move(getVsyncPeriodFunction)) { LOG_ALWAYS_FATAL_IF(getVsyncPeriodFunction == nullptr, "getVsyncPeriodFunction must not be null"); mCallback(callback) { mThread = std::thread([this]() NO_THREAD_SAFETY_ANALYSIS { std::unique_lock<std::mutex> lock(mMutex); threadMain(lock); Loading Loading @@ -307,10 +299,10 @@ void EventThread::setDuration(std::chrono::nanoseconds workDuration, } sp<EventThreadConnection> EventThread::createEventConnection( ResyncCallback resyncCallback, EventRegistrationFlags eventRegistration) const { EventRegistrationFlags eventRegistration) const { return sp<EventThreadConnection>::make(const_cast<EventThread*>(this), IPCThreadState::self()->getCallingUid(), std::move(resyncCallback), eventRegistration); eventRegistration); } status_t EventThread::registerDisplayEventConnection(const sp<EventThreadConnection>& connection) { Loading Loading @@ -353,9 +345,7 @@ void EventThread::setVsyncRate(uint32_t rate, const sp<EventThreadConnection>& c } void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection) { if (connection->resyncCallback) { connection->resyncCallback(); } mCallback.resync(); std::lock_guard<std::mutex> lock(mMutex); Loading @@ -371,20 +361,18 @@ VsyncEventData EventThread::getLatestVsyncEventData( const sp<EventThreadConnection>& connection) const { // Resync so that the vsync is accurate with hardware. getLatestVsyncEventData is an alternate // way to get vsync data (instead of posting callbacks to Choreographer). if (connection->resyncCallback) { connection->resyncCallback(); } mCallback.resync(); VsyncEventData vsyncEventData; nsecs_t frameInterval = mGetVsyncPeriodFunction(connection->mOwnerUid); vsyncEventData.frameInterval = frameInterval; const Period frameInterval = mCallback.getVsyncPeriod(connection->mOwnerUid); vsyncEventData.frameInterval = frameInterval.ns(); const auto [presentTime, deadline] = [&]() -> std::pair<nsecs_t, nsecs_t> { std::lock_guard<std::mutex> lock(mMutex); const auto vsyncTime = mVsyncSchedule->getTracker().nextAnticipatedVSyncTimeFrom( systemTime() + mWorkDuration.get().count() + mReadyDuration.count()); return {vsyncTime, vsyncTime - mReadyDuration.count()}; }(); generateFrameTimeline(vsyncEventData, frameInterval, systemTime(SYSTEM_TIME_MONOTONIC), generateFrameTimeline(vsyncEventData, frameInterval.ns(), systemTime(SYSTEM_TIME_MONOTONIC), presentTime, deadline); return vsyncEventData; } Loading Loading @@ -549,9 +537,9 @@ bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event, connection->frameRate); } return mThrottleVsyncCallback && mThrottleVsyncCallback(event.vsync.vsyncData.preferredExpectedPresentationTime(), connection->mOwnerUid); const auto expectedPresentTime = TimePoint::fromNs(event.vsync.vsyncData.preferredExpectedPresentationTime()); return mCallback.throttleVsync(expectedPresentTime, connection->mOwnerUid); }; switch (event.header.type) { Loading Loading @@ -671,9 +659,9 @@ void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event, for (const auto& consumer : consumers) { DisplayEventReceiver::Event copy = event; if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) { const int64_t frameInterval = mGetVsyncPeriodFunction(consumer->mOwnerUid); copy.vsync.vsyncData.frameInterval = frameInterval; generateFrameTimeline(copy.vsync.vsyncData, frameInterval, copy.header.timestamp, const Period frameInterval = mCallback.getVsyncPeriod(consumer->mOwnerUid); copy.vsync.vsyncData.frameInterval = frameInterval.ns(); generateFrameTimeline(copy.vsync.vsyncData, frameInterval.ns(), copy.header.timestamp, event.vsync.vsyncData.preferredExpectedPresentationTime(), event.vsync.vsyncData.preferredDeadlineTimestamp()); } Loading
services/surfaceflinger/Scheduler/EventThread.h +13 −13 Original line number Diff line number Diff line Loading @@ -54,7 +54,6 @@ using gui::VsyncEventData; // --------------------------------------------------------------------------- using ResyncCallback = std::function<void()>; using FrameRateOverride = DisplayEventReceiver::Event::FrameRateOverride; enum class VSyncRequest { Loading @@ -69,7 +68,7 @@ enum class VSyncRequest { class EventThreadConnection : public gui::BnDisplayEventConnection { public: EventThreadConnection(EventThread*, uid_t callingUid, ResyncCallback, EventThreadConnection(EventThread*, uid_t callingUid, EventRegistrationFlags eventRegistration = {}); virtual ~EventThreadConnection(); Loading @@ -80,9 +79,6 @@ public: binder::Status requestNextVsync() override; // asynchronous binder::Status getLatestVsyncEventData(ParcelableVsyncEventData* outVsyncEventData) override; // Called in response to requestNextVsync. const ResyncCallback resyncCallback; VSyncRequest vsyncRequest = VSyncRequest::None; const uid_t mOwnerUid; const EventRegistrationFlags mEventRegistration; Loading @@ -104,7 +100,7 @@ public: virtual ~EventThread(); virtual sp<EventThreadConnection> createEventConnection( ResyncCallback, EventRegistrationFlags eventRegistration = {}) const = 0; EventRegistrationFlags eventRegistration = {}) const = 0; // Feed clients with fake VSYNC, e.g. while the display is off. virtual void enableSyntheticVsync(bool) = 0; Loading Loading @@ -136,20 +132,25 @@ public: virtual void onNewVsyncSchedule(std::shared_ptr<scheduler::VsyncSchedule>) = 0; }; struct IEventThreadCallback { virtual ~IEventThreadCallback() = default; virtual bool throttleVsync(TimePoint, uid_t) = 0; virtual Period getVsyncPeriod(uid_t) = 0; virtual void resync() = 0; }; namespace impl { class EventThread : public android::EventThread { public: using ThrottleVsyncCallback = std::function<bool(nsecs_t, uid_t)>; using GetVsyncPeriodFunction = std::function<nsecs_t(uid_t)>; EventThread(const char* name, std::shared_ptr<scheduler::VsyncSchedule>, frametimeline::TokenManager*, ThrottleVsyncCallback, GetVsyncPeriodFunction, frametimeline::TokenManager*, IEventThreadCallback& callback, std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration); ~EventThread(); sp<EventThreadConnection> createEventConnection( ResyncCallback, EventRegistrationFlags eventRegistration = {}) const override; EventRegistrationFlags eventRegistration = {}) const override; status_t registerDisplayEventConnection(const sp<EventThreadConnection>& connection) override; void setVsyncRate(uint32_t rate, const sp<EventThreadConnection>& connection) override; Loading Loading @@ -214,8 +215,7 @@ private: scheduler::VSyncCallbackRegistration mVsyncRegistration GUARDED_BY(mMutex); frametimeline::TokenManager* const mTokenManager; const ThrottleVsyncCallback mThrottleVsyncCallback; const GetVsyncPeriodFunction mGetVsyncPeriodFunction; IEventThreadCallback& mCallback; std::thread mThread; mutable std::mutex mMutex; Loading
services/surfaceflinger/Scheduler/Scheduler.cpp +27 −31 Original line number Diff line number Diff line Loading @@ -242,14 +242,11 @@ bool Scheduler::isVsyncInPhase(TimePoint expectedVsyncTime, Fps frameRate) const return getVsyncSchedule()->getTracker().isVSyncInPhase(expectedVsyncTime.ns(), frameRate); } impl::EventThread::ThrottleVsyncCallback Scheduler::makeThrottleVsyncCallback() const { return [this](nsecs_t expectedVsyncTime, uid_t uid) { return !isVsyncValid(TimePoint::fromNs(expectedVsyncTime), uid); }; bool Scheduler::throttleVsync(android::TimePoint expectedPresentTime, uid_t uid) { return !isVsyncValid(expectedPresentTime, uid); } impl::EventThread::GetVsyncPeriodFunction Scheduler::makeGetVsyncPeriodFunction() const { return [this](uid_t uid) { Period Scheduler::getVsyncPeriod(uid_t uid) { const auto [refreshRate, period] = [this] { std::scoped_lock lock(mDisplayLock); const auto pacesetterOpt = pacesetterDisplayLocked(); Loading @@ -263,15 +260,17 @@ impl::EventThread::GetVsyncPeriodFunction Scheduler::makeGetVsyncPeriodFunction( const auto frameRate = getFrameRateOverride(uid); if (!frameRate.has_value()) { return currentPeriod.ns(); return currentPeriod; } const auto divisor = RefreshRateSelector::getFrameRateDivisor(refreshRate, *frameRate); if (divisor <= 1) { return currentPeriod.ns(); return currentPeriod; } return currentPeriod.ns() * divisor; }; // TODO(b/299378819): the casting is not needed, but we need a flag as it might change // behaviour. return Period::fromNs(currentPeriod.ns() * divisor); } ConnectionHandle Scheduler::createEventThread(Cycle cycle, Loading @@ -279,9 +278,7 @@ ConnectionHandle Scheduler::createEventThread(Cycle cycle, std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration) { auto eventThread = std::make_unique<impl::EventThread>(cycle == Cycle::Render ? "app" : "appSf", getVsyncSchedule(), tokenManager, makeThrottleVsyncCallback(), makeGetVsyncPeriodFunction(), getVsyncSchedule(), tokenManager, *this, workDuration, readyDuration); auto& handle = cycle == Cycle::Render ? mAppConnectionHandle : mSfConnectionHandle; Loading @@ -293,7 +290,7 @@ ConnectionHandle Scheduler::createConnection(std::unique_ptr<EventThread> eventT const ConnectionHandle handle = ConnectionHandle{mNextConnectionHandleId++}; ALOGV("Creating a connection handle with ID %" PRIuPTR, handle.id); auto connection = eventThread->createEventConnection([&] { resync(); }); auto connection = eventThread->createEventConnection(); std::lock_guard<std::mutex> lock(mConnectionsLock); mConnections.emplace(handle, Connection{connection, std::move(eventThread)}); Loading @@ -307,8 +304,7 @@ sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection( std::scoped_lock lock(mConnectionsLock); RETURN_IF_INVALID_HANDLE(handle, nullptr); return mConnections[handle].thread->createEventConnection([&] { resync(); }, eventRegistration); return mConnections[handle].thread->createEventConnection(eventRegistration); }(); const auto layerId = static_cast<int32_t>(LayerHandle::getLayerId(layerHandle)); Loading
services/surfaceflinger/Scheduler/Scheduler.h +5 −4 Original line number Diff line number Diff line Loading @@ -98,7 +98,7 @@ using GlobalSignals = RefreshRateSelector::GlobalSignals; class VsyncSchedule; class Scheduler : android::impl::MessageQueue { class Scheduler : public IEventThreadCallback, android::impl::MessageQueue { using Impl = android::impl::MessageQueue; public: Loading Loading @@ -217,7 +217,6 @@ public: ftl::FakeGuard guard(kMainThreadContext); resyncToHardwareVsyncLocked(id, allowToEnable, refreshRate); } void resync() EXCLUDES(mDisplayLock); void forceNextResync() { mLastResyncTime = 0; } // Passes a vsync sample to VsyncController. Returns true if Loading Loading @@ -420,8 +419,10 @@ private: void dispatchCachedReportedMode() REQUIRES(mPolicyLock) EXCLUDES(mDisplayLock); android::impl::EventThread::ThrottleVsyncCallback makeThrottleVsyncCallback() const; android::impl::EventThread::GetVsyncPeriodFunction makeGetVsyncPeriodFunction() const; // IEventThreadCallback overrides bool throttleVsync(TimePoint, uid_t) override; Period getVsyncPeriod(uid_t) override EXCLUDES(mDisplayLock); void resync() override EXCLUDES(mDisplayLock); // Stores EventThread associated with a given VSyncSource, and an initial EventThreadConnection. struct Connection { Loading
services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp +9 −4 Original line number Diff line number Diff line Loading @@ -97,21 +97,26 @@ PhysicalDisplayId SchedulerFuzzer::getPhysicalDisplayId() { return displayId; } struct EventThreadCallback : public IEventThreadCallback { bool throttleVsync(TimePoint, uid_t) override { return false; } Period getVsyncPeriod(uid_t) override { return kSyncPeriod; } void resync() override {} }; void SchedulerFuzzer::fuzzEventThread() { mVsyncSchedule = std::shared_ptr<scheduler::VsyncSchedule>( new scheduler::VsyncSchedule(getPhysicalDisplayId(), std::make_shared<mock::VSyncTracker>(), std::make_shared<mock::VSyncDispatch>(), nullptr)); const auto getVsyncPeriod = [](uid_t /* uid */) { return kSyncPeriod.count(); }; EventThreadCallback callback; std::unique_ptr<android::impl::EventThread> thread = std::make_unique< android::impl::EventThread>("fuzzer", mVsyncSchedule, nullptr, nullptr, getVsyncPeriod, android::impl::EventThread>("fuzzer", mVsyncSchedule, nullptr, callback, (std::chrono::nanoseconds)mFdp.ConsumeIntegral<uint64_t>(), (std::chrono::nanoseconds)mFdp.ConsumeIntegral<uint64_t>()); thread->onHotplugReceived(getPhysicalDisplayId(), mFdp.ConsumeBool()); sp<EventThreadConnection> connection = sp<EventThreadConnection>::make(thread.get(), mFdp.ConsumeIntegral<uint16_t>(), nullptr); sp<EventThreadConnection>::make(thread.get(), mFdp.ConsumeIntegral<uint16_t>()); thread->requestNextVsync(connection); thread->setVsyncRate(mFdp.ConsumeIntegral<uint32_t>() /*rate*/, connection); Loading