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

Commit 53f0e308 authored by Su Hong Koo's avatar Su Hong Koo Committed by Android (Google) Code Review
Browse files

Merge "SF: Add sfdo command to force set pacesetter display" into main

parents f1c5a0d6 cea4787f
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -75,6 +75,20 @@ enum Commands {

    #[command(about = "Force commit ahead of next VSYNC.")]
    ScheduleCommit,

    #[command(
        about = "display_id = i64, Forcibly changes the pacesetter display to specified display, \
                      which will persist until the display is removed or another ForcePacesetter \
                      or ResetForcedPacesetter call is made. Valid display IDs can be obtained   \
                      through: adb shell dumpsys SurfaceFlinger --display-ids"
    )]
    ForcePacesetter { display_id: i64 },

    #[command(
        about = "Resets the forced pacesetter display selection made by the ForcePacesetter \
                        call. No-op if there was no forced pacesetter display set."
    )]
    ResetForcedPacesetter,
}

/// sfdo command line tool
@@ -146,6 +160,14 @@ fn main() {
                eprintln!("No state, choices are [enabled | disabled]");
            }
        }
        Some(Commands::ForcePacesetter { display_id }) => {
            let res = composer_service.forcePacesetter(*display_id);
            print_result("forcePacesetter", res);
        }
        Some(Commands::ResetForcedPacesetter) => {
            let res = composer_service.resetForcedPacesetter();
            print_result("resetForcedPacesetter", res);
        }
        None => {
            println!("Execute SurfaceFlinger internal commands.");
            println!("run `adb shell sfdo help` for more to view the commands.");
+14 −0
Original line number Diff line number Diff line
@@ -650,4 +650,18 @@ interface ISurfaceComposer {
     * profiles.
     */
    oneway void removeActivePictureListener(IActivePictureListener listener);

    /**
     * Force the display specified by the argument to become the pacesetter display until the
     * display is removed or another forcePacesetter/resetForcedPacesetter call is invoked.
     * Requires root
     */
    void forcePacesetter(long displayId);

    /**
     * Resets the forced pacesetter display selection made by the forcePacesetter call. No-op
     * if there was no forced pacesetter display set.
     * Requires root
     */
     void resetForcedPacesetter();
}
+4 −0
Original line number Diff line number Diff line
@@ -1061,6 +1061,10 @@ public:
        return binder::Status::ok();
    }

    binder::Status forcePacesetter(int64_t) { return binder::Status::ok(); }

    binder::Status resetForcedPacesetter() { return binder::Status::ok(); }

protected:
    IBinder* onAsBinder() override { return nullptr; }

+42 −9
Original line number Diff line number Diff line
@@ -111,9 +111,7 @@ void Scheduler::startTimers() {
}

