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 <cinttypes> 20 #include <cstdint> 21 #include <deque> 22 #include <mutex> 23 #include <numeric> 24 #include <string> 25 26 #include <log/log.h> 27 28 #include <utils/Mutex.h> 29 #include <utils/Timers.h> 30 31 #include "SchedulerUtils.h" 32 33 namespace android { 34 namespace scheduler { 35 36 /* 37 * This class represents information about individial layers. 38 */ 39 class LayerInfo { 40 /** 41 * Struct that keeps the information about the refresh rate for last 42 * HISTORY_SIZE frames. This is used to better determine the refresh rate 43 * for individual layers. 44 */ 45 class RefreshRateHistory { 46 public: RefreshRateHistory(nsecs_t minRefreshDuration)47 explicit RefreshRateHistory(nsecs_t minRefreshDuration) 48 : mMinRefreshDuration(minRefreshDuration) {} insertRefreshRate(nsecs_t refreshRate)49 void insertRefreshRate(nsecs_t refreshRate) { 50 mElements.push_back(refreshRate); 51 if (mElements.size() > HISTORY_SIZE) { 52 mElements.pop_front(); 53 } 54 } 55 getRefreshRateAvg()56 float getRefreshRateAvg() const { 57 nsecs_t refreshDuration = mMinRefreshDuration; 58 if (mElements.size() == HISTORY_SIZE) { 59 refreshDuration = scheduler::calculate_mean(mElements); 60 } 61 62 return 1e9f / refreshDuration; 63 } clearHistory()64 void clearHistory() { mElements.clear(); } 65 66 private: 67 std::deque<nsecs_t> mElements; 68 static constexpr size_t HISTORY_SIZE = 30; 69 const nsecs_t mMinRefreshDuration; 70 }; 71 72 /** 73 * Struct that keeps the information about the present time for last 74 * HISTORY_SIZE frames. This is used to better determine whether the given layer 75 * is still relevant and it's refresh rate should be considered. 76 */ 77 class PresentTimeHistory { 78 public: insertPresentTime(nsecs_t presentTime)79 void insertPresentTime(nsecs_t presentTime) { 80 mElements.push_back(presentTime); 81 if (mElements.size() > HISTORY_SIZE) { 82 mElements.pop_front(); 83 } 84 } 85 86 // Checks whether the present time that was inserted HISTORY_SIZE ago is within a 87 // certain threshold: TIME_EPSILON_NS. isRelevant()88 bool isRelevant() const { 89 const int64_t obsoleteEpsilon = systemTime() - scheduler::TIME_EPSILON_NS.count(); 90 // The layer had to publish at least HISTORY_SIZE of updates, and the first 91 // update should not be older than TIME_EPSILON_NS nanoseconds. 92 if (mElements.size() == HISTORY_SIZE && 93 mElements.at(HISTORY_SIZE - 1) > obsoleteEpsilon) { 94 return true; 95 } 96 return false; 97 } 98 clearHistory()99 void clearHistory() { mElements.clear(); } 100 101 private: 102 std::deque<nsecs_t> mElements; 103 static constexpr size_t HISTORY_SIZE = 10; 104 }; 105 106 public: 107 LayerInfo(const std::string name, float maxRefreshRate); 108 ~LayerInfo(); 109 110 LayerInfo(const LayerInfo&) = delete; 111 LayerInfo& operator=(const LayerInfo&) = delete; 112 113 // Records the last requested oresent time. It also stores information about when 114 // the layer was last updated. If the present time is farther in the future than the 115 // updated time, the updated time is the present time. 116 void setLastPresentTime(nsecs_t lastPresentTime); 117 setHDRContent(bool isHdr)118 void setHDRContent(bool isHdr) { 119 std::lock_guard lock(mLock); 120 mIsHDR = isHdr; 121 } 122 setVisibility(bool visible)123 void setVisibility(bool visible) { 124 std::lock_guard lock(mLock); 125 mIsVisible = visible; 126 } 127 128 // Checks the present time history to see whether the layer is relevant. isRecentlyActive()129 bool isRecentlyActive() const { 130 std::lock_guard lock(mLock); 131 return mPresentTimeHistory.isRelevant(); 132 } 133 134 // Calculate the average refresh rate. getDesiredRefreshRate()135 float getDesiredRefreshRate() const { 136 std::lock_guard lock(mLock); 137 return mRefreshRateHistory.getRefreshRateAvg(); 138 } 139 getHDRContent()140 bool getHDRContent() { 141 std::lock_guard lock(mLock); 142 return mIsHDR; 143 } 144 isVisible()145 bool isVisible() { 146 std::lock_guard lock(mLock); 147 return mIsVisible; 148 } 149 150 // Return the last updated time. If the present time is farther in the future than the 151 // updated time, the updated time is the present time. getLastUpdatedTime()152 nsecs_t getLastUpdatedTime() { 153 std::lock_guard lock(mLock); 154 return mLastUpdatedTime; 155 } 156 getName()157 std::string getName() const { return mName; } 158 clearHistory()159 void clearHistory() { 160 std::lock_guard lock(mLock); 161 mRefreshRateHistory.clearHistory(); 162 mPresentTimeHistory.clearHistory(); 163 } 164 165 private: 166 const std::string mName; 167 const nsecs_t mMinRefreshDuration; 168 mutable std::mutex mLock; 169 nsecs_t mLastUpdatedTime GUARDED_BY(mLock) = 0; 170 nsecs_t mLastPresentTime GUARDED_BY(mLock) = 0; 171 RefreshRateHistory mRefreshRateHistory GUARDED_BY(mLock); 172 PresentTimeHistory mPresentTimeHistory GUARDED_BY(mLock); 173 bool mIsHDR GUARDED_BY(mLock) = false; 174 bool mIsVisible GUARDED_BY(mLock) = false; 175 }; 176 177 } // namespace scheduler 178 } // namespace android