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

Commit 4babfc4e authored by Dominik Laskowski's avatar Dominik Laskowski
Browse files

SF: Remove ConnectionHandle concept in Scheduler

This abstraction never made sense, and only incurs pointless locking and
hash map lookups. This is a step toward replacing the two EventThreads
with a single EventDispatcher.

Start the Scheduler's timers after initialization. This solves the same
bug as Ib2617b914145bc4180cc7ca27203c59dbd625c94, which avoided crashes
without fixing the root cause of the race.

In a few cases, initScheduler indirectly calls Scheduler functions that
attempt EventThread dispatch before EventThread creation, so skip those
EventThread accesses using hasEventThreads for now. Further refactoring
will untangle circular dependencies and remove hasEventThreads.

Bug: 241285191
Bug: 241285945
Test: presubmit
Change-Id: I89b93b47540ab24bb5675edc79370f38bc48114f
parent 20b7ccbd
Loading
Loading
Loading
Loading
+41 −120
Original line number Diff line number Diff line
@@ -60,14 +60,6 @@
#include "VsyncController.h"
#include "VsyncSchedule.h"

#define RETURN_IF_INVALID_HANDLE(handle, ...)                        \
    do {                                                             \
        if (mConnections.count(handle) == 0) {                       \
            ALOGE("Invalid connection handle %" PRIuPTR, handle.id); \
            return __VA_ARGS__;                                      \
        }                                                            \
    } while (false)

