1 /* 2 * Copyright 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <algorithm> 20 #include <numeric> 21 22 #include "android-base/stringprintf.h" 23 24 #include "DisplayHardware/HWComposer.h" 25 #include "Scheduler/SchedulerUtils.h" 26 27 namespace android { 28 namespace scheduler { 29 30 /** 31 * This class is used to encapsulate configuration for refresh rates. It holds information 32 * about available refresh rates on the device, and the mapping between the numbers and human 33 * readable names. 34 */ 35 class RefreshRateConfigs { 36 public: 37 // Enum to indicate which vsync rate to run at. Power saving is intended to be the lowest 38 // (eg. when the screen is in AOD mode or off), default is the old 60Hz, and performance 39 // is the new 90Hz. Eventually we want to have a way for vendors to map these in the configs. 40 enum class RefreshRateType { POWER_SAVING, DEFAULT, PERFORMANCE }; 41 42 struct RefreshRate { 43 // This config ID corresponds to the position of the config in the vector that is stored 44 // on the device. 45 int configId; 46 // Human readable name of the refresh rate. 47 std::string name; 48 // Refresh rate in frames per second, rounded to the nearest integer. 49 uint32_t fps = 0; 50 // config Id (returned from HWC2::Display::Config::getId()) 51 hwc2_config_t id; 52 }; 53 54 // TODO(b/122916473): Get this information from configs prepared by vendors, instead of 55 // baking them in. getRefreshRates()56 const std::map<RefreshRateType, std::shared_ptr<RefreshRate>>& getRefreshRates() const { 57 return mRefreshRates; 58 } getRefreshRate(RefreshRateType type)59 std::shared_ptr<RefreshRate> getRefreshRate(RefreshRateType type) const { 60 const auto& refreshRate = mRefreshRates.find(type); 61 if (refreshRate != mRefreshRates.end()) { 62 return refreshRate->second; 63 } 64 return nullptr; 65 } 66 getRefreshRateType(hwc2_config_t id)67 RefreshRateType getRefreshRateType(hwc2_config_t id) const { 68 for (const auto& [type, refreshRate] : mRefreshRates) { 69 if (refreshRate->id == id) { 70 return type; 71 } 72 } 73 74 return RefreshRateType::DEFAULT; 75 } 76 populate(const std::vector<std::shared_ptr<const HWC2::Display::Config>> & configs)77 void populate(const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs) { 78 mRefreshRates.clear(); 79 80 // This is the rate that HWC encapsulates right now when the device is in DOZE mode. 81 mRefreshRates.emplace(RefreshRateType::POWER_SAVING, 82 std::make_shared<RefreshRate>( 83 RefreshRate{SCREEN_OFF_CONFIG_ID, "ScreenOff", 0, 84 HWC2_SCREEN_OFF_CONFIG_ID})); 85 86 if (configs.size() < 1) { 87 ALOGE("Device does not have valid configs. Config size is 0."); 88 return; 89 } 90 91 // Create a map between config index and vsync period. This is all the info we need 92 // from the configs. 93 std::vector<std::pair<int, nsecs_t>> configIdToVsyncPeriod; 94 for (int i = 0; i < configs.size(); ++i) { 95 configIdToVsyncPeriod.emplace_back(i, configs.at(i)->getVsyncPeriod()); 96 } 97 98 std::sort(configIdToVsyncPeriod.begin(), configIdToVsyncPeriod.end(), 99 [](const std::pair<int, nsecs_t>& a, const std::pair<int, nsecs_t>& b) { 100 return a.second > b.second; 101 }); 102 103 // When the configs are ordered by the resync rate. We assume that the first one is DEFAULT. 104 nsecs_t vsyncPeriod = configIdToVsyncPeriod[0].second; 105 if (vsyncPeriod != 0) { 106 const float fps = 1e9 / vsyncPeriod; 107 const int configId = configIdToVsyncPeriod[0].first; 108 mRefreshRates.emplace(RefreshRateType::DEFAULT, 109 std::make_shared<RefreshRate>( 110 RefreshRate{configId, base::StringPrintf("%2.ffps", fps), 111 static_cast<uint32_t>(fps), 112 configs.at(configId)->getId()})); 113 } 114 115 if (configs.size() < 2) { 116 return; 117 } 118 119 // When the configs are ordered by the resync rate. We assume that the second one is 120 // PERFORMANCE, eg. the higher rate. 121 vsyncPeriod = configIdToVsyncPeriod[1].second; 122 if (vsyncPeriod != 0) { 123 const float fps = 1e9 / vsyncPeriod; 124 const int configId = configIdToVsyncPeriod[1].first; 125 mRefreshRates.emplace(RefreshRateType::PERFORMANCE, 126 std::make_shared<RefreshRate>( 127 RefreshRate{configId, base::StringPrintf("%2.ffps", fps), 128 static_cast<uint32_t>(fps), 129 configs.at(configId)->getId()})); 130 } 131 } 132 133 private: 134 std::map<RefreshRateType, std::shared_ptr<RefreshRate>> mRefreshRates; 135 }; 136 137 } // namespace scheduler 138 } // namespace android 139