1 /* 2 * Copyright (C) 2024 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 <hardware/hwcomposer2.h> 20 #include <map> 21 #include <sstream> 22 #include <string> 23 #include <utility> 24 25 #include "EventQueue.h" 26 #include "Utils.h" 27 #include "display/common/CommonDisplayContextProvider.h" 28 #include "interface/DisplayContextProvider.h" 29 #include "interface/VariableRefreshRateInterface.h" 30 31 // #define DEBUG_VRR_STATISTICS 1 32 33 namespace android::hardware::graphics::composer { 34 35 // |DisplayStatus| is the intrinsic property of the key for statistics, representing the display 36 // configuration. 37 typedef struct DisplayStatus { isOffDisplayStatus38 inline bool isOff() const { 39 if ((mPowerMode == HWC_POWER_MODE_OFF) || (mPowerMode == HWC_POWER_MODE_DOZE_SUSPEND)) { 40 return true; 41 } else { 42 return false; 43 } 44 } 45 46 bool operator==(const DisplayStatus& rhs) const { 47 if (isOff() || rhs.isOff()) { 48 return isOff() == rhs.isOff(); 49 } 50 return (mActiveConfigId == rhs.mActiveConfigId) && (mPowerMode == rhs.mPowerMode) && 51 (mBrightnessMode == rhs.mBrightnessMode); 52 } 53 54 bool operator<(const DisplayStatus& rhs) const { 55 if (isOff() && rhs.isOff()) { 56 return false; 57 } 58 59 if (mPowerMode != rhs.mPowerMode) { 60 return (isOff() || (mPowerMode < rhs.mPowerMode)); 61 } else if (mActiveConfigId != rhs.mActiveConfigId) { 62 return mActiveConfigId < rhs.mActiveConfigId; 63 } else { 64 return mBrightnessMode < rhs.mBrightnessMode; 65 } 66 } 67 toStringDisplayStatus68 std::string toString() const { 69 std::ostringstream os; 70 os << "id = " << mActiveConfigId; 71 os << ", power mode = " << mPowerMode; 72 os << ", brightness = " << static_cast<int>(mBrightnessMode); 73 return os.str(); 74 } 75 76 hwc2_config_t mActiveConfigId = -1; 77 int mPowerMode = HWC_POWER_MODE_OFF; 78 BrightnessMode mBrightnessMode = BrightnessMode::kInvalidBrightnessMode; 79 } DisplayStatus; 80 81 // |DisplayPresentProfile| is the key to the statistics. 82 typedef struct DisplayPresentProfile { isOffDisplayPresentProfile83 inline bool isOff() const { return mCurrentDisplayConfig.isOff(); } 84 85 bool operator<(const DisplayPresentProfile& rhs) const { 86 if (isOff() || rhs.isOff()) { 87 if (isOff() == rhs.isOff()) { 88 return false; 89 } 90 } 91 92 if (mCurrentDisplayConfig != rhs.mCurrentDisplayConfig) { 93 return (mCurrentDisplayConfig < rhs.mCurrentDisplayConfig); 94 } else { 95 return (mNumVsync < rhs.mNumVsync); 96 } 97 } 98 toStringDisplayPresentProfile99 std::string toString() const { 100 std::string res = mCurrentDisplayConfig.toString(); 101 res += ", mNumVsync = " + std::to_string(mNumVsync); 102 return res; 103 } 104 105 DisplayStatus mCurrentDisplayConfig; 106 // |mNumVsync| is the timing property of the key for statistics, representing the distribution 107 // of presentations. It represents the interval between a present and the previous present in 108 // terms of the number of vsyncs. 109 int mNumVsync = -1; 110 } DisplayPresentProfile; 111 112 // |DisplayPresentRecord| is the value to the statistics. 113 typedef struct DisplayPresentRecord { 114 DisplayPresentRecord() = default; 115 DisplayPresentRecord& operator+=(const DisplayPresentRecord& other) { 116 this->mCount += other.mCount; 117 this->mAccumulatedTimeNs += other.mAccumulatedTimeNs; 118 this->mLastTimeStampInBootClockNs = 119 std::max(mLastTimeStampInBootClockNs, other.mLastTimeStampInBootClockNs); 120 mUpdated = true; 121 return *this; 122 } toStringDisplayPresentRecord123 std::string toString() const { 124 std::ostringstream os; 125 os << "Count = " << mCount; 126 os << ", AccumulatedTimeNs = " << mAccumulatedTimeNs / 1000000; 127 os << ", LastTimeStampInBootClockNs = " << mLastTimeStampInBootClockNs; 128 return os.str(); 129 } 130 uint64_t mCount = 0; 131 uint64_t mAccumulatedTimeNs = 0; 132 uint64_t mLastTimeStampInBootClockNs = 0; 133 bool mUpdated = false; 134 } DisplayPresentRecord; 135 136 // |DisplayPresentStatistics| is a map consisting of key-value pairs for statistics. 137 // The key consists of two parts: display configuration and refresh frequency (in terms of vsync). 138 typedef std::map<DisplayPresentProfile, DisplayPresentRecord> DisplayPresentStatistics; 139 140 class StatisticsProvider { 141 public: 142 virtual ~StatisticsProvider() = default; 143 144 virtual uint64_t getStartStatisticTimeNs() const = 0; 145 146 virtual DisplayPresentStatistics getStatistics() = 0; 147 148 virtual DisplayPresentStatistics getUpdatedStatistics() = 0; 149 }; 150 151 class VariableRefreshRateStatistic : public PowerModeListener, 152 public PresentListener, 153 public StatisticsProvider { 154 public: 155 VariableRefreshRateStatistic(CommonDisplayContextProvider* displayContextProvider, 156 EventQueue* eventQueue, int maxFrameRate, int maxTeFrequency, 157 int64_t updatePeriodNs); 158 159 uint64_t getPowerOffDurationNs() const; 160 161 uint64_t getStartStatisticTimeNs() const override; 162 163 DisplayPresentStatistics getStatistics() override; 164 165 DisplayPresentStatistics getUpdatedStatistics() override; 166 167 void onPowerStateChange(int from, int to) final; 168 169 void onPresent(int64_t presentTimeNs, int flag) override; 170 171 void setActiveVrrConfiguration(int activeConfigId, int teFrequency); 172 173 // If |minimumRefreshRate| is not equal to zero, enforce the minimum (fixed) refresh rate; 174 // otherwise, revert to a variable refresh rate. 175 void setFixedRefreshRate(uint32_t minimumRefreshRate); 176 177 VariableRefreshRateStatistic(const VariableRefreshRateStatistic& other) = delete; 178 VariableRefreshRateStatistic& operator=(const VariableRefreshRateStatistic& other) = delete; 179 180 private: 181 static constexpr int64_t kMaxPresentIntervalNs = std::nano::den; 182 static constexpr uint32_t kFrameRateWhenPresentAtLpMode = 30; 183 184 bool isPowerModeOffNowLocked() const; 185 186 void updateCurrentDisplayStatus(); 187 188 void updateIdleStats(int64_t endTimeStampInBootClockNs = -1); 189 190 #ifdef DEBUG_VRR_STATISTICS 191 int updateStatistic(); 192 #endif 193 194 CommonDisplayContextProvider* mDisplayContextProvider; 195 EventQueue* mEventQueue; 196 197 const int mMaxFrameRate; 198 const int mMaxTeFrequency; 199 const int64_t mMinFrameIntervalNs; 200 201 int mTeFrequency; 202 int64_t mTeIntervalNs; 203 204 const int64_t mUpdatePeriodNs; 205 206 int64_t mLastPresentTimeInBootClockNs = kDefaultInvalidPresentTimeNs; 207 208 DisplayPresentStatistics mStatistics; 209 DisplayPresentProfile mDisplayPresentProfile; 210 211 uint64_t mPowerOffDurationNs = 0; 212 213 uint32_t mMinimumRefreshRate = 1; 214 uint64_t mMaximumFrameIntervalNs = kMaxPresentIntervalNs; // 1 second. 215 216 uint64_t mStartStatisticTimeNs; 217 218 #ifdef DEBUG_VRR_STATISTICS 219 VrrControllerEvent mUpdateEvent; 220 #endif 221 222 mutable std::mutex mMutex; 223 }; 224 225 } // namespace android::hardware::graphics::composer 226