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

Commit 19f01d0e authored by Rachel Lee's avatar Rachel Lee
Browse files

NoPreference frame rate category is no-op

Change NoPreference frame rate category to behave like a no-op.
When all layers are NoPreference votes, the current frame rate should be
used, instead of choosing Min.
This also allows idle timer to trigger.

Bug: 328084518
Test: atest libsurfaceflinger_unittest
Test: Manual sysui jank suit
Change-Id: Ibe25ab8427367c5b86a1eaf0ed43434b6d270691
parent 22a71fb4
Loading
Loading
Loading
Loading
+14 −4
Original line number Diff line number Diff line
@@ -506,6 +506,8 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi
    }

    int noVoteLayers = 0;
    // Layers that prefer the same mode ("no-op").
    int noPreferenceLayers = 0;
    int minVoteLayers = 0;
    int maxVoteLayers = 0;
    int explicitDefaultVoteLayers = 0;
@@ -549,10 +551,7 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi
                    explicitCategoryVoteLayers++;
                }
                if (layer.frameRateCategory == FrameRateCategory::NoPreference) {
                    // Count this layer for Min vote as well. The explicit vote avoids
                    // touch boost and idle for choosing a category, while Min vote is for correct
                    // behavior when all layers are Min or no vote.
                    minVoteLayers++;
                    noPreferenceLayers++;
                }
                break;
            case LayerVoteType::Heuristic:
@@ -612,6 +611,16 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi
        return {ranking, kNoSignals};
    }

    // If all layers are category NoPreference, use the current config.
    if (noPreferenceLayers + noVoteLayers == layers.size()) {
        ALOGV("All layers NoPreference");
        const auto ascendingWithPreferred =
                rankFrameRates(anchorGroup, RefreshRateOrder::Ascending, activeMode.getId());
        ATRACE_FORMAT_INSTANT("%s (All layers NoPreference)",
                              to_string(ascendingWithPreferred.front().frameRateMode.fps).c_str());
        return {ascendingWithPreferred, kNoSignals};
    }

    const bool smoothSwitchOnly = categorySmoothSwitchOnlyLayers > 0;
    const DisplayModeId activeModeId = activeMode.getId();

@@ -643,6 +652,7 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi
              ftl::enum_string(layer.frameRateCategory).c_str());
        if (layer.isNoVote() || layer.frameRateCategory == FrameRateCategory::NoPreference ||
            layer.vote == LayerVoteType::Min) {
            ALOGV("%s scoring skipped due to vote", formatLayerInfo(layer, layer.weight).c_str());
            continue;
        }

+133 −10
Original line number Diff line number Diff line
@@ -295,6 +295,12 @@ protected:
                    << "Did not get expected frame rate for frameRate="
                    << to_string(testCase.desiredFrameRate)
                    << " category=" << ftl::enum_string(testCase.frameRateCategory);
            EXPECT_EQ(testCase.expectedModeId,
                      selector.getBestFrameRateMode(layers).modePtr->getId())
                    << "Did not get expected DisplayModeId for modeId="
                    << ftl::to_underlying(testCase.expectedModeId)
                    << " frameRate=" << to_string(testCase.desiredFrameRate)
                    << " category=" << ftl::enum_string(testCase.frameRateCategory);
        }
    }
};
@@ -1534,7 +1540,7 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_withFrameRateCategory_30_60
            {0_Hz, FrameRateCategory::High, 90_Hz},
            {0_Hz, FrameRateCategory::Normal, 60_Hz},
            {0_Hz, FrameRateCategory::Low, 30_Hz},
            {0_Hz, FrameRateCategory::NoPreference, 30_Hz},
            {0_Hz, FrameRateCategory::NoPreference, 60_Hz},

            // Cases that have both desired frame rate and frame rate category requirements.
            {24_Hz, FrameRateCategory::High, 120_Hz},
