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

Commit ba75fbf7 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Create a VsyncSchedule per display"

parents 2efc751d 31d41415
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -93,7 +93,7 @@ public:
    MOCK_METHOD2(onHotplug,
    MOCK_METHOD2(onHotplug,
                 std::optional<DisplayIdentificationInfo>(hal::HWDisplayId, hal::Connection));
                 std::optional<DisplayIdentificationInfo>(hal::HWDisplayId, hal::Connection));
    MOCK_CONST_METHOD0(updatesDeviceProductInfoOnHotplugReconnect, bool());
    MOCK_CONST_METHOD0(updatesDeviceProductInfoOnHotplugReconnect, bool());
    MOCK_METHOD2(onVsync, bool(hal::HWDisplayId, int64_t));
    MOCK_METHOD(std::optional<PhysicalDisplayId>, onVsync, (hal::HWDisplayId, int64_t));
    MOCK_METHOD2(setVsyncEnabled, void(PhysicalDisplayId, hal::Vsync));
    MOCK_METHOD2(setVsyncEnabled, void(PhysicalDisplayId, hal::Vsync));
    MOCK_CONST_METHOD1(isConnected, bool(PhysicalDisplayId));
    MOCK_CONST_METHOD1(isConnected, bool(PhysicalDisplayId));
    MOCK_CONST_METHOD1(getModes, std::vector<HWComposer::HWCDisplayMode>(PhysicalDisplayId));
    MOCK_CONST_METHOD1(getModes, std::vector<HWComposer::HWCDisplayMode>(PhysicalDisplayId));
+12 −10
Original line number Original line Diff line number Diff line
@@ -30,6 +30,7 @@
#include <compositionengine/Output.h>
#include <compositionengine/Output.h>
#include <compositionengine/OutputLayer.h>
#include <compositionengine/OutputLayer.h>
#include <compositionengine/impl/OutputLayerCompositionState.h>
#include <compositionengine/impl/OutputLayerCompositionState.h>
#include <ftl/concat.h>
#include <log/log.h>
#include <log/log.h>
#include <ui/DebugUtils.h>
#include <ui/DebugUtils.h>
#include <ui/GraphicBuffer.h>
#include <ui/GraphicBuffer.h>
@@ -148,16 +149,17 @@ bool HWComposer::updatesDeviceProductInfoOnHotplugReconnect() const {
    return mUpdateDeviceProductInfoOnHotplugReconnect;
    return mUpdateDeviceProductInfoOnHotplugReconnect;
}
}


