Home | History | Annotate | Download | only in Scheduler
      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