@@ -1591,6 +1597,7 @@ TEST_P(RefreshRateSelectorTest,

        // Expected result
        Fps expectedFrameRate = 0_Hz;
        DisplayModeId expectedModeId = kModeId90;
    };

    testFrameRateCategoryWithMultipleLayers(
@@ -1605,7 +1612,7 @@ TEST_P(RefreshRateSelectorTest,

    testFrameRateCategoryWithMultipleLayers(
            std::initializer_list<Case>{
                    {0_Hz, FrameRateCategory::Normal, 60_Hz},
                    {0_Hz, FrameRateCategory::Normal, 60_Hz, kModeId60},
                    {0_Hz, FrameRateCategory::High, 90_Hz},
                    {0_Hz, FrameRateCategory::NoPreference, 90_Hz},
            },
@@ -1614,18 +1621,18 @@ TEST_P(RefreshRateSelectorTest,
    testFrameRateCategoryWithMultipleLayers(
            std::initializer_list<Case>{
                    {30_Hz, FrameRateCategory::High, 90_Hz},
                    {24_Hz, FrameRateCategory::High, 120_Hz},
                    {12_Hz, FrameRateCategory::Normal, 120_Hz},
                    {30_Hz, FrameRateCategory::NoPreference, 120_Hz},
                    {24_Hz, FrameRateCategory::High, 120_Hz, kModeId120},
                    {12_Hz, FrameRateCategory::Normal, 120_Hz, kModeId120},
                    {30_Hz, FrameRateCategory::NoPreference, 120_Hz, kModeId120},

            },
            selector);

    testFrameRateCategoryWithMultipleLayers(
            std::initializer_list<Case>{
                    {24_Hz, FrameRateCategory::Default, 120_Hz},
                    {30_Hz, FrameRateCategory::Default, 120_Hz},
                    {120_Hz, FrameRateCategory::Default, 120_Hz},
                    {24_Hz, FrameRateCategory::Default, 120_Hz, kModeId120},
                    {30_Hz, FrameRateCategory::Default, 120_Hz, kModeId120},
                    {120_Hz, FrameRateCategory::Default, 120_Hz, kModeId120},
            },
            selector);
}
@@ -1640,6 +1647,7 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_withFrameRateCategoryMultiL

        // Expected result
        Fps expectedFrameRate = 0_Hz;
        DisplayModeId expectedModeId = kModeId120;
    };

    testFrameRateCategoryWithMultipleLayers(std::initializer_list<
@@ -1969,6 +1977,122 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_withFrameRateCategory_Touch
    EXPECT_FALSE(actualRankedFrameRates.consideredSignals.touch);
}

TEST_P(RefreshRateSelectorTest,
       getBestFrameRateMode_withFrameRateCategory_idleTimer_60_120_nonVrr) {
    SET_FLAG_FOR_TEST(flags::vrr_config, false);
    using KernelIdleTimerAction = RefreshRateSelector::KernelIdleTimerAction;
    struct LayerArg {
        // Params
        FrameRateCategory frameRateCategory = FrameRateCategory::Default;
        LayerVoteType voteType = LayerVoteType::ExplicitDefault;

        // Expected result
        Fps expectedFrameRate = 0_Hz;
        DisplayModeId expectedModeId = kModeId60;
    };

    const auto runTest = [&](const TestableRefreshRateSelector& selector,
                             const std::initializer_list<LayerArg>& layerArgs,
                             const RefreshRateSelector::GlobalSignals& signals) {
        std::vector<LayerRequirement> layers;
        for (auto testCase : layerArgs) {
            ALOGI("**** %s: Testing frameRateCategory=%s", __func__,
                  ftl::enum_string(testCase.frameRateCategory).c_str());

            if (testCase.frameRateCategory != FrameRateCategory::Default) {
                std::stringstream ss;
                ss << "ExplicitCategory (" << ftl::enum_string(testCase.frameRateCategory) << ")";
                LayerRequirement layer = {.name = ss.str(),
                                          .vote = LayerVoteType::ExplicitCategory,
                                          .frameRateCategory = testCase.frameRateCategory,
                                          .weight = 1.f};
                layers.push_back(layer);
            }

            if (testCase.voteType != LayerVoteType::ExplicitDefault) {
                std::stringstream ss;
                ss << ftl::enum_string(testCase.voteType);
                LayerRequirement layer = {.name = ss.str(),
                                          .vote = testCase.voteType,
                                          .weight = 1.f};
                layers.push_back(layer);
            }

            EXPECT_EQ(testCase.expectedFrameRate,
                      selector.getBestFrameRateMode(layers, signals).modePtr->getPeakFps())
                    << "Did not get expected frame rate for"
                    << " category=" << ftl::enum_string(testCase.frameRateCategory);
            EXPECT_EQ(testCase.expectedModeId,
                      selector.getBestFrameRateMode(layers, signals).modePtr->getId())
                    << "Did not get expected DisplayModeId for modeId="
                    << ftl::to_underlying(testCase.expectedModeId)
                    << " category=" << ftl::enum_string(testCase.frameRateCategory);
        }
    };

    {
        // IdleTimer not configured
        auto selector = createSelector(makeModes(kMode60, kMode120), kModeId120);
        ASSERT_EQ(0ms, selector.getIdleTimerTimeout());

        runTest(selector,
                std::initializer_list<LayerArg>{
                        // Rate does not change due to NoPreference.
                        {.frameRateCategory = FrameRateCategory::NoPreference,
                         .expectedFrameRate = 120_Hz,
                         .expectedModeId = kModeId120},
                        {.voteType = LayerVoteType::NoVote,
                         .expectedFrameRate = 120_Hz,
                         .expectedModeId = kModeId120},
                        {.frameRateCategory = FrameRateCategory::NoPreference,
                         .expectedFrameRate = 120_Hz,
                         .expectedModeId = kModeId120},
                },
                {.idle = false});
    }

    // IdleTimer configured
    constexpr std::chrono::milliseconds kIdleTimerTimeoutMs = 10ms;
    auto selector = createSelector(makeModes(kMode60, kMode120), kModeId120,
                                   Config{
                                           .idleTimerTimeout = kIdleTimerTimeoutMs,
                                   });
    ASSERT_EQ(KernelIdleTimerAction::TurnOn, selector.getIdleTimerAction());
    ASSERT_EQ(kIdleTimerTimeoutMs, selector.getIdleTimerTimeout());
    runTest(selector,
            std::initializer_list<LayerArg>{
                    // Rate won't change immediately and will stay 120 due to NoPreference, as
                    // idle timer did not timeout yet.
                    {.frameRateCategory = FrameRateCategory::NoPreference,
                     .expectedFrameRate = 120_Hz,
                     .expectedModeId = kModeId120},
                    {.voteType = LayerVoteType::NoVote,
                     .expectedFrameRate = 120_Hz,
                     .expectedModeId = kModeId120},
                    {.frameRateCategory = FrameRateCategory::NoPreference,
                     .expectedFrameRate = 120_Hz,
                     .expectedModeId = kModeId120},
            },
            {.idle = false});

    // Idle timer is triggered using GlobalSignals.
    ASSERT_EQ(KernelIdleTimerAction::TurnOn, selector.getIdleTimerAction());
    ASSERT_EQ(kIdleTimerTimeoutMs, selector.getIdleTimerTimeout());
    runTest(selector,
            std::initializer_list<LayerArg>{
                    {.frameRateCategory = FrameRateCategory::NoPreference,
                     .expectedFrameRate = 60_Hz,
                     .expectedModeId = kModeId60},
                    {.voteType = LayerVoteType::NoVote,
                     .expectedFrameRate = 60_Hz,
                     .expectedModeId = kModeId60},
                    {.frameRateCategory = FrameRateCategory::NoPreference,
                     .expectedFrameRate = 60_Hz,
                     .expectedModeId = kModeId60},
            },
            {.idle = true});
}

TEST_P(RefreshRateSelectorTest,
       getBestFrameRateMode_withFrameRateCategory_smoothSwitchOnly_60_120_nonVrr) {
    if (GetParam() != Config::FrameRateOverride::Enabled) {
@@ -1992,8 +2116,7 @@ TEST_P(RefreshRateSelectorTest,
    const std::initializer_list<Case> testCases = {
            // These layers may switch modes because smoothSwitchOnly=false.
            {FrameRateCategory::Default, false, 120_Hz, kModeId120},
            // TODO(b/266481656): Once this bug is fixed, NoPreference should be a lower frame rate.
            {FrameRateCategory::NoPreference, false, 60_Hz, kModeId60},
            {FrameRateCategory::NoPreference, false, 120_Hz, kModeId120},
            {FrameRateCategory::Low, false, 30_Hz, kModeId60},
            {FrameRateCategory::Normal, false, 60_Hz, kModeId60},
            {FrameRateCategory::High, false, 120_Hz, kModeId120},