1 /* 2 * Copyright 2018 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 #define ATRACE_TAG ATRACE_TAG_GRAPHICS 18 19 #include "LayerHistory.h" 20 21 #include <cinttypes> 22 #include <cstdint> 23 #include <limits> 24 #include <numeric> 25 #include <string> 26 #include <unordered_map> 27 28 #include <cutils/properties.h> 29 #include <utils/Log.h> 30 #include <utils/Timers.h> 31 #include <utils/Trace.h> 32 33 #include "SchedulerUtils.h" 34 35 namespace android { 36 namespace scheduler { 37 38 std::atomic<int64_t> LayerHistory::sNextId = 0; 39 40 LayerHistory::LayerHistory() { 41 char value[PROPERTY_VALUE_MAX]; 42 property_get("debug.sf.layer_history_trace", value, "0"); 43 mTraceEnabled = bool(atoi(value)); 44 } 45 46 LayerHistory::~LayerHistory() = default; 47 48 std::unique_ptr<LayerHistory::LayerHandle> LayerHistory::createLayer(const std::string name, 49 float maxRefreshRate) { 50 const int64_t id = sNextId++; 51 52 std::lock_guard lock(mLock); 53 mInactiveLayerInfos.emplace(id, std::make_shared<LayerInfo>(name, maxRefreshRate)); 54 return std::make_unique<LayerHistory::LayerHandle>(*this, id); 55 } 56 57 void LayerHistory::destroyLayer(const int64_t id) { 58 std::lock_guard lock(mLock); 59 auto it = mActiveLayerInfos.find(id); 60 if (it != mActiveLayerInfos.end()) { 61 mActiveLayerInfos.erase(it); 62 } 63 64 it = mInactiveLayerInfos.find(id); 65 if (it != mInactiveLayerInfos.end()) { 66 mInactiveLayerInfos.erase(it); 67 } 68 } 69 70 void LayerHistory::insert(const std::unique_ptr<LayerHandle>& layerHandle, nsecs_t presentTime, 71 bool isHdr) { 72 std::shared_ptr<LayerInfo> layerInfo; 73 { 74 std::lock_guard lock(mLock); 75 auto layerInfoIterator = mInactiveLayerInfos.find(layerHandle->mId); 76 if (layerInfoIterator != mInactiveLayerInfos.end()) { 77 layerInfo = layerInfoIterator->second; 78 mInactiveLayerInfos.erase(layerInfoIterator); 79 mActiveLayerInfos.insert({layerHandle->mId, layerInfo}); 80 } else { 81 layerInfoIterator = mActiveLayerInfos.find(layerHandle->mId); 82 if (layerInfoIterator != mActiveLayerInfos.end()) { 83 layerInfo = layerInfoIterator->second; 84 } else { 85 ALOGW("Inserting information about layer that is not registered: %" PRId64, 86 layerHandle->mId); 87 return; 88 } 89 } 90 } 91 layerInfo->setLastPresentTime(presentTime); 92 layerInfo->setHDRContent(isHdr); 93 } 94 95 void LayerHistory::setVisibility(const std::unique_ptr<LayerHandle>& layerHandle, bool visible) { 96 std::shared_ptr<LayerInfo> layerInfo; 97 { 98 std::lock_guard lock(mLock); 99 auto layerInfoIterator = mInactiveLayerInfos.find(layerHandle->mId); 100 if (layerInfoIterator != mInactiveLayerInfos.end()) { 101 layerInfo = layerInfoIterator->second; 102 if (visible) { 103 mInactiveLayerInfos.erase(layerInfoIterator); 104 mActiveLayerInfos.insert({layerHandle->mId, layerInfo}); 105 } 106 } else { 107 layerInfoIterator = mActiveLayerInfos.find(layerHandle->mId); 108 if (layerInfoIterator != mActiveLayerInfos.end()) { 109 layerInfo = layerInfoIterator->second; 110 } else { 111 ALOGW("Inserting information about layer that is not registered: %" PRId64, 112 layerHandle->mId); 113 return; 114 } 115 } 116 } 117 layerInfo->setVisibility(visible); 118 } 119 120 std::pair<float, bool> LayerHistory::getDesiredRefreshRateAndHDR() { 121 bool isHDR = false; 122 float newRefreshRate = 0.f; 123 std::lock_guard lock(mLock); 124 125 removeIrrelevantLayers(); 126 127 // Iterate through all layers that have been recently updated, and find the max refresh rate. 128 for (const auto& [layerId, layerInfo] : mActiveLayerInfos) { 129 const float layerRefreshRate = layerInfo->getDesiredRefreshRate(); 130 if (mTraceEnabled) { 131 // Store the refresh rate in traces for easy debugging. 132 std::string layerName = "LFPS " + layerInfo->getName(); 133 ATRACE_INT(layerName.c_str(), std::round(layerRefreshRate)); 134 ALOGD("%s: %f", layerName.c_str(), std::round(layerRefreshRate)); 135 } 136 if (layerInfo->isRecentlyActive() && layerRefreshRate > newRefreshRate) { 137 newRefreshRate = layerRefreshRate; 138 } 139 isHDR |= layerInfo->getHDRContent(); 140 } 141 if (mTraceEnabled) { 142 ALOGD("LayerHistory DesiredRefreshRate: %.2f", newRefreshRate); 143 } 144 145 return {newRefreshRate, isHDR}; 146 } 147 148 void LayerHistory::removeIrrelevantLayers() { 149 const int64_t obsoleteEpsilon = systemTime() - scheduler::OBSOLETE_TIME_EPSILON_NS.count(); 150 // Iterator pointing to first element in map 151 auto it = mActiveLayerInfos.begin(); 152 while (it != mActiveLayerInfos.end()) { 153 // If last updated was before the obsolete time, remove it. 154 // Keep HDR layer around as long as they are visible. 155 if (!it->second->isVisible() || 156 (!it->second->getHDRContent() && it->second->getLastUpdatedTime() < obsoleteEpsilon)) { 157 // erase() function returns the iterator of the next 158 // to last deleted element. 159 if (mTraceEnabled) { 160 ALOGD("Layer %s obsolete", it->second->getName().c_str()); 161 // Make sure to update systrace to indicate that the layer was erased. 162 std::string layerName = "LFPS " + it->second->getName(); 163 ATRACE_INT(layerName.c_str(), 0); 164 } 165 auto id = it->first; 166 auto layerInfo = it->second; 167 layerInfo->clearHistory(); 168 mInactiveLayerInfos.insert({id, layerInfo}); 169 it = mActiveLayerInfos.erase(it); 170 } else { 171 ++it; 172 } 173 } 174 } 175 176 } // namespace scheduler 177 } // namespace android