xref: /aosp_15_r20/frameworks/native/services/surfaceflinger/Scheduler/VsyncConfiguration.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker  * Copyright 2019 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker  *
4*38e8c45fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker  *
8*38e8c45fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker  *
10*38e8c45fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker  * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker  */
16*38e8c45fSAndroid Build Coastguard Worker 
17*38e8c45fSAndroid Build Coastguard Worker #include "VsyncConfiguration.h"
18*38e8c45fSAndroid Build Coastguard Worker 
19*38e8c45fSAndroid Build Coastguard Worker #include <chrono>
20*38e8c45fSAndroid Build Coastguard Worker #include <cinttypes>
21*38e8c45fSAndroid Build Coastguard Worker #include <optional>
22*38e8c45fSAndroid Build Coastguard Worker 
23*38e8c45fSAndroid Build Coastguard Worker #include <cutils/properties.h>
24*38e8c45fSAndroid Build Coastguard Worker #include <log/log.h>
25*38e8c45fSAndroid Build Coastguard Worker 
26*38e8c45fSAndroid Build Coastguard Worker #include "SurfaceFlingerProperties.h"
27*38e8c45fSAndroid Build Coastguard Worker 
28*38e8c45fSAndroid Build Coastguard Worker namespace {
29*38e8c45fSAndroid Build Coastguard Worker 
30*38e8c45fSAndroid Build Coastguard Worker using namespace std::chrono_literals;
31*38e8c45fSAndroid Build Coastguard Worker 
getProperty(const char * name)32*38e8c45fSAndroid Build Coastguard Worker std::optional<nsecs_t> getProperty(const char* name) {
33*38e8c45fSAndroid Build Coastguard Worker     char value[PROPERTY_VALUE_MAX];
34*38e8c45fSAndroid Build Coastguard Worker     property_get(name, value, "-1");
35*38e8c45fSAndroid Build Coastguard Worker     if (const int i = atoi(value); i != -1) return i;
36*38e8c45fSAndroid Build Coastguard Worker     return std::nullopt;
37*38e8c45fSAndroid Build Coastguard Worker }
38*38e8c45fSAndroid Build Coastguard Worker 
39*38e8c45fSAndroid Build Coastguard Worker } // namespace
40*38e8c45fSAndroid Build Coastguard Worker 
41*38e8c45fSAndroid Build Coastguard Worker namespace android::scheduler::impl {
42*38e8c45fSAndroid Build Coastguard Worker 
VsyncConfiguration(Fps currentFps)43*38e8c45fSAndroid Build Coastguard Worker VsyncConfiguration::VsyncConfiguration(Fps currentFps) : mRefreshRateFps(currentFps) {}
44*38e8c45fSAndroid Build Coastguard Worker 
getConfigsForRefreshRate(Fps fps) const45*38e8c45fSAndroid Build Coastguard Worker VsyncConfigSet VsyncConfiguration::getConfigsForRefreshRate(Fps fps) const {
46*38e8c45fSAndroid Build Coastguard Worker     std::lock_guard lock(mLock);
47*38e8c45fSAndroid Build Coastguard Worker     return getConfigsForRefreshRateLocked(fps);
48*38e8c45fSAndroid Build Coastguard Worker }
49*38e8c45fSAndroid Build Coastguard Worker 
getConfigsForRefreshRateLocked(Fps fps) const50*38e8c45fSAndroid Build Coastguard Worker VsyncConfigSet VsyncConfiguration::getConfigsForRefreshRateLocked(Fps fps) const {
51*38e8c45fSAndroid Build Coastguard Worker     if (const auto offsets = mOffsetsCache.get(fps)) {
52*38e8c45fSAndroid Build Coastguard Worker         return offsets->get();
53*38e8c45fSAndroid Build Coastguard Worker     }
54*38e8c45fSAndroid Build Coastguard Worker 
55*38e8c45fSAndroid Build Coastguard Worker     const auto [it, _] = mOffsetsCache.try_emplace(fps, constructOffsets(fps.getPeriodNsecs()));
56*38e8c45fSAndroid Build Coastguard Worker     return it->second;
57*38e8c45fSAndroid Build Coastguard Worker }
58*38e8c45fSAndroid Build Coastguard Worker 
dump(std::string & result) const59*38e8c45fSAndroid Build Coastguard Worker void VsyncConfiguration::dump(std::string& result) const {
60*38e8c45fSAndroid Build Coastguard Worker     const auto [early, earlyGpu, late, hwcMinWorkDuration] = getCurrentConfigs();
61*38e8c45fSAndroid Build Coastguard Worker     using base::StringAppendF;
62*38e8c45fSAndroid Build Coastguard Worker     StringAppendF(&result,
63*38e8c45fSAndroid Build Coastguard Worker                   "           app phase:    %9" PRId64 " ns\t         SF phase:    %9" PRId64
64*38e8c45fSAndroid Build Coastguard Worker                   " ns\n"
65*38e8c45fSAndroid Build Coastguard Worker                   "           app duration: %9lld ns\t         SF duration: %9lld ns\n"
66*38e8c45fSAndroid Build Coastguard Worker                   "     early app phase:    %9" PRId64 " ns\t   early SF phase:    %9" PRId64
67*38e8c45fSAndroid Build Coastguard Worker                   " ns\n"
68*38e8c45fSAndroid Build Coastguard Worker                   "     early app duration: %9lld ns\t   early SF duration: %9lld ns\n"
69*38e8c45fSAndroid Build Coastguard Worker                   "  GL early app phase:    %9" PRId64 " ns\tGL early SF phase:    %9" PRId64
70*38e8c45fSAndroid Build Coastguard Worker                   " ns\n"
71*38e8c45fSAndroid Build Coastguard Worker                   "  GL early app duration: %9lld ns\tGL early SF duration: %9lld ns\n"
72*38e8c45fSAndroid Build Coastguard Worker                   "       HWC min duration: %9lld ns\n",
73*38e8c45fSAndroid Build Coastguard Worker                   late.appOffset, late.sfOffset,
74*38e8c45fSAndroid Build Coastguard Worker 
75*38e8c45fSAndroid Build Coastguard Worker                   late.appWorkDuration.count(), late.sfWorkDuration.count(),
76*38e8c45fSAndroid Build Coastguard Worker 
77*38e8c45fSAndroid Build Coastguard Worker                   early.appOffset, early.sfOffset,
78*38e8c45fSAndroid Build Coastguard Worker 
79*38e8c45fSAndroid Build Coastguard Worker                   early.appWorkDuration.count(), early.sfWorkDuration.count(),
80*38e8c45fSAndroid Build Coastguard Worker 
81*38e8c45fSAndroid Build Coastguard Worker                   earlyGpu.appOffset, earlyGpu.sfOffset,
82*38e8c45fSAndroid Build Coastguard Worker 
83*38e8c45fSAndroid Build Coastguard Worker                   earlyGpu.appWorkDuration.count(), earlyGpu.sfWorkDuration.count(),
84*38e8c45fSAndroid Build Coastguard Worker 
85*38e8c45fSAndroid Build Coastguard Worker                   hwcMinWorkDuration.count());
86*38e8c45fSAndroid Build Coastguard Worker }
87*38e8c45fSAndroid Build Coastguard Worker 
PhaseOffsets(Fps currentRefreshRate)88*38e8c45fSAndroid Build Coastguard Worker PhaseOffsets::PhaseOffsets(Fps currentRefreshRate)
89*38e8c45fSAndroid Build Coastguard Worker       : PhaseOffsets(currentRefreshRate, sysprop::vsync_event_phase_offset_ns(1000000),
90*38e8c45fSAndroid Build Coastguard Worker                      sysprop::vsync_sf_event_phase_offset_ns(1000000),
91*38e8c45fSAndroid Build Coastguard Worker                      getProperty("debug.sf.early_phase_offset_ns"),
92*38e8c45fSAndroid Build Coastguard Worker                      getProperty("debug.sf.early_gl_phase_offset_ns"),
93*38e8c45fSAndroid Build Coastguard Worker                      getProperty("debug.sf.early_app_phase_offset_ns"),
94*38e8c45fSAndroid Build Coastguard Worker                      getProperty("debug.sf.early_gl_app_phase_offset_ns"),
95*38e8c45fSAndroid Build Coastguard Worker                      getProperty("debug.sf.high_fps_late_app_phase_offset_ns").value_or(2000000),
96*38e8c45fSAndroid Build Coastguard Worker                      getProperty("debug.sf.high_fps_late_sf_phase_offset_ns").value_or(1000000),
97*38e8c45fSAndroid Build Coastguard Worker                      getProperty("debug.sf.high_fps_early_phase_offset_ns"),
98*38e8c45fSAndroid Build Coastguard Worker                      getProperty("debug.sf.high_fps_early_gl_phase_offset_ns"),
99*38e8c45fSAndroid Build Coastguard Worker                      getProperty("debug.sf.high_fps_early_app_phase_offset_ns"),
100*38e8c45fSAndroid Build Coastguard Worker                      getProperty("debug.sf.high_fps_early_gl_app_phase_offset_ns"),
101*38e8c45fSAndroid Build Coastguard Worker                      // Below defines the threshold when an offset is considered to be negative,
102*38e8c45fSAndroid Build Coastguard Worker                      // i.e. targeting for the N+2 vsync instead of N+1. This means that: For offset
103*38e8c45fSAndroid Build Coastguard Worker                      // < threshold, SF wake up (vsync_duration - offset) before HW vsync. For
104*38e8c45fSAndroid Build Coastguard Worker                      // offset >= threshold, SF wake up (2 * vsync_duration - offset) before HW
105*38e8c45fSAndroid Build Coastguard Worker                      // vsync.
106*38e8c45fSAndroid Build Coastguard Worker                      getProperty("debug.sf.phase_offset_threshold_for_next_vsync_ns")
107*38e8c45fSAndroid Build Coastguard Worker                              .value_or(std::numeric_limits<nsecs_t>::max()),
108*38e8c45fSAndroid Build Coastguard Worker                      getProperty("debug.sf.hwc.min.duration").value_or(0)) {}
109*38e8c45fSAndroid Build Coastguard Worker 
PhaseOffsets(Fps currentFps,nsecs_t vsyncPhaseOffsetNs,nsecs_t sfVSyncPhaseOffsetNs,std::optional<nsecs_t> earlySfOffsetNs,std::optional<nsecs_t> earlyGpuSfOffsetNs,std::optional<nsecs_t> earlyAppOffsetNs,std::optional<nsecs_t> earlyGpuAppOffsetNs,nsecs_t highFpsVsyncPhaseOffsetNs,nsecs_t highFpsSfVSyncPhaseOffsetNs,std::optional<nsecs_t> highFpsEarlySfOffsetNs,std::optional<nsecs_t> highFpsEarlyGpuSfOffsetNs,std::optional<nsecs_t> highFpsEarlyAppOffsetNs,std::optional<nsecs_t> highFpsEarlyGpuAppOffsetNs,nsecs_t thresholdForNextVsync,nsecs_t hwcMinWorkDuration)110*38e8c45fSAndroid Build Coastguard Worker PhaseOffsets::PhaseOffsets(Fps currentFps, nsecs_t vsyncPhaseOffsetNs, nsecs_t sfVSyncPhaseOffsetNs,
111*38e8c45fSAndroid Build Coastguard Worker                            std::optional<nsecs_t> earlySfOffsetNs,
112*38e8c45fSAndroid Build Coastguard Worker                            std::optional<nsecs_t> earlyGpuSfOffsetNs,
113*38e8c45fSAndroid Build Coastguard Worker                            std::optional<nsecs_t> earlyAppOffsetNs,
114*38e8c45fSAndroid Build Coastguard Worker                            std::optional<nsecs_t> earlyGpuAppOffsetNs,
115*38e8c45fSAndroid Build Coastguard Worker                            nsecs_t highFpsVsyncPhaseOffsetNs, nsecs_t highFpsSfVSyncPhaseOffsetNs,
116*38e8c45fSAndroid Build Coastguard Worker                            std::optional<nsecs_t> highFpsEarlySfOffsetNs,
117*38e8c45fSAndroid Build Coastguard Worker                            std::optional<nsecs_t> highFpsEarlyGpuSfOffsetNs,
118*38e8c45fSAndroid Build Coastguard Worker                            std::optional<nsecs_t> highFpsEarlyAppOffsetNs,
119*38e8c45fSAndroid Build Coastguard Worker                            std::optional<nsecs_t> highFpsEarlyGpuAppOffsetNs,
120*38e8c45fSAndroid Build Coastguard Worker                            nsecs_t thresholdForNextVsync, nsecs_t hwcMinWorkDuration)
121*38e8c45fSAndroid Build Coastguard Worker       : VsyncConfiguration(currentFps),
122*38e8c45fSAndroid Build Coastguard Worker         mVSyncPhaseOffsetNs(vsyncPhaseOffsetNs),
123*38e8c45fSAndroid Build Coastguard Worker         mSfVSyncPhaseOffsetNs(sfVSyncPhaseOffsetNs),
124*38e8c45fSAndroid Build Coastguard Worker         mEarlySfOffsetNs(earlySfOffsetNs),
125*38e8c45fSAndroid Build Coastguard Worker         mEarlyGpuSfOffsetNs(earlyGpuSfOffsetNs),
126*38e8c45fSAndroid Build Coastguard Worker         mEarlyAppOffsetNs(earlyAppOffsetNs),
127*38e8c45fSAndroid Build Coastguard Worker         mEarlyGpuAppOffsetNs(earlyGpuAppOffsetNs),
128*38e8c45fSAndroid Build Coastguard Worker         mHighFpsVSyncPhaseOffsetNs(highFpsVsyncPhaseOffsetNs),
129*38e8c45fSAndroid Build Coastguard Worker         mHighFpsSfVSyncPhaseOffsetNs(highFpsSfVSyncPhaseOffsetNs),
130*38e8c45fSAndroid Build Coastguard Worker         mHighFpsEarlySfOffsetNs(highFpsEarlySfOffsetNs),
131*38e8c45fSAndroid Build Coastguard Worker         mHighFpsEarlyGpuSfOffsetNs(highFpsEarlyGpuSfOffsetNs),
132*38e8c45fSAndroid Build Coastguard Worker         mHighFpsEarlyAppOffsetNs(highFpsEarlyAppOffsetNs),
133*38e8c45fSAndroid Build Coastguard Worker         mHighFpsEarlyGpuAppOffsetNs(highFpsEarlyGpuAppOffsetNs),
134*38e8c45fSAndroid Build Coastguard Worker         mThresholdForNextVsync(thresholdForNextVsync),
135*38e8c45fSAndroid Build Coastguard Worker         mHwcMinWorkDuration(hwcMinWorkDuration) {}
136*38e8c45fSAndroid Build Coastguard Worker 
constructOffsets(nsecs_t vsyncDuration) const137*38e8c45fSAndroid Build Coastguard Worker VsyncConfigSet PhaseOffsets::constructOffsets(nsecs_t vsyncDuration) const {
138*38e8c45fSAndroid Build Coastguard Worker     if (vsyncDuration < std::chrono::nanoseconds(15ms).count()) {
139*38e8c45fSAndroid Build Coastguard Worker         return getHighFpsOffsets(vsyncDuration);
140*38e8c45fSAndroid Build Coastguard Worker     } else {
141*38e8c45fSAndroid Build Coastguard Worker         return getDefaultOffsets(vsyncDuration);
142*38e8c45fSAndroid Build Coastguard Worker     }
143*38e8c45fSAndroid Build Coastguard Worker }
144*38e8c45fSAndroid Build Coastguard Worker 
145*38e8c45fSAndroid Build Coastguard Worker namespace {
sfOffsetToDuration(nsecs_t sfOffset,nsecs_t vsyncDuration)146*38e8c45fSAndroid Build Coastguard Worker std::chrono::nanoseconds sfOffsetToDuration(nsecs_t sfOffset, nsecs_t vsyncDuration) {
147*38e8c45fSAndroid Build Coastguard Worker     return std::chrono::nanoseconds(vsyncDuration - sfOffset);
148*38e8c45fSAndroid Build Coastguard Worker }
149*38e8c45fSAndroid Build Coastguard Worker 
appOffsetToDuration(nsecs_t appOffset,nsecs_t sfOffset,nsecs_t vsyncDuration)150*38e8c45fSAndroid Build Coastguard Worker std::chrono::nanoseconds appOffsetToDuration(nsecs_t appOffset, nsecs_t sfOffset,
151*38e8c45fSAndroid Build Coastguard Worker                                              nsecs_t vsyncDuration) {
152*38e8c45fSAndroid Build Coastguard Worker     auto duration = vsyncDuration + (sfOffset - appOffset);
153*38e8c45fSAndroid Build Coastguard Worker     if (duration < vsyncDuration) {
154*38e8c45fSAndroid Build Coastguard Worker         duration += vsyncDuration;
155*38e8c45fSAndroid Build Coastguard Worker     }
156*38e8c45fSAndroid Build Coastguard Worker 
157*38e8c45fSAndroid Build Coastguard Worker     return std::chrono::nanoseconds(duration);
158*38e8c45fSAndroid Build Coastguard Worker }
159*38e8c45fSAndroid Build Coastguard Worker } // namespace
160*38e8c45fSAndroid Build Coastguard Worker 
getDefaultOffsets(nsecs_t vsyncDuration) const161*38e8c45fSAndroid Build Coastguard Worker VsyncConfigSet PhaseOffsets::getDefaultOffsets(nsecs_t vsyncDuration) const {
162*38e8c45fSAndroid Build Coastguard Worker     const auto earlySfOffset =
163*38e8c45fSAndroid Build Coastguard Worker             mEarlySfOffsetNs.value_or(mSfVSyncPhaseOffsetNs) < mThresholdForNextVsync
164*38e8c45fSAndroid Build Coastguard Worker 
165*38e8c45fSAndroid Build Coastguard Worker             ? mEarlySfOffsetNs.value_or(mSfVSyncPhaseOffsetNs)
166*38e8c45fSAndroid Build Coastguard Worker             : mEarlySfOffsetNs.value_or(mSfVSyncPhaseOffsetNs) - vsyncDuration;
167*38e8c45fSAndroid Build Coastguard Worker     const auto earlyAppOffset = mEarlyAppOffsetNs.value_or(mVSyncPhaseOffsetNs);
168*38e8c45fSAndroid Build Coastguard Worker     const auto earlyGpuSfOffset =
169*38e8c45fSAndroid Build Coastguard Worker             mEarlyGpuSfOffsetNs.value_or(mSfVSyncPhaseOffsetNs) < mThresholdForNextVsync
170*38e8c45fSAndroid Build Coastguard Worker 
171*38e8c45fSAndroid Build Coastguard Worker             ? mEarlyGpuSfOffsetNs.value_or(mSfVSyncPhaseOffsetNs)
172*38e8c45fSAndroid Build Coastguard Worker             : mEarlyGpuSfOffsetNs.value_or(mSfVSyncPhaseOffsetNs) - vsyncDuration;
173*38e8c45fSAndroid Build Coastguard Worker     const auto earlyGpuAppOffset = mEarlyGpuAppOffsetNs.value_or(mVSyncPhaseOffsetNs);
174*38e8c45fSAndroid Build Coastguard Worker     const auto lateSfOffset = mSfVSyncPhaseOffsetNs < mThresholdForNextVsync
175*38e8c45fSAndroid Build Coastguard Worker             ? mSfVSyncPhaseOffsetNs
176*38e8c45fSAndroid Build Coastguard Worker             : mSfVSyncPhaseOffsetNs - vsyncDuration;
177*38e8c45fSAndroid Build Coastguard Worker     const auto lateAppOffset = mVSyncPhaseOffsetNs;
178*38e8c45fSAndroid Build Coastguard Worker 
179*38e8c45fSAndroid Build Coastguard Worker     return {
180*38e8c45fSAndroid Build Coastguard Worker             .early = {.sfOffset = earlySfOffset,
181*38e8c45fSAndroid Build Coastguard Worker                       .appOffset = earlyAppOffset,
182*38e8c45fSAndroid Build Coastguard Worker                       .sfWorkDuration = sfOffsetToDuration(earlySfOffset, vsyncDuration),
183*38e8c45fSAndroid Build Coastguard Worker                       .appWorkDuration =
184*38e8c45fSAndroid Build Coastguard Worker                               appOffsetToDuration(earlyAppOffset, earlySfOffset, vsyncDuration)},
185*38e8c45fSAndroid Build Coastguard Worker             .earlyGpu = {.sfOffset = earlyGpuSfOffset,
186*38e8c45fSAndroid Build Coastguard Worker                          .appOffset = earlyGpuAppOffset,
187*38e8c45fSAndroid Build Coastguard Worker                          .sfWorkDuration = sfOffsetToDuration(earlyGpuSfOffset, vsyncDuration),
188*38e8c45fSAndroid Build Coastguard Worker                          .appWorkDuration = appOffsetToDuration(earlyGpuAppOffset, earlyGpuSfOffset,
189*38e8c45fSAndroid Build Coastguard Worker                                                                 vsyncDuration)},
190*38e8c45fSAndroid Build Coastguard Worker             .late = {.sfOffset = lateSfOffset,
191*38e8c45fSAndroid Build Coastguard Worker                      .appOffset = lateAppOffset,
192*38e8c45fSAndroid Build Coastguard Worker                      .sfWorkDuration = sfOffsetToDuration(lateSfOffset, vsyncDuration),
193*38e8c45fSAndroid Build Coastguard Worker                      .appWorkDuration =
194*38e8c45fSAndroid Build Coastguard Worker                              appOffsetToDuration(lateAppOffset, lateSfOffset, vsyncDuration)},
195*38e8c45fSAndroid Build Coastguard Worker             .hwcMinWorkDuration = std::chrono::nanoseconds(mHwcMinWorkDuration),
196*38e8c45fSAndroid Build Coastguard Worker     };
197*38e8c45fSAndroid Build Coastguard Worker }
198*38e8c45fSAndroid Build Coastguard Worker 
getHighFpsOffsets(nsecs_t vsyncDuration) const199*38e8c45fSAndroid Build Coastguard Worker VsyncConfigSet PhaseOffsets::getHighFpsOffsets(nsecs_t vsyncDuration) const {
200*38e8c45fSAndroid Build Coastguard Worker     const auto earlySfOffset =
201*38e8c45fSAndroid Build Coastguard Worker             mHighFpsEarlySfOffsetNs.value_or(mHighFpsSfVSyncPhaseOffsetNs) < mThresholdForNextVsync
202*38e8c45fSAndroid Build Coastguard Worker             ? mHighFpsEarlySfOffsetNs.value_or(mHighFpsSfVSyncPhaseOffsetNs)
203*38e8c45fSAndroid Build Coastguard Worker             : mHighFpsEarlySfOffsetNs.value_or(mHighFpsSfVSyncPhaseOffsetNs) - vsyncDuration;
204*38e8c45fSAndroid Build Coastguard Worker     const auto earlyAppOffset = mHighFpsEarlyAppOffsetNs.value_or(mHighFpsVSyncPhaseOffsetNs);
205*38e8c45fSAndroid Build Coastguard Worker     const auto earlyGpuSfOffset = mHighFpsEarlyGpuSfOffsetNs.value_or(
206*38e8c45fSAndroid Build Coastguard Worker                                           mHighFpsSfVSyncPhaseOffsetNs) < mThresholdForNextVsync
207*38e8c45fSAndroid Build Coastguard Worker 
208*38e8c45fSAndroid Build Coastguard Worker             ? mHighFpsEarlyGpuSfOffsetNs.value_or(mHighFpsSfVSyncPhaseOffsetNs)
209*38e8c45fSAndroid Build Coastguard Worker             : mHighFpsEarlyGpuSfOffsetNs.value_or(mHighFpsSfVSyncPhaseOffsetNs) - vsyncDuration;
210*38e8c45fSAndroid Build Coastguard Worker     const auto earlyGpuAppOffset = mHighFpsEarlyGpuAppOffsetNs.value_or(mHighFpsVSyncPhaseOffsetNs);
211*38e8c45fSAndroid Build Coastguard Worker     const auto lateSfOffset = mHighFpsSfVSyncPhaseOffsetNs < mThresholdForNextVsync
212*38e8c45fSAndroid Build Coastguard Worker             ? mHighFpsSfVSyncPhaseOffsetNs
213*38e8c45fSAndroid Build Coastguard Worker             : mHighFpsSfVSyncPhaseOffsetNs - vsyncDuration;
214*38e8c45fSAndroid Build Coastguard Worker     const auto lateAppOffset = mHighFpsVSyncPhaseOffsetNs;
215*38e8c45fSAndroid Build Coastguard Worker 
216*38e8c45fSAndroid Build Coastguard Worker     return {
217*38e8c45fSAndroid Build Coastguard Worker             .early =
218*38e8c45fSAndroid Build Coastguard Worker                     {
219*38e8c45fSAndroid Build Coastguard Worker                             .sfOffset = earlySfOffset,
220*38e8c45fSAndroid Build Coastguard Worker                             .appOffset = earlyAppOffset,
221*38e8c45fSAndroid Build Coastguard Worker                             .sfWorkDuration = sfOffsetToDuration(earlySfOffset, vsyncDuration),
222*38e8c45fSAndroid Build Coastguard Worker                             .appWorkDuration = appOffsetToDuration(earlyAppOffset, earlySfOffset,
223*38e8c45fSAndroid Build Coastguard Worker                                                                    vsyncDuration),
224*38e8c45fSAndroid Build Coastguard Worker                     },
225*38e8c45fSAndroid Build Coastguard Worker             .earlyGpu =
226*38e8c45fSAndroid Build Coastguard Worker                     {
227*38e8c45fSAndroid Build Coastguard Worker                             .sfOffset = earlyGpuSfOffset,
228*38e8c45fSAndroid Build Coastguard Worker                             .appOffset = earlyGpuAppOffset,
229*38e8c45fSAndroid Build Coastguard Worker                             .sfWorkDuration = sfOffsetToDuration(earlyGpuSfOffset, vsyncDuration),
230*38e8c45fSAndroid Build Coastguard Worker                             .appWorkDuration = appOffsetToDuration(earlyGpuAppOffset,
231*38e8c45fSAndroid Build Coastguard Worker                                                                    earlyGpuSfOffset, vsyncDuration),
232*38e8c45fSAndroid Build Coastguard Worker                     },
233*38e8c45fSAndroid Build Coastguard Worker             .late =
234*38e8c45fSAndroid Build Coastguard Worker                     {
235*38e8c45fSAndroid Build Coastguard Worker                             .sfOffset = lateSfOffset,
236*38e8c45fSAndroid Build Coastguard Worker                             .appOffset = lateAppOffset,
237*38e8c45fSAndroid Build Coastguard Worker                             .sfWorkDuration = sfOffsetToDuration(lateSfOffset, vsyncDuration),
238*38e8c45fSAndroid Build Coastguard Worker                             .appWorkDuration =
239*38e8c45fSAndroid Build Coastguard Worker                                     appOffsetToDuration(lateAppOffset, lateSfOffset, vsyncDuration),
240*38e8c45fSAndroid Build Coastguard Worker                     },
241*38e8c45fSAndroid Build Coastguard Worker             .hwcMinWorkDuration = std::chrono::nanoseconds(mHwcMinWorkDuration),
242*38e8c45fSAndroid Build Coastguard Worker     };
243*38e8c45fSAndroid Build Coastguard Worker }
244*38e8c45fSAndroid Build Coastguard Worker 
validateSysprops()245*38e8c45fSAndroid Build Coastguard Worker static void validateSysprops() {
246*38e8c45fSAndroid Build Coastguard Worker     const auto validatePropertyBool = [](const char* prop) {
247*38e8c45fSAndroid Build Coastguard Worker         LOG_ALWAYS_FATAL_IF(!property_get_bool(prop, false), "%s is false", prop);
248*38e8c45fSAndroid Build Coastguard Worker     };
249*38e8c45fSAndroid Build Coastguard Worker 
250*38e8c45fSAndroid Build Coastguard Worker     validatePropertyBool("debug.sf.use_phase_offsets_as_durations");
251*38e8c45fSAndroid Build Coastguard Worker 
252*38e8c45fSAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(sysprop::vsync_event_phase_offset_ns(-1) != -1,
253*38e8c45fSAndroid Build Coastguard Worker                         "ro.surface_flinger.vsync_event_phase_offset_ns is set but expecting "
254*38e8c45fSAndroid Build Coastguard Worker                         "duration");
255*38e8c45fSAndroid Build Coastguard Worker 
256*38e8c45fSAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(sysprop::vsync_sf_event_phase_offset_ns(-1) != -1,
257*38e8c45fSAndroid Build Coastguard Worker                         "ro.surface_flinger.vsync_sf_event_phase_offset_ns is set but expecting "
258*38e8c45fSAndroid Build Coastguard Worker                         "duration");
259*38e8c45fSAndroid Build Coastguard Worker 
260*38e8c45fSAndroid Build Coastguard Worker     const auto validateProperty = [](const char* prop) {
261*38e8c45fSAndroid Build Coastguard Worker         LOG_ALWAYS_FATAL_IF(getProperty(prop).has_value(),
262*38e8c45fSAndroid Build Coastguard Worker                             "%s is set to %" PRId64 " but expecting duration", prop,
263*38e8c45fSAndroid Build Coastguard Worker                             getProperty(prop).value_or(-1));
264*38e8c45fSAndroid Build Coastguard Worker     };
265*38e8c45fSAndroid Build Coastguard Worker 
266*38e8c45fSAndroid Build Coastguard Worker     validateProperty("debug.sf.early_phase_offset_ns");
267*38e8c45fSAndroid Build Coastguard Worker     validateProperty("debug.sf.early_gl_phase_offset_ns");
268*38e8c45fSAndroid Build Coastguard Worker     validateProperty("debug.sf.early_app_phase_offset_ns");
269*38e8c45fSAndroid Build Coastguard Worker     validateProperty("debug.sf.early_gl_app_phase_offset_ns");
270*38e8c45fSAndroid Build Coastguard Worker     validateProperty("debug.sf.high_fps_late_app_phase_offset_ns");
271*38e8c45fSAndroid Build Coastguard Worker     validateProperty("debug.sf.high_fps_late_sf_phase_offset_ns");
272*38e8c45fSAndroid Build Coastguard Worker     validateProperty("debug.sf.high_fps_early_phase_offset_ns");
273*38e8c45fSAndroid Build Coastguard Worker     validateProperty("debug.sf.high_fps_early_gl_phase_offset_ns");
274*38e8c45fSAndroid Build Coastguard Worker     validateProperty("debug.sf.high_fps_early_app_phase_offset_ns");
275*38e8c45fSAndroid Build Coastguard Worker     validateProperty("debug.sf.high_fps_early_gl_app_phase_offset_ns");
276*38e8c45fSAndroid Build Coastguard Worker }
277*38e8c45fSAndroid Build Coastguard Worker 
278*38e8c45fSAndroid Build Coastguard Worker namespace {
sfDurationToOffset(std::chrono::nanoseconds sfDuration,nsecs_t vsyncDuration)279*38e8c45fSAndroid Build Coastguard Worker nsecs_t sfDurationToOffset(std::chrono::nanoseconds sfDuration, nsecs_t vsyncDuration) {
280*38e8c45fSAndroid Build Coastguard Worker     return vsyncDuration - sfDuration.count() % vsyncDuration;
281*38e8c45fSAndroid Build Coastguard Worker }
282*38e8c45fSAndroid Build Coastguard Worker 
appDurationToOffset(std::chrono::nanoseconds appDuration,std::chrono::nanoseconds sfDuration,nsecs_t vsyncDuration)283*38e8c45fSAndroid Build Coastguard Worker nsecs_t appDurationToOffset(std::chrono::nanoseconds appDuration,
284*38e8c45fSAndroid Build Coastguard Worker                             std::chrono::nanoseconds sfDuration, nsecs_t vsyncDuration) {
285*38e8c45fSAndroid Build Coastguard Worker     return vsyncDuration - (appDuration + sfDuration).count() % vsyncDuration;
286*38e8c45fSAndroid Build Coastguard Worker }
287*38e8c45fSAndroid Build Coastguard Worker } // namespace
288*38e8c45fSAndroid Build Coastguard Worker 
constructOffsets(nsecs_t vsyncDuration) const289*38e8c45fSAndroid Build Coastguard Worker VsyncConfigSet WorkDuration::constructOffsets(nsecs_t vsyncDuration) const {
290*38e8c45fSAndroid Build Coastguard Worker     const auto sfDurationFixup = [vsyncDuration](nsecs_t duration) {
291*38e8c45fSAndroid Build Coastguard Worker         return duration == -1 ? std::chrono::nanoseconds(vsyncDuration) - 1ms
292*38e8c45fSAndroid Build Coastguard Worker                               : std::chrono::nanoseconds(duration);
293*38e8c45fSAndroid Build Coastguard Worker     };
294*38e8c45fSAndroid Build Coastguard Worker 
295*38e8c45fSAndroid Build Coastguard Worker     const auto appDurationFixup = [vsyncDuration](nsecs_t duration) {
296*38e8c45fSAndroid Build Coastguard Worker         return duration == -1 ? std::chrono::nanoseconds(vsyncDuration)
297*38e8c45fSAndroid Build Coastguard Worker                               : std::chrono::nanoseconds(duration);
298*38e8c45fSAndroid Build Coastguard Worker     };
299*38e8c45fSAndroid Build Coastguard Worker 
300*38e8c45fSAndroid Build Coastguard Worker     const auto sfEarlyDuration = sfDurationFixup(mSfEarlyDuration);
301*38e8c45fSAndroid Build Coastguard Worker     const auto appEarlyDuration = appDurationFixup(mAppEarlyDuration);
302*38e8c45fSAndroid Build Coastguard Worker     const auto sfEarlyGpuDuration = sfDurationFixup(mSfEarlyGpuDuration);
303*38e8c45fSAndroid Build Coastguard Worker     const auto appEarlyGpuDuration = appDurationFixup(mAppEarlyGpuDuration);
304*38e8c45fSAndroid Build Coastguard Worker     const auto sfDuration = sfDurationFixup(mSfDuration);
305*38e8c45fSAndroid Build Coastguard Worker     const auto appDuration = appDurationFixup(mAppDuration);
306*38e8c45fSAndroid Build Coastguard Worker 
307*38e8c45fSAndroid Build Coastguard Worker     return {
308*38e8c45fSAndroid Build Coastguard Worker             .early =
309*38e8c45fSAndroid Build Coastguard Worker                     {
310*38e8c45fSAndroid Build Coastguard Worker 
311*38e8c45fSAndroid Build Coastguard Worker                             .sfOffset = sfEarlyDuration.count() < vsyncDuration
312*38e8c45fSAndroid Build Coastguard Worker                                     ? sfDurationToOffset(sfEarlyDuration, vsyncDuration)
313*38e8c45fSAndroid Build Coastguard Worker                                     : sfDurationToOffset(sfEarlyDuration, vsyncDuration) -
314*38e8c45fSAndroid Build Coastguard Worker                                             vsyncDuration,
315*38e8c45fSAndroid Build Coastguard Worker 
316*38e8c45fSAndroid Build Coastguard Worker                             .appOffset = appDurationToOffset(appEarlyDuration, sfEarlyDuration,
317*38e8c45fSAndroid Build Coastguard Worker                                                              vsyncDuration),
318*38e8c45fSAndroid Build Coastguard Worker 
319*38e8c45fSAndroid Build Coastguard Worker                             .sfWorkDuration = sfEarlyDuration,
320*38e8c45fSAndroid Build Coastguard Worker                             .appWorkDuration = appEarlyDuration,
321*38e8c45fSAndroid Build Coastguard Worker                     },
322*38e8c45fSAndroid Build Coastguard Worker             .earlyGpu =
323*38e8c45fSAndroid Build Coastguard Worker                     {
324*38e8c45fSAndroid Build Coastguard Worker 
325*38e8c45fSAndroid Build Coastguard Worker                             .sfOffset = sfEarlyGpuDuration.count() < vsyncDuration
326*38e8c45fSAndroid Build Coastguard Worker 
327*38e8c45fSAndroid Build Coastguard Worker                                     ? sfDurationToOffset(sfEarlyGpuDuration, vsyncDuration)
328*38e8c45fSAndroid Build Coastguard Worker                                     : sfDurationToOffset(sfEarlyGpuDuration, vsyncDuration) -
329*38e8c45fSAndroid Build Coastguard Worker                                             vsyncDuration,
330*38e8c45fSAndroid Build Coastguard Worker 
331*38e8c45fSAndroid Build Coastguard Worker                             .appOffset = appDurationToOffset(appEarlyGpuDuration,
332*38e8c45fSAndroid Build Coastguard Worker                                                              sfEarlyGpuDuration, vsyncDuration),
333*38e8c45fSAndroid Build Coastguard Worker                             .sfWorkDuration = sfEarlyGpuDuration,
334*38e8c45fSAndroid Build Coastguard Worker                             .appWorkDuration = appEarlyGpuDuration,
335*38e8c45fSAndroid Build Coastguard Worker                     },
336*38e8c45fSAndroid Build Coastguard Worker             .late =
337*38e8c45fSAndroid Build Coastguard Worker                     {
338*38e8c45fSAndroid Build Coastguard Worker 
339*38e8c45fSAndroid Build Coastguard Worker                             .sfOffset = sfDuration.count() < vsyncDuration
340*38e8c45fSAndroid Build Coastguard Worker 
341*38e8c45fSAndroid Build Coastguard Worker                                     ? sfDurationToOffset(sfDuration, vsyncDuration)
342*38e8c45fSAndroid Build Coastguard Worker                                     : sfDurationToOffset(sfDuration, vsyncDuration) - vsyncDuration,
343*38e8c45fSAndroid Build Coastguard Worker 
344*38e8c45fSAndroid Build Coastguard Worker                             .appOffset =
345*38e8c45fSAndroid Build Coastguard Worker                                     appDurationToOffset(appDuration, sfDuration, vsyncDuration),
346*38e8c45fSAndroid Build Coastguard Worker 
347*38e8c45fSAndroid Build Coastguard Worker                             .sfWorkDuration = sfDuration,
348*38e8c45fSAndroid Build Coastguard Worker                             .appWorkDuration = appDuration,
349*38e8c45fSAndroid Build Coastguard Worker                     },
350*38e8c45fSAndroid Build Coastguard Worker             .hwcMinWorkDuration = std::chrono::nanoseconds(mHwcMinWorkDuration),
351*38e8c45fSAndroid Build Coastguard Worker     };
352*38e8c45fSAndroid Build Coastguard Worker }
353*38e8c45fSAndroid Build Coastguard Worker 
WorkDuration(Fps currentRefreshRate)354*38e8c45fSAndroid Build Coastguard Worker WorkDuration::WorkDuration(Fps currentRefreshRate)
355*38e8c45fSAndroid Build Coastguard Worker       : WorkDuration(currentRefreshRate, getProperty("debug.sf.late.sf.duration").value_or(-1),
356*38e8c45fSAndroid Build Coastguard Worker                      getProperty("debug.sf.late.app.duration").value_or(-1),
357*38e8c45fSAndroid Build Coastguard Worker                      getProperty("debug.sf.early.sf.duration").value_or(mSfDuration),
358*38e8c45fSAndroid Build Coastguard Worker                      getProperty("debug.sf.early.app.duration").value_or(mAppDuration),
359*38e8c45fSAndroid Build Coastguard Worker                      getProperty("debug.sf.earlyGl.sf.duration").value_or(mSfDuration),
360*38e8c45fSAndroid Build Coastguard Worker                      getProperty("debug.sf.earlyGl.app.duration").value_or(mAppDuration),
361*38e8c45fSAndroid Build Coastguard Worker                      getProperty("debug.sf.hwc.min.duration").value_or(0)) {
362*38e8c45fSAndroid Build Coastguard Worker     validateSysprops();
363*38e8c45fSAndroid Build Coastguard Worker }
364*38e8c45fSAndroid Build Coastguard Worker 
WorkDuration(Fps currentRefreshRate,nsecs_t sfDuration,nsecs_t appDuration,nsecs_t sfEarlyDuration,nsecs_t appEarlyDuration,nsecs_t sfEarlyGpuDuration,nsecs_t appEarlyGpuDuration,nsecs_t hwcMinWorkDuration)365*38e8c45fSAndroid Build Coastguard Worker WorkDuration::WorkDuration(Fps currentRefreshRate, nsecs_t sfDuration, nsecs_t appDuration,
366*38e8c45fSAndroid Build Coastguard Worker                            nsecs_t sfEarlyDuration, nsecs_t appEarlyDuration,
367*38e8c45fSAndroid Build Coastguard Worker                            nsecs_t sfEarlyGpuDuration, nsecs_t appEarlyGpuDuration,
368*38e8c45fSAndroid Build Coastguard Worker                            nsecs_t hwcMinWorkDuration)
369*38e8c45fSAndroid Build Coastguard Worker       : VsyncConfiguration(currentRefreshRate),
370*38e8c45fSAndroid Build Coastguard Worker         mSfDuration(sfDuration),
371*38e8c45fSAndroid Build Coastguard Worker         mAppDuration(appDuration),
372*38e8c45fSAndroid Build Coastguard Worker         mSfEarlyDuration(sfEarlyDuration),
373*38e8c45fSAndroid Build Coastguard Worker         mAppEarlyDuration(appEarlyDuration),
374*38e8c45fSAndroid Build Coastguard Worker         mSfEarlyGpuDuration(sfEarlyGpuDuration),
375*38e8c45fSAndroid Build Coastguard Worker         mAppEarlyGpuDuration(appEarlyGpuDuration),
376*38e8c45fSAndroid Build Coastguard Worker         mHwcMinWorkDuration(hwcMinWorkDuration) {}
377*38e8c45fSAndroid Build Coastguard Worker 
378*38e8c45fSAndroid Build Coastguard Worker } // namespace android::scheduler::impl
379