namespace android::scheduler {

Scheduler::Scheduler(ICompositor& compositor, ISchedulerCallback& callback, FeatureFlags features,
@@ -344,8 +336,7 @@ void Scheduler::onExpectedPresentTimePosted(TimePoint expectedPresentTime) {
    }
}

ConnectionHandle Scheduler::createEventThread(Cycle cycle,
                                              frametimeline::TokenManager* tokenManager,
void Scheduler::createEventThread(Cycle cycle, frametimeline::TokenManager* tokenManager,
                                  std::chrono::nanoseconds workDuration,
                                  std::chrono::nanoseconds readyDuration) {
    auto eventThread =
@@ -353,31 +344,18 @@ ConnectionHandle Scheduler::createEventThread(Cycle cycle,
                                                         getVsyncSchedule(), tokenManager, *this,
                                                         workDuration, readyDuration);

    auto& handle = cycle == Cycle::Render ? mAppConnectionHandle : mSfConnectionHandle;
    handle = createConnection(std::move(eventThread));
    return handle;
    if (cycle == Cycle::Render) {
        mRenderEventThread = std::move(eventThread);
        mRenderEventConnection = mRenderEventThread->createEventConnection();
    } else {
        mLastCompositeEventThread = std::move(eventThread);
        mLastCompositeEventConnection = mLastCompositeEventThread->createEventConnection();
    }

ConnectionHandle Scheduler::createConnection(std::unique_ptr<EventThread> eventThread) {
    const ConnectionHandle handle = ConnectionHandle{mNextConnectionHandleId++};
    ALOGV("Creating a connection handle with ID %" PRIuPTR, handle.id);

    auto connection = eventThread->createEventConnection();

    std::lock_guard<std::mutex> lock(mConnectionsLock);
    mConnections.emplace(handle, Connection{connection, std::move(eventThread)});
    return handle;
}

sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection(
        ConnectionHandle handle, EventRegistrationFlags eventRegistration,
        const sp<IBinder>& layerHandle) {
    const auto connection = [&]() -> sp<EventThreadConnection> {
        std::scoped_lock lock(mConnectionsLock);
        RETURN_IF_INVALID_HANDLE(handle, nullptr);

        return mConnections[handle].thread->createEventConnection(eventRegistration);
    }();
        Cycle cycle, EventRegistrationFlags eventRegistration, const sp<IBinder>& layerHandle) {
    const auto connection = eventThreadFor(cycle).createEventConnection(eventRegistration);
    const auto layerId = static_cast<int32_t>(LayerHandle::getLayerId(layerHandle));

    if (layerId != static_cast<int32_t>(UNASSIGNED_LAYER_ID)) {
@@ -397,85 +375,48 @@ sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection(
    return connection;
}

sp<EventThreadConnection> Scheduler::getEventConnection(ConnectionHandle handle) {
    std::lock_guard<std::mutex> lock(mConnectionsLock);
    RETURN_IF_INVALID_HANDLE(handle, nullptr);
    return mConnections[handle].connection;
void Scheduler::onHotplugReceived(Cycle cycle, PhysicalDisplayId displayId, bool connected) {
    if (hasEventThreads()) {
        eventThreadFor(cycle).onHotplugReceived(displayId, connected);
    }

void Scheduler::onHotplugReceived(ConnectionHandle handle, PhysicalDisplayId displayId,
                                  bool connected) {
    android::EventThread* thread;
    {
        std::lock_guard<std::mutex> lock(mConnectionsLock);
        RETURN_IF_INVALID_HANDLE(handle);
        thread = mConnections[handle].thread.get();
}

    thread->onHotplugReceived(displayId, connected);
void Scheduler::onHotplugConnectionError(Cycle cycle, int32_t errorCode) {
    if (hasEventThreads()) {
        eventThreadFor(cycle).onHotplugConnectionError(errorCode);
    }

void Scheduler::onHotplugConnectionError(ConnectionHandle handle, int32_t errorCode) {
    android::EventThread* thread;
    {
        std::lock_guard<std::mutex> lock(mConnectionsLock);
        RETURN_IF_INVALID_HANDLE(handle);
        thread = mConnections[handle].thread.get();
    }

    thread->onHotplugConnectionError(errorCode);
}

void Scheduler::enableSyntheticVsync(bool enable) {
    // TODO(b/241285945): Remove connection handles.
    const ConnectionHandle handle = mAppConnectionHandle;
    android::EventThread* thread;
    {
        std::lock_guard<std::mutex> lock(mConnectionsLock);
        RETURN_IF_INVALID_HANDLE(handle);
        thread = mConnections[handle].thread.get();
    }
    thread->enableSyntheticVsync(enable);
    eventThreadFor(Cycle::Render).enableSyntheticVsync(enable);
}

void Scheduler::onFrameRateOverridesChanged(ConnectionHandle handle, PhysicalDisplayId displayId) {
void Scheduler::onFrameRateOverridesChanged(Cycle cycle, PhysicalDisplayId displayId) {
    const bool supportsFrameRateOverrideByContent =
            pacesetterSelectorPtr()->supportsAppFrameRateOverrideByContent();

    std::vector<FrameRateOverride> overrides =
            mFrameRateOverrideMappings.getAllFrameRateOverrides(supportsFrameRateOverrideByContent);

    android::EventThread* thread;
    {
        std::lock_guard lock(mConnectionsLock);
        RETURN_IF_INVALID_HANDLE(handle);
        thread = mConnections[handle].thread.get();
    }
    thread->onFrameRateOverridesChanged(displayId, std::move(overrides));
    eventThreadFor(cycle).onFrameRateOverridesChanged(displayId, std::move(overrides));
}

void Scheduler::onHdcpLevelsChanged(ConnectionHandle handle, PhysicalDisplayId displayId,
void Scheduler::onHdcpLevelsChanged(Cycle cycle, PhysicalDisplayId displayId,
                                    int32_t connectedLevel, int32_t maxLevel) {
    android::EventThread* thread;
    {
        std::lock_guard<std::mutex> lock(mConnectionsLock);
        RETURN_IF_INVALID_HANDLE(handle);
        thread = mConnections[handle].thread.get();
    }
    thread->onHdcpLevelsChanged(displayId, connectedLevel, maxLevel);
    eventThreadFor(cycle).onHdcpLevelsChanged(displayId, connectedLevel, maxLevel);
}

void Scheduler::onPrimaryDisplayModeChanged(ConnectionHandle handle, const FrameRateMode& mode) {
void Scheduler::onPrimaryDisplayModeChanged(Cycle cycle, const FrameRateMode& mode) {
    {
        std::lock_guard<std::mutex> lock(mPolicyLock);
        // Cache the last reported modes for primary display.
        mPolicy.cachedModeChangedParams = {handle, mode};
        mPolicy.cachedModeChangedParams = {cycle, mode};

        // Invalidate content based refresh rate selection so it could be calculated
        // again for the new refresh rate.
        mPolicy.contentRequirements.clear();
    }
    onNonPrimaryDisplayModeChanged(handle, mode);
    onNonPrimaryDisplayModeChanged(cycle, mode);
}

void Scheduler::dispatchCachedReportedMode() {
@@ -502,39 +443,25 @@ void Scheduler::dispatchCachedReportedMode() {
    }

    mPolicy.cachedModeChangedParams->mode = *mPolicy.modeOpt;
    onNonPrimaryDisplayModeChanged(mPolicy.cachedModeChangedParams->handle,
    onNonPrimaryDisplayModeChanged(mPolicy.cachedModeChangedParams->cycle,
                                   mPolicy.cachedModeChangedParams->mode);
}

void Scheduler::onNonPrimaryDisplayModeChanged(ConnectionHandle handle, const FrameRateMode& mode) {
    android::EventThread* thread;
    {
        std::lock_guard<std::mutex> lock(mConnectionsLock);
        RETURN_IF_INVALID_HANDLE(handle);
        thread = mConnections[handle].thread.get();
void Scheduler::onNonPrimaryDisplayModeChanged(Cycle cycle, const FrameRateMode& mode) {
    if (hasEventThreads()) {
        eventThreadFor(cycle).onModeChanged(mode);
    }
    thread->onModeChanged(mode);
}

void Scheduler::dump(ConnectionHandle handle, std::string& result) const {
    android::EventThread* thread;
    {
        std::lock_guard<std::mutex> lock(mConnectionsLock);
        RETURN_IF_INVALID_HANDLE(handle);
        thread = mConnections.at(handle).thread.get();
    }
    thread->dump(result);
void Scheduler::dump(Cycle cycle, std::string& result) const {
    eventThreadFor(cycle).dump(result);
}

void Scheduler::setDuration(ConnectionHandle handle, std::chrono::nanoseconds workDuration,
void Scheduler::setDuration(Cycle cycle, std::chrono::nanoseconds workDuration,
                            std::chrono::nanoseconds readyDuration) {
    android::EventThread* thread;
    {
        std::lock_guard<std::mutex> lock(mConnectionsLock);
        RETURN_IF_INVALID_HANDLE(handle);
        thread = mConnections[handle].thread.get();
    if (hasEventThreads()) {
        eventThreadFor(cycle).setDuration(workDuration, readyDuration);
    }
    thread->setDuration(workDuration, readyDuration);
}

void Scheduler::updatePhaseConfiguration(Fps refreshRate) {
@@ -557,10 +484,10 @@ void Scheduler::setActiveDisplayPowerModeForRefreshRateStats(hal::PowerMode powe
}

void Scheduler::setVsyncConfig(const VsyncConfig& config, Period vsyncPeriod) {
    setDuration(mAppConnectionHandle,
    setDuration(Cycle::Render,
                /* workDuration */ config.appWorkDuration,
                /* readyDuration */ config.sfWorkDuration);
    setDuration(mSfConnectionHandle,
    setDuration(Cycle::LastComposite,
                /* workDuration */ vsyncPeriod,
                /* readyDuration */ config.sfWorkDuration);
    setDuration(config.sfWorkDuration);
@@ -1027,16 +954,10 @@ std::shared_ptr<VsyncSchedule> Scheduler::promotePacesetterDisplayLocked(

void Scheduler::applyNewVsyncSchedule(std::shared_ptr<VsyncSchedule> vsyncSchedule) {
    onNewVsyncSchedule(vsyncSchedule->getDispatch());
    std::vector<android::EventThread*> threads;
    {
        std::lock_guard<std::mutex> lock(mConnectionsLock);
        threads.reserve(mConnections.size());
        for (auto& [_, connection] : mConnections) {
            threads.push_back(connection.thread.get());
        }
    }
    for (auto* thread : threads) {
        thread->onNewVsyncSchedule(vsyncSchedule);

    if (hasEventThreads()) {
        eventThreadFor(Cycle::Render).onNewVsyncSchedule(vsyncSchedule);
        eventThreadFor(Cycle::LastComposite).onNewVsyncSchedule(vsyncSchedule);
    }
}

+34 −62
Original line number Diff line number Diff line
@@ -56,35 +56,6 @@

#include <FrontEnd/LayerHierarchy.h>

namespace android::scheduler {

// Opaque handle to scheduler connection.
struct ConnectionHandle {
    using Id = std::uintptr_t;
    static constexpr Id INVALID_ID = static_cast<Id>(-1);

    Id id = INVALID_ID;

    explicit operator bool() const { return id != INVALID_ID; }
};

inline bool operator==(ConnectionHandle lhs, ConnectionHandle rhs) {
    return lhs.id == rhs.id;
}

} // namespace android::scheduler

namespace std {

template <>
struct hash<android::scheduler::ConnectionHandle> {
    size_t operator()(android::scheduler::ConnectionHandle handle) const {
        return hash<android::scheduler::ConnectionHandle::Id>()(handle.id);
    }
};

} // namespace std

namespace android {

class FenceTime;
@@ -106,6 +77,11 @@ class RefreshRateStats;
class VsyncConfiguration;
class VsyncSchedule;

enum class Cycle {
    Render,       // Surface rendering.
    LastComposite // Ahead of display compositing by one refresh period.
};

class Scheduler : public IEventThreadCallback, android::impl::MessageQueue {
    using Impl = android::impl::MessageQueue;

@@ -154,36 +130,32 @@ public:
        return std::move(future);
    }

    enum class Cycle {
        Render,       // Surface rendering.
        LastComposite // Ahead of display compositing by one refresh period.
    };

    ConnectionHandle createEventThread(Cycle, frametimeline::TokenManager*,
    void createEventThread(Cycle, frametimeline::TokenManager*,
                           std::chrono::nanoseconds workDuration,
                           std::chrono::nanoseconds readyDuration);

    sp<IDisplayEventConnection> createDisplayEventConnection(
            ConnectionHandle, EventRegistrationFlags eventRegistration = {},
            Cycle, EventRegistrationFlags eventRegistration = {},
            const sp<IBinder>& layerHandle = nullptr) EXCLUDES(mChoreographerLock);

    sp<EventThreadConnection> getEventConnection(ConnectionHandle);
    const sp<EventThreadConnection>& getEventConnection(Cycle cycle) const {
        return cycle == Cycle::Render ? mRenderEventConnection : mLastCompositeEventConnection;
    }

    void onHotplugReceived(ConnectionHandle, PhysicalDisplayId, bool connected);
    void onHotplugConnectionError(ConnectionHandle, int32_t errorCode);
    void onHotplugReceived(Cycle, PhysicalDisplayId, bool connected);
    void onHotplugConnectionError(Cycle, int32_t errorCode);

    void onPrimaryDisplayModeChanged(ConnectionHandle, const FrameRateMode&) EXCLUDES(mPolicyLock);
    void onNonPrimaryDisplayModeChanged(ConnectionHandle, const FrameRateMode&);
    void onPrimaryDisplayModeChanged(Cycle, const FrameRateMode&) EXCLUDES(mPolicyLock);
    void onNonPrimaryDisplayModeChanged(Cycle, const FrameRateMode&);

    void enableSyntheticVsync(bool = true) REQUIRES(kMainThreadContext);

    void onFrameRateOverridesChanged(ConnectionHandle, PhysicalDisplayId)
            EXCLUDES(mConnectionsLock);
    void onFrameRateOverridesChanged(Cycle, PhysicalDisplayId);

    void onHdcpLevelsChanged(ConnectionHandle, PhysicalDisplayId, int32_t, int32_t);
    void onHdcpLevelsChanged(Cycle, PhysicalDisplayId, int32_t, int32_t);

    // Modifies work duration in the event thread.
    void setDuration(ConnectionHandle, std::chrono::nanoseconds workDuration,
    void setDuration(Cycle, std::chrono::nanoseconds workDuration,
                     std::chrono::nanoseconds readyDuration);

    VsyncModulator& vsyncModulator() { return *mVsyncModulator; }
@@ -288,7 +260,7 @@ public:
    bool isVsyncInPhase(TimePoint expectedVsyncTime, Fps frameRate) const;

    void dump(utils::Dumper&) const;
    void dump(ConnectionHandle, std::string&) const;
    void dump(Cycle, std::string&) const;
    void dumpVsync(std::string&) const EXCLUDES(mDisplayLock);

    // Returns the preferred refresh rate and frame rate for the pacesetter display.
@@ -369,8 +341,15 @@ private:
    void onFrameSignal(ICompositor&, VsyncId, TimePoint expectedVsyncTime) override
            REQUIRES(kMainThreadContext, mDisplayLock);

    // Create a connection on the given EventThread.
    ConnectionHandle createConnection(std::unique_ptr<EventThread>);
    // Used to skip event dispatch before EventThread creation during boot.
    // TODO: b/241285191 - Reorder Scheduler initialization to avoid this.
    bool hasEventThreads() const {
        return CC_LIKELY(mRenderEventThread && mLastCompositeEventThread);
    }

    EventThread& eventThreadFor(Cycle cycle) const {
        return *(cycle == Cycle::Render ? mRenderEventThread : mLastCompositeEventThread);
    }

    // Update feature state machine to given state when corresponding timer resets or expires.
    void kernelIdleTimerCallback(TimerState) EXCLUDES(mDisplayLock);
@@ -460,18 +439,11 @@ private:
    void resync() override EXCLUDES(mDisplayLock);
    void onExpectedPresentTimePosted(TimePoint expectedPresentTime) override EXCLUDES(mDisplayLock);

    // Stores EventThread associated with a given VSyncSource, and an initial EventThreadConnection.
    struct Connection {
        sp<EventThreadConnection> connection;
        std::unique_ptr<EventThread> thread;
    };

    ConnectionHandle::Id mNextConnectionHandleId = 0;
    mutable std::mutex mConnectionsLock;
    std::unordered_map<ConnectionHandle, Connection> mConnections GUARDED_BY(mConnectionsLock);
    std::unique_ptr<EventThread> mRenderEventThread;
    sp<EventThreadConnection> mRenderEventConnection;

    ConnectionHandle mAppConnectionHandle;
    ConnectionHandle mSfConnectionHandle;
    std::unique_ptr<EventThread> mLastCompositeEventThread;
    sp<EventThreadConnection> mLastCompositeEventConnection;

    std::atomic<nsecs_t> mLastResyncTime = 0;

@@ -585,7 +557,7 @@ private:
        ftl::Optional<FrameRateMode> modeOpt;

        struct ModeChangedParams {
            ConnectionHandle handle;
            Cycle cycle;
            FrameRateMode mode;
        };

+35 −33
Original line number Diff line number Diff line
@@ -2092,12 +2092,11 @@ status_t SurfaceFlinger::getDisplayDecorationSupport(
sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection(
        gui::ISurfaceComposer::VsyncSource vsyncSource, EventRegistrationFlags eventRegistration,
        const sp<IBinder>& layerHandle) {
    const auto& handle =
            vsyncSource == gui::ISurfaceComposer::VsyncSource::eVsyncSourceSurfaceFlinger
            ? mSfConnectionHandle
            : mAppConnectionHandle;
    const auto cycle = vsyncSource == gui::ISurfaceComposer::VsyncSource::eVsyncSourceSurfaceFlinger
            ? scheduler::Cycle::LastComposite
            : scheduler::Cycle::Render;

    return mScheduler->createDisplayEventConnection(handle, eventRegistration, layerHandle);
    return mScheduler->createDisplayEventConnection(cycle, eventRegistration, layerHandle);
}

void SurfaceFlinger::scheduleCommit(FrameHint hint) {
@@ -2139,7 +2138,7 @@ void SurfaceFlinger::onComposerHalVsync(hal::HWDisplayId hwcDisplayId, int64_t t
            const int32_t hotplugErrorCode = static_cast<int32_t>(-timestamp);
            ALOGD("SurfaceFlinger got hotplugErrorCode=%d for display %" PRIu64, hotplugErrorCode,
                  hwcDisplayId);
            mScheduler->onHotplugConnectionError(mAppConnectionHandle, hotplugErrorCode);
            mScheduler->onHotplugConnectionError(scheduler::Cycle::Render, hotplugErrorCode);
            return;
        }

@@ -2190,7 +2189,7 @@ void SurfaceFlinger::onComposerHalHotplugEvent(hal::HWDisplayId hwcDisplayId,
    if (FlagManager::getInstance().hotplug2()) {
        ALOGD("SurfaceFlinger got hotplug event=%d", static_cast<int32_t>(event));
        // TODO(b/311403559): use enum type instead of int
        mScheduler->onHotplugConnectionError(mAppConnectionHandle, static_cast<int32_t>(event));
        mScheduler->onHotplugConnectionError(scheduler::Cycle::Render, static_cast<int32_t>(event));
    }
}

@@ -3480,7 +3479,7 @@ const char* SurfaceFlinger::processHotplug(PhysicalDisplayId displayId,
    if (!activeMode) {
        ALOGE("Failed to hotplug display %s", to_string(displayId).c_str());
        if (FlagManager::getInstance().hotplug2()) {
            mScheduler->onHotplugConnectionError(mAppConnectionHandle,
            mScheduler->onHotplugConnectionError(scheduler::Cycle::Render,
                                                 static_cast<int32_t>(
                                                         DisplayHotplugEvent::ERROR_UNKNOWN));
        }
@@ -3533,8 +3532,8 @@ const char* SurfaceFlinger::processHotplug(PhysicalDisplayId displayId,
}

void SurfaceFlinger::dispatchDisplayHotplugEvent(PhysicalDisplayId displayId, bool connected) {
    mScheduler->onHotplugReceived(mAppConnectionHandle, displayId, connected);
    mScheduler->onHotplugReceived(mSfConnectionHandle, displayId, connected);
    mScheduler->onHotplugReceived(scheduler::Cycle::Render, displayId, connected);
    mScheduler->onHotplugReceived(scheduler::Cycle::LastComposite, displayId, connected);
}

void SurfaceFlinger::dispatchDisplayModeChangeEvent(PhysicalDisplayId displayId,
@@ -3544,7 +3543,7 @@ void SurfaceFlinger::dispatchDisplayModeChangeEvent(PhysicalDisplayId displayId,
            ? &scheduler::Scheduler::onPrimaryDisplayModeChanged
            : &scheduler::Scheduler::onNonPrimaryDisplayModeChanged;

    ((*mScheduler).*onDisplayModeChanged)(mAppConnectionHandle, mode);
    ((*mScheduler).*onDisplayModeChanged)(scheduler::Cycle::Render, mode);
}

sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal(
@@ -4196,7 +4195,7 @@ void SurfaceFlinger::triggerOnFrameRateOverridesChanged() {
        return getDefaultDisplayDeviceLocked()->getPhysicalId();
    }();

    mScheduler->onFrameRateOverridesChanged(mAppConnectionHandle, displayId);
    mScheduler->onFrameRateOverridesChanged(scheduler::Cycle::Render, displayId);
}

void SurfaceFlinger::notifyCpuLoadUp() {
@@ -4361,21 +4360,19 @@ void SurfaceFlinger::initScheduler(const sp<const DisplayDevice>& display) {
    mScheduler = std::make_unique<Scheduler>(static_cast<ICompositor&>(*this),
                                             static_cast<ISchedulerCallback&>(*this), features,
                                             getFactory(), activeRefreshRate, *mTimeStats);

    // The pacesetter must be registered before EventThread creation below.
    mScheduler->registerDisplay(display->getPhysicalId(), display->holdRefreshRateSelector());
    if (FlagManager::getInstance().vrr_config()) {
        mScheduler->setRenderRate(display->getPhysicalId(), activeMode.fps);
    }
    mScheduler->startTimers();

    const auto configs = mScheduler->getVsyncConfiguration().getCurrentConfigs();

    mAppConnectionHandle =
            mScheduler->createEventThread(Scheduler::Cycle::Render,
                                          mFrameTimeline->getTokenManager(),
    mScheduler->createEventThread(scheduler::Cycle::Render, mFrameTimeline->getTokenManager(),
                                  /* workDuration */ configs.late.appWorkDuration,
                                  /* readyDuration */ configs.late.sfWorkDuration);
    mSfConnectionHandle =
            mScheduler->createEventThread(Scheduler::Cycle::LastComposite,
    mScheduler->createEventThread(scheduler::Cycle::LastComposite,
                                  mFrameTimeline->getTokenManager(),
                                  /* workDuration */ activeRefreshRate.getPeriod(),
                                  /* readyDuration */ configs.late.sfWorkDuration);
@@ -4386,6 +4383,9 @@ void SurfaceFlinger::initScheduler(const sp<const DisplayDevice>& display) {
            sp<RegionSamplingThread>::make(*this,
                                           RegionSamplingThread::EnvironmentTimingTunables());
    mFpsReporter = sp<FpsReporter>::make(*mFrameTimeline);

    // Timer callbacks may fire, so do this last.
    mScheduler->startTimers();
}

void SurfaceFlinger::doCommitTransactions() {
@@ -6322,7 +6322,7 @@ void SurfaceFlinger::dumpScheduler(std::string& result) const {
}

void SurfaceFlinger::dumpEvents(std::string& result) const {
    mScheduler->dump(mAppConnectionHandle, result);
    mScheduler->dump(scheduler::Cycle::Render, result);
}

void SurfaceFlinger::dumpVsync(std::string& result) const {
@@ -7094,14 +7094,15 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r
                mForceFullDamage = n != 0;
                return NO_ERROR;
            }
            case 1018: { // Modify Choreographer's duration
            case 1018: { // Set the render deadline as a duration until VSYNC.
                n = data.readInt32();
                mScheduler->setDuration(mAppConnectionHandle, std::chrono::nanoseconds(n), 0ns);
                mScheduler->setDuration(scheduler::Cycle::Render, std::chrono::nanoseconds(n), 0ns);
                return NO_ERROR;
            }
            case 1019: { // Modify SurfaceFlinger's duration
            case 1019: { // Set the deadline of the last composite as a duration until VSYNC.
                n = data.readInt32();
                mScheduler->setDuration(mSfConnectionHandle, std::chrono::nanoseconds(n), 0ns);
                mScheduler->setDuration(scheduler::Cycle::LastComposite,
                                        std::chrono::nanoseconds(n), 0ns);
                return NO_ERROR;
            }
            case 1020: { // Unused
@@ -7333,7 +7334,7 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r
                auto inUid = static_cast<uid_t>(data.readInt32());
                const auto refreshRate = data.readFloat();
                mScheduler->setPreferredRefreshRateForUid(FrameRateOverride{inUid, refreshRate});
                mScheduler->onFrameRateOverridesChanged(mAppConnectionHandle, displayId);
                mScheduler->onFrameRateOverridesChanged(scheduler::Cycle::Render, displayId);
                return NO_ERROR;
            }
            // Toggle caching feature
@@ -8473,10 +8474,10 @@ status_t SurfaceFlinger::applyRefreshRateSelectorPolicy(
    // TODO(b/140204874): Leave the event in until we do proper testing with all apps that might
    // be depending in this callback.
    if (const auto activeMode = selector.getActiveMode(); displayId == mActiveDisplayId) {
        mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, activeMode);
        mScheduler->onPrimaryDisplayModeChanged(scheduler::Cycle::Render, activeMode);
        toggleKernelIdleTimer();
    } else {
        mScheduler->onNonPrimaryDisplayModeChanged(mAppConnectionHandle, activeMode);
        mScheduler->onNonPrimaryDisplayModeChanged(scheduler::Cycle::Render, activeMode);
    }

    auto preferredModeOpt = getPreferredDisplayMode(displayId, currentPolicy.defaultMode);
@@ -8664,7 +8665,7 @@ status_t SurfaceFlinger::setGameModeFrameRateOverride(uid_t uid, float frameRate
    }();

    mScheduler->setGameModeFrameRateForUid(FrameRateOverride{static_cast<uid_t>(uid), frameRate});
    mScheduler->onFrameRateOverridesChanged(mAppConnectionHandle, displayId);
    mScheduler->onFrameRateOverridesChanged(scheduler::Cycle::Render, displayId);
    return NO_ERROR;
}

@@ -8926,7 +8927,8 @@ void SurfaceFlinger::updateHdcpLevels(hal::HWDisplayId hwcDisplayId, int32_t con
            Mutex::Autolock lock(mStateLock);
            display->setSecure(connectedLevel >= 2 /* HDCP_V1 */);
        }
        mScheduler->onHdcpLevelsChanged(mAppConnectionHandle, displayId, connectedLevel, maxLevel);
        mScheduler->onHdcpLevelsChanged(scheduler::Cycle::Render, displayId, connectedLevel,
                                        maxLevel);
    }));
}

+0 −5
Original line number Diff line number Diff line
@@ -1356,12 +1356,7 @@ private:

    const std::string mHwcServiceName;

    /*
     * Scheduler
     */
    std::unique_ptr<scheduler::Scheduler> mScheduler;
    scheduler::ConnectionHandle mAppConnectionHandle;
    scheduler::ConnectionHandle mSfConnectionHandle;

    scheduler::PresentLatencyTracker mPresentLatencyTracker GUARDED_BY(kMainThreadContext);

+14 −72

File changed.

Preview size limit exceeded, changes collapsed.

Loading