Add a flag for refresh rate switching
Some devices don't do refresh rate switching, so we should take that
into account when filtering display manager config settings and deciding
scheduling behavior.
This CL adds a sysprop that can be set to indicate if surface flinger
should do refresh rate switching, and modifies surface flinger to have
the correct behavior when we're not doing refresh rate switching.
Bug: 147233255
Bug: 136592946
Bug: 138261472
Test: Ran through various 60/90 switching scenarios on a device with
refresh rate switching.
Test: Set the refresh rate switching sysprop to false, and confirmed we
get a consistent 60Hz.
Test: Inspected dumpsys output and confirmed it looks correct. In
particular, refresh rate stats are output correctly.
Test: Ran automated tests: RefreshRateConfigsTest, RefreshRateStatsTest,
SchedulerTest.
Change-Id: I54cd5be9d2c1b9abc8475c3ce39846cbe9f9fe53
Merged-In: I54cd5be9d2c1b9abc8475c3ce39846cbe9f9fe53
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
index 411ec61..cec0b32 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
@@ -22,7 +22,6 @@
#include <thread>
#include "Scheduler/RefreshRateStats.h"
-#include "mock/DisplayHardware/MockDisplay.h"
#include "mock/MockTimeStats.h"
using namespace std::chrono_literals;
@@ -42,9 +41,18 @@
RefreshRateStatsTest();
~RefreshRateStatsTest();
+ void init(const std::vector<RefreshRateConfigs::InputConfig>& configs) {
+ mRefreshRateConfigs = std::make_unique<RefreshRateConfigs>(
+ /*refreshRateSwitching=*/true, configs, /*currentConfig=*/0);
+ mRefreshRateStats =
+ std::make_unique<RefreshRateStats>(*mRefreshRateConfigs, mTimeStats,
+ /*currentConfig=*/0,
+ /*currentPowerMode=*/HWC_POWER_MODE_OFF);
+ }
+
mock::TimeStats mTimeStats;
- RefreshRateConfigs mRefreshRateConfigs;
- RefreshRateStats mRefreshRateStats{mRefreshRateConfigs, mTimeStats};
+ std::unique_ptr<RefreshRateConfigs> mRefreshRateConfigs;
+ std::unique_ptr<RefreshRateStats> mRefreshRateStats;
};
RefreshRateStatsTest::RefreshRateStatsTest() {
@@ -63,63 +71,46 @@
/* ------------------------------------------------------------------------
* Test cases
*/
-TEST_F(RefreshRateStatsTest, canCreateAndDestroyTest) {
- std::vector<std::shared_ptr<const HWC2::Display::Config>> configs;
- mRefreshRateConfigs.populate(configs);
-
- // There is one default config, so the refresh rates should have one item.
- EXPECT_EQ(1, mRefreshRateStats.getTotalTimes().size());
-}
-
TEST_F(RefreshRateStatsTest, oneConfigTest) {
- auto display = new Hwc2::mock::Display();
-
- auto config = HWC2::Display::Config::Builder(*display, CONFIG_ID_90);
- config.setVsyncPeriod(VSYNC_90);
- std::vector<std::shared_ptr<const HWC2::Display::Config>> configs;
- configs.push_back(config.build());
-
- mRefreshRateConfigs.populate(configs);
+ init({{CONFIG_ID_90, VSYNC_90}});
EXPECT_CALL(mTimeStats, recordRefreshRate(0, _)).Times(AtLeast(1));
EXPECT_CALL(mTimeStats, recordRefreshRate(90, _)).Times(AtLeast(1));
- std::unordered_map<std::string, int64_t> times = mRefreshRateStats.getTotalTimes();
- EXPECT_EQ(2, times.size());
+ std::unordered_map<std::string, int64_t> times = mRefreshRateStats->getTotalTimes();
+ ASSERT_EQ(1, times.size());
EXPECT_NE(0u, times.count("ScreenOff"));
- EXPECT_EQ(1u, times.count("90fps"));
- EXPECT_EQ(0, times["90fps"]);
// Setting up tests on mobile harness can be flaky with time passing, so testing for
// exact time changes can result in flaxy numbers. To avoid that remember old
// numbers to make sure the correct values are increasing in the next test.
int screenOff = times["ScreenOff"];
- int ninety = times["90fps"];
// Screen is off by default.
std::this_thread::sleep_for(std::chrono::milliseconds(2));
- times = mRefreshRateStats.getTotalTimes();
+ times = mRefreshRateStats->getTotalTimes();
EXPECT_LT(screenOff, times["ScreenOff"]);
- EXPECT_EQ(0, times["90fps"]);
+ EXPECT_EQ(0u, times.count("90fps"));
- mRefreshRateStats.setConfigMode(CONFIG_ID_90);
- mRefreshRateStats.setPowerMode(HWC_POWER_MODE_NORMAL);
- screenOff = mRefreshRateStats.getTotalTimes()["ScreenOff"];
+ mRefreshRateStats->setConfigMode(CONFIG_ID_90);
+ mRefreshRateStats->setPowerMode(HWC_POWER_MODE_NORMAL);
+ screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"];
std::this_thread::sleep_for(std::chrono::milliseconds(2));
- times = mRefreshRateStats.getTotalTimes();
+ times = mRefreshRateStats->getTotalTimes();
EXPECT_EQ(screenOff, times["ScreenOff"]);
- EXPECT_LT(ninety, times["90fps"]);
+ ASSERT_EQ(1u, times.count("90fps"));
+ EXPECT_LT(0, times["90fps"]);
- mRefreshRateStats.setPowerMode(HWC_POWER_MODE_DOZE);
- ninety = mRefreshRateStats.getTotalTimes()["90fps"];
+ mRefreshRateStats->setPowerMode(HWC_POWER_MODE_DOZE);
+ int ninety = mRefreshRateStats->getTotalTimes()["90fps"];
std::this_thread::sleep_for(std::chrono::milliseconds(2));
- times = mRefreshRateStats.getTotalTimes();
+ times = mRefreshRateStats->getTotalTimes();
EXPECT_LT(screenOff, times["ScreenOff"]);
EXPECT_EQ(ninety, times["90fps"]);
- mRefreshRateStats.setConfigMode(CONFIG_ID_90);
- screenOff = mRefreshRateStats.getTotalTimes()["ScreenOff"];
+ mRefreshRateStats->setConfigMode(CONFIG_ID_90);
+ screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"];
std::this_thread::sleep_for(std::chrono::milliseconds(2));
- times = mRefreshRateStats.getTotalTimes();
+ times = mRefreshRateStats->getTotalTimes();
// Because the power mode is not HWC_POWER_MODE_NORMAL, switching the config
// does not update refresh rates that come from the config.
EXPECT_LT(screenOff, times["ScreenOff"]);
@@ -127,93 +118,75 @@
}
TEST_F(RefreshRateStatsTest, twoConfigsTest) {
- auto display = new Hwc2::mock::Display();
-
- auto config90 = HWC2::Display::Config::Builder(*display, CONFIG_ID_90);
- config90.setVsyncPeriod(VSYNC_90);
- std::vector<std::shared_ptr<const HWC2::Display::Config>> configs;
- configs.push_back(config90.build());
-
- auto config60 = HWC2::Display::Config::Builder(*display, CONFIG_ID_60);
- config60.setVsyncPeriod(VSYNC_60);
- configs.push_back(config60.build());
-
- mRefreshRateConfigs.populate(configs);
+ init({{CONFIG_ID_90, VSYNC_90}, {CONFIG_ID_60, VSYNC_60}});
EXPECT_CALL(mTimeStats, recordRefreshRate(0, _)).Times(AtLeast(1));
EXPECT_CALL(mTimeStats, recordRefreshRate(60, _)).Times(AtLeast(1));
EXPECT_CALL(mTimeStats, recordRefreshRate(90, _)).Times(AtLeast(1));
- std::unordered_map<std::string, int64_t> times = mRefreshRateStats.getTotalTimes();
- EXPECT_EQ(3, times.size());
+ std::unordered_map<std::string, int64_t> times = mRefreshRateStats->getTotalTimes();
+ ASSERT_EQ(1, times.size());
EXPECT_NE(0u, times.count("ScreenOff"));
- EXPECT_EQ(1u, times.count("60fps"));
- EXPECT_EQ(0, times["60fps"]);
- EXPECT_EQ(1u, times.count("90fps"));
- EXPECT_EQ(0, times["90fps"]);
// Setting up tests on mobile harness can be flaky with time passing, so testing for
// exact time changes can result in flaxy numbers. To avoid that remember old
// numbers to make sure the correct values are increasing in the next test.
int screenOff = times["ScreenOff"];
- int sixty = times["60fps"];
- int ninety = times["90fps"];
// Screen is off by default.
std::this_thread::sleep_for(std::chrono::milliseconds(2));
- times = mRefreshRateStats.getTotalTimes();
+ times = mRefreshRateStats->getTotalTimes();
EXPECT_LT(screenOff, times["ScreenOff"]);
- EXPECT_EQ(sixty, times["60fps"]);
- EXPECT_EQ(ninety, times["90fps"]);
- mRefreshRateStats.setConfigMode(CONFIG_ID_90);
- mRefreshRateStats.setPowerMode(HWC_POWER_MODE_NORMAL);
- screenOff = mRefreshRateStats.getTotalTimes()["ScreenOff"];
+ mRefreshRateStats->setConfigMode(CONFIG_ID_90);
+ mRefreshRateStats->setPowerMode(HWC_POWER_MODE_NORMAL);
+ screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"];
std::this_thread::sleep_for(std::chrono::milliseconds(2));
- times = mRefreshRateStats.getTotalTimes();
+ times = mRefreshRateStats->getTotalTimes();
EXPECT_EQ(screenOff, times["ScreenOff"]);
- EXPECT_EQ(sixty, times["60fps"]);
- EXPECT_LT(ninety, times["90fps"]);
+ ASSERT_EQ(1u, times.count("90fps"));
+ EXPECT_LT(0, times["90fps"]);
// When power mode is normal, time for configs updates.
- mRefreshRateStats.setConfigMode(CONFIG_ID_60);
- ninety = mRefreshRateStats.getTotalTimes()["90fps"];
+ mRefreshRateStats->setConfigMode(CONFIG_ID_60);
+ int ninety = mRefreshRateStats->getTotalTimes()["90fps"];
std::this_thread::sleep_for(std::chrono::milliseconds(2));
- times = mRefreshRateStats.getTotalTimes();
+ times = mRefreshRateStats->getTotalTimes();
EXPECT_EQ(screenOff, times["ScreenOff"]);
EXPECT_EQ(ninety, times["90fps"]);
- EXPECT_LT(sixty, times["60fps"]);
+ ASSERT_EQ(1u, times.count("60fps"));
+ EXPECT_LT(0, times["60fps"]);
- mRefreshRateStats.setConfigMode(CONFIG_ID_90);
- sixty = mRefreshRateStats.getTotalTimes()["60fps"];
+ mRefreshRateStats->setConfigMode(CONFIG_ID_90);
+ int sixty = mRefreshRateStats->getTotalTimes()["60fps"];
std::this_thread::sleep_for(std::chrono::milliseconds(2));
- times = mRefreshRateStats.getTotalTimes();
+ times = mRefreshRateStats->getTotalTimes();
EXPECT_EQ(screenOff, times["ScreenOff"]);
EXPECT_LT(ninety, times["90fps"]);
EXPECT_EQ(sixty, times["60fps"]);
- mRefreshRateStats.setConfigMode(CONFIG_ID_60);
- ninety = mRefreshRateStats.getTotalTimes()["90fps"];
+ mRefreshRateStats->setConfigMode(CONFIG_ID_60);
+ ninety = mRefreshRateStats->getTotalTimes()["90fps"];
std::this_thread::sleep_for(std::chrono::milliseconds(2));
- times = mRefreshRateStats.getTotalTimes();
+ times = mRefreshRateStats->getTotalTimes();
EXPECT_EQ(screenOff, times["ScreenOff"]);
EXPECT_EQ(ninety, times["90fps"]);
EXPECT_LT(sixty, times["60fps"]);
// Because the power mode is not HWC_POWER_MODE_NORMAL, switching the config
// does not update refresh rates that come from the config.
- mRefreshRateStats.setPowerMode(HWC_POWER_MODE_DOZE);
- mRefreshRateStats.setConfigMode(CONFIG_ID_90);
- sixty = mRefreshRateStats.getTotalTimes()["60fps"];
+ mRefreshRateStats->setPowerMode(HWC_POWER_MODE_DOZE);
+ mRefreshRateStats->setConfigMode(CONFIG_ID_90);
+ sixty = mRefreshRateStats->getTotalTimes()["60fps"];
std::this_thread::sleep_for(std::chrono::milliseconds(2));
- times = mRefreshRateStats.getTotalTimes();
+ times = mRefreshRateStats->getTotalTimes();
EXPECT_LT(screenOff, times["ScreenOff"]);
EXPECT_EQ(ninety, times["90fps"]);
EXPECT_EQ(sixty, times["60fps"]);
- mRefreshRateStats.setConfigMode(CONFIG_ID_60);
- screenOff = mRefreshRateStats.getTotalTimes()["ScreenOff"];
+ mRefreshRateStats->setConfigMode(CONFIG_ID_60);
+ screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"];
std::this_thread::sleep_for(std::chrono::milliseconds(2));
- times = mRefreshRateStats.getTotalTimes();
+ times = mRefreshRateStats->getTotalTimes();
EXPECT_LT(screenOff, times["ScreenOff"]);
EXPECT_EQ(ninety, times["90fps"]);
EXPECT_EQ(sixty, times["60fps"]);