1 /*
2  * Copyright 2020 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 <chrono>
20 #include <deque>
21 #include <optional>
22 #include <string>
23 #include <unordered_map>
24 
25 #include <ui/Transform.h>
26 #include <utils/Timers.h>
27 
28 #include <scheduler/Fps.h>
29 #include <scheduler/Seamlessness.h>
30 
31 #include "FrameRateCompatibility.h"
32 #include "LayerHistory.h"
33 #include "RefreshRateSelector.h"
34 
35 namespace android {
36 
37 class Layer;
38 
39 namespace scheduler {
40 
41 using namespace std::chrono_literals;
42 struct LayerProps;
43 // Maximum period between presents for a layer to be considered active.
44 constexpr std::chrono::nanoseconds MAX_ACTIVE_LAYER_PERIOD_NS = 1200ms;
45 
46 // Earliest present time for a layer to be considered active.
getActiveLayerThreshold(nsecs_t now)47 constexpr nsecs_t getActiveLayerThreshold(nsecs_t now) {
48     return now - MAX_ACTIVE_LAYER_PERIOD_NS.count();
49 }
50 
51 // Stores history of present times and refresh rates for a layer.
52 class LayerInfo {
53     using LayerUpdateType = LayerHistory::LayerUpdateType;
54 
55     // Layer is considered frequent if the earliest value in the window of most recent present times
56     // is within a threshold. If a layer is infrequent, its average refresh rate is disregarded in
57     // favor of a low refresh rate.
58     static constexpr size_t kFrequentLayerWindowSize = 4;
59     static constexpr Fps kMinFpsForFrequentLayer = 10_Hz;
60     static constexpr auto kMaxPeriodForFrequentLayerNs =
61             std::chrono::nanoseconds(kMinFpsForFrequentLayer.getPeriodNsecs()) + 1ms;
62     static constexpr size_t kNumSmallDirtyThreshold = 2;
63 
64     friend class LayerHistoryTest;
65     friend class LayerHistoryIntegrationTest;
66     friend class LayerInfoTest;
67 
68 public:
69     // Holds information about the layer vote
70     struct LayerVote {
71         LayerHistory::LayerVoteType type = LayerHistory::LayerVoteType::Heuristic;
72         Fps fps;
73         Seamlessness seamlessness = Seamlessness::Default;
74         FrameRateCategory category = FrameRateCategory::Default;
75         bool categorySmoothSwitchOnly = false;
76 
77         // Returns true if the layer explicitly should contribute to frame rate scoring.
isNoVoteLayerVote78         bool isNoVote() const { return RefreshRateSelector::isNoVote(type); }
79     };
80 
81     using RefreshRateVotes = ftl::SmallVector<LayerInfo::LayerVote, 2>;
82 
83     enum class FrameRateSelectionStrategy {
84         Propagate,
85         OverrideChildren,
86         Self,
87 
88         ftl_last = Self
89     };
90 
91     // Encapsulates the frame rate specifications of the layer. This information will be used
92     // when the display refresh rate is determined.
93     struct FrameRate {
94         using Seamlessness = scheduler::Seamlessness;
95 
96         // Information related to a specific desired frame rate vote.
97         struct FrameRateVote {
98             Fps rate;
99             FrameRateCompatibility type = FrameRateCompatibility::Default;
100             Seamlessness seamlessness = Seamlessness::Default;
101 
102             bool operator==(const FrameRateVote& other) const {
103                 return isApproxEqual(rate, other.rate) && type == other.type &&
104                         seamlessness == other.seamlessness;
105             }
106 
107             FrameRateVote() = default;
108 
109             FrameRateVote(Fps rate, FrameRateCompatibility type,
110                           Seamlessness seamlessness = Seamlessness::OnlySeamless)
rateFrameRate::FrameRateVote111                   : rate(rate), type(type), seamlessness(getSeamlessness(rate, seamlessness)) {}
112         } vote;
113 
114         FrameRateCategory category = FrameRateCategory::Default;
115         bool categorySmoothSwitchOnly = false;
116 
117         FrameRate() = default;
118 
119         FrameRate(Fps rate, FrameRateCompatibility type,
120                   Seamlessness seamlessness = Seamlessness::OnlySeamless,
121                   FrameRateCategory category = FrameRateCategory::Default)
voteFrameRate122               : vote(FrameRateVote(rate, type, seamlessness)), category(category) {}
123 
124         bool operator==(const FrameRate& other) const {
125             return vote == other.vote && category == other.category;
126         }
127 
128         bool operator!=(const FrameRate& other) const { return !(*this == other); }
129 
130         // Convert an ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_* value to a
131         // Layer::FrameRateCompatibility. Logs fatal if the compatibility value is invalid.
132         static FrameRateCompatibility convertCompatibility(int8_t compatibility);
133 
134         // Convert an ANATIVEWINDOW_CHANGE_FRAME_RATE_* value to a scheduler::Seamlessness.
135         // Logs fatal if the strategy value is invalid.
136         static scheduler::Seamlessness convertChangeFrameRateStrategy(int8_t strategy);
137 
138         // Convert an ANATIVEWINDOW_FRAME_RATE_CATEGORY_* value to a FrameRateCategory.
139         // Logs fatal if the category value is invalid.
140         static FrameRateCategory convertCategory(int8_t category);
141 
142         // True if the FrameRate has explicit frame rate specifications.
143         bool isValid() const;
144 
145         // Returns true if the FrameRate explicitly instructs to not contribute to frame rate
146         // selection.
147         bool isNoVote() const;
148 
149         // Returns true if the FrameRate has a valid valueless (0 Hz) frame rate type.
150         bool isValuelessType() const;
151 
152         // Checks whether the given FrameRate's vote specifications is valid for MRR devices
153         // given the current flagging.
154         bool isVoteValidForMrr(bool isVrrDevice) const;
155 
156     private:
getSeamlessnessFrameRate157         static Seamlessness getSeamlessness(Fps rate, Seamlessness seamlessness) {
158             if (!rate.isValid()) {
159                 // Refresh rate of 0 is a special value which should reset the vote to
160                 // its default value.
161                 return Seamlessness::Default;
162             }
163             return seamlessness;
164         }
165     };
166 
167     // Convert an ANATIVEWINDOW_FRAME_RATE_SELECTION_STRATEGY_* value to FrameRateSelectionStrategy.
168     // Logs fatal if the strategy value is invalid.
169     static FrameRateSelectionStrategy convertFrameRateSelectionStrategy(int8_t strategy);
170 
setTraceEnabled(bool enabled)171     static void setTraceEnabled(bool enabled) { sTraceEnabled = enabled; }
172 
173     LayerInfo(const std::string& name, uid_t ownerUid, LayerHistory::LayerVoteType defaultVote);
174 
175     LayerInfo(const LayerInfo&) = delete;
176     LayerInfo& operator=(const LayerInfo&) = delete;
177 
178     // Records the last requested present time. It also stores information about when
179     // the layer was last updated. If the present time is farther in the future than the
180     // updated time, the updated time is the present time.
181     void setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now, LayerUpdateType updateType,
182                             bool pendingModeChange, const LayerProps& props);
183 
184     // Sets an explicit layer vote. This usually comes directly from the application via
185     // ANativeWindow_setFrameRate API. This is also used by Game Default Frame Rate and
186     // Game Mode Intervention Frame Rate.
setLayerVote(LayerVote vote)187     void setLayerVote(LayerVote vote) { mLayerVote = vote; }
188 
189     // Sets the default layer vote. This will be the layer vote after calling to resetLayerVote().
190     // This is used for layers that called to setLayerVote() and then removed the vote, so that the
191     // layer can go back to whatever vote it had before the app voted for it.
setDefaultLayerVote(LayerHistory::LayerVoteType type)192     void setDefaultLayerVote(LayerHistory::LayerVoteType type) { mDefaultVote = type; }
193 
194     void setProperties(const LayerProps&);
195 
196     // Resets the layer vote to its default.
resetLayerVote()197     void resetLayerVote() {
198         mLayerVote = {mDefaultVote, Fps(), Seamlessness::Default, FrameRateCategory::Default};
199     }
200 
getName()201     std::string getName() const { return mName; }
202 
getOwnerUid()203     uid_t getOwnerUid() const { return mOwnerUid; }
204 
205     RefreshRateVotes getRefreshRateVote(const RefreshRateSelector&, nsecs_t now);
206 
207     // Return the last updated time. If the present time is farther in the future than the
208     // updated time, the updated time is the present time.
getLastUpdatedTime()209     nsecs_t getLastUpdatedTime() const { return mLastUpdatedTime; }
210 
211     FrameRate getSetFrameRateVote() const;
212     bool isVisible() const;
213     int32_t getFrameRateSelectionPriority() const;
214     bool isFrontBuffered() const;
215     FloatRect getBounds() const;
216     ui::Transform getTransform() const;
217 
218     // Returns a C string for tracing a vote
219     const char* getTraceTag(LayerHistory::LayerVoteType type) const;
220 
221     // Return the framerate of this layer.
222     Fps getFps(nsecs_t now) const;
223 
onLayerInactive(nsecs_t now)224     void onLayerInactive(nsecs_t now) {
225         // Mark mFrameTimeValidSince to now to ignore all previous frame times.
226         // We are not deleting the old frame to keep track of whether we should treat the first
227         // buffer as Max as we don't know anything about this layer or Min as this layer is
228         // posting infrequent updates.
229         const auto timePoint = std::chrono::nanoseconds(now);
230         mFrameTimeValidSince = std::chrono::time_point<std::chrono::steady_clock>(timePoint);
231         mLastRefreshRate = {};
232         mRefreshRateHistory.clear();
233         mIsFrequencyConclusive = true;
234     }
235 
clearHistory(nsecs_t now)236     void clearHistory(nsecs_t now) {
237         onLayerInactive(now);
238         mFrameTimes.clear();
239     }
240 
241 private:
242     // Used to store the layer timestamps
243     struct FrameTimeData {
244         nsecs_t presentTime; // desiredPresentTime, if provided
245         nsecs_t queueTime;  // buffer queue time
246         bool pendingModeChange;
247         bool isSmallDirty;
248     };
249 
250     // Holds information about the calculated and reported refresh rate
251     struct RefreshRateHeuristicData {
252         // Rate calculated on the layer
253         Fps calculated;
254         // Last reported rate for LayerInfo::getRefreshRate()
255         Fps reported;
256         // Whether the last reported rate for LayerInfo::getRefreshRate()
257         // was due to animation or infrequent updates
258         bool animating = false;
259         // Whether the last reported rate for LayerInfo::getRefreshRate()
260         // was due to infrequent updates
261         bool infrequent = false;
262     };
263 
264     // Class to store past calculated refresh rate and determine whether
265     // the refresh rate calculated is consistent with past values
266     class RefreshRateHistory {
267     public:
268         static constexpr auto HISTORY_SIZE = 90;
269         static constexpr std::chrono::nanoseconds HISTORY_DURATION = 2s;
270 
RefreshRateHistory(const std::string & name)271         RefreshRateHistory(const std::string& name) : mName(name) {}
272 
273         // Clears History
274         void clear();
275 
276         // Adds a new refresh rate and returns valid refresh rate if it is consistent enough
277         Fps add(Fps refreshRate, nsecs_t now, const RefreshRateSelector&);
278 
279     private:
280         friend class LayerHistoryTest;
281         friend class LayerHistoryIntegrationTest;
282 
283         // Holds the refresh rate when it was calculated
284         struct RefreshRateData {
285             Fps refreshRate;
286             nsecs_t timestamp = 0;
287         };
288 
289         // Holds tracing strings
290         struct HeuristicTraceTagData {
291             std::string min;
292             std::string max;
293             std::string consistent;
294             std::string average;
295         };
296 
297         Fps selectRefreshRate(const RefreshRateSelector&) const;
298         HeuristicTraceTagData makeHeuristicTraceTagData() const;
299 
300         const std::string mName;
301         mutable std::optional<HeuristicTraceTagData> mHeuristicTraceTagData;
302         std::deque<RefreshRateData> mRefreshRates;
303         static constexpr float MARGIN_CONSISTENT_FPS = 1.0;
304         static constexpr float MARGIN_CONSISTENT_FPS_FOR_CLOSEST_REFRESH_RATE = 5.0;
305     };
306 
307     // Represents whether we were able to determine either layer is frequent or infrequent
308     bool mIsFrequencyConclusive = true;
309     struct Frequent {
310         bool isFrequent;
311         bool clearHistory;
312         // Represents whether we were able to determine isFrequent conclusively
313         bool isConclusive;
314         // Represents whether the latest frames are small dirty.
315         bool isSmallDirty = false;
316     };
317     Frequent isFrequent(nsecs_t now) const;
318     bool isAnimating(nsecs_t now) const;
319     bool hasEnoughDataForHeuristic() const;
320     std::optional<Fps> calculateRefreshRateIfPossible(const RefreshRateSelector&, nsecs_t now);
321     std::optional<nsecs_t> calculateAverageFrameTime() const;
322     bool isFrameTimeValid(const FrameTimeData&) const;
323 
324     const std::string mName;
325     const uid_t mOwnerUid;
326 
327     // Used for sanitizing the heuristic data. If two frames are less than
328     // this period apart from each other they'll be considered as duplicates.
329     static constexpr nsecs_t kMinPeriodBetweenFrames = (240_Hz).getPeriodNsecs();
330     // Used for sanitizing the heuristic data. If two frames are more than
331     // this period apart from each other, the interval between them won't be
332     // taken into account when calculating average frame rate.
333     static constexpr nsecs_t kMaxPeriodBetweenFrames = kMinFpsForFrequentLayer.getPeriodNsecs();
334     // Used for sanitizing the heuristic data. If frames are small dirty updating and are less
335     // than this period apart from each other, the interval between them won't be
336     // taken into account when calculating average frame rate.
337     static constexpr nsecs_t kMinPeriodBetweenSmallDirtyFrames = (60_Hz).getPeriodNsecs();
338 
339     LayerHistory::LayerVoteType mDefaultVote;
340 
341     LayerVote mLayerVote;
342 
343     nsecs_t mLastUpdatedTime = 0;
344 
345     nsecs_t mLastAnimationTime = 0;
346 
347     RefreshRateHeuristicData mLastRefreshRate;
348 
349     std::deque<FrameTimeData> mFrameTimes;
350     std::chrono::time_point<std::chrono::steady_clock> mFrameTimeValidSince =
351             std::chrono::steady_clock::now();
352     static constexpr size_t HISTORY_SIZE = RefreshRateHistory::HISTORY_SIZE;
353     static constexpr std::chrono::nanoseconds HISTORY_DURATION = LayerHistory::kMaxPeriodForHistory;
354 
355     std::unique_ptr<LayerProps> mLayerProps;
356 
357     RefreshRateHistory mRefreshRateHistory;
358 
359     // This will be accessed from only one thread when counting a layer is frequent or infrequent,
360     // and to determine whether a layer is in small dirty updating.
361     mutable int32_t mLastSmallDirtyCount = 0;
362 
363     mutable std::unordered_map<LayerHistory::LayerVoteType, std::string> mTraceTags;
364 
365     // Shared for all LayerInfo instances
366     static bool sTraceEnabled;
367 };
368 
369 struct LayerProps {
370     bool visible = false;
371     FloatRect bounds;
372     ui::Transform transform;
373     LayerInfo::FrameRate setFrameRateVote;
374     int32_t frameRateSelectionPriority = -1;
375     bool isSmallDirty = false;
376     bool isFrontBuffered = false;
377 };
378 
379 } // namespace scheduler
380 } // namespace android
381