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

Commit 55fa7272 authored by Ady Abraham's avatar Ady Abraham
Browse files

SurfaceFlinger: decouple EventThread from SF wakeup

Today we have two instances of EventThread:
1. 'app' - used to wake up Choreographer clients
2. 'sf' - used to wake up SF mian thead *and*
          Choreographer clients that uses sf instance

Now this creates an ambiguity when trying to reason about the expected
vsync time and deadline of 'sf' EventThread:
 - SF wakes up sfWorkDuration before a vsync and targets that vsync
 - Choreographer users wakes up with SF main thread but targets the
   vsync that happens after the next SF wakeup.

To resolve this ambiguity we are decoupling SF wakeup from 'sf'
EventThread. This means that Choreographer clients that uses 'sf'
instance will keep using the EventThread but SF will be waking up
directly by a callback with VSyncDispatch. This allows us to correct
the expected vsync and deadline for both.

Test: Interacting with the device and observe systraces
Test: new unit test added to SF suite
Bug: 166302754

Change-Id: I76d154029b4bc1902198074c33d38ff030c4601b
parent 97651d23
Loading
Loading
Loading
Loading
+7 −0
Original line number Original line Diff line number Diff line
@@ -39,6 +39,13 @@ struct TimelineItem {
    nsecs_t startTime;
    nsecs_t startTime;
    nsecs_t endTime;
    nsecs_t endTime;
    nsecs_t presentTime;
    nsecs_t presentTime;

    bool operator==(const TimelineItem& other) const {
        return startTime == other.startTime && endTime == other.endTime &&
                presentTime == other.presentTime;
    }

    bool operator!=(const TimelineItem& other) const { return !(*this == other); }
};
};


/*
/*
+55 −9
Original line number Original line Diff line number Diff line
@@ -14,9 +14,7 @@
 * limitations under the License.
 * limitations under the License.
 */
 */


// TODO(b/129481165): remove the #pragma below and fix conversion issues
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"


#include <binder/IPCThreadState.h>
#include <binder/IPCThreadState.h>


@@ -28,6 +26,7 @@
#include <gui/IDisplayEventConnection.h>
#include <gui/IDisplayEventConnection.h>


#include "EventThread.h"
#include "EventThread.h"
#include "FrameTimeline.h"
#include "MessageQueue.h"
#include "MessageQueue.h"
#include "SurfaceFlinger.h"
#include "SurfaceFlinger.h"


@@ -68,16 +67,54 @@ void MessageQueue::init(const sp<SurfaceFlinger>& flinger) {
    mHandler = new Handler(*this);
    mHandler = new Handler(*this);
}
}


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


    mEvents = connection;
    mEvents = connection;
    if (mEvents) {
        mEvents->stealReceiveChannel(&mEventTube);
        mEvents->stealReceiveChannel(&mEventTube);
        mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT, MessageQueue::cb_eventReceiver,
        mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT, MessageQueue::cb_eventReceiver,
                       this);
                       this);
    }
    }
}

void MessageQueue::vsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime, nsecs_t readyTime) {
    ATRACE_CALL();
    // Trace VSYNC-sf
    mVsync.value = (mVsync.value + 1) % 2;

    {
        std::lock_guard lock(mVsync.mutex);
        mVsync.lastCallbackTime = std::chrono::nanoseconds(vsyncTime);
    }
    mHandler->dispatchInvalidate(mVsync.tokenManager->generateTokenForPredictions(
                                         {targetWakeupTime, readyTime, vsyncTime}),
                                 vsyncTime);
}

void MessageQueue::initVsync(scheduler::VSyncDispatch& dispatch,
                             frametimeline::TokenManager& tokenManager,
                             std::chrono::nanoseconds workDuration) {
    setDuration(workDuration);
    mVsync.tokenManager = &tokenManager;
    mVsync.registration = std::make_unique<
            scheduler::VSyncCallbackRegistration>(dispatch,
                                                  std::bind(&MessageQueue::vsyncCallback, this,
                                                            std::placeholders::_1,
                                                            std::placeholders::_2,
                                                            std::placeholders::_3),
                                                  "sf");
}

void MessageQueue::setDuration(std::chrono::nanoseconds workDuration) {
    ATRACE_CALL();
    std::lock_guard lock(mVsync.mutex);
    mVsync.workDuration = workDuration;
}


