Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b5d3afa0 authored by Ady Abraham's avatar Ady Abraham
Browse files

SF: return the expected wakeup time from VSyncDispatch

Return the expected wakeup of a callback scheduled with VSyncDispatch.
This would help the client to better plan it's work. In particular
this would be used for SF to know when to schedule the region sample
thread to capture the screen.

Bug: 181983990
Test: SF unit tests
Change-Id: I38b538c1f6fac7cadcf456c55e78f67cf637480d
parent ccf4b47e
Loading
Loading
Loading
Loading
+2 −4
Original line number Diff line number Diff line
@@ -60,8 +60,7 @@ public:
                mRegistration.schedule({.workDuration = mWorkDuration.count(),
                                        .readyDuration = mReadyDuration.count(),
                                        .earliestVsync = mLastCallTime.count()});
        LOG_ALWAYS_FATAL_IF((scheduleResult != scheduler::ScheduleResult::Scheduled),
                            "Error scheduling callback: rc %X", scheduleResult);
        LOG_ALWAYS_FATAL_IF((!scheduleResult.has_value()), "Error scheduling callback");
    }

    void stop() {
@@ -100,8 +99,7 @@ private:
                    mRegistration.schedule({.workDuration = mWorkDuration.count(),
                                            .readyDuration = mReadyDuration.count(),
                                            .earliestVsync = vsyncTime});
            LOG_ALWAYS_FATAL_IF((scheduleResult != ScheduleResult::Scheduled),
                                "Error rescheduling callback: rc %X", scheduleResult);
            LOG_ALWAYS_FATAL_IF(!scheduleResult.has_value(), "Error rescheduling callback");
        }
    }

+6 −6
Original line number Diff line number Diff line
@@ -16,8 +16,10 @@

#pragma once

#include <utils/Log.h>
#include <utils/Timers.h>
#include <functional>
#include <optional>
#include <string>

