Home | History | Annotate | Download | only in Scheduler
      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:
     47         explicit RefreshRateHistory(nsecs_t minRefreshDuration)
     48               : mMinRefreshDuration(minRefreshDuration) {}
     49         void insertRefreshRate(nsecs_t refreshRate) {
     50             mElements.push_back(refreshRate);
     51             if (mElements.size() > HISTORY_SIZE) {
     52                 mElements.pop_front();
     53             }
     54         }
     55 
     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         }
     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:
     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.
     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 
     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 
    118     void setHDRContent(bool isHdr) {
    119         std::lock_guard lock(mLock);
    120         mIsHDR = isHdr;
    121     }
    122 
    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.
    129     bool isRecentlyActive() const {
    130         std::lock_guard lock(mLock);
    131         return mPresentTimeHistory.isRelevant();
    132     }
    133 
    134     // Calculate the average refresh rate.
    135     float getDesiredRefreshRate() const {
    136         std::lock_guard lock(mLock);
    137         return mRefreshRateHistory.getRefreshRateAvg();
    138     }
    139 
    140     bool getHDRContent() {
    141         std::lock_guard lock(mLock);
    142         return mIsHDR;
    143     }
    144 
    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.
    152     nsecs_t getLastUpdatedTime() {
    153         std::lock_guard lock(mLock);
    154         return mLastUpdatedTime;
    155     }
    156 
    157     std::string getName() const { return mName; }
    158 
    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