Loading services/surfaceflinger/Scheduler/Scheduler.cpp +41 −120 Original line number Diff line number Diff line Loading @@ -60,14 +60,6 @@ #include "VsyncController.h" #include "VsyncSchedule.h" #define RETURN_IF_INVALID_HANDLE(handle, ...) \ do { \ if (mConnections.count(handle) == 0) { \ ALOGE("Invalid connection handle %" PRIuPTR, handle.id); \ return __VA_ARGS__; \ } \ } while (false) namespace android::scheduler { Scheduler::Scheduler(ICompositor& compositor, ISchedulerCallback& callback, FeatureFlags features, Loading Loading @@ -344,8 +336,7 @@ void Scheduler::onExpectedPresentTimePosted(TimePoint expectedPresentTime) { } } ConnectionHandle Scheduler::createEventThread(Cycle cycle, frametimeline::TokenManager* tokenManager, void Scheduler::createEventThread(Cycle cycle, frametimeline::TokenManager* tokenManager, std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration) { auto eventThread = Loading @@ -353,31 +344,18 @@ ConnectionHandle Scheduler::createEventThread(Cycle cycle, getVsyncSchedule(), tokenManager, *this, workDuration, readyDuration); auto& handle = cycle == Cycle::Render ? mAppConnectionHandle : mSfConnectionHandle; handle = createConnection(std::move(eventThread)); return handle; if (cycle == Cycle::Render) { mRenderEventThread = std::move(eventThread); mRenderEventConnection = mRenderEventThread->createEventConnection(); } else { mLastCompositeEventThread = std::move(eventThread); mLastCompositeEventConnection = mLastCompositeEventThread->createEventConnection(); } ConnectionHandle Scheduler::createConnection(std::unique_ptr<EventThread> eventThread) { const ConnectionHandle handle = ConnectionHandle{mNextConnectionHandleId++}; ALOGV("Creating a connection handle with ID %" PRIuPTR, handle.id); auto connection = eventThread->createEventConnection(); std::lock_guard<std::mutex> lock(mConnectionsLock); mConnections.emplace(handle, Connection{connection, std::move(eventThread)}); return handle; } sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection( ConnectionHandle handle, EventRegistrationFlags eventRegistration, const sp<IBinder>& layerHandle) { const auto connection = [&]() -> sp<EventThreadConnection> { std::scoped_lock lock(mConnectionsLock); RETURN_IF_INVALID_HANDLE(handle, nullptr); return mConnections[handle].thread->createEventConnection(eventRegistration); }(); Cycle cycle, EventRegistrationFlags eventRegistration, const sp<IBinder>& layerHandle) { const auto connection = eventThreadFor(cycle).createEventConnection(eventRegistration); const auto layerId = static_cast<int32_t>(LayerHandle::getLayerId(layerHandle)); if (layerId != static_cast<int32_t>(UNASSIGNED_LAYER_ID)) { Loading @@ -397,85 +375,48 @@ sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection( return connection; } sp<EventThreadConnection> Scheduler::getEventConnection(ConnectionHandle handle) { std::lock_guard<std::mutex> lock(mConnectionsLock); RETURN_IF_INVALID_HANDLE(handle, nullptr); return mConnections[handle].connection; void Scheduler::onHotplugReceived(Cycle cycle, PhysicalDisplayId displayId, bool connected) { if (hasEventThreads()) { eventThreadFor(cycle).onHotplugReceived(displayId, connected); } void Scheduler::onHotplugReceived(ConnectionHandle handle, PhysicalDisplayId displayId, bool connected) { android::EventThread* thread; { std::lock_guard<std::mutex> lock(mConnectionsLock); RETURN_IF_INVALID_HANDLE(handle); thread = mConnections[handle].thread.get(); } thread->onHotplugReceived(displayId, connected); void Scheduler::onHotplugConnectionError(Cycle cycle, int32_t errorCode) { if (hasEventThreads()) { eventThreadFor(cycle).onHotplugConnectionError(errorCode); } void Scheduler::onHotplugConnectionError(ConnectionHandle handle, int32_t errorCode) { android::EventThread* thread; { std::lock_guard<std::mutex> lock(mConnectionsLock); RETURN_IF_INVALID_HANDLE(handle); thread = mConnections[handle].thread.get(); } thread->onHotplugConnectionError(errorCode); } void Scheduler::enableSyntheticVsync(bool enable) { // TODO(b/241285945): Remove connection handles. const ConnectionHandle handle = mAppConnectionHandle; android::EventThread* thread; { std::lock_guard<std::mutex> lock(mConnectionsLock); RETURN_IF_INVALID_HANDLE(handle); thread = mConnections[handle].thread.get(); } thread->enableSyntheticVsync(enable); eventThreadFor(Cycle::Render).enableSyntheticVsync(enable); } void Scheduler::onFrameRateOverridesChanged(ConnectionHandle handle, PhysicalDisplayId displayId) { void Scheduler::onFrameRateOverridesChanged(Cycle cycle, PhysicalDisplayId displayId) { const bool supportsFrameRateOverrideByContent = pacesetterSelectorPtr()->supportsAppFrameRateOverrideByContent(); std::vector<FrameRateOverride> overrides = mFrameRateOverrideMappings.getAllFrameRateOverrides(supportsFrameRateOverrideByContent); android::EventThread* thread; { std::lock_guard lock(mConnectionsLock); RETURN_IF_INVALID_HANDLE(handle); thread = mConnections[handle].thread.get(); } thread->onFrameRateOverridesChanged(displayId, std::move(overrides)); eventThreadFor(cycle).onFrameRateOverridesChanged(displayId, std::move(overrides)); } void Scheduler::onHdcpLevelsChanged(ConnectionHandle handle, PhysicalDisplayId displayId, void Scheduler::onHdcpLevelsChanged(Cycle cycle, PhysicalDisplayId displayId, int32_t connectedLevel, int32_t maxLevel) { android::EventThread* thread; { std::lock_guard<std::mutex> lock(mConnectionsLock); RETURN_IF_INVALID_HANDLE(handle); thread = mConnections[handle].thread.get(); } thread->onHdcpLevelsChanged(displayId, connectedLevel, maxLevel); eventThreadFor(cycle).onHdcpLevelsChanged(displayId, connectedLevel, maxLevel); } void Scheduler::onPrimaryDisplayModeChanged(ConnectionHandle handle, const FrameRateMode& mode) { void Scheduler::onPrimaryDisplayModeChanged(Cycle cycle, const FrameRateMode& mode) { { std::lock_guard<std::mutex> lock(mPolicyLock); // Cache the last reported modes for primary display. mPolicy.cachedModeChangedParams = {handle, mode}; mPolicy.cachedModeChangedParams = {cycle, mode}; // Invalidate content based refresh rate selection so it could be calculated // again for the new refresh rate. mPolicy.contentRequirements.clear(); } onNonPrimaryDisplayModeChanged(handle, mode); onNonPrimaryDisplayModeChanged(cycle, mode); } void Scheduler::dispatchCachedReportedMode() { Loading @@ -502,39 +443,25 @@ void Scheduler::dispatchCachedReportedMode() { } mPolicy.cachedModeChangedParams->mode = *mPolicy.modeOpt; onNonPrimaryDisplayModeChanged(mPolicy.cachedModeChangedParams->handle, onNonPrimaryDisplayModeChanged(mPolicy.cachedModeChangedParams->cycle, mPolicy.cachedModeChangedParams->mode); } void Scheduler::onNonPrimaryDisplayModeChanged(ConnectionHandle handle, const FrameRateMode& mode) { android::EventThread* thread; { std::lock_guard<std::mutex> lock(mConnectionsLock); RETURN_IF_INVALID_HANDLE(handle); thread = mConnections[handle].thread.get(); void Scheduler::onNonPrimaryDisplayModeChanged(Cycle cycle, const FrameRateMode& mode) { if (hasEventThreads()) { eventThreadFor(cycle).onModeChanged(mode); } thread->onModeChanged(mode); } void Scheduler::dump(ConnectionHandle handle, std::string& result) const { android::EventThread* thread; { std::lock_guard<std::mutex> lock(mConnectionsLock); RETURN_IF_INVALID_HANDLE(handle); thread = mConnections.at(handle).thread.get(); } thread->dump(result); void Scheduler::dump(Cycle cycle, std::string& result) const { eventThreadFor(cycle).dump(result); } void Scheduler::setDuration(ConnectionHandle handle, std::chrono::nanoseconds workDuration, void Scheduler::setDuration(Cycle cycle, std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration) { android::EventThread* thread; { std::lock_guard<std::mutex> lock(mConnectionsLock); RETURN_IF_INVALID_HANDLE(handle); thread = mConnections[handle].thread.get(); if (hasEventThreads()) { eventThreadFor(cycle).setDuration(workDuration, readyDuration); } thread->setDuration(workDuration, readyDuration); } void Scheduler::updatePhaseConfiguration(Fps refreshRate) { Loading @@ -557,10 +484,10 @@ void Scheduler::setActiveDisplayPowerModeForRefreshRateStats(hal::PowerMode powe } void Scheduler::setVsyncConfig(const VsyncConfig& config, Period vsyncPeriod) { setDuration(mAppConnectionHandle, setDuration(Cycle::Render, /* workDuration */ config.appWorkDuration, /* readyDuration */ config.sfWorkDuration); setDuration(mSfConnectionHandle, setDuration(Cycle::LastComposite, /* workDuration */ vsyncPeriod, /* readyDuration */ config.sfWorkDuration); setDuration(config.sfWorkDuration); Loading Loading @@ -1027,16 +954,10 @@ std::shared_ptr<VsyncSchedule> Scheduler::promotePacesetterDisplayLocked( void Scheduler::applyNewVsyncSchedule(std::shared_ptr<VsyncSchedule> vsyncSchedule) { onNewVsyncSchedule(vsyncSchedule->getDispatch()); std::vector<android::EventThread*> threads; { std::lock_guard<std::mutex> lock(mConnectionsLock); threads.reserve(mConnections.size()); for (auto& [_, connection] : mConnections) { threads.push_back(connection.thread.get()); } } for (auto* thread : threads) { thread->onNewVsyncSchedule(vsyncSchedule); if (hasEventThreads()) { eventThreadFor(Cycle::Render).onNewVsyncSchedule(vsyncSchedule); eventThreadFor(Cycle::LastComposite).onNewVsyncSchedule(vsyncSchedule); } } Loading services/surfaceflinger/Scheduler/Scheduler.h +34 −62 Original line number Diff line number Diff line Loading @@ -56,35 +56,6 @@ #include <FrontEnd/LayerHierarchy.h> namespace android::scheduler { // Opaque handle to scheduler connection. struct ConnectionHandle { using Id = std::uintptr_t; static constexpr Id INVALID_ID = static_cast<Id>(-1); Id id = INVALID_ID; explicit operator bool() const { return id != INVALID_ID; } }; inline bool operator==(ConnectionHandle lhs, ConnectionHandle rhs) { return lhs.id == rhs.id; } } // namespace android::scheduler namespace std { template <> struct hash<android::scheduler::ConnectionHandle> { size_t operator()(android::scheduler::ConnectionHandle handle) const { return hash<android::scheduler::ConnectionHandle::Id>()(handle.id); } }; } // namespace std namespace android { class FenceTime; Loading @@ -106,6 +77,11 @@ class RefreshRateStats; class VsyncConfiguration; class VsyncSchedule; enum class Cycle { Render, // Surface rendering. LastComposite // Ahead of display compositing by one refresh period. }; class Scheduler : public IEventThreadCallback, android::impl::MessageQueue { using Impl = android::impl::MessageQueue; Loading Loading @@ -154,36 +130,32 @@ public: return std::move(future); } enum class Cycle { Render, // Surface rendering. LastComposite // Ahead of display compositing by one refresh period. }; ConnectionHandle createEventThread(Cycle, frametimeline::TokenManager*, void createEventThread(Cycle, frametimeline::TokenManager*, std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration); sp<IDisplayEventConnection> createDisplayEventConnection( ConnectionHandle, EventRegistrationFlags eventRegistration = {}, Cycle, EventRegistrationFlags eventRegistration = {}, const sp<IBinder>& layerHandle = nullptr) EXCLUDES(mChoreographerLock); sp<EventThreadConnection> getEventConnection(ConnectionHandle); const sp<EventThreadConnection>& getEventConnection(Cycle cycle) const { return cycle == Cycle::Render ? mRenderEventConnection : mLastCompositeEventConnection; } void onHotplugReceived(ConnectionHandle, PhysicalDisplayId, bool connected); void onHotplugConnectionError(ConnectionHandle, int32_t errorCode); void onHotplugReceived(Cycle, PhysicalDisplayId, bool connected); void onHotplugConnectionError(Cycle, int32_t errorCode); void onPrimaryDisplayModeChanged(ConnectionHandle, const FrameRateMode&) EXCLUDES(mPolicyLock); void onNonPrimaryDisplayModeChanged(ConnectionHandle, const FrameRateMode&); void onPrimaryDisplayModeChanged(Cycle, const FrameRateMode&) EXCLUDES(mPolicyLock); void onNonPrimaryDisplayModeChanged(Cycle, const FrameRateMode&); void enableSyntheticVsync(bool = true) REQUIRES(kMainThreadContext); void onFrameRateOverridesChanged(ConnectionHandle, PhysicalDisplayId) EXCLUDES(mConnectionsLock); void onFrameRateOverridesChanged(Cycle, PhysicalDisplayId); void onHdcpLevelsChanged(ConnectionHandle, PhysicalDisplayId, int32_t, int32_t); void onHdcpLevelsChanged(Cycle, PhysicalDisplayId, int32_t, int32_t); // Modifies work duration in the event thread. void setDuration(ConnectionHandle, std::chrono::nanoseconds workDuration, void setDuration(Cycle, std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration); VsyncModulator& vsyncModulator() { return *mVsyncModulator; } Loading Loading @@ -288,7 +260,7 @@ public: bool isVsyncInPhase(TimePoint expectedVsyncTime, Fps frameRate) const; void dump(utils::Dumper&) const; void dump(ConnectionHandle, std::string&) const; void dump(Cycle, std::string&) const; void dumpVsync(std::string&) const EXCLUDES(mDisplayLock); // Returns the preferred refresh rate and frame rate for the pacesetter display. Loading Loading @@ -369,8 +341,15 @@ private: void onFrameSignal(ICompositor&, VsyncId, TimePoint expectedVsyncTime) override REQUIRES(kMainThreadContext, mDisplayLock); // Create a connection on the given EventThread. ConnectionHandle createConnection(std::unique_ptr<EventThread>); // Used to skip event dispatch before EventThread creation during boot. // TODO: b/241285191 - Reorder Scheduler initialization to avoid this. bool hasEventThreads() const { return CC_LIKELY(mRenderEventThread && mLastCompositeEventThread); } EventThread& eventThreadFor(Cycle cycle) const { return *(cycle == Cycle::Render ? mRenderEventThread : mLastCompositeEventThread); } // Update feature state machine to given state when corresponding timer resets or expires. void kernelIdleTimerCallback(TimerState) EXCLUDES(mDisplayLock); Loading Loading @@ -460,18 +439,11 @@ private: void resync() override EXCLUDES(mDisplayLock); void onExpectedPresentTimePosted(TimePoint expectedPresentTime) override EXCLUDES(mDisplayLock); // Stores EventThread associated with a given VSyncSource, and an initial EventThreadConnection. struct Connection { sp<EventThreadConnection> connection; std::unique_ptr<EventThread> thread; }; ConnectionHandle::Id mNextConnectionHandleId = 0; mutable std::mutex mConnectionsLock; std::unordered_map<ConnectionHandle, Connection> mConnections GUARDED_BY(mConnectionsLock); std::unique_ptr<EventThread> mRenderEventThread; sp<EventThreadConnection> mRenderEventConnection; ConnectionHandle mAppConnectionHandle; ConnectionHandle mSfConnectionHandle; std::unique_ptr<EventThread> mLastCompositeEventThread; sp<EventThreadConnection> mLastCompositeEventConnection; std::atomic<nsecs_t> mLastResyncTime = 0; Loading Loading @@ -585,7 +557,7 @@ private: ftl::Optional<FrameRateMode> modeOpt; struct ModeChangedParams { ConnectionHandle handle; Cycle cycle; FrameRateMode mode; }; Loading services/surfaceflinger/SurfaceFlinger.cpp +35 −33 Original line number Diff line number Diff line Loading @@ -2085,12 +2085,11 @@ status_t SurfaceFlinger::getDisplayDecorationSupport( sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection( gui::ISurfaceComposer::VsyncSource vsyncSource, EventRegistrationFlags eventRegistration, const sp<IBinder>& layerHandle) { const auto& handle = vsyncSource == gui::ISurfaceComposer::VsyncSource::eVsyncSourceSurfaceFlinger ? mSfConnectionHandle : mAppConnectionHandle; const auto cycle = vsyncSource == gui::ISurfaceComposer::VsyncSource::eVsyncSourceSurfaceFlinger ? scheduler::Cycle::LastComposite : scheduler::Cycle::Render; return mScheduler->createDisplayEventConnection(handle, eventRegistration, layerHandle); return mScheduler->createDisplayEventConnection(cycle, eventRegistration, layerHandle); } void SurfaceFlinger::scheduleCommit(FrameHint hint) { Loading Loading @@ -2132,7 +2131,7 @@ void SurfaceFlinger::onComposerHalVsync(hal::HWDisplayId hwcDisplayId, int64_t t const int32_t hotplugErrorCode = static_cast<int32_t>(-timestamp); ALOGD("SurfaceFlinger got hotplugErrorCode=%d for display %" PRIu64, hotplugErrorCode, hwcDisplayId); mScheduler->onHotplugConnectionError(mAppConnectionHandle, hotplugErrorCode); mScheduler->onHotplugConnectionError(scheduler::Cycle::Render, hotplugErrorCode); return; } Loading Loading @@ -2183,7 +2182,7 @@ void SurfaceFlinger::onComposerHalHotplugEvent(hal::HWDisplayId hwcDisplayId, if (FlagManager::getInstance().hotplug2()) { ALOGD("SurfaceFlinger got hotplug event=%d", static_cast<int32_t>(event)); // TODO(b/311403559): use enum type instead of int mScheduler->onHotplugConnectionError(mAppConnectionHandle, static_cast<int32_t>(event)); mScheduler->onHotplugConnectionError(scheduler::Cycle::Render, static_cast<int32_t>(event)); } } Loading Loading @@ -3473,7 +3472,7 @@ const char* SurfaceFlinger::processHotplug(PhysicalDisplayId displayId, if (!activeMode) { ALOGE("Failed to hotplug display %s", to_string(displayId).c_str()); if (FlagManager::getInstance().hotplug2()) { mScheduler->onHotplugConnectionError(mAppConnectionHandle, mScheduler->onHotplugConnectionError(scheduler::Cycle::Render, static_cast<int32_t>( DisplayHotplugEvent::ERROR_UNKNOWN)); } Loading Loading @@ -3526,8 +3525,8 @@ const char* SurfaceFlinger::processHotplug(PhysicalDisplayId displayId, } void SurfaceFlinger::dispatchDisplayHotplugEvent(PhysicalDisplayId displayId, bool connected) { mScheduler->onHotplugReceived(mAppConnectionHandle, displayId, connected); mScheduler->onHotplugReceived(mSfConnectionHandle, displayId, connected); mScheduler->onHotplugReceived(scheduler::Cycle::Render, displayId, connected); mScheduler->onHotplugReceived(scheduler::Cycle::LastComposite, displayId, connected); } void SurfaceFlinger::dispatchDisplayModeChangeEvent(PhysicalDisplayId displayId, Loading @@ -3537,7 +3536,7 @@ void SurfaceFlinger::dispatchDisplayModeChangeEvent(PhysicalDisplayId displayId, ? &scheduler::Scheduler::onPrimaryDisplayModeChanged : &scheduler::Scheduler::onNonPrimaryDisplayModeChanged; ((*mScheduler).*onDisplayModeChanged)(mAppConnectionHandle, mode); ((*mScheduler).*onDisplayModeChanged)(scheduler::Cycle::Render, mode); } sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( Loading Loading @@ -4189,7 +4188,7 @@ void SurfaceFlinger::triggerOnFrameRateOverridesChanged() { return getDefaultDisplayDeviceLocked()->getPhysicalId(); }(); mScheduler->onFrameRateOverridesChanged(mAppConnectionHandle, displayId); mScheduler->onFrameRateOverridesChanged(scheduler::Cycle::Render, displayId); } void SurfaceFlinger::notifyCpuLoadUp() { Loading Loading @@ -4354,21 +4353,19 @@ void SurfaceFlinger::initScheduler(const sp<const DisplayDevice>& display) { mScheduler = std::make_unique<Scheduler>(static_cast<ICompositor&>(*this), static_cast<ISchedulerCallback&>(*this), features, getFactory(), activeRefreshRate, *mTimeStats); // The pacesetter must be registered before EventThread creation below. mScheduler->registerDisplay(display->getPhysicalId(), display->holdRefreshRateSelector()); if (FlagManager::getInstance().vrr_config()) { mScheduler->setRenderRate(display->getPhysicalId(), activeMode.fps); } mScheduler->startTimers(); const auto configs = mScheduler->getVsyncConfiguration().getCurrentConfigs(); mAppConnectionHandle = mScheduler->createEventThread(Scheduler::Cycle::Render, mFrameTimeline->getTokenManager(), mScheduler->createEventThread(scheduler::Cycle::Render, mFrameTimeline->getTokenManager(), /* workDuration */ configs.late.appWorkDuration, /* readyDuration */ configs.late.sfWorkDuration); mSfConnectionHandle = mScheduler->createEventThread(Scheduler::Cycle::LastComposite, mScheduler->createEventThread(scheduler::Cycle::LastComposite, mFrameTimeline->getTokenManager(), /* workDuration */ activeRefreshRate.getPeriod(), /* readyDuration */ configs.late.sfWorkDuration); Loading @@ -4379,6 +4376,9 @@ void SurfaceFlinger::initScheduler(const sp<const DisplayDevice>& display) { sp<RegionSamplingThread>::make(*this, RegionSamplingThread::EnvironmentTimingTunables()); mFpsReporter = sp<FpsReporter>::make(*mFrameTimeline); // Timer callbacks may fire, so do this last. mScheduler->startTimers(); } void SurfaceFlinger::doCommitTransactions() { Loading Loading @@ -6315,7 +6315,7 @@ void SurfaceFlinger::dumpScheduler(std::string& result) const { } void SurfaceFlinger::dumpEvents(std::string& result) const { mScheduler->dump(mAppConnectionHandle, result); mScheduler->dump(scheduler::Cycle::Render, result); } void SurfaceFlinger::dumpVsync(std::string& result) const { Loading Loading @@ -7087,14 +7087,15 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r mForceFullDamage = n != 0; return NO_ERROR; } case 1018: { // Modify Choreographer's duration case 1018: { // Set the render deadline as a duration until VSYNC. n = data.readInt32(); mScheduler->setDuration(mAppConnectionHandle, std::chrono::nanoseconds(n), 0ns); mScheduler->setDuration(scheduler::Cycle::Render, std::chrono::nanoseconds(n), 0ns); return NO_ERROR; } case 1019: { // Modify SurfaceFlinger's duration case 1019: { // Set the deadline of the last composite as a duration until VSYNC. n = data.readInt32(); mScheduler->setDuration(mSfConnectionHandle, std::chrono::nanoseconds(n), 0ns); mScheduler->setDuration(scheduler::Cycle::LastComposite, std::chrono::nanoseconds(n), 0ns); return NO_ERROR; } case 1020: { // Unused Loading Loading @@ -7326,7 +7327,7 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r auto inUid = static_cast<uid_t>(data.readInt32()); const auto refreshRate = data.readFloat(); mScheduler->setPreferredRefreshRateForUid(FrameRateOverride{inUid, refreshRate}); mScheduler->onFrameRateOverridesChanged(mAppConnectionHandle, displayId); mScheduler->onFrameRateOverridesChanged(scheduler::Cycle::Render, displayId); return NO_ERROR; } // Toggle caching feature Loading Loading @@ -8466,10 +8467,10 @@ status_t SurfaceFlinger::applyRefreshRateSelectorPolicy( // TODO(b/140204874): Leave the event in until we do proper testing with all apps that might // be depending in this callback. if (const auto activeMode = selector.getActiveMode(); displayId == mActiveDisplayId) { mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, activeMode); mScheduler->onPrimaryDisplayModeChanged(scheduler::Cycle::Render, activeMode); toggleKernelIdleTimer(); } else { mScheduler->onNonPrimaryDisplayModeChanged(mAppConnectionHandle, activeMode); mScheduler->onNonPrimaryDisplayModeChanged(scheduler::Cycle::Render, activeMode); } auto preferredModeOpt = getPreferredDisplayMode(displayId, currentPolicy.defaultMode); Loading Loading @@ -8657,7 +8658,7 @@ status_t SurfaceFlinger::setGameModeFrameRateOverride(uid_t uid, float frameRate }(); mScheduler->setGameModeFrameRateForUid(FrameRateOverride{static_cast<uid_t>(uid), frameRate}); mScheduler->onFrameRateOverridesChanged(mAppConnectionHandle, displayId); mScheduler->onFrameRateOverridesChanged(scheduler::Cycle::Render, displayId); return NO_ERROR; } Loading Loading @@ -8919,7 +8920,8 @@ void SurfaceFlinger::updateHdcpLevels(hal::HWDisplayId hwcDisplayId, int32_t con Mutex::Autolock lock(mStateLock); display->setSecure(connectedLevel >= 2 /* HDCP_V1 */); } mScheduler->onHdcpLevelsChanged(mAppConnectionHandle, displayId, connectedLevel, maxLevel); mScheduler->onHdcpLevelsChanged(scheduler::Cycle::Render, displayId, connectedLevel, maxLevel); })); } Loading services/surfaceflinger/SurfaceFlinger.h +0 −5 Original line number Diff line number Diff line Loading @@ -1356,12 +1356,7 @@ private: const std::string mHwcServiceName; /* * Scheduler */ std::unique_ptr<scheduler::Scheduler> mScheduler; scheduler::ConnectionHandle mAppConnectionHandle; scheduler::ConnectionHandle mSfConnectionHandle; scheduler::PresentLatencyTracker mPresentLatencyTracker GUARDED_BY(kMainThreadContext); Loading services/surfaceflinger/tests/unittests/SchedulerTest.cpp +14 −72 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
services/surfaceflinger/Scheduler/Scheduler.cpp +41 −120 Original line number Diff line number Diff line Loading @@ -60,14 +60,6 @@ #include "VsyncController.h" #include "VsyncSchedule.h" #define RETURN_IF_INVALID_HANDLE(handle, ...) \ do { \ if (mConnections.count(handle) == 0) { \ ALOGE("Invalid connection handle %" PRIuPTR, handle.id); \ return __VA_ARGS__; \ } \ } while (false) namespace android::scheduler { Scheduler::Scheduler(ICompositor& compositor, ISchedulerCallback& callback, FeatureFlags features, Loading Loading @@ -344,8 +336,7 @@ void Scheduler::onExpectedPresentTimePosted(TimePoint expectedPresentTime) { } } ConnectionHandle Scheduler::createEventThread(Cycle cycle, frametimeline::TokenManager* tokenManager, void Scheduler::createEventThread(Cycle cycle, frametimeline::TokenManager* tokenManager, std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration) { auto eventThread = Loading @@ -353,31 +344,18 @@ ConnectionHandle Scheduler::createEventThread(Cycle cycle, getVsyncSchedule(), tokenManager, *this, workDuration, readyDuration); auto& handle = cycle == Cycle::Render ? mAppConnectionHandle : mSfConnectionHandle; handle = createConnection(std::move(eventThread)); return handle; if (cycle == Cycle::Render) { mRenderEventThread = std::move(eventThread); mRenderEventConnection = mRenderEventThread->createEventConnection(); } else { mLastCompositeEventThread = std::move(eventThread); mLastCompositeEventConnection = mLastCompositeEventThread->createEventConnection(); } ConnectionHandle Scheduler::createConnection(std::unique_ptr<EventThread> eventThread) { const ConnectionHandle handle = ConnectionHandle{mNextConnectionHandleId++}; ALOGV("Creating a connection handle with ID %" PRIuPTR, handle.id); auto connection = eventThread->createEventConnection(); std::lock_guard<std::mutex> lock(mConnectionsLock); mConnections.emplace(handle, Connection{connection, std::move(eventThread)}); return handle; } sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection( ConnectionHandle handle, EventRegistrationFlags eventRegistration, const sp<IBinder>& layerHandle) { const auto connection = [&]() -> sp<EventThreadConnection> { std::scoped_lock lock(mConnectionsLock); RETURN_IF_INVALID_HANDLE(handle, nullptr); return mConnections[handle].thread->createEventConnection(eventRegistration); }(); Cycle cycle, EventRegistrationFlags eventRegistration, const sp<IBinder>& layerHandle) { const auto connection = eventThreadFor(cycle).createEventConnection(eventRegistration); const auto layerId = static_cast<int32_t>(LayerHandle::getLayerId(layerHandle)); if (layerId != static_cast<int32_t>(UNASSIGNED_LAYER_ID)) { Loading @@ -397,85 +375,48 @@ sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection( return connection; } sp<EventThreadConnection> Scheduler::getEventConnection(ConnectionHandle handle) { std::lock_guard<std::mutex> lock(mConnectionsLock); RETURN_IF_INVALID_HANDLE(handle, nullptr); return mConnections[handle].connection; void Scheduler::onHotplugReceived(Cycle cycle, PhysicalDisplayId displayId, bool connected) { if (hasEventThreads()) { eventThreadFor(cycle).onHotplugReceived(displayId, connected); } void Scheduler::onHotplugReceived(ConnectionHandle handle, PhysicalDisplayId displayId, bool connected) { android::EventThread* thread; { std::lock_guard<std::mutex> lock(mConnectionsLock); RETURN_IF_INVALID_HANDLE(handle); thread = mConnections[handle].thread.get(); } thread->onHotplugReceived(displayId, connected); void Scheduler::onHotplugConnectionError(Cycle cycle, int32_t errorCode) { if (hasEventThreads()) { eventThreadFor(cycle).onHotplugConnectionError(errorCode); } void Scheduler::onHotplugConnectionError(ConnectionHandle handle, int32_t errorCode) { android::EventThread* thread; { std::lock_guard<std::mutex> lock(mConnectionsLock); RETURN_IF_INVALID_HANDLE(handle); thread = mConnections[handle].thread.get(); } thread->onHotplugConnectionError(errorCode); } void Scheduler::enableSyntheticVsync(bool enable) { // TODO(b/241285945): Remove connection handles. const ConnectionHandle handle = mAppConnectionHandle; android::EventThread* thread; { std::lock_guard<std::mutex> lock(mConnectionsLock); RETURN_IF_INVALID_HANDLE(handle); thread = mConnections[handle].thread.get(); } thread->enableSyntheticVsync(enable); eventThreadFor(Cycle::Render).enableSyntheticVsync(enable); } void Scheduler::onFrameRateOverridesChanged(ConnectionHandle handle, PhysicalDisplayId displayId) { void Scheduler::onFrameRateOverridesChanged(Cycle cycle, PhysicalDisplayId displayId) { const bool supportsFrameRateOverrideByContent = pacesetterSelectorPtr()->supportsAppFrameRateOverrideByContent(); std::vector<FrameRateOverride> overrides = mFrameRateOverrideMappings.getAllFrameRateOverrides(supportsFrameRateOverrideByContent); android::EventThread* thread; { std::lock_guard lock(mConnectionsLock); RETURN_IF_INVALID_HANDLE(handle); thread = mConnections[handle].thread.get(); } thread->onFrameRateOverridesChanged(displayId, std::move(overrides)); eventThreadFor(cycle).onFrameRateOverridesChanged(displayId, std::move(overrides)); } void Scheduler::onHdcpLevelsChanged(ConnectionHandle handle, PhysicalDisplayId displayId, void Scheduler::onHdcpLevelsChanged(Cycle cycle, PhysicalDisplayId displayId, int32_t connectedLevel, int32_t maxLevel) { android::EventThread* thread; { std::lock_guard<std::mutex> lock(mConnectionsLock); RETURN_IF_INVALID_HANDLE(handle); thread = mConnections[handle].thread.get(); } thread->onHdcpLevelsChanged(displayId, connectedLevel, maxLevel); eventThreadFor(cycle).onHdcpLevelsChanged(displayId, connectedLevel, maxLevel); } void Scheduler::onPrimaryDisplayModeChanged(ConnectionHandle handle, const FrameRateMode& mode) { void Scheduler::onPrimaryDisplayModeChanged(Cycle cycle, const FrameRateMode& mode) { { std::lock_guard<std::mutex> lock(mPolicyLock); // Cache the last reported modes for primary display. mPolicy.cachedModeChangedParams = {handle, mode}; mPolicy.cachedModeChangedParams = {cycle, mode}; // Invalidate content based refresh rate selection so it could be calculated // again for the new refresh rate. mPolicy.contentRequirements.clear(); } onNonPrimaryDisplayModeChanged(handle, mode); onNonPrimaryDisplayModeChanged(cycle, mode); } void Scheduler::dispatchCachedReportedMode() { Loading @@ -502,39 +443,25 @@ void Scheduler::dispatchCachedReportedMode() { } mPolicy.cachedModeChangedParams->mode = *mPolicy.modeOpt; onNonPrimaryDisplayModeChanged(mPolicy.cachedModeChangedParams->handle, onNonPrimaryDisplayModeChanged(mPolicy.cachedModeChangedParams->cycle, mPolicy.cachedModeChangedParams->mode); } void Scheduler::onNonPrimaryDisplayModeChanged(ConnectionHandle handle, const FrameRateMode& mode) { android::EventThread* thread; { std::lock_guard<std::mutex> lock(mConnectionsLock); RETURN_IF_INVALID_HANDLE(handle); thread = mConnections[handle].thread.get(); void Scheduler::onNonPrimaryDisplayModeChanged(Cycle cycle, const FrameRateMode& mode) { if (hasEventThreads()) { eventThreadFor(cycle).onModeChanged(mode); } thread->onModeChanged(mode); } void Scheduler::dump(ConnectionHandle handle, std::string& result) const { android::EventThread* thread; { std::lock_guard<std::mutex> lock(mConnectionsLock); RETURN_IF_INVALID_HANDLE(handle); thread = mConnections.at(handle).thread.get(); } thread->dump(result); void Scheduler::dump(Cycle cycle, std::string& result) const { eventThreadFor(cycle).dump(result); } void Scheduler::setDuration(ConnectionHandle handle, std::chrono::nanoseconds workDuration, void Scheduler::setDuration(Cycle cycle, std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration) { android::EventThread* thread; { std::lock_guard<std::mutex> lock(mConnectionsLock); RETURN_IF_INVALID_HANDLE(handle); thread = mConnections[handle].thread.get(); if (hasEventThreads()) { eventThreadFor(cycle).setDuration(workDuration, readyDuration); } thread->setDuration(workDuration, readyDuration); } void Scheduler::updatePhaseConfiguration(Fps refreshRate) { Loading @@ -557,10 +484,10 @@ void Scheduler::setActiveDisplayPowerModeForRefreshRateStats(hal::PowerMode powe } void Scheduler::setVsyncConfig(const VsyncConfig& config, Period vsyncPeriod) { setDuration(mAppConnectionHandle, setDuration(Cycle::Render, /* workDuration */ config.appWorkDuration, /* readyDuration */ config.sfWorkDuration); setDuration(mSfConnectionHandle, setDuration(Cycle::LastComposite, /* workDuration */ vsyncPeriod, /* readyDuration */ config.sfWorkDuration); setDuration(config.sfWorkDuration); Loading Loading @@ -1027,16 +954,10 @@ std::shared_ptr<VsyncSchedule> Scheduler::promotePacesetterDisplayLocked( void Scheduler::applyNewVsyncSchedule(std::shared_ptr<VsyncSchedule> vsyncSchedule) { onNewVsyncSchedule(vsyncSchedule->getDispatch()); std::vector<android::EventThread*> threads; { std::lock_guard<std::mutex> lock(mConnectionsLock); threads.reserve(mConnections.size()); for (auto& [_, connection] : mConnections) { threads.push_back(connection.thread.get()); } } for (auto* thread : threads) { thread->onNewVsyncSchedule(vsyncSchedule); if (hasEventThreads()) { eventThreadFor(Cycle::Render).onNewVsyncSchedule(vsyncSchedule); eventThreadFor(Cycle::LastComposite).onNewVsyncSchedule(vsyncSchedule); } } Loading
services/surfaceflinger/Scheduler/Scheduler.h +34 −62 Original line number Diff line number Diff line Loading @@ -56,35 +56,6 @@ #include <FrontEnd/LayerHierarchy.h> namespace android::scheduler { // Opaque handle to scheduler connection. struct ConnectionHandle { using Id = std::uintptr_t; static constexpr Id INVALID_ID = static_cast<Id>(-1); Id id = INVALID_ID; explicit operator bool() const { return id != INVALID_ID; } }; inline bool operator==(ConnectionHandle lhs, ConnectionHandle rhs) { return lhs.id == rhs.id; } } // namespace android::scheduler namespace std { template <> struct hash<android::scheduler::ConnectionHandle> { size_t operator()(android::scheduler::ConnectionHandle handle) const { return hash<android::scheduler::ConnectionHandle::Id>()(handle.id); } }; } // namespace std namespace android { class FenceTime; Loading @@ -106,6 +77,11 @@ class RefreshRateStats; class VsyncConfiguration; class VsyncSchedule; enum class Cycle { Render, // Surface rendering. LastComposite // Ahead of display compositing by one refresh period. }; class Scheduler : public IEventThreadCallback, android::impl::MessageQueue { using Impl = android::impl::MessageQueue; Loading Loading @@ -154,36 +130,32 @@ public: return std::move(future); } enum class Cycle { Render, // Surface rendering. LastComposite // Ahead of display compositing by one refresh period. }; ConnectionHandle createEventThread(Cycle, frametimeline::TokenManager*, void createEventThread(Cycle, frametimeline::TokenManager*, std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration); sp<IDisplayEventConnection> createDisplayEventConnection( ConnectionHandle, EventRegistrationFlags eventRegistration = {}, Cycle, EventRegistrationFlags eventRegistration = {}, const sp<IBinder>& layerHandle = nullptr) EXCLUDES(mChoreographerLock); sp<EventThreadConnection> getEventConnection(ConnectionHandle); const sp<EventThreadConnection>& getEventConnection(Cycle cycle) const { return cycle == Cycle::Render ? mRenderEventConnection : mLastCompositeEventConnection; } void onHotplugReceived(ConnectionHandle, PhysicalDisplayId, bool connected); void onHotplugConnectionError(ConnectionHandle, int32_t errorCode); void onHotplugReceived(Cycle, PhysicalDisplayId, bool connected); void onHotplugConnectionError(Cycle, int32_t errorCode); void onPrimaryDisplayModeChanged(ConnectionHandle, const FrameRateMode&) EXCLUDES(mPolicyLock); void onNonPrimaryDisplayModeChanged(ConnectionHandle, const FrameRateMode&); void onPrimaryDisplayModeChanged(Cycle, const FrameRateMode&) EXCLUDES(mPolicyLock); void onNonPrimaryDisplayModeChanged(Cycle, const FrameRateMode&); void enableSyntheticVsync(bool = true) REQUIRES(kMainThreadContext); void onFrameRateOverridesChanged(ConnectionHandle, PhysicalDisplayId) EXCLUDES(mConnectionsLock); void onFrameRateOverridesChanged(Cycle, PhysicalDisplayId); void onHdcpLevelsChanged(ConnectionHandle, PhysicalDisplayId, int32_t, int32_t); void onHdcpLevelsChanged(Cycle, PhysicalDisplayId, int32_t, int32_t); // Modifies work duration in the event thread. void setDuration(ConnectionHandle, std::chrono::nanoseconds workDuration, void setDuration(Cycle, std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration); VsyncModulator& vsyncModulator() { return *mVsyncModulator; } Loading Loading @@ -288,7 +260,7 @@ public: bool isVsyncInPhase(TimePoint expectedVsyncTime, Fps frameRate) const; void dump(utils::Dumper&) const; void dump(ConnectionHandle, std::string&) const; void dump(Cycle, std::string&) const; void dumpVsync(std::string&) const EXCLUDES(mDisplayLock); // Returns the preferred refresh rate and frame rate for the pacesetter display. Loading Loading @@ -369,8 +341,15 @@ private: void onFrameSignal(ICompositor&, VsyncId, TimePoint expectedVsyncTime) override REQUIRES(kMainThreadContext, mDisplayLock); // Create a connection on the given EventThread. ConnectionHandle createConnection(std::unique_ptr<EventThread>); // Used to skip event dispatch before EventThread creation during boot. // TODO: b/241285191 - Reorder Scheduler initialization to avoid this. bool hasEventThreads() const { return CC_LIKELY(mRenderEventThread && mLastCompositeEventThread); } EventThread& eventThreadFor(Cycle cycle) const { return *(cycle == Cycle::Render ? mRenderEventThread : mLastCompositeEventThread); } // Update feature state machine to given state when corresponding timer resets or expires. void kernelIdleTimerCallback(TimerState) EXCLUDES(mDisplayLock); Loading Loading @@ -460,18 +439,11 @@ private: void resync() override EXCLUDES(mDisplayLock); void onExpectedPresentTimePosted(TimePoint expectedPresentTime) override EXCLUDES(mDisplayLock); // Stores EventThread associated with a given VSyncSource, and an initial EventThreadConnection. struct Connection { sp<EventThreadConnection> connection; std::unique_ptr<EventThread> thread; }; ConnectionHandle::Id mNextConnectionHandleId = 0; mutable std::mutex mConnectionsLock; std::unordered_map<ConnectionHandle, Connection> mConnections GUARDED_BY(mConnectionsLock); std::unique_ptr<EventThread> mRenderEventThread; sp<EventThreadConnection> mRenderEventConnection; ConnectionHandle mAppConnectionHandle; ConnectionHandle mSfConnectionHandle; std::unique_ptr<EventThread> mLastCompositeEventThread; sp<EventThreadConnection> mLastCompositeEventConnection; std::atomic<nsecs_t> mLastResyncTime = 0; Loading Loading @@ -585,7 +557,7 @@ private: ftl::Optional<FrameRateMode> modeOpt; struct ModeChangedParams { ConnectionHandle handle; Cycle cycle; FrameRateMode mode; }; Loading
services/surfaceflinger/SurfaceFlinger.cpp +35 −33 Original line number Diff line number Diff line Loading @@ -2085,12 +2085,11 @@ status_t SurfaceFlinger::getDisplayDecorationSupport( sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection( gui::ISurfaceComposer::VsyncSource vsyncSource, EventRegistrationFlags eventRegistration, const sp<IBinder>& layerHandle) { const auto& handle = vsyncSource == gui::ISurfaceComposer::VsyncSource::eVsyncSourceSurfaceFlinger ? mSfConnectionHandle : mAppConnectionHandle; const auto cycle = vsyncSource == gui::ISurfaceComposer::VsyncSource::eVsyncSourceSurfaceFlinger ? scheduler::Cycle::LastComposite : scheduler::Cycle::Render; return mScheduler->createDisplayEventConnection(handle, eventRegistration, layerHandle); return mScheduler->createDisplayEventConnection(cycle, eventRegistration, layerHandle); } void SurfaceFlinger::scheduleCommit(FrameHint hint) { Loading Loading @@ -2132,7 +2131,7 @@ void SurfaceFlinger::onComposerHalVsync(hal::HWDisplayId hwcDisplayId, int64_t t const int32_t hotplugErrorCode = static_cast<int32_t>(-timestamp); ALOGD("SurfaceFlinger got hotplugErrorCode=%d for display %" PRIu64, hotplugErrorCode, hwcDisplayId); mScheduler->onHotplugConnectionError(mAppConnectionHandle, hotplugErrorCode); mScheduler->onHotplugConnectionError(scheduler::Cycle::Render, hotplugErrorCode); return; } Loading Loading @@ -2183,7 +2182,7 @@ void SurfaceFlinger::onComposerHalHotplugEvent(hal::HWDisplayId hwcDisplayId, if (FlagManager::getInstance().hotplug2()) { ALOGD("SurfaceFlinger got hotplug event=%d", static_cast<int32_t>(event)); // TODO(b/311403559): use enum type instead of int mScheduler->onHotplugConnectionError(mAppConnectionHandle, static_cast<int32_t>(event)); mScheduler->onHotplugConnectionError(scheduler::Cycle::Render, static_cast<int32_t>(event)); } } Loading Loading @@ -3473,7 +3472,7 @@ const char* SurfaceFlinger::processHotplug(PhysicalDisplayId displayId, if (!activeMode) { ALOGE("Failed to hotplug display %s", to_string(displayId).c_str()); if (FlagManager::getInstance().hotplug2()) { mScheduler->onHotplugConnectionError(mAppConnectionHandle, mScheduler->onHotplugConnectionError(scheduler::Cycle::Render, static_cast<int32_t>( DisplayHotplugEvent::ERROR_UNKNOWN)); } Loading Loading @@ -3526,8 +3525,8 @@ const char* SurfaceFlinger::processHotplug(PhysicalDisplayId displayId, } void SurfaceFlinger::dispatchDisplayHotplugEvent(PhysicalDisplayId displayId, bool connected) { mScheduler->onHotplugReceived(mAppConnectionHandle, displayId, connected); mScheduler->onHotplugReceived(mSfConnectionHandle, displayId, connected); mScheduler->onHotplugReceived(scheduler::Cycle::Render, displayId, connected); mScheduler->onHotplugReceived(scheduler::Cycle::LastComposite, displayId, connected); } void SurfaceFlinger::dispatchDisplayModeChangeEvent(PhysicalDisplayId displayId, Loading @@ -3537,7 +3536,7 @@ void SurfaceFlinger::dispatchDisplayModeChangeEvent(PhysicalDisplayId displayId, ? &scheduler::Scheduler::onPrimaryDisplayModeChanged : &scheduler::Scheduler::onNonPrimaryDisplayModeChanged; ((*mScheduler).*onDisplayModeChanged)(mAppConnectionHandle, mode); ((*mScheduler).*onDisplayModeChanged)(scheduler::Cycle::Render, mode); } sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( Loading Loading @@ -4189,7 +4188,7 @@ void SurfaceFlinger::triggerOnFrameRateOverridesChanged() { return getDefaultDisplayDeviceLocked()->getPhysicalId(); }(); mScheduler->onFrameRateOverridesChanged(mAppConnectionHandle, displayId); mScheduler->onFrameRateOverridesChanged(scheduler::Cycle::Render, displayId); } void SurfaceFlinger::notifyCpuLoadUp() { Loading Loading @@ -4354,21 +4353,19 @@ void SurfaceFlinger::initScheduler(const sp<const DisplayDevice>& display) { mScheduler = std::make_unique<Scheduler>(static_cast<ICompositor&>(*this), static_cast<ISchedulerCallback&>(*this), features, getFactory(), activeRefreshRate, *mTimeStats); // The pacesetter must be registered before EventThread creation below. mScheduler->registerDisplay(display->getPhysicalId(), display->holdRefreshRateSelector()); if (FlagManager::getInstance().vrr_config()) { mScheduler->setRenderRate(display->getPhysicalId(), activeMode.fps); } mScheduler->startTimers(); const auto configs = mScheduler->getVsyncConfiguration().getCurrentConfigs(); mAppConnectionHandle = mScheduler->createEventThread(Scheduler::Cycle::Render, mFrameTimeline->getTokenManager(), mScheduler->createEventThread(scheduler::Cycle::Render, mFrameTimeline->getTokenManager(), /* workDuration */ configs.late.appWorkDuration, /* readyDuration */ configs.late.sfWorkDuration); mSfConnectionHandle = mScheduler->createEventThread(Scheduler::Cycle::LastComposite, mScheduler->createEventThread(scheduler::Cycle::LastComposite, mFrameTimeline->getTokenManager(), /* workDuration */ activeRefreshRate.getPeriod(), /* readyDuration */ configs.late.sfWorkDuration); Loading @@ -4379,6 +4376,9 @@ void SurfaceFlinger::initScheduler(const sp<const DisplayDevice>& display) { sp<RegionSamplingThread>::make(*this, RegionSamplingThread::EnvironmentTimingTunables()); mFpsReporter = sp<FpsReporter>::make(*mFrameTimeline); // Timer callbacks may fire, so do this last. mScheduler->startTimers(); } void SurfaceFlinger::doCommitTransactions() { Loading Loading @@ -6315,7 +6315,7 @@ void SurfaceFlinger::dumpScheduler(std::string& result) const { } void SurfaceFlinger::dumpEvents(std::string& result) const { mScheduler->dump(mAppConnectionHandle, result); mScheduler->dump(scheduler::Cycle::Render, result); } void SurfaceFlinger::dumpVsync(std::string& result) const { Loading Loading @@ -7087,14 +7087,15 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r mForceFullDamage = n != 0; return NO_ERROR; } case 1018: { // Modify Choreographer's duration case 1018: { // Set the render deadline as a duration until VSYNC. n = data.readInt32(); mScheduler->setDuration(mAppConnectionHandle, std::chrono::nanoseconds(n), 0ns); mScheduler->setDuration(scheduler::Cycle::Render, std::chrono::nanoseconds(n), 0ns); return NO_ERROR; } case 1019: { // Modify SurfaceFlinger's duration case 1019: { // Set the deadline of the last composite as a duration until VSYNC. n = data.readInt32(); mScheduler->setDuration(mSfConnectionHandle, std::chrono::nanoseconds(n), 0ns); mScheduler->setDuration(scheduler::Cycle::LastComposite, std::chrono::nanoseconds(n), 0ns); return NO_ERROR; } case 1020: { // Unused Loading Loading @@ -7326,7 +7327,7 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r auto inUid = static_cast<uid_t>(data.readInt32()); const auto refreshRate = data.readFloat(); mScheduler->setPreferredRefreshRateForUid(FrameRateOverride{inUid, refreshRate}); mScheduler->onFrameRateOverridesChanged(mAppConnectionHandle, displayId); mScheduler->onFrameRateOverridesChanged(scheduler::Cycle::Render, displayId); return NO_ERROR; } // Toggle caching feature Loading Loading @@ -8466,10 +8467,10 @@ status_t SurfaceFlinger::applyRefreshRateSelectorPolicy( // TODO(b/140204874): Leave the event in until we do proper testing with all apps that might // be depending in this callback. if (const auto activeMode = selector.getActiveMode(); displayId == mActiveDisplayId) { mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, activeMode); mScheduler->onPrimaryDisplayModeChanged(scheduler::Cycle::Render, activeMode); toggleKernelIdleTimer(); } else { mScheduler->onNonPrimaryDisplayModeChanged(mAppConnectionHandle, activeMode); mScheduler->onNonPrimaryDisplayModeChanged(scheduler::Cycle::Render, activeMode); } auto preferredModeOpt = getPreferredDisplayMode(displayId, currentPolicy.defaultMode); Loading Loading @@ -8657,7 +8658,7 @@ status_t SurfaceFlinger::setGameModeFrameRateOverride(uid_t uid, float frameRate }(); mScheduler->setGameModeFrameRateForUid(FrameRateOverride{static_cast<uid_t>(uid), frameRate}); mScheduler->onFrameRateOverridesChanged(mAppConnectionHandle, displayId); mScheduler->onFrameRateOverridesChanged(scheduler::Cycle::Render, displayId); return NO_ERROR; } Loading Loading @@ -8919,7 +8920,8 @@ void SurfaceFlinger::updateHdcpLevels(hal::HWDisplayId hwcDisplayId, int32_t con Mutex::Autolock lock(mStateLock); display->setSecure(connectedLevel >= 2 /* HDCP_V1 */); } mScheduler->onHdcpLevelsChanged(mAppConnectionHandle, displayId, connectedLevel, maxLevel); mScheduler->onHdcpLevelsChanged(scheduler::Cycle::Render, displayId, connectedLevel, maxLevel); })); } Loading
services/surfaceflinger/SurfaceFlinger.h +0 −5 Original line number Diff line number Diff line Loading @@ -1356,12 +1356,7 @@ private: const std::string mHwcServiceName; /* * Scheduler */ std::unique_ptr<scheduler::Scheduler> mScheduler; scheduler::ConnectionHandle mAppConnectionHandle; scheduler::ConnectionHandle mSfConnectionHandle; scheduler::PresentLatencyTracker mPresentLatencyTracker GUARDED_BY(kMainThreadContext); Loading
services/surfaceflinger/tests/unittests/SchedulerTest.cpp +14 −72 File changed.Preview size limit exceeded, changes collapsed. Show changes