void MessageQueue::waitMessage() {
void MessageQueue::waitMessage() {
    do {
    do {
@@ -106,7 +143,18 @@ void MessageQueue::postMessage(sp<MessageHandler>&& handler) {
}
}


void MessageQueue::invalidate() {
void MessageQueue::invalidate() {
    ATRACE_CALL();
    if (mEvents) {
        mEvents->requestNextVsync();
        mEvents->requestNextVsync();
    } else {
        const auto [workDuration, lastVsyncCallback] = [&] {
            std::lock_guard lock(mVsync.mutex);
            std::chrono::nanoseconds mWorkDurationNanos = mVsync.workDuration;
            return std::make_pair(mWorkDurationNanos.count(), mVsync.lastCallbackTime.count());
        }();

        mVsync.registration->schedule({workDuration, /*readyDuration=*/0, lastVsyncCallback});
    }
}
}


void MessageQueue::refresh() {
void MessageQueue::refresh() {
@@ -135,5 +183,3 @@ int MessageQueue::eventReceiver(int /*fd*/, int /*events*/) {


} // namespace android::impl
} // namespace android::impl
// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic pop // ignored "-Wconversion"
+28 −4
Original line number Original line Diff line number Diff line
@@ -29,6 +29,8 @@
#include <private/gui/BitTube.h>
#include <private/gui/BitTube.h>


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


namespace android {
namespace android {


@@ -63,6 +65,9 @@ public:
    virtual ~MessageQueue() = default;
    virtual ~MessageQueue() = default;


    virtual void init(const sp<SurfaceFlinger>& flinger) = 0;
    virtual void init(const sp<SurfaceFlinger>& flinger) = 0;
    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 setEventConnection(const sp<EventThreadConnection>& connection) = 0;
    virtual void waitMessage() = 0;
    virtual void waitMessage() = 0;
    virtual void postMessage(sp<MessageHandler>&&) = 0;
    virtual void postMessage(sp<MessageHandler>&&) = 0;
@@ -74,7 +79,8 @@ public:


namespace impl {
namespace impl {


class MessageQueue final : public android::MessageQueue {
class MessageQueue : public android::MessageQueue {
protected:
    class Handler : public MessageHandler {
    class Handler : public MessageHandler {
        enum { eventMaskInvalidate = 0x1, eventMaskRefresh = 0x2, eventMaskTransaction = 0x4 };
        enum { eventMaskInvalidate = 0x1, eventMaskRefresh = 0x2, eventMaskTransaction = 0x4 };
        MessageQueue& mQueue;
        MessageQueue& mQueue;
@@ -84,9 +90,9 @@ class MessageQueue final : public android::MessageQueue {


    public:
    public:
        explicit Handler(MessageQueue& queue) : mQueue(queue), mEventMask(0) {}
        explicit Handler(MessageQueue& queue) : mQueue(queue), mEventMask(0) {}
        virtual void handleMessage(const Message& message);
        void handleMessage(const Message& message) override;
        void dispatchRefresh();
        virtual void dispatchRefresh();
        void dispatchInvalidate(int64_t vsyncId, nsecs_t expectedVSyncTimestamp);
        virtual void dispatchInvalidate(int64_t vsyncId, nsecs_t expectedVSyncTimestamp);
    };
    };


    friend class Handler;
    friend class Handler;
@@ -94,15 +100,33 @@ class MessageQueue final : public android::MessageQueue {
    sp<SurfaceFlinger> mFlinger;
    sp<SurfaceFlinger> mFlinger;
    sp<Looper> mLooper;
    sp<Looper> mLooper;
    sp<EventThreadConnection> mEvents;
    sp<EventThreadConnection> mEvents;

    struct Vsync {
        frametimeline::TokenManager* tokenManager = nullptr;
        std::unique_ptr<scheduler::VSyncCallbackRegistration> registration;

        std::mutex mutex;
        TracedOrdinal<std::chrono::nanoseconds> workDuration
                GUARDED_BY(mutex) = {"VsyncWorkDuration-sf", std::chrono::nanoseconds(0)};
        std::chrono::nanoseconds lastCallbackTime GUARDED_BY(mutex) = std::chrono::nanoseconds{0};
        TracedOrdinal<int> value = {"VSYNC-sf", 0};
    };

    Vsync mVsync;

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


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


public:
public:
    ~MessageQueue() override = default;
    ~MessageQueue() override = default;
    void init(const sp<SurfaceFlinger>& flinger) override;
    void init(const sp<SurfaceFlinger>& flinger) override;
    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 setEventConnection(const sp<EventThreadConnection>& connection) override;


    void waitMessage() override;
    void waitMessage() override;
+2 −0
Original line number Original line Diff line number Diff line
@@ -137,6 +137,8 @@ public:


    void setDisplayPowerState(bool normal);
    void setDisplayPowerState(bool normal);


    scheduler::VSyncDispatch& getVsyncDispatch() { return *mVsyncSchedule.dispatch; }

    void dump(std::string&) const;
    void dump(std::string&) const;
    void dump(ConnectionHandle, std::string&) const;
    void dump(ConnectionHandle, std::string&) const;
    void dumpVsync(std::string&) const;
    void dumpVsync(std::string&) const;
+7 −0
Original line number Original line Diff line number Diff line
@@ -94,6 +94,13 @@ public:
        nsecs_t workDuration = 0;
        nsecs_t workDuration = 0;
        nsecs_t readyDuration = 0;
        nsecs_t readyDuration = 0;
        nsecs_t earliestVsync = 0;
        nsecs_t earliestVsync = 0;

        bool operator==(const ScheduleTiming& other) const {
            return workDuration == other.workDuration && readyDuration == other.readyDuration &&
                    earliestVsync == other.earliestVsync;
        }

        bool operator!=(const ScheduleTiming& other) const { return !(*this == other); }
    };
    };


    /*
    /*
Loading