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 <mutex>
20 #include <optional>
21 #include <string>
22 
23 #include <android-base/thread_annotations.h>
24 #include <ftl/small_map.h>
25 #include <utils/Timers.h>
26 
27 #include <scheduler/Fps.h>
28 #include <scheduler/VsyncConfig.h>
29 
30 namespace android::scheduler {
31 
32 /*
33  * This class encapsulates vsync configurations for different refresh rates. Depending
34  * on what refresh rate we are using, and wheter we are composing in GL,
35  * different offsets will help us with latency. This class keeps track of
36  * which mode the device is on, and returns approprate offsets when needed.
37  */
38 class VsyncConfiguration {
39 public:
40     virtual ~VsyncConfiguration() = default;
41     virtual VsyncConfigSet getCurrentConfigs() const = 0;
42     virtual VsyncConfigSet getConfigsForRefreshRate(Fps fps) const = 0;
43     virtual void reset() = 0;
44 
45     virtual void setRefreshRateFps(Fps fps) = 0;
46     virtual void dump(std::string& result) const = 0;
47 };
48 
49 namespace impl {
50 
51 /*
52  * This is a common implementation for both phase offsets and durations.
53  * PhaseOffsets and WorkDuration derive from this class and implement the
54  * constructOffsets method
55  */
56 class VsyncConfiguration : public scheduler::VsyncConfiguration {
57 public:
58     explicit VsyncConfiguration(Fps currentFps);
59 
60     // Returns early, early GL, and late offsets for Apps and SF for a given refresh rate.
61     VsyncConfigSet getConfigsForRefreshRate(Fps fps) const override EXCLUDES(mLock);
62 
63     // Returns early, early GL, and late offsets for Apps and SF.
getCurrentConfigs()64     VsyncConfigSet getCurrentConfigs() const override EXCLUDES(mLock) {
65         std::lock_guard lock(mLock);
66         return getConfigsForRefreshRateLocked(mRefreshRateFps);
67     }
68 
69     // Cleans the internal cache.
reset()70     void reset() override EXCLUDES(mLock) {
71         std::lock_guard lock(mLock);
72         mOffsetsCache.clear();
73     }
74 
75     // This function should be called when the device is switching between different
76     // refresh rates, to properly update the offsets.
setRefreshRateFps(Fps fps)77     void setRefreshRateFps(Fps fps) override EXCLUDES(mLock) {
78         std::lock_guard lock(mLock);
79         mRefreshRateFps = fps;
80     }
81 
82     // Returns current offsets in human friendly format.
83     void dump(std::string& result) const override;
84 
85 protected:
86     virtual VsyncConfigSet constructOffsets(nsecs_t vsyncDuration) const = 0;
87 
88     VsyncConfigSet getConfigsForRefreshRateLocked(Fps fps) const REQUIRES(mLock);
89 
90     mutable ftl::SmallMap<Fps, VsyncConfigSet, 2, FpsApproxEqual> mOffsetsCache GUARDED_BY(mLock);
91     Fps mRefreshRateFps GUARDED_BY(mLock);
92     mutable std::mutex mLock;
93 };
94 
95 /*
96  * This is the old implementation of phase offsets and considered as deprecated.
97  * WorkDuration is the new implementation.
98  */
99 class PhaseOffsets : public VsyncConfiguration {
100 public:
101     explicit PhaseOffsets(Fps currentRefreshRate);
102 
103 protected:
104     // Used for unit tests
105     PhaseOffsets(Fps currentRefreshRate, nsecs_t vsyncPhaseOffsetNs, nsecs_t sfVSyncPhaseOffsetNs,
106                  std::optional<nsecs_t> earlySfOffsetNs, std::optional<nsecs_t> earlyGpuSfOffsetNs,
107                  std::optional<nsecs_t> earlyAppOffsetNs,
108                  std::optional<nsecs_t> earlyGpuAppOffsetNs, nsecs_t highFpsVsyncPhaseOffsetNs,
109                  nsecs_t highFpsSfVSyncPhaseOffsetNs, std::optional<nsecs_t> highFpsEarlySfOffsetNs,
110                  std::optional<nsecs_t> highFpsEarlyGpuSfOffsetNs,
111                  std::optional<nsecs_t> highFpsEarlyAppOffsetNs,
112                  std::optional<nsecs_t> highFpsEarlyGpuAppOffsetNs, nsecs_t thresholdForNextVsync,
113                  nsecs_t hwcMinWorkDuration);
114 
115 private:
116     VsyncConfigSet constructOffsets(nsecs_t vsyncDuration) const override;
117 
118     VsyncConfigSet getDefaultOffsets(nsecs_t vsyncPeriod) const;
119     VsyncConfigSet getHighFpsOffsets(nsecs_t vsyncPeriod) const;
120 
121     const nsecs_t mVSyncPhaseOffsetNs;
122     const nsecs_t mSfVSyncPhaseOffsetNs;
123     const std::optional<nsecs_t> mEarlySfOffsetNs;
124     const std::optional<nsecs_t> mEarlyGpuSfOffsetNs;
125     const std::optional<nsecs_t> mEarlyAppOffsetNs;
126     const std::optional<nsecs_t> mEarlyGpuAppOffsetNs;
127 
128     const nsecs_t mHighFpsVSyncPhaseOffsetNs;
129     const nsecs_t mHighFpsSfVSyncPhaseOffsetNs;
130     const std::optional<nsecs_t> mHighFpsEarlySfOffsetNs;
131     const std::optional<nsecs_t> mHighFpsEarlyGpuSfOffsetNs;
132     const std::optional<nsecs_t> mHighFpsEarlyAppOffsetNs;
133     const std::optional<nsecs_t> mHighFpsEarlyGpuAppOffsetNs;
134 
135     const nsecs_t mThresholdForNextVsync;
136     const nsecs_t mHwcMinWorkDuration;
137 };
138 
139 /*
140  * Class that encapsulates the phase offsets for SurfaceFlinger and App.
141  * The offsets are calculated from durations for each one of the (late, early, earlyGpu)
142  * offset types.
143  */
144 class WorkDuration : public VsyncConfiguration {
145 public:
146     explicit WorkDuration(Fps currentRefreshRate);
147 
148 protected:
149     // Used for unit tests
150     WorkDuration(Fps currentFps, nsecs_t sfDuration, nsecs_t appDuration, nsecs_t sfEarlyDuration,
151                  nsecs_t appEarlyDuration, nsecs_t sfEarlyGpuDuration, nsecs_t appEarlyGpuDuration,
152                  nsecs_t hwcMinWorkDuration);
153 
154 private:
155     VsyncConfigSet constructOffsets(nsecs_t vsyncDuration) const override;
156 
157     const nsecs_t mSfDuration;
158     const nsecs_t mAppDuration;
159 
160     const nsecs_t mSfEarlyDuration;
161     const nsecs_t mAppEarlyDuration;
162 
163     const nsecs_t mSfEarlyGpuDuration;
164     const nsecs_t mAppEarlyGpuDuration;
165 
166     const nsecs_t mHwcMinWorkDuration;
167 };
168 
169 } // namespace impl
170 } // namespace android::scheduler
171