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

Commit 36dced86 authored by Dominik Laskowski's avatar Dominik Laskowski
Browse files

SF: Refactor setter for DM and override policy

Move DisplayDevice::setRefreshRatePolicy to RefreshRateConfigs, and
merge the repetitive set{DisplayManager,Override}Policy helpers.

Improve type correctness of the parameters and return value.

Bug: 241285191
Test: libsurfaceflinger_unittest
Change-Id: Iee87316e5702282b828bc3f28cd7d30041030ed5
parent 788945b0
Loading
Loading
Loading
Loading
+0 −22
Original line number Diff line number Diff line
@@ -216,7 +216,6 @@ status_t DisplayDevice::initiateModeChange(const ActiveModeInfo& info,
              to_string(getId()).c_str());
        return BAD_VALUE;
    }
    mNumModeSwitchesInPolicy++;
    mUpcomingActiveMode = info;
    ATRACE_INT(mActiveModeFPSHwcTrace.c_str(), info.mode->getFps().getIntValue());
    return mHwComposer.setActiveModeWithConstraints(getPhysicalId(), info.mode->getHwcId(),
@@ -498,27 +497,6 @@ void DisplayDevice::clearDesiredActiveModeState() {
    mDesiredActiveModeChanged = false;
}

status_t DisplayDevice::setRefreshRatePolicy(
        const std::optional<scheduler::RefreshRateConfigs::Policy>& policy, bool overridePolicy) {
    const auto oldPolicy = mRefreshRateConfigs->getCurrentPolicy();
    const status_t setPolicyResult = overridePolicy
            ? mRefreshRateConfigs->setOverridePolicy(policy)
            : mRefreshRateConfigs->setDisplayManagerPolicy(*policy);

    if (setPolicyResult == OK) {
        const int numModeChanges = mNumModeSwitchesInPolicy.exchange(0);

        ALOGI("Display %s policy changed\n"
              "Previous: {%s}\n"
              "Current:  {%s}\n"
              "%d mode changes were performed under the previous policy",
              to_string(getId()).c_str(), oldPolicy.toString().c_str(),
              policy ? policy->toString().c_str() : "null", numModeChanges);
    }

    return setPolicyResult;
}

std::atomic<int32_t> DisplayDeviceState::sNextSequenceId(1);

}  // namespace android
+0 −6
Original line number Diff line number Diff line
@@ -236,10 +236,6 @@ public:

    nsecs_t getVsyncPeriodFromHWC() const;

    status_t setRefreshRatePolicy(
            const std::optional<scheduler::RefreshRateConfigs::Policy>& policy,
            bool overridePolicy);

    // release HWC resources (if any) for removable displays
    void disconnect();

@@ -287,8 +283,6 @@ private:
    TracedOrdinal<bool> mDesiredActiveModeChanged
            GUARDED_BY(mActiveModeLock) = {"DesiredActiveModeChanged", false};
    ActiveModeInfo mUpcomingActiveMode GUARDED_BY(kMainThreadContext);

    std::atomic_int mNumModeSwitchesInPolicy = 0;
};

struct DisplayDeviceState {
+67 −27
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#include <android-base/stringprintf.h>
#include <ftl/enum.h>
#include <ftl/fake_guard.h>
#include <ftl/match.h>
#include <utils/Trace.h>

#include "../SurfaceFlingerProperties.h"
@@ -117,6 +118,20 @@ bool canModesSupportFrameRateOverride(const std::vector<DisplayModeIterator>& so
    return false;
}

std::string toString(const RefreshRateConfigs::PolicyVariant& policy) {
    using namespace std::string_literals;

    return ftl::match(
            policy,
            [](const RefreshRateConfigs::DisplayManagerPolicy& policy) {
                return "DisplayManagerPolicy"s + policy.toString();
            },
            [](const RefreshRateConfigs::OverridePolicy& policy) {
                return "OverridePolicy"s + policy.toString();
            },
            [](RefreshRateConfigs::NoOverridePolicy) { return "NoOverridePolicy"s; });
}

} // namespace

