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 
LayerHistory()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 
createLayer(const std::string name,float maxRefreshRate)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 
destroyLayer(const int64_t id)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 
insert(const std::unique_ptr<LayerHandle> & layerHandle,nsecs_t presentTime,bool isHdr)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 
setVisibility(const std::unique_ptr<LayerHandle> & layerHandle,bool visible)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 
getDesiredRefreshRateAndHDR()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 
removeIrrelevantLayers()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