diff options
| author | 2024-02-23 22:09:36 +0000 | |
|---|---|---|
| committer | 2024-02-23 22:09:36 +0000 | |
| commit | c7c3ed1b50083e2150731f6e58955032e774c94e (patch) | |
| tree | 52527bbf555cebc963b2727318824373cf0959d1 | |
| parent | 674215c15f13d280d444c788d7893a5999095f05 (diff) | |
| parent | 558f4a96d3e1208b0fc6002c654d6bac9e1a93e3 (diff) | |
Merge changes I5b0dd111,I40135534,Ief7fff69 into main
* changes:
[SF] Change VSyncDispatchTimerQueue::Schedule to return ScheduleResult
[SF] Enable vrr_timeout_hint_enabled
[SF] Send NotifyExpectedPresentHint at the transaction time
14 files changed, 413 insertions, 182 deletions
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index cfa03397d6..776bcd3e32 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -92,7 +92,7 @@ HWComposer::HWComposer(std::unique_ptr<Hwc2::Composer> composer) mMaxVirtualDisplayDimension(static_cast<size_t>(sysprop::max_virtual_display_dimension(0))), mUpdateDeviceProductInfoOnHotplugReconnect( sysprop::update_device_product_info_on_hotplug_reconnect(false)), - mEnableVrrTimeout(base::GetBoolProperty("debug.sf.vrr_timeout_hint_enabled"s, false)) {} + mEnableVrrTimeout(base::GetBoolProperty("debug.sf.vrr_timeout_hint_enabled"s, true)) {} HWComposer::HWComposer(const std::string& composerServiceName) : HWComposer(Hwc2::Composer::create(composerServiceName)) {} diff --git a/services/surfaceflinger/Scheduler/MessageQueue.cpp b/services/surfaceflinger/Scheduler/MessageQueue.cpp index a145e59eb5..ff88d71259 100644 --- a/services/surfaceflinger/Scheduler/MessageQueue.cpp +++ b/services/surfaceflinger/Scheduler/MessageQueue.cpp @@ -17,7 +17,6 @@ #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include <binder/IPCThreadState.h> -#include <gui/DisplayEventReceiver.h> #include <utils/Log.h> #include <utils/Timers.h> #include <utils/threads.h> @@ -66,7 +65,7 @@ void MessageQueue::vsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime, ns { std::lock_guard lock(mVsync.mutex); mVsync.lastCallbackTime = expectedVsyncTime; - mVsync.scheduledFrameTime.reset(); + mVsync.scheduledFrameTimeOpt.reset(); } const auto vsyncId = VsyncId{mVsync.tokenManager->generateTokenForPredictions( @@ -122,7 +121,7 @@ std::unique_ptr<scheduler::VSyncCallbackRegistration> MessageQueue::onNewVsyncSc std::placeholders::_3), "sf"); if (reschedule) { - mVsync.scheduledFrameTime = + mVsync.scheduledFrameTimeOpt = mVsync.registration->schedule({.workDuration = mVsync.workDuration.get().count(), .readyDuration = 0, .lastVsync = mVsync.lastCallbackTime.ns()}); @@ -140,7 +139,7 @@ void MessageQueue::setDuration(std::chrono::nanoseconds workDuration) { ATRACE_CALL(); std::lock_guard lock(mVsync.mutex); mVsync.workDuration = workDuration; - mVsync.scheduledFrameTime = + mVsync.scheduledFrameTimeOpt = mVsync.registration->update({.workDuration = mVsync.workDuration.get().count(), .readyDuration = 0, .lastVsync = mVsync.lastCallbackTime.ns()}); @@ -193,22 +192,20 @@ void MessageQueue::scheduleFrame() { ATRACE_CALL(); std::lock_guard lock(mVsync.mutex); - mVsync.scheduledFrameTime = + mVsync.scheduledFrameTimeOpt = mVsync.registration->schedule({.workDuration = mVsync.workDuration.get().count(), .readyDuration = 0, .lastVsync = mVsync.lastCallbackTime.ns()}); } -auto MessageQueue::getScheduledFrameTime() const -> std::optional<Clock::time_point> { +std::optional<scheduler::ScheduleResult> MessageQueue::getScheduledFrameResult() const { if (mHandler->isFramePending()) { - return Clock::now(); + return scheduler::ScheduleResult{TimePoint::now(), mHandler->getExpectedVsyncTime()}; } - std::lock_guard lock(mVsync.mutex); - if (const auto time = mVsync.scheduledFrameTime) { - return Clock::time_point(std::chrono::nanoseconds(*time)); + if (const auto scheduledFrameTimeline = mVsync.scheduledFrameTimeOpt) { + return scheduledFrameTimeline; } - return std::nullopt; } diff --git a/services/surfaceflinger/Scheduler/MessageQueue.h b/services/surfaceflinger/Scheduler/MessageQueue.h index edb424b5b9..c5fc371d3a 100644 --- a/services/surfaceflinger/Scheduler/MessageQueue.h +++ b/services/surfaceflinger/Scheduler/MessageQueue.h @@ -76,8 +76,7 @@ public: virtual void scheduleConfigure() = 0; virtual void scheduleFrame() = 0; - using Clock = std::chrono::steady_clock; - virtual std::optional<Clock::time_point> getScheduledFrameTime() const = 0; + virtual std::optional<scheduler::ScheduleResult> getScheduledFrameResult() const = 0; }; namespace impl { @@ -95,7 +94,9 @@ protected: explicit Handler(MessageQueue& queue) : mQueue(queue) {} void handleMessage(const Message& message) override; - bool isFramePending() const; + virtual TimePoint getExpectedVsyncTime() const { return mExpectedVsyncTime.load(); } + + virtual bool isFramePending() const; virtual void dispatchFrame(VsyncId, TimePoint expectedVsyncTime); }; @@ -124,7 +125,7 @@ private: TracedOrdinal<std::chrono::nanoseconds> workDuration GUARDED_BY(mutex) = {"VsyncWorkDuration-sf", std::chrono::nanoseconds(0)}; TimePoint lastCallbackTime GUARDED_BY(mutex); - std::optional<nsecs_t> scheduledFrameTime GUARDED_BY(mutex); + std::optional<scheduler::ScheduleResult> scheduledFrameTimeOpt GUARDED_BY(mutex); TracedOrdinal<int> value = {"VSYNC-sf", 0}; }; @@ -150,7 +151,7 @@ public: void scheduleConfigure() override; void scheduleFrame() override; - std::optional<Clock::time_point> getScheduledFrameTime() const override; + std::optional<scheduler::ScheduleResult> getScheduledFrameResult() const override; }; } // namespace impl diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index 71df507a00..dc322254c0 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -109,9 +109,9 @@ public: void initVsync(frametimeline::TokenManager&, std::chrono::nanoseconds workDuration); - using Impl::getScheduledFrameTime; using Impl::setDuration; + using Impl::getScheduledFrameResult; using Impl::scheduleConfigure; using Impl::scheduleFrame; diff --git a/services/surfaceflinger/Scheduler/VSyncDispatch.h b/services/surfaceflinger/Scheduler/VSyncDispatch.h index ed8f8fef93..0c43ffbc04 100644 --- a/services/surfaceflinger/Scheduler/VSyncDispatch.h +++ b/services/surfaceflinger/Scheduler/VSyncDispatch.h @@ -21,11 +21,15 @@ #include <string> #include <ftl/mixins.h> +#include <scheduler/Time.h> #include <utils/Timers.h> namespace android::scheduler { -using ScheduleResult = std::optional<nsecs_t>; +struct ScheduleResult { + TimePoint callbackTime; + TimePoint vsyncTime; +}; enum class CancelResult { Cancelled, TooLate, Error }; @@ -124,10 +128,12 @@ public: * * \param [in] token The callback to schedule. * \param [in] scheduleTiming The timing information for this schedule call - * \return The expected callback time if a callback was scheduled. + * \return The expected callback time if a callback was scheduled, + * along with VSYNC time for the callback scheduled. * std::nullopt if the callback is not registered. */ - virtual ScheduleResult schedule(CallbackToken token, ScheduleTiming scheduleTiming) = 0; + virtual std::optional<ScheduleResult> schedule(CallbackToken token, + ScheduleTiming scheduleTiming) = 0; /* * Update the timing information for a scheduled callback. @@ -135,10 +141,12 @@ public: * * \param [in] token The callback to schedule. * \param [in] scheduleTiming The timing information for this schedule call - * \return The expected callback time if a callback was scheduled. + * \return The expected callback time if a callback was scheduled, + * along with VSYNC time for the callback scheduled. * std::nullopt if the callback is not registered. */ - virtual ScheduleResult update(CallbackToken token, ScheduleTiming scheduleTiming) = 0; + virtual std::optional<ScheduleResult> update(CallbackToken token, + ScheduleTiming scheduleTiming) = 0; /* Cancels a scheduled callback, if possible. * @@ -168,10 +176,10 @@ public: VSyncCallbackRegistration& operator=(VSyncCallbackRegistration&&); // See documentation for VSyncDispatch::schedule. - ScheduleResult schedule(VSyncDispatch::ScheduleTiming scheduleTiming); + std::optional<ScheduleResult> schedule(VSyncDispatch::ScheduleTiming scheduleTiming); // See documentation for VSyncDispatch::update. - ScheduleResult update(VSyncDispatch::ScheduleTiming scheduleTiming); + std::optional<ScheduleResult> update(VSyncDispatch::ScheduleTiming scheduleTiming); // See documentation for VSyncDispatch::cancel. CancelResult cancel(); diff --git a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp index b92fa24670..84ccf8e938 100644 --- a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp +++ b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp @@ -38,9 +38,10 @@ using base::StringAppendF; namespace { -nsecs_t getExpectedCallbackTime(nsecs_t nextVsyncTime, - const VSyncDispatch::ScheduleTiming& timing) { - return nextVsyncTime - timing.readyDuration - timing.workDuration; +ScheduleResult getExpectedCallbackTime(nsecs_t nextVsyncTime, + const VSyncDispatch::ScheduleTiming& timing) { + return {TimePoint::fromNs(nextVsyncTime - timing.readyDuration - timing.workDuration), + TimePoint::fromNs(nextVsyncTime)}; } } // namespace @@ -115,14 +116,15 @@ ScheduleResult VSyncDispatchTimerQueueEntry::schedule(VSyncDispatch::ScheduleTim auto const nextReadyTime = nextVsyncTime - timing.readyDuration; mScheduleTiming = timing; mArmedInfo = {nextWakeupTime, nextVsyncTime, nextReadyTime}; - return nextWakeupTime; + return ScheduleResult{TimePoint::fromNs(nextWakeupTime), TimePoint::fromNs(nextVsyncTime)}; } -nsecs_t VSyncDispatchTimerQueueEntry::addPendingWorkloadUpdate( +ScheduleResult VSyncDispatchTimerQueueEntry::addPendingWorkloadUpdate( VSyncTracker& tracker, nsecs_t now, VSyncDispatch::ScheduleTiming timing) { mWorkloadUpdateInfo = timing; const auto armedInfo = update(tracker, now, timing, mArmedInfo); - return armedInfo.mActualWakeupTime; + return {TimePoint::fromNs(armedInfo.mActualWakeupTime), + TimePoint::fromNs(armedInfo.mActualVsyncTime)}; } bool VSyncDispatchTimerQueueEntry::hasPendingWorkloadUpdate() const { @@ -383,14 +385,14 @@ void VSyncDispatchTimerQueue::unregisterCallback(CallbackToken token) { } } -ScheduleResult VSyncDispatchTimerQueue::schedule(CallbackToken token, - ScheduleTiming scheduleTiming) { +std::optional<ScheduleResult> VSyncDispatchTimerQueue::schedule(CallbackToken token, + ScheduleTiming scheduleTiming) { std::lock_guard lock(mMutex); return scheduleLocked(token, scheduleTiming); } -ScheduleResult VSyncDispatchTimerQueue::scheduleLocked(CallbackToken token, - ScheduleTiming scheduleTiming) { +std::optional<ScheduleResult> VSyncDispatchTimerQueue::scheduleLocked( + CallbackToken token, ScheduleTiming scheduleTiming) { auto it = mCallbacks.find(token); if (it == mCallbacks.end()) { return {}; @@ -405,10 +407,7 @@ ScheduleResult VSyncDispatchTimerQueue::scheduleLocked(CallbackToken token, return callback->addPendingWorkloadUpdate(*mTracker, now, scheduleTiming); } - const ScheduleResult result = callback->schedule(scheduleTiming, *mTracker, now); - if (!result.has_value()) { - return {}; - } + const auto result = callback->schedule(scheduleTiming, *mTracker, now); if (callback->wakeupTime() < mIntendedWakeupTime - mTimerSlack) { rearmTimerSkippingUpdateFor(now, it); @@ -417,7 +416,8 @@ ScheduleResult VSyncDispatchTimerQueue::scheduleLocked(CallbackToken token, return result; } -ScheduleResult VSyncDispatchTimerQueue::update(CallbackToken token, ScheduleTiming scheduleTiming) { +std::optional<ScheduleResult> VSyncDispatchTimerQueue::update(CallbackToken token, + ScheduleTiming scheduleTiming) { std::lock_guard lock(mMutex); const auto it = mCallbacks.find(token); if (it == mCallbacks.end()) { @@ -494,14 +494,16 @@ VSyncCallbackRegistration::~VSyncCallbackRegistration() { if (mToken) mDispatch->unregisterCallback(*mToken); } -ScheduleResult VSyncCallbackRegistration::schedule(VSyncDispatch::ScheduleTiming scheduleTiming) { +std::optional<ScheduleResult> VSyncCallbackRegistration::schedule( + VSyncDispatch::ScheduleTiming scheduleTiming) { if (!mToken) { return std::nullopt; } return mDispatch->schedule(*mToken, scheduleTiming); } -ScheduleResult VSyncCallbackRegistration::update(VSyncDispatch::ScheduleTiming scheduleTiming) { +std::optional<ScheduleResult> VSyncCallbackRegistration::update( + VSyncDispatch::ScheduleTiming scheduleTiming) { if (!mToken) { return std::nullopt; } diff --git a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.h b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.h index b5ddd25293..252c09ce53 100644 --- a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.h +++ b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.h @@ -69,7 +69,8 @@ public: // Adds a pending upload of the earliestVSync and workDuration that will be applied on the next // call to update() - nsecs_t addPendingWorkloadUpdate(VSyncTracker&, nsecs_t now, VSyncDispatch::ScheduleTiming); + ScheduleResult addPendingWorkloadUpdate(VSyncTracker&, nsecs_t now, + VSyncDispatch::ScheduleTiming); // Checks if there is a pending update to the workload, returning true if so. bool hasPendingWorkloadUpdate() const; @@ -128,8 +129,8 @@ public: CallbackToken registerCallback(Callback, std::string callbackName) final; void unregisterCallback(CallbackToken) final; - ScheduleResult schedule(CallbackToken, ScheduleTiming) final; - ScheduleResult update(CallbackToken, ScheduleTiming) final; + std::optional<ScheduleResult> schedule(CallbackToken, ScheduleTiming) final; + std::optional<ScheduleResult> update(CallbackToken, ScheduleTiming) final; CancelResult cancel(CallbackToken) final; void dump(std::string&) const final; @@ -147,7 +148,7 @@ private: void rearmTimerSkippingUpdateFor(nsecs_t now, CallbackMap::const_iterator skipUpdate) REQUIRES(mMutex); void cancelTimer() REQUIRES(mMutex); - ScheduleResult scheduleLocked(CallbackToken, ScheduleTiming) REQUIRES(mMutex); + std::optional<ScheduleResult> scheduleLocked(CallbackToken, ScheduleTiming) REQUIRES(mMutex); std::mutex mutable mMutex; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index ecb266d2ca..08a78cc54a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2751,7 +2751,11 @@ CompositeResultsPerDisplay SurfaceFlinger::composite( // TODO(b/255601557) Update frameInterval per display refreshArgs.frameInterval = mScheduler->getNextFrameInterval(pacesetterId, pacesetterTarget.expectedPresentTime()); - refreshArgs.scheduledFrameTime = mScheduler->getScheduledFrameTime(); + const auto scheduledFrameResultOpt = mScheduler->getScheduledFrameResult(); + const auto scheduledFrameTimeOpt = scheduledFrameResultOpt + ? std::optional{scheduledFrameResultOpt->callbackTime} + : std::nullopt; + refreshArgs.scheduledFrameTime = scheduledFrameTimeOpt; refreshArgs.hasTrustedPresentationListener = mNumTrustedPresentationListeners > 0; // Store the present time just before calling to the composition engine so we could notify // the scheduler. @@ -4250,7 +4254,8 @@ void SurfaceFlinger::notifyExpectedPresentIfRequired(PhysicalDisplayId displayId auto hintStatus = data.hintStatus.load(); if (!expectedPresentWithinTimeout) { - if (hintStatus != NotifyExpectedPresentHintStatus::Sent || + if ((hintStatus != NotifyExpectedPresentHintStatus::Sent && + hintStatus != NotifyExpectedPresentHintStatus::ScheduleOnTx) || (timeoutOpt && timeoutOpt->ns() == 0)) { // Send the hint immediately if timeout, as the hint gets // delayed otherwise, as the frame is scheduled close @@ -4259,11 +4264,16 @@ void SurfaceFlinger::notifyExpectedPresentIfRequired(PhysicalDisplayId displayId .compare_exchange_strong(hintStatus, NotifyExpectedPresentHintStatus::ScheduleOnTx)) { scheduleNotifyExpectedPresentHint(displayId); + return; } - return; } } + if (hintStatus == NotifyExpectedPresentHintStatus::Sent && + data.hintStatus.compare_exchange_strong(hintStatus, + NotifyExpectedPresentHintStatus::ScheduleOnTx)) { + return; + } if (hintStatus != NotifyExpectedPresentHintStatus::Start) { return; } @@ -4271,7 +4281,8 @@ void SurfaceFlinger::notifyExpectedPresentIfRequired(PhysicalDisplayId displayId mScheduler->scheduleFrame(); } -void SurfaceFlinger::scheduleNotifyExpectedPresentHint(PhysicalDisplayId displayId) { +void SurfaceFlinger::scheduleNotifyExpectedPresentHint(PhysicalDisplayId displayId, + VsyncId vsyncId) { auto itr = mNotifyExpectedPresentMap.find(displayId); if (itr == mNotifyExpectedPresentMap.end()) { return; @@ -4280,10 +4291,30 @@ void SurfaceFlinger::scheduleNotifyExpectedPresentHint(PhysicalDisplayId display const char* const whence = __func__; const auto sendHint = [=, this]() { auto& data = mNotifyExpectedPresentMap.at(displayId); - data.hintStatus.store(NotifyExpectedPresentHintStatus::Sent); - const auto status = - getHwComposer().notifyExpectedPresent(displayId, data.lastExpectedPresentTimestamp, - data.lastFrameInterval); + TimePoint expectedPresentTime = data.lastExpectedPresentTimestamp; + if (ftl::to_underlying(vsyncId) != FrameTimelineInfo::INVALID_VSYNC_ID) { + const auto predictionOpt = mFrameTimeline->getTokenManager()->getPredictionsForToken( + ftl::to_underlying(vsyncId)); + const auto expectedPresentTimeOnPredictor = TimePoint::fromNs( + predictionOpt ? predictionOpt->presentTime : expectedPresentTime.ns()); + const auto scheduledFrameResultOpt = mScheduler->getScheduledFrameResult(); + const auto expectedPresentTimeOnScheduler = scheduledFrameResultOpt.has_value() + ? scheduledFrameResultOpt->vsyncTime + : TimePoint::fromNs(0); + expectedPresentTime = + std::max(expectedPresentTimeOnPredictor, expectedPresentTimeOnScheduler); + } + + if (expectedPresentTime < TimePoint::now()) { + expectedPresentTime = + mScheduler->getVsyncSchedule()->vsyncDeadlineAfter(TimePoint::now()); + if (mScheduler->vsyncModulator().getVsyncConfig().sfWorkDuration > + mScheduler->getVsyncSchedule(displayId)->period()) { + expectedPresentTime += mScheduler->getVsyncSchedule(displayId)->period(); + } + } + const auto status = getHwComposer().notifyExpectedPresent(displayId, expectedPresentTime, + data.lastFrameInterval); if (status != NO_ERROR) { ALOGE("%s failed to notifyExpectedPresentHint for display %" PRId64, whence, displayId.value); @@ -4301,7 +4332,11 @@ void SurfaceFlinger::scheduleNotifyExpectedPresentHint(PhysicalDisplayId display } })); } - sendHint(); + auto scheduleHintOnPresent = NotifyExpectedPresentHintStatus::ScheduleOnPresent; + if (itr->second.hintStatus.compare_exchange_strong(scheduleHintOnPresent, + NotifyExpectedPresentHintStatus::Sent)) { + sendHint(); + } } void SurfaceFlinger::sendNotifyExpectedPresentHint(PhysicalDisplayId displayId) { @@ -5105,6 +5140,11 @@ status_t SurfaceFlinger::setTransactionState( const auto frameHint = state.isFrameActive() ? FrameHint::kActive : FrameHint::kNone; mTransactionHandler.queueTransaction(std::move(state)); + for (const auto& [displayId, data] : mNotifyExpectedPresentMap) { + if (data.hintStatus.load() == NotifyExpectedPresentHintStatus::ScheduleOnTx) { + scheduleNotifyExpectedPresentHint(displayId, VsyncId{frameTimelineInfo.vsyncId}); + } + } setTransactionFlags(eTransactionFlushNeeded, schedule, applyToken, frameHint); return NO_ERROR; } @@ -8814,7 +8854,11 @@ void SurfaceFlinger::sample() { return; } - mRegionSamplingThread->onCompositionComplete(mScheduler->getScheduledFrameTime()); + const auto scheduledFrameResultOpt = mScheduler->getScheduledFrameResult(); + const auto scheduleFrameTimeOpt = scheduledFrameResultOpt + ? std::optional{scheduledFrameResultOpt->callbackTime} + : std::nullopt; + mRegionSamplingThread->onCompositionComplete(scheduleFrameTimeOpt); } void SurfaceFlinger::onActiveDisplaySizeChanged(const DisplayDevice& activeDisplay) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index b01d1aa0e8..bada8292fd 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -1495,7 +1495,9 @@ private: std::unordered_map<PhysicalDisplayId, NotifyExpectedPresentData> mNotifyExpectedPresentMap; void sendNotifyExpectedPresentHint(PhysicalDisplayId displayId) override REQUIRES(kMainThreadContext); - void scheduleNotifyExpectedPresentHint(PhysicalDisplayId displayId); + void scheduleNotifyExpectedPresentHint(PhysicalDisplayId displayId, + VsyncId vsyncId = VsyncId{ + FrameTimelineInfo::INVALID_VSYNC_ID}); void notifyExpectedPresentIfRequired(PhysicalDisplayId, Period vsyncPeriod, TimePoint expectedPresentTime, Fps frameInterval, std::optional<Period> timeoutOpt); diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp index d5ec654c59..3eabe1f362 100644 --- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp +++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp @@ -117,14 +117,16 @@ protected: mThread->onVsync(expectedPresentationTime, timestamp, deadlineTimestamp); } + static constexpr scheduler::ScheduleResult kScheduleResult{TimePoint::fromNs(0), + TimePoint::fromNs(0)}; AsyncCallRecorderWithCannedReturn< scheduler::ScheduleResult (*)(scheduler::VSyncDispatch::CallbackToken, scheduler::VSyncDispatch::ScheduleTiming)> - mVSyncCallbackScheduleRecorder{0}; + mVSyncCallbackScheduleRecorder{kScheduleResult}; AsyncCallRecorderWithCannedReturn< scheduler::ScheduleResult (*)(scheduler::VSyncDispatch::CallbackToken, scheduler::VSyncDispatch::ScheduleTiming)> - mVSyncCallbackUpdateRecorder{0}; + mVSyncCallbackUpdateRecorder{kScheduleResult}; AsyncCallRecorderWithCannedReturn< scheduler::VSyncDispatch::CallbackToken (*)(scheduler::VSyncDispatch::Callback, std::string)> diff --git a/services/surfaceflinger/tests/unittests/MessageQueueTest.cpp b/services/surfaceflinger/tests/unittests/MessageQueueTest.cpp index f5661fccf5..71f9f88ba7 100644 --- a/services/surfaceflinger/tests/unittests/MessageQueueTest.cpp +++ b/services/surfaceflinger/tests/unittests/MessageQueueTest.cpp @@ -25,6 +25,7 @@ #include "FrameTimeline.h" #include "Scheduler/MessageQueue.h" #include "mock/MockVSyncDispatch.h" +#include "utils/Timers.h" namespace android { @@ -49,6 +50,8 @@ class TestableMessageQueue : public impl::MessageQueue { using MessageQueue::Handler::Handler; MOCK_METHOD(void, dispatchFrame, (VsyncId, TimePoint), (override)); + MOCK_METHOD(bool, isFramePending, (), (const, override)); + MOCK_METHOD(TimePoint, getExpectedVsyncTime, (), (const override)); }; explicit TestableMessageQueue(sp<MockHandler> handler) @@ -94,13 +97,17 @@ TEST_F(MessageQueueTest, commit) { const auto timing = scheduler::VSyncDispatch::ScheduleTiming{.workDuration = kDuration.ns(), .readyDuration = 0, .lastVsync = 0}; - EXPECT_FALSE(mEventQueue.getScheduledFrameTime()); + EXPECT_FALSE(mEventQueue.getScheduledFrameResult()); - EXPECT_CALL(*mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(1234)); + const auto timePoint = TimePoint::fromNs(1234); + const auto scheduleResult = scheduler::ScheduleResult{timePoint, timePoint}; + EXPECT_CALL(*mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(scheduleResult)); EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleFrame()); - ASSERT_TRUE(mEventQueue.getScheduledFrameTime()); - EXPECT_EQ(1234, mEventQueue.getScheduledFrameTime()->time_since_epoch().count()); + const auto scheduledFrameResult = mEventQueue.getScheduledFrameResult(); + ASSERT_TRUE(scheduledFrameResult); + EXPECT_EQ(1234, scheduledFrameResult->callbackTime.ns()); + EXPECT_EQ(1234, scheduledFrameResult->vsyncTime.ns()); } TEST_F(MessageQueueTest, commitTwice) { @@ -109,17 +116,25 @@ TEST_F(MessageQueueTest, commitTwice) { .readyDuration = 0, .lastVsync = 0}; - EXPECT_CALL(*mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(1234)); + auto timePoint = TimePoint::fromNs(1234); + auto scheduleResult = scheduler::ScheduleResult{timePoint, timePoint}; + EXPECT_CALL(*mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(scheduleResult)); EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleFrame()); - ASSERT_TRUE(mEventQueue.getScheduledFrameTime()); - EXPECT_EQ(1234, mEventQueue.getScheduledFrameTime()->time_since_epoch().count()); + auto scheduledFrameResult = mEventQueue.getScheduledFrameResult(); + ASSERT_TRUE(scheduledFrameResult); + EXPECT_EQ(1234, scheduledFrameResult->callbackTime.ns()); + EXPECT_EQ(1234, scheduledFrameResult->vsyncTime.ns()); - EXPECT_CALL(*mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(4567)); + timePoint = TimePoint::fromNs(4567); + scheduleResult = scheduler::ScheduleResult{timePoint, timePoint}; + EXPECT_CALL(*mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(scheduleResult)); EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleFrame()); - ASSERT_TRUE(mEventQueue.getScheduledFrameTime()); - EXPECT_EQ(4567, mEventQueue.getScheduledFrameTime()->time_since_epoch().count()); + scheduledFrameResult = mEventQueue.getScheduledFrameResult(); + ASSERT_TRUE(scheduledFrameResult); + EXPECT_EQ(4567, scheduledFrameResult->callbackTime.ns()); + EXPECT_EQ(4567, scheduledFrameResult->vsyncTime.ns()); } TEST_F(MessageQueueTest, commitTwiceWithCallback) { @@ -128,11 +143,15 @@ TEST_F(MessageQueueTest, commitTwiceWithCallback) { .readyDuration = 0, .lastVsync = 0}; - EXPECT_CALL(*mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(1234)); + const auto timePoint = TimePoint::fromNs(1234); + auto scheduleResult = scheduler::ScheduleResult{timePoint, timePoint}; + EXPECT_CALL(*mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(scheduleResult)); EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleFrame()); - ASSERT_TRUE(mEventQueue.getScheduledFrameTime()); - EXPECT_EQ(1234, mEventQueue.getScheduledFrameTime()->time_since_epoch().count()); + auto scheduledFrameResult = mEventQueue.getScheduledFrameResult(); + ASSERT_TRUE(scheduledFrameResult); + EXPECT_EQ(1234, scheduledFrameResult->callbackTime.ns()); + EXPECT_EQ(1234, scheduledFrameResult->vsyncTime.ns()); constexpr TimePoint kStartTime = TimePoint::fromNs(100); constexpr TimePoint kEndTime = kStartTime + kDuration; @@ -148,14 +167,15 @@ TEST_F(MessageQueueTest, commitTwiceWithCallback) { EXPECT_NO_FATAL_FAILURE( mEventQueue.vsyncCallback(kPresentTime.ns(), kStartTime.ns(), kEndTime.ns())); - EXPECT_FALSE(mEventQueue.getScheduledFrameTime()); + EXPECT_FALSE(mEventQueue.getScheduledFrameResult()); const auto timingAfterCallback = scheduler::VSyncDispatch::ScheduleTiming{.workDuration = kDuration.ns(), .readyDuration = 0, .lastVsync = kPresentTime.ns()}; - - EXPECT_CALL(*mVSyncDispatch, schedule(mCallbackToken, timingAfterCallback)).WillOnce(Return(0)); + scheduleResult = scheduler::ScheduleResult{TimePoint::fromNs(0), TimePoint::fromNs(0)}; + EXPECT_CALL(*mVSyncDispatch, schedule(mCallbackToken, timingAfterCallback)) + .WillOnce(Return(scheduleResult)); EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleFrame()); } @@ -167,9 +187,24 @@ TEST_F(MessageQueueTest, commitWithDurationChange) { .readyDuration = 0, .lastVsync = 0}; - EXPECT_CALL(*mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(0)); + const auto scheduleResult = + scheduler::ScheduleResult{TimePoint::fromNs(0), TimePoint::fromNs(0)}; + EXPECT_CALL(*mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(scheduleResult)); EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleFrame()); } +TEST_F(MessageQueueTest, scheduleResultWhenFrameIsPending) { + const auto timePoint = TimePoint::now(); + EXPECT_CALL(*mEventQueue.mHandler, isFramePending()).WillOnce(Return(true)); + EXPECT_CALL(*mEventQueue.mHandler, getExpectedVsyncTime()).WillRepeatedly(Return(timePoint)); + + const auto scheduledFrameResult = mEventQueue.getScheduledFrameResult(); + + ASSERT_TRUE(scheduledFrameResult); + EXPECT_NEAR(static_cast<double>(TimePoint::now().ns()), + static_cast<double>(scheduledFrameResult->callbackTime.ns()), ms2ns(1)); + EXPECT_EQ(timePoint, scheduledFrameResult->vsyncTime); +} + } // namespace } // namespace android diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_NotifyExpectedPresentTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_NotifyExpectedPresentTest.cpp index 91b901838c..20a3315169 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_NotifyExpectedPresentTest.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_NotifyExpectedPresentTest.cpp @@ -41,6 +41,33 @@ public: } protected: + void setTransactionState() { + ASSERT_TRUE(mFlinger.getTransactionQueue().isEmpty()); + TransactionInfo transaction; + mFlinger.setTransactionState(FrameTimelineInfo{}, transaction.states, transaction.displays, + transaction.flags, transaction.applyToken, + transaction.inputWindowCommands, + TimePoint::now().ns() + s2ns(1), transaction.isAutoTimestamp, + transaction.unCachedBuffers, + /*HasListenerCallbacks=*/false, transaction.callbacks, + transaction.id, transaction.mergedTransactionIds); + } + + struct TransactionInfo { + Vector<ComposerState> states; + Vector<DisplayState> displays; + uint32_t flags = 0; + sp<IBinder> applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance()); + InputWindowCommands inputWindowCommands; + int64_t desiredPresentTime = 0; + bool isAutoTimestamp = false; + FrameTimelineInfo frameTimelineInfo{}; + std::vector<client_cache_t> unCachedBuffers; + uint64_t id = static_cast<uint64_t>(-1); + std::vector<uint64_t> mergedTransactionIds; + std::vector<ListenerCallbacks> callbacks; + }; + struct Compositor final : ICompositor { explicit Compositor(PhysicalDisplayId displayId, TestableSurfaceFlinger& surfaceFlinger) : displayId(displayId), surfaceFlinger(surfaceFlinger) {} @@ -102,7 +129,7 @@ protected: }; TEST_F(NotifyExpectedPresentTest, noNotifyExpectedPresentHintCall_absentTimeout) { - auto expectedPresentTime = systemTime() + ms2ns(10); + auto expectedPresentTime = TimePoint::now().ns() + ms2ns(10); ASSERT_NO_FATAL_FAILURE( mFlinger.setNotifyExpectedPresentData(mPhysicalDisplayId, TimePoint::fromNs(expectedPresentTime), @@ -120,7 +147,7 @@ TEST_F(NotifyExpectedPresentTest, noNotifyExpectedPresentHintCall_absentTimeout) } TEST_F(NotifyExpectedPresentTest, notifyExpectedPresentHint_zeroTimeout) { - auto expectedPresentTime = systemTime() + ms2ns(10); + auto expectedPresentTime = TimePoint::now().ns() + ms2ns(10); { // Very first ExpectedPresent after idle, no previous timestamp. EXPECT_CALL(*mComposer, @@ -139,6 +166,10 @@ TEST_F(NotifyExpectedPresentTest, notifyExpectedPresentHint_zeroTimeout) { { mCompositor->committed = false; expectedPresentTime += kFrameInterval60HzNs; + EXPECT_CALL(static_cast<mock::VSyncTracker&>( + mFlinger.scheduler()->getVsyncSchedule()->getTracker()), + nextAnticipatedVSyncTimeFrom(_, _)) + .WillRepeatedly(Return(expectedPresentTime)); EXPECT_CALL(*mComposer, notifyExpectedPresent(kHwcDisplayId, expectedPresentTime, kFrameInterval60HzNs)) .WillOnce(Return(Error::NONE)); @@ -154,6 +185,10 @@ TEST_F(NotifyExpectedPresentTest, notifyExpectedPresentHint_zeroTimeout) { } { expectedPresentTime += kFrameInterval60HzNs; + EXPECT_CALL(static_cast<mock::VSyncTracker&>( + mFlinger.scheduler()->getVsyncSchedule()->getTracker()), + nextAnticipatedVSyncTimeFrom(_, _)) + .WillRepeatedly(Return(expectedPresentTime)); EXPECT_CALL(*mComposer, notifyExpectedPresent(kHwcDisplayId, expectedPresentTime, kFrameInterval60HzNs)) .WillOnce(Return(Error::NONE)); @@ -168,9 +203,8 @@ TEST_F(NotifyExpectedPresentTest, notifyExpectedPresentHint_zeroTimeout) { ASSERT_TRUE(mFlinger.verifyHintIsSent(mPhysicalDisplayId)); } } - TEST_F(NotifyExpectedPresentTest, notifyExpectedPresentTimeout) { - auto expectedPresentTime = systemTime() + ms2ns(10); + auto expectedPresentTime = TimePoint::now().ns() + ms2ns(10); { // Very first ExpectedPresent after idle, no previous timestamp mCompositor->committed = false; @@ -185,6 +219,27 @@ TEST_F(NotifyExpectedPresentTest, notifyExpectedPresentTimeout) { ASSERT_TRUE(mFlinger.verifyHintIsSent(mPhysicalDisplayId)); } { + EXPECT_CALL(*mComposer, notifyExpectedPresent(kHwcDisplayId, _, _)).Times(0); + expectedPresentTime += 2 * kFrameInterval5HzNs; + mFlinger.notifyExpectedPresentIfRequired(mPhysicalDisplayId, kVsyncPeriod, + TimePoint::fromNs(expectedPresentTime), kFps60Hz, + kTimeoutNs); + EXPECT_TRUE( + mFlinger.verifyLastExpectedPresentTime(mPhysicalDisplayId, expectedPresentTime)); + ASSERT_TRUE(mFlinger.verifyHintStatusIsScheduledOnTx(mPhysicalDisplayId)); + mFlinger.scheduler()->doFrameSignal(*mCompositor, VsyncId{42}); + ASSERT_TRUE(mFlinger.verifyHintStatusIsScheduledOnTx(mPhysicalDisplayId)); + { + EXPECT_CALL(*mComposer, + notifyExpectedPresent(kHwcDisplayId, expectedPresentTime, + kFrameInterval60HzNs)) + .WillOnce(Return(Error::NONE)); + // Hint sent with the setTransactionState + setTransactionState(); + ASSERT_TRUE(mFlinger.verifyHintIsSent(mPhysicalDisplayId)); + } + } + { // ExpectedPresentTime is after the timeoutNs mCompositor->committed = true; expectedPresentTime += 2 * kFrameInterval5HzNs; @@ -194,7 +249,7 @@ TEST_F(NotifyExpectedPresentTest, notifyExpectedPresentTimeout) { kTimeoutNs); EXPECT_TRUE( mFlinger.verifyLastExpectedPresentTime(mPhysicalDisplayId, expectedPresentTime)); - ASSERT_TRUE(mFlinger.verifyHintIsSent(mPhysicalDisplayId)); + ASSERT_TRUE(mFlinger.verifyHintStatusIsScheduledOnTx(mPhysicalDisplayId)); mFlinger.scheduler()->doFrameSignal(*mCompositor, VsyncId{42}); // Present happens notifyExpectedPresentHintStatus is Start ASSERT_TRUE(mFlinger.verifyHintStatusIsStart(mPhysicalDisplayId)); @@ -259,7 +314,7 @@ TEST_F(NotifyExpectedPresentTest, notifyExpectedPresentTimeout) { } TEST_F(NotifyExpectedPresentTest, notifyExpectedPresentRenderRateChanged) { - const auto now = systemTime(); + const auto now = TimePoint::now().ns(); auto expectedPresentTime = now; static constexpr Period kTimeoutNs = Period::fromNs(static_cast<Fps>(1_Hz).getPeriodNsecs()); @@ -298,6 +353,10 @@ TEST_F(NotifyExpectedPresentTest, notifyExpectedPresentRenderRateChanged) { TimePoint::fromNs(expectedPresentTime), Fps::fromPeriodNsecs(frameIntervalNs), kTimeoutNs); + EXPECT_CALL(static_cast<mock::VSyncTracker&>( + mFlinger.scheduler()->getVsyncSchedule()->getTracker()), + nextAnticipatedVSyncTimeFrom(_, _)) + .WillRepeatedly(Return(expectedPresentTime)); if (callNotifyExpectedPresentHint) { mCompositor->committed = false; ASSERT_TRUE(mFlinger.verifyHintIsScheduledOnPresent(mPhysicalDisplayId)) diff --git a/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp b/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp index eb4e84ef4f..9b70d92eac 100644 --- a/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp +++ b/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp @@ -247,7 +247,8 @@ TEST_F(VSyncDispatchTimerQueueTest, unregistersSetAlarmOnDestruction) { mDispatch->schedule(cb, {.workDuration = 100, .readyDuration = 0, .lastVsync = 1000}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(900, *result); + EXPECT_EQ(900, result->callbackTime.ns()); + EXPECT_EQ(1000, result->vsyncTime.ns()); } } @@ -260,7 +261,8 @@ TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingFuture) { mDispatch->schedule(cb, {.workDuration = 100, .readyDuration = 0, .lastVsync = intended}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(900, *result); + EXPECT_EQ(900, result->callbackTime.ns()); + EXPECT_EQ(1000, result->vsyncTime.ns()); advanceToNextCallback(); @@ -279,12 +281,14 @@ TEST_F(VSyncDispatchTimerQueueTest, updateAlarmSettingFuture) { mDispatch->schedule(cb, {.workDuration = 100, .readyDuration = 0, .lastVsync = intended}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(900, *result); + EXPECT_EQ(900, result->callbackTime.ns()); + EXPECT_EQ(1000, result->vsyncTime.ns()); result = mDispatch->update(cb, {.workDuration = 300, .readyDuration = 0, .lastVsync = intended}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(700, *result); + EXPECT_EQ(700, result->callbackTime.ns()); + EXPECT_EQ(1000, result->vsyncTime.ns()); advanceToNextCallback(); @@ -332,7 +336,8 @@ TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingAdjustmentPast) { .readyDuration = 0, .lastVsync = mPeriod}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(mPeriod, *result); + EXPECT_EQ(mPeriod, result->callbackTime.ns()); + EXPECT_EQ(workDuration + mPeriod, result->vsyncTime.ns()); } TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancel) { @@ -344,7 +349,8 @@ TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancel) { mDispatch->schedule(cb, {.workDuration = 100, .readyDuration = 0, .lastVsync = mPeriod}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(mPeriod - 100, *result); + EXPECT_EQ(mPeriod - 100, result->callbackTime.ns()); + EXPECT_EQ(mPeriod, result->vsyncTime.ns()); EXPECT_EQ(mDispatch->cancel(cb), CancelResult::Cancelled); } @@ -357,7 +363,8 @@ TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancelTooLate) { mDispatch->schedule(cb, {.workDuration = 100, .readyDuration = 0, .lastVsync = mPeriod}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(mPeriod - 100, *result); + EXPECT_EQ(mPeriod - 100, result->callbackTime.ns()); + EXPECT_EQ(mPeriod, result->vsyncTime.ns()); mMockClock.advanceBy(950); EXPECT_EQ(mDispatch->cancel(cb), CancelResult::TooLate); } @@ -371,7 +378,8 @@ TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancelTooLateWhenRunning) { mDispatch->schedule(cb, {.workDuration = 100, .readyDuration = 0, .lastVsync = mPeriod}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(mPeriod - 100, *result); + EXPECT_EQ(mPeriod - 100, result->callbackTime.ns()); + EXPECT_EQ(mPeriod, result->vsyncTime.ns()); std::thread pausingThread([&] { mMockClock.advanceToNextCallback(); }); EXPECT_TRUE(cb.waitForPause()); @@ -392,7 +400,8 @@ TEST_F(VSyncDispatchTimerQueueTest, unregisterSynchronizes) { mDispatch->schedule(cb, {.workDuration = 100, .readyDuration = 0, .lastVsync = mPeriod}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(mPeriod - 100, *result); + EXPECT_EQ(mPeriod - 100, result->callbackTime.ns()); + EXPECT_EQ(mPeriod, result->vsyncTime.ns()); std::thread pausingThread([&] { mMockClock.advanceToNextCallback(); }); EXPECT_TRUE(cb.waitForPause()); @@ -625,19 +634,22 @@ TEST_F(VSyncDispatchTimerQueueTest, callbackReentrantWithPastWakeup) { .readyDuration = 0, .lastVsync = timestamp - mVsyncMoveThreshold}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(mPeriod + timestamp - 400, *result); + EXPECT_EQ(mPeriod + timestamp - 400, result->callbackTime.ns()); + EXPECT_EQ(mPeriod + timestamp, result->vsyncTime.ns()); result = mDispatch->schedule(tmp, {.workDuration = 400, .readyDuration = 0, .lastVsync = timestamp}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(mPeriod + timestamp - 400, *result); + EXPECT_EQ(mPeriod + timestamp - 400, result->callbackTime.ns()); + EXPECT_EQ(mPeriod + timestamp, result->vsyncTime.ns()); result = mDispatch->schedule(tmp, {.workDuration = 400, .readyDuration = 0, .lastVsync = timestamp + mVsyncMoveThreshold}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(mPeriod + timestamp - 400, *result); + EXPECT_EQ(mPeriod + timestamp - 400, result->callbackTime.ns()); + EXPECT_EQ(mPeriod + timestamp, result->vsyncTime.ns()); lastTarget = timestamp; }, "oo"); @@ -726,10 +738,12 @@ TEST_F(VSyncDispatchTimerQueueTest, canMoveCallbackBackwardsInTime) { auto result = mDispatch->schedule(cb0, {.workDuration = 500, .readyDuration = 0, .lastVsync = 1000}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(500, *result); + EXPECT_EQ(500, result->callbackTime.ns()); + EXPECT_EQ(1000, result->vsyncTime.ns()); result = mDispatch->schedule(cb0, {.workDuration = 100, .readyDuration = 0, .lastVsync = 1000}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(900, *result); + EXPECT_EQ(900, result->callbackTime.ns()); + EXPECT_EQ(1000, result->vsyncTime.ns()); } // b/1450138150 @@ -741,12 +755,14 @@ TEST_F(VSyncDispatchTimerQueueTest, doesNotMoveCallbackBackwardsAndSkipASchedule auto result = mDispatch->schedule(cb, {.workDuration = 500, .readyDuration = 0, .lastVsync = 1000}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(500, *result); + EXPECT_EQ(500, result->callbackTime.ns()); + EXPECT_EQ(1000, result->vsyncTime.ns()); mMockClock.advanceBy(400); result = mDispatch->schedule(cb, {.workDuration = 800, .readyDuration = 0, .lastVsync = 1000}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(1200, *result); + EXPECT_EQ(1200, result->callbackTime.ns()); + EXPECT_EQ(2000, result->vsyncTime.ns()); advanceToNextCallback(); ASSERT_THAT(cb.mCalls.size(), Eq(1)); @@ -763,12 +779,14 @@ TEST_F(VSyncDispatchTimerQueueTest, movesCallbackBackwardsAndSkipAScheduledTarge auto result = mDispatch->schedule(cb, {.workDuration = 500, .readyDuration = 0, .lastVsync = 1000}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(500, *result); + EXPECT_EQ(500, result->callbackTime.ns()); + EXPECT_EQ(1000, result->vsyncTime.ns()); mMockClock.advanceBy(400); result = mDispatch->schedule(cb, {.workDuration = 800, .readyDuration = 0, .lastVsync = 1000}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(400, *result); + EXPECT_EQ(400, result->callbackTime.ns()); + EXPECT_EQ(1000, result->vsyncTime.ns()); advanceToNextCallback(); ASSERT_THAT(cb.mCalls.size(), Eq(1)); @@ -784,11 +802,13 @@ TEST_F(VSyncDispatchTimerQueueTest, targetOffsetMovingBackALittleCanStillSchedul auto result = mDispatch->schedule(cb, {.workDuration = 500, .readyDuration = 0, .lastVsync = 1000}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(500, *result); + EXPECT_EQ(500, result->callbackTime.ns()); + EXPECT_EQ(1000, result->vsyncTime.ns()); mMockClock.advanceBy(400); result = mDispatch->schedule(cb, {.workDuration = 400, .readyDuration = 0, .lastVsync = 1000}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(602, *result); + EXPECT_EQ(602, result->callbackTime.ns()); + EXPECT_EQ(1002, result->vsyncTime.ns()); } TEST_F(VSyncDispatchTimerQueueTest, canScheduleNegativeOffsetAgainstDifferentPeriods) { @@ -796,12 +816,14 @@ TEST_F(VSyncDispatchTimerQueueTest, canScheduleNegativeOffsetAgainstDifferentPer auto result = mDispatch->schedule(cb0, {.workDuration = 500, .readyDuration = 0, .lastVsync = 1000}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(500, *result); + EXPECT_EQ(500, result->callbackTime.ns()); + EXPECT_EQ(1000, result->vsyncTime.ns()); advanceToNextCallback(); result = mDispatch->schedule(cb0, {.workDuration = 1100, .readyDuration = 0, .lastVsync = 2000}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(900, *result); + EXPECT_EQ(900, result->callbackTime.ns()); + EXPECT_EQ(2000, result->vsyncTime.ns()); } TEST_F(VSyncDispatchTimerQueueTest, canScheduleLargeNegativeOffset) { @@ -812,12 +834,14 @@ TEST_F(VSyncDispatchTimerQueueTest, canScheduleLargeNegativeOffset) { auto result = mDispatch->schedule(cb0, {.workDuration = 500, .readyDuration = 0, .lastVsync = 1000}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(500, *result); + EXPECT_EQ(500, result->callbackTime.ns()); + EXPECT_EQ(1000, result->vsyncTime.ns()); advanceToNextCallback(); result = mDispatch->schedule(cb0, {.workDuration = 1900, .readyDuration = 0, .lastVsync = 2000}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(1100, *result); + EXPECT_EQ(1100, result->callbackTime.ns()); + EXPECT_EQ(3000, result->vsyncTime.ns()); } TEST_F(VSyncDispatchTimerQueueTest, scheduleUpdatesDoesNotAffectSchedulingState) { @@ -829,11 +853,13 @@ TEST_F(VSyncDispatchTimerQueueTest, scheduleUpdatesDoesNotAffectSchedulingState) auto result = mDispatch->schedule(cb, {.workDuration = 400, .readyDuration = 0, .lastVsync = 1000}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(600, *result); + EXPECT_EQ(600, result->callbackTime.ns()); + EXPECT_EQ(1000, result->vsyncTime.ns()); result = mDispatch->schedule(cb, {.workDuration = 1400, .readyDuration = 0, .lastVsync = 1000}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(600, *result); + EXPECT_EQ(600, result->callbackTime.ns()); + EXPECT_EQ(2000, result->vsyncTime.ns()); advanceToNextCallback(); } @@ -849,11 +875,13 @@ TEST_F(VSyncDispatchTimerQueueTest, scheduleUpdatesDoesAffectSchedulingState) { auto result = mDispatch->schedule(cb, {.workDuration = 400, .readyDuration = 0, .lastVsync = 1000}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(600, *result); + EXPECT_EQ(600, result->callbackTime.ns()); + EXPECT_EQ(1000, result->vsyncTime.ns()); result = mDispatch->schedule(cb, {.workDuration = 1400, .readyDuration = 0, .lastVsync = 1000}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(0, *result); + EXPECT_EQ(0, result->callbackTime.ns()); + EXPECT_EQ(1000, result->vsyncTime.ns()); advanceToNextCallback(); } @@ -899,14 +927,16 @@ TEST_F(VSyncDispatchTimerQueueTest, skipsSchedulingIfTimerReschedulingIsImminent auto result = mDispatch->schedule(cb1, {.workDuration = 400, .readyDuration = 0, .lastVsync = 1000}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(600, *result); + EXPECT_EQ(600, result->callbackTime.ns()); + EXPECT_EQ(1000, result->vsyncTime.ns()); mMockClock.setLag(100); mMockClock.advanceBy(620); result = mDispatch->schedule(cb2, {.workDuration = 100, .readyDuration = 0, .lastVsync = 2000}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(1900, *result); + EXPECT_EQ(1900, result->callbackTime.ns()); + EXPECT_EQ(2000, result->vsyncTime.ns()); mMockClock.advanceBy(80); EXPECT_THAT(cb1.mCalls.size(), Eq(1)); @@ -927,14 +957,16 @@ TEST_F(VSyncDispatchTimerQueueTest, skipsSchedulingIfTimerReschedulingIsImminent auto result = mDispatch->schedule(cb, {.workDuration = 400, .readyDuration = 0, .lastVsync = 1000}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(600, *result); + EXPECT_EQ(600, result->callbackTime.ns()); + EXPECT_EQ(1000, result->vsyncTime.ns()); mMockClock.setLag(100); mMockClock.advanceBy(620); result = mDispatch->schedule(cb, {.workDuration = 370, .readyDuration = 0, .lastVsync = 2000}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(1630, *result); + EXPECT_EQ(1630, result->callbackTime.ns()); + EXPECT_EQ(2000, result->vsyncTime.ns()); mMockClock.advanceBy(80); EXPECT_THAT(cb.mCalls.size(), Eq(1)); @@ -954,14 +986,16 @@ TEST_F(VSyncDispatchTimerQueueTest, doesntSkipSchedulingIfTimerReschedulingIsImm auto result = mDispatch->schedule(cb, {.workDuration = 400, .readyDuration = 0, .lastVsync = 1000}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(600, *result); + EXPECT_EQ(600, result->callbackTime.ns()); + EXPECT_EQ(1000, result->vsyncTime.ns()); mMockClock.setLag(100); mMockClock.advanceBy(620); result = mDispatch->schedule(cb, {.workDuration = 370, .readyDuration = 0, .lastVsync = 2000}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(600, *result); + EXPECT_EQ(600, result->callbackTime.ns()); + EXPECT_EQ(1000, result->vsyncTime.ns()); mMockClock.advanceBy(80); ASSERT_EQ(1, cb.mCalls.size()); @@ -982,10 +1016,12 @@ TEST_F(VSyncDispatchTimerQueueTest, skipsRearmingWhenNotNextScheduled) { auto result = mDispatch->schedule(cb1, {.workDuration = 400, .readyDuration = 0, .lastVsync = 1000}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(600, *result); + EXPECT_EQ(600, result->callbackTime.ns()); + EXPECT_EQ(1000, result->vsyncTime.ns()); result = mDispatch->schedule(cb2, {.workDuration = 100, .readyDuration = 0, .lastVsync = 2000}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(1900, *result); + EXPECT_EQ(1900, result->callbackTime.ns()); + EXPECT_EQ(2000, result->vsyncTime.ns()); mMockClock.setLag(100); mMockClock.advanceBy(620); @@ -1009,10 +1045,12 @@ TEST_F(VSyncDispatchTimerQueueTest, rearmsWhenCancelledAndIsNextScheduled) { auto result = mDispatch->schedule(cb1, {.workDuration = 400, .readyDuration = 0, .lastVsync = 1000}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(600, *result); + EXPECT_EQ(600, result->callbackTime.ns()); + EXPECT_EQ(1000, result->vsyncTime.ns()); result = mDispatch->schedule(cb2, {.workDuration = 100, .readyDuration = 0, .lastVsync = 2000}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(1900, *result); + EXPECT_EQ(1900, result->callbackTime.ns()); + EXPECT_EQ(2000, result->vsyncTime.ns()); mMockClock.setLag(100); mMockClock.advanceBy(620); @@ -1045,10 +1083,12 @@ TEST_F(VSyncDispatchTimerQueueTest, laggedTimerGroupsCallbacksWithinLag) { auto result = mDispatch->schedule(cb1, {.workDuration = 400, .readyDuration = 0, .lastVsync = 1000}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(600, *result); + EXPECT_EQ(600, result->callbackTime.ns()); + EXPECT_EQ(1000, result->vsyncTime.ns()); result = mDispatch->schedule(cb2, {.workDuration = 390, .readyDuration = 0, .lastVsync = 1000}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(610, *result); + EXPECT_EQ(610, result->callbackTime.ns()); + EXPECT_EQ(1000, result->vsyncTime.ns()); mMockClock.setLag(100); mMockClock.advanceBy(700); @@ -1072,7 +1112,8 @@ TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingFutureWithReadyDuration) { mDispatch->schedule(cb, {.workDuration = 70, .readyDuration = 30, .lastVsync = intended}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(900, *result); + EXPECT_EQ(900, result->callbackTime.ns()); + EXPECT_EQ(1000, result->vsyncTime.ns()); advanceToNextCallback(); ASSERT_THAT(cb.mCalls.size(), Eq(1)); @@ -1138,12 +1179,14 @@ TEST_F(VSyncDispatchTimerQueueTest, skipAVsyc) { auto result = mDispatch->schedule(cb, {.workDuration = 500, .readyDuration = 0, .lastVsync = 1000}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(500, *result); + EXPECT_EQ(500, result->callbackTime.ns()); + EXPECT_EQ(1000, result->vsyncTime.ns()); mMockClock.advanceBy(300); result = mDispatch->schedule(cb, {.workDuration = 800, .readyDuration = 0, .lastVsync = 1000}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(1200, *result); + EXPECT_EQ(1200, result->callbackTime.ns()); + EXPECT_EQ(2000, result->vsyncTime.ns()); advanceToNextCallback(); ASSERT_THAT(cb.mCalls.size(), Eq(1)); @@ -1159,12 +1202,14 @@ TEST_F(VSyncDispatchTimerQueueTest, dontskipAVsyc) { auto result = mDispatch->schedule(cb, {.workDuration = 500, .readyDuration = 0, .lastVsync = 1000}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(500, *result); + EXPECT_EQ(500, result->callbackTime.ns()); + EXPECT_EQ(1000, result->vsyncTime.ns()); mMockClock.advanceBy(300); result = mDispatch->schedule(cb, {.workDuration = 800, .readyDuration = 0, .lastVsync = 1000}); EXPECT_TRUE(result.has_value()); - EXPECT_EQ(300, *result); + EXPECT_EQ(300, result->callbackTime.ns()); + EXPECT_EQ(1000, result->vsyncTime.ns()); advanceToNextCallback(); ASSERT_THAT(cb.mCalls.size(), Eq(1)); @@ -1197,9 +1242,11 @@ TEST_F(VSyncDispatchTimerQueueEntryTest, stateScheduling) { "test", [](auto, auto, auto) {}, mVsyncMoveThreshold); EXPECT_FALSE(entry.wakeupTime()); - EXPECT_TRUE(entry.schedule({.workDuration = 100, .readyDuration = 0, .lastVsync = 500}, - *mStubTracker.get(), 0) - .has_value()); + const auto scheduleResult = + entry.schedule({.workDuration = 100, .readyDuration = 0, .lastVsync = 500}, + *mStubTracker, 0); + EXPECT_EQ(900, scheduleResult.callbackTime.ns()); + EXPECT_EQ(1000, scheduleResult.vsyncTime.ns()); auto const wakeup = entry.wakeupTime(); ASSERT_TRUE(wakeup); EXPECT_THAT(*wakeup, Eq(900)); @@ -1220,9 +1267,11 @@ TEST_F(VSyncDispatchTimerQueueEntryTest, stateSchedulingReallyLongWakeupLatency) "test", [](auto, auto, auto) {}, mVsyncMoveThreshold); EXPECT_FALSE(entry.wakeupTime()); - EXPECT_TRUE(entry.schedule({.workDuration = 500, .readyDuration = 0, .lastVsync = 994}, - *mStubTracker.get(), now) - .has_value()); + const auto scheduleResult = + entry.schedule({.workDuration = 500, .readyDuration = 0, .lastVsync = 994}, + *mStubTracker, now); + EXPECT_EQ(9500, scheduleResult.callbackTime.ns()); + EXPECT_EQ(10000, scheduleResult.vsyncTime.ns()); auto const wakeup = entry.wakeupTime(); ASSERT_TRUE(wakeup); EXPECT_THAT(*wakeup, Eq(9500)); @@ -1243,9 +1292,11 @@ TEST_F(VSyncDispatchTimerQueueEntryTest, runCallback) { }, mVsyncMoveThreshold); - EXPECT_TRUE(entry.schedule({.workDuration = 100, .readyDuration = 0, .lastVsync = 500}, - *mStubTracker.get(), 0) - .has_value()); + const auto scheduleResult = + entry.schedule({.workDuration = 100, .readyDuration = 0, .lastVsync = 500}, + *mStubTracker, 0); + EXPECT_EQ(900, scheduleResult.callbackTime.ns()); + EXPECT_EQ(1000, scheduleResult.vsyncTime.ns()); auto const wakeup = entry.wakeupTime(); ASSERT_TRUE(wakeup); EXPECT_THAT(*wakeup, Eq(900)); @@ -1275,17 +1326,19 @@ TEST_F(VSyncDispatchTimerQueueEntryTest, updateCallback) { "test", [](auto, auto, auto) {}, mVsyncMoveThreshold); EXPECT_FALSE(entry.wakeupTime()); - entry.update(*mStubTracker.get(), 0); + entry.update(*mStubTracker, 0); EXPECT_FALSE(entry.wakeupTime()); - EXPECT_TRUE(entry.schedule({.workDuration = 100, .readyDuration = 0, .lastVsync = 500}, - *mStubTracker.get(), 0) - .has_value()); + const auto scheduleResult = + entry.schedule({.workDuration = 100, .readyDuration = 0, .lastVsync = 500}, + *mStubTracker, 0); + EXPECT_EQ(900, scheduleResult.callbackTime.ns()); + EXPECT_EQ(1000, scheduleResult.vsyncTime.ns()); auto wakeup = entry.wakeupTime(); ASSERT_TRUE(wakeup); EXPECT_THAT(wakeup, Eq(900)); - entry.update(*mStubTracker.get(), 0); + entry.update(*mStubTracker, 0); wakeup = entry.wakeupTime(); ASSERT_TRUE(wakeup); EXPECT_THAT(*wakeup, Eq(920)); @@ -1294,9 +1347,10 @@ TEST_F(VSyncDispatchTimerQueueEntryTest, updateCallback) { TEST_F(VSyncDispatchTimerQueueEntryTest, skipsUpdateIfJustScheduled) { VSyncDispatchTimerQueueEntry entry( "test", [](auto, auto, auto) {}, mVsyncMoveThreshold); - EXPECT_TRUE(entry.schedule({.workDuration = 100, .readyDuration = 0, .lastVsync = 500}, - *mStubTracker.get(), 0) - .has_value()); + EXPECT_EQ(900, + entry.schedule({.workDuration = 100, .readyDuration = 0, .lastVsync = 500}, + *mStubTracker.get(), 0) + .callbackTime.ns()); entry.update(*mStubTracker.get(), 0); auto const wakeup = entry.wakeupTime(); @@ -1307,26 +1361,32 @@ TEST_F(VSyncDispatchTimerQueueEntryTest, skipsUpdateIfJustScheduled) { TEST_F(VSyncDispatchTimerQueueEntryTest, willSnapToNextTargettableVSync) { VSyncDispatchTimerQueueEntry entry( "test", [](auto, auto, auto) {}, mVsyncMoveThreshold); - EXPECT_TRUE(entry.schedule({.workDuration = 100, .readyDuration = 0, .lastVsync = 500}, - *mStubTracker.get(), 0) - .has_value()); + auto scheduleResult = + entry.schedule({.workDuration = 100, .readyDuration = 0, .lastVsync = 500}, + *mStubTracker, 0); + + EXPECT_EQ(900, scheduleResult.callbackTime.ns()); + EXPECT_EQ(1000, scheduleResult.vsyncTime.ns()); entry.executing(); // 1000 is executing // had 1000 not been executing, this could have been scheduled for time 800. - EXPECT_TRUE(entry.schedule({.workDuration = 200, .readyDuration = 0, .lastVsync = 500}, - *mStubTracker.get(), 0) - .has_value()); + scheduleResult = entry.schedule({.workDuration = 200, .readyDuration = 0, .lastVsync = 500}, + *mStubTracker, 0); + EXPECT_EQ(1800, scheduleResult.callbackTime.ns()); + EXPECT_EQ(2000, scheduleResult.vsyncTime.ns()); EXPECT_THAT(*entry.wakeupTime(), Eq(1800)); EXPECT_THAT(*entry.readyTime(), Eq(2000)); - EXPECT_TRUE(entry.schedule({.workDuration = 50, .readyDuration = 0, .lastVsync = 500}, - *mStubTracker.get(), 0) - .has_value()); + scheduleResult = entry.schedule({.workDuration = 50, .readyDuration = 0, .lastVsync = 500}, + *mStubTracker, 0); + EXPECT_EQ(1950, scheduleResult.callbackTime.ns()); + EXPECT_EQ(2000, scheduleResult.vsyncTime.ns()); EXPECT_THAT(*entry.wakeupTime(), Eq(1950)); EXPECT_THAT(*entry.readyTime(), Eq(2000)); - EXPECT_TRUE(entry.schedule({.workDuration = 200, .readyDuration = 0, .lastVsync = 1001}, - *mStubTracker.get(), 0) - .has_value()); + scheduleResult = entry.schedule({.workDuration = 200, .readyDuration = 0, .lastVsync = 1001}, + *mStubTracker, 0); + EXPECT_EQ(1800, scheduleResult.callbackTime.ns()); + EXPECT_EQ(2000, scheduleResult.vsyncTime.ns()); EXPECT_THAT(*entry.wakeupTime(), Eq(1800)); EXPECT_THAT(*entry.readyTime(), Eq(2000)); } @@ -1349,32 +1409,48 @@ TEST_F(VSyncDispatchTimerQueueEntryTest, .InSequence(seq) .WillOnce(Return(2000)); - EXPECT_TRUE(entry.schedule({.workDuration = 100, .readyDuration = 0, .lastVsync = 500}, - *mStubTracker.get(), 0) - .has_value()); + auto scheduleResult = + entry.schedule({.workDuration = 100, .readyDuration = 0, .lastVsync = 500}, + *mStubTracker, 0); + EXPECT_EQ(900, scheduleResult.callbackTime.ns()); + EXPECT_EQ(1000, scheduleResult.vsyncTime.ns()); entry.executing(); // 1000 is executing - EXPECT_TRUE(entry.schedule({.workDuration = 200, .readyDuration = 0, .lastVsync = 500}, - *mStubTracker.get(), 0) - .has_value()); + scheduleResult = entry.schedule({.workDuration = 200, .readyDuration = 0, .lastVsync = 500}, + *mStubTracker, 0); + EXPECT_EQ(1800, scheduleResult.callbackTime.ns()); + EXPECT_EQ(2000, scheduleResult.vsyncTime.ns()); } TEST_F(VSyncDispatchTimerQueueEntryTest, reportsScheduledIfStillTime) { - VSyncDispatchTimerQueueEntry entry( - "test", [](auto, auto, auto) {}, mVsyncMoveThreshold); - EXPECT_TRUE(entry.schedule({.workDuration = 100, .readyDuration = 0, .lastVsync = 500}, - *mStubTracker.get(), 0) - .has_value()); - EXPECT_TRUE(entry.schedule({.workDuration = 200, .readyDuration = 0, .lastVsync = 500}, - *mStubTracker.get(), 0) - .has_value()); - EXPECT_TRUE(entry.schedule({.workDuration = 50, .readyDuration = 0, .lastVsync = 500}, - *mStubTracker.get(), 0) - .has_value()); - EXPECT_TRUE(entry.schedule({.workDuration = 1200, .readyDuration = 0, .lastVsync = 500}, - *mStubTracker.get(), 0) - .has_value()); + VSyncDispatchTimerQueueEntry entry("test", [](auto, auto, auto) {}, mVsyncMoveThreshold); + EXPECT_EQ(900, + entry.schedule({.workDuration = 100, .readyDuration = 0, .lastVsync = 500}, + *mStubTracker, 0) + .callbackTime.ns()); + EXPECT_EQ(800, + entry.schedule({.workDuration = 200, .readyDuration = 0, .lastVsync = 500}, + *mStubTracker, 0) + .callbackTime.ns()); + EXPECT_EQ(950, + entry.schedule({.workDuration = 50, .readyDuration = 0, .lastVsync = 500}, + *mStubTracker, 0) + .callbackTime.ns()); + { + SET_FLAG_FOR_TEST(flags::dont_skip_on_early_ro, true); + EXPECT_EQ(0, + entry.schedule({.workDuration = 1200, .readyDuration = 0, .lastVsync = 500}, + *mStubTracker, 0) + .callbackTime.ns()); + } + { + SET_FLAG_FOR_TEST(flags::dont_skip_on_early_ro, false); + EXPECT_EQ(800, + entry.schedule({.workDuration = 1200, .readyDuration = 0, .lastVsync = 500}, + *mStubTracker, 0) + .callbackTime.ns()); + } } TEST_F(VSyncDispatchTimerQueueEntryTest, storesPendingUpdatesUntilUpdateAndDontSkip) { @@ -1389,7 +1465,7 @@ TEST_F(VSyncDispatchTimerQueueEntryTest, storesPendingUpdatesUntilUpdateAndDontS .readyDuration = 0, .lastVsync = 400}); EXPECT_TRUE(entry.hasPendingWorkloadUpdate()); - entry.update(*mStubTracker.get(), 0); + entry.update(*mStubTracker, 0); EXPECT_FALSE(entry.hasPendingWorkloadUpdate()); EXPECT_THAT(*entry.wakeupTime(), Eq(mPeriod - effectualOffset)); } @@ -1409,9 +1485,11 @@ TEST_F(VSyncDispatchTimerQueueEntryTest, runCallbackWithReadyDuration) { }, mVsyncMoveThreshold); - EXPECT_TRUE(entry.schedule({.workDuration = 70, .readyDuration = 30, .lastVsync = 500}, - *mStubTracker.get(), 0) - .has_value()); + const auto scheduleResult = + entry.schedule({.workDuration = 70, .readyDuration = 30, .lastVsync = 500}, + *mStubTracker, 0); + EXPECT_EQ(900, scheduleResult.callbackTime.ns()); + EXPECT_EQ(mPeriod, scheduleResult.vsyncTime.ns()); auto const wakeup = entry.wakeupTime(); ASSERT_TRUE(wakeup); EXPECT_THAT(*wakeup, Eq(900)); diff --git a/services/surfaceflinger/tests/unittests/mock/MockVSyncDispatch.h b/services/surfaceflinger/tests/unittests/mock/MockVSyncDispatch.h index dc32ff969c..1dc2ef42d6 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockVSyncDispatch.h +++ b/services/surfaceflinger/tests/unittests/mock/MockVSyncDispatch.h @@ -29,8 +29,10 @@ public: MOCK_METHOD(CallbackToken, registerCallback, (Callback, std::string), (override)); MOCK_METHOD(void, unregisterCallback, (CallbackToken), (override)); - MOCK_METHOD(scheduler::ScheduleResult, schedule, (CallbackToken, ScheduleTiming), (override)); - MOCK_METHOD(scheduler::ScheduleResult, update, (CallbackToken, ScheduleTiming), (override)); + MOCK_METHOD(std::optional<scheduler::ScheduleResult>, schedule, (CallbackToken, ScheduleTiming), + (override)); + MOCK_METHOD(std::optional<scheduler::ScheduleResult>, update, (CallbackToken, ScheduleTiming), + (override)); MOCK_METHOD(scheduler::CancelResult, cancel, (CallbackToken token), (override)); MOCK_METHOD(void, dump, (std::string&), (const, override)); }; |