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

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

Merge "SF: Avoid registering DisplayDevice with Scheduler"

parents 7bcc6d6d b5a094b9
Loading
Loading
Loading
Loading
+11 −12
Original line number Original line Diff line number Diff line
@@ -94,7 +94,7 @@ void Scheduler::startTimers() {
    }
    }
}
}


void Scheduler::setRefreshRateSelector(std::shared_ptr<RefreshRateSelector> selectorPtr) {
void Scheduler::setRefreshRateSelector(RefreshRateSelectorPtr selectorPtr) {
    // The current RefreshRateSelector instance may outlive this call, so unbind its idle timer.
    // The current RefreshRateSelector instance may outlive this call, so unbind its idle timer.
    {
    {
        // mRefreshRateSelectorLock is not locked here to avoid the deadlock
        // mRefreshRateSelectorLock is not locked here to avoid the deadlock
@@ -126,13 +126,12 @@ void Scheduler::setRefreshRateSelector(std::shared_ptr<RefreshRateSelector> sele
    mRefreshRateSelector->startIdleTimer();
    mRefreshRateSelector->startIdleTimer();
}
}


void Scheduler::registerDisplay(sp<const DisplayDevice> display) {
void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr) {
    if (display->isPrimary()) {
    if (!mLeaderDisplayId) {
        mLeaderDisplayId = display->getPhysicalId();
        mLeaderDisplayId = displayId;
    }
    }


    const bool ok = mDisplays.try_emplace(display->getPhysicalId(), std::move(display)).second;
    mRefreshRateSelectors.emplace_or_replace(displayId, std::move(selectorPtr));
    ALOGE_IF(!ok, "%s: Duplicate display", __func__);
}
}


void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) {
void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) {
@@ -140,7 +139,7 @@ void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) {
        mLeaderDisplayId.reset();
        mLeaderDisplayId.reset();
    }
    }


    mDisplays.erase(displayId);
    mRefreshRateSelectors.erase(displayId);
}
}


