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

Commit fdac5651 authored by Dominik Laskowski's avatar Dominik Laskowski
Browse files

SF: Fix mode setting for secondary displays

Desired modes were only propagated to HWC for the "active" display, i.e.
generally the primary display and specially the rear display when in the
folded state. In other words, mode setting did not happen for external
displays, and the rear display when driving both displays concurrently.

Store per-display state for whether a mode set is pending. Propagate the
desired mode for both internal and external displays as long as they are
powered on.

Fixes: 277776378
Fixes: 289182528
Bug: 255635711
Bug: 255635821
Test: The 60 Hz constraint applies to both displays in concurrent mode.
Test: ADB `set-user-preferred-display-mode` applies to external display.
Test: DisplayModeSwitchingTest#inner{Xor,And}OuterDisplay
Test: DisplayModeSwitchingTest#powerOffDuringModeSet
Change-Id: I9da3a0be07f9fbb08f11485aa6ab9400259a4e09
parent 9bd0c2ba
Loading
Loading
Loading
Loading
+12 −5
Original line number Original line Diff line number Diff line
@@ -38,7 +38,6 @@
#include <log/log.h>
#include <log/log.h>
#include <system/window.h>
#include <system/window.h>


#include "Display/DisplaySnapshot.h"
#include "DisplayDevice.h"
#include "DisplayDevice.h"
#include "FrontEnd/DisplayInfo.h"
#include "FrontEnd/DisplayInfo.h"
#include "HdrSdrRatioOverlay.h"
#include "HdrSdrRatioOverlay.h"
@@ -231,10 +230,18 @@ status_t DisplayDevice::initiateModeChange(const ActiveModeInfo& info,
        return BAD_VALUE;
        return BAD_VALUE;
    }
    }
    mUpcomingActiveMode = info;
    mUpcomingActiveMode = info;
    ATRACE_INT(mActiveModeFPSHwcTrace.c_str(), info.modeOpt->modePtr->getFps().getIntValue());
    mIsModeSetPending = true;
    return mHwComposer.setActiveModeWithConstraints(getPhysicalId(),

                                                    info.modeOpt->modePtr->getHwcId(), constraints,
    const auto& pendingMode = *info.modeOpt->modePtr;
                                                    outTimeline);
    ATRACE_INT(mActiveModeFPSHwcTrace.c_str(), pendingMode.getFps().getIntValue());

    return mHwComposer.setActiveModeWithConstraints(getPhysicalId(), pendingMode.getHwcId(),
                                                    constraints, outTimeline);
}

void DisplayDevice::finalizeModeChange(DisplayModeId modeId, Fps displayFps, Fps renderFps) {
    setActiveMode(modeId, displayFps, renderFps);
    mIsModeSetPending = false;
}
}


nsecs_t DisplayDevice::getVsyncPeriodFromHWC() const {
nsecs_t DisplayDevice::getVsyncPeriodFromHWC() const {
+7 −0
Original line number Original line Diff line number Diff line
@@ -218,6 +218,8 @@ public:
        return mUpcomingActiveMode;
        return mUpcomingActiveMode;
    }
    }


    bool isModeSetPending() const REQUIRES(kMainThreadContext) { return mIsModeSetPending; }

    scheduler::FrameRateMode getActiveMode() const REQUIRES(kMainThreadContext) {
    scheduler::FrameRateMode getActiveMode() const REQUIRES(kMainThreadContext) {
        return mRefreshRateSelector->getActiveMode();
        return mRefreshRateSelector->getActiveMode();
    }
    }
@@ -229,6 +231,9 @@ public:
                                hal::VsyncPeriodChangeTimeline* outTimeline)
                                hal::VsyncPeriodChangeTimeline* outTimeline)
            REQUIRES(kMainThreadContext);
            REQUIRES(kMainThreadContext);


    void finalizeModeChange(DisplayModeId, Fps displayFps, Fps renderFps)
            REQUIRES(kMainThreadContext);

    scheduler::RefreshRateSelector& refreshRateSelector() const { return *mRefreshRateSelector; }
    scheduler::RefreshRateSelector& refreshRateSelector() const { return *mRefreshRateSelector; }


    // Extends the lifetime of the RefreshRateSelector, so it can outlive this DisplayDevice.
    // Extends the lifetime of the RefreshRateSelector, so it can outlive this DisplayDevice.