bool Scheduler::designatePacesetterDisplay(std::optional<PhysicalDisplayId> pacesetterId) {
    if (FlagManager::getInstance().pacesetter_selection() && !pacesetterId.has_value()) {
        pacesetterId = selectPacesetterDisplay();
    }
    pacesetterId = selectPacesetterDisplay(pacesetterId);

    // Skip an unnecessary demotion/promotion cycle if there's no work to do.
    if ((ftl::FakeGuard(mDisplayLock), mPacesetterDisplayId == *pacesetterId)) {
@@ -138,12 +136,30 @@ bool Scheduler::designatePacesetterDisplay(std::optional<PhysicalDisplayId> pace
    return true;
}

PhysicalDisplayId Scheduler::selectPacesetterDisplay() const {
bool Scheduler::forcePacesetterDisplay(PhysicalDisplayId pacesetterId) {
    {
        std::scoped_lock lock(mDisplayLock);
        mForcedPacesetterDisplayId = pacesetterId;
    }
    return designatePacesetterDisplay();
}

PhysicalDisplayId Scheduler::selectPacesetterDisplay(
        std::optional<PhysicalDisplayId> desiredPacesetterId) const {
    std::scoped_lock lock(mDisplayLock);
    return selectPacesetterDisplayLocked();
    return selectPacesetterDisplayLocked(desiredPacesetterId);
}

PhysicalDisplayId Scheduler::selectPacesetterDisplayLocked(
        std::optional<PhysicalDisplayId> desiredPacesetterId) const {
    if (mForcedPacesetterDisplayId.has_value()) {
        return *mForcedPacesetterDisplayId;
    }

    if (desiredPacesetterId.has_value()) {
        return *desiredPacesetterId;
    }

PhysicalDisplayId Scheduler::selectPacesetterDisplayLocked() const {
    // The first display should be the new pacesetter if none of the displays are powered on.
    const auto& [firstDisplayId, firstDisplay] = *mDisplays.begin();
    PhysicalDisplayId newPacesetterId = firstDisplayId;
@@ -189,6 +205,19 @@ PhysicalDisplayId Scheduler::selectPacesetterDisplayLocked() const {
    return newPacesetterId;
}

bool Scheduler::resetForcedPacesetterDisplay(std::optional<PhysicalDisplayId> pacesetterId) {
    {
        std::scoped_lock lock(mDisplayLock);
        if (!mForcedPacesetterDisplayId.has_value()) {
            return false;
        }

        mForcedPacesetterDisplayId.reset();
    }

    return designatePacesetterDisplay(pacesetterId);
}

PhysicalDisplayId Scheduler::getPacesetterDisplayId() const {
    std::scoped_lock lock(mDisplayLock);
    LOG_ALWAYS_FATAL_IF(!mPacesetterDisplayId, "Missing a pacesetter!");
@@ -259,6 +288,10 @@ void Scheduler::unregisterDisplay(PhysicalDisplayId displayId,
        // headless virtual display.)
        LOG_ALWAYS_FATAL_IF(mDisplays.empty(), "Cannot unregister all displays!");

        if (mForcedPacesetterDisplayId == displayId) {
            mForcedPacesetterDisplayId.reset();
        }

        pacesetterVsyncSchedule =
                promotePacesetterDisplayLocked(defaultPacesetterId, kPromotionParams);
    }
@@ -1069,6 +1102,7 @@ void Scheduler::dump(utils::Dumper& dumper) const {
            std::scoped_lock lock(mDisplayLock);
            ftl::FakeGuard guard(kMainThreadContext);
            dumper.dump("pacesetterDisplayId"sv, mPacesetterDisplayId);
            dumper.dump("forcedPacesetterDisplayId"sv, mForcedPacesetterDisplayId);
        }
        dumper.dump("layerHistory"sv, mLayerHistory.dump());
        dumper.dump("touchTimer"sv, mTouchTimer.transform(&OneShotTimer::interval));
@@ -1163,11 +1197,10 @@ void Scheduler::promotePacesetterDisplay(std::optional<PhysicalDisplayId> pacese

std::shared_ptr<VsyncSchedule> Scheduler::promotePacesetterDisplayLocked(
        std::optional<PhysicalDisplayId> pacesetterId, PromotionParams params) {
    if (FlagManager::getInstance().pacesetter_selection() && !pacesetterId.has_value()) {
        pacesetterId = selectPacesetterDisplayLocked();
    }
    pacesetterId = selectPacesetterDisplayLocked(pacesetterId);

    mPacesetterDisplayId = *pacesetterId;

    ALOGI("Display %s is the pacesetter", to_string(*pacesetterId).c_str());

    std::shared_ptr<VsyncSchedule> newVsyncSchedulePtr;
+24 −6
Original line number Diff line number Diff line
@@ -91,12 +91,24 @@ public:

    void startTimers();

    // Automatically selects a pacesetter display and designates if |pacesetterId| is not present,
    // Automatically selects a pacesetter display and designates if `pacesetterId` is not present,
    // otherwise promotes `pacesetterId` to pacesetter. Returns true if a new display was chosen as
    // the pacesetter.
    bool designatePacesetterDisplay(std::optional<PhysicalDisplayId> pacesetterId = std::nullopt)
            REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock);

    // Force `pacesetterId` as the pacesetter display, which will remain as the pacesetter display
    // until it is unregistered or the forced pacesetter is reset. Returns true if the forced
    // pacesetter is different from the previous pacesetter.
    bool forcePacesetterDisplay(PhysicalDisplayId pacesetterId) REQUIRES(kMainThreadContext)
            EXCLUDES(mDisplayLock);

    // Clears forced pacesetter display if present and sets the pacesetter to
    // `pacesetterId` if present, otherwise automatically selects one. No-op if
    // `mForcedPacesetterDisplayId` is not set.
    bool resetForcedPacesetterDisplay(std::optional<PhysicalDisplayId> pacesetterId)
            REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock);

    PhysicalDisplayId getPacesetterDisplayId() const EXCLUDES(mDisplayLock);

    using RefreshRateSelectorPtr = std::shared_ptr<RefreshRateSelector>;
@@ -499,14 +511,17 @@ private:
    Period getVsyncPeriod(uid_t) override EXCLUDES(mDisplayLock);
    void onExpectedPresentTimePosted(TimePoint expectedPresentTime) override EXCLUDES(mDisplayLock);

    // Returns the powered-on display with the highest refresh rate in |mDisplays| as the new
    // pacesetter, but does not set the display as pacesetter.
    // Returns the display that should be promoted to pacesetter using the following priority:
    // 1. `mForcedPacesetterDisplayId`, if present
    // 2. `desiredPacesetterId`, if specified
    // 3. powered-on display with the highest refresh rate in `mDisplays`
    // NOTE: If displays with highest refresh rates have roughly equal refresh rates,
    // and the current pacesetter is among them, then the current pacesetter will remain the
    // pacesetter.
    PhysicalDisplayId selectPacesetterDisplay() const REQUIRES(kMainThreadContext)
            EXCLUDES(mDisplayLock);
    PhysicalDisplayId selectPacesetterDisplayLocked() const
    PhysicalDisplayId selectPacesetterDisplay(std::optional<PhysicalDisplayId> desiredPacesetterId)
            const REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock);
    PhysicalDisplayId selectPacesetterDisplayLocked(
            std::optional<PhysicalDisplayId> desiredPacesetterId) const
            REQUIRES(kMainThreadContext, mDisplayLock);

    std::unique_ptr<EventThread> mRenderEventThread;
@@ -575,6 +590,9 @@ private:
    // May be read from any thread, but must only be written from the main thread.
    ftl::Optional<PhysicalDisplayId> mPacesetterDisplayId GUARDED_BY(mDisplayLock);

    ftl::Optional<PhysicalDisplayId> mForcedPacesetterDisplayId GUARDED_BY(mDisplayLock)
            GUARDED_BY(kMainThreadContext);

    ftl::Optional<DisplayRef> pacesetterDisplayLocked() REQUIRES(mDisplayLock) {
        return static_cast<const Scheduler*>(this)->pacesetterDisplayLocked().transform(
                [](const Display& display) { return std::ref(const_cast<Display&>(display)); });
Loading