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 minRefreshRate,float maxRefreshRate)48 std::unique_ptr<LayerHistory::LayerHandle> LayerHistory::createLayer(const std::string name,
49                                                                      float minRefreshRate,
50                                                                      float maxRefreshRate) {
51     const int64_t id = sNextId++;
52 
53     std::lock_guard lock(mLock);
54     mInactiveLayerInfos.emplace(id,
55                                 std::make_shared<LayerInfo>(name, minRefreshRate, maxRefreshRate));
56     return std::make_unique<LayerHistory::LayerHandle>(*this, id);
57 }
58 
destroyLayer(const int64_t id)59 void LayerHistory::destroyLayer(const int64_t id) {
60     std::lock_guard lock(mLock);
61     auto it = mActiveLayerInfos.find(id);
62     if (it != mActiveLayerInfos.end()) {
63         mActiveLayerInfos.erase(it);
64     }
65 
66     it = mInactiveLayerInfos.find(id);
67     if (it != mInactiveLayerInfos.end()) {
68         mInactiveLayerInfos.erase(it);
69     }
70 }
71 
insert(const std::unique_ptr<LayerHandle> & layerHandle,nsecs_t presentTime,bool isHdr)72 void LayerHistory::insert(const std::unique_ptr<LayerHandle>& layerHandle, nsecs_t presentTime,
73                           bool isHdr) {
74     std::shared_ptr<LayerInfo> layerInfo;
75     {
76         std::lock_guard lock(mLock);
77         auto layerInfoIterator = mInactiveLayerInfos.find(layerHandle->mId);
78         if (layerInfoIterator != mInactiveLayerInfos.end()) {
79             layerInfo = layerInfoIterator->second;
80             mInactiveLayerInfos.erase(layerInfoIterator);
81             mActiveLayerInfos.insert({layerHandle->mId, layerInfo});
82         } else {
83             layerInfoIterator = mActiveLayerInfos.find(layerHandle->mId);
84             if (layerInfoIterator != mActiveLayerInfos.end()) {
85                 layerInfo = layerInfoIterator->second;
86             } else {
87                 ALOGW("Inserting information about layer that is not registered: %" PRId64,
88                       layerHandle->mId);
89                 return;
90             }
91         }
92     }
93     layerInfo->setLastPresentTime(presentTime);
94     layerInfo->setHDRContent(isHdr);
95 }
96 
setVisibility(const std::unique_ptr<LayerHandle> & layerHandle,bool visible)97 void LayerHistory::setVisibility(const std::unique_ptr<LayerHandle>& layerHandle, bool visible) {
98     std::shared_ptr<LayerInfo> layerInfo;
99     {
100         std::lock_guard lock(mLock);
101         auto layerInfoIterator = mInactiveLayerInfos.find(layerHandle->mId);
102         if (layerInfoIterator != mInactiveLayerInfos.end()) {
103             layerInfo = layerInfoIterator->second;
104             if (visible) {
105                 mInactiveLayerInfos.erase(layerInfoIterator);
106                 mActiveLayerInfos.insert({layerHandle->mId, layerInfo});
107             }
108         } else {
109             layerInfoIterator = mActiveLayerInfos.find(layerHandle->mId);
110             if (layerInfoIterator != mActiveLayerInfos.end()) {
111                 layerInfo = layerInfoIterator->second;
112             } else {
113                 ALOGW("Inserting information about layer that is not registered: %" PRId64,
114                       layerHandle->mId);
115                 return;
116             }
117         }
118     }
119     layerInfo->setVisibility(visible);
120 }
121 
getDesiredRefreshRateAndHDR()122 std::pair<float, bool> LayerHistory::getDesiredRefreshRateAndHDR() {
123     bool isHDR = false;
124     float newRefreshRate = 0.f;
125     std::lock_guard lock(mLock);
126 
127     removeIrrelevantLayers();
128 
129     // Iterate through all layers that have been recently updated, and find the max refresh rate.
130     for (const auto& [layerId, layerInfo] : mActiveLayerInfos) {
131         const float layerRefreshRate = layerInfo->getDesiredRefreshRate();
132         if (mTraceEnabled) {
133             // Store the refresh rate in traces for easy debugging.
134             std::string layerName = "LFPS " + layerInfo->getName();
135             ATRACE_INT(layerName.c_str(), std::round(layerRefreshRate));
136             ALOGD("%s: %f", layerName.c_str(), std::round(layerRefreshRate));
137         }
138         if (layerInfo->isRecentlyActive() && layerRefreshRate > newRefreshRate) {
139             newRefreshRate = layerRefreshRate;
140         }
141         isHDR |= layerInfo->getHDRContent();
142     }
143     if (mTraceEnabled) {
144         ALOGD("LayerHistory DesiredRefreshRate: %.2f", newRefreshRate);
145     }
146 
147     return {newRefreshRate, isHDR};
148 }
149 
removeIrrelevantLayers()150 void LayerHistory::removeIrrelevantLayers() {
151     const int64_t obsoleteEpsilon = systemTime() - scheduler::OBSOLETE_TIME_EPSILON_NS.count();
152     // Iterator pointing to first element in map
153     auto it = mActiveLayerInfos.begin();
154     while (it != mActiveLayerInfos.end()) {
155         // If last updated was before the obsolete time, remove it.
156         // Keep HDR layer around as long as they are visible.
157         if (!it->second->isVisible() ||
158             (!it->second->getHDRContent() && it->second->getLastUpdatedTime() < obsoleteEpsilon)) {
159             // erase() function returns the iterator of the next
160             // to last deleted element.
161             if (mTraceEnabled) {
162                 ALOGD("Layer %s obsolete", it->second->getName().c_str());
163                 // Make sure to update systrace to indicate that the layer was erased.
164                 std::string layerName = "LFPS " + it->second->getName();
165                 ATRACE_INT(layerName.c_str(), 0);
166             }
167             auto id = it->first;
168             auto layerInfo = it->second;
169             layerInfo->clearHistory();
170             mInactiveLayerInfos.insert({id, layerInfo});
171             it = mActiveLayerInfos.erase(it);
172         } else {
173             ++it;
174         }
175     }
176 }
177 
clearHistory()178 void LayerHistory::clearHistory() {
179     std::lock_guard lock(mLock);
180 
181     auto it = mActiveLayerInfos.begin();
182     while (it != mActiveLayerInfos.end()) {
183         auto id = it->first;
184         auto layerInfo = it->second;
185         layerInfo->clearHistory();
186         mInactiveLayerInfos.insert({id, layerInfo});
187         it = mActiveLayerInfos.erase(it);
188     }
189 }
190 
191 } // namespace scheduler
192 } // namespace android