diff options
12 files changed, 120 insertions, 24 deletions
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h index 8ca178c1d7..7ca9031f77 100644 --- a/include/input/InputTransport.h +++ b/include/input/InputTransport.h @@ -404,6 +404,13 @@ public: */ bool hasPendingBatch() const; + /* Returns the source of first pending batch if exist. + * + * Should be called after calling consume() with consumeBatches == false to determine + * whether consume() should be called again later on with consumeBatches == true. + */ + int32_t getPendingBatchSource() const; + private: // True if touch resampling is enabled. const bool mResampleTouch; diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp index 5b65c95e95..b2b74dce6e 100644 --- a/libs/dumputils/dump_utils.cpp +++ b/libs/dumputils/dump_utils.cpp @@ -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, }; diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp index 7335b30a49..ef7cc7d531 100644 --- a/libs/input/InputTransport.cpp +++ b/libs/input/InputTransport.cpp @@ -1130,6 +1130,16 @@ bool InputConsumer::hasPendingBatch() const { return !mBatches.isEmpty(); } +int32_t InputConsumer::getPendingBatchSource() const { + if (mBatches.isEmpty()) { + return AINPUT_SOURCE_CLASS_NONE; + } + + const Batch& batch = mBatches.itemAt(0); + const InputMessage& head = batch.samples.itemAt(0); + return head.body.motion.source; +} + ssize_t InputConsumer::findBatch(int32_t deviceId, int32_t source) const { for (size_t i = 0; i < mBatches.size(); i++) { const Batch& batch = mBatches.itemAt(i); diff --git a/services/surfaceflinger/CompositionEngine/src/ClientCompositionRequestCache.cpp b/services/surfaceflinger/CompositionEngine/src/ClientCompositionRequestCache.cpp index acaaf4e1b9..2d9f01b9fd 100644 --- a/services/surfaceflinger/CompositionEngine/src/ClientCompositionRequestCache.cpp +++ b/services/surfaceflinger/CompositionEngine/src/ClientCompositionRequestCache.cpp @@ -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) { diff --git a/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h b/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h index e740b13203..b738096479 100644 --- a/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h +++ b/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h @@ -29,6 +29,7 @@ public: PowerAdvisor(); ~PowerAdvisor() override; + MOCK_METHOD0(onBootFinished, void()); MOCK_METHOD2(setExpensiveRenderingExpected, void(DisplayId displayId, bool expected)); MOCK_METHOD0(notifyDisplayUpdateImminent, void()); }; diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp index 06e0cbb044..1d8179c9ac 100644 --- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp +++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp @@ -72,6 +72,10 @@ PowerAdvisor::PowerAdvisor() } } +void PowerAdvisor::onBootFinished() { + mBootFinished.store(true); +} + void PowerAdvisor::setExpensiveRenderingExpected(DisplayId displayId, bool expected) { if (expected) { mExpensiveDisplays.insert(displayId); @@ -97,6 +101,12 @@ void PowerAdvisor::setExpensiveRenderingExpected(DisplayId displayId, bool expec } void PowerAdvisor::notifyDisplayUpdateImminent() { + // Only start sending this notification once the system has booted so we don't introduce an + // early-boot dependency on Power HAL + if (!mBootFinished.load()) { + return; + } + if (mSendUpdateImminent.load()) { HalWrapper* const halWrapper = getPowerHal(); if (halWrapper == nullptr) { diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h index 957d28989b..4a90acbdee 100644 --- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h +++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h @@ -35,6 +35,7 @@ class PowerAdvisor { public: virtual ~PowerAdvisor(); + virtual void onBootFinished() = 0; virtual void setExpensiveRenderingExpected(DisplayId displayId, bool expected) = 0; virtual void notifyDisplayUpdateImminent() = 0; }; @@ -56,12 +57,14 @@ public: PowerAdvisor(); ~PowerAdvisor() override; + void onBootFinished() override; void setExpensiveRenderingExpected(DisplayId displayId, bool expected) override; void notifyDisplayUpdateImminent() override; private: HalWrapper* getPowerHal(); + std::atomic_bool mBootFinished = false; bool mReconnectPowerHal = false; std::unordered_set<DisplayId> mExpensiveDisplays; diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp index c04447d106..7941cda6ef 100644 --- a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp +++ b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp @@ -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); @@ -159,8 +164,15 @@ 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()); - return iter->second; + + 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() { @@ -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)); diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.h b/services/surfaceflinger/Scheduler/PhaseOffsets.h index b7d4eae5b6..208f06b185 100644 --- a/services/surfaceflinger/Scheduler/PhaseOffsets.h +++ b/services/surfaceflinger/Scheduler/PhaseOffsets.h @@ -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; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index cfaabfc78c..2da92b3145 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -567,6 +567,7 @@ void SurfaceFlinger::bootFinished() postMessageAsync(new LambdaMessage([this]() NO_THREAD_SAFETY_ANALYSIS { readPersistentProperties(); + mPowerAdvisor.onBootFinished(); mBootStage = BootStage::FINISHED; if (property_get_bool("sf.debug.show_refresh_rate_overlay", false)) { @@ -1028,7 +1029,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; @@ -1775,13 +1776,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] - : mPreviousPresentFences[1]; + 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; @@ -1794,6 +1799,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); @@ -1811,6 +1826,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 @@ -1821,12 +1837,32 @@ void SurfaceFlinger::onMessageReceived(int32_t what) NO_THREAD_SAFETY_ANALYSIS { (mPropagateBackpressureClientComposition || !mHadClientComposition)) ? 1 : 0; - const TracedOrdinal<bool> frameMissed = {"FrameMissed", - previousFrameMissed( - graceTimeForPresentFenceMs)}; - const TracedOrdinal<bool> hwcFrameMissed = {"HwcFrameMissed", + + // Pending frames may trigger backpressure propagation. + const TracedOrdinal<bool> framePending = {"PrevFramePending", + previousFramePending( + graceTimeForPresentFenceMs)}; + + // 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) { @@ -1846,7 +1882,7 @@ void SurfaceFlinger::onMessageReceived(int32_t what) NO_THREAD_SAFETY_ANALYSIS { mGpuFrameMissedCount++; } - if (frameMissed && mPropagateBackpressure) { + if (framePending && mPropagateBackpressure) { if ((hwcFrameMissed && !gpuFrameMissed) || mPropagateBackpressureClientComposition) { signalLayerUpdate(); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 44e18a7463..6ab1fcf9d5 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -844,7 +844,21 @@ private: bool isDisplayConfigAllowed(HwcConfigIndexType configId) const REQUIRES(mStateLock); - bool previousFrameMissed(int graceTimeMs = 0); + // Gets the fence for the previous frame. + // Must be called on the main thread. + sp<Fence> previousFrameFence(); + + // Whether the previous frame has not yet been presented to the display. + // If graceTimeMs is positive, this method waits for at most the provided + // grace period before reporting if the frame missed. + // Must be called on the main thread. + bool previousFramePending(int graceTimeMs = 0); + + // Returns the previous time that the frame was presented. If the frame has + // not been presented yet, then returns Fence::SIGNAL_TIME_PENDING. If there + // is no pending frame, then returns Fence::SIGNAL_TIME_INVALID. + // Must be called on the main thread. + nsecs_t previousFramePresentTime(); // Populates the expected present time for this frame. For negative offsets, performs a // correction using the predicted vsync for the next frame instead. diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h index fe57c98df8..e22d0cf74c 100644 --- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h +++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h @@ -29,6 +29,7 @@ public: PowerAdvisor(); ~PowerAdvisor() override; + MOCK_METHOD0(onBootFinished, void()); MOCK_METHOD2(setExpensiveRenderingExpected, void(DisplayId displayId, bool expected)); MOCK_METHOD0(notifyDisplayUpdateImminent, void()); }; |