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

Commit 93bec07b authored by Rachel Lee's avatar Rachel Lee
Browse files

HighHint touch boost fix re. frame rate override

Fix HighHint touch boost regarding frame rate override. The
touch boost logic in getFrameRateOverrides should mirror frame rate
selection in getRankedFrameRates. We decided earlier that HighHint is
only ignored when there are ExplicitDefault compatibility votes.

Bug: 326666127
Test: atest libsurfaceflinger_unittest
Test: jank test cases + manual
Change-Id: I54ac61f2a174b9a4dea7d67d8b196217b4f60921
parent ef9fb68e
Loading
Loading
Loading
Loading
+32 −6
Original line number Diff line number Diff line
@@ -948,17 +948,43 @@ auto RefreshRateSelector::getFrameRateOverrides(const std::vector<LayerRequireme
    const auto layersByUid = groupLayersByUid(layers);
    UidToFrameRateOverride frameRateOverrides;
    for (const auto& [uid, layersWithSameUid] : layersByUid) {
        // Layers with ExplicitExactOrMultiple expect touch boost
        const bool hasExplicitExactOrMultiple =
                std::any_of(layersWithSameUid.cbegin(), layersWithSameUid.cend(),
                            [](const auto& layer) {
                                return layer->vote == LayerVoteType::ExplicitExactOrMultiple;
                            });
        // Look for cases that should not have frame rate overrides.
        bool hasExplicitExactOrMultiple = false;
        bool hasExplicitDefault = false;
        bool hasHighHint = false;
        for (const auto& layer : layersWithSameUid) {
            switch (layer->vote) {
                case LayerVoteType::ExplicitExactOrMultiple:
                    hasExplicitExactOrMultiple = true;
                    break;
                case LayerVoteType::ExplicitDefault:
                    hasExplicitDefault = true;
                    break;
                case LayerVoteType::ExplicitCategory:
                    if (layer->frameRateCategory == FrameRateCategory::HighHint) {
                        hasHighHint = true;
                    }
                    break;
                default:
                    // No action
                    break;
            }
            if (hasExplicitExactOrMultiple && hasExplicitDefault && hasHighHint) {
                break;
            }
        }

        // Layers with ExplicitExactOrMultiple expect touch boost
        if (globalSignals.touch && hasExplicitExactOrMultiple) {
            continue;
        }

        // Mirrors getRankedFrameRates. If there is no ExplicitDefault, expect touch boost and
        // skip frame rate override.
        if (hasHighHint && !hasExplicitDefault) {
            continue;
        }

        for (auto& [_, score] : scoredFrameRates) {
            score = 0;
        }
+215 −0
Original line number Diff line number Diff line
@@ -3159,6 +3159,210 @@ TEST_P(RefreshRateSelectorTest, getFrameRateOverrides_twoUids) {
    EXPECT_TRUE(frameRateOverrides.empty());
}

TEST_P(RefreshRateSelectorTest, getFrameRateOverrides_withFrameRateCategory) {
    if (GetParam() == Config::FrameRateOverride::Disabled) {
        return;
    }

    ASSERT_TRUE(GetParam() == Config::FrameRateOverride::AppOverrideNativeRefreshRates ||
                GetParam() == Config::FrameRateOverride::AppOverride ||
                GetParam() == Config::FrameRateOverride::Enabled);

    auto selector = createSelector(kModes_30_60_72_90_120, kModeId120);

    std::vector<LayerRequirement> layers = {{.ownerUid = 1234, .weight = 1.f},
                                            {.ownerUid = 1234, .weight = 1.f}};

    // HighHint case with touch boost and thus should skip frame rate override.
    layers[0].name = "ExplicitCategory HighHint";
    layers[0].vote = LayerVoteType::ExplicitCategory;
    layers[0].desiredRefreshRate = 0_Hz;
    layers[0].frameRateCategory = FrameRateCategory::HighHint;
    layers[1].name = "ExplicitCategory High";
    layers[1].vote = LayerVoteType::ExplicitCategory;
    layers[1].desiredRefreshRate = 0_Hz;
    layers[1].frameRateCategory = FrameRateCategory::High;
    auto frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {});
    EXPECT_TRUE(frameRateOverrides.empty());
    frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {.touch = true});
    EXPECT_TRUE(frameRateOverrides.empty());

    // HighHint case with touch boost and thus should skip frame rate override.
    layers[0].name = "ExplicitCategory HighHint";
    layers[0].vote = LayerVoteType::ExplicitCategory;
    layers[0].desiredRefreshRate = 0_Hz;
    layers[0].frameRateCategory = FrameRateCategory::HighHint;
    layers[1].name = "ExplicitCategory Normal";
    layers[1].vote = LayerVoteType::ExplicitCategory;
    layers[1].desiredRefreshRate = 0_Hz;
    layers[1].frameRateCategory = FrameRateCategory::Normal;
    frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {});
    EXPECT_TRUE(frameRateOverrides.empty());
    frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {.touch = true});
    EXPECT_TRUE(frameRateOverrides.empty());

    // HighHint case with touch boost and thus should skip frame rate override.
    layers[0].name = "ExplicitCategory HighHint";
    layers[0].vote = LayerVoteType::ExplicitCategory;
    layers[0].desiredRefreshRate = 0_Hz;
    layers[0].frameRateCategory = FrameRateCategory::HighHint;
    layers[1].name = "ExplicitCategory Low";
    layers[1].vote = LayerVoteType::ExplicitCategory;
    layers[1].desiredRefreshRate = 0_Hz;
    layers[1].frameRateCategory = FrameRateCategory::Low;
    frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {});
    EXPECT_TRUE(frameRateOverrides.empty());
    frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {.touch = true});
    EXPECT_TRUE(frameRateOverrides.empty());

    // HighHint case with touch boost and thus should skip frame rate override.
    layers[0].name = "ExplicitCategory HighHint";
    layers[0].vote = LayerVoteType::ExplicitCategory;
    layers[0].desiredRefreshRate = 0_Hz;
    layers[0].frameRateCategory = FrameRateCategory::HighHint;
    layers[1].name = "ExplicitCategory NoPreference";
    layers[1].vote = LayerVoteType::ExplicitCategory;
    layers[1].desiredRefreshRate = 0_Hz;
    layers[1].frameRateCategory = FrameRateCategory::NoPreference;
    frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {});
    EXPECT_TRUE(frameRateOverrides.empty());
    frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {.touch = true});
    EXPECT_TRUE(frameRateOverrides.empty());

    // HighHint case *without* touch boost has frame rate override.
    // For example, game and touch interaction.
    layers[0].name = "ExplicitCategory HighHint";
    layers[0].vote = LayerVoteType::ExplicitCategory;
    layers[0].desiredRefreshRate = 0_Hz;
    layers[0].frameRateCategory = FrameRateCategory::HighHint;
    layers[1].name = "ExplicitDefault 60";
    layers[1].vote = LayerVoteType::ExplicitDefault;
    layers[1].desiredRefreshRate = 60_Hz;
    layers[1].frameRateCategory = FrameRateCategory::Default;
    frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {});
    EXPECT_EQ(1u, frameRateOverrides.size());
    ASSERT_EQ(1u, frameRateOverrides.count(1234));
    EXPECT_EQ(60_Hz, frameRateOverrides.at(1234));
    frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {.touch = true});
    EXPECT_EQ(1u, frameRateOverrides.size());
    ASSERT_EQ(1u, frameRateOverrides.count(1234));
    EXPECT_EQ(60_Hz, frameRateOverrides.at(1234));

    // HighHint case with touch boost and thus should skip frame rate override.
    layers[0].name = "ExplicitCategory HighHint";
    layers[0].vote = LayerVoteType::ExplicitCategory;
    layers[0].desiredRefreshRate = 0_Hz;
    layers[0].frameRateCategory = FrameRateCategory::HighHint;
    layers[1].name = "ExplicitExactOrMultiple 30";
    layers[1].vote = LayerVoteType::ExplicitExactOrMultiple;
    layers[1].desiredRefreshRate = 30_Hz;
    layers[1].frameRateCategory = FrameRateCategory::Default;
    frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {});
    EXPECT_TRUE(frameRateOverrides.empty());
    frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {.touch = true});
    EXPECT_TRUE(frameRateOverrides.empty());

    // HighHint case with touch boost and thus should skip frame rate override.
    layers[0].name = "ExplicitCategory HighHint";
    layers[0].vote = LayerVoteType::ExplicitCategory;
    layers[0].desiredRefreshRate = 0_Hz;
    layers[0].frameRateCategory = FrameRateCategory::HighHint;
    layers[1].name = "ExplicitExact 60";
    layers[1].vote = LayerVoteType::ExplicitExact;
    layers[1].desiredRefreshRate = 60_Hz;
    layers[1].frameRateCategory = FrameRateCategory::Default;
    frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {});
    EXPECT_TRUE(frameRateOverrides.empty());
    frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {.touch = true});
    EXPECT_TRUE(frameRateOverrides.empty());

    // HighHint case with touch boost and thus should skip frame rate override.
    layers[0].name = "ExplicitCategory HighHint";
    layers[0].vote = LayerVoteType::ExplicitCategory;
    layers[0].desiredRefreshRate = 0_Hz;
    layers[0].frameRateCategory = FrameRateCategory::HighHint;
    layers[1].name = "ExplicitGte 60";
    layers[1].vote = LayerVoteType::ExplicitGte;
    layers[1].desiredRefreshRate = 60_Hz;
    layers[1].frameRateCategory = FrameRateCategory::Default;
    frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {});
    EXPECT_TRUE(frameRateOverrides.empty());
    frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {.touch = true});
    EXPECT_TRUE(frameRateOverrides.empty());

    // ExplicitCategory case that expects no global touch boost and thus has frame rate override.
    layers[0].name = "ExplicitDefault 60";
    layers[0].vote = LayerVoteType::ExplicitDefault;
    layers[0].desiredRefreshRate = 60_Hz;
    layers[0].frameRateCategory = FrameRateCategory::Default;
    layers[1].name = "ExplicitCategory High";
    layers[1].vote = LayerVoteType::ExplicitCategory;
    layers[1].desiredRefreshRate = 0_Hz;
    layers[1].frameRateCategory = FrameRateCategory::High;
    frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {});
    EXPECT_EQ(1u, frameRateOverrides.size());
    ASSERT_EQ(1u, frameRateOverrides.count(1234));
    EXPECT_EQ(120_Hz, frameRateOverrides.at(1234));
    frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {.touch = true});
    EXPECT_EQ(1u, frameRateOverrides.size());
    ASSERT_EQ(1u, frameRateOverrides.count(1234));
    EXPECT_EQ(120_Hz, frameRateOverrides.at(1234));

    // ExplicitCategory case that expects no global touch boost and thus has frame rate override.
    layers[0].name = "ExplicitDefault 60";
    layers[0].vote = LayerVoteType::ExplicitDefault;
    layers[0].desiredRefreshRate = 60_Hz;
    layers[0].frameRateCategory = FrameRateCategory::Default;
    layers[1].name = "ExplicitCategory Normal";
    layers[1].vote = LayerVoteType::ExplicitCategory;
    layers[1].desiredRefreshRate = 0_Hz;
    layers[1].frameRateCategory = FrameRateCategory::Normal;
    frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {});
    EXPECT_EQ(1u, frameRateOverrides.size());
    ASSERT_EQ(1u, frameRateOverrides.count(1234));
    EXPECT_EQ(60_Hz, frameRateOverrides.at(1234));
    frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {.touch = true});
    EXPECT_EQ(1u, frameRateOverrides.size());
    ASSERT_EQ(1u, frameRateOverrides.count(1234));
    EXPECT_EQ(60_Hz, frameRateOverrides.at(1234));

    // ExplicitCategory case that expects no global touch boost and thus has frame rate override.
    layers[0].name = "ExplicitDefault 60";
    layers[0].vote = LayerVoteType::ExplicitDefault;
    layers[0].desiredRefreshRate = 60_Hz;
    layers[0].frameRateCategory = FrameRateCategory::Default;
    layers[1].name = "ExplicitCategory Low";
    layers[1].vote = LayerVoteType::ExplicitCategory;
    layers[1].desiredRefreshRate = 0_Hz;
    layers[1].frameRateCategory = FrameRateCategory::Low;
    frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {});
    EXPECT_EQ(1u, frameRateOverrides.size());
    ASSERT_EQ(1u, frameRateOverrides.count(1234));
    EXPECT_EQ(60_Hz, frameRateOverrides.at(1234));
    frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {.touch = true});
    EXPECT_EQ(1u, frameRateOverrides.size());
    ASSERT_EQ(1u, frameRateOverrides.count(1234));
    EXPECT_EQ(60_Hz, frameRateOverrides.at(1234));

    // ExplicitCategory case that expects no global touch boost and thus has frame rate override.
    layers[0].name = "ExplicitDefault 60";
    layers[0].vote = LayerVoteType::ExplicitDefault;
    layers[0].desiredRefreshRate = 60_Hz;
    layers[0].frameRateCategory = FrameRateCategory::Default;
    layers[1].name = "ExplicitCategory NoPreference";
    layers[1].vote = LayerVoteType::ExplicitCategory;
    layers[1].desiredRefreshRate = 0_Hz;
    layers[1].frameRateCategory = FrameRateCategory::NoPreference;
    frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {});
    EXPECT_EQ(1u, frameRateOverrides.size());
    ASSERT_EQ(1u, frameRateOverrides.count(1234));
    EXPECT_EQ(60_Hz, frameRateOverrides.at(1234));
    frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {.touch = true});
    EXPECT_EQ(1u, frameRateOverrides.size());
    ASSERT_EQ(1u, frameRateOverrides.count(1234));
    EXPECT_EQ(60_Hz, frameRateOverrides.at(1234));
}

TEST_P(RefreshRateSelectorTest, getFrameRateOverrides_touch) {
    if (GetParam() == Config::FrameRateOverride::Disabled) {
        return;
@@ -3204,6 +3408,17 @@ TEST_P(RefreshRateSelectorTest, getFrameRateOverrides_touch) {

    frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {.touch = true});
    EXPECT_TRUE(frameRateOverrides.empty());

    layers[0].vote = LayerVoteType::ExplicitGte;
    frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {});
    EXPECT_EQ(1u, frameRateOverrides.size());
    ASSERT_EQ(1u, frameRateOverrides.count(1234));
    EXPECT_EQ(60_Hz, frameRateOverrides.at(1234));

    frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {.touch = true});
    EXPECT_EQ(1u, frameRateOverrides.size());
    ASSERT_EQ(1u, frameRateOverrides.count(1234));
    EXPECT_EQ(60_Hz, frameRateOverrides.at(1234));
}

TEST_P(RefreshRateSelectorTest, getFrameRateOverrides_DivisorIsNotDisplayRefreshRate) {