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 #include "PhaseOffsets.h"
18 
19 #include <cutils/properties.h>
20 
21 #include "SurfaceFlingerProperties.h"
22 
23 namespace android {
24 using namespace android::sysprop;
25 
26 namespace scheduler {
27 
28 PhaseOffsets::~PhaseOffsets() = default;
29 
30 namespace impl {
PhaseOffsets()31 PhaseOffsets::PhaseOffsets() {
32     int64_t vsyncPhaseOffsetNs = vsync_event_phase_offset_ns(1000000);
33 
34     int64_t sfVsyncPhaseOffsetNs = vsync_sf_event_phase_offset_ns(1000000);
35 
36     char value[PROPERTY_VALUE_MAX];
37     property_get("debug.sf.early_phase_offset_ns", value, "-1");
38     const int earlySfOffsetNs = atoi(value);
39 
40     property_get("debug.sf.early_gl_phase_offset_ns", value, "-1");
41     const int earlyGlSfOffsetNs = atoi(value);
42 
43     property_get("debug.sf.early_app_phase_offset_ns", value, "-1");
44     const int earlyAppOffsetNs = atoi(value);
45 
46     property_get("debug.sf.early_gl_app_phase_offset_ns", value, "-1");
47     const int earlyGlAppOffsetNs = atoi(value);
48 
49     property_get("debug.sf.high_fps_early_phase_offset_ns", value, "-1");
50     const int highFpsEarlySfOffsetNs = atoi(value);
51 
52     property_get("debug.sf.high_fps_early_gl_phase_offset_ns", value, "-1");
53     const int highFpsEarlyGlSfOffsetNs = atoi(value);
54 
55     property_get("debug.sf.high_fps_early_app_phase_offset_ns", value, "-1");
56     const int highFpsEarlyAppOffsetNs = atoi(value);
57 
58     property_get("debug.sf.high_fps_early_gl_app_phase_offset_ns", value, "-1");
59     const int highFpsEarlyGlAppOffsetNs = atoi(value);
60 
61     // TODO(b/122905996): Define these in device.mk.
62     property_get("debug.sf.high_fps_late_app_phase_offset_ns", value, "2000000");
63     const int highFpsLateAppOffsetNs = atoi(value);
64 
65     property_get("debug.sf.high_fps_late_sf_phase_offset_ns", value, "1000000");
66     const int highFpsLateSfOffsetNs = atoi(value);
67 
68     // Below defines the threshold when an offset is considered to be negative, i.e. targeting
69     // for the N+2 vsync instead of N+1. This means that:
70     // For offset < threshold, SF wake up (vsync_duration - offset) before HW vsync.
71     // For offset >= threshold, SF wake up (2 * vsync_duration - offset) before HW vsync.
72     property_get("debug.sf.phase_offset_threshold_for_next_vsync_ns", value, "-1");
73     const int phaseOffsetThresholdForNextVsyncNs = atoi(value);
74 
75     mDefaultRefreshRateOffsets.early = {earlySfOffsetNs != -1 ? earlySfOffsetNs
76                                                               : sfVsyncPhaseOffsetNs,
77                                         earlyAppOffsetNs != -1 ? earlyAppOffsetNs
78                                                                : vsyncPhaseOffsetNs};
79     mDefaultRefreshRateOffsets.earlyGl = {earlyGlSfOffsetNs != -1 ? earlyGlSfOffsetNs
80                                                                   : sfVsyncPhaseOffsetNs,
81                                           earlyGlAppOffsetNs != -1 ? earlyGlAppOffsetNs
82                                                                    : vsyncPhaseOffsetNs};
83     mDefaultRefreshRateOffsets.late = {sfVsyncPhaseOffsetNs, vsyncPhaseOffsetNs};
84 
85     mHighRefreshRateOffsets.early = {highFpsEarlySfOffsetNs != -1 ? highFpsEarlySfOffsetNs
86                                                                   : highFpsLateSfOffsetNs,
87                                      highFpsEarlyAppOffsetNs != -1 ? highFpsEarlyAppOffsetNs
88                                                                    : highFpsLateAppOffsetNs};
89     mHighRefreshRateOffsets.earlyGl = {highFpsEarlyGlSfOffsetNs != -1 ? highFpsEarlyGlSfOffsetNs
90                                                                       : highFpsLateSfOffsetNs,
91                                        highFpsEarlyGlAppOffsetNs != -1 ? highFpsEarlyGlAppOffsetNs
92                                                                        : highFpsLateAppOffsetNs};
93     mHighRefreshRateOffsets.late = {highFpsLateSfOffsetNs, highFpsLateAppOffsetNs};
94 
95     mOffsetThresholdForNextVsync = phaseOffsetThresholdForNextVsyncNs != -1
96             ? phaseOffsetThresholdForNextVsyncNs
97             : std::numeric_limits<nsecs_t>::max();
98 }
99 
getOffsetsForRefreshRate(android::scheduler::RefreshRateConfigs::RefreshRateType refreshRateType) const100 PhaseOffsets::Offsets PhaseOffsets::getOffsetsForRefreshRate(
101         android::scheduler::RefreshRateConfigs::RefreshRateType refreshRateType) const {
102     switch (refreshRateType) {
103         case RefreshRateConfigs::RefreshRateType::PERFORMANCE:
104             return mHighRefreshRateOffsets;
105         default:
106             return mDefaultRefreshRateOffsets;
107     }
108 }
109 
dump(std::string & result) const110 void PhaseOffsets::dump(std::string& result) const {
111     const auto [early, earlyGl, late] = getCurrentOffsets();
112     base::StringAppendF(&result,
113                         "         app phase: %9" PRId64 " ns\t         SF phase: %9" PRId64 " ns\n"
114                         "   early app phase: %9" PRId64 " ns\t   early SF phase: %9" PRId64 " ns\n"
115                         "GL early app phase: %9" PRId64 " ns\tGL early SF phase: %9" PRId64 " ns\n",
116                         late.app, late.sf, early.app, early.sf, earlyGl.app, earlyGl.sf);
117 }
118 
getCurrentAppOffset()119 nsecs_t PhaseOffsets::getCurrentAppOffset() {
120     return getCurrentOffsets().late.app;
121 }
122 
getCurrentSfOffset()123 nsecs_t PhaseOffsets::getCurrentSfOffset() {
124     return getCurrentOffsets().late.sf;
125 }
126 
127 } // namespace impl
128 } // namespace scheduler
129 } // namespace android
130