Loading services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h +1 −1 Original line number Original line Diff line number Diff line Loading @@ -93,7 +93,7 @@ public: MOCK_METHOD2(onHotplug, MOCK_METHOD2(onHotplug, std::optional<DisplayIdentificationInfo>(hal::HWDisplayId, hal::Connection)); std::optional<DisplayIdentificationInfo>(hal::HWDisplayId, hal::Connection)); MOCK_CONST_METHOD0(updatesDeviceProductInfoOnHotplugReconnect, bool()); MOCK_CONST_METHOD0(updatesDeviceProductInfoOnHotplugReconnect, bool()); MOCK_METHOD2(onVsync, bool(hal::HWDisplayId, int64_t)); MOCK_METHOD(std::optional<PhysicalDisplayId>, onVsync, (hal::HWDisplayId, int64_t)); MOCK_METHOD2(setVsyncEnabled, void(PhysicalDisplayId, hal::Vsync)); MOCK_METHOD2(setVsyncEnabled, void(PhysicalDisplayId, hal::Vsync)); MOCK_CONST_METHOD1(isConnected, bool(PhysicalDisplayId)); MOCK_CONST_METHOD1(isConnected, bool(PhysicalDisplayId)); MOCK_CONST_METHOD1(getModes, std::vector<HWComposer::HWCDisplayMode>(PhysicalDisplayId)); MOCK_CONST_METHOD1(getModes, std::vector<HWComposer::HWCDisplayMode>(PhysicalDisplayId)); Loading services/surfaceflinger/DisplayHardware/HWComposer.cpp +12 −10 Original line number Original line Diff line number Diff line Loading @@ -30,6 +30,7 @@ #include <compositionengine/Output.h> #include <compositionengine/Output.h> #include <compositionengine/OutputLayer.h> #include <compositionengine/OutputLayer.h> #include <compositionengine/impl/OutputLayerCompositionState.h> #include <compositionengine/impl/OutputLayerCompositionState.h> #include <ftl/concat.h> #include <log/log.h> #include <log/log.h> #include <ui/DebugUtils.h> #include <ui/DebugUtils.h> #include <ui/GraphicBuffer.h> #include <ui/GraphicBuffer.h> Loading Loading @@ -148,16 +149,17 @@ bool HWComposer::updatesDeviceProductInfoOnHotplugReconnect() const { return mUpdateDeviceProductInfoOnHotplugReconnect; return mUpdateDeviceProductInfoOnHotplugReconnect; } } bool HWComposer::onVsync(hal::HWDisplayId hwcDisplayId, nsecs_t timestamp) { std::optional<PhysicalDisplayId> HWComposer::onVsync(hal::HWDisplayId hwcDisplayId, const auto displayId = toPhysicalDisplayId(hwcDisplayId); nsecs_t timestamp) { if (!displayId) { const auto displayIdOpt = toPhysicalDisplayId(hwcDisplayId); if (!displayIdOpt) { LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid HWC display"); LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid HWC display"); return false; return {}; } } RETURN_IF_INVALID_DISPLAY(*displayId, false); RETURN_IF_INVALID_DISPLAY(*displayIdOpt, {}); auto& displayData = mDisplayData[*displayId]; auto& displayData = mDisplayData[*displayIdOpt]; { { // There have been reports of HWCs that signal several vsync events // There have been reports of HWCs that signal several vsync events Loading @@ -166,18 +168,18 @@ bool HWComposer::onVsync(hal::HWDisplayId hwcDisplayId, nsecs_t timestamp) { // out here so they don't cause havoc downstream. // out here so they don't cause havoc downstream. if (timestamp == displayData.lastPresentTimestamp) { if (timestamp == displayData.lastPresentTimestamp) { ALOGW("Ignoring duplicate VSYNC event from HWC for display %s (t=%" PRId64 ")", ALOGW("Ignoring duplicate VSYNC event from HWC for display %s (t=%" PRId64 ")", to_string(*displayId).c_str(), timestamp); to_string(*displayIdOpt).c_str(), timestamp); return false; return {}; } } displayData.lastPresentTimestamp = timestamp; displayData.lastPresentTimestamp = timestamp; } } const auto tag = "HW_VSYNC_" + to_string(*displayId); const ftl::Concat tag("HW_VSYNC_", displayIdOpt->value); ATRACE_INT(tag.c_str(), displayData.vsyncTraceToggle); ATRACE_INT(tag.c_str(), displayData.vsyncTraceToggle); displayData.vsyncTraceToggle = !displayData.vsyncTraceToggle; displayData.vsyncTraceToggle = !displayData.vsyncTraceToggle; return true; return displayIdOpt; } } size_t HWComposer::getMaxVirtualDisplayCount() const { size_t HWComposer::getMaxVirtualDisplayCount() const { Loading services/surfaceflinger/DisplayHardware/HWComposer.h +5 −2 Original line number Original line Diff line number Diff line Loading @@ -221,7 +221,10 @@ public: // TODO(b/157555476): Remove when the framework has proper support for headless mode // TODO(b/157555476): Remove when the framework has proper support for headless mode virtual bool updatesDeviceProductInfoOnHotplugReconnect() const = 0; virtual bool updatesDeviceProductInfoOnHotplugReconnect() const = 0; virtual bool onVsync(hal::HWDisplayId, nsecs_t timestamp) = 0; // Called when a vsync happens. If the vsync is valid, returns the // corresponding PhysicalDisplayId. Otherwise returns nullopt. virtual std::optional<PhysicalDisplayId> onVsync(hal::HWDisplayId, nsecs_t timestamp) = 0; virtual void setVsyncEnabled(PhysicalDisplayId, hal::Vsync enabled) = 0; virtual void setVsyncEnabled(PhysicalDisplayId, hal::Vsync enabled) = 0; virtual bool isConnected(PhysicalDisplayId) const = 0; virtual bool isConnected(PhysicalDisplayId) const = 0; Loading Loading @@ -402,7 +405,7 @@ public: bool updatesDeviceProductInfoOnHotplugReconnect() const override; bool updatesDeviceProductInfoOnHotplugReconnect() const override; bool onVsync(hal::HWDisplayId, nsecs_t timestamp) override; std::optional<PhysicalDisplayId> onVsync(hal::HWDisplayId, nsecs_t timestamp) override; void setVsyncEnabled(PhysicalDisplayId, hal::Vsync enabled) override; void setVsyncEnabled(PhysicalDisplayId, hal::Vsync enabled) override; bool isConnected(PhysicalDisplayId) const override; bool isConnected(PhysicalDisplayId) const override; Loading services/surfaceflinger/Scheduler/EventThread.cpp +40 −26 Original line number Original line Diff line number Diff line Loading @@ -238,29 +238,19 @@ EventThread::~EventThread() = default; namespace impl { namespace impl { EventThread::EventThread(const char* name, scheduler::VsyncSchedule& vsyncSchedule, EventThread::EventThread(const char* name, std::shared_ptr<scheduler::VsyncSchedule> vsyncSchedule, IEventThreadCallback& eventThreadCallback, android::frametimeline::TokenManager* tokenManager, android::frametimeline::TokenManager* tokenManager, ThrottleVsyncCallback throttleVsyncCallback, GetVsyncPeriodFunction getVsyncPeriodFunction, std::chrono::nanoseconds workDuration, std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration) std::chrono::nanoseconds readyDuration) : mThreadName(name), : mThreadName(name), mVsyncTracer(base::StringPrintf("VSYNC-%s", name), 0), mVsyncTracer(base::StringPrintf("VSYNC-%s", name), 0), mWorkDuration(base::StringPrintf("VsyncWorkDuration-%s", name), workDuration), mWorkDuration(base::StringPrintf("VsyncWorkDuration-%s", name), workDuration), mReadyDuration(readyDuration), mReadyDuration(readyDuration), mVsyncSchedule(vsyncSchedule), mVsyncSchedule(std::move(vsyncSchedule)), mVsyncRegistration( mVsyncRegistration(mVsyncSchedule->getDispatch(), createDispatchCallback(), name), vsyncSchedule.getDispatch(), [this](nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) { onVsync(vsyncTime, wakeupTime, readyTime); }, name), mTokenManager(tokenManager), mTokenManager(tokenManager), mThrottleVsyncCallback(std::move(throttleVsyncCallback)), mEventThreadCallback(eventThreadCallback) { mGetVsyncPeriodFunction(std::move(getVsyncPeriodFunction)) { LOG_ALWAYS_FATAL_IF(getVsyncPeriodFunction == nullptr, "getVsyncPeriodFunction must not be null"); mThread = std::thread([this]() NO_THREAD_SAFETY_ANALYSIS { mThread = std::thread([this]() NO_THREAD_SAFETY_ANALYSIS { std::unique_lock<std::mutex> lock(mMutex); std::unique_lock<std::mutex> lock(mMutex); threadMain(lock); threadMain(lock); Loading Loading @@ -371,16 +361,16 @@ VsyncEventData EventThread::getLatestVsyncEventData( } } VsyncEventData vsyncEventData; VsyncEventData vsyncEventData; nsecs_t frameInterval = mGetVsyncPeriodFunction(connection->mOwnerUid); const Fps frameInterval = mEventThreadCallback.getLeaderRenderFrameRate(connection->mOwnerUid); vsyncEventData.frameInterval = frameInterval; vsyncEventData.frameInterval = frameInterval.getPeriodNsecs(); const auto [presentTime, deadline] = [&]() -> std::pair<nsecs_t, nsecs_t> { const auto [presentTime, deadline] = [&]() -> std::pair<nsecs_t, nsecs_t> { std::lock_guard<std::mutex> lock(mMutex); std::lock_guard<std::mutex> lock(mMutex); const auto vsyncTime = mVsyncSchedule.getTracker().nextAnticipatedVSyncTimeFrom( const auto vsyncTime = mVsyncSchedule->getTracker().nextAnticipatedVSyncTimeFrom( systemTime() + mWorkDuration.get().count() + mReadyDuration.count()); systemTime() + mWorkDuration.get().count() + mReadyDuration.count()); return {vsyncTime, vsyncTime - mReadyDuration.count()}; return {vsyncTime, vsyncTime - mReadyDuration.count()}; }(); }(); generateFrameTimeline(vsyncEventData, frameInterval, systemTime(SYSTEM_TIME_MONOTONIC), generateFrameTimeline(vsyncEventData, frameInterval.getPeriodNsecs(), presentTime, deadline); systemTime(SYSTEM_TIME_MONOTONIC), presentTime, deadline); return vsyncEventData; return vsyncEventData; } } Loading Loading @@ -541,8 +531,10 @@ void EventThread::threadMain(std::unique_lock<std::mutex>& lock) { bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event, bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event, const sp<EventThreadConnection>& connection) const { const sp<EventThreadConnection>& connection) const { const auto throttleVsync = [&] { const auto throttleVsync = [&] { return mThrottleVsyncCallback && const auto& vsyncData = event.vsync.vsyncData; mThrottleVsyncCallback(event.vsync.vsyncData.preferredExpectedPresentationTime(), const auto expectedPresentTime = TimePoint::fromNs(vsyncData.preferredExpectedPresentationTime()); return !mEventThreadCallback.isVsyncTargetForUid(expectedPresentTime, connection->mOwnerUid); connection->mOwnerUid); }; }; Loading Loading @@ -631,9 +623,11 @@ void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event, for (const auto& consumer : consumers) { for (const auto& consumer : consumers) { DisplayEventReceiver::Event copy = event; DisplayEventReceiver::Event copy = event; if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) { if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) { const int64_t frameInterval = mGetVsyncPeriodFunction(consumer->mOwnerUid); const Fps frameInterval = copy.vsync.vsyncData.frameInterval = frameInterval; mEventThreadCallback.getLeaderRenderFrameRate(consumer->mOwnerUid); generateFrameTimeline(copy.vsync.vsyncData, frameInterval, copy.header.timestamp, copy.vsync.vsyncData.frameInterval = frameInterval.getPeriodNsecs(); generateFrameTimeline(copy.vsync.vsyncData, frameInterval.getPeriodNsecs(), copy.header.timestamp, event.vsync.vsyncData.preferredExpectedPresentationTime(), event.vsync.vsyncData.preferredExpectedPresentationTime(), event.vsync.vsyncData.preferredDeadlineTimestamp()); event.vsync.vsyncData.preferredDeadlineTimestamp()); } } Loading Loading @@ -699,6 +693,26 @@ const char* EventThread::toCString(State state) { } } } } void EventThread::onNewVsyncSchedule(std::shared_ptr<scheduler::VsyncSchedule> schedule) { std::lock_guard<std::mutex> lock(mMutex); const bool reschedule = mVsyncRegistration.cancel() == scheduler::CancelResult::Cancelled; mVsyncSchedule = std::move(schedule); mVsyncRegistration = scheduler::VSyncCallbackRegistration(mVsyncSchedule->getDispatch(), createDispatchCallback(), mThreadName); if (reschedule) { mVsyncRegistration.schedule({.workDuration = mWorkDuration.get().count(), .readyDuration = mReadyDuration.count(), .earliestVsync = mLastVsyncCallbackTime.ns()}); } } scheduler::VSyncDispatch::Callback EventThread::createDispatchCallback() { return [this](nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) { onVsync(vsyncTime, wakeupTime, readyTime); }; } } // namespace impl } // namespace impl } // namespace android } // namespace android Loading services/surfaceflinger/Scheduler/EventThread.h +22 −9 Original line number Original line Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <sys/types.h> #include <sys/types.h> #include <utils/Errors.h> #include <utils/Errors.h> #include <scheduler/Fps.h> #include <scheduler/FrameRateMode.h> #include <scheduler/FrameRateMode.h> #include <condition_variable> #include <condition_variable> #include <cstdint> #include <cstdint> Loading Loading @@ -67,6 +68,15 @@ enum class VSyncRequest { // Subsequent values are periods. // Subsequent values are periods. }; }; class IEventThreadCallback { public: virtual ~IEventThreadCallback() = default; virtual bool isVsyncTargetForUid(TimePoint expectedVsyncTime, uid_t uid) const = 0; virtual Fps getLeaderRenderFrameRate(uid_t uid) const = 0; }; class EventThreadConnection : public gui::BnDisplayEventConnection { class EventThreadConnection : public gui::BnDisplayEventConnection { public: public: EventThreadConnection(EventThread*, uid_t callingUid, ResyncCallback, EventThreadConnection(EventThread*, uid_t callingUid, ResyncCallback, Loading Loading @@ -133,18 +143,17 @@ public: // Retrieves the number of event connections tracked by this EventThread. // Retrieves the number of event connections tracked by this EventThread. virtual size_t getEventThreadConnectionCount() = 0; virtual size_t getEventThreadConnectionCount() = 0; virtual void onNewVsyncSchedule(std::shared_ptr<scheduler::VsyncSchedule>) = 0; }; }; namespace impl { namespace impl { class EventThread : public android::EventThread { class EventThread : public android::EventThread { public: public: using ThrottleVsyncCallback = std::function<bool(nsecs_t, uid_t)>; EventThread(const char* name, std::shared_ptr<scheduler::VsyncSchedule>, IEventThreadCallback&, using GetVsyncPeriodFunction = std::function<nsecs_t(uid_t)>; frametimeline::TokenManager*, std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration); EventThread(const char* name, scheduler::VsyncSchedule&, frametimeline::TokenManager*, ThrottleVsyncCallback, GetVsyncPeriodFunction, std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration); ~EventThread(); ~EventThread(); sp<EventThreadConnection> createEventConnection( sp<EventThreadConnection> createEventConnection( Loading Loading @@ -176,6 +185,8 @@ public: size_t getEventThreadConnectionCount() override; size_t getEventThreadConnectionCount() override; void onNewVsyncSchedule(std::shared_ptr<scheduler::VsyncSchedule>) override; private: private: friend EventThreadTest; friend EventThreadTest; Loading @@ -199,17 +210,19 @@ private: nsecs_t timestamp, nsecs_t preferredExpectedPresentationTime, nsecs_t timestamp, nsecs_t preferredExpectedPresentationTime, nsecs_t preferredDeadlineTimestamp) const; nsecs_t preferredDeadlineTimestamp) const; scheduler::VSyncDispatch::Callback createDispatchCallback(); const char* const mThreadName; const char* const mThreadName; TracedOrdinal<int> mVsyncTracer; TracedOrdinal<int> mVsyncTracer; TracedOrdinal<std::chrono::nanoseconds> mWorkDuration GUARDED_BY(mMutex); TracedOrdinal<std::chrono::nanoseconds> mWorkDuration GUARDED_BY(mMutex); std::chrono::nanoseconds mReadyDuration GUARDED_BY(mMutex); std::chrono::nanoseconds mReadyDuration GUARDED_BY(mMutex); scheduler::VsyncSchedule& mVsyncSchedule; std::shared_ptr<scheduler::VsyncSchedule> mVsyncSchedule; TimePoint mLastVsyncCallbackTime GUARDED_BY(mMutex) = TimePoint::now(); TimePoint mLastVsyncCallbackTime GUARDED_BY(mMutex) = TimePoint::now(); scheduler::VSyncCallbackRegistration mVsyncRegistration GUARDED_BY(mMutex); scheduler::VSyncCallbackRegistration mVsyncRegistration GUARDED_BY(mMutex); frametimeline::TokenManager* const mTokenManager; frametimeline::TokenManager* const mTokenManager; const ThrottleVsyncCallback mThrottleVsyncCallback; // mEventThreadCallback will outlive the EventThread. const GetVsyncPeriodFunction mGetVsyncPeriodFunction; IEventThreadCallback& mEventThreadCallback; std::thread mThread; std::thread mThread; mutable std::mutex mMutex; mutable std::mutex mMutex; Loading Loading
services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h +1 −1 Original line number Original line Diff line number Diff line Loading @@ -93,7 +93,7 @@ public: MOCK_METHOD2(onHotplug, MOCK_METHOD2(onHotplug, std::optional<DisplayIdentificationInfo>(hal::HWDisplayId, hal::Connection)); std::optional<DisplayIdentificationInfo>(hal::HWDisplayId, hal::Connection)); MOCK_CONST_METHOD0(updatesDeviceProductInfoOnHotplugReconnect, bool()); MOCK_CONST_METHOD0(updatesDeviceProductInfoOnHotplugReconnect, bool()); MOCK_METHOD2(onVsync, bool(hal::HWDisplayId, int64_t)); MOCK_METHOD(std::optional<PhysicalDisplayId>, onVsync, (hal::HWDisplayId, int64_t)); MOCK_METHOD2(setVsyncEnabled, void(PhysicalDisplayId, hal::Vsync)); MOCK_METHOD2(setVsyncEnabled, void(PhysicalDisplayId, hal::Vsync)); MOCK_CONST_METHOD1(isConnected, bool(PhysicalDisplayId)); MOCK_CONST_METHOD1(isConnected, bool(PhysicalDisplayId)); MOCK_CONST_METHOD1(getModes, std::vector<HWComposer::HWCDisplayMode>(PhysicalDisplayId)); MOCK_CONST_METHOD1(getModes, std::vector<HWComposer::HWCDisplayMode>(PhysicalDisplayId)); Loading
services/surfaceflinger/DisplayHardware/HWComposer.cpp +12 −10 Original line number Original line Diff line number Diff line Loading @@ -30,6 +30,7 @@ #include <compositionengine/Output.h> #include <compositionengine/Output.h> #include <compositionengine/OutputLayer.h> #include <compositionengine/OutputLayer.h> #include <compositionengine/impl/OutputLayerCompositionState.h> #include <compositionengine/impl/OutputLayerCompositionState.h> #include <ftl/concat.h> #include <log/log.h> #include <log/log.h> #include <ui/DebugUtils.h> #include <ui/DebugUtils.h> #include <ui/GraphicBuffer.h> #include <ui/GraphicBuffer.h> Loading Loading @@ -148,16 +149,17 @@ bool HWComposer::updatesDeviceProductInfoOnHotplugReconnect() const { return mUpdateDeviceProductInfoOnHotplugReconnect; return mUpdateDeviceProductInfoOnHotplugReconnect; } } bool HWComposer::onVsync(hal::HWDisplayId hwcDisplayId, nsecs_t timestamp) { std::optional<PhysicalDisplayId> HWComposer::onVsync(hal::HWDisplayId hwcDisplayId, const auto displayId = toPhysicalDisplayId(hwcDisplayId); nsecs_t timestamp) { if (!displayId) { const auto displayIdOpt = toPhysicalDisplayId(hwcDisplayId); if (!displayIdOpt) { LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid HWC display"); LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid HWC display"); return false; return {}; } } RETURN_IF_INVALID_DISPLAY(*displayId, false); RETURN_IF_INVALID_DISPLAY(*displayIdOpt, {}); auto& displayData = mDisplayData[*displayId]; auto& displayData = mDisplayData[*displayIdOpt]; { { // There have been reports of HWCs that signal several vsync events // There have been reports of HWCs that signal several vsync events Loading @@ -166,18 +168,18 @@ bool HWComposer::onVsync(hal::HWDisplayId hwcDisplayId, nsecs_t timestamp) { // out here so they don't cause havoc downstream. // out here so they don't cause havoc downstream. if (timestamp == displayData.lastPresentTimestamp) { if (timestamp == displayData.lastPresentTimestamp) { ALOGW("Ignoring duplicate VSYNC event from HWC for display %s (t=%" PRId64 ")", ALOGW("Ignoring duplicate VSYNC event from HWC for display %s (t=%" PRId64 ")", to_string(*displayId).c_str(), timestamp); to_string(*displayIdOpt).c_str(), timestamp); return false; return {}; } } displayData.lastPresentTimestamp = timestamp; displayData.lastPresentTimestamp = timestamp; } } const auto tag = "HW_VSYNC_" + to_string(*displayId); const ftl::Concat tag("HW_VSYNC_", displayIdOpt->value); ATRACE_INT(tag.c_str(), displayData.vsyncTraceToggle); ATRACE_INT(tag.c_str(), displayData.vsyncTraceToggle); displayData.vsyncTraceToggle = !displayData.vsyncTraceToggle; displayData.vsyncTraceToggle = !displayData.vsyncTraceToggle; return true; return displayIdOpt; } } size_t HWComposer::getMaxVirtualDisplayCount() const { size_t HWComposer::getMaxVirtualDisplayCount() const { Loading
services/surfaceflinger/DisplayHardware/HWComposer.h +5 −2 Original line number Original line Diff line number Diff line Loading @@ -221,7 +221,10 @@ public: // TODO(b/157555476): Remove when the framework has proper support for headless mode // TODO(b/157555476): Remove when the framework has proper support for headless mode virtual bool updatesDeviceProductInfoOnHotplugReconnect() const = 0; virtual bool updatesDeviceProductInfoOnHotplugReconnect() const = 0; virtual bool onVsync(hal::HWDisplayId, nsecs_t timestamp) = 0; // Called when a vsync happens. If the vsync is valid, returns the // corresponding PhysicalDisplayId. Otherwise returns nullopt. virtual std::optional<PhysicalDisplayId> onVsync(hal::HWDisplayId, nsecs_t timestamp) = 0; virtual void setVsyncEnabled(PhysicalDisplayId, hal::Vsync enabled) = 0; virtual void setVsyncEnabled(PhysicalDisplayId, hal::Vsync enabled) = 0; virtual bool isConnected(PhysicalDisplayId) const = 0; virtual bool isConnected(PhysicalDisplayId) const = 0; Loading Loading @@ -402,7 +405,7 @@ public: bool updatesDeviceProductInfoOnHotplugReconnect() const override; bool updatesDeviceProductInfoOnHotplugReconnect() const override; bool onVsync(hal::HWDisplayId, nsecs_t timestamp) override; std::optional<PhysicalDisplayId> onVsync(hal::HWDisplayId, nsecs_t timestamp) override; void setVsyncEnabled(PhysicalDisplayId, hal::Vsync enabled) override; void setVsyncEnabled(PhysicalDisplayId, hal::Vsync enabled) override; bool isConnected(PhysicalDisplayId) const override; bool isConnected(PhysicalDisplayId) const override; Loading
services/surfaceflinger/Scheduler/EventThread.cpp +40 −26 Original line number Original line Diff line number Diff line Loading @@ -238,29 +238,19 @@ EventThread::~EventThread() = default; namespace impl { namespace impl { EventThread::EventThread(const char* name, scheduler::VsyncSchedule& vsyncSchedule, EventThread::EventThread(const char* name, std::shared_ptr<scheduler::VsyncSchedule> vsyncSchedule, IEventThreadCallback& eventThreadCallback, android::frametimeline::TokenManager* tokenManager, android::frametimeline::TokenManager* tokenManager, ThrottleVsyncCallback throttleVsyncCallback, GetVsyncPeriodFunction getVsyncPeriodFunction, std::chrono::nanoseconds workDuration, std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration) std::chrono::nanoseconds readyDuration) : mThreadName(name), : mThreadName(name), mVsyncTracer(base::StringPrintf("VSYNC-%s", name), 0), mVsyncTracer(base::StringPrintf("VSYNC-%s", name), 0), mWorkDuration(base::StringPrintf("VsyncWorkDuration-%s", name), workDuration), mWorkDuration(base::StringPrintf("VsyncWorkDuration-%s", name), workDuration), mReadyDuration(readyDuration), mReadyDuration(readyDuration), mVsyncSchedule(vsyncSchedule), mVsyncSchedule(std::move(vsyncSchedule)), mVsyncRegistration( mVsyncRegistration(mVsyncSchedule->getDispatch(), createDispatchCallback(), name), vsyncSchedule.getDispatch(), [this](nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) { onVsync(vsyncTime, wakeupTime, readyTime); }, name), mTokenManager(tokenManager), mTokenManager(tokenManager), mThrottleVsyncCallback(std::move(throttleVsyncCallback)), mEventThreadCallback(eventThreadCallback) { mGetVsyncPeriodFunction(std::move(getVsyncPeriodFunction)) { LOG_ALWAYS_FATAL_IF(getVsyncPeriodFunction == nullptr, "getVsyncPeriodFunction must not be null"); mThread = std::thread([this]() NO_THREAD_SAFETY_ANALYSIS { mThread = std::thread([this]() NO_THREAD_SAFETY_ANALYSIS { std::unique_lock<std::mutex> lock(mMutex); std::unique_lock<std::mutex> lock(mMutex); threadMain(lock); threadMain(lock); Loading Loading @@ -371,16 +361,16 @@ VsyncEventData EventThread::getLatestVsyncEventData( } } VsyncEventData vsyncEventData; VsyncEventData vsyncEventData; nsecs_t frameInterval = mGetVsyncPeriodFunction(connection->mOwnerUid); const Fps frameInterval = mEventThreadCallback.getLeaderRenderFrameRate(connection->mOwnerUid); vsyncEventData.frameInterval = frameInterval; vsyncEventData.frameInterval = frameInterval.getPeriodNsecs(); const auto [presentTime, deadline] = [&]() -> std::pair<nsecs_t, nsecs_t> { const auto [presentTime, deadline] = [&]() -> std::pair<nsecs_t, nsecs_t> { std::lock_guard<std::mutex> lock(mMutex); std::lock_guard<std::mutex> lock(mMutex); const auto vsyncTime = mVsyncSchedule.getTracker().nextAnticipatedVSyncTimeFrom( const auto vsyncTime = mVsyncSchedule->getTracker().nextAnticipatedVSyncTimeFrom( systemTime() + mWorkDuration.get().count() + mReadyDuration.count()); systemTime() + mWorkDuration.get().count() + mReadyDuration.count()); return {vsyncTime, vsyncTime - mReadyDuration.count()}; return {vsyncTime, vsyncTime - mReadyDuration.count()}; }(); }(); generateFrameTimeline(vsyncEventData, frameInterval, systemTime(SYSTEM_TIME_MONOTONIC), generateFrameTimeline(vsyncEventData, frameInterval.getPeriodNsecs(), presentTime, deadline); systemTime(SYSTEM_TIME_MONOTONIC), presentTime, deadline); return vsyncEventData; return vsyncEventData; } } Loading Loading @@ -541,8 +531,10 @@ void EventThread::threadMain(std::unique_lock<std::mutex>& lock) { bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event, bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event, const sp<EventThreadConnection>& connection) const { const sp<EventThreadConnection>& connection) const { const auto throttleVsync = [&] { const auto throttleVsync = [&] { return mThrottleVsyncCallback && const auto& vsyncData = event.vsync.vsyncData; mThrottleVsyncCallback(event.vsync.vsyncData.preferredExpectedPresentationTime(), const auto expectedPresentTime = TimePoint::fromNs(vsyncData.preferredExpectedPresentationTime()); return !mEventThreadCallback.isVsyncTargetForUid(expectedPresentTime, connection->mOwnerUid); connection->mOwnerUid); }; }; Loading Loading @@ -631,9 +623,11 @@ void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event, for (const auto& consumer : consumers) { for (const auto& consumer : consumers) { DisplayEventReceiver::Event copy = event; DisplayEventReceiver::Event copy = event; if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) { if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) { const int64_t frameInterval = mGetVsyncPeriodFunction(consumer->mOwnerUid); const Fps frameInterval = copy.vsync.vsyncData.frameInterval = frameInterval; mEventThreadCallback.getLeaderRenderFrameRate(consumer->mOwnerUid); generateFrameTimeline(copy.vsync.vsyncData, frameInterval, copy.header.timestamp, copy.vsync.vsyncData.frameInterval = frameInterval.getPeriodNsecs(); generateFrameTimeline(copy.vsync.vsyncData, frameInterval.getPeriodNsecs(), copy.header.timestamp, event.vsync.vsyncData.preferredExpectedPresentationTime(), event.vsync.vsyncData.preferredExpectedPresentationTime(), event.vsync.vsyncData.preferredDeadlineTimestamp()); event.vsync.vsyncData.preferredDeadlineTimestamp()); } } Loading Loading @@ -699,6 +693,26 @@ const char* EventThread::toCString(State state) { } } } } void EventThread::onNewVsyncSchedule(std::shared_ptr<scheduler::VsyncSchedule> schedule) { std::lock_guard<std::mutex> lock(mMutex); const bool reschedule = mVsyncRegistration.cancel() == scheduler::CancelResult::Cancelled; mVsyncSchedule = std::move(schedule); mVsyncRegistration = scheduler::VSyncCallbackRegistration(mVsyncSchedule->getDispatch(), createDispatchCallback(), mThreadName); if (reschedule) { mVsyncRegistration.schedule({.workDuration = mWorkDuration.get().count(), .readyDuration = mReadyDuration.count(), .earliestVsync = mLastVsyncCallbackTime.ns()}); } } scheduler::VSyncDispatch::Callback EventThread::createDispatchCallback() { return [this](nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) { onVsync(vsyncTime, wakeupTime, readyTime); }; } } // namespace impl } // namespace impl } // namespace android } // namespace android Loading
services/surfaceflinger/Scheduler/EventThread.h +22 −9 Original line number Original line Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <sys/types.h> #include <sys/types.h> #include <utils/Errors.h> #include <utils/Errors.h> #include <scheduler/Fps.h> #include <scheduler/FrameRateMode.h> #include <scheduler/FrameRateMode.h> #include <condition_variable> #include <condition_variable> #include <cstdint> #include <cstdint> Loading Loading @@ -67,6 +68,15 @@ enum class VSyncRequest { // Subsequent values are periods. // Subsequent values are periods. }; }; class IEventThreadCallback { public: virtual ~IEventThreadCallback() = default; virtual bool isVsyncTargetForUid(TimePoint expectedVsyncTime, uid_t uid) const = 0; virtual Fps getLeaderRenderFrameRate(uid_t uid) const = 0; }; class EventThreadConnection : public gui::BnDisplayEventConnection { class EventThreadConnection : public gui::BnDisplayEventConnection { public: public: EventThreadConnection(EventThread*, uid_t callingUid, ResyncCallback, EventThreadConnection(EventThread*, uid_t callingUid, ResyncCallback, Loading Loading @@ -133,18 +143,17 @@ public: // Retrieves the number of event connections tracked by this EventThread. // Retrieves the number of event connections tracked by this EventThread. virtual size_t getEventThreadConnectionCount() = 0; virtual size_t getEventThreadConnectionCount() = 0; virtual void onNewVsyncSchedule(std::shared_ptr<scheduler::VsyncSchedule>) = 0; }; }; namespace impl { namespace impl { class EventThread : public android::EventThread { class EventThread : public android::EventThread { public: public: using ThrottleVsyncCallback = std::function<bool(nsecs_t, uid_t)>; EventThread(const char* name, std::shared_ptr<scheduler::VsyncSchedule>, IEventThreadCallback&, using GetVsyncPeriodFunction = std::function<nsecs_t(uid_t)>; frametimeline::TokenManager*, std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration); EventThread(const char* name, scheduler::VsyncSchedule&, frametimeline::TokenManager*, ThrottleVsyncCallback, GetVsyncPeriodFunction, std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration); ~EventThread(); ~EventThread(); sp<EventThreadConnection> createEventConnection( sp<EventThreadConnection> createEventConnection( Loading Loading @@ -176,6 +185,8 @@ public: size_t getEventThreadConnectionCount() override; size_t getEventThreadConnectionCount() override; void onNewVsyncSchedule(std::shared_ptr<scheduler::VsyncSchedule>) override; private: private: friend EventThreadTest; friend EventThreadTest; Loading @@ -199,17 +210,19 @@ private: nsecs_t timestamp, nsecs_t preferredExpectedPresentationTime, nsecs_t timestamp, nsecs_t preferredExpectedPresentationTime, nsecs_t preferredDeadlineTimestamp) const; nsecs_t preferredDeadlineTimestamp) const; scheduler::VSyncDispatch::Callback createDispatchCallback(); const char* const mThreadName; const char* const mThreadName; TracedOrdinal<int> mVsyncTracer; TracedOrdinal<int> mVsyncTracer; TracedOrdinal<std::chrono::nanoseconds> mWorkDuration GUARDED_BY(mMutex); TracedOrdinal<std::chrono::nanoseconds> mWorkDuration GUARDED_BY(mMutex); std::chrono::nanoseconds mReadyDuration GUARDED_BY(mMutex); std::chrono::nanoseconds mReadyDuration GUARDED_BY(mMutex); scheduler::VsyncSchedule& mVsyncSchedule; std::shared_ptr<scheduler::VsyncSchedule> mVsyncSchedule; TimePoint mLastVsyncCallbackTime GUARDED_BY(mMutex) = TimePoint::now(); TimePoint mLastVsyncCallbackTime GUARDED_BY(mMutex) = TimePoint::now(); scheduler::VSyncCallbackRegistration mVsyncRegistration GUARDED_BY(mMutex); scheduler::VSyncCallbackRegistration mVsyncRegistration GUARDED_BY(mMutex); frametimeline::TokenManager* const mTokenManager; frametimeline::TokenManager* const mTokenManager; const ThrottleVsyncCallback mThrottleVsyncCallback; // mEventThreadCallback will outlive the EventThread. const GetVsyncPeriodFunction mGetVsyncPeriodFunction; IEventThreadCallback& mEventThreadCallback; std::thread mThread; std::thread mThread; mutable std::mutex mMutex; mutable std::mutex mMutex; Loading