#include "StrongTyping.h"
@@ -26,7 +28,8 @@ namespace android::scheduler {
class TimeKeeper;
class VSyncTracker;

enum class ScheduleResult { Scheduled, CannotSchedule, Error };
using ScheduleResult = std::optional<nsecs_t>;

enum class CancelResult { Cancelled, TooLate, Error };

/*
@@ -121,11 +124,8 @@ public:
     *
     * \param [in] token           The callback to schedule.
     * \param [in] scheduleTiming  The timing information for this schedule call
     * \return                     A ScheduleResult::Scheduled if callback was scheduled.
     *                             A ScheduleResult::CannotSchedule
     *                             if (workDuration + readyDuration - earliestVsync) is in the past,
     * or if a callback was dispatched for the predictedVsync already. A ScheduleResult::Error if
     * there was another error.
     * \return                     The expected callback time if a callback was scheduled.
     *                             std::nullopt if the callback is not registered.
     */
    virtual ScheduleResult schedule(CallbackToken token, ScheduleTiming scheduleTiming) = 0;

+20 −6
Original line number Diff line number Diff line
@@ -26,6 +26,20 @@
namespace android::scheduler {
using base::StringAppendF;

namespace {
nsecs_t getExpectedCallbackTime(nsecs_t nextVsyncTime,
                                const VSyncDispatch::ScheduleTiming& timing) {
    return nextVsyncTime - timing.readyDuration - timing.workDuration;
}

nsecs_t getExpectedCallbackTime(VSyncTracker& tracker, nsecs_t now,
                                const VSyncDispatch::ScheduleTiming& timing) {
    const auto nextVsyncTime = tracker.nextAnticipatedVSyncTimeFrom(
            std::max(timing.earliestVsync, now + timing.workDuration + timing.readyDuration));
    return getExpectedCallbackTime(nextVsyncTime, timing);
}
} // namespace

VSyncDispatch::~VSyncDispatch() = default;
VSyncTracker::~VSyncTracker() = default;
TimeKeeper::~TimeKeeper() = default;
@@ -74,7 +88,7 @@ ScheduleResult VSyncDispatchTimerQueueEntry::schedule(VSyncDispatch::ScheduleTim
    bool const wouldSkipAVsyncTarget =
            mArmedInfo && (nextVsyncTime > (mArmedInfo->mActualVsyncTime + mMinVsyncDistance));
    if (wouldSkipAVsyncTarget) {
        return ScheduleResult::Scheduled;
        return getExpectedCallbackTime(nextVsyncTime, timing);
    }

    bool const alreadyDispatchedForVsync = mLastDispatchTime &&
@@ -89,7 +103,7 @@ ScheduleResult VSyncDispatchTimerQueueEntry::schedule(VSyncDispatch::ScheduleTim
    auto const nextReadyTime = nextVsyncTime - timing.readyDuration;
    mScheduleTiming = timing;
    mArmedInfo = {nextWakeupTime, nextVsyncTime, nextReadyTime};
    return ScheduleResult::Scheduled;
    return getExpectedCallbackTime(nextVsyncTime, timing);
}

void VSyncDispatchTimerQueueEntry::addPendingWorkloadUpdate(VSyncDispatch::ScheduleTiming timing) {
@@ -317,7 +331,7 @@ void VSyncDispatchTimerQueue::unregisterCallback(CallbackToken token) {

ScheduleResult VSyncDispatchTimerQueue::schedule(CallbackToken token,
                                                 ScheduleTiming scheduleTiming) {
    auto result = ScheduleResult::Error;
    ScheduleResult result;
    {
        std::lock_guard lock(mMutex);

@@ -333,11 +347,11 @@ ScheduleResult VSyncDispatchTimerQueue::schedule(CallbackToken token,
        auto const rearmImminent = now > mIntendedWakeupTime;
        if (CC_UNLIKELY(rearmImminent)) {
            callback->addPendingWorkloadUpdate(scheduleTiming);
            return ScheduleResult::Scheduled;
            return getExpectedCallbackTime(mTracker, now, scheduleTiming);
        }

        result = callback->schedule(scheduleTiming, mTracker, now);
        if (result == ScheduleResult::CannotSchedule) {
        if (!result.has_value()) {
            return result;
        }

@@ -416,7 +430,7 @@ VSyncCallbackRegistration::~VSyncCallbackRegistration() {

ScheduleResult VSyncCallbackRegistration::schedule(VSyncDispatch::ScheduleTiming scheduleTiming) {
    if (!mValidToken) {
        return ScheduleResult::Error;
        return std::nullopt;
    }
    return mDispatch.get().schedule(mToken, scheduleTiming);
}
+2 −2
Original line number Diff line number Diff line
@@ -66,7 +66,7 @@ public:
            ALOGD("schedule: %zu", token.value());
            if (mCallbacks.count(token) == 0) {
                ALOGD("schedule: callback %zu not registered", token.value());
                return scheduler::ScheduleResult::Error;
                return scheduler::ScheduleResult{};
            }

            auto& callback = mCallbacks.at(token);
@@ -75,7 +75,7 @@ public:
            callback.targetWakeupTime =
                    timing.earliestVsync - timing.workDuration - timing.readyDuration;
            ALOGD("schedule: callback %zu scheduled", token.value());
            return scheduler::ScheduleResult::Scheduled;
            return scheduler::ScheduleResult{callback.targetWakeupTime};
        });

        ON_CALL(*this, cancel).WillByDefault([this](CallbackToken token) {
+6 −6
Original line number Diff line number Diff line
@@ -104,7 +104,7 @@ TEST_F(MessageQueueTest, invalidate) {
    const auto timing = scheduler::VSyncDispatch::ScheduleTiming{.workDuration = mDuration.count(),
                                                                 .readyDuration = 0,
                                                                 .earliestVsync = 0};
    EXPECT_CALL(mVSyncDispatch, schedule(mCallbackToken, timing)).Times(1);
    EXPECT_CALL(mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(0));
    EXPECT_NO_FATAL_FAILURE(mEventQueue.invalidate());
}

@@ -114,10 +114,10 @@ TEST_F(MessageQueueTest, invalidateTwice) {
                                                                 .readyDuration = 0,
                                                                 .earliestVsync = 0};

    EXPECT_CALL(mVSyncDispatch, schedule(mCallbackToken, timing)).Times(1);
    EXPECT_CALL(mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(0));
    EXPECT_NO_FATAL_FAILURE(mEventQueue.invalidate());

    EXPECT_CALL(mVSyncDispatch, schedule(mCallbackToken, timing)).Times(1);
    EXPECT_CALL(mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(0));
    EXPECT_NO_FATAL_FAILURE(mEventQueue.invalidate());
}

@@ -127,7 +127,7 @@ TEST_F(MessageQueueTest, invalidateTwiceWithCallback) {
                                                                 .readyDuration = 0,
                                                                 .earliestVsync = 0};

    EXPECT_CALL(mVSyncDispatch, schedule(mCallbackToken, timing)).Times(1);
    EXPECT_CALL(mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(0));
    EXPECT_NO_FATAL_FAILURE(mEventQueue.invalidate());

    const auto startTime = 100;
@@ -146,7 +146,7 @@ TEST_F(MessageQueueTest, invalidateTwiceWithCallback) {
                                                     .readyDuration = 0,
                                                     .earliestVsync = presentTime};

    EXPECT_CALL(mVSyncDispatch, schedule(mCallbackToken, timingAfterCallback)).Times(1);
    EXPECT_CALL(mVSyncDispatch, schedule(mCallbackToken, timingAfterCallback)).WillOnce(Return(0));
    EXPECT_NO_FATAL_FAILURE(mEventQueue.invalidate());
}

@@ -158,7 +158,7 @@ TEST_F(MessageQueueTest, invalidateWithDurationChange) {
                                                     .readyDuration = 0,
                                                     .earliestVsync = 0};

    EXPECT_CALL(mVSyncDispatch, schedule(mCallbackToken, timing)).Times(1);
    EXPECT_CALL(mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(0));
    EXPECT_NO_FATAL_FAILURE(mEventQueue.invalidate());
}

Loading