diff options
author | 2019-03-27 01:02:07 +0000 | |
---|---|---|
committer | 2019-03-27 01:02:07 +0000 | |
commit | 7ed195b3ea0095f824aec44660deccac68f1a210 (patch) | |
tree | d23a2f08715ae3bd0ba94b612d92fee4eb1786f4 | |
parent | 605ee5e4da34e960b9428fbc2d39d7b9292931da (diff) | |
parent | 0a1cc96f0efe8a527e81807db400ac5554d75b12 (diff) |
Merge "Cleanup dumpsys for refresh configs for non-90hz devices."
5 files changed, 214 insertions, 25 deletions
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h index cbcc031767..9e95f95092 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h @@ -57,16 +57,23 @@ public: } ~RefreshRateConfigs() = default; - const std::unordered_map<RefreshRateType, RefreshRate>& getRefreshRates() { + const std::unordered_map<RefreshRateType, std::shared_ptr<RefreshRate>>& getRefreshRates() { return mRefreshRates; } - const RefreshRate& getRefreshRate(RefreshRateType type) { return mRefreshRates[type]; } + std::shared_ptr<RefreshRate> getRefreshRate(RefreshRateType type) { + const auto& refreshRate = mRefreshRates.find(type); + if (refreshRate != mRefreshRates.end()) { + return refreshRate->second; + } + return nullptr; + } private: void init(const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs) { // This is the rate that HWC encapsulates right now when the device is in DOZE mode. mRefreshRates.emplace(RefreshRateType::POWER_SAVING, - RefreshRate{SCREEN_OFF_CONFIG_ID, "ScreenOff", 0}); + std::make_shared<RefreshRate>( + RefreshRate{SCREEN_OFF_CONFIG_ID, "ScreenOff", 0})); if (configs.size() < 1) { ALOGE("Device does not have valid configs. Config size is 0."); @@ -90,9 +97,10 @@ private: if (vsyncPeriod != 0) { const float fps = 1e9 / vsyncPeriod; mRefreshRates.emplace(RefreshRateType::DEFAULT, - RefreshRate{configIdToVsyncPeriod[0].first, - base::StringPrintf("%2.ffps", fps), - static_cast<uint32_t>(fps)}); + std::make_shared<RefreshRate>( + RefreshRate{configIdToVsyncPeriod[0].first, + base::StringPrintf("%2.ffps", fps), + static_cast<uint32_t>(fps)})); } if (configs.size() < 2) { @@ -105,13 +113,14 @@ private: if (vsyncPeriod != 0) { const float fps = 1e9 / vsyncPeriod; mRefreshRates.emplace(RefreshRateType::PERFORMANCE, - RefreshRate{configIdToVsyncPeriod[1].first, - base::StringPrintf("%2.ffps", fps), - static_cast<uint32_t>(fps)}); + std::make_shared<RefreshRate>( + RefreshRate{configIdToVsyncPeriod[1].first, + base::StringPrintf("%2.ffps", fps), + static_cast<uint32_t>(fps)})); } } - std::unordered_map<RefreshRateType, RefreshRate> mRefreshRates; + std::unordered_map<RefreshRateType, std::shared_ptr<RefreshRate>> mRefreshRates; }; } // namespace scheduler diff --git a/services/surfaceflinger/Scheduler/RefreshRateStats.h b/services/surfaceflinger/Scheduler/RefreshRateStats.h index d4ae330494..ff63faf029 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateStats.h +++ b/services/surfaceflinger/Scheduler/RefreshRateStats.h @@ -85,10 +85,13 @@ public: std::unordered_map<std::string, int64_t> totalTime; for (auto [type, config] : mRefreshRateConfigs->getRefreshRates()) { int64_t totalTimeForConfig = 0; - if (mConfigModesTotalTime.find(config.configId) != mConfigModesTotalTime.end()) { - totalTimeForConfig = mConfigModesTotalTime.at(config.configId); + if (!config) { + continue; } - totalTime[config.name] = totalTimeForConfig; + if (mConfigModesTotalTime.find(config->configId) != mConfigModesTotalTime.end()) { + totalTimeForConfig = mConfigModesTotalTime.at(config->configId); + } + totalTime[config->name] = totalTimeForConfig; } return totalTime; } @@ -124,8 +127,11 @@ private: mConfigModesTotalTime[mode] += timeElapsedMs; for (const auto& [type, config] : mRefreshRateConfigs->getRefreshRates()) { - if (config.configId == mode) { - mTimeStats->recordRefreshRate(config.fps, timeElapsed); + if (!config) { + continue; + } + if (config->configId == mode) { + mTimeStats->recordRefreshRate(config->fps, timeElapsed); } } } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 63a1e4f47d..945f6fa6ac 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -592,10 +592,11 @@ void SurfaceFlinger::bootFinished() const auto displayId = getInternalDisplayIdLocked(); LOG_ALWAYS_FATAL_IF(!displayId); - const auto performanceRefreshRate = + const auto& performanceRefreshRate = mRefreshRateConfigs[*displayId]->getRefreshRate(RefreshRateType::PERFORMANCE); - if (isConfigAllowed(*displayId, performanceRefreshRate.configId)) { + if (performanceRefreshRate && + isConfigAllowed(*displayId, performanceRefreshRate->configId)) { setRefreshRateTo(RefreshRateType::PERFORMANCE, Scheduler::ConfigEvent::None); } else { setRefreshRateTo(RefreshRateType::DEFAULT, Scheduler::ConfigEvent::None); @@ -1471,17 +1472,24 @@ void SurfaceFlinger::setRefreshRateTo(RefreshRateType refreshRate, Scheduler::Co LOG_ALWAYS_FATAL_IF(!displayId); const auto displayToken = getInternalDisplayTokenLocked(); - auto desiredConfigId = mRefreshRateConfigs[*displayId]->getRefreshRate(refreshRate).configId; - const auto display = getDisplayDeviceLocked(displayToken); - if (desiredConfigId == display->getActiveConfig()) { + const auto& refreshRateConfig = mRefreshRateConfigs[*displayId]->getRefreshRate(refreshRate); + if (!refreshRateConfig) { + ALOGV("Skipping refresh rate change request for unsupported rate."); return; } + const int desiredConfigId = refreshRateConfig->configId; + if (!isConfigAllowed(*displayId, desiredConfigId)) { ALOGV("Skipping config %d as it is not part of allowed configs", desiredConfigId); return; } + const auto display = getDisplayDeviceLocked(displayToken); + if (desiredConfigId == display->getActiveConfig()) { + return; + } + mPhaseOffsets->setRefreshRateType(refreshRate); setDesiredActiveConfig(getInternalDisplayTokenLocked(), desiredConfigId, event); } @@ -5797,12 +5805,12 @@ void SurfaceFlinger::setAllowedDisplayConfigsInternal( int currentConfigIndex = getHwComposer().getActiveConfigIndex(*displayId); if (!isConfigAllowed(*displayId, currentConfigIndex)) { for (const auto& [type, config] : mRefreshRateConfigs[*displayId]->getRefreshRates()) { - if (isConfigAllowed(*displayId, config.configId)) { + if (config && isConfigAllowed(*displayId, config->configId)) { // TODO: we switch to the first allowed config. In the future // we may want to enhance this logic to pick a similar config // to the current one - ALOGV("Old config is not allowed - switching to config %d", config.configId); - setDesiredActiveConfig(displayToken, config.configId, + ALOGV("Old config is not allowed - switching to config %d", config->configId); + setDesiredActiveConfig(displayToken, config->configId, Scheduler::ConfigEvent::Changed); break; } @@ -5812,9 +5820,10 @@ void SurfaceFlinger::setAllowedDisplayConfigsInternal( // If idle timer and fps detection are disabled and we are in RefreshRateType::DEFAULT, // there is no trigger to move to RefreshRateType::PERFORMANCE, even if it is an allowed. if (!mScheduler->isIdleTimerEnabled() && !mUseSmart90ForVideo) { - const auto performanceRefreshRate = + const auto& performanceRefreshRate = mRefreshRateConfigs[*displayId]->getRefreshRate(RefreshRateType::PERFORMANCE); - if (isConfigAllowed(*displayId, performanceRefreshRate.configId)) { + if (performanceRefreshRate && + isConfigAllowed(*displayId, performanceRefreshRate->configId)) { setRefreshRateTo(RefreshRateType::PERFORMANCE, Scheduler::ConfigEvent::Changed); } } diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp index 25ce4ac605..12b41fd32c 100644 --- a/services/surfaceflinger/tests/unittests/Android.bp +++ b/services/surfaceflinger/tests/unittests/Android.bp @@ -47,6 +47,7 @@ cc_test { "LayerMetadataTest.cpp", "SchedulerTest.cpp", "SchedulerUtilsTest.cpp", + "RefreshRateConfigsTest.cpp", "RefreshRateStatsTest.cpp", "TimeStatsTest.cpp", "mock/DisplayHardware/MockComposer.cpp", diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp new file mode 100644 index 0000000000..b218ad63d6 --- /dev/null +++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp @@ -0,0 +1,164 @@ +/* + * Copyright 2019 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 "SchedulerUnittests" + +#include <gmock/gmock.h> +#include <log/log.h> +#include <thread> + +#include "DisplayHardware/HWC2.h" +#include "Scheduler/RefreshRateConfigs.h" +#include "mock/DisplayHardware/MockDisplay.h" + +using namespace std::chrono_literals; +using testing::_; + +namespace android { +namespace scheduler { + +using RefreshRateType = RefreshRateConfigs::RefreshRateType; +using RefreshRate = RefreshRateConfigs::RefreshRate; + +class RefreshRateConfigsTest : public testing::Test { +protected: + static constexpr int CONFIG_ID_60 = 0; + static constexpr int CONFIG_ID_90 = 1; + static constexpr int64_t VSYNC_60 = 16666667; + static constexpr int64_t VSYNC_90 = 11111111; + + RefreshRateConfigsTest(); + ~RefreshRateConfigsTest(); + + void assertRatesEqual(const RefreshRate& left, const RefreshRate& right) { + ASSERT_EQ(left.configId, right.configId); + ASSERT_EQ(left.name, right.name); + ASSERT_EQ(left.fps, right.fps); + } +}; + +RefreshRateConfigsTest::RefreshRateConfigsTest() { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); +} + +RefreshRateConfigsTest::~RefreshRateConfigsTest() { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name()); +} + +namespace { +/* ------------------------------------------------------------------------ + * Test cases + */ +TEST_F(RefreshRateConfigsTest, zeroDeviceConfigs_storesPowerSavingConfig) { + std::vector<std::shared_ptr<const HWC2::Display::Config>> displayConfigs; + RefreshRateConfigs configs(displayConfigs); + + // We always store a configuration for screen off. + const auto& rates = configs.getRefreshRates(); + ASSERT_EQ(1, rates.size()); + const auto& powerSavingRate = rates.find(RefreshRateType::POWER_SAVING); + ASSERT_NE(rates.end(), powerSavingRate); + ASSERT_EQ(rates.end(), rates.find(RefreshRateType::PERFORMANCE)); + ASSERT_EQ(rates.end(), rates.find(RefreshRateType::DEFAULT)); + + RefreshRate expectedConfig = RefreshRate{SCREEN_OFF_CONFIG_ID, "ScreenOff", 0}; + assertRatesEqual(expectedConfig, *powerSavingRate->second); + + ASSERT_TRUE(configs.getRefreshRate(RefreshRateType::POWER_SAVING)); + assertRatesEqual(expectedConfig, *configs.getRefreshRate(RefreshRateType::POWER_SAVING)); + ASSERT_FALSE(configs.getRefreshRate(RefreshRateType::PERFORMANCE)); + ASSERT_FALSE(configs.getRefreshRate(RefreshRateType::DEFAULT)); + + // Sanity check that getRefreshRate() does not modify the underlying configs. + ASSERT_EQ(1, configs.getRefreshRates().size()); +} + +TEST_F(RefreshRateConfigsTest, oneDeviceConfig_storesDefaultConfig) { + auto display = new Hwc2::mock::Display(); + std::vector<std::shared_ptr<const HWC2::Display::Config>> displayConfigs; + auto config60 = HWC2::Display::Config::Builder(*display, CONFIG_ID_60); + config60.setVsyncPeriod(VSYNC_60); + displayConfigs.push_back(config60.build()); + RefreshRateConfigs configs(displayConfigs); + + const auto& rates = configs.getRefreshRates(); + ASSERT_EQ(2, rates.size()); + const auto& powerSavingRate = rates.find(RefreshRateType::POWER_SAVING); + const auto& defaultRate = rates.find(RefreshRateType::DEFAULT); + ASSERT_NE(rates.end(), powerSavingRate); + ASSERT_NE(rates.end(), defaultRate); + ASSERT_EQ(rates.end(), rates.find(RefreshRateType::PERFORMANCE)); + + RefreshRate expectedPowerSavingConfig = RefreshRate{SCREEN_OFF_CONFIG_ID, "ScreenOff", 0}; + assertRatesEqual(expectedPowerSavingConfig, *powerSavingRate->second); + RefreshRate expectedDefaultConfig = RefreshRate{CONFIG_ID_60, "60fps", 60}; + assertRatesEqual(expectedDefaultConfig, *defaultRate->second); + + ASSERT_TRUE(configs.getRefreshRate(RefreshRateType::POWER_SAVING)); + assertRatesEqual(expectedPowerSavingConfig, + *configs.getRefreshRate(RefreshRateType::POWER_SAVING)); + ASSERT_TRUE(configs.getRefreshRate(RefreshRateType::DEFAULT)); + assertRatesEqual(expectedDefaultConfig, *configs.getRefreshRate(RefreshRateType::DEFAULT)); + ASSERT_FALSE(configs.getRefreshRate(RefreshRateType::PERFORMANCE)); + + // Sanity check that getRefreshRate() does not modify the underlying configs. + ASSERT_EQ(2, configs.getRefreshRates().size()); +} + +TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesPerformanceConfig) { + auto display = new Hwc2::mock::Display(); + std::vector<std::shared_ptr<const HWC2::Display::Config>> displayConfigs; + auto config60 = HWC2::Display::Config::Builder(*display, CONFIG_ID_60); + config60.setVsyncPeriod(VSYNC_60); + displayConfigs.push_back(config60.build()); + auto config90 = HWC2::Display::Config::Builder(*display, CONFIG_ID_90); + config90.setVsyncPeriod(VSYNC_90); + displayConfigs.push_back(config90.build()); + RefreshRateConfigs configs(displayConfigs); + + const auto& rates = configs.getRefreshRates(); + ASSERT_EQ(3, rates.size()); + const auto& powerSavingRate = rates.find(RefreshRateType::POWER_SAVING); + const auto& defaultRate = rates.find(RefreshRateType::DEFAULT); + const auto& performanceRate = rates.find(RefreshRateType::PERFORMANCE); + ASSERT_NE(rates.end(), powerSavingRate); + ASSERT_NE(rates.end(), defaultRate); + ASSERT_NE(rates.end(), performanceRate); + + RefreshRate expectedPowerSavingConfig = RefreshRate{SCREEN_OFF_CONFIG_ID, "ScreenOff", 0}; + assertRatesEqual(expectedPowerSavingConfig, *powerSavingRate->second); + RefreshRate expectedDefaultConfig = RefreshRate{CONFIG_ID_60, "60fps", 60}; + assertRatesEqual(expectedDefaultConfig, *defaultRate->second); + RefreshRate expectedPerformanceConfig = RefreshRate{CONFIG_ID_90, "90fps", 90}; + assertRatesEqual(expectedPerformanceConfig, *performanceRate->second); + + ASSERT_TRUE(configs.getRefreshRate(RefreshRateType::POWER_SAVING)); + assertRatesEqual(expectedPowerSavingConfig, + *configs.getRefreshRate(RefreshRateType::POWER_SAVING)); + ASSERT_TRUE(configs.getRefreshRate(RefreshRateType::DEFAULT)); + assertRatesEqual(expectedDefaultConfig, *configs.getRefreshRate(RefreshRateType::DEFAULT)); + ASSERT_TRUE(configs.getRefreshRate(RefreshRateType::PERFORMANCE)); + assertRatesEqual(expectedPerformanceConfig, + *configs.getRefreshRate(RefreshRateType::PERFORMANCE)); +} +} // namespace +} // namespace scheduler +} // namespace android |