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

Commit 2e9dd873 authored by Rachel Lee's avatar Rachel Lee Committed by Android (Google) Code Review
Browse files

Merge "HighHint touch boost fix re. frame rate override" into main

parents 5ee9c8d9 93bec07b
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) {