void Scheduler::run() {
void Scheduler::run() {
@@ -711,10 +710,9 @@ auto Scheduler::chooseDisplayModes() const -> DisplayModeChoiceMap {


    const auto globalSignals = makeGlobalSignals();
    const auto globalSignals = makeGlobalSignals();


    for (const auto& [id, display] : mDisplays) {
    for (const auto& [id, selectorPtr] : mRefreshRateSelectors) {
        auto rankedRefreshRates =
        auto rankedRefreshRates =
                display->holdRefreshRateSelector()
                selectorPtr->getRankedRefreshRates(mPolicy.contentRequirements, globalSignals);
                        ->getRankedRefreshRates(mPolicy.contentRequirements, globalSignals);


        for (const auto& [modePtr, score] : rankedRefreshRates.ranking) {
        for (const auto& [modePtr, score] : rankedRefreshRates.ranking) {
            const auto [it, inserted] = refreshRateTallies.try_emplace(modePtr->getFps(), score);
            const auto [it, inserted] = refreshRateTallies.try_emplace(modePtr->getFps(), score);
@@ -733,7 +731,7 @@ auto Scheduler::chooseDisplayModes() const -> DisplayModeChoiceMap {


    // Find the first refresh rate common to all displays.
    // Find the first refresh rate common to all displays.
    while (maxScoreIt != refreshRateTallies.cend() &&
    while (maxScoreIt != refreshRateTallies.cend() &&
           maxScoreIt->second.displayCount != mDisplays.size()) {
           maxScoreIt->second.displayCount != mRefreshRateSelectors.size()) {
        ++maxScoreIt;
        ++maxScoreIt;
    }
    }


@@ -742,7 +740,8 @@ auto Scheduler::chooseDisplayModes() const -> DisplayModeChoiceMap {
        for (auto it = maxScoreIt + 1; it != refreshRateTallies.cend(); ++it) {
        for (auto it = maxScoreIt + 1; it != refreshRateTallies.cend(); ++it) {
            const auto [fps, tally] = *it;
            const auto [fps, tally] = *it;


            if (tally.displayCount == mDisplays.size() && tally.score > maxScoreIt->second.score) {
            if (tally.displayCount == mRefreshRateSelectors.size() &&
                tally.score > maxScoreIt->second.score) {
                maxScoreIt = it;
                maxScoreIt = it;
            }
            }
        }
        }
+8 −8
Original line number Original line Diff line number Diff line
@@ -39,7 +39,6 @@


#include "Display/DisplayMap.h"
#include "Display/DisplayMap.h"
#include "Display/DisplayModeRequest.h"
#include "Display/DisplayModeRequest.h"
#include "DisplayDevice.h"
#include "EventThread.h"
#include "EventThread.h"
#include "FrameRateOverrideMappings.h"
#include "FrameRateOverrideMappings.h"
#include "LayerHistory.h"
#include "LayerHistory.h"
@@ -107,10 +106,11 @@ public:
    virtual ~Scheduler();
    virtual ~Scheduler();


    void startTimers();
    void startTimers();
    void setRefreshRateSelector(std::shared_ptr<RefreshRateSelector>)
            EXCLUDES(mRefreshRateSelectorLock);


    void registerDisplay(sp<const DisplayDevice>);
    using RefreshRateSelectorPtr = std::shared_ptr<RefreshRateSelector>;
    void setRefreshRateSelector(RefreshRateSelectorPtr) EXCLUDES(mRefreshRateSelectorLock);

    void registerDisplay(PhysicalDisplayId, RefreshRateSelectorPtr);
    void unregisterDisplay(PhysicalDisplayId);
    void unregisterDisplay(PhysicalDisplayId);


    void run();
    void run();
@@ -299,8 +299,7 @@ private:
            EXCLUDES(mRefreshRateSelectorLock);
            EXCLUDES(mRefreshRateSelectorLock);
    android::impl::EventThread::GetVsyncPeriodFunction makeGetVsyncPeriodFunction() const;
    android::impl::EventThread::GetVsyncPeriodFunction makeGetVsyncPeriodFunction() const;


    std::shared_ptr<RefreshRateSelector> holdRefreshRateSelector() const
    RefreshRateSelectorPtr holdRefreshRateSelector() const EXCLUDES(mRefreshRateSelectorLock) {
            EXCLUDES(mRefreshRateSelectorLock) {
        std::scoped_lock lock(mRefreshRateSelectorLock);
        std::scoped_lock lock(mRefreshRateSelectorLock);
        return mRefreshRateSelector;
        return mRefreshRateSelector;
    }
    }
@@ -336,7 +335,7 @@ private:


    mutable std::mutex mPolicyLock;
    mutable std::mutex mPolicyLock;


    display::PhysicalDisplayMap<PhysicalDisplayId, sp<const DisplayDevice>> mDisplays;
    display::PhysicalDisplayMap<PhysicalDisplayId, RefreshRateSelectorPtr> mRefreshRateSelectors;
    std::optional<PhysicalDisplayId> mLeaderDisplayId;
    std::optional<PhysicalDisplayId> mLeaderDisplayId;


    struct Policy {
    struct Policy {
@@ -359,8 +358,9 @@ private:
        std::optional<ModeChangedParams> cachedModeChangedParams;
        std::optional<ModeChangedParams> cachedModeChangedParams;
    } mPolicy GUARDED_BY(mPolicyLock);
    } mPolicy GUARDED_BY(mPolicyLock);


    // TODO(b/255635821): Remove this by instead looking up the `mLeaderDisplayId` selector.
    mutable std::mutex mRefreshRateSelectorLock;
    mutable std::mutex mRefreshRateSelectorLock;
    std::shared_ptr<RefreshRateSelector> mRefreshRateSelector GUARDED_BY(mRefreshRateSelectorLock);
    RefreshRateSelectorPtr mRefreshRateSelector GUARDED_BY(mRefreshRateSelectorLock);


    std::mutex mVsyncTimelineLock;
    std::mutex mVsyncTimelineLock;
    std::optional<hal::VsyncPeriodChangeTimeline> mLastVsyncPeriodChangeTimeline
    std::optional<hal::VsyncPeriodChangeTimeline> mLastVsyncPeriodChangeTimeline
+8 −6
Original line number Original line Diff line number Diff line
@@ -2937,11 +2937,15 @@ void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken,
                                                 displaySurface, producer);
                                                 displaySurface, producer);


    if (mScheduler && !display->isVirtual()) {
    if (mScheduler && !display->isVirtual()) {
        auto selectorPtr = display->holdRefreshRateSelector();

        // Display modes are reloaded on hotplug reconnect.
        // Display modes are reloaded on hotplug reconnect.
        if (display->isPrimary()) {
        if (display->isPrimary()) {
            mScheduler->setRefreshRateSelector(display->holdRefreshRateSelector());
            mScheduler->setRefreshRateSelector(selectorPtr);
        }
        }
        mScheduler->registerDisplay(display);

        const auto displayId = display->getPhysicalId();
        mScheduler->registerDisplay(displayId, std::move(selectorPtr));
        dispatchDisplayHotplugEvent(display->getPhysicalId(), true);
        dispatchDisplayHotplugEvent(display->getPhysicalId(), true);
    }
    }


@@ -2994,8 +2998,6 @@ void SurfaceFlinger::processDisplayChanged(const wp<IBinder>& displayToken,
            display->disconnect();
            display->disconnect();
            if (display->isVirtual()) {
            if (display->isVirtual()) {
                releaseVirtualDisplay(display->getVirtualId());
                releaseVirtualDisplay(display->getVirtualId());
            } else {
                mScheduler->unregisterDisplay(display->getPhysicalId());
            }
            }
        }
        }


@@ -3409,8 +3411,8 @@ void SurfaceFlinger::initScheduler(const sp<const DisplayDevice>& display) {
        }
        }


        mScheduler->createVsyncSchedule(features);
        mScheduler->createVsyncSchedule(features);
        mScheduler->setRefreshRateSelector(std::move(selectorPtr));
        mScheduler->setRefreshRateSelector(selectorPtr);
        mScheduler->registerDisplay(display);
        mScheduler->registerDisplay(display->getPhysicalId(), std::move(selectorPtr));
    }
    }
    setVsyncEnabled(false);
    setVsyncEnabled(false);
    mScheduler->startTimers();
    mScheduler->startTimers();
+18 −41
Original line number Original line Diff line number Diff line
@@ -20,7 +20,6 @@


#include <mutex>
#include <mutex>


#include "FakeDisplayInjector.h"
#include "Scheduler/EventThread.h"
#include "Scheduler/EventThread.h"
#include "Scheduler/RefreshRateSelector.h"
#include "Scheduler/RefreshRateSelector.h"
#include "TestableScheduler.h"
#include "TestableScheduler.h"
@@ -41,7 +40,6 @@ namespace {


using MockEventThread = android::mock::EventThread;
using MockEventThread = android::mock::EventThread;
using MockLayer = android::mock::MockLayer;
using MockLayer = android::mock::MockLayer;
using FakeDisplayDeviceInjector = TestableSurfaceFlinger::FakeDisplayDeviceInjector;


class SchedulerTest : public testing::Test {
class SchedulerTest : public testing::Test {
protected:
protected:
@@ -90,10 +88,6 @@ protected:
    sp<MockEventThreadConnection> mEventThreadConnection;
    sp<MockEventThreadConnection> mEventThreadConnection;


    TestableSurfaceFlinger mFlinger;
    TestableSurfaceFlinger mFlinger;
    Hwc2::mock::PowerAdvisor mPowerAdvisor;
    sp<android::mock::NativeWindow> mNativeWindow = sp<android::mock::NativeWindow>::make();

    FakeDisplayInjector mFakeDisplayInjector{mFlinger, mPowerAdvisor, mNativeWindow};
};
};


SchedulerTest::SchedulerTest() {
SchedulerTest::SchedulerTest() {
@@ -240,14 +234,11 @@ MATCHER(Is120Hz, "") {
}
}


TEST_F(SchedulerTest, chooseRefreshRateForContentSelectsMaxRefreshRate) {
TEST_F(SchedulerTest, chooseRefreshRateForContentSelectsMaxRefreshRate) {
    const auto display = mFakeDisplayInjector.injectInternalDisplay(
    const auto selectorPtr =
            [&](FakeDisplayDeviceInjector& injector) {
            std::make_shared<RefreshRateSelector>(kDisplay1Modes, kDisplay1Mode60->getId());
                injector.setDisplayModes(kDisplay1Modes, kDisplay1Mode60->getId());
            },
            {.displayId = kDisplayId1});


    mScheduler->registerDisplay(display);
    mScheduler->registerDisplay(kDisplayId1, selectorPtr);
    mScheduler->setRefreshRateSelector(display->holdRefreshRateSelector());
    mScheduler->setRefreshRateSelector(selectorPtr);


    const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
    const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
    EXPECT_CALL(*layer, isVisible()).WillOnce(Return(true));
    EXPECT_CALL(*layer, isVisible()).WillOnce(Return(true));
@@ -269,13 +260,9 @@ TEST_F(SchedulerTest, chooseRefreshRateForContentSelectsMaxRefreshRate) {
}
}


TEST_F(SchedulerTest, chooseDisplayModesSingleDisplay) {
TEST_F(SchedulerTest, chooseDisplayModesSingleDisplay) {
    const auto display = mFakeDisplayInjector.injectInternalDisplay(
    mScheduler->registerDisplay(kDisplayId1,
            [&](FakeDisplayDeviceInjector& injector) {
                                std::make_shared<RefreshRateSelector>(kDisplay1Modes,
                injector.setDisplayModes(kDisplay1Modes, kDisplay1Mode60->getId());
                                                                      kDisplay1Mode60->getId()));
            },
            {.displayId = kDisplayId1});

    mScheduler->registerDisplay(display);


    std::vector<RefreshRateSelector::LayerRequirement> layers =
    std::vector<RefreshRateSelector::LayerRequirement> layers =
            std::vector<RefreshRateSelector::LayerRequirement>({{.weight = 1.f}, {.weight = 1.f}});
            std::vector<RefreshRateSelector::LayerRequirement>({{.weight = 1.f}, {.weight = 1.f}});
@@ -314,23 +301,16 @@ TEST_F(SchedulerTest, chooseDisplayModesSingleDisplay) {
    EXPECT_EQ(choice->get(), DisplayModeChoice(kDisplay1Mode120, globalSignals));
    EXPECT_EQ(choice->get(), DisplayModeChoice(kDisplay1Mode120, globalSignals));


    mScheduler->unregisterDisplay(kDisplayId1);
    mScheduler->unregisterDisplay(kDisplayId1);
    EXPECT_TRUE(mScheduler->mutableDisplays().empty());
    EXPECT_FALSE(mScheduler->hasRefreshRateSelectors());
}
}


TEST_F(SchedulerTest, chooseDisplayModesMultipleDisplays) {
TEST_F(SchedulerTest, chooseDisplayModesMultipleDisplays) {
    const auto display1 = mFakeDisplayInjector.injectInternalDisplay(
    mScheduler->registerDisplay(kDisplayId1,
            [&](FakeDisplayDeviceInjector& injector) {
                                std::make_shared<RefreshRateSelector>(kDisplay1Modes,
                injector.setDisplayModes(kDisplay1Modes, kDisplay1Mode60->getId());
                                                                      kDisplay1Mode60->getId()));
            },
    mScheduler->registerDisplay(kDisplayId2,
            {.displayId = kDisplayId1, .hwcDisplayId = 42, .isPrimary = true});
                                std::make_shared<RefreshRateSelector>(kDisplay2Modes,
    const auto display2 = mFakeDisplayInjector.injectInternalDisplay(
                                                                      kDisplay2Mode60->getId()));
            [&](FakeDisplayDeviceInjector& injector) {
                injector.setDisplayModes(kDisplay2Modes, kDisplay2Mode60->getId());
            },
            {.displayId = kDisplayId2, .hwcDisplayId = 41, .isPrimary = false});

    mScheduler->registerDisplay(display1);
    mScheduler->registerDisplay(display2);


    using DisplayModeChoice = TestableScheduler::DisplayModeChoice;
    using DisplayModeChoice = TestableScheduler::DisplayModeChoice;
    TestableScheduler::DisplayModeChoiceMap expectedChoices;
    TestableScheduler::DisplayModeChoiceMap expectedChoices;
@@ -380,13 +360,10 @@ TEST_F(SchedulerTest, chooseDisplayModesMultipleDisplays) {
    }
    }
    {
    {
        // This display does not support 120 Hz, so we should choose 60 Hz despite the touch signal.
        // This display does not support 120 Hz, so we should choose 60 Hz despite the touch signal.
        const auto display3 = mFakeDisplayInjector.injectInternalDisplay(
        mScheduler
                [&](FakeDisplayDeviceInjector& injector) {
                ->registerDisplay(kDisplayId3,
                    injector.setDisplayModes(kDisplay3Modes, kDisplay3Mode60->getId());
                                  std::make_shared<RefreshRateSelector>(kDisplay3Modes,
                },
                                                                        kDisplay3Mode60->getId()));
                {.displayId = kDisplayId3, .hwcDisplayId = 40, .isPrimary = false});

        mScheduler->registerDisplay(display3);


        const GlobalSignals globalSignals = {.touch = true};
        const GlobalSignals globalSignals = {.touch = true};
        mScheduler->replaceTouchTimer(10);
        mScheduler->replaceTouchTimer(10);
+5 −8
Original line number Original line Diff line number Diff line
@@ -32,15 +32,13 @@ namespace android::scheduler {


class TestableScheduler : public Scheduler, private ICompositor {
class TestableScheduler : public Scheduler, private ICompositor {
public:
public:
    TestableScheduler(std::shared_ptr<RefreshRateSelector> selectorPtr,
    TestableScheduler(RefreshRateSelectorPtr selectorPtr, ISchedulerCallback& callback)
                      ISchedulerCallback& callback)
          : TestableScheduler(std::make_unique<mock::VsyncController>(),
          : TestableScheduler(std::make_unique<mock::VsyncController>(),
                              std::make_unique<mock::VSyncTracker>(), std::move(selectorPtr),
                              std::make_unique<mock::VSyncTracker>(), std::move(selectorPtr),
                              callback) {}
                              callback) {}


    TestableScheduler(std::unique_ptr<VsyncController> controller,
    TestableScheduler(std::unique_ptr<VsyncController> controller,
                      std::unique_ptr<VSyncTracker> tracker,
                      std::unique_ptr<VSyncTracker> tracker, RefreshRateSelectorPtr selectorPtr,
                      std::shared_ptr<RefreshRateSelector> selectorPtr,
                      ISchedulerCallback& callback)
                      ISchedulerCallback& callback)
          : Scheduler(*this, callback, Feature::kContentDetection) {
          : Scheduler(*this, callback, Feature::kContentDetection) {
        mVsyncSchedule.emplace(VsyncSchedule(std::move(tracker), nullptr, std::move(controller)));
        mVsyncSchedule.emplace(VsyncSchedule(std::move(tracker), nullptr, std::move(controller)));
@@ -68,16 +66,15 @@ public:
    auto& mutablePrimaryHWVsyncEnabled() { return mPrimaryHWVsyncEnabled; }
    auto& mutablePrimaryHWVsyncEnabled() { return mPrimaryHWVsyncEnabled; }
    auto& mutableHWVsyncAvailable() { return mHWVsyncAvailable; }
    auto& mutableHWVsyncAvailable() { return mHWVsyncAvailable; }


    auto& mutableLayerHistory() { return mLayerHistory; }
    auto refreshRateSelector() { return holdRefreshRateSelector(); }
    bool hasRefreshRateSelectors() const { return !mRefreshRateSelectors.empty(); }


    auto& mutableDisplays() { return mDisplays; }
    auto& mutableLayerHistory() { return mLayerHistory; }


    size_t layerHistorySize() NO_THREAD_SAFETY_ANALYSIS {
    size_t layerHistorySize() NO_THREAD_SAFETY_ANALYSIS {
        return mLayerHistory.mActiveLayerInfos.size() + mLayerHistory.mInactiveLayerInfos.size();
        return mLayerHistory.mActiveLayerInfos.size() + mLayerHistory.mInactiveLayerInfos.size();
    }
    }


    auto refreshRateSelector() { return holdRefreshRateSelector(); }

    size_t getNumActiveLayers() NO_THREAD_SAFETY_ANALYSIS {
    size_t getNumActiveLayers() NO_THREAD_SAFETY_ANALYSIS {
        return mLayerHistory.mActiveLayerInfos.size();
        return mLayerHistory.mActiveLayerInfos.size();
    }
    }
Loading