bool HWComposer::onVsync(hal::HWDisplayId hwcDisplayId, nsecs_t timestamp) {
std::optional<PhysicalDisplayId> HWComposer::onVsync(hal::HWDisplayId hwcDisplayId,
    const auto displayId = toPhysicalDisplayId(hwcDisplayId);
                                                     nsecs_t timestamp) {
    if (!displayId) {
    const auto displayIdOpt = toPhysicalDisplayId(hwcDisplayId);
    if (!displayIdOpt) {
        LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid HWC display");
        LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid HWC display");
        return false;
        return {};
    }
    }


    RETURN_IF_INVALID_DISPLAY(*displayId, false);
    RETURN_IF_INVALID_DISPLAY(*displayIdOpt, {});


    auto& displayData = mDisplayData[*displayId];
    auto& displayData = mDisplayData[*displayIdOpt];


    {
    {
        // There have been reports of HWCs that signal several vsync events
        // There have been reports of HWCs that signal several vsync events
@@ -166,18 +168,18 @@ bool HWComposer::onVsync(hal::HWDisplayId hwcDisplayId, nsecs_t timestamp) {
        // out here so they don't cause havoc downstream.
        // out here so they don't cause havoc downstream.
        if (timestamp == displayData.lastPresentTimestamp) {
        if (timestamp == displayData.lastPresentTimestamp) {
            ALOGW("Ignoring duplicate VSYNC event from HWC for display %s (t=%" PRId64 ")",
            ALOGW("Ignoring duplicate VSYNC event from HWC for display %s (t=%" PRId64 ")",
                  to_string(*displayId).c_str(), timestamp);
                  to_string(*displayIdOpt).c_str(), timestamp);
            return false;
            return {};
        }
        }


        displayData.lastPresentTimestamp = timestamp;
        displayData.lastPresentTimestamp = timestamp;
    }
    }


    const auto tag = "HW_VSYNC_" + to_string(*displayId);
    const ftl::Concat tag("HW_VSYNC_", displayIdOpt->value);
    ATRACE_INT(tag.c_str(), displayData.vsyncTraceToggle);
    ATRACE_INT(tag.c_str(), displayData.vsyncTraceToggle);
    displayData.vsyncTraceToggle = !displayData.vsyncTraceToggle;
    displayData.vsyncTraceToggle = !displayData.vsyncTraceToggle;


    return true;
    return displayIdOpt;
}
}


size_t HWComposer::getMaxVirtualDisplayCount() const {
size_t HWComposer::getMaxVirtualDisplayCount() const {
+5 −2
Original line number Original line Diff line number Diff line
@@ -221,7 +221,10 @@ public:
    // TODO(b/157555476): Remove when the framework has proper support for headless mode
    // TODO(b/157555476): Remove when the framework has proper support for headless mode
    virtual bool updatesDeviceProductInfoOnHotplugReconnect() const = 0;
    virtual bool updatesDeviceProductInfoOnHotplugReconnect() const = 0;


    virtual bool onVsync(hal::HWDisplayId, nsecs_t timestamp) = 0;
    // Called when a vsync happens. If the vsync is valid, returns the
    // corresponding PhysicalDisplayId. Otherwise returns nullopt.
    virtual std::optional<PhysicalDisplayId> onVsync(hal::HWDisplayId, nsecs_t timestamp) = 0;

    virtual void setVsyncEnabled(PhysicalDisplayId, hal::Vsync enabled) = 0;
    virtual void setVsyncEnabled(PhysicalDisplayId, hal::Vsync enabled) = 0;


    virtual bool isConnected(PhysicalDisplayId) const = 0;
    virtual bool isConnected(PhysicalDisplayId) const = 0;
@@ -402,7 +405,7 @@ public:


    bool updatesDeviceProductInfoOnHotplugReconnect() const override;
    bool updatesDeviceProductInfoOnHotplugReconnect() const override;


    bool onVsync(hal::HWDisplayId, nsecs_t timestamp) override;
    std::optional<PhysicalDisplayId> onVsync(hal::HWDisplayId, nsecs_t timestamp) override;
    void setVsyncEnabled(PhysicalDisplayId, hal::Vsync enabled) override;
    void setVsyncEnabled(PhysicalDisplayId, hal::Vsync enabled) override;


    bool isConnected(PhysicalDisplayId) const override;
    bool isConnected(PhysicalDisplayId) const override;
+40 −26
Original line number Original line Diff line number Diff line
@@ -238,29 +238,19 @@ EventThread::~EventThread() = default;


namespace impl {
namespace impl {


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

    mThread = std::thread([this]() NO_THREAD_SAFETY_ANALYSIS {
    mThread = std::thread([this]() NO_THREAD_SAFETY_ANALYSIS {
        std::unique_lock<std::mutex> lock(mMutex);
        std::unique_lock<std::mutex> lock(mMutex);
        threadMain(lock);
        threadMain(lock);
@@ -371,16 +361,16 @@ VsyncEventData EventThread::getLatestVsyncEventData(
    }
    }


    VsyncEventData vsyncEventData;
    VsyncEventData vsyncEventData;
    nsecs_t frameInterval = mGetVsyncPeriodFunction(connection->mOwnerUid);
    const Fps frameInterval = mEventThreadCallback.getLeaderRenderFrameRate(connection->mOwnerUid);
    vsyncEventData.frameInterval = frameInterval;
    vsyncEventData.frameInterval = frameInterval.getPeriodNsecs();
    const auto [presentTime, deadline] = [&]() -> std::pair<nsecs_t, nsecs_t> {
    const auto [presentTime, deadline] = [&]() -> std::pair<nsecs_t, nsecs_t> {
        std::lock_guard<std::mutex> lock(mMutex);
        std::lock_guard<std::mutex> lock(mMutex);
        const auto vsyncTime = mVsyncSchedule.getTracker().nextAnticipatedVSyncTimeFrom(
        const auto vsyncTime = mVsyncSchedule->getTracker().nextAnticipatedVSyncTimeFrom(
                systemTime() + mWorkDuration.get().count() + mReadyDuration.count());
                systemTime() + mWorkDuration.get().count() + mReadyDuration.count());
        return {vsyncTime, vsyncTime - mReadyDuration.count()};
        return {vsyncTime, vsyncTime - mReadyDuration.count()};
    }();
    }();
    generateFrameTimeline(vsyncEventData, frameInterval, systemTime(SYSTEM_TIME_MONOTONIC),
    generateFrameTimeline(vsyncEventData, frameInterval.getPeriodNsecs(),
                          presentTime, deadline);
                          systemTime(SYSTEM_TIME_MONOTONIC), presentTime, deadline);
    return vsyncEventData;
    return vsyncEventData;
}
}


@@ -541,8 +531,10 @@ void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {
bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event,
bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event,
                                     const sp<EventThreadConnection>& connection) const {
                                     const sp<EventThreadConnection>& connection) const {
    const auto throttleVsync = [&] {
    const auto throttleVsync = [&] {
        return mThrottleVsyncCallback &&
        const auto& vsyncData = event.vsync.vsyncData;
                mThrottleVsyncCallback(event.vsync.vsyncData.preferredExpectedPresentationTime(),
        const auto expectedPresentTime =
                TimePoint::fromNs(vsyncData.preferredExpectedPresentationTime());
        return !mEventThreadCallback.isVsyncTargetForUid(expectedPresentTime,
                                                         connection->mOwnerUid);
                                                         connection->mOwnerUid);
    };
    };


@@ -631,9 +623,11 @@ void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event,
    for (const auto& consumer : consumers) {
    for (const auto& consumer : consumers) {
        DisplayEventReceiver::Event copy = event;
        DisplayEventReceiver::Event copy = event;
        if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
        if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
            const int64_t frameInterval = mGetVsyncPeriodFunction(consumer->mOwnerUid);
            const Fps frameInterval =
            copy.vsync.vsyncData.frameInterval = frameInterval;
                    mEventThreadCallback.getLeaderRenderFrameRate(consumer->mOwnerUid);
            generateFrameTimeline(copy.vsync.vsyncData, frameInterval, copy.header.timestamp,
            copy.vsync.vsyncData.frameInterval = frameInterval.getPeriodNsecs();
            generateFrameTimeline(copy.vsync.vsyncData, frameInterval.getPeriodNsecs(),
                                  copy.header.timestamp,
                                  event.vsync.vsyncData.preferredExpectedPresentationTime(),
                                  event.vsync.vsyncData.preferredExpectedPresentationTime(),
                                  event.vsync.vsyncData.preferredDeadlineTimestamp());
                                  event.vsync.vsyncData.preferredDeadlineTimestamp());
        }
        }
@@ -699,6 +693,26 @@ const char* EventThread::toCString(State state) {
    }
    }
}
}


void EventThread::onNewVsyncSchedule(std::shared_ptr<scheduler::VsyncSchedule> schedule) {
    std::lock_guard<std::mutex> lock(mMutex);
    const bool reschedule = mVsyncRegistration.cancel() == scheduler::CancelResult::Cancelled;
    mVsyncSchedule = std::move(schedule);
    mVsyncRegistration =
            scheduler::VSyncCallbackRegistration(mVsyncSchedule->getDispatch(),
                                                 createDispatchCallback(), mThreadName);
    if (reschedule) {
        mVsyncRegistration.schedule({.workDuration = mWorkDuration.get().count(),
                                     .readyDuration = mReadyDuration.count(),
                                     .earliestVsync = mLastVsyncCallbackTime.ns()});
    }
}

scheduler::VSyncDispatch::Callback EventThread::createDispatchCallback() {
    return [this](nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
        onVsync(vsyncTime, wakeupTime, readyTime);
    };
}

} // namespace impl
} // namespace impl
} // namespace android
} // namespace android