struct RefreshRateConfigs::RefreshRateScoreComparator {
@@ -874,35 +889,60 @@ bool RefreshRateConfigs::isPolicyValidLocked(const Policy& policy) const {
            policy.appRequestRange.max >= policy.primaryRange.max;
}

status_t RefreshRateConfigs::setDisplayManagerPolicy(const Policy& policy) {
auto RefreshRateConfigs::setPolicy(const PolicyVariant& policy) -> SetPolicyResult {
    Policy oldPolicy;
    {
        std::lock_guard lock(mLock);
        oldPolicy = *getCurrentPolicyLocked();

        const bool valid = ftl::match(
                policy,
                [this](const auto& policy) {
                    ftl::FakeGuard guard(mLock);
                    if (!isPolicyValidLocked(policy)) {
        ALOGE("Invalid refresh rate policy: %s", policy.toString().c_str());
        return BAD_VALUE;
                        ALOGE("Invalid policy: %s", policy.toString().c_str());
                        return false;
                    }
    mGetRankedRefreshRatesCache.reset();
    Policy previousPolicy = *getCurrentPolicyLocked();

                    using T = std::decay_t<decltype(policy)>;

                    if constexpr (std::is_same_v<T, DisplayManagerPolicy>) {
                        mDisplayManagerPolicy = policy;
    if (*getCurrentPolicyLocked() == previousPolicy) {
        return CURRENT_POLICY_UNCHANGED;
    }
    constructAvailableRefreshRates();
    return NO_ERROR;
                    } else {
                        static_assert(std::is_same_v<T, OverridePolicy>);
                        mOverridePolicy = policy;
                    }
                    return true;
                },
                [this](NoOverridePolicy) {
                    ftl::FakeGuard guard(mLock);
                    mOverridePolicy.reset();
                    return true;
                });

status_t RefreshRateConfigs::setOverridePolicy(const std::optional<Policy>& policy) {
    std::lock_guard lock(mLock);
    if (policy && !isPolicyValidLocked(*policy)) {
        return BAD_VALUE;
        if (!valid) {
            return SetPolicyResult::Invalid;
        }

        mGetRankedRefreshRatesCache.reset();
    Policy previousPolicy = *getCurrentPolicyLocked();
    mOverridePolicy = policy;
    if (*getCurrentPolicyLocked() == previousPolicy) {
        return CURRENT_POLICY_UNCHANGED;

        if (*getCurrentPolicyLocked() == oldPolicy) {
            return SetPolicyResult::Unchanged;
        }
        constructAvailableRefreshRates();
    return NO_ERROR;
    }

    const auto displayId = getActiveMode().getPhysicalDisplayId();
    const unsigned numModeChanges = std::exchange(mNumModeSwitchesInPolicy, 0u);

    ALOGI("Display %s policy changed\n"
          "Previous: %s\n"
          "Current:  %s\n"
          "%u mode changes were performed under the previous policy",
          to_string(displayId).c_str(), oldPolicy.toString().c_str(), toString(policy).c_str(),
          numModeChanges);

    return SetPolicyResult::Changed;
}

const RefreshRateConfigs::Policy* RefreshRateConfigs::getCurrentPolicyLocked() const {
+20 −13
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include <optional>
#include <type_traits>
#include <utility>
#include <variant>

#include <gui/DisplayEventReceiver.h>

@@ -67,8 +68,7 @@ public:
    static constexpr nsecs_t MARGIN_FOR_PERIOD_CALCULATION =
            std::chrono::nanoseconds(800us).count();

    struct Policy {
    private:
    class Policy {
        static constexpr int kAllowGroupSwitchingDefault = false;

    public:
@@ -118,23 +118,28 @@ public:
        std::string toString() const;
    };

    // Return code set*Policy() to indicate the current policy is unchanged.
    static constexpr int CURRENT_POLICY_UNCHANGED = 1;
    enum class SetPolicyResult { Invalid, Unchanged, Changed };

    // We maintain the display manager policy and the override policy separately. The override
    // policy is used by CTS tests to get a consistent device state for testing. While the override
    // policy is set, it takes precedence over the display manager policy. Once the override policy
    // is cleared, we revert to using the display manager policy.
    struct DisplayManagerPolicy : Policy {
        using Policy::Policy;
    };

    struct OverridePolicy : Policy {
        using Policy::Policy;
    };

    struct NoOverridePolicy {};

    using PolicyVariant = std::variant<DisplayManagerPolicy, OverridePolicy, NoOverridePolicy>;

    SetPolicyResult setPolicy(const PolicyVariant&) EXCLUDES(mLock) REQUIRES(kMainThreadContext);

    void onModeChangeInitiated() REQUIRES(kMainThreadContext) { mNumModeSwitchesInPolicy++; }

    // Sets the display manager policy to choose refresh rates. The return value will be:
    //   - A negative value if the policy is invalid or another error occurred.
    //   - NO_ERROR if the policy was successfully updated, and the current policy is different from
    //     what it was before the call.
    //   - CURRENT_POLICY_UNCHANGED if the policy was successfully updated, but the current policy
    //     is the same as it was before the call.
    status_t setDisplayManagerPolicy(const Policy& policy) EXCLUDES(mLock);
    // Sets the override policy. See setDisplayManagerPolicy() for the meaning of the return value.
    status_t setOverridePolicy(const std::optional<Policy>& policy) EXCLUDES(mLock);
    // Gets the current policy, which will be the override policy if active, and the display manager
    // policy otherwise.
    Policy getCurrentPolicy() const EXCLUDES(mLock);
@@ -418,6 +423,8 @@ private:
    Policy mDisplayManagerPolicy GUARDED_BY(mLock);
    std::optional<Policy> mOverridePolicy GUARDED_BY(mLock);

    unsigned mNumModeSwitchesInPolicy GUARDED_BY(kMainThreadContext) = 0;

    mutable std::mutex mLock;

    // A sorted list of known frame rates that a Heuristic layer will choose
+32 −30
Original line number Diff line number Diff line
@@ -1105,7 +1105,7 @@ status_t SurfaceFlinger::setActiveModeFromBackdoor(const sp<display::DisplayToke
    }

    const char* const whence = __func__;
    auto future = mScheduler->schedule([=]() -> status_t {
    auto future = mScheduler->schedule([=]() FTL_FAKE_GUARD(kMainThreadContext) -> status_t {
        const auto displayOpt =
                FTL_FAKE_GUARD(mStateLock,
                               ftl::find_if(mPhysicalDisplays,
@@ -1130,13 +1130,16 @@ status_t SurfaceFlinger::setActiveModeFromBackdoor(const sp<display::DisplayToke
        }

        const Fps fps = *fpsOpt;

        // Keep the old switching type.
        const bool allowGroupSwitching =
                display->refreshRateConfigs().getCurrentPolicy().allowGroupSwitching;
        const scheduler::RefreshRateConfigs::Policy policy{modeId, allowGroupSwitching, {fps, fps}};
        constexpr bool kOverridePolicy = false;

        return setDesiredDisplayModeSpecsInternal(display, policy, kOverridePolicy);
        const scheduler::RefreshRateConfigs::DisplayManagerPolicy policy{modeId,
                                                                         allowGroupSwitching,
                                                                         {fps, fps}};

        return setDesiredDisplayModeSpecsInternal(display, policy);
    });

    return future.get();
@@ -1273,6 +1276,8 @@ void SurfaceFlinger::setActiveModeInHwcIfNeeded() {
            ALOGW("initiateModeChange failed: %d", status);
            continue;
        }

        display->refreshRateConfigs().onModeChangeInitiated();
        mScheduler->onNewVsyncPeriodChangeTimeline(outTimeline);

        if (outTimeline.refreshRequired) {
@@ -5866,7 +5871,7 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r
            case 1036: {
                if (data.readInt32() > 0) { // turn on
                    return mScheduler
                            ->schedule([this] {
                            ->schedule([this]() FTL_FAKE_GUARD(kMainThreadContext) {
                                const auto display =
                                        FTL_FAKE_GUARD(mStateLock, getDefaultDisplayDeviceLocked());

@@ -5876,24 +5881,21 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r
                                // defaultMode. The defaultMode doesn't matter for the override
                                // policy though, since we set allowGroupSwitching to true, so it's
                                // not a problem.
                                scheduler::RefreshRateConfigs::Policy overridePolicy;
                                scheduler::RefreshRateConfigs::OverridePolicy overridePolicy;
                                overridePolicy.defaultMode = display->refreshRateConfigs()
                                                                     .getDisplayManagerPolicy()
                                                                     .defaultMode;
                                overridePolicy.allowGroupSwitching = true;
                                constexpr bool kOverridePolicy = true;
                                return setDesiredDisplayModeSpecsInternal(display, overridePolicy,
                                                                          kOverridePolicy);
                                return setDesiredDisplayModeSpecsInternal(display, overridePolicy);
                            })
                            .get();
                } else { // turn off
                    return mScheduler
                            ->schedule([this] {
                            ->schedule([this]() FTL_FAKE_GUARD(kMainThreadContext) {
                                const auto display =
                                        FTL_FAKE_GUARD(mStateLock, getDefaultDisplayDeviceLocked());
                                constexpr bool kOverridePolicy = true;
                                return setDesiredDisplayModeSpecsInternal(display, {},
                                                                          kOverridePolicy);
                                return setDesiredDisplayModeSpecsInternal(
                                        display, scheduler::RefreshRateConfigs::NoOverridePolicy{});
                            })
                            .get();
                }
@@ -6732,7 +6734,7 @@ std::optional<DisplayModePtr> SurfaceFlinger::getPreferredDisplayMode(

status_t SurfaceFlinger::setDesiredDisplayModeSpecsInternal(
        const sp<DisplayDevice>& display,
        const std::optional<scheduler::RefreshRateConfigs::Policy>& policy, bool overridePolicy) {
        const scheduler::RefreshRateConfigs::PolicyVariant& policy) {
    Mutex::Autolock lock(mStateLock);

    if (mDebugDisplayModeSetByBackdoor) {
@@ -6740,23 +6742,24 @@ status_t SurfaceFlinger::setDesiredDisplayModeSpecsInternal(
        return NO_ERROR;
    }

    const status_t setPolicyResult = display->setRefreshRatePolicy(policy, overridePolicy);
    if (setPolicyResult < 0) {
    auto& configs = display->refreshRateConfigs();
    using SetPolicyResult = scheduler::RefreshRateConfigs::SetPolicyResult;

    switch (configs.setPolicy(policy)) {
        case SetPolicyResult::Invalid:
            return BAD_VALUE;
    }
    if (setPolicyResult == scheduler::RefreshRateConfigs::CURRENT_POLICY_UNCHANGED) {
        case SetPolicyResult::Unchanged:
            return NO_ERROR;
        case SetPolicyResult::Changed:
            break;
    }

    const scheduler::RefreshRateConfigs::Policy currentPolicy =
            display->refreshRateConfigs().getCurrentPolicy();

    const scheduler::RefreshRateConfigs::Policy currentPolicy = configs.getCurrentPolicy();
    ALOGV("Setting desired display mode specs: %s", currentPolicy.toString().c_str());

    // TODO(b/140204874): Leave the event in until we do proper testing with all apps that might
    // be depending in this callback.
    const auto activeModePtr = display->refreshRateConfigs().getActiveModePtr();
    if (isDisplayActiveLocked(display)) {
    if (const auto activeModePtr = configs.getActiveModePtr(); isDisplayActiveLocked(display)) {
        mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, activeModePtr);
        toggleKernelIdleTimer();
    } else {
@@ -6776,7 +6779,7 @@ status_t SurfaceFlinger::setDesiredDisplayModeSpecsInternal(
    ALOGV("Switching to Scheduler preferred mode %d (%s)", preferredModeId.value(),
          to_string(preferredMode->getFps()).c_str());

    if (!display->refreshRateConfigs().isModeAllowed(preferredModeId)) {
    if (!configs.isModeAllowed(preferredModeId)) {
        ALOGE("%s: Preferred mode %d is disallowed", __func__, preferredModeId.value());
        return INVALID_OPERATION;
    }
@@ -6795,7 +6798,7 @@ status_t SurfaceFlinger::setDesiredDisplayModeSpecs(
        return BAD_VALUE;
    }

    auto future = mScheduler->schedule([=]() -> status_t {
    auto future = mScheduler->schedule([=]() FTL_FAKE_GUARD(kMainThreadContext) -> status_t {
        const auto display = FTL_FAKE_GUARD(mStateLock, getDisplayDeviceLocked(displayToken));
        if (!display) {
            ALOGE("Attempt to set desired display modes for invalid display token %p",
@@ -6805,16 +6808,15 @@ status_t SurfaceFlinger::setDesiredDisplayModeSpecs(
            ALOGW("Attempt to set desired display modes for virtual display");
            return INVALID_OPERATION;
        } else {
            using Policy = scheduler::RefreshRateConfigs::Policy;
            using Policy = scheduler::RefreshRateConfigs::DisplayManagerPolicy;
            const Policy policy{DisplayModeId(defaultMode),
                                allowGroupSwitching,
                                {Fps::fromValue(primaryRefreshRateMin),
                                 Fps::fromValue(primaryRefreshRateMax)},
                                {Fps::fromValue(appRequestRefreshRateMin),
                                 Fps::fromValue(appRequestRefreshRateMax)}};
            constexpr bool kOverridePolicy = false;

            return setDesiredDisplayModeSpecsInternal(display, policy, kOverridePolicy);
            return setDesiredDisplayModeSpecsInternal(display, policy);
        }
    });

Loading