Add FrameRateOverrideMappings unit test
- Add unit test
- Modify Scheduler and FrameRateOverrideMappings to check
supportFrameRateOverrideByContent in getAllFrameRateOverrides
- Remove flag usage in Scheduler to keep it within
FrameRateOverrideMappings class
- Add operator== for FrameRateOverride event to enable ASSERT_EQ
Bug: b/204322816, b/216445833
Test: atest libsurfaceflinger_unittest:FrameRateOverrideMappingsTest
Change-Id: Ie8717e76cb1bcfeefac93a7093ee30581767c18b
diff --git a/services/surfaceflinger/Scheduler/FrameRateOverrideMappings.cpp b/services/surfaceflinger/Scheduler/FrameRateOverrideMappings.cpp
index d9d64ae..c233455 100644
--- a/services/surfaceflinger/Scheduler/FrameRateOverrideMappings.cpp
+++ b/services/surfaceflinger/Scheduler/FrameRateOverrideMappings.cpp
@@ -51,7 +51,8 @@
return std::nullopt;
}
-std::vector<FrameRateOverride> FrameRateOverrideMappings::getAllFrameRateOverrides() {
+std::vector<FrameRateOverride> FrameRateOverrideMappings::getAllFrameRateOverrides(
+ bool supportsFrameRateOverrideByContent) {
std::lock_guard lock(mFrameRateOverridesLock);
std::vector<FrameRateOverride> overrides;
overrides.reserve(std::max({mFrameRateOverridesFromGameManager.size(),
@@ -67,6 +68,11 @@
overrides.emplace_back(FrameRateOverride{uid, frameRate.getValue()});
}
}
+
+ if (!supportsFrameRateOverrideByContent) {
+ return overrides;
+ }
+
for (const auto& [uid, frameRate] : mFrameRateOverridesByContent) {
if (std::find_if(overrides.begin(), overrides.end(),
[uid = uid](auto i) { return i.uid == uid; }) == overrides.end()) {
diff --git a/services/surfaceflinger/Scheduler/FrameRateOverrideMappings.h b/services/surfaceflinger/Scheduler/FrameRateOverrideMappings.h
index 278f87c..4185a4c 100644
--- a/services/surfaceflinger/Scheduler/FrameRateOverrideMappings.h
+++ b/services/surfaceflinger/Scheduler/FrameRateOverrideMappings.h
@@ -32,7 +32,8 @@
std::optional<Fps> getFrameRateOverrideForUid(uid_t uid,
bool supportsFrameRateOverrideByContent) const
EXCLUDES(mFrameRateOverridesLock);
- std::vector<FrameRateOverride> getAllFrameRateOverrides() EXCLUDES(mFrameRateOverridesLock);
+ std::vector<FrameRateOverride> getAllFrameRateOverrides(bool supportsFrameRateOverrideByContent)
+ EXCLUDES(mFrameRateOverridesLock);
void dump(std::string& result) const;
bool updateFrameRateOverridesByContent(const UidToFrameRateOverride& frameRateOverrides)
EXCLUDES(mFrameRateOverridesLock);
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 665d36982..a80ba66 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -262,8 +262,12 @@
}
void Scheduler::onFrameRateOverridesChanged(ConnectionHandle handle, PhysicalDisplayId displayId) {
+ const auto refreshRateConfigs = holdRefreshRateConfigs();
+ const bool supportsFrameRateOverrideByContent =
+ refreshRateConfigs->supportsFrameRateOverrideByContent();
+
std::vector<FrameRateOverride> overrides =
- mFrameRateOverrideMappings.getAllFrameRateOverrides();
+ mFrameRateOverrideMappings.getAllFrameRateOverrides(supportsFrameRateOverrideByContent);
android::EventThread* thread;
{
@@ -681,10 +685,10 @@
bool Scheduler::updateFrameRateOverrides(GlobalSignals consideredSignals, Fps displayRefreshRate) {
const auto refreshRateConfigs = holdRefreshRateConfigs();
- if (!refreshRateConfigs->supportsFrameRateOverrideByContent()) {
- return false;
- }
+ // we always update mFrameRateOverridesByContent here
+ // supportsFrameRateOverridesByContent will be checked
+ // when getting FrameRateOverrides from mFrameRateOverrideMappings
if (!consideredSignals.idle) {
const auto frameRateOverrides =
refreshRateConfigs->getFrameRateOverrides(mPolicy.contentRequirements,
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 48f18b9..1db5e61 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -80,6 +80,7 @@
"FpsReporterTest.cpp",
"FpsTest.cpp",
"FramebufferSurfaceTest.cpp",
+ "FrameRateOverrideMappingsTest.cpp",
"FrameTimelineTest.cpp",
"GameModeTest.cpp",
"HWComposerTest.cpp",
diff --git a/services/surfaceflinger/tests/unittests/FrameRateOverrideMappingsTest.cpp b/services/surfaceflinger/tests/unittests/FrameRateOverrideMappingsTest.cpp
new file mode 100644
index 0000000..a581c7a
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/FrameRateOverrideMappingsTest.cpp
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "FrameRateOverrideMappingsTest"
+
+#include <gtest/gtest.h>
+#include <unordered_map>
+
+#include "Scheduler/FrameRateOverrideMappings.h"
+
+namespace android::scheduler {
+
+using FrameRateOverride = DisplayEventReceiver::Event::FrameRateOverride;
+using UidToFrameRateOverride = std::map<uid_t, Fps>;
+
+class FrameRateOverrideMappingsTest : public testing::Test {
+protected:
+ FrameRateOverrideMappings mFrameRateOverrideMappings;
+ UidToFrameRateOverride mFrameRateOverrideByContent;
+};
+
+namespace {
+TEST_F(FrameRateOverrideMappingsTest, testUpdateFrameRateOverridesByContent) {
+ mFrameRateOverrideByContent.clear();
+ mFrameRateOverrideByContent.emplace(0, 30.0_Hz);
+ mFrameRateOverrideByContent.emplace(1, 60.0_Hz);
+ ASSERT_TRUE(mFrameRateOverrideMappings.updateFrameRateOverridesByContent(
+ mFrameRateOverrideByContent));
+
+ ASSERT_TRUE(isApproxEqual(30.0_Hz,
+ *mFrameRateOverrideMappings.getFrameRateOverrideForUid(
+ 0, /*supportsFrameRateOverrideByContent*/ true)));
+ ASSERT_TRUE(isApproxEqual(60.0_Hz,
+ *mFrameRateOverrideMappings.getFrameRateOverrideForUid(
+ 1, /*supportsFrameRateOverrideByContent*/ true)));
+ ASSERT_EQ(std::nullopt,
+ mFrameRateOverrideMappings
+ .getFrameRateOverrideForUid(1, /*supportsFrameRateOverrideByContent*/ false));
+ ASSERT_EQ(std::nullopt,
+ mFrameRateOverrideMappings
+ .getFrameRateOverrideForUid(3, /*supportsFrameRateOverrideByContent*/ true));
+ ASSERT_EQ(std::nullopt,
+ mFrameRateOverrideMappings
+ .getFrameRateOverrideForUid(3, /*supportsFrameRateOverrideByContent*/ false));
+}
+
+TEST_F(FrameRateOverrideMappingsTest, testSetGameModeRefreshRateForUid) {
+ mFrameRateOverrideMappings.setGameModeRefreshRateForUid({1, 30.0f});
+ mFrameRateOverrideMappings.setGameModeRefreshRateForUid({2, 90.0f});
+
+ ASSERT_TRUE(isApproxEqual(30.0_Hz,
+ *mFrameRateOverrideMappings.getFrameRateOverrideForUid(
+ 1, /*supportsFrameRateOverrideByContent*/ true)));
+ ASSERT_TRUE(isApproxEqual(90.0_Hz,
+ *mFrameRateOverrideMappings.getFrameRateOverrideForUid(
+ 2, /*supportsFrameRateOverrideByContent*/ false)));
+ ASSERT_EQ(std::nullopt,
+ mFrameRateOverrideMappings
+ .getFrameRateOverrideForUid(0, /*supportsFrameRateOverrideByContent*/ true));
+ ASSERT_EQ(std::nullopt,
+ mFrameRateOverrideMappings
+ .getFrameRateOverrideForUid(0, /*supportsFrameRateOverrideByContent*/ false));
+}
+
+TEST_F(FrameRateOverrideMappingsTest, testSetPreferredRefreshRateForUid) {
+ mFrameRateOverrideMappings.setPreferredRefreshRateForUid({0, 60.0f});
+ mFrameRateOverrideMappings.setPreferredRefreshRateForUid({2, 120.0f});
+
+ ASSERT_TRUE(isApproxEqual(60.0_Hz,
+ *mFrameRateOverrideMappings.getFrameRateOverrideForUid(
+ 0, /*supportsFrameRateOverrideByContent*/ true)));
+ ASSERT_TRUE(isApproxEqual(120.0_Hz,
+ *mFrameRateOverrideMappings.getFrameRateOverrideForUid(
+ 2, /*supportsFrameRateOverrideByContent*/ false)));
+ ASSERT_EQ(std::nullopt,
+ mFrameRateOverrideMappings
+ .getFrameRateOverrideForUid(1, /*supportsFrameRateOverrideByContent*/ true));
+ ASSERT_EQ(std::nullopt,
+ mFrameRateOverrideMappings
+ .getFrameRateOverrideForUid(1, /*supportsFrameRateOverrideByContent*/ false));
+}
+
+TEST_F(FrameRateOverrideMappingsTest, testGetFrameRateOverrideForUidMixed) {
+ mFrameRateOverrideByContent.clear();
+ mFrameRateOverrideByContent.emplace(0, 30.0_Hz);
+ mFrameRateOverrideByContent.emplace(1, 60.0_Hz);
+ mFrameRateOverrideByContent.emplace(2, 45.0_Hz);
+ mFrameRateOverrideByContent.emplace(5, 120.0_Hz);
+ ASSERT_TRUE(mFrameRateOverrideMappings.updateFrameRateOverridesByContent(
+ mFrameRateOverrideByContent));
+
+ std::vector<FrameRateOverride> allFrameRateOverrides;
+ ASSERT_EQ(allFrameRateOverrides,
+ mFrameRateOverrideMappings.getAllFrameRateOverrides(
+ /*supportsFrameRateOverrideByContent*/ false));
+ allFrameRateOverrides = {{0, 30.0f}, {1, 60.0f}, {2, 45.0f}, {5, 120.0f}};
+ ASSERT_EQ(allFrameRateOverrides,
+ mFrameRateOverrideMappings.getAllFrameRateOverrides(
+ /*supportsFrameRateOverrideByContent*/ true));
+
+ mFrameRateOverrideMappings.setGameModeRefreshRateForUid({1, 30.0f});
+ mFrameRateOverrideMappings.setGameModeRefreshRateForUid({2, 90.0f});
+ mFrameRateOverrideMappings.setGameModeRefreshRateForUid({4, 120.0f});
+
+ allFrameRateOverrides.clear();
+ allFrameRateOverrides = {{1, 30.0f}, {2, 90.0f}, {4, 120.0f}};
+ ASSERT_EQ(allFrameRateOverrides,
+ mFrameRateOverrideMappings.getAllFrameRateOverrides(
+ /*supportsFrameRateOverrideByContent*/ false));
+ allFrameRateOverrides.clear();
+ allFrameRateOverrides = {{1, 30.0f}, {2, 90.0f}, {4, 120.0f}, {0, 30.0f}, {5, 120.0f}};
+ ASSERT_EQ(allFrameRateOverrides,
+ mFrameRateOverrideMappings.getAllFrameRateOverrides(
+ /*supportsFrameRateOverrideByContent*/ true));
+
+ mFrameRateOverrideMappings.setPreferredRefreshRateForUid({0, 60.0f});
+ mFrameRateOverrideMappings.setPreferredRefreshRateForUid({2, 120.0f});
+ mFrameRateOverrideMappings.setPreferredRefreshRateForUid({3, 30.0f});
+
+ allFrameRateOverrides.clear();
+ allFrameRateOverrides = {{0, 60.0f}, {2, 120.0f}, {3, 30.0f}, {1, 30.0f}, {4, 120.0f}};
+ ASSERT_EQ(allFrameRateOverrides,
+ mFrameRateOverrideMappings.getAllFrameRateOverrides(
+ /*supportsFrameRateOverrideByContent*/ false));
+ allFrameRateOverrides.clear();
+ allFrameRateOverrides = {{0, 60.0f}, {2, 120.0f}, {3, 30.0f},
+ {1, 30.0f}, {4, 120.0f}, {5, 120.0f}};
+ ASSERT_EQ(allFrameRateOverrides,
+ mFrameRateOverrideMappings.getAllFrameRateOverrides(
+ /*supportsFrameRateOverrideByContent*/ true));
+
+ ASSERT_TRUE(isApproxEqual(60.0_Hz,
+ *mFrameRateOverrideMappings.getFrameRateOverrideForUid(
+ 0, /*supportsFrameRateOverrideByContent*/ true)));
+ ASSERT_TRUE(isApproxEqual(30.0_Hz,
+ *mFrameRateOverrideMappings.getFrameRateOverrideForUid(
+ 1, /*supportsFrameRateOverrideByContent*/ true)));
+ ASSERT_TRUE(isApproxEqual(120.0_Hz,
+ *mFrameRateOverrideMappings.getFrameRateOverrideForUid(
+ 2, /*supportsFrameRateOverrideByContent*/ true)));
+ ASSERT_TRUE(isApproxEqual(30.0_Hz,
+ *mFrameRateOverrideMappings.getFrameRateOverrideForUid(
+ 3, /*supportsFrameRateOverrideByContent*/ true)));
+ ASSERT_TRUE(isApproxEqual(120.0_Hz,
+ *mFrameRateOverrideMappings.getFrameRateOverrideForUid(
+ 4, /*supportsFrameRateOverrideByContent*/ true)));
+ ASSERT_TRUE(isApproxEqual(120.0_Hz,
+ *mFrameRateOverrideMappings.getFrameRateOverrideForUid(
+ 5, /*supportsFrameRateOverrideByContent*/ true)));
+
+ ASSERT_TRUE(isApproxEqual(60.0_Hz,
+ *mFrameRateOverrideMappings.getFrameRateOverrideForUid(
+ 0, /*supportsFrameRateOverrideByContent*/ false)));
+ ASSERT_TRUE(isApproxEqual(30.0_Hz,
+ *mFrameRateOverrideMappings.getFrameRateOverrideForUid(
+ 1, /*supportsFrameRateOverrideByContent*/ false)));
+ ASSERT_TRUE(isApproxEqual(120.0_Hz,
+ *mFrameRateOverrideMappings.getFrameRateOverrideForUid(
+ 2, /*supportsFrameRateOverrideByContent*/ false)));
+ ASSERT_TRUE(isApproxEqual(30.0_Hz,
+ *mFrameRateOverrideMappings.getFrameRateOverrideForUid(
+ 3, /*supportsFrameRateOverrideByContent*/ false)));
+ ASSERT_TRUE(isApproxEqual(120.0_Hz,
+ *mFrameRateOverrideMappings.getFrameRateOverrideForUid(
+ 4, /*supportsFrameRateOverrideByContent*/ false)));
+ ASSERT_EQ(std::nullopt,
+ mFrameRateOverrideMappings
+ .getFrameRateOverrideForUid(5, /*supportsFrameRateOverrideByContent*/ false));
+}
+} // namespace
+} // namespace android::scheduler