Revert "SF: Encapsulate frame targeting"
This reverts commit c183eed053289c242c32c5c35a7071863165a61d.
Reason for revert: Regression in SF performance.
Bug: 281884106
Test: Jank suites
Change-Id: I05adaa57c955a8c09c210943bc06977b48362aa4
diff --git a/libs/ui/include/ui/FenceTime.h b/libs/ui/include/ui/FenceTime.h
index 334106f..ac75f43 100644
--- a/libs/ui/include/ui/FenceTime.h
+++ b/libs/ui/include/ui/FenceTime.h
@@ -142,8 +142,6 @@
std::atomic<nsecs_t> mSignalTime{Fence::SIGNAL_TIME_INVALID};
};
-using FenceTimePtr = std::shared_ptr<FenceTime>;
-
// A queue of FenceTimes that are expected to signal in FIFO order.
// Only maintains a queue of weak pointers so it doesn't keep references
// to Fences on its own.
@@ -192,15 +190,8 @@
// before the new one is added.
class FenceToFenceTimeMap {
public:
- using FencePair = std::pair<sp<Fence>, FenceTimePtr>;
-
- FencePair makePendingFenceForTest() {
- const auto fence = sp<Fence>::make();
- return {fence, createFenceTimeForTest(fence)};
- }
-
- // Create a new FenceTime that wraps the provided Fence.
- FenceTimePtr createFenceTimeForTest(const sp<Fence>&);
+ // Create a new FenceTime with that wraps the provided Fence.
+ std::shared_ptr<FenceTime> createFenceTimeForTest(const sp<Fence>& fence);
// Signals all FenceTimes created through this class that are wrappers
// around |fence|.
@@ -214,6 +205,7 @@
std::unordered_map<Fence*, std::vector<std::weak_ptr<FenceTime>>> mMap;
};
-} // namespace android
+
+}; // namespace android
#endif // ANDROID_FENCE_TIME_H
diff --git a/services/surfaceflinger/Scheduler/Android.bp b/services/surfaceflinger/Scheduler/Android.bp
index 6d2586a..d5d8688 100644
--- a/services/surfaceflinger/Scheduler/Android.bp
+++ b/services/surfaceflinger/Scheduler/Android.bp
@@ -40,7 +40,6 @@
name: "libscheduler",
defaults: ["libscheduler_defaults"],
srcs: [
- "src/FrameTargeter.cpp",
"src/PresentLatencyTracker.cpp",
"src/Timer.cpp",
],
@@ -53,7 +52,6 @@
test_suites: ["device-tests"],
defaults: ["libscheduler_defaults"],
srcs: [
- "tests/FrameTargeterTest.cpp",
"tests/PresentLatencyTrackerTest.cpp",
"tests/TimerTest.cpp",
],
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 41639b6..918d401 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -171,21 +171,14 @@
void Scheduler::onFrameSignal(ICompositor& compositor, VsyncId vsyncId,
TimePoint expectedVsyncTime) {
- mPacesetterFrameTargeter.beginFrame({.frameBeginTime = SchedulerClock::now(),
- .vsyncId = vsyncId,
- .expectedVsyncTime = expectedVsyncTime,
- .sfWorkDuration =
- mVsyncModulator->getVsyncConfig().sfWorkDuration},
- *getVsyncSchedule());
+ const TimePoint frameTime = SchedulerClock::now();
- if (!compositor.commit(mPacesetterFrameTargeter.target())) {
+ if (!compositor.commit(frameTime, vsyncId, expectedVsyncTime)) {
return;
}
- const auto compositeResult = compositor.composite(mPacesetterFrameTargeter);
+ compositor.composite(frameTime, vsyncId);
compositor.sample();
-
- mPacesetterFrameTargeter.endFrame(compositeResult);
}
std::optional<Fps> Scheduler::getFrameRateOverride(uid_t uid) const {
@@ -195,23 +188,23 @@
.getFrameRateOverrideForUid(uid, supportsFrameRateOverrideByContent);
}
-bool Scheduler::isVsyncValid(TimePoint expectedVsyncTime, uid_t uid) const {
+bool Scheduler::isVsyncValid(TimePoint expectedVsyncTimestamp, uid_t uid) const {
const auto frameRate = getFrameRateOverride(uid);
if (!frameRate.has_value()) {
return true;
}
ATRACE_FORMAT("%s uid: %d frameRate: %s", __func__, uid, to_string(*frameRate).c_str());
- return getVsyncSchedule()->getTracker().isVSyncInPhase(expectedVsyncTime.ns(), *frameRate);
+ return getVsyncSchedule()->getTracker().isVSyncInPhase(expectedVsyncTimestamp.ns(), *frameRate);
}
-bool Scheduler::isVsyncInPhase(TimePoint expectedVsyncTime, Fps frameRate) const {
- return getVsyncSchedule()->getTracker().isVSyncInPhase(expectedVsyncTime.ns(), frameRate);
+bool Scheduler::isVsyncInPhase(TimePoint timePoint, const Fps frameRate) const {
+ return getVsyncSchedule()->getTracker().isVSyncInPhase(timePoint.ns(), frameRate);
}
impl::EventThread::ThrottleVsyncCallback Scheduler::makeThrottleVsyncCallback() const {
- return [this](nsecs_t expectedVsyncTime, uid_t uid) {
- return !isVsyncValid(TimePoint::fromNs(expectedVsyncTime), uid);
+ return [this](nsecs_t expectedVsyncTimestamp, uid_t uid) {
+ return !isVsyncValid(TimePoint::fromNs(expectedVsyncTimestamp), uid);
};
}
@@ -723,8 +716,6 @@
mFrameRateOverrideMappings.dump(dumper);
dumper.eol();
-
- mPacesetterFrameTargeter.dump(dumper);
}
void Scheduler::dumpVsync(std::string& out) const {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 17e9cea..a1354fa 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -35,7 +35,6 @@
#include <ftl/fake_guard.h>
#include <ftl/optional.h>
#include <scheduler/Features.h>
-#include <scheduler/FrameTargeter.h>
#include <scheduler/Time.h>
#include <scheduler/VsyncConfig.h>
#include <ui/DisplayId.h>
@@ -250,11 +249,9 @@
return std::const_pointer_cast<VsyncSchedule>(std::as_const(*this).getVsyncSchedule(idOpt));
}
- const FrameTarget& pacesetterFrameTarget() { return mPacesetterFrameTargeter.target(); }
-
// Returns true if a given vsync timestamp is considered valid vsync
// for a given uid
- bool isVsyncValid(TimePoint expectedVsyncTime, uid_t uid) const;
+ bool isVsyncValid(TimePoint expectedVsyncTimestamp, uid_t uid) const;
bool isVsyncInPhase(TimePoint expectedVsyncTime, Fps frameRate) const;
@@ -449,8 +446,6 @@
ftl::Optional<PhysicalDisplayId> mPacesetterDisplayId GUARDED_BY(mDisplayLock)
GUARDED_BY(kMainThreadContext);
- FrameTargeter mPacesetterFrameTargeter{mFeatures.test(Feature::kBackpressureGpuComposition)};
-
ftl::Optional<DisplayRef> pacesetterDisplayLocked() REQUIRES(mDisplayLock) {
return static_cast<const Scheduler*>(this)->pacesetterDisplayLocked().transform(
[](const Display& display) { return std::ref(const_cast<Display&>(display)); });
diff --git a/services/surfaceflinger/Scheduler/VsyncSchedule.h b/services/surfaceflinger/Scheduler/VsyncSchedule.h
index 0757b57..5eca29a 100644
--- a/services/surfaceflinger/Scheduler/VsyncSchedule.h
+++ b/services/surfaceflinger/Scheduler/VsyncSchedule.h
@@ -20,16 +20,13 @@
#include <memory>
#include <string>
+#include <ThreadContext.h>
#include <android-base/thread_annotations.h>
#include <ftl/enum.h>
#include <ftl/optional.h>
-#include <ui/DisplayId.h>
-
#include <scheduler/Features.h>
-#include <scheduler/IVsyncSource.h>
#include <scheduler/Time.h>
-
-#include "ThreadContext.h"
+#include <ui/DisplayId.h>
namespace android {
class EventThreadTest;
@@ -51,16 +48,15 @@
using VsyncTracker = VSyncTracker;
// Schedule that synchronizes to hardware VSYNC of a physical display.
-class VsyncSchedule final : public IVsyncSource {
+class VsyncSchedule {
public:
using RequestHardwareVsync = std::function<void(PhysicalDisplayId, bool enabled)>;
VsyncSchedule(PhysicalDisplayId, FeatureFlags, RequestHardwareVsync);
~VsyncSchedule();
- // IVsyncSource overrides:
- Period period() const override;
- TimePoint vsyncDeadlineAfter(TimePoint) const override;
+ Period period() const;
+ TimePoint vsyncDeadlineAfter(TimePoint) const;
// Inform the schedule that the period is changing and the schedule needs to recalibrate
// itself. The schedule will end the period transition internally. This will
diff --git a/services/surfaceflinger/Scheduler/include/scheduler/Features.h b/services/surfaceflinger/Scheduler/include/scheduler/Features.h
index 200407d..b3a6a60 100644
--- a/services/surfaceflinger/Scheduler/include/scheduler/Features.h
+++ b/services/surfaceflinger/Scheduler/include/scheduler/Features.h
@@ -23,11 +23,10 @@
namespace android::scheduler {
enum class Feature : std::uint8_t {
- kPresentFences = 1 << 0,
- kKernelIdleTimer = 1 << 1,
- kContentDetection = 1 << 2,
- kTracePredictedVsync = 1 << 3,
- kBackpressureGpuComposition = 1 << 4,
+ kPresentFences = 0b1,
+ kKernelIdleTimer = 0b10,
+ kContentDetection = 0b100,
+ kTracePredictedVsync = 0b1000,
};
using FeatureFlags = ftl::Flags<Feature>;
diff --git a/services/surfaceflinger/Scheduler/include/scheduler/FrameTargeter.h b/services/surfaceflinger/Scheduler/include/scheduler/FrameTargeter.h
deleted file mode 100644
index 6878370..0000000
--- a/services/surfaceflinger/Scheduler/include/scheduler/FrameTargeter.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <array>
-#include <atomic>
-#include <memory>
-
-#include <ui/Fence.h>
-#include <ui/FenceTime.h>
-
-#include <scheduler/Time.h>
-#include <scheduler/VsyncId.h>
-#include <scheduler/interface/CompositeResult.h>
-
-// TODO(b/185536303): Pull to FTL.
-#include "../../../TracedOrdinal.h"
-#include "../../../Utils/Dumper.h"
-
-namespace android::scheduler {
-
-struct IVsyncSource;
-
-// Read-only interface to the metrics computed by FrameTargeter for the latest frame.
-class FrameTarget {
-public:
- VsyncId vsyncId() const { return mVsyncId; }
-
- // The time when the frame actually began, as opposed to when it had been scheduled to begin.
- TimePoint frameBeginTime() const { return mFrameBeginTime; }
-
- // Relative to when the frame actually began, as opposed to when it had been scheduled to begin.
- Duration expectedFrameDuration() const { return mExpectedPresentTime - mFrameBeginTime; }
-
- TimePoint expectedPresentTime() const { return mExpectedPresentTime; }
-
- // The time of the VSYNC that preceded this frame. See `presentFenceForPastVsync` for details.
- TimePoint pastVsyncTime(Period vsyncPeriod) const;
-
- // The present fence for the frame that had targeted the most recent VSYNC before this frame.
- // If the target VSYNC for any given frame is more than `vsyncPeriod` in the future, then the
- // VSYNC of at least one previous frame has not yet passed. In other words, this is NOT the
- // fence of the previous frame if running N VSYNCs ahead, but the one that should have been
- // signaled by now (unless that frame missed).
- const FenceTimePtr& presentFenceForPastVsync(Period vsyncPeriod) const;
-
- bool wouldPresentEarly(Period vsyncPeriod) const;
-
- bool isFramePending() const { return mFramePending; }
- bool didMissFrame() const { return mFrameMissed; }
- bool didMissHwcFrame() const { return mHwcFrameMissed && !mGpuFrameMissed; }
-
-protected:
- ~FrameTarget() = default;
-
- VsyncId mVsyncId;
- TimePoint mFrameBeginTime;
- TimePoint mExpectedPresentTime;
-
- TracedOrdinal<bool> mFramePending{"PrevFramePending", false};
- TracedOrdinal<bool> mFrameMissed{"PrevFrameMissed", false};
- TracedOrdinal<bool> mHwcFrameMissed{"PrevHwcFrameMissed", false};
- TracedOrdinal<bool> mGpuFrameMissed{"PrevGpuFrameMissed", false};
-
- struct FenceWithFenceTime {
- sp<Fence> fence = Fence::NO_FENCE;
- FenceTimePtr fenceTime = FenceTime::NO_FENCE;
- };
- std::array<FenceWithFenceTime, 2> mPresentFences;
-
-private:
- template <int N>
- inline bool targetsVsyncsAhead(Period vsyncPeriod) const {
- static_assert(N > 1);
- return expectedFrameDuration() > (N - 1) * vsyncPeriod;
- }
-};
-
-// Computes a display's per-frame metrics about past/upcoming targeting of present deadlines.
-class FrameTargeter final : private FrameTarget {
-public:
- explicit FrameTargeter(bool backpressureGpuComposition)
- : mBackpressureGpuComposition(backpressureGpuComposition) {}
-
- const FrameTarget& target() const { return *this; }
-
- struct BeginFrameArgs {
- TimePoint frameBeginTime;
- VsyncId vsyncId;
- TimePoint expectedVsyncTime;
- Duration sfWorkDuration;
- };
-
- void beginFrame(const BeginFrameArgs&, const IVsyncSource&);
-
- // TODO(b/241285191): Merge with FrameTargeter::endFrame.
- FenceTimePtr setPresentFence(sp<Fence>);
-
- void endFrame(const CompositeResult&);
-
- void dump(utils::Dumper&) const;
-
-private:
- friend class FrameTargeterTest;
-
- // For tests.
- using IsFencePendingFuncPtr = bool (*)(const FenceTimePtr&, int graceTimeMs);
- void beginFrame(const BeginFrameArgs&, const IVsyncSource&, IsFencePendingFuncPtr);
- FenceTimePtr setPresentFence(sp<Fence>, FenceTimePtr);
-
- static bool isFencePending(const FenceTimePtr&, int graceTimeMs);
-
- const bool mBackpressureGpuComposition;
-
- TimePoint mScheduledPresentTime;
- CompositionCoverageFlags mCompositionCoverage;
-
- std::atomic_uint mFrameMissedCount = 0;
- std::atomic_uint mHwcFrameMissedCount = 0;
- std::atomic_uint mGpuFrameMissedCount = 0;
-};
-
-} // namespace android::scheduler
diff --git a/services/surfaceflinger/Scheduler/include/scheduler/IVsyncSource.h b/services/surfaceflinger/Scheduler/include/scheduler/IVsyncSource.h
deleted file mode 100644
index bb2de75..0000000
--- a/services/surfaceflinger/Scheduler/include/scheduler/IVsyncSource.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <scheduler/Time.h>
-
-namespace android::scheduler {
-
-struct IVsyncSource {
- virtual Period period() const = 0;
- virtual TimePoint vsyncDeadlineAfter(TimePoint) const = 0;
-
-protected:
- ~IVsyncSource() = default;
-};
-
-} // namespace android::scheduler
diff --git a/services/surfaceflinger/Scheduler/include/scheduler/interface/CompositeResult.h b/services/surfaceflinger/Scheduler/include/scheduler/interface/CompositeResult.h
deleted file mode 100644
index f795f1f..0000000
--- a/services/surfaceflinger/Scheduler/include/scheduler/interface/CompositeResult.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <scheduler/interface/CompositionCoverage.h>
-
-namespace android {
-
-struct CompositeResult {
- CompositionCoverageFlags compositionCoverage;
-};
-
-} // namespace android
diff --git a/services/surfaceflinger/Scheduler/include/scheduler/interface/ICompositor.h b/services/surfaceflinger/Scheduler/include/scheduler/interface/ICompositor.h
index 2696076..cc41925 100644
--- a/services/surfaceflinger/Scheduler/include/scheduler/interface/ICompositor.h
+++ b/services/surfaceflinger/Scheduler/include/scheduler/interface/ICompositor.h
@@ -18,15 +18,8 @@
#include <scheduler/Time.h>
#include <scheduler/VsyncId.h>
-#include <scheduler/interface/CompositeResult.h>
namespace android {
-namespace scheduler {
-
-class FrameTarget;
-class FrameTargeter;
-
-} // namespace scheduler
struct ICompositor {
// Configures physical displays, processing hotplug and/or mode setting via the Composer HAL.
@@ -34,11 +27,11 @@
// Commits transactions for layers and displays. Returns whether any state has been invalidated,
// i.e. whether a frame should be composited for each display.
- virtual bool commit(const scheduler::FrameTarget&) = 0;
+ virtual bool commit(TimePoint frameTime, VsyncId, TimePoint expectedVsyncTime) = 0;
// Composites a frame for each display. CompositionEngine performs GPU and/or HAL composition
// via RenderEngine and the Composer HAL, respectively.
- virtual CompositeResult composite(scheduler::FrameTargeter&) = 0;
+ virtual void composite(TimePoint frameTime, VsyncId) = 0;
// Samples the composited frame via RegionSamplingThread.
virtual void sample() = 0;
diff --git a/services/surfaceflinger/Scheduler/src/FrameTargeter.cpp b/services/surfaceflinger/Scheduler/src/FrameTargeter.cpp
deleted file mode 100644
index cf4c0a0..0000000
--- a/services/surfaceflinger/Scheduler/src/FrameTargeter.cpp
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <gui/TraceUtils.h>
-
-#include <scheduler/FrameTargeter.h>
-#include <scheduler/IVsyncSource.h>
-
-namespace android::scheduler {
-
-TimePoint FrameTarget::pastVsyncTime(Period vsyncPeriod) const {
- // TODO(b/267315508): Generalize to N VSYNCs.
- const int shift = static_cast<int>(targetsVsyncsAhead<2>(vsyncPeriod));
- return mExpectedPresentTime - Period::fromNs(vsyncPeriod.ns() << shift);
-}
-
-const FenceTimePtr& FrameTarget::presentFenceForPastVsync(Period vsyncPeriod) const {
- // TODO(b/267315508): Generalize to N VSYNCs.
- const size_t i = static_cast<size_t>(targetsVsyncsAhead<2>(vsyncPeriod));
- return mPresentFences[i].fenceTime;
-}
-
-bool FrameTarget::wouldPresentEarly(Period vsyncPeriod) const {
- // TODO(b/267315508): Generalize to N VSYNCs.
- if (targetsVsyncsAhead<3>(vsyncPeriod)) {
- return true;
- }
-
- const auto fence = presentFenceForPastVsync(vsyncPeriod);
- return fence->isValid() && fence->getSignalTime() != Fence::SIGNAL_TIME_PENDING;
-}
-
-void FrameTargeter::beginFrame(const BeginFrameArgs& args, const IVsyncSource& vsyncSource) {
- return beginFrame(args, vsyncSource, &FrameTargeter::isFencePending);
-}
-
-void FrameTargeter::beginFrame(const BeginFrameArgs& args, const IVsyncSource& vsyncSource,
- IsFencePendingFuncPtr isFencePendingFuncPtr) {
- mVsyncId = args.vsyncId;
- mFrameBeginTime = args.frameBeginTime;
-
- // The `expectedVsyncTime`, which was predicted when this frame was scheduled, is normally in
- // the future relative to `frameBeginTime`, but may not be for delayed frames. Adjust
- // `mExpectedPresentTime` accordingly, but not `mScheduledPresentTime`.
- const TimePoint lastScheduledPresentTime = mScheduledPresentTime;
- mScheduledPresentTime = args.expectedVsyncTime;
-
- const Period vsyncPeriod = vsyncSource.period();
-
- // Calculate the expected present time once and use the cached value throughout this frame to
- // make sure all layers are seeing this same value.
- if (args.expectedVsyncTime >= args.frameBeginTime) {
- mExpectedPresentTime = args.expectedVsyncTime;
- } else {
- mExpectedPresentTime = vsyncSource.vsyncDeadlineAfter(args.frameBeginTime);
- if (args.sfWorkDuration > vsyncPeriod) {
- // Inflate the expected present time if we're targeting the next VSYNC.
- mExpectedPresentTime += vsyncPeriod;
- }
- }
-
- ATRACE_FORMAT("%s %" PRId64 " vsyncIn %.2fms%s", __func__, ftl::to_underlying(args.vsyncId),
- ticks<std::milli, float>(mExpectedPresentTime - TimePoint::now()),
- mExpectedPresentTime == args.expectedVsyncTime ? "" : " (adjusted)");
-
- const FenceTimePtr& pastPresentFence = presentFenceForPastVsync(vsyncPeriod);
-
- // In cases where the present fence is about to fire, give it a small grace period instead of
- // giving up on the frame.
- //
- // TODO(b/280667110): The grace period should depend on `sfWorkDuration` and `vsyncPeriod` being
- // approximately equal, not whether backpressure propagation is enabled.
- const int graceTimeForPresentFenceMs = static_cast<int>(
- mBackpressureGpuComposition || !mCompositionCoverage.test(CompositionCoverage::Gpu));
-
- // Pending frames may trigger backpressure propagation.
- const auto& isFencePending = *isFencePendingFuncPtr;
- mFramePending = pastPresentFence != FenceTime::NO_FENCE &&
- isFencePending(pastPresentFence, graceTimeForPresentFenceMs);
-
- // 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.
- mFrameMissed = mFramePending || [&] {
- const nsecs_t pastPresentTime = pastPresentFence->getSignalTime();
- if (pastPresentTime < 0) return false;
- const nsecs_t frameMissedSlop = vsyncPeriod.ns() / 2;
- return lastScheduledPresentTime.ns() < pastPresentTime - frameMissedSlop;
- }();
-
- mHwcFrameMissed = mFrameMissed && mCompositionCoverage.test(CompositionCoverage::Hwc);
- mGpuFrameMissed = mFrameMissed && mCompositionCoverage.test(CompositionCoverage::Gpu);
-
- if (mFrameMissed) mFrameMissedCount++;
- if (mHwcFrameMissed) mHwcFrameMissedCount++;
- if (mGpuFrameMissed) mGpuFrameMissedCount++;
-}
-
-void FrameTargeter::endFrame(const CompositeResult& result) {
- mCompositionCoverage = result.compositionCoverage;
-}
-
-FenceTimePtr FrameTargeter::setPresentFence(sp<Fence> presentFence) {
- auto presentFenceTime = std::make_shared<FenceTime>(presentFence);
- return setPresentFence(std::move(presentFence), std::move(presentFenceTime));
-}
-
-FenceTimePtr FrameTargeter::setPresentFence(sp<Fence> presentFence, FenceTimePtr presentFenceTime) {
- mPresentFences[1] = mPresentFences[0];
- mPresentFences[0] = {std::move(presentFence), presentFenceTime};
- return presentFenceTime;
-}
-
-void FrameTargeter::dump(utils::Dumper& dumper) const {
- using namespace std::string_view_literals;
-
- utils::Dumper::Section section(dumper, "Frame Targeting"sv);
-
- dumper.dump("frameMissedCount"sv, mFrameMissedCount);
- dumper.dump("hwcFrameMissedCount"sv, mHwcFrameMissedCount);
- dumper.dump("gpuFrameMissedCount"sv, mGpuFrameMissedCount);
-}
-
-bool FrameTargeter::isFencePending(const FenceTimePtr& fence, int graceTimeMs) {
- ATRACE_CALL();
- const status_t status = fence->wait(graceTimeMs);
-
- // This is the same as Fence::Status::Unsignaled, but it saves a call to getStatus,
- // which calls wait(0) again internally.
- return status == -ETIME;
-}
-
-} // namespace android::scheduler
diff --git a/services/surfaceflinger/Scheduler/tests/FrameTargeterTest.cpp b/services/surfaceflinger/Scheduler/tests/FrameTargeterTest.cpp
deleted file mode 100644
index 908f214..0000000
--- a/services/surfaceflinger/Scheduler/tests/FrameTargeterTest.cpp
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <ftl/optional.h>
-#include <gtest/gtest.h>
-
-#include <scheduler/Fps.h>
-#include <scheduler/FrameTargeter.h>
-#include <scheduler/IVsyncSource.h>
-
-using namespace std::chrono_literals;
-
-namespace android::scheduler {
-namespace {
-
-struct VsyncSource final : IVsyncSource {
- VsyncSource(Period period, TimePoint deadline) : vsyncPeriod(period), vsyncDeadline(deadline) {}
-
- const Period vsyncPeriod;
- const TimePoint vsyncDeadline;
-
- Period period() const override { return vsyncPeriod; }
- TimePoint vsyncDeadlineAfter(TimePoint) const override { return vsyncDeadline; }
-};
-
-} // namespace
-
-class FrameTargeterTest : public testing::Test {
-public:
- const auto& target() const { return mTargeter.target(); }
-
- struct Frame {
- Frame(FrameTargeterTest* testPtr, VsyncId vsyncId, TimePoint& frameBeginTime,
- Duration frameDuration, Fps refreshRate,
- FrameTargeter::IsFencePendingFuncPtr isFencePendingFuncPtr = Frame::fenceSignaled,
- const ftl::Optional<VsyncSource>& vsyncSourceOpt = std::nullopt)
- : testPtr(testPtr), frameBeginTime(frameBeginTime), period(refreshRate.getPeriod()) {
- const FrameTargeter::BeginFrameArgs args{.frameBeginTime = frameBeginTime,
- .vsyncId = vsyncId,
- .expectedVsyncTime =
- frameBeginTime + frameDuration,
- .sfWorkDuration = 10ms};
-
- testPtr->mTargeter.beginFrame(args,
- vsyncSourceOpt
- .or_else([&] {
- return std::make_optional(
- VsyncSource(period,
- args.expectedVsyncTime));
- })
- .value(),
- isFencePendingFuncPtr);
- }
-
- FenceTimePtr end(CompositionCoverage coverage = CompositionCoverage::Hwc) {
- if (ended) return nullptr;
- ended = true;
-
- auto [fence, fenceTime] = testPtr->mFenceMap.makePendingFenceForTest();
- testPtr->mTargeter.setPresentFence(std::move(fence), fenceTime);
-
- testPtr->mTargeter.endFrame({.compositionCoverage = coverage});
- return fenceTime;
- }
-
- ~Frame() {
- end();
- frameBeginTime += period;
- }
-
- static bool fencePending(const FenceTimePtr&, int) { return true; }
- static bool fenceSignaled(const FenceTimePtr&, int) { return false; }
-
- FrameTargeterTest* const testPtr;
-
- TimePoint& frameBeginTime;
- const Period period;
-
- bool ended = false;
- };
-
-private:
- FenceToFenceTimeMap mFenceMap;
-
- static constexpr bool kBackpressureGpuComposition = true;
- FrameTargeter mTargeter{kBackpressureGpuComposition};
-};
-
-TEST_F(FrameTargeterTest, targetsFrames) {
- VsyncId vsyncId{42};
- {
- TimePoint frameBeginTime(989ms);
- const Frame frame(this, vsyncId++, frameBeginTime, 10ms, 60_Hz);
-
- EXPECT_EQ(target().vsyncId(), VsyncId{42});
- EXPECT_EQ(target().frameBeginTime(), TimePoint(989ms));
- EXPECT_EQ(target().expectedPresentTime(), TimePoint(999ms));
- EXPECT_EQ(target().expectedFrameDuration(), 10ms);
- }
- {
- TimePoint frameBeginTime(1100ms);
- const Frame frame(this, vsyncId++, frameBeginTime, 11ms, 60_Hz);
-
- EXPECT_EQ(target().vsyncId(), VsyncId{43});
- EXPECT_EQ(target().frameBeginTime(), TimePoint(1100ms));
- EXPECT_EQ(target().expectedPresentTime(), TimePoint(1111ms));
- EXPECT_EQ(target().expectedFrameDuration(), 11ms);
- }
-}
-
-TEST_F(FrameTargeterTest, inflatesExpectedPresentTime) {
- // Negative such that `expectedVsyncTime` is in the past.
- constexpr Duration kFrameDuration = -3ms;
- TimePoint frameBeginTime(777ms);
-
- constexpr Fps kRefreshRate = 120_Hz;
- const VsyncSource vsyncSource(kRefreshRate.getPeriod(), frameBeginTime + 5ms);
- const Frame frame(this, VsyncId{123}, frameBeginTime, kFrameDuration, kRefreshRate,
- Frame::fenceSignaled, vsyncSource);
-
- EXPECT_EQ(target().expectedPresentTime(), vsyncSource.vsyncDeadline + vsyncSource.vsyncPeriod);
-}
-
-TEST_F(FrameTargeterTest, recallsPastVsync) {
- VsyncId vsyncId{111};
- TimePoint frameBeginTime(1000ms);
- constexpr Fps kRefreshRate = 60_Hz;
- constexpr Period kPeriod = kRefreshRate.getPeriod();
- constexpr Duration kFrameDuration = 13ms;
-
- for (int n = 5; n-- > 0;) {
- Frame frame(this, vsyncId++, frameBeginTime, kFrameDuration, kRefreshRate);
- const auto fence = frame.end();
-
- EXPECT_EQ(target().pastVsyncTime(kPeriod), frameBeginTime + kFrameDuration - kPeriod);
- EXPECT_EQ(target().presentFenceForPastVsync(kPeriod), fence);
- }
-}
-
-TEST_F(FrameTargeterTest, recallsPastVsyncTwoVsyncsAhead) {
- VsyncId vsyncId{222};
- TimePoint frameBeginTime(2000ms);
- constexpr Fps kRefreshRate = 120_Hz;
- constexpr Period kPeriod = kRefreshRate.getPeriod();
- constexpr Duration kFrameDuration = 10ms;
-
- FenceTimePtr previousFence = FenceTime::NO_FENCE;
-
- for (int n = 5; n-- > 0;) {
- Frame frame(this, vsyncId++, frameBeginTime, kFrameDuration, kRefreshRate);
- const auto fence = frame.end();
-
- EXPECT_EQ(target().pastVsyncTime(kPeriod), frameBeginTime + kFrameDuration - 2 * kPeriod);
- EXPECT_EQ(target().presentFenceForPastVsync(kPeriod), previousFence);
-
- previousFence = fence;
- }
-}
-
-TEST_F(FrameTargeterTest, doesNotDetectEarlyPresentIfNoFence) {
- constexpr Period kPeriod = (60_Hz).getPeriod();
- EXPECT_EQ(target().presentFenceForPastVsync(kPeriod), FenceTime::NO_FENCE);
- EXPECT_FALSE(target().wouldPresentEarly(kPeriod));
-}
-
-TEST_F(FrameTargeterTest, detectsEarlyPresent) {
- VsyncId vsyncId{333};
- TimePoint frameBeginTime(3000ms);
- constexpr Fps kRefreshRate = 60_Hz;
- constexpr Period kPeriod = kRefreshRate.getPeriod();
-
- // The target is not early while past present fences are pending.
- for (int n = 3; n-- > 0;) {
- const Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate);
- EXPECT_FALSE(target().wouldPresentEarly(kPeriod));
- }
-
- // The target is early if the past present fence was signaled.
- Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate);
- const auto fence = frame.end();
- fence->signalForTest(frameBeginTime.ns());
-
- EXPECT_TRUE(target().wouldPresentEarly(kPeriod));
-}
-
-TEST_F(FrameTargeterTest, detectsEarlyPresentTwoVsyncsAhead) {
- VsyncId vsyncId{444};
- TimePoint frameBeginTime(4000ms);
- constexpr Fps kRefreshRate = 120_Hz;
- constexpr Period kPeriod = kRefreshRate.getPeriod();
-
- // The target is not early while past present fences are pending.
- for (int n = 3; n-- > 0;) {
- const Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate);
- EXPECT_FALSE(target().wouldPresentEarly(kPeriod));
- }
-
- Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate);
- const auto fence = frame.end();
- fence->signalForTest(frameBeginTime.ns());
-
- // The target is two VSYNCs ahead, so the past present fence is still pending.
- EXPECT_FALSE(target().wouldPresentEarly(kPeriod));
-
- { const Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate); }
-
- // The target is early if the past present fence was signaled.
- EXPECT_TRUE(target().wouldPresentEarly(kPeriod));
-}
-
-TEST_F(FrameTargeterTest, detectsEarlyPresentThreeVsyncsAhead) {
- TimePoint frameBeginTime(5000ms);
- constexpr Fps kRefreshRate = 144_Hz;
- constexpr Period kPeriod = kRefreshRate.getPeriod();
-
- const Frame frame(this, VsyncId{555}, frameBeginTime, 16ms, kRefreshRate);
-
- // The target is more than two VSYNCs ahead, but present fences are not tracked that far back.
- EXPECT_TRUE(target().wouldPresentEarly(kPeriod));
-}
-
-TEST_F(FrameTargeterTest, detectsMissedFrames) {
- VsyncId vsyncId{555};
- TimePoint frameBeginTime(5000ms);
- constexpr Fps kRefreshRate = 60_Hz;
- constexpr Period kPeriod = kRefreshRate.getPeriod();
-
- EXPECT_FALSE(target().isFramePending());
- EXPECT_FALSE(target().didMissFrame());
- EXPECT_FALSE(target().didMissHwcFrame());
-
- {
- const Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate);
- EXPECT_FALSE(target().isFramePending());
-
- // The frame did not miss if the past present fence is invalid.
- EXPECT_FALSE(target().didMissFrame());
- EXPECT_FALSE(target().didMissHwcFrame());
- }
- {
- Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate, Frame::fencePending);
- EXPECT_TRUE(target().isFramePending());
-
- // The frame missed if the past present fence is pending.
- EXPECT_TRUE(target().didMissFrame());
- EXPECT_TRUE(target().didMissHwcFrame());
-
- frame.end(CompositionCoverage::Gpu);
- }
- {
- const Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate, Frame::fencePending);
- EXPECT_TRUE(target().isFramePending());
-
- // The GPU frame missed if the past present fence is pending.
- EXPECT_TRUE(target().didMissFrame());
- EXPECT_FALSE(target().didMissHwcFrame());
- }
- {
- Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate);
- EXPECT_FALSE(target().isFramePending());
-
- const auto fence = frame.end();
- const auto expectedPresentTime = target().expectedPresentTime();
- fence->signalForTest(expectedPresentTime.ns() + kPeriod.ns() / 2 + 1);
- }
- {
- Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate);
- EXPECT_FALSE(target().isFramePending());
-
- const auto fence = frame.end();
- const auto expectedPresentTime = target().expectedPresentTime();
- fence->signalForTest(expectedPresentTime.ns() + kPeriod.ns() / 2);
-
- // The frame missed if the past present fence was signaled but not within slop.
- EXPECT_TRUE(target().didMissFrame());
- EXPECT_TRUE(target().didMissHwcFrame());
- }
- {
- Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate);
- EXPECT_FALSE(target().isFramePending());
-
- // The frame did not miss if the past present fence was signaled within slop.
- EXPECT_FALSE(target().didMissFrame());
- EXPECT_FALSE(target().didMissHwcFrame());
- }
-}
-
-} // namespace android::scheduler
diff --git a/services/surfaceflinger/Scheduler/tests/PresentLatencyTrackerTest.cpp b/services/surfaceflinger/Scheduler/tests/PresentLatencyTrackerTest.cpp
index df2ea83..8952ca9 100644
--- a/services/surfaceflinger/Scheduler/tests/PresentLatencyTrackerTest.cpp
+++ b/services/surfaceflinger/Scheduler/tests/PresentLatencyTrackerTest.cpp
@@ -23,6 +23,16 @@
#include <ui/FenceTime.h>
namespace android::scheduler {
+namespace {
+
+using FencePair = std::pair<sp<Fence>, std::shared_ptr<FenceTime>>;
+
+FencePair makePendingFence(FenceToFenceTimeMap& fenceMap) {
+ const auto fence = sp<Fence>::make();
+ return {fence, fenceMap.createFenceTimeForTest(fence)};
+}
+
+} // namespace
TEST(PresentLatencyTrackerTest, skipsInvalidFences) {
PresentLatencyTracker tracker;
@@ -33,7 +43,7 @@
EXPECT_EQ(tracker.trackPendingFrame(kCompositeTime, FenceTime::NO_FENCE), Duration::zero());
FenceToFenceTimeMap fenceMap;
- const auto [fence, fenceTime] = fenceMap.makePendingFenceForTest();
+ const auto [fence, fenceTime] = makePendingFence(fenceMap);
EXPECT_EQ(tracker.trackPendingFrame(kCompositeTime, fenceTime), Duration::zero());
fenceTime->signalForTest(9999);
@@ -46,9 +56,8 @@
PresentLatencyTracker tracker;
FenceToFenceTimeMap fenceMap;
- std::array<FenceToFenceTimeMap::FencePair, PresentLatencyTracker::kMaxPendingFrames> fences;
- std::generate(fences.begin(), fences.end(),
- [&fenceMap] { return fenceMap.makePendingFenceForTest(); });
+ std::array<FencePair, PresentLatencyTracker::kMaxPendingFrames> fences;
+ std::generate(fences.begin(), fences.end(), [&fenceMap] { return makePendingFence(fenceMap); });
// The present latency is 0 if all fences are pending.
const TimePoint kCompositeTime = TimePoint::fromNs(1234);
@@ -62,7 +71,7 @@
fences[i].second->signalForTest(kCompositeTime.ns() + static_cast<nsecs_t>(i));
}
- const auto fence = fenceMap.makePendingFenceForTest();
+ const auto fence = makePendingFence(fenceMap);
// ...then the present latency is measured using the latest frame.
constexpr Duration kPresentLatency = Duration::fromNs(static_cast<nsecs_t>(kPresentCount) - 1);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 06d6ef0..736b752 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -77,7 +77,6 @@
#include <processgroup/processgroup.h>
#include <renderengine/RenderEngine.h>
#include <renderengine/impl/ExternalTexture.h>
-#include <scheduler/FrameTargeter.h>
#include <sys/types.h>
#include <ui/ColorSpace.h>
#include <ui/DataspaceUtils.h>
@@ -2140,6 +2139,44 @@
}
}
+bool SurfaceFlinger::wouldPresentEarly(TimePoint frameTime, Period vsyncPeriod) const {
+ const bool isThreeVsyncsAhead = mExpectedPresentTime - frameTime > 2 * vsyncPeriod;
+ return isThreeVsyncsAhead ||
+ getPreviousPresentFence(frameTime, vsyncPeriod)->getSignalTime() !=
+ Fence::SIGNAL_TIME_PENDING;
+}
+
+auto SurfaceFlinger::getPreviousPresentFence(TimePoint frameTime, Period vsyncPeriod) const
+ -> const FenceTimePtr& {
+ const bool isTwoVsyncsAhead = mExpectedPresentTime - frameTime > vsyncPeriod;
+ const size_t i = static_cast<size_t>(isTwoVsyncsAhead);
+ return mPreviousPresentFences[i].fenceTime;
+}
+
+bool SurfaceFlinger::isFencePending(const FenceTimePtr& fence, int graceTimeMs) {
+ ATRACE_CALL();
+ if (fence == FenceTime::NO_FENCE) {
+ return false;
+ }
+
+ const status_t status = fence->wait(graceTimeMs);
+ // This is the same as Fence::Status::Unsignaled, but it saves a getStatus() call,
+ // which calls wait(0) again internally
+ return status == -ETIME;
+}
+
+TimePoint SurfaceFlinger::calculateExpectedPresentTime(TimePoint frameTime) const {
+ const auto& schedule = mScheduler->getVsyncSchedule();
+
+ const TimePoint vsyncDeadline = schedule->vsyncDeadlineAfter(frameTime);
+ if (mScheduler->vsyncModulator().getVsyncConfig().sfOffset > 0) {
+ return vsyncDeadline;
+ }
+
+ // Inflate the expected present time if we're targeting the next vsync.
+ return vsyncDeadline + schedule->period();
+}
+
void SurfaceFlinger::configure() FTL_FAKE_GUARD(kMainThreadContext) {
Mutex::Autolock lock(mStateLock);
if (configureLocked()) {
@@ -2313,15 +2350,75 @@
return mustComposite;
}
-bool SurfaceFlinger::commit(const scheduler::FrameTarget& pacesetterFrameTarget)
+bool SurfaceFlinger::commit(TimePoint frameTime, VsyncId vsyncId, TimePoint expectedVsyncTime)
FTL_FAKE_GUARD(kMainThreadContext) {
- const VsyncId vsyncId = pacesetterFrameTarget.vsyncId();
- ATRACE_NAME(ftl::Concat(__func__, ' ', ftl::to_underlying(vsyncId)).c_str());
+ // The expectedVsyncTime, which was predicted when this frame was scheduled, is normally in the
+ // future relative to frameTime, but may not be for delayed frames. Adjust mExpectedPresentTime
+ // accordingly, but not mScheduledPresentTime.
+ const TimePoint lastScheduledPresentTime = mScheduledPresentTime;
+ mScheduledPresentTime = expectedVsyncTime;
- if (pacesetterFrameTarget.didMissFrame()) {
+ // Calculate the expected present time once and use the cached value throughout this frame to
+ // make sure all layers are seeing this same value.
+ mExpectedPresentTime = expectedVsyncTime >= frameTime ? expectedVsyncTime
+ : calculateExpectedPresentTime(frameTime);
+
+ ATRACE_FORMAT("%s %" PRId64 " vsyncIn %.2fms%s", __func__, ftl::to_underlying(vsyncId),
+ ticks<std::milli, float>(mExpectedPresentTime - TimePoint::now()),
+ mExpectedPresentTime == expectedVsyncTime ? "" : " (adjusted)");
+
+ const Period vsyncPeriod = mScheduler->getVsyncSchedule()->period();
+ const FenceTimePtr& previousPresentFence = getPreviousPresentFence(frameTime, vsyncPeriod);
+
+ // When backpressure propagation is enabled, we want to give a small grace period of 1ms
+ // for the present fence to fire instead of just giving up on this frame to handle cases
+ // where present fence is just about to get signaled.
+ const int graceTimeForPresentFenceMs = static_cast<int>(
+ mBackpressureGpuComposition || !mCompositionCoverage.test(CompositionCoverage::Gpu));
+
+ // Pending frames may trigger backpressure propagation.
+ const TracedOrdinal<bool> framePending = {"PrevFramePending",
+ isFencePending(previousPresentFence,
+ 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.
+ const nsecs_t frameMissedSlop = vsyncPeriod.ns() / 2;
+ const nsecs_t previousPresentTime = previousPresentFence->getSignalTime();
+ const TracedOrdinal<bool> frameMissed = {"PrevFrameMissed",
+ framePending ||
+ (previousPresentTime >= 0 &&
+ (lastScheduledPresentTime.ns() <
+ previousPresentTime - frameMissedSlop))};
+ const TracedOrdinal<bool> hwcFrameMissed = {"PrevHwcFrameMissed",
+ frameMissed &&
+ mCompositionCoverage.test(
+ CompositionCoverage::Hwc)};
+
+ const TracedOrdinal<bool> gpuFrameMissed = {"PrevGpuFrameMissed",
+ frameMissed &&
+ mCompositionCoverage.test(
+ CompositionCoverage::Gpu)};
+
+ if (frameMissed) {
+ mFrameMissedCount++;
mTimeStats->incrementMissedFrames();
}
+ if (hwcFrameMissed) {
+ mHwcFrameMissedCount++;
+ }
+
+ if (gpuFrameMissed) {
+ mGpuFrameMissedCount++;
+ }
+
if (mTracingEnabledChanged) {
mLayerTracingEnabled = mLayerTracing.isEnabled();
mTracingEnabledChanged = false;
@@ -2330,7 +2427,7 @@
// If we are in the middle of a mode change and the fence hasn't
// fired yet just wait for the next commit.
if (mSetActiveModePending) {
- if (pacesetterFrameTarget.isFramePending()) {
+ if (framePending) {
mScheduler->scheduleFrame();
return false;
}
@@ -2344,29 +2441,26 @@
}
}
- if (pacesetterFrameTarget.isFramePending()) {
- if (mBackpressureGpuComposition || pacesetterFrameTarget.didMissHwcFrame()) {
+ if (framePending) {
+ if (mBackpressureGpuComposition || (hwcFrameMissed && !gpuFrameMissed)) {
scheduleCommit(FrameHint::kNone);
return false;
}
}
- const Period vsyncPeriod = mScheduler->getVsyncSchedule()->period();
-
// Save this once per commit + composite to ensure consistency
// TODO (b/240619471): consider removing active display check once AOD is fixed
const auto activeDisplay = FTL_FAKE_GUARD(mStateLock, getDisplayDeviceLocked(mActiveDisplayId));
mPowerHintSessionEnabled = mPowerAdvisor->usePowerHintSession() && activeDisplay &&
activeDisplay->getPowerMode() == hal::PowerMode::ON;
if (mPowerHintSessionEnabled) {
- mPowerAdvisor->setCommitStart(pacesetterFrameTarget.frameBeginTime());
- mPowerAdvisor->setExpectedPresentTime(pacesetterFrameTarget.expectedPresentTime());
+ mPowerAdvisor->setCommitStart(frameTime);
+ mPowerAdvisor->setExpectedPresentTime(mExpectedPresentTime);
// Frame delay is how long we should have minus how long we actually have.
const Duration idealSfWorkDuration =
mScheduler->vsyncModulator().getVsyncConfig().sfWorkDuration;
- const Duration frameDelay =
- idealSfWorkDuration - pacesetterFrameTarget.expectedFrameDuration();
+ const Duration frameDelay = idealSfWorkDuration - (mExpectedPresentTime - frameTime);
mPowerAdvisor->setFrameDelay(frameDelay);
mPowerAdvisor->setTotalFrameTargetWorkDuration(idealSfWorkDuration);
@@ -2383,8 +2477,7 @@
// Composite if transactions were committed, or if requested by HWC.
bool mustComposite = mMustComposite.exchange(false);
{
- mFrameTimeline->setSfWakeUp(ftl::to_underlying(vsyncId),
- pacesetterFrameTarget.frameBeginTime().ns(),
+ mFrameTimeline->setSfWakeUp(ftl::to_underlying(vsyncId), frameTime.ns(),
Fps::fromPeriodNsecs(vsyncPeriod.ns()));
const bool flushTransactions = clearTransactionFlags(eTransactionFlushNeeded);
@@ -2392,11 +2485,10 @@
if (flushTransactions) {
updates = flushLifecycleUpdates();
if (mTransactionTracing) {
- mTransactionTracing
- ->addCommittedTransactions(ftl::to_underlying(vsyncId),
- pacesetterFrameTarget.frameBeginTime().ns(),
- updates, mFrontEndDisplayInfos,
- mFrontEndDisplayInfosChanged);
+ mTransactionTracing->addCommittedTransactions(ftl::to_underlying(vsyncId),
+ frameTime.ns(), updates,
+ mFrontEndDisplayInfos,
+ mFrontEndDisplayInfosChanged);
}
}
bool transactionsAreEmpty;
@@ -2439,7 +2531,7 @@
if (mLayerTracingEnabled && !mLayerTracing.flagIsSet(LayerTracing::TRACE_COMPOSITION)) {
// This will block and tracing should only be enabled for debugging.
- addToLayerTracing(mVisibleRegionsDirty, pacesetterFrameTarget.frameBeginTime(), vsyncId);
+ addToLayerTracing(mVisibleRegionsDirty, frameTime, vsyncId);
}
mLastCommittedVsyncId = vsyncId;
@@ -2448,11 +2540,8 @@
return mustComposite && CC_LIKELY(mBootStage != BootStage::BOOTLOADER);
}
-CompositeResult SurfaceFlinger::composite(scheduler::FrameTargeter& pacesetterFrameTargeter)
+void SurfaceFlinger::composite(TimePoint frameTime, VsyncId vsyncId)
FTL_FAKE_GUARD(kMainThreadContext) {
- const scheduler::FrameTarget& pacesetterFrameTarget = pacesetterFrameTargeter.target();
-
- const VsyncId vsyncId = pacesetterFrameTarget.vsyncId();
ATRACE_NAME(ftl::Concat(__func__, ' ', ftl::to_underlying(vsyncId)).c_str());
compositionengine::CompositionRefreshArgs refreshArgs;
@@ -2460,18 +2549,17 @@
refreshArgs.outputs.reserve(displays.size());
std::vector<DisplayId> displayIds;
for (const auto& [_, display] : displays) {
- displayIds.push_back(display->getId());
- display->tracePowerMode();
-
+ bool dropFrame = false;
if (display->isVirtual()) {
- const Fps refreshRate = display->getAdjustedRefreshRate();
- if (refreshRate.isValid() &&
- !mScheduler->isVsyncInPhase(pacesetterFrameTarget.frameBeginTime(), refreshRate)) {
- continue;
- }
+ Fps refreshRate = display->getAdjustedRefreshRate();
+ using fps_approx_ops::operator>;
+ dropFrame = (refreshRate > 0_Hz) && !mScheduler->isVsyncInPhase(frameTime, refreshRate);
}
-
- refreshArgs.outputs.push_back(display->getCompositionDisplay());
+ if (!dropFrame) {
+ refreshArgs.outputs.push_back(display->getCompositionDisplay());
+ }
+ display->tracePowerMode();
+ displayIds.push_back(display->getId());
}
mPowerAdvisor->setDisplays(displayIds);
@@ -2531,15 +2619,15 @@
if (!getHwComposer().getComposer()->isSupported(
Hwc2::Composer::OptionalFeature::ExpectedPresentTime) &&
- pacesetterFrameTarget.wouldPresentEarly(vsyncPeriod)) {
+ wouldPresentEarly(frameTime, vsyncPeriod)) {
+ const auto prevVsyncTime = mExpectedPresentTime - vsyncPeriod;
const auto hwcMinWorkDuration = mVsyncConfiguration->getCurrentConfigs().hwcMinWorkDuration;
- refreshArgs.earliestPresentTime =
- pacesetterFrameTarget.pastVsyncTime(vsyncPeriod) - hwcMinWorkDuration;
+ refreshArgs.earliestPresentTime = prevVsyncTime - hwcMinWorkDuration;
}
refreshArgs.scheduledFrameTime = mScheduler->getScheduledFrameTime();
- refreshArgs.expectedPresentTime = pacesetterFrameTarget.expectedPresentTime().ns();
+ refreshArgs.expectedPresentTime = mExpectedPresentTime.ns();
refreshArgs.hasTrustedPresentationListener = mNumTrustedPresentationListeners > 0;
// Store the present time just before calling to the composition engine so we could notify
@@ -2565,12 +2653,13 @@
}
}
- mTimeStats->recordFrameDuration(pacesetterFrameTarget.frameBeginTime().ns(), systemTime());
+ mTimeStats->recordFrameDuration(frameTime.ns(), systemTime());
// Send a power hint hint after presentation is finished
if (mPowerHintSessionEnabled) {
const nsecs_t pastPresentTime =
- pacesetterFrameTarget.presentFenceForPastVsync(vsyncPeriod)->getSignalTime();
+ getPreviousPresentFence(frameTime, vsyncPeriod)->getSignalTime();
+
mPowerAdvisor->setSfPresentTiming(TimePoint::fromNs(pastPresentTime), TimePoint::now());
mPowerAdvisor->reportActualWorkDuration();
}
@@ -2579,7 +2668,7 @@
scheduleComposite(FrameHint::kNone);
}
- postComposition(pacesetterFrameTargeter, presentTime);
+ postComposition(presentTime);
const bool hadGpuComposited = mCompositionCoverage.test(CompositionCoverage::Gpu);
mCompositionCoverage.clear();
@@ -2622,7 +2711,7 @@
mLayersWithQueuedFrames.clear();
if (mLayerTracingEnabled && mLayerTracing.flagIsSet(LayerTracing::TRACE_COMPOSITION)) {
// This will block and should only be used for debugging.
- addToLayerTracing(mVisibleRegionsDirty, pacesetterFrameTarget.frameBeginTime(), vsyncId);
+ addToLayerTracing(mVisibleRegionsDirty, frameTime, vsyncId);
}
if (mVisibleRegionsDirty) mHdrLayerInfoChanged = true;
@@ -2635,8 +2724,6 @@
if (mPowerHintSessionEnabled) {
mPowerAdvisor->setCompositeEnd(TimePoint::now());
}
-
- return {mCompositionCoverage};
}
void SurfaceFlinger::updateLayerGeometry() {
@@ -2720,8 +2807,7 @@
return ui::ROTATION_0;
}
-void SurfaceFlinger::postComposition(scheduler::FrameTargeter& pacesetterFrameTargeter,
- nsecs_t presentStartTime) {
+void SurfaceFlinger::postComposition(nsecs_t callTime) {
ATRACE_CALL();
ALOGV(__func__);
@@ -2738,11 +2824,15 @@
glCompositionDoneFenceTime = FenceTime::NO_FENCE;
}
+ mPreviousPresentFences[1] = mPreviousPresentFences[0];
+
auto presentFence = defaultDisplay
? getHwComposer().getPresentFence(defaultDisplay->getPhysicalId())
: Fence::NO_FENCE;
- auto presentFenceTime = pacesetterFrameTargeter.setPresentFence(presentFence);
+ auto presentFenceTime = std::make_shared<FenceTime>(presentFence);
+ mPreviousPresentFences[0] = {presentFence, presentFenceTime};
+
const TimePoint presentTime = TimePoint::now();
// Set presentation information before calling Layer::releasePendingBuffer, such that jank
@@ -2925,7 +3015,7 @@
if (!layer->hasTrustedPresentationListener()) {
return;
}
- const frontend::LayerSnapshot* snapshot = mLayerLifecycleManagerEnabled
+ const frontend::LayerSnapshot* snapshot = (mLayerLifecycleManagerEnabled)
? mLayerSnapshotBuilder.getSnapshot(layer->sequence)
: layer->getLayerSnapshot();
std::optional<const DisplayDevice*> displayOpt = std::nullopt;
@@ -2934,8 +3024,7 @@
}
const DisplayDevice* display = displayOpt.value_or(nullptr);
layer->updateTrustedPresentationState(display, snapshot,
- nanoseconds_to_milliseconds(presentStartTime),
- false);
+ nanoseconds_to_milliseconds(callTime), false);
});
}
@@ -3847,9 +3936,6 @@
if (display->refreshRateSelector().kernelIdleTimerController()) {
features |= Feature::kKernelIdleTimer;
}
- if (mBackpressureGpuComposition) {
- features |= Feature::kBackpressureGpuComposition;
- }
auto modulatorPtr = sp<VsyncModulator>::make(mVsyncConfiguration->getCurrentConfigs());
@@ -4167,38 +4253,33 @@
TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyTimelineCheck(
const TransactionHandler::TransactionFlushState& flushState) {
- const auto& transaction = *flushState.transaction;
-
- const TimePoint desiredPresentTime = TimePoint::fromNs(transaction.desiredPresentTime);
- const TimePoint expectedPresentTime = mScheduler->pacesetterFrameTarget().expectedPresentTime();
-
using TransactionReadiness = TransactionHandler::TransactionReadiness;
-
+ const auto& transaction = *flushState.transaction;
+ TimePoint desiredPresentTime = TimePoint::fromNs(transaction.desiredPresentTime);
// Do not present if the desiredPresentTime has not passed unless it is more than
// one second in the future. We ignore timestamps more than 1 second in the future
// for stability reasons.
- if (!transaction.isAutoTimestamp && desiredPresentTime >= expectedPresentTime &&
- desiredPresentTime < expectedPresentTime + 1s) {
+ if (!transaction.isAutoTimestamp && desiredPresentTime >= mExpectedPresentTime &&
+ desiredPresentTime < mExpectedPresentTime + 1s) {
ATRACE_FORMAT("not current desiredPresentTime: %" PRId64 " expectedPresentTime: %" PRId64,
- desiredPresentTime, expectedPresentTime);
+ desiredPresentTime, mExpectedPresentTime);
return TransactionReadiness::NotReady;
}
- if (!mScheduler->isVsyncValid(expectedPresentTime, transaction.originUid)) {
- ATRACE_FORMAT("!isVsyncValid expectedPresentTime: %" PRId64 " uid: %d", expectedPresentTime,
- transaction.originUid);
+ if (!mScheduler->isVsyncValid(mExpectedPresentTime, transaction.originUid)) {
+ ATRACE_FORMAT("!isVsyncValid expectedPresentTime: %" PRId64 " uid: %d",
+ mExpectedPresentTime, transaction.originUid);
return TransactionReadiness::NotReady;
}
// If the client didn't specify desiredPresentTime, use the vsyncId to determine the
// expected present time of this transaction.
if (transaction.isAutoTimestamp &&
- frameIsEarly(expectedPresentTime, VsyncId{transaction.frameTimelineInfo.vsyncId})) {
+ frameIsEarly(mExpectedPresentTime, VsyncId{transaction.frameTimelineInfo.vsyncId})) {
ATRACE_FORMAT("frameIsEarly vsyncId: %" PRId64 " expectedPresentTime: %" PRId64,
- transaction.frameTimelineInfo.vsyncId, expectedPresentTime);
+ transaction.frameTimelineInfo.vsyncId, mExpectedPresentTime);
return TransactionReadiness::NotReady;
}
-
return TransactionReadiness::Ready;
}
@@ -5942,6 +6023,10 @@
dumpVsync(result);
result.append("\n");
+ StringAppendF(&result, "Total missed frame count: %u\n", mFrameMissedCount.load());
+ StringAppendF(&result, "HWC missed frame count: %u\n", mHwcFrameMissedCount.load());
+ StringAppendF(&result, "GPU missed frame count: %u\n\n", mGpuFrameMissedCount.load());
+
/*
* Dump the visible layer list
*/
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 5a6f22c..6b9ba8c 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -632,8 +632,8 @@
// ICompositor overrides:
void configure() override;
- bool commit(const scheduler::FrameTarget&) override;
- CompositeResult composite(scheduler::FrameTargeter&) override;
+ bool commit(TimePoint frameTime, VsyncId, TimePoint expectedVsyncTime) override;
+ void composite(TimePoint frameTime, VsyncId) override;
void sample() override;
// ISchedulerCallback overrides:
@@ -952,8 +952,7 @@
/*
* Compositing
*/
- void postComposition(scheduler::FrameTargeter&, nsecs_t presentStartTime)
- REQUIRES(kMainThreadContext);
+ void postComposition(nsecs_t callTime) REQUIRES(kMainThreadContext);
/*
* Display management
@@ -994,6 +993,20 @@
*/
nsecs_t getVsyncPeriodFromHWC() const REQUIRES(mStateLock);
+ using FenceTimePtr = std::shared_ptr<FenceTime>;
+
+ bool wouldPresentEarly(TimePoint frameTime, Period) const REQUIRES(kMainThreadContext);
+
+ const FenceTimePtr& getPreviousPresentFence(TimePoint frameTime, Period) const
+ REQUIRES(kMainThreadContext);
+
+ // Blocks the thread waiting for up to graceTimeMs in case the fence is about to signal.
+ static bool isFencePending(const FenceTimePtr&, int graceTimeMs);
+
+ // Calculates the expected present time for this frame. For negative offsets, performs a
+ // correction using the predicted vsync for the next frame instead.
+ TimePoint calculateExpectedPresentTime(TimePoint frameTime) const;
+
/*
* Display identification
*/
@@ -1242,6 +1255,9 @@
// If blurs should be enabled on this device.
bool mSupportsBlur = false;
+ std::atomic<uint32_t> mFrameMissedCount = 0;
+ std::atomic<uint32_t> mHwcFrameMissedCount = 0;
+ std::atomic<uint32_t> mGpuFrameMissedCount = 0;
TransactionCallbackInvoker mTransactionCallbackInvoker;
@@ -1309,6 +1325,15 @@
std::unique_ptr<scheduler::RefreshRateStats> mRefreshRateStats;
scheduler::PresentLatencyTracker mPresentLatencyTracker GUARDED_BY(kMainThreadContext);
+ struct FenceWithFenceTime {
+ sp<Fence> fence = Fence::NO_FENCE;
+ FenceTimePtr fenceTime = FenceTime::NO_FENCE;
+ };
+ std::array<FenceWithFenceTime, 2> mPreviousPresentFences;
+
+ TimePoint mScheduledPresentTime GUARDED_BY(kMainThreadContext);
+ TimePoint mExpectedPresentTime GUARDED_BY(kMainThreadContext);
+
// below flags are set by main thread only
bool mSetActiveModePending = false;
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
index 42b3879..534a8f3 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
@@ -286,8 +286,8 @@
private:
// ICompositor overrides:
void configure() override {}
- bool commit(const scheduler::FrameTarget&) override { return false; }
- CompositeResult composite(scheduler::FrameTargeter&) override { return {}; }
+ bool commit(TimePoint, VsyncId, TimePoint) override { return false; }
+ void composite(TimePoint, VsyncId) override {}
void sample() override {}
// MessageQueue overrides:
@@ -604,9 +604,7 @@
mFlinger->commitTransactions();
mFlinger->flushTransactionQueues(getFuzzedVsyncId(mFdp));
-
- scheduler::FrameTargeter frameTargeter(mFdp.ConsumeBool());
- mFlinger->postComposition(frameTargeter, mFdp.ConsumeIntegral<nsecs_t>());
+ mFlinger->postComposition(systemTime());
}
mFlinger->setTransactionFlags(mFdp.ConsumeIntegral<uint32_t>());
@@ -624,6 +622,8 @@
mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate(mFdp.ConsumeIntegral<uid_t>());
+ mFlinger->calculateExpectedPresentTime({});
+
mFlinger->enableHalVirtualDisplays(mFdp.ConsumeBool());
fuzzDumpsysAndDebug(&mFdp);
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
index b1fd06f..f17d2e1 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
@@ -19,7 +19,6 @@
#include <fuzzer/FuzzedDataProvider.h>
#include <processgroup/sched_policy.h>
-#include <scheduler/IVsyncSource.h>
#include <scheduler/PresentLatencyTracker.h>
#include "Scheduler/OneShotTimer.h"
@@ -43,7 +42,6 @@
(120_Hz).getPeriodNsecs()};
constexpr auto kLayerVoteTypes = ftl::enum_range<scheduler::RefreshRateSelector::LayerVoteType>();
-constexpr auto kCompositionCoverage = ftl::enum_range<CompositionCoverage>();
constexpr PowerMode kPowerModes[] = {PowerMode::ON, PowerMode::DOZE, PowerMode::OFF,
PowerMode::DOZE_SUSPEND, PowerMode::ON_SUSPEND};
@@ -58,10 +56,6 @@
component->dump(res);
}
-inline sp<Fence> makeFakeFence() {
- return sp<Fence>::make(memfd_create("fd", MFD_ALLOW_SEALING));
-}
-
class SchedulerFuzzer {
public:
SchedulerFuzzer(const uint8_t* data, size_t size) : mFdp(data, size){};
@@ -71,7 +65,6 @@
void fuzzRefreshRateSelection();
void fuzzRefreshRateSelector();
void fuzzPresentLatencyTracker();
- void fuzzFrameTargeter();
void fuzzVSyncModulator();
void fuzzVSyncPredictor();
void fuzzVSyncReactor();
@@ -263,13 +256,13 @@
reactor.addHwVsyncTimestamp(0, std::nullopt, &periodFlushed);
reactor.addHwVsyncTimestamp(mFdp.ConsumeIntegral<nsecs_t>() /*newPeriod*/, std::nullopt,
&periodFlushed);
-
- const auto fence = std::make_shared<FenceTime>(makeFakeFence());
+ sp<Fence> fence = sp<Fence>::make(memfd_create("fd", MFD_ALLOW_SEALING));
+ std::shared_ptr<FenceTime> ft = std::make_shared<FenceTime>(fence);
vSyncTracker->addVsyncTimestamp(mFdp.ConsumeIntegral<nsecs_t>());
FenceTime::Snapshot snap(mFdp.ConsumeIntegral<nsecs_t>());
- fence->applyTrustedSnapshot(snap);
+ ft->applyTrustedSnapshot(snap);
reactor.setIgnorePresentFences(mFdp.ConsumeBool());
- reactor.addPresentFence(fence);
+ reactor.addPresentFence(ft);
dump<scheduler::VSyncReactor>(&reactor, &mFdp);
}
@@ -399,45 +392,14 @@
void SchedulerFuzzer::fuzzPresentLatencyTracker() {
scheduler::PresentLatencyTracker tracker;
-
- int i = 5;
- while (i-- > 0) {
- tracker.trackPendingFrame(getFuzzedTimePoint(mFdp),
- std::make_shared<FenceTime>(makeFakeFence()));
- }
-}
-
-void SchedulerFuzzer::fuzzFrameTargeter() {
- scheduler::FrameTargeter frameTargeter(mFdp.ConsumeBool());
-
- const struct VsyncSource final : scheduler::IVsyncSource {
- explicit VsyncSource(FuzzedDataProvider& fuzzer) : fuzzer(fuzzer) {}
- FuzzedDataProvider& fuzzer;
-
- Period period() const { return getFuzzedDuration(fuzzer); }
- TimePoint vsyncDeadlineAfter(TimePoint) const { return getFuzzedTimePoint(fuzzer); }
- } vsyncSource{mFdp};
-
- int i = 10;
- while (i-- > 0) {
- frameTargeter.beginFrame({.frameBeginTime = getFuzzedTimePoint(mFdp),
- .vsyncId = getFuzzedVsyncId(mFdp),
- .expectedVsyncTime = getFuzzedTimePoint(mFdp),
- .sfWorkDuration = getFuzzedDuration(mFdp)},
- vsyncSource);
-
- frameTargeter.setPresentFence(makeFakeFence());
-
- frameTargeter.endFrame(
- {.compositionCoverage = mFdp.PickValueInArray(kCompositionCoverage.values)});
- }
+ tracker.trackPendingFrame(TimePoint::fromNs(mFdp.ConsumeIntegral<nsecs_t>()),
+ FenceTime::NO_FENCE);
}
void SchedulerFuzzer::process() {
fuzzRefreshRateSelection();
fuzzRefreshRateSelector();
fuzzPresentLatencyTracker();
- fuzzFrameTargeter();
fuzzVSyncModulator();
fuzzVSyncPredictor();
fuzzVSyncReactor();
diff --git a/services/surfaceflinger/tests/unittests/MessageQueueTest.cpp b/services/surfaceflinger/tests/unittests/MessageQueueTest.cpp
index 359e2ab..91875cc 100644
--- a/services/surfaceflinger/tests/unittests/MessageQueueTest.cpp
+++ b/services/surfaceflinger/tests/unittests/MessageQueueTest.cpp
@@ -20,10 +20,9 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
-#include <scheduler/interface/ICompositor.h>
-
#include "FrameTimeline.h"
#include "Scheduler/MessageQueue.h"
+#include "SurfaceFlinger.h"
#include "mock/MockVSyncDispatch.h"
namespace android {
@@ -35,8 +34,8 @@
struct NoOpCompositor final : ICompositor {
void configure() override {}
- bool commit(const scheduler::FrameTarget&) override { return false; }
- CompositeResult composite(scheduler::FrameTargeter&) override { return {}; }
+ bool commit(TimePoint, VsyncId, TimePoint) override { return false; }
+ void composite(TimePoint, VsyncId) override {}
void sample() override {}
} gNoOpCompositor;
diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h
index aac11c0..a30f7e0 100644
--- a/services/surfaceflinger/tests/unittests/TestableScheduler.h
+++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h
@@ -173,8 +173,8 @@
private:
// ICompositor overrides:
void configure() override {}
- bool commit(const scheduler::FrameTarget&) override { return false; }
- CompositeResult composite(scheduler::FrameTargeter&) override { return {}; }
+ bool commit(TimePoint, VsyncId, TimePoint) override { return false; }
+ void composite(TimePoint, VsyncId) override {}
void sample() override {}
};
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 833984f..945e488 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -20,11 +20,6 @@
#include <chrono>
#include <variant>
-#include <ftl/fake_guard.h>
-#include <ftl/match.h>
-#include <gui/ScreenCaptureResults.h>
-#include <ui/DynamicDisplayInfo.h>
-
#include <compositionengine/Display.h>
#include <compositionengine/LayerFECompositionState.h>
#include <compositionengine/OutputLayer.h>
@@ -32,7 +27,11 @@
#include <compositionengine/impl/Display.h>
#include <compositionengine/impl/OutputLayerCompositionState.h>
#include <compositionengine/mock/DisplaySurface.h>
+#include <ftl/fake_guard.h>
+#include <ftl/match.h>
+#include <gui/ScreenCaptureResults.h>
+#include <ui/DynamicDisplayInfo.h>
#include "DisplayDevice.h"
#include "FakeVsyncConfiguration.h"
#include "FrameTracer/FrameTracer.h"
@@ -45,6 +44,7 @@
#include "Scheduler/RefreshRateSelector.h"
#include "StartPropertySetThread.h"
#include "SurfaceFlinger.h"
+#include "SurfaceFlingerDefaultFactory.h"
#include "TestableScheduler.h"
#include "mock/DisplayHardware/MockComposer.h"
#include "mock/DisplayHardware/MockDisplayMode.h"
@@ -360,42 +360,25 @@
commitTransactionsLocked(eDisplayTransactionNeeded);
}
- void commit(TimePoint frameTime, VsyncId vsyncId, TimePoint expectedVsyncTime,
- bool composite = false) {
- constexpr bool kBackpressureGpuComposition = true;
- scheduler::FrameTargeter frameTargeter(kBackpressureGpuComposition);
-
- frameTargeter.beginFrame({.frameBeginTime = frameTime,
- .vsyncId = vsyncId,
- .expectedVsyncTime = expectedVsyncTime,
- .sfWorkDuration = 10ms},
- *mScheduler->getVsyncSchedule());
-
- mFlinger->commit(frameTargeter.target());
-
- if (composite) {
- mFlinger->composite(frameTargeter);
- }
+ TimePoint commit(TimePoint frameTime, VsyncId vsyncId, TimePoint expectedVsyncTime) {
+ mFlinger->commit(frameTime, vsyncId, expectedVsyncTime);
+ return frameTime;
}
- void commit(TimePoint frameTime, VsyncId vsyncId, bool composite = false) {
- return commit(frameTime, vsyncId, frameTime + Period(10ms), composite);
+ TimePoint commit(TimePoint frameTime, VsyncId vsyncId) {
+ return commit(frameTime, vsyncId, frameTime + Period(10ms));
}
- void commit(bool composite = false) {
+ TimePoint commit() {
const TimePoint frameTime = scheduler::SchedulerClock::now();
- commit(frameTime, kVsyncId, composite);
+ return commit(frameTime, kVsyncId);
}
void commitAndComposite(TimePoint frameTime, VsyncId vsyncId, TimePoint expectedVsyncTime) {
- constexpr bool kComposite = true;
- commit(frameTime, vsyncId, expectedVsyncTime, kComposite);
+ mFlinger->composite(commit(frameTime, vsyncId, expectedVsyncTime), vsyncId);
}
- void commitAndComposite() {
- constexpr bool kComposite = true;
- commit(kComposite);
- }
+ void commitAndComposite() { mFlinger->composite(commit(), kVsyncId); }
auto createDisplay(const String8& displayName, bool secure, float requestedRefreshRate = 0.0f) {
return mFlinger->createDisplay(displayName, secure, requestedRefreshRate);