+22 −9
Original line number Original line Diff line number Diff line
@@ -23,6 +23,7 @@
#include <sys/types.h>
#include <sys/types.h>
#include <utils/Errors.h>
#include <utils/Errors.h>


#include <scheduler/Fps.h>
#include <scheduler/FrameRateMode.h>
#include <scheduler/FrameRateMode.h>
#include <condition_variable>
#include <condition_variable>
#include <cstdint>
#include <cstdint>
@@ -67,6 +68,15 @@ enum class VSyncRequest {
    // Subsequent values are periods.
    // Subsequent values are periods.
};
};


class IEventThreadCallback {
public:
    virtual ~IEventThreadCallback() = default;

    virtual bool isVsyncTargetForUid(TimePoint expectedVsyncTime, uid_t uid) const = 0;

    virtual Fps getLeaderRenderFrameRate(uid_t uid) const = 0;
};

class EventThreadConnection : public gui::BnDisplayEventConnection {
class EventThreadConnection : public gui::BnDisplayEventConnection {
public:
public:
    EventThreadConnection(EventThread*, uid_t callingUid, ResyncCallback,
    EventThreadConnection(EventThread*, uid_t callingUid, ResyncCallback,
@@ -133,18 +143,17 @@ public:


    // Retrieves the number of event connections tracked by this EventThread.
    // Retrieves the number of event connections tracked by this EventThread.
    virtual size_t getEventThreadConnectionCount() = 0;
    virtual size_t getEventThreadConnectionCount() = 0;

    virtual void onNewVsyncSchedule(std::shared_ptr<scheduler::VsyncSchedule>) = 0;
};
};


namespace impl {
namespace impl {


class EventThread : public android::EventThread {
class EventThread : public android::EventThread {
public:
public:
    using ThrottleVsyncCallback = std::function<bool(nsecs_t, uid_t)>;
    EventThread(const char* name, std::shared_ptr<scheduler::VsyncSchedule>, IEventThreadCallback&,
    using GetVsyncPeriodFunction = std::function<nsecs_t(uid_t)>;
                frametimeline::TokenManager*, std::chrono::nanoseconds workDuration,

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


    sp<EventThreadConnection> createEventConnection(
    sp<EventThreadConnection> createEventConnection(
@@ -176,6 +185,8 @@ public:


    size_t getEventThreadConnectionCount() override;
    size_t getEventThreadConnectionCount() override;


    void onNewVsyncSchedule(std::shared_ptr<scheduler::VsyncSchedule>) override;

private:
private:
    friend EventThreadTest;
    friend EventThreadTest;


@@ -199,17 +210,19 @@ private:
                               nsecs_t timestamp, nsecs_t preferredExpectedPresentationTime,
                               nsecs_t timestamp, nsecs_t preferredExpectedPresentationTime,
                               nsecs_t preferredDeadlineTimestamp) const;
                               nsecs_t preferredDeadlineTimestamp) const;


    scheduler::VSyncDispatch::Callback createDispatchCallback();

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


    const ThrottleVsyncCallback mThrottleVsyncCallback;
    // mEventThreadCallback will outlive the EventThread.
    const GetVsyncPeriodFunction mGetVsyncPeriodFunction;
    IEventThreadCallback& mEventThreadCallback;


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