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

Commit 011f8ba7 authored by Ady Abraham's avatar Ady Abraham
Browse files

SF: remove DispSyncSource

DispSyncSource is a legacy reminder of DispSync which was removed
a while ago. This changes removes the DispSyncSource and instead use
the VsyncDispatch interface directly.

Test: SF unit tests
Bug: 255601557
Bug: 256196556
Change-Id: I4247c3927b9ee9443437bf960f8cedc29759c4ac
parent 15dd0a94
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -176,7 +176,6 @@ filegroup {
        "RefreshRateOverlay.cpp",
        "RegionSamplingThread.cpp",
        "RenderArea.cpp",
        "Scheduler/DispSyncSource.cpp",
        "Scheduler/EventThread.cpp",
        "Scheduler/FrameRateOverrideMappings.cpp",
        "Scheduler/OneShotTimer.cpp",
+0 −202
Original line number Diff line number Diff line
/*
 * Copyright 2018 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.
 */

#define ATRACE_TAG ATRACE_TAG_GRAPHICS

#include "DispSyncSource.h"

#include <android-base/stringprintf.h>
#include <utils/Trace.h>
#include <mutex>

#include "EventThread.h"
#include "VSyncTracker.h"
#include "VsyncController.h"

namespace android::scheduler {
using base::StringAppendF;
using namespace std::chrono_literals;

class CallbackRepeater {
public:
    CallbackRepeater(VSyncDispatch& dispatch, VSyncDispatch::Callback cb, const char* name,
                     std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration,
                     std::chrono::nanoseconds notBefore)
          : mName(name),
            mCallback(cb),
            mRegistration(dispatch,
                          std::bind(&CallbackRepeater::callback, this, std::placeholders::_1,
                                    std::placeholders::_2, std::placeholders::_3),
                          mName),
            mStarted(false),
            mWorkDuration(workDuration),
            mReadyDuration(readyDuration),
            mLastCallTime(notBefore) {}

    ~CallbackRepeater() {
        std::lock_guard lock(mMutex);
        mRegistration.cancel();
    }

    void start(std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration) {
        std::lock_guard lock(mMutex);
        mStarted = true;
        mWorkDuration = workDuration;
        mReadyDuration = readyDuration;

        auto const scheduleResult =
                mRegistration.schedule({.workDuration = mWorkDuration.count(),
                                        .readyDuration = mReadyDuration.count(),
                                        .earliestVsync = mLastCallTime.count()});
        LOG_ALWAYS_FATAL_IF((!scheduleResult.has_value()), "Error scheduling callback");
    }

    void stop() {
        std::lock_guard lock(mMutex);
        LOG_ALWAYS_FATAL_IF(!mStarted, "DispSyncInterface misuse: callback already stopped");
        mStarted = false;
        mRegistration.cancel();
    }

    void dump(std::string& result) const {
        std::lock_guard lock(mMutex);
        const auto relativeLastCallTime =
                mLastCallTime - std::chrono::steady_clock::now().time_since_epoch();
        StringAppendF(&result, "\t%s: ", mName.c_str());
        StringAppendF(&result, "mWorkDuration=%.2f mReadyDuration=%.2f last vsync time ",
                      mWorkDuration.count() / 1e6f, mReadyDuration.count() / 1e6f);
        StringAppendF(&result, "%.2fms relative to now (%s)\n", relativeLastCallTime.count() / 1e6f,
                      mStarted ? "running" : "stopped");
    }

private:
    void callback(nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
        {
            std::lock_guard lock(mMutex);
            mLastCallTime = std::chrono::nanoseconds(vsyncTime);
        }

        mCallback(vsyncTime, wakeupTime, readyTime);

        {
            std::lock_guard lock(mMutex);
            if (!mStarted) {
                return;
            }
            auto const scheduleResult =
                    mRegistration.schedule({.workDuration = mWorkDuration.count(),
                                            .readyDuration = mReadyDuration.count(),
                                            .earliestVsync = vsyncTime});
            LOG_ALWAYS_FATAL_IF(!scheduleResult.has_value(), "Error rescheduling callback");
        }
    }

    const std::string mName;
    scheduler::VSyncDispatch::Callback mCallback;

    mutable std::mutex mMutex;
    VSyncCallbackRegistration mRegistration GUARDED_BY(mMutex);
    bool mStarted GUARDED_BY(mMutex) = false;
    std::chrono::nanoseconds mWorkDuration GUARDED_BY(mMutex) = 0ns;
    std::chrono::nanoseconds mReadyDuration GUARDED_BY(mMutex) = 0ns;
    std::chrono::nanoseconds mLastCallTime GUARDED_BY(mMutex) = 0ns;
};

DispSyncSource::DispSyncSource(VSyncDispatch& vSyncDispatch, VSyncTracker& vSyncTracker,
                               std::chrono::nanoseconds workDuration,
                               std::chrono::nanoseconds readyDuration, bool traceVsync,
                               const char* name)
      : mName(name),
        mValue(base::StringPrintf("VSYNC-%s", name), 0),
        mTraceVsync(traceVsync),
        mVsyncOnLabel(base::StringPrintf("VsyncOn-%s", name)),
        mVSyncTracker(vSyncTracker),
        mWorkDuration(base::StringPrintf("VsyncWorkDuration-%s", name), workDuration),
        mReadyDuration(readyDuration) {
    mCallbackRepeater =
            std::make_unique<CallbackRepeater>(vSyncDispatch,
                                               std::bind(&DispSyncSource::onVsyncCallback, this,
                                                         std::placeholders::_1,
                                                         std::placeholders::_2,
                                                         std::placeholders::_3),
                                               name, workDuration, readyDuration,
                                               std::chrono::steady_clock::now().time_since_epoch());
}

DispSyncSource::~DispSyncSource() = default;

void DispSyncSource::setVSyncEnabled(bool enable) {
    std::lock_guard lock(mVsyncMutex);
    if (enable) {
        mCallbackRepeater->start(mWorkDuration, mReadyDuration);
        // ATRACE_INT(mVsyncOnLabel.c_str(), 1);
    } else {
        mCallbackRepeater->stop();
        // ATRACE_INT(mVsyncOnLabel.c_str(), 0);
    }
    mEnabled = enable;
}

void DispSyncSource::setCallback(VSyncSource::Callback* callback) {
    std::lock_guard lock(mCallbackMutex);
    mCallback = callback;
}

void DispSyncSource::setDuration(std::chrono::nanoseconds workDuration,
                                 std::chrono::nanoseconds readyDuration) {
    std::lock_guard lock(mVsyncMutex);
    mWorkDuration = workDuration;
    mReadyDuration = readyDuration;

    // If we're not enabled, we don't need to mess with the listeners
    if (!mEnabled) {
        return;
    }

    mCallbackRepeater->start(mWorkDuration, mReadyDuration);
}

void DispSyncSource::onVsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime,
                                     nsecs_t readyTime) {
    VSyncSource::Callback* callback;
    {
        std::lock_guard lock(mCallbackMutex);
        callback = mCallback;
    }

    if (mTraceVsync) {
        mValue = (mValue + 1) % 2;
    }

    if (callback != nullptr) {
        callback->onVSyncEvent(targetWakeupTime, {vsyncTime, readyTime});
    }
}

VSyncSource::VSyncData DispSyncSource::getLatestVSyncData() const {
    std::lock_guard lock(mVsyncMutex);
    nsecs_t expectedPresentationTime = mVSyncTracker.nextAnticipatedVSyncTimeFrom(
            systemTime() + mWorkDuration.get().count() + mReadyDuration.count());
    nsecs_t deadline = expectedPresentationTime - mReadyDuration.count();
    return {expectedPresentationTime, deadline};
}

void DispSyncSource::dump(std::string& result) const {
    std::lock_guard lock(mVsyncMutex);
    StringAppendF(&result, "DispSyncSource: %s(%s)\n", mName, mEnabled ? "enabled" : "disabled");
}

} // namespace android::scheduler
+0 −69
Original line number Diff line number Diff line
/*
 * Copyright 2018 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 <mutex>
#include <string>

#include "EventThread.h"
#include "TracedOrdinal.h"
#include "VSyncDispatch.h"

namespace android::scheduler {
class CallbackRepeater;
class VSyncTracker;

class DispSyncSource final : public VSyncSource {
public:
    DispSyncSource(VSyncDispatch& vSyncDispatch, VSyncTracker& vSyncTracker,
                   std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration,
                   bool traceVsync, const char* name);

    ~DispSyncSource() override;

    // The following methods are implementation of VSyncSource.
    const char* getName() const override { return mName; }
    void setVSyncEnabled(bool enable) override;
    void setCallback(VSyncSource::Callback* callback) override;
    void setDuration(std::chrono::nanoseconds workDuration,
                     std::chrono::nanoseconds readyDuration) override;
    VSyncData getLatestVSyncData() const override;

    void dump(std::string&) const override;

private:
    void onVsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime, nsecs_t readyTime);

    const char* const mName;
    TracedOrdinal<int> mValue;

    const bool mTraceVsync;
    const std::string mVsyncOnLabel;

    const VSyncTracker& mVSyncTracker;

    std::unique_ptr<CallbackRepeater> mCallbackRepeater;

    std::mutex mCallbackMutex;
    VSyncSource::Callback* mCallback GUARDED_BY(mCallbackMutex) = nullptr;

    mutable std::mutex mVsyncMutex;
    TracedOrdinal<std::chrono::nanoseconds> mWorkDuration GUARDED_BY(mVsyncMutex);
    std::chrono::nanoseconds mReadyDuration GUARDED_BY(mVsyncMutex);
    bool mEnabled GUARDED_BY(mVsyncMutex) = false;
};

} // namespace android::scheduler
+57 −42
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#include <cstdint>
#include <optional>
#include <type_traits>
#include <utility>

#include <android-base/stringprintf.h>

@@ -43,6 +44,8 @@

#include "DisplayHardware/DisplayMode.h"
#include "FrameTimeline.h"
#include "VSyncDispatch.h"
#include "VSyncTracker.h"

#include "EventThread.h"

@@ -235,20 +238,29 @@ EventThread::~EventThread() = default;

namespace impl {

EventThread::EventThread(std::unique_ptr<VSyncSource> vsyncSource,
EventThread::EventThread(const char* name, scheduler::VsyncSchedule& vsyncSchedule,
                         android::frametimeline::TokenManager* tokenManager,
                         ThrottleVsyncCallback throttleVsyncCallback,
                         GetVsyncPeriodFunction getVsyncPeriodFunction)
      : mVSyncSource(std::move(vsyncSource)),
                         GetVsyncPeriodFunction getVsyncPeriodFunction,
                         std::chrono::nanoseconds workDuration,
                         std::chrono::nanoseconds readyDuration)
      : mThreadName(name),
        mVsyncTracer(base::StringPrintf("VSYNC-%s", name), 0),
        mWorkDuration(base::StringPrintf("VsyncWorkDuration-%s", name), workDuration),
        mReadyDuration(readyDuration),
        mVsyncSchedule(vsyncSchedule),
        mVsyncRegistration(
                vsyncSchedule.getDispatch(),
                [this](nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
                    onVsync(vsyncTime, wakeupTime, readyTime);
                },
                name),
        mTokenManager(tokenManager),
        mThrottleVsyncCallback(std::move(throttleVsyncCallback)),
        mGetVsyncPeriodFunction(std::move(getVsyncPeriodFunction)),
        mThreadName(mVSyncSource->getName()) {
        mGetVsyncPeriodFunction(std::move(getVsyncPeriodFunction)) {
    LOG_ALWAYS_FATAL_IF(getVsyncPeriodFunction == nullptr,
            "getVsyncPeriodFunction must not be null");

    mVSyncSource->setCallback(this);

    mThread = std::thread([this]() NO_THREAD_SAFETY_ANALYSIS {
        std::unique_lock<std::mutex> lock(mMutex);
        threadMain(lock);
@@ -270,8 +282,6 @@ EventThread::EventThread(std::unique_ptr<VSyncSource> vsyncSource,
}

EventThread::~EventThread() {
    mVSyncSource->setCallback(nullptr);

    {
        std::lock_guard<std::mutex> lock(mMutex);
        mState = State::Quit;
@@ -283,7 +293,12 @@ EventThread::~EventThread() {
void EventThread::setDuration(std::chrono::nanoseconds workDuration,
                              std::chrono::nanoseconds readyDuration) {
    std::lock_guard<std::mutex> lock(mMutex);
    mVSyncSource->setDuration(workDuration, readyDuration);
    mWorkDuration = workDuration;
    mReadyDuration = readyDuration;

    mVsyncRegistration.update({.workDuration = mWorkDuration.get().count(),
                               .readyDuration = mReadyDuration.count(),
                               .earliestVsync = mLastVsyncCallbackTime.ns()});
}

sp<EventThreadConnection> EventThread::createEventConnection(
@@ -358,13 +373,14 @@ VsyncEventData EventThread::getLatestVsyncEventData(
    VsyncEventData vsyncEventData;
    nsecs_t frameInterval = mGetVsyncPeriodFunction(connection->mOwnerUid);
    vsyncEventData.frameInterval = frameInterval;
    VSyncSource::VSyncData vsyncData;
    {
    const auto [presentTime, deadline] = [&]() -> std::pair<nsecs_t, nsecs_t> {
        std::lock_guard<std::mutex> lock(mMutex);
        vsyncData = mVSyncSource->getLatestVSyncData();
    }
        const auto vsyncTime = mVsyncSchedule.getTracker().nextAnticipatedVSyncTimeFrom(
                systemTime() + mWorkDuration.get().count() + mReadyDuration.count());
        return {vsyncTime, vsyncTime - mReadyDuration.count()};
    }();
    generateFrameTimeline(vsyncEventData, frameInterval, systemTime(SYSTEM_TIME_MONOTONIC),
                          vsyncData.expectedPresentationTime, vsyncData.deadlineTimestamp);
                          presentTime, deadline);
    return vsyncEventData;
}

@@ -388,13 +404,14 @@ void EventThread::onScreenAcquired() {
    mCondition.notify_all();
}

void EventThread::onVSyncEvent(nsecs_t timestamp, VSyncSource::VSyncData vsyncData) {
void EventThread::onVsync(nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
    std::lock_guard<std::mutex> lock(mMutex);
    mLastVsyncCallbackTime = TimePoint::fromNs(vsyncTime);

    LOG_FATAL_IF(!mVSyncState);
    mPendingEvents.push_back(makeVSync(mVSyncState->displayId, timestamp, ++mVSyncState->count,
                                       vsyncData.expectedPresentationTime,
                                       vsyncData.deadlineTimestamp));
    mVsyncTracer = (mVsyncTracer + 1) % 2;
    mPendingEvents.push_back(makeVSync(mVSyncState->displayId, wakeupTime, ++mVSyncState->count,
                                       vsyncTime, readyTime));
    mCondition.notify_all();
}

@@ -456,12 +473,12 @@ void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {
        auto it = mDisplayEventConnections.begin();
        while (it != mDisplayEventConnections.end()) {
            if (const auto connection = it->promote()) {
                vsyncRequested |= connection->vsyncRequest != VSyncRequest::None;

                if (event && shouldConsumeEvent(*event, connection)) {
                    consumers.push_back(connection);
                }

                vsyncRequested |= connection->vsyncRequest != VSyncRequest::None;

                ++it;
            } else {
                it = mDisplayEventConnections.erase(it);
@@ -473,25 +490,24 @@ void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {
            consumers.clear();
        }

        State nextState;
        if (mVSyncState && vsyncRequested) {
            nextState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync;
            mState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync;
        } else {
            ALOGW_IF(!mVSyncState, "Ignoring VSYNC request while display is disconnected");
            nextState = State::Idle;
            mState = State::Idle;
        }

        if (mState != nextState) {
        if (mState == State::VSync) {
                mVSyncSource->setVSyncEnabled(false);
            } else if (nextState == State::VSync) {
                mVSyncSource->setVSyncEnabled(true);
            }

            mState = nextState;
            const auto scheduleResult =
                    mVsyncRegistration.schedule({.workDuration = mWorkDuration.get().count(),
                                                 .readyDuration = mReadyDuration.count(),
                                                 .earliestVsync = mLastVsyncCallbackTime.ns()});
            LOG_ALWAYS_FATAL_IF(!scheduleResult, "Error scheduling callback");
        } else {
            mVsyncRegistration.cancel();
        }

        if (event) {
        if (!mPendingEvents.empty()) {
            continue;
        }

@@ -506,15 +522,6 @@ void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {
            if (mCondition.wait_for(lock, timeout) == std::cv_status::timeout) {
                if (mState == State::VSync) {
                    ALOGW("Faking VSYNC due to driver stall for thread %s", mThreadName);
                    std::string debugInfo = "VsyncSource debug info:\n";
                    mVSyncSource->dump(debugInfo);
                    // Log the debug info line-by-line to avoid logcat overflow
                    auto pos = debugInfo.find('\n');
                    while (pos != std::string::npos) {
                        ALOGW("%s", debugInfo.substr(0, pos).c_str());
                        debugInfo = debugInfo.substr(pos + 1);
                        pos = debugInfo.find('\n');
                    }
                }

                LOG_FATAL_IF(!mVSyncState);
@@ -527,6 +534,8 @@ void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {
            }
        }
    }
    // cancel any pending vsync event before exiting
    mVsyncRegistration.cancel();
}

bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event,
@@ -657,6 +666,12 @@ void EventThread::dump(std::string& result) const {
        StringAppendF(&result, "none\n");
    }

    const auto relativeLastCallTime =
            ticks<std::milli, float>(mLastVsyncCallbackTime - TimePoint::now());
    StringAppendF(&result, "mWorkDuration=%.2f mReadyDuration=%.2f last vsync time ",
                  mWorkDuration.get().count() / 1e6f, mReadyDuration.count() / 1e6f);
    StringAppendF(&result, "%.2fms relative to now\n", relativeLastCallTime);

    StringAppendF(&result, "  pending events (count=%zu):\n", mPendingEvents.size());
    for (const auto& event : mPendingEvents) {
        StringAppendF(&result, "    %s\n", toString(event).c_str());
+15 −33
Original line number Diff line number Diff line
@@ -33,6 +33,9 @@
#include <vector>

#include "DisplayHardware/DisplayMode.h"
#include "TracedOrdinal.h"
#include "VSyncDispatch.h"
#include "VsyncSchedule.h"

// ---------------------------------------------------------------------------
namespace android {
@@ -64,32 +67,6 @@ enum class VSyncRequest {
    // Subsequent values are periods.
};

class VSyncSource {
public:
    class VSyncData {
    public:
        nsecs_t expectedPresentationTime;
        nsecs_t deadlineTimestamp;
    };

    class Callback {
    public:
        virtual ~Callback() {}
        virtual void onVSyncEvent(nsecs_t when, VSyncData vsyncData) = 0;
    };

    virtual ~VSyncSource() {}

    virtual const char* getName() const = 0;
    virtual void setVSyncEnabled(bool enable) = 0;
    virtual void setCallback(Callback* callback) = 0;
    virtual void setDuration(std::chrono::nanoseconds workDuration,
                             std::chrono::nanoseconds readyDuration) = 0;
    virtual VSyncData getLatestVSyncData() const = 0;

    virtual void dump(std::string& result) const = 0;
};

class EventThreadConnection : public gui::BnDisplayEventConnection {
public:
    EventThreadConnection(EventThread*, uid_t callingUid, ResyncCallback,
@@ -160,13 +137,14 @@ public:

namespace impl {

class EventThread : public android::EventThread, private VSyncSource::Callback {
class EventThread : public android::EventThread {
public:
    using ThrottleVsyncCallback = std::function<bool(nsecs_t, uid_t)>;
    using GetVsyncPeriodFunction = std::function<nsecs_t(uid_t)>;

    EventThread(std::unique_ptr<VSyncSource>, frametimeline::TokenManager*, ThrottleVsyncCallback,
                GetVsyncPeriodFunction);
    EventThread(const char* name, scheduler::VsyncSchedule&, frametimeline::TokenManager*,
                ThrottleVsyncCallback, GetVsyncPeriodFunction,
                std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration);
    ~EventThread();

    sp<EventThreadConnection> createEventConnection(
@@ -213,8 +191,7 @@ private:
    void removeDisplayEventConnectionLocked(const wp<EventThreadConnection>& connection)
            REQUIRES(mMutex);

    // Implements VSyncSource::Callback
    void onVSyncEvent(nsecs_t timestamp, VSyncSource::VSyncData vsyncData) override;
    void onVsync(nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime);

    int64_t generateToken(nsecs_t timestamp, nsecs_t deadlineTimestamp,
                          nsecs_t expectedPresentationTime) const;
@@ -222,12 +199,17 @@ private:
                               nsecs_t timestamp, nsecs_t preferredExpectedPresentationTime,
                               nsecs_t preferredDeadlineTimestamp) const;

    const std::unique_ptr<VSyncSource> mVSyncSource GUARDED_BY(mMutex);
    const char* const mThreadName;
    TracedOrdinal<int> mVsyncTracer;
    TracedOrdinal<std::chrono::nanoseconds> mWorkDuration GUARDED_BY(mMutex);
    std::chrono::nanoseconds mReadyDuration GUARDED_BY(mMutex);
    scheduler::VsyncSchedule& mVsyncSchedule;
    TimePoint mLastVsyncCallbackTime GUARDED_BY(mMutex) = TimePoint::now();
    scheduler::VSyncCallbackRegistration mVsyncRegistration GUARDED_BY(mMutex);
    frametimeline::TokenManager* const mTokenManager;

    const ThrottleVsyncCallback mThrottleVsyncCallback;
    const GetVsyncPeriodFunction mGetVsyncPeriodFunction;
    const char* const mThreadName;

    std::thread mThread;
    mutable std::mutex mMutex;
Loading