1 /*
2  * Copyright (C) 2024 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 <hardware/hwcomposer2.h>
20 #include <map>
21 #include <sstream>
22 #include <string>
23 #include <utility>
24 
25 #include "EventQueue.h"
26 #include "Utils.h"
27 #include "display/common/CommonDisplayContextProvider.h"
28 #include "interface/DisplayContextProvider.h"
29 #include "interface/VariableRefreshRateInterface.h"
30 
31 // #define DEBUG_VRR_STATISTICS 1
32 
33 namespace android::hardware::graphics::composer {
34 
35 // |DisplayStatus| is the intrinsic property of the key for statistics, representing the display
36 // configuration.
37 typedef struct DisplayStatus {
isOffDisplayStatus38     inline bool isOff() const {
39         if ((mPowerMode == HWC_POWER_MODE_OFF) || (mPowerMode == HWC_POWER_MODE_DOZE_SUSPEND)) {
40             return true;
41         } else {
42             return false;
43         }
44     }
45 
46     bool operator==(const DisplayStatus& rhs) const {
47         if (isOff() || rhs.isOff()) {
48             return isOff() == rhs.isOff();
49         }
50         return (mActiveConfigId == rhs.mActiveConfigId) && (mPowerMode == rhs.mPowerMode) &&
51                 (mBrightnessMode == rhs.mBrightnessMode);
52     }
53 
54     bool operator<(const DisplayStatus& rhs) const {
55         if (isOff() && rhs.isOff()) {
56             return false;
57         }
58 
59         if (mPowerMode != rhs.mPowerMode) {
60             return (isOff() || (mPowerMode < rhs.mPowerMode));
61         } else if (mActiveConfigId != rhs.mActiveConfigId) {
62             return mActiveConfigId < rhs.mActiveConfigId;
63         } else {
64             return mBrightnessMode < rhs.mBrightnessMode;
65         }
66     }
67 
toStringDisplayStatus68     std::string toString() const {
69         std::ostringstream os;
70         os << "id = " << mActiveConfigId;
71         os << ", power mode = " << mPowerMode;
72         os << ", brightness = " << static_cast<int>(mBrightnessMode);
73         return os.str();
74     }
75 
76     hwc2_config_t mActiveConfigId = -1;
77     int mPowerMode = HWC_POWER_MODE_OFF;
78     BrightnessMode mBrightnessMode = BrightnessMode::kInvalidBrightnessMode;
79 } DisplayStatus;
80 
81 // |DisplayPresentProfile| is the key to the statistics.
82 typedef struct DisplayPresentProfile {
isOffDisplayPresentProfile83     inline bool isOff() const { return mCurrentDisplayConfig.isOff(); }
84 
85     bool operator<(const DisplayPresentProfile& rhs) const {
86         if (isOff() || rhs.isOff()) {
87             if (isOff() == rhs.isOff()) {
88                 return false;
89             }
90         }
91 
92         if (mCurrentDisplayConfig != rhs.mCurrentDisplayConfig) {
93             return (mCurrentDisplayConfig < rhs.mCurrentDisplayConfig);
94         } else {
95             return (mNumVsync < rhs.mNumVsync);
96         }
97     }
98 
toStringDisplayPresentProfile99     std::string toString() const {
100         std::string res = mCurrentDisplayConfig.toString();
101         res += ", mNumVsync = " + std::to_string(mNumVsync);
102         return res;
103     }
104 
105     DisplayStatus mCurrentDisplayConfig;
106     // |mNumVsync| is the timing property of the key for statistics, representing the distribution
107     // of presentations. It represents the interval between a present and the previous present in
108     // terms of the number of vsyncs.
109     int mNumVsync = -1;
110 } DisplayPresentProfile;
111 
112 // |DisplayPresentRecord| is the value to the statistics.
113 typedef struct DisplayPresentRecord {
114     DisplayPresentRecord() = default;
115     DisplayPresentRecord& operator+=(const DisplayPresentRecord& other) {
116         this->mCount += other.mCount;
117         this->mAccumulatedTimeNs += other.mAccumulatedTimeNs;
118         this->mLastTimeStampInBootClockNs =
119                 std::max(mLastTimeStampInBootClockNs, other.mLastTimeStampInBootClockNs);
120         mUpdated = true;
121         return *this;
122     }
toStringDisplayPresentRecord123     std::string toString() const {
124         std::ostringstream os;
125         os << "Count = " << mCount;
126         os << ", AccumulatedTimeNs = " << mAccumulatedTimeNs / 1000000;
127         os << ", LastTimeStampInBootClockNs = " << mLastTimeStampInBootClockNs;
128         return os.str();
129     }
130     uint64_t mCount = 0;
131     uint64_t mAccumulatedTimeNs = 0;
132     uint64_t mLastTimeStampInBootClockNs = 0;
133     bool mUpdated = false;
134 } DisplayPresentRecord;
135 
136 // |DisplayPresentStatistics| is a map consisting of key-value pairs for statistics.
137 // The key consists of two parts: display configuration and refresh frequency (in terms of vsync).
138 typedef std::map<DisplayPresentProfile, DisplayPresentRecord> DisplayPresentStatistics;
139 
140 class StatisticsProvider {
141 public:
142     virtual ~StatisticsProvider() = default;
143 
144     virtual uint64_t getStartStatisticTimeNs() const = 0;
145 
146     virtual DisplayPresentStatistics getStatistics() = 0;
147 
148     virtual DisplayPresentStatistics getUpdatedStatistics() = 0;
149 };
150 
151 class VariableRefreshRateStatistic : public PowerModeListener,
152                                      public PresentListener,
153                                      public StatisticsProvider {
154 public:
155     VariableRefreshRateStatistic(CommonDisplayContextProvider* displayContextProvider,
156                                  EventQueue* eventQueue, int maxFrameRate, int maxTeFrequency,
157                                  int64_t updatePeriodNs);
158 
159     uint64_t getPowerOffDurationNs() const;
160 
161     uint64_t getStartStatisticTimeNs() const override;
162 
163     DisplayPresentStatistics getStatistics() override;
164 
165     DisplayPresentStatistics getUpdatedStatistics() override;
166 
167     void onPowerStateChange(int from, int to) final;
168 
169     void onPresent(int64_t presentTimeNs, int flag) override;
170 
171     void setActiveVrrConfiguration(int activeConfigId, int teFrequency);
172 
173     // If |minimumRefreshRate| is not equal to zero, enforce the minimum (fixed) refresh rate;
174     // otherwise, revert to a variable refresh rate.
175     void setFixedRefreshRate(uint32_t minimumRefreshRate);
176 
177     VariableRefreshRateStatistic(const VariableRefreshRateStatistic& other) = delete;
178     VariableRefreshRateStatistic& operator=(const VariableRefreshRateStatistic& other) = delete;
179 
180 private:
181     static constexpr int64_t kMaxPresentIntervalNs = std::nano::den;
182     static constexpr uint32_t kFrameRateWhenPresentAtLpMode = 30;
183 
184     bool isPowerModeOffNowLocked() const;
185 
186     void updateCurrentDisplayStatus();
187 
188     void updateIdleStats(int64_t endTimeStampInBootClockNs = -1);
189 
190 #ifdef DEBUG_VRR_STATISTICS
191     int updateStatistic();
192 #endif
193 
194     CommonDisplayContextProvider* mDisplayContextProvider;
195     EventQueue* mEventQueue;
196 
197     const int mMaxFrameRate;
198     const int mMaxTeFrequency;
199     const int64_t mMinFrameIntervalNs;
200 
201     int mTeFrequency;
202     int64_t mTeIntervalNs;
203 
204     const int64_t mUpdatePeriodNs;
205 
206     int64_t mLastPresentTimeInBootClockNs = kDefaultInvalidPresentTimeNs;
207 
208     DisplayPresentStatistics mStatistics;
209     DisplayPresentProfile mDisplayPresentProfile;
210 
211     uint64_t mPowerOffDurationNs = 0;
212 
213     uint32_t mMinimumRefreshRate = 1;
214     uint64_t mMaximumFrameIntervalNs = kMaxPresentIntervalNs; // 1 second.
215 
216     uint64_t mStartStatisticTimeNs;
217 
218 #ifdef DEBUG_VRR_STATISTICS
219     VrrControllerEvent mUpdateEvent;
220 #endif
221 
222     mutable std::mutex mMutex;
223 };
224 
225 } // namespace android::hardware::graphics::composer
226