Loading libs/dumputils/dump_utils.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -75,6 +75,7 @@ static const char* hal_interfaces_to_dump[] { "android.hardware.automotive.audiocontrol@1.0::IAudioControl", "android.hardware.automotive.vehicle@2.0::IVehicle", "android.hardware.automotive.evs@1.0::IEvsCamera", "android.hardware.neuralnetworks@1.0::IDevice", NULL, }; Loading services/surfaceflinger/CompositionEngine/src/ClientCompositionRequestCache.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -35,7 +35,8 @@ inline bool equalIgnoringSource(const renderengine::LayerSettings& lhs, return lhs.geometry == rhs.geometry && lhs.alpha == rhs.alpha && lhs.sourceDataspace == rhs.sourceDataspace && lhs.colorTransform == rhs.colorTransform && lhs.disableBlending == rhs.disableBlending && lhs.shadow == rhs.shadow; lhs.disableBlending == rhs.disableBlending && lhs.shadow == rhs.shadow && lhs.backgroundBlurRadius == rhs.backgroundBlurRadius; } inline bool equalIgnoringBuffer(const renderengine::Buffer& lhs, const renderengine::Buffer& rhs) { Loading services/surfaceflinger/Scheduler/PhaseOffsets.cpp +20 −9 Original line number Diff line number Diff line Loading @@ -71,15 +71,20 @@ std::unordered_map<float, PhaseOffsets::Offsets> PhaseOffsets::initializeOffsets std::unordered_map<float, Offsets> offsets; for (const auto& [ignored, refreshRate] : refreshRateConfigs.getAllRefreshRates()) { if (refreshRate->fps > 65.0f) { offsets.emplace(refreshRate->fps, getHighFpsOffsets(refreshRate->vsyncPeriod)); } else { offsets.emplace(refreshRate->fps, getDefaultOffsets(refreshRate->vsyncPeriod)); } const float fps = refreshRate->fps; offsets.emplace(fps, getPhaseOffsets(fps, refreshRate->vsyncPeriod)); } return offsets; } PhaseOffsets::Offsets PhaseOffsets::getPhaseOffsets(float fps, nsecs_t vsyncPeriod) const { if (fps > 65.0f) { return getHighFpsOffsets(vsyncPeriod); } else { return getDefaultOffsets(vsyncPeriod); } } PhaseOffsets::Offsets PhaseOffsets::getDefaultOffsets(nsecs_t vsyncDuration) const { const int64_t vsyncPhaseOffsetNs = sysprop::vsync_event_phase_offset_ns(1000000); const int64_t sfVsyncPhaseOffsetNs = sysprop::vsync_sf_event_phase_offset_ns(1000000); Loading Loading @@ -159,10 +164,17 @@ PhaseOffsets::Offsets PhaseOffsets::getOffsetsForRefreshRate(float fps) const { [&fps](const std::pair<float, Offsets>& candidateFps) { return fpsEqualsWithMargin(fps, candidateFps.first); }); LOG_ALWAYS_FATAL_IF(iter == mOffsets.end()); if (iter != mOffsets.end()) { return iter->second; } // Unknown refresh rate. This might happen if we get a hotplug event for an external display. // In this case just construct the offset. ALOGW("Can't find offset for %.2f fps", fps); return getPhaseOffsets(fps, static_cast<nsecs_t>(1e9f / fps)); } static void validateSysprops() { const auto validatePropertyBool = [](const char* prop) { LOG_ALWAYS_FATAL_IF(!property_get_bool(prop, false), "%s is false", prop); Loading Loading @@ -288,8 +300,7 @@ PhaseOffsets::Offsets PhaseDurations::getOffsetsForRefreshRate(float fps) const return iter->second; } // Unknown refresh rate. This might happen if we get a hotplug event for the default display. // This happens only during tests and not during regular device operation. // Unknown refresh rate. This might happen if we get a hotplug event for an external display. // In this case just construct the offset. ALOGW("Can't find offset for %.2f fps", fps); return constructOffsets(static_cast<nsecs_t>(1e9f / fps)); Loading services/surfaceflinger/Scheduler/PhaseOffsets.h +3 −2 Original line number Diff line number Diff line Loading @@ -69,8 +69,9 @@ public: private: std::unordered_map<float, Offsets> initializeOffsets( const scheduler::RefreshRateConfigs&) const; Offsets getDefaultOffsets(nsecs_t vsyncDuration) const; Offsets getHighFpsOffsets(nsecs_t vsyncDuration) const; Offsets getDefaultOffsets(nsecs_t vsyncPeriod) const; Offsets getHighFpsOffsets(nsecs_t vsyncPeriod) const; Offsets getPhaseOffsets(float fps, nsecs_t vsyncPeriod) const; const nsecs_t mThresholdForNextVsync; const std::unordered_map<float, Offsets> mOffsets; Loading services/surfaceflinger/SurfaceFlinger.cpp +46 −11 Original line number Diff line number Diff line Loading @@ -1028,7 +1028,7 @@ bool SurfaceFlinger::performSetActiveConfig() { ATRACE_CALL(); ALOGV("performSetActiveConfig"); if (mCheckPendingFence) { if (previousFrameMissed()) { if (previousFramePending()) { // fence has not signaled yet. wait for the next invalidate mEventQueue->invalidate(); return true; Loading Loading @@ -1775,13 +1775,17 @@ void SurfaceFlinger::updateVrFlinger() { setTransactionFlags(eDisplayTransactionNeeded); } bool SurfaceFlinger::previousFrameMissed(int graceTimeMs) NO_THREAD_SAFETY_ANALYSIS { ATRACE_CALL(); sp<Fence> SurfaceFlinger::previousFrameFence() NO_THREAD_SAFETY_ANALYSIS { // We are storing the last 2 present fences. If sf's phase offset is to be // woken up before the actual vsync but targeting the next vsync, we need to check // fence N-2 const sp<Fence>& fence = mVSyncModulator->getOffsets().sf > 0 ? mPreviousPresentFences[0] return mVSyncModulator->getOffsets().sf > 0 ? mPreviousPresentFences[0] : mPreviousPresentFences[1]; } bool SurfaceFlinger::previousFramePending(int graceTimeMs) NO_THREAD_SAFETY_ANALYSIS { ATRACE_CALL(); const sp<Fence>& fence = previousFrameFence(); if (fence == Fence::NO_FENCE) { return false; Loading @@ -1794,6 +1798,16 @@ bool SurfaceFlinger::previousFrameMissed(int graceTimeMs) NO_THREAD_SAFETY_ANALY return (fence->getStatus() == Fence::Status::Unsignaled); } nsecs_t SurfaceFlinger::previousFramePresentTime() NO_THREAD_SAFETY_ANALYSIS { const sp<Fence>& fence = previousFrameFence(); if (fence == Fence::NO_FENCE) { return Fence::SIGNAL_TIME_INVALID; } return fence->getSignalTime(); } void SurfaceFlinger::populateExpectedPresentTime() { DisplayStatInfo stats; mScheduler->getDisplayStatInfo(&stats); Loading @@ -1811,6 +1825,7 @@ void SurfaceFlinger::onMessageReceived(int32_t what) NO_THREAD_SAFETY_ANALYSIS { // calculate the expected present time once and use the cached // value throughout this frame to make sure all layers are // seeing this same value. const nsecs_t lastExpectedPresentTime = mExpectedPresentTime.load(); populateExpectedPresentTime(); // When Backpressure propagation is enabled we want to give a small grace period Loading @@ -1821,12 +1836,32 @@ void SurfaceFlinger::onMessageReceived(int32_t what) NO_THREAD_SAFETY_ANALYSIS { (mPropagateBackpressureClientComposition || !mHadClientComposition)) ? 1 : 0; const TracedOrdinal<bool> frameMissed = {"FrameMissed", previousFrameMissed( // Pending frames may trigger backpressure propagation. const TracedOrdinal<bool> framePending = {"PrevFramePending", previousFramePending( graceTimeForPresentFenceMs)}; const TracedOrdinal<bool> hwcFrameMissed = {"HwcFrameMissed", // Frame missed counts for metrics tracking. // A frame is missed if the prior frame is still pending. If no longer pending, // then we still count the frame as missed if the predicted present time // was further in the past than when the fence actually fired. // Add some slop to correct for drift. This should generally be // smaller than a typical frame duration, but should not be so small // that it reports reasonable drift as a missed frame. DisplayStatInfo stats; mScheduler->getDisplayStatInfo(&stats); const nsecs_t frameMissedSlop = stats.vsyncPeriod / 2; const nsecs_t previousPresentTime = previousFramePresentTime(); const TracedOrdinal<bool> frameMissed = {"PrevFrameMissed", framePending || (previousPresentTime >= 0 && (lastExpectedPresentTime < previousPresentTime - frameMissedSlop))}; const TracedOrdinal<bool> hwcFrameMissed = {"PrevHwcFrameMissed", mHadDeviceComposition && frameMissed}; const TracedOrdinal<bool> gpuFrameMissed = {"GpuFrameMissed", const TracedOrdinal<bool> gpuFrameMissed = {"PrevGpuFrameMissed", mHadClientComposition && frameMissed}; if (frameMissed) { Loading @@ -1846,7 +1881,7 @@ void SurfaceFlinger::onMessageReceived(int32_t what) NO_THREAD_SAFETY_ANALYSIS { mGpuFrameMissedCount++; } if (frameMissed && mPropagateBackpressure) { if (framePending && mPropagateBackpressure) { if ((hwcFrameMissed && !gpuFrameMissed) || mPropagateBackpressureClientComposition) { signalLayerUpdate(); Loading Loading
libs/dumputils/dump_utils.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -75,6 +75,7 @@ static const char* hal_interfaces_to_dump[] { "android.hardware.automotive.audiocontrol@1.0::IAudioControl", "android.hardware.automotive.vehicle@2.0::IVehicle", "android.hardware.automotive.evs@1.0::IEvsCamera", "android.hardware.neuralnetworks@1.0::IDevice", NULL, }; Loading
services/surfaceflinger/CompositionEngine/src/ClientCompositionRequestCache.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -35,7 +35,8 @@ inline bool equalIgnoringSource(const renderengine::LayerSettings& lhs, return lhs.geometry == rhs.geometry && lhs.alpha == rhs.alpha && lhs.sourceDataspace == rhs.sourceDataspace && lhs.colorTransform == rhs.colorTransform && lhs.disableBlending == rhs.disableBlending && lhs.shadow == rhs.shadow; lhs.disableBlending == rhs.disableBlending && lhs.shadow == rhs.shadow && lhs.backgroundBlurRadius == rhs.backgroundBlurRadius; } inline bool equalIgnoringBuffer(const renderengine::Buffer& lhs, const renderengine::Buffer& rhs) { Loading
services/surfaceflinger/Scheduler/PhaseOffsets.cpp +20 −9 Original line number Diff line number Diff line Loading @@ -71,15 +71,20 @@ std::unordered_map<float, PhaseOffsets::Offsets> PhaseOffsets::initializeOffsets std::unordered_map<float, Offsets> offsets; for (const auto& [ignored, refreshRate] : refreshRateConfigs.getAllRefreshRates()) { if (refreshRate->fps > 65.0f) { offsets.emplace(refreshRate->fps, getHighFpsOffsets(refreshRate->vsyncPeriod)); } else { offsets.emplace(refreshRate->fps, getDefaultOffsets(refreshRate->vsyncPeriod)); } const float fps = refreshRate->fps; offsets.emplace(fps, getPhaseOffsets(fps, refreshRate->vsyncPeriod)); } return offsets; } PhaseOffsets::Offsets PhaseOffsets::getPhaseOffsets(float fps, nsecs_t vsyncPeriod) const { if (fps > 65.0f) { return getHighFpsOffsets(vsyncPeriod); } else { return getDefaultOffsets(vsyncPeriod); } } PhaseOffsets::Offsets PhaseOffsets::getDefaultOffsets(nsecs_t vsyncDuration) const { const int64_t vsyncPhaseOffsetNs = sysprop::vsync_event_phase_offset_ns(1000000); const int64_t sfVsyncPhaseOffsetNs = sysprop::vsync_sf_event_phase_offset_ns(1000000); Loading Loading @@ -159,10 +164,17 @@ PhaseOffsets::Offsets PhaseOffsets::getOffsetsForRefreshRate(float fps) const { [&fps](const std::pair<float, Offsets>& candidateFps) { return fpsEqualsWithMargin(fps, candidateFps.first); }); LOG_ALWAYS_FATAL_IF(iter == mOffsets.end()); if (iter != mOffsets.end()) { return iter->second; } // Unknown refresh rate. This might happen if we get a hotplug event for an external display. // In this case just construct the offset. ALOGW("Can't find offset for %.2f fps", fps); return getPhaseOffsets(fps, static_cast<nsecs_t>(1e9f / fps)); } static void validateSysprops() { const auto validatePropertyBool = [](const char* prop) { LOG_ALWAYS_FATAL_IF(!property_get_bool(prop, false), "%s is false", prop); Loading Loading @@ -288,8 +300,7 @@ PhaseOffsets::Offsets PhaseDurations::getOffsetsForRefreshRate(float fps) const return iter->second; } // Unknown refresh rate. This might happen if we get a hotplug event for the default display. // This happens only during tests and not during regular device operation. // Unknown refresh rate. This might happen if we get a hotplug event for an external display. // In this case just construct the offset. ALOGW("Can't find offset for %.2f fps", fps); return constructOffsets(static_cast<nsecs_t>(1e9f / fps)); Loading
services/surfaceflinger/Scheduler/PhaseOffsets.h +3 −2 Original line number Diff line number Diff line Loading @@ -69,8 +69,9 @@ public: private: std::unordered_map<float, Offsets> initializeOffsets( const scheduler::RefreshRateConfigs&) const; Offsets getDefaultOffsets(nsecs_t vsyncDuration) const; Offsets getHighFpsOffsets(nsecs_t vsyncDuration) const; Offsets getDefaultOffsets(nsecs_t vsyncPeriod) const; Offsets getHighFpsOffsets(nsecs_t vsyncPeriod) const; Offsets getPhaseOffsets(float fps, nsecs_t vsyncPeriod) const; const nsecs_t mThresholdForNextVsync; const std::unordered_map<float, Offsets> mOffsets; Loading
services/surfaceflinger/SurfaceFlinger.cpp +46 −11 Original line number Diff line number Diff line Loading @@ -1028,7 +1028,7 @@ bool SurfaceFlinger::performSetActiveConfig() { ATRACE_CALL(); ALOGV("performSetActiveConfig"); if (mCheckPendingFence) { if (previousFrameMissed()) { if (previousFramePending()) { // fence has not signaled yet. wait for the next invalidate mEventQueue->invalidate(); return true; Loading Loading @@ -1775,13 +1775,17 @@ void SurfaceFlinger::updateVrFlinger() { setTransactionFlags(eDisplayTransactionNeeded); } bool SurfaceFlinger::previousFrameMissed(int graceTimeMs) NO_THREAD_SAFETY_ANALYSIS { ATRACE_CALL(); sp<Fence> SurfaceFlinger::previousFrameFence() NO_THREAD_SAFETY_ANALYSIS { // We are storing the last 2 present fences. If sf's phase offset is to be // woken up before the actual vsync but targeting the next vsync, we need to check // fence N-2 const sp<Fence>& fence = mVSyncModulator->getOffsets().sf > 0 ? mPreviousPresentFences[0] return mVSyncModulator->getOffsets().sf > 0 ? mPreviousPresentFences[0] : mPreviousPresentFences[1]; } bool SurfaceFlinger::previousFramePending(int graceTimeMs) NO_THREAD_SAFETY_ANALYSIS { ATRACE_CALL(); const sp<Fence>& fence = previousFrameFence(); if (fence == Fence::NO_FENCE) { return false; Loading @@ -1794,6 +1798,16 @@ bool SurfaceFlinger::previousFrameMissed(int graceTimeMs) NO_THREAD_SAFETY_ANALY return (fence->getStatus() == Fence::Status::Unsignaled); } nsecs_t SurfaceFlinger::previousFramePresentTime() NO_THREAD_SAFETY_ANALYSIS { const sp<Fence>& fence = previousFrameFence(); if (fence == Fence::NO_FENCE) { return Fence::SIGNAL_TIME_INVALID; } return fence->getSignalTime(); } void SurfaceFlinger::populateExpectedPresentTime() { DisplayStatInfo stats; mScheduler->getDisplayStatInfo(&stats); Loading @@ -1811,6 +1825,7 @@ void SurfaceFlinger::onMessageReceived(int32_t what) NO_THREAD_SAFETY_ANALYSIS { // calculate the expected present time once and use the cached // value throughout this frame to make sure all layers are // seeing this same value. const nsecs_t lastExpectedPresentTime = mExpectedPresentTime.load(); populateExpectedPresentTime(); // When Backpressure propagation is enabled we want to give a small grace period Loading @@ -1821,12 +1836,32 @@ void SurfaceFlinger::onMessageReceived(int32_t what) NO_THREAD_SAFETY_ANALYSIS { (mPropagateBackpressureClientComposition || !mHadClientComposition)) ? 1 : 0; const TracedOrdinal<bool> frameMissed = {"FrameMissed", previousFrameMissed( // Pending frames may trigger backpressure propagation. const TracedOrdinal<bool> framePending = {"PrevFramePending", previousFramePending( graceTimeForPresentFenceMs)}; const TracedOrdinal<bool> hwcFrameMissed = {"HwcFrameMissed", // Frame missed counts for metrics tracking. // A frame is missed if the prior frame is still pending. If no longer pending, // then we still count the frame as missed if the predicted present time // was further in the past than when the fence actually fired. // Add some slop to correct for drift. This should generally be // smaller than a typical frame duration, but should not be so small // that it reports reasonable drift as a missed frame. DisplayStatInfo stats; mScheduler->getDisplayStatInfo(&stats); const nsecs_t frameMissedSlop = stats.vsyncPeriod / 2; const nsecs_t previousPresentTime = previousFramePresentTime(); const TracedOrdinal<bool> frameMissed = {"PrevFrameMissed", framePending || (previousPresentTime >= 0 && (lastExpectedPresentTime < previousPresentTime - frameMissedSlop))}; const TracedOrdinal<bool> hwcFrameMissed = {"PrevHwcFrameMissed", mHadDeviceComposition && frameMissed}; const TracedOrdinal<bool> gpuFrameMissed = {"GpuFrameMissed", const TracedOrdinal<bool> gpuFrameMissed = {"PrevGpuFrameMissed", mHadClientComposition && frameMissed}; if (frameMissed) { Loading @@ -1846,7 +1881,7 @@ void SurfaceFlinger::onMessageReceived(int32_t what) NO_THREAD_SAFETY_ANALYSIS { mGpuFrameMissedCount++; } if (frameMissed && mPropagateBackpressure) { if (framePending && mPropagateBackpressure) { if ((hwcFrameMissed && !gpuFrameMissed) || mPropagateBackpressureClientComposition) { signalLayerUpdate(); Loading