@@ -313,7 +318,9 @@ private:
    ActiveModeInfo mDesiredActiveMode GUARDED_BY(mActiveModeLock);
    ActiveModeInfo mDesiredActiveMode GUARDED_BY(mActiveModeLock);
    TracedOrdinal<bool> mDesiredActiveModeChanged GUARDED_BY(mActiveModeLock) =
    TracedOrdinal<bool> mDesiredActiveModeChanged GUARDED_BY(mActiveModeLock) =
            {ftl::Concat("DesiredActiveModeChanged-", getId().value).c_str(), false};
            {ftl::Concat("DesiredActiveModeChanged-", getId().value).c_str(), false};

    ActiveModeInfo mUpcomingActiveMode GUARDED_BY(kMainThreadContext);
    ActiveModeInfo mUpcomingActiveMode GUARDED_BY(kMainThreadContext);
    bool mIsModeSetPending GUARDED_BY(kMainThreadContext) = false;
};
};


struct DisplayDeviceState {
struct DisplayDeviceState {
+11 −1
Original line number Original line Diff line number Diff line
@@ -186,7 +186,17 @@ void Scheduler::onFrameSignal(ICompositor& compositor, VsyncId vsyncId,
    FrameTargeter& pacesetterTargeter = *pacesetterOpt->get().targeterPtr;
    FrameTargeter& pacesetterTargeter = *pacesetterOpt->get().targeterPtr;
    pacesetterTargeter.beginFrame(beginFrameArgs, *pacesetterOpt->get().schedulePtr);
    pacesetterTargeter.beginFrame(beginFrameArgs, *pacesetterOpt->get().schedulePtr);


    if (!compositor.commit(pacesetterTargeter.target())) return;
    FrameTargets targets;
    targets.try_emplace(pacesetterId, &pacesetterTargeter.target());

    for (const auto& [id, display] : mDisplays) {
        if (id == pacesetterId) continue;

        const FrameTargeter& targeter = *display.targeterPtr;
        targets.try_emplace(id, &targeter.target());
    }

    if (!compositor.commit(pacesetterId, targets)) return;


    // TODO(b/256196556): Choose the frontrunner display.
    // TODO(b/256196556): Choose the frontrunner display.
    FrameTargeters targeters;
    FrameTargeters targeters;
+2 −1
Original line number Original line Diff line number Diff line
@@ -29,6 +29,7 @@ namespace scheduler {
class FrameTarget;
class FrameTarget;
class FrameTargeter;
class FrameTargeter;


using FrameTargets = ui::PhysicalDisplayMap<PhysicalDisplayId, const scheduler::FrameTarget*>;
using FrameTargeters = ui::PhysicalDisplayMap<PhysicalDisplayId, scheduler::FrameTargeter*>;
using FrameTargeters = ui::PhysicalDisplayMap<PhysicalDisplayId, scheduler::FrameTargeter*>;


} // namespace scheduler
} // namespace scheduler
@@ -39,7 +40,7 @@ struct ICompositor {


    // Commits transactions for layers and displays. Returns whether any state has been invalidated,
    // Commits transactions for layers and displays. Returns whether any state has been invalidated,
    // i.e. whether a frame should be composited for each display.
    // i.e. whether a frame should be composited for each display.
    virtual bool commit(const scheduler::FrameTarget&) = 0;
    virtual bool commit(PhysicalDisplayId pacesetterId, const scheduler::FrameTargets&) = 0;


    // Composites a frame for each display. CompositionEngine performs GPU and/or HAL composition
    // Composites a frame for each display. CompositionEngine performs GPU and/or HAL composition
    // via RenderEngine and the Composer HAL, respectively.
    // via RenderEngine and the Composer HAL, respectively.
+99 −84
Original line number Original line Diff line number Diff line
@@ -1195,9 +1195,9 @@ status_t SurfaceFlinger::getDisplayStats(const sp<IBinder>& displayToken,
}
}


void SurfaceFlinger::setDesiredActiveMode(display::DisplayModeRequest&& request, bool force) {
void SurfaceFlinger::setDesiredActiveMode(display::DisplayModeRequest&& request, bool force) {
    ATRACE_CALL();

    const auto displayId = request.mode.modePtr->getPhysicalDisplayId();
    const auto displayId = request.mode.modePtr->getPhysicalDisplayId();
    ATRACE_NAME(ftl::Concat(__func__, ' ', displayId.value).c_str());

    const auto display = getDisplayDeviceLocked(displayId);
    const auto display = getDisplayDeviceLocked(displayId);
    if (!display) {
    if (!display) {
        ALOGW("%s: display is no longer valid", __func__);
        ALOGW("%s: display is no longer valid", __func__);
@@ -1225,17 +1225,24 @@ void SurfaceFlinger::setDesiredActiveMode(display::DisplayModeRequest&& request,
            // As we called to set period, we will call to onRefreshRateChangeCompleted once
            // As we called to set period, we will call to onRefreshRateChangeCompleted once
            // VsyncController model is locked.
            // VsyncController model is locked.
            mScheduler->modulateVsync(displayId, &VsyncModulator::onRefreshRateChangeInitiated);
            mScheduler->modulateVsync(displayId, &VsyncModulator::onRefreshRateChangeInitiated);

            if (displayId == mActiveDisplayId) {
                updatePhaseConfiguration(mode.fps);
                updatePhaseConfiguration(mode.fps);
            }

            mScheduler->setModeChangePending(true);
            mScheduler->setModeChangePending(true);
            break;
            break;
        case DisplayDevice::DesiredActiveModeAction::InitiateRenderRateSwitch:
        case DisplayDevice::DesiredActiveModeAction::InitiateRenderRateSwitch:
            mScheduler->setRenderRate(displayId, mode.fps);
            mScheduler->setRenderRate(displayId, mode.fps);

            if (displayId == mActiveDisplayId) {
                updatePhaseConfiguration(mode.fps);
                updatePhaseConfiguration(mode.fps);
                mRefreshRateStats->setRefreshRate(mode.fps);
                mRefreshRateStats->setRefreshRate(mode.fps);
            if (display->getPhysicalId() == mActiveDisplayId && emitEvent) {
                mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, mode);
            }
            }


            if (emitEvent) {
                dispatchDisplayModeChangeEvent(displayId, mode);
            }
            break;
            break;
        case DisplayDevice::DesiredActiveModeAction::None:
        case DisplayDevice::DesiredActiveModeAction::None:
            break;
            break;
@@ -1291,24 +1298,20 @@ status_t SurfaceFlinger::setActiveModeFromBackdoor(const sp<display::DisplayToke
    return future.get();
    return future.get();
}
}


void SurfaceFlinger::updateInternalStateWithChangedMode() {
void SurfaceFlinger::finalizeDisplayModeChange(DisplayDevice& display) {
    ATRACE_CALL();
    const auto displayId = display.getPhysicalId();

    ATRACE_NAME(ftl::Concat(__func__, ' ', displayId.value).c_str());
    const auto display = getDefaultDisplayDeviceLocked();
    if (!display) {
        return;
    }


    const auto upcomingModeInfo = display->getUpcomingActiveMode();
    const auto upcomingModeInfo = display.getUpcomingActiveMode();
    if (!upcomingModeInfo.modeOpt) {
    if (!upcomingModeInfo.modeOpt) {
        // There is no pending mode change. This can happen if the active
        // There is no pending mode change. This can happen if the active
        // display changed and the mode change happened on a different display.
        // display changed and the mode change happened on a different display.
        return;
        return;
    }
    }


    if (display->getActiveMode().modePtr->getResolution() !=
    if (display.getActiveMode().modePtr->getResolution() !=
        upcomingModeInfo.modeOpt->modePtr->getResolution()) {
        upcomingModeInfo.modeOpt->modePtr->getResolution()) {
        auto& state = mCurrentState.displays.editValueFor(display->getDisplayToken());
        auto& state = mCurrentState.displays.editValueFor(display.getDisplayToken());
        // We need to generate new sequenceId in order to recreate the display (and this
        // We need to generate new sequenceId in order to recreate the display (and this
        // way the framebuffer).
        // way the framebuffer).
        state.sequenceId = DisplayDeviceState{}.sequenceId;
        state.sequenceId = DisplayDeviceState{}.sequenceId;
@@ -1319,27 +1322,24 @@ void SurfaceFlinger::updateInternalStateWithChangedMode() {
        return;
        return;
    }
    }


    mPhysicalDisplays.get(display->getPhysicalId())
    const auto& activeMode = *upcomingModeInfo.modeOpt;
            .transform(&PhysicalDisplay::snapshotRef)
    display.finalizeModeChange(activeMode.modePtr->getId(), activeMode.modePtr->getFps(),
            .transform(ftl::unit_fn([&](const display::DisplaySnapshot& snapshot) {
                               activeMode.fps);
                FTL_FAKE_GUARD(kMainThreadContext,
                               display->setActiveMode(upcomingModeInfo.modeOpt->modePtr->getId(),
                                                      upcomingModeInfo.modeOpt->modePtr->getFps(),
                                                      upcomingModeInfo.modeOpt->fps));
            }));


    const Fps refreshRate = upcomingModeInfo.modeOpt->fps;
    if (displayId == mActiveDisplayId) {
    mRefreshRateStats->setRefreshRate(refreshRate);
        mRefreshRateStats->setRefreshRate(activeMode.fps);
    updatePhaseConfiguration(refreshRate);
        updatePhaseConfiguration(activeMode.fps);
    }


    if (upcomingModeInfo.event != scheduler::DisplayModeEvent::None) {
    if (upcomingModeInfo.event != scheduler::DisplayModeEvent::None) {
        mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, *upcomingModeInfo.modeOpt);
        dispatchDisplayModeChangeEvent(displayId, activeMode);
    }
    }
}
}


void SurfaceFlinger::clearDesiredActiveModeState(const sp<DisplayDevice>& display) {
void SurfaceFlinger::clearDesiredActiveModeState(const sp<DisplayDevice>& display) {
    display->clearDesiredActiveModeState();
    display->clearDesiredActiveModeState();
    if (display->getPhysicalId() == mActiveDisplayId) {
    if (display->getPhysicalId() == mActiveDisplayId) {
        // TODO(b/255635711): Check for pending mode changes on other displays.
        mScheduler->setModeChangePending(false);
        mScheduler->setModeChangePending(false);
    }
    }
}
}
@@ -1353,21 +1353,18 @@ void SurfaceFlinger::desiredActiveModeChangeDone(const sp<DisplayDevice>& displa
    clearDesiredActiveModeState(display);
    clearDesiredActiveModeState(display);
    mScheduler->resyncToHardwareVsync(displayId, true /* allowToEnable */, displayFps);
    mScheduler->resyncToHardwareVsync(displayId, true /* allowToEnable */, displayFps);
    mScheduler->setRenderRate(displayId, renderFps);
    mScheduler->setRenderRate(displayId, renderFps);

    if (displayId == mActiveDisplayId) {
        updatePhaseConfiguration(renderFps);
        updatePhaseConfiguration(renderFps);
    }
    }
}


void SurfaceFlinger::setActiveModeInHwcIfNeeded() {
void SurfaceFlinger::initiateDisplayModeChanges() {
    ATRACE_CALL();
    ATRACE_CALL();


    std::optional<PhysicalDisplayId> displayToUpdateImmediately;
    std::optional<PhysicalDisplayId> displayToUpdateImmediately;


    for (const auto& [id, physical] : mPhysicalDisplays) {
    for (const auto& [id, physical] : mPhysicalDisplays) {
        const auto& snapshot = physical.snapshot();

        if (snapshot.connectionType() != ui::DisplayConnectionType::Internal) {
            continue;
        }

        const auto display = getDisplayDeviceLocked(id);
        const auto display = getDisplayDeviceLocked(id);
        if (!display) continue;
        if (!display) continue;


@@ -1378,14 +1375,14 @@ void SurfaceFlinger::setActiveModeInHwcIfNeeded() {
            continue;
            continue;
        }
        }


        if (id != mActiveDisplayId) {
        if (!display->isPoweredOn()) {
            // Display is no longer the active display, so abort the mode change.
            // Display is no longer powered on, so abort the mode change.
            clearDesiredActiveModeState(display);
            clearDesiredActiveModeState(display);
            continue;
            continue;
        }
        }


        const auto desiredModeId = desiredActiveMode->modeOpt->modePtr->getId();
        const auto desiredModeId = desiredActiveMode->modeOpt->modePtr->getId();
        const auto displayModePtrOpt = snapshot.displayModes().get(desiredModeId);
        const auto displayModePtrOpt = physical.snapshot().displayModes().get(desiredModeId);


        if (!displayModePtrOpt) {
        if (!displayModePtrOpt) {
            ALOGW("Desired display mode is no longer supported. Mode ID = %d",
            ALOGW("Desired display mode is no longer supported. Mode ID = %d",
@@ -1435,19 +1432,18 @@ void SurfaceFlinger::setActiveModeInHwcIfNeeded() {


        if (outTimeline.refreshRequired) {
        if (outTimeline.refreshRequired) {
            scheduleComposite(FrameHint::kNone);
            scheduleComposite(FrameHint::kNone);
            mSetActiveModePending = true;
        } else {
        } else {
            // Updating the internal state should be done outside the loop,
            // TODO(b/255635711): Remove `displayToUpdateImmediately` to `finalizeDisplayModeChange`
            // because it can recreate a DisplayDevice and modify mDisplays
            // for all displays. This was only needed when the loop iterated over `mDisplays` rather
            // which will invalidate the iterator.
            // than `mPhysicalDisplays`.
            displayToUpdateImmediately = display->getPhysicalId();
            displayToUpdateImmediately = display->getPhysicalId();
        }
        }
    }
    }


    if (displayToUpdateImmediately) {
    if (displayToUpdateImmediately) {
        updateInternalStateWithChangedMode();

        const auto display = getDisplayDeviceLocked(*displayToUpdateImmediately);
        const auto display = getDisplayDeviceLocked(*displayToUpdateImmediately);
        finalizeDisplayModeChange(*display);

        const auto desiredActiveMode = display->getDesiredActiveMode();
        const auto desiredActiveMode = display->getDesiredActiveMode();
        if (desiredActiveMode && display->getActiveMode() == desiredActiveMode->modeOpt) {
        if (desiredActiveMode && display->getActiveMode() == desiredActiveMode->modeOpt) {
            desiredActiveModeChangeDone(display);
            desiredActiveModeChangeDone(display);
@@ -2398,7 +2394,10 @@ bool SurfaceFlinger::updateLayerSnapshots(VsyncId vsyncId, nsecs_t frameTimeNs,
    return mustComposite;
    return mustComposite;
}
}


bool SurfaceFlinger::commit(const scheduler::FrameTarget& pacesetterFrameTarget) {
bool SurfaceFlinger::commit(PhysicalDisplayId pacesetterId,
                            const scheduler::FrameTargets& frameTargets) {
    const scheduler::FrameTarget& pacesetterFrameTarget = *frameTargets.get(pacesetterId)->get();

    const VsyncId vsyncId = pacesetterFrameTarget.vsyncId();
    const VsyncId vsyncId = pacesetterFrameTarget.vsyncId();
    ATRACE_NAME(ftl::Concat(__func__, ' ', ftl::to_underlying(vsyncId)).c_str());
    ATRACE_NAME(ftl::Concat(__func__, ' ', ftl::to_underlying(vsyncId)).c_str());


@@ -2411,20 +2410,35 @@ bool SurfaceFlinger::commit(const scheduler::FrameTarget& pacesetterFrameTarget)
        mTracingEnabledChanged = false;
        mTracingEnabledChanged = false;
    }
    }


    // If we are in the middle of a mode change and the fence hasn't
    // If a mode set is pending and the fence hasn't fired yet, wait for the next commit.
    // fired yet just wait for the next commit.
    if (std::any_of(frameTargets.begin(), frameTargets.end(),
    if (mSetActiveModePending) {
                    [this](const auto& pair) FTL_FAKE_GUARD(mStateLock)
        if (pacesetterFrameTarget.isFramePending()) {
                            FTL_FAKE_GUARD(kMainThreadContext) {
                                if (!pair.second->isFramePending()) return false;

                                if (const auto display = getDisplayDeviceLocked(pair.first)) {
                                    return display->isModeSetPending();
                                }

                                return false;
                            })) {
        mScheduler->scheduleFrame();
        mScheduler->scheduleFrame();
        return false;
        return false;
    }
    }


        // We received the present fence from the HWC, so we assume it successfully updated
        // the mode, hence we update SF.
        mSetActiveModePending = false;
    {
    {
        Mutex::Autolock lock(mStateLock);
        Mutex::Autolock lock(mStateLock);
            updateInternalStateWithChangedMode();

        for (const auto [id, target] : frameTargets) {
            // TODO(b/241285876): This is `nullptr` when the DisplayDevice is about to be removed in
            // this commit, since the PhysicalDisplay has already been removed. Rather than checking
            // for `nullptr` below, change Scheduler::onFrameSignal to filter out the FrameTarget of
            // the removed display.
            const auto display = getDisplayDeviceLocked(id);

            if (display && display->isModeSetPending()) {
                finalizeDisplayModeChange(*display);
            }
        }
        }
    }
    }


@@ -2515,7 +2529,7 @@ bool SurfaceFlinger::commit(const scheduler::FrameTarget& pacesetterFrameTarget)
                                                        ? &mLayerHierarchyBuilder.getHierarchy()
                                                        ? &mLayerHierarchyBuilder.getHierarchy()
                                                        : nullptr,
                                                        : nullptr,
                                                updateAttachedChoreographer);
                                                updateAttachedChoreographer);
        setActiveModeInHwcIfNeeded();
        initiateDisplayModeChanges();
    }
    }


    updateCursorAsync();
    updateCursorAsync();
@@ -3322,6 +3336,16 @@ void SurfaceFlinger::dispatchDisplayHotplugEvent(PhysicalDisplayId displayId, bo
    mScheduler->onHotplugReceived(mSfConnectionHandle, displayId, connected);
    mScheduler->onHotplugReceived(mSfConnectionHandle, displayId, connected);
}
}


void SurfaceFlinger::dispatchDisplayModeChangeEvent(PhysicalDisplayId displayId,
                                                    const scheduler::FrameRateMode& mode) {
    // TODO(b/255635821): Merge code paths and move to Scheduler.
    const auto onDisplayModeChanged = displayId == mActiveDisplayId
            ? &scheduler::Scheduler::onPrimaryDisplayModeChanged
            : &scheduler::Scheduler::onNonPrimaryDisplayModeChanged;

    ((*mScheduler).*onDisplayModeChanged)(mAppConnectionHandle, mode);
}

sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal(
sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal(
        const wp<IBinder>& displayToken,
        const wp<IBinder>& displayToken,
        std::shared_ptr<compositionengine::Display> compositionDisplay,
        std::shared_ptr<compositionengine::Display> compositionDisplay,
@@ -3420,14 +3444,8 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal(
                                                    RenderIntent::COLORIMETRIC});
                                                    RenderIntent::COLORIMETRIC});


    if (const auto& physical = state.physical) {
    if (const auto& physical = state.physical) {
        mPhysicalDisplays.get(physical->id)
        const auto& mode = *physical->activeMode;
                .transform(&PhysicalDisplay::snapshotRef)
        display->setActiveMode(mode.getId(), mode.getFps(), mode.getFps());
                .transform(ftl::unit_fn([&](const display::DisplaySnapshot& snapshot) {
                    FTL_FAKE_GUARD(kMainThreadContext,
                                   display->setActiveMode(physical->activeMode->getId(),
                                                          physical->activeMode->getFps(),
                                                          physical->activeMode->getFps()));
                }));
    }
    }


    display->setLayerFilter(makeLayerFilterForDisplay(display->getId(), state.layerStack));
    display->setLayerFilter(makeLayerFilterForDisplay(display->getId(), state.layerStack));
@@ -3946,12 +3964,8 @@ void SurfaceFlinger::requestDisplayModes(std::vector<display::DisplayModeRequest


        if (!display) continue;
        if (!display) continue;


        const bool isInternalDisplay = mPhysicalDisplays.get(displayId)
        if (!display->isPoweredOn()) {
                                               .transform(&PhysicalDisplay::isInternal)
            ALOGV("%s(%s): Display is powered off", __func__, to_string(displayId).c_str());
                                               .value_or(false);

        if (isInternalDisplay && displayId != mActiveDisplayId) {
            ALOGV("%s(%s): Inactive display", __func__, to_string(displayId).c_str());
            continue;
            continue;
        }
        }


@@ -3959,7 +3973,7 @@ void SurfaceFlinger::requestDisplayModes(std::vector<display::DisplayModeRequest
            setDesiredActiveMode(std::move(request));
            setDesiredActiveMode(std::move(request));
        } else {
        } else {
            ALOGV("%s: Mode %d is disallowed for display %s", __func__, modePtr->getId().value(),
            ALOGV("%s: Mode %d is disallowed for display %s", __func__, modePtr->getId().value(),
                  to_string(display->getId()).c_str());
                  to_string(displayId).c_str());
        }
        }
    }
    }
}
}
@@ -7922,6 +7936,7 @@ status_t SurfaceFlinger::setDesiredDisplayModeSpecsInternal(
        const sp<DisplayDevice>& display,
        const sp<DisplayDevice>& display,
        const scheduler::RefreshRateSelector::PolicyVariant& policy) {
        const scheduler::RefreshRateSelector::PolicyVariant& policy) {
    const auto displayId = display->getPhysicalId();
    const auto displayId = display->getPhysicalId();
    ATRACE_NAME(ftl::Concat(__func__, ' ', displayId.value).c_str());


    Mutex::Autolock lock(mStateLock);
    Mutex::Autolock lock(mStateLock);


@@ -7942,13 +7957,11 @@ status_t SurfaceFlinger::setDesiredDisplayModeSpecsInternal(
            break;
            break;
    }
    }


    const bool isInternalDisplay = mPhysicalDisplays.get(displayId)
    // TODO(b/255635711): Apply the policy once the display is powered on, which is currently only
                                           .transform(&PhysicalDisplay::isInternal)
    // done for the internal display that becomes active on fold/unfold. For now, assume that DM
                                           .value_or(false);
    // always powers on the secondary (internal or external) display before setting its policy.

    if (!display->isPoweredOn()) {
    if (isInternalDisplay && displayId != mActiveDisplayId) {
        ALOGV("%s(%s): Display is powered off", __func__, to_string(displayId).c_str());
        // The policy will be be applied when the display becomes active.
        ALOGV("%s(%s): Inactive display", __func__, to_string(displayId).c_str());
        return NO_ERROR;
        return NO_ERROR;
    }
    }


@@ -8311,7 +8324,9 @@ void SurfaceFlinger::onActiveDisplayChangedLocked(const DisplayDevice* inactiveD


    resetPhaseConfiguration(activeDisplay.getActiveMode().fps);
    resetPhaseConfiguration(activeDisplay.getActiveMode().fps);


    // TODO(b/255635711): Check for pending mode changes on other displays.
    mScheduler->setModeChangePending(false);
    mScheduler->setModeChangePending(false);

    mScheduler->setPacesetterDisplay(mActiveDisplayId);
    mScheduler->setPacesetterDisplay(mActiveDisplayId);


    onActiveDisplaySizeChanged(activeDisplay);
    onActiveDisplaySizeChanged(activeDisplay);
Loading