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

Commit bb395fa1 authored by Dominik Laskowski's avatar Dominik Laskowski Committed by Android (Google) Code Review
Browse files

Merge "SF: Fix VSYNC injection"

parents ac146663 208235ce
Loading
Loading
Loading
Loading
+40 −24
Original line number Diff line number Diff line
@@ -69,17 +69,33 @@ void MessageQueue::init(const sp<SurfaceFlinger>& flinger) {

// TODO(b/169865816): refactor VSyncInjections to use MessageQueue directly
// and remove the EventThread from MessageQueue
void MessageQueue::setEventConnection(const sp<EventThreadConnection>& connection) {
    if (mEventTube.getFd() >= 0) {
        mLooper->removeFd(mEventTube.getFd());
void MessageQueue::setInjector(sp<EventThreadConnection> connection) {
    auto& tube = mInjector.tube;

    if (const int fd = tube.getFd(); fd >= 0) {
        mLooper->removeFd(fd);
    }

    mEvents = connection;
    if (mEvents) {
        mEvents->stealReceiveChannel(&mEventTube);
        mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT, MessageQueue::cb_eventReceiver,
    if (connection) {
        // The EventThreadConnection is retained when disabling injection, so avoid subsequently
        // stealing invalid FDs. Note that the stolen FDs are kept open.
        if (tube.getFd() < 0) {
            connection->stealReceiveChannel(&tube);
        } else {
            ALOGW("Recycling channel for VSYNC injection.");
        }

        mLooper->addFd(
                tube.getFd(), 0, Looper::EVENT_INPUT,
                [](int, int, void* data) {
                    reinterpret_cast<MessageQueue*>(data)->injectorCallback();
                    return 1; // Keep registration.
                },
                this);
    }

    std::lock_guard lock(mInjector.mutex);
    mInjector.connection = std::move(connection);
}

void MessageQueue::vsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime, nsecs_t readyTime) {
@@ -149,29 +165,31 @@ void MessageQueue::postMessage(sp<MessageHandler>&& handler) {

void MessageQueue::invalidate() {
    ATRACE_CALL();
    if (mEvents) {
        mEvents->requestNextVsync();
    } else {

    {
        std::lock_guard lock(mInjector.mutex);
        if (CC_UNLIKELY(mInjector.connection)) {
            ALOGD("%s while injecting VSYNC", __FUNCTION__);
            mInjector.connection->requestNextVsync();
            return;
        }
    }

    std::lock_guard lock(mVsync.mutex);
    mVsync.mScheduled = true;
        mVsync.registration->schedule({mVsync.workDuration.get().count(), /*readyDuration=*/0,
                                       mVsync.lastCallbackTime.count()});
    }
    mVsync.registration->schedule({.workDuration = mVsync.workDuration.get().count(),
                                   .readyDuration = 0,
                                   .earliestVsync = mVsync.lastCallbackTime.count()});
}

void MessageQueue::refresh() {
    mHandler->dispatchRefresh();
}

int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {
    MessageQueue* queue = reinterpret_cast<MessageQueue*>(data);
    return queue->eventReceiver(fd, events);
}

int MessageQueue::eventReceiver(int /*fd*/, int /*events*/) {
void MessageQueue::injectorCallback() {
    ssize_t n;
    DisplayEventReceiver::Event buffer[8];
    while ((n = DisplayEventReceiver::getEvents(&mEventTube, buffer, 8)) > 0) {
    while ((n = DisplayEventReceiver::getEvents(&mInjector.tube, buffer, 8)) > 0) {
        for (int i = 0; i < n; i++) {
            if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
                mHandler->dispatchInvalidate(buffer[i].vsync.vsyncId,
@@ -180,8 +198,6 @@ int MessageQueue::eventReceiver(int /*fd*/, int /*events*/) {
            }
        }
    }
    return 1;
}

} // namespace android::impl
+13 −10
Original line number Diff line number Diff line
@@ -21,12 +21,11 @@
#include <type_traits>
#include <utility>

#include <utils/Looper.h>
#include <utils/Timers.h>
#include <utils/threads.h>

#include <android-base/thread_annotations.h>
#include <gui/IDisplayEventConnection.h>
#include <private/gui/BitTube.h>
#include <utils/Looper.h>
#include <utils/Timers.h>

#include "EventThread.h"
#include "TracedOrdinal.h"
@@ -68,7 +67,7 @@ public:
    virtual void initVsync(scheduler::VSyncDispatch&, frametimeline::TokenManager&,
                           std::chrono::nanoseconds workDuration) = 0;
    virtual void setDuration(std::chrono::nanoseconds workDuration) = 0;
    virtual void setEventConnection(const sp<EventThreadConnection>& connection) = 0;
    virtual void setInjector(sp<EventThreadConnection>) = 0;
    virtual void waitMessage() = 0;
    virtual void postMessage(sp<MessageHandler>&&) = 0;
    virtual void invalidate() = 0;
@@ -99,7 +98,6 @@ protected:

    sp<SurfaceFlinger> mFlinger;
    sp<Looper> mLooper;
    sp<EventThreadConnection> mEvents;

    struct Vsync {
        frametimeline::TokenManager* tokenManager = nullptr;
@@ -113,14 +111,19 @@ protected:
        TracedOrdinal<int> value = {"VSYNC-sf", 0};
    };

    struct Injector {
        gui::BitTube tube;
        std::mutex mutex;
        sp<EventThreadConnection> connection GUARDED_BY(mutex);
    };

    Vsync mVsync;
    Injector mInjector;

    gui::BitTube mEventTube;
    sp<Handler> mHandler;

    static int cb_eventReceiver(int fd, int events, void* data);
    int eventReceiver(int fd, int events);
    void vsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime, nsecs_t readyTime);
    void injectorCallback();

public:
    ~MessageQueue() override = default;
@@ -128,7 +131,7 @@ public:
    void initVsync(scheduler::VSyncDispatch&, frametimeline::TokenManager&,
                   std::chrono::nanoseconds workDuration) override;
    void setDuration(std::chrono::nanoseconds workDuration) override;
    void setEventConnection(const sp<EventThreadConnection>& connection) override;
    void setInjector(sp<EventThreadConnection>) override;

    void waitMessage() override;
    void postMessage(sp<MessageHandler>&&) override;
+4 −0
Original line number Diff line number Diff line
@@ -436,6 +436,10 @@ Scheduler::ConnectionHandle Scheduler::enableVSyncInjection(bool enable) {
                                                    impl::EventThread::InterceptVSyncsCallback(),
                                                    impl::EventThread::ThrottleVsyncCallback());

        // EventThread does not dispatch VSYNC unless the display is connected and powered on.
        eventThread->onHotplugReceived(PhysicalDisplayId::fromPort(0), true);
        eventThread->onScreenAcquired();

        mInjectorConnectionHandle = createConnection(std::move(eventThread));
    }

+1 −2
Original line number Diff line number Diff line
@@ -1431,8 +1431,7 @@ status_t SurfaceFlinger::enableVSyncInjections(bool enable) {
        Mutex::Autolock lock(mStateLock);

        if (const auto handle = mScheduler->enableVSyncInjection(enable)) {
            mEventQueue->setEventConnection(enable ? mScheduler->getEventConnection(handle)
                                                   : nullptr);
            mEventQueue->setInjector(enable ? mScheduler->getEventConnection(handle) : nullptr);
        }
    }).wait();

+1 −0
Original line number Diff line number Diff line
@@ -907,6 +907,7 @@ void FakeComposerClient::onSurfaceFlingerStart() {
}

void FakeComposerClient::onSurfaceFlingerStop() {
    mSurfaceComposer->enableVSyncInjections(false);
    mSurfaceComposer->dispose();
    mSurfaceComposer.clear();
}
Loading