1 /*
2  * Copyright (C) 2023 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 package com.android.server.display.mode;
18 
19 import android.annotation.IntDef;
20 import android.annotation.NonNull;
21 
22 import com.android.server.display.config.SupportedModeData;
23 
24 import java.lang.annotation.Retention;
25 import java.lang.annotation.RetentionPolicy;
26 import java.util.ArrayList;
27 import java.util.List;
28 
29 interface Vote {
30     // DEFAULT_RENDER_FRAME_RATE votes for render frame rate [0, DEFAULT]. As the lowest
31     // priority vote, it's overridden by all other considerations. It acts to set a default
32     // frame rate for a device.
33     int PRIORITY_DEFAULT_RENDER_FRAME_RATE = 0;
34 
35     // PRIORITY_FLICKER_REFRESH_RATE votes for a single refresh rate like [60,60], [90,90] or
36     // null. It is used to set a preferred refresh rate value in case the higher priority votes
37     // result is a range.
38     static final int PRIORITY_FLICKER_REFRESH_RATE = 1;
39 
40     // High-brightness-mode may need a specific range of refresh-rates to function properly.
41     int PRIORITY_HIGH_BRIGHTNESS_MODE = 2;
42 
43     // SETTING_MIN_RENDER_FRAME_RATE is used to propose a lower bound of the render frame rate.
44     // It votes [minRefreshRate, Float.POSITIVE_INFINITY]
45     int PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE = 3;
46 
47     // User setting preferred display resolution.
48     int PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE = 4;
49 
50     // APP_REQUEST_RENDER_FRAME_RATE_RANGE is used to for internal apps to limit the render
51     // frame rate in certain cases, mostly to preserve power.
52     // @see android.view.WindowManager.LayoutParams#preferredMinRefreshRate
53     // @see android.view.WindowManager.LayoutParams#preferredMaxRefreshRate
54     // It votes to [preferredMinRefreshRate, preferredMaxRefreshRate].
55     int PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE = 5;
56 
57     // We split the app request into different priorities in case we can satisfy one desire
58     // without the other.
59 
60     // Application can specify preferred refresh rate with below attrs.
61     // @see android.view.WindowManager.LayoutParams#preferredRefreshRate
62     // @see android.view.WindowManager.LayoutParams#preferredDisplayModeId
63     //
64     // When the app specifies a LayoutParams#preferredDisplayModeId, in addition to the
65     // refresh rate, it also chooses a preferred size (resolution) as part of the selected
66     // mode id. The app preference is then translated to APP_REQUEST_BASE_MODE_REFRESH_RATE and
67     // optionally to APP_REQUEST_SIZE as well, if a mode id was selected.
68     // The system also forces some apps like denylisted app to run at a lower refresh rate.
69     // @see android.R.array#config_highRefreshRateBlacklist
70     //
71     // When summarizing the votes and filtering the allowed display modes, these votes determine
72     // which mode id should be the base mode id to be sent to SurfaceFlinger:
73     // - APP_REQUEST_BASE_MODE_REFRESH_RATE is used to validate the vote summary. If a summary
74     //   includes a base mode refresh rate, but it is not in the refresh rate range, then the
75     //   summary is considered invalid so we could drop a lower priority vote and try again.
76     // - APP_REQUEST_SIZE is used to filter out display modes of a different size.
77     //
78     // The preferred refresh rate is set on the main surface of the app outside of
79     // DisplayModeDirector.
80     // @see com.android.server.wm.WindowState#updateFrameRateSelectionPriorityIfNeeded
81     int PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE = 6;
82 
83     int PRIORITY_APP_REQUEST_SIZE = 7;
84 
85     // PRIORITY_USER_SETTING_PEAK_REFRESH_RATE restricts physical refresh rate to
86     // [0, max(PEAK, MIN)], depending on user settings peakRR/minRR values
87     int PRIORITY_USER_SETTING_PEAK_REFRESH_RATE = 8;
88 
89     // PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE has a higher priority than
90     // PRIORITY_USER_SETTING_PEAK_REFRESH_RATE and will limit render rate to [0, max(PEAK, MIN)]
91     // in case physical refresh rate vote is discarded (due to other high priority votes),
92     // render rate vote can still apply
93     int PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE = 9;
94 
95     // Restrict all displays to 60Hz when external display is connected. It votes [59Hz, 61Hz].
96     int PRIORITY_SYNCHRONIZED_REFRESH_RATE = 10;
97 
98     // Restrict displays max available resolution and refresh rates. It votes [0, LIMIT]
99     int PRIORITY_LIMIT_MODE = 11;
100 
101     // To avoid delay in switching between 60HZ -> 90HZ when activating LHBM, set refresh
102     // rate to max value (same as for PRIORITY_UDFPS) on lock screen
103     int PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE = 12;
104 
105     // For concurrent displays we want to limit refresh rate on all displays
106     int PRIORITY_LAYOUT_LIMITED_FRAME_RATE = 13;
107 
108     // For internal application to limit display modes to specific ids
109     int PRIORITY_SYSTEM_REQUESTED_MODES = 14;
110 
111     // PRIORITY_LOW_POWER_MODE_MODES limits display modes to specific refreshRate-vsync pairs if
112     // Settings.Global.LOW_POWER_MODE is on.
113     // Lower priority that PRIORITY_LOW_POWER_MODE_RENDER_RATE and if discarded (due to other
114     // higher priority votes), render rate limit can still apply
115     int PRIORITY_LOW_POWER_MODE_MODES = 15;
116 
117     // PRIORITY_LOW_POWER_MODE_RENDER_RATE force the render frame rate to [0, 60HZ] if
118     // Settings.Global.LOW_POWER_MODE is on.
119     int PRIORITY_LOW_POWER_MODE_RENDER_RATE = 16;
120 
121     // PRIORITY_FLICKER_REFRESH_RATE_SWITCH votes for disabling refresh rate switching. If the
122     // higher priority voters' result is a range, it will fix the rate to a single choice.
123     // It's used to avoid refresh rate switches in certain conditions which may result in the
124     // user seeing the display flickering when the switches occur.
125     int PRIORITY_FLICKER_REFRESH_RATE_SWITCH = 17;
126 
127     // Force display to [0, 60HZ] if skin temperature is at or above CRITICAL.
128     int PRIORITY_SKIN_TEMPERATURE = 18;
129 
130     // The proximity sensor needs the refresh rate to be locked in order to function, so this is
131     // set to a high priority.
132     int PRIORITY_PROXIMITY = 19;
133 
134     // The Under-Display Fingerprint Sensor (UDFPS) needs the refresh rate to be locked in order
135     // to function, so this needs to be the highest priority of all votes.
136     int PRIORITY_UDFPS = 20;
137 
138     @IntDef(prefix = { "PRIORITY_" }, value = {
139             PRIORITY_DEFAULT_RENDER_FRAME_RATE,
140             PRIORITY_FLICKER_REFRESH_RATE,
141             PRIORITY_HIGH_BRIGHTNESS_MODE,
142             PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE,
143             PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE,
144             PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE,
145             PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE,
146             PRIORITY_APP_REQUEST_SIZE,
147             PRIORITY_USER_SETTING_PEAK_REFRESH_RATE,
148             PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE,
149             PRIORITY_SYNCHRONIZED_REFRESH_RATE,
150             PRIORITY_LIMIT_MODE,
151             PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE,
152             PRIORITY_LAYOUT_LIMITED_FRAME_RATE,
153             PRIORITY_SYSTEM_REQUESTED_MODES,
154             PRIORITY_LOW_POWER_MODE_MODES,
155             PRIORITY_LOW_POWER_MODE_RENDER_RATE,
156             PRIORITY_FLICKER_REFRESH_RATE_SWITCH,
157             PRIORITY_SKIN_TEMPERATURE,
158             PRIORITY_PROXIMITY,
159             PRIORITY_UDFPS
160     })
161     @Retention(RetentionPolicy.SOURCE)
162     @interface Priority {}
163 
164     // Whenever a new priority is added, remember to update MIN_PRIORITY, MAX_PRIORITY, and
165     // APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF, as well as priorityToString.
166     @Priority int MIN_PRIORITY = PRIORITY_DEFAULT_RENDER_FRAME_RATE;
167     @Priority int MAX_PRIORITY = PRIORITY_UDFPS;
168 
169     // The cutoff for the app request refresh rate range. Votes with priorities lower than this
170     // value will not be considered when constructing the app request refresh rate range.
171     @Priority int APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF =
172             PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE;
173 
174     /**
175      * A value signifying an invalid width or height in a vote.
176      */
177     int INVALID_SIZE = -1;
178 
updateSummary(@onNull VoteSummary summary)179     void updateSummary(@NonNull VoteSummary summary);
180 
forPhysicalRefreshRates(float minRefreshRate, float maxRefreshRate)181     static Vote forPhysicalRefreshRates(float minRefreshRate, float maxRefreshRate) {
182         return new CombinedVote(
183                 List.of(
184                         new RefreshRateVote.PhysicalVote(minRefreshRate, maxRefreshRate),
185                         new DisableRefreshRateSwitchingVote(minRefreshRate == maxRefreshRate)
186                 )
187         );
188     }
189 
forRenderFrameRates(float minFrameRate, float maxFrameRate)190     static Vote forRenderFrameRates(float minFrameRate, float maxFrameRate) {
191         return new RefreshRateVote.RenderVote(minFrameRate, maxFrameRate);
192     }
193 
forSize(int width, int height)194     static Vote forSize(int width, int height) {
195         return new SizeVote(width, height, width, height);
196     }
197 
forSizeAndPhysicalRefreshRatesRange(int minWidth, int minHeight, int width, int height, float minRefreshRate, float maxRefreshRate)198     static Vote forSizeAndPhysicalRefreshRatesRange(int minWidth, int minHeight,
199             int width, int height, float minRefreshRate, float maxRefreshRate) {
200         return new CombinedVote(
201                 List.of(
202                         new SizeVote(width, height, minWidth, minHeight),
203                         new RefreshRateVote.PhysicalVote(minRefreshRate, maxRefreshRate),
204                         new DisableRefreshRateSwitchingVote(minRefreshRate == maxRefreshRate)
205                 )
206         );
207     }
208 
forDisableRefreshRateSwitching()209     static Vote forDisableRefreshRateSwitching() {
210         return new DisableRefreshRateSwitchingVote(true);
211     }
212 
forBaseModeRefreshRate(float baseModeRefreshRate)213     static Vote forBaseModeRefreshRate(float baseModeRefreshRate) {
214         return new BaseModeRefreshRateVote(baseModeRefreshRate);
215     }
216 
forRequestedRefreshRate(float refreshRate)217     static Vote forRequestedRefreshRate(float refreshRate) {
218         return new RequestedRefreshRateVote(refreshRate);
219     }
220 
forSupportedRefreshRates(List<SupportedModeData> supportedModes)221     static Vote forSupportedRefreshRates(List<SupportedModeData> supportedModes) {
222         if (supportedModes.isEmpty()) {
223             return null;
224         }
225         List<SupportedRefreshRatesVote.RefreshRates> rates = new ArrayList<>();
226         for (SupportedModeData data : supportedModes) {
227             rates.add(new SupportedRefreshRatesVote.RefreshRates(data.refreshRate, data.vsyncRate));
228         }
229         return new SupportedRefreshRatesVote(rates);
230     }
231 
forSupportedModes(List<Integer> modeIds)232     static Vote forSupportedModes(List<Integer> modeIds) {
233         return new SupportedModesVote(modeIds);
234     }
235 
priorityToString(int priority)236     static String priorityToString(int priority) {
237         switch (priority) {
238             case PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE:
239                 return "PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE";
240             case PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE:
241                 return "PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE";
242             case PRIORITY_APP_REQUEST_SIZE:
243                 return "PRIORITY_APP_REQUEST_SIZE";
244             case PRIORITY_DEFAULT_RENDER_FRAME_RATE:
245                 return "PRIORITY_DEFAULT_REFRESH_RATE";
246             case PRIORITY_FLICKER_REFRESH_RATE:
247                 return "PRIORITY_FLICKER_REFRESH_RATE";
248             case PRIORITY_FLICKER_REFRESH_RATE_SWITCH:
249                 return "PRIORITY_FLICKER_REFRESH_RATE_SWITCH";
250             case PRIORITY_HIGH_BRIGHTNESS_MODE:
251                 return "PRIORITY_HIGH_BRIGHTNESS_MODE";
252             case PRIORITY_PROXIMITY:
253                 return "PRIORITY_PROXIMITY";
254             case PRIORITY_LOW_POWER_MODE_MODES:
255                 return "PRIORITY_LOW_POWER_MODE_MODES";
256             case PRIORITY_LOW_POWER_MODE_RENDER_RATE:
257                 return "PRIORITY_LOW_POWER_MODE_RENDER_RATE";
258             case PRIORITY_SKIN_TEMPERATURE:
259                 return "PRIORITY_SKIN_TEMPERATURE";
260             case PRIORITY_UDFPS:
261                 return "PRIORITY_UDFPS";
262             case PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE:
263                 return "PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE";
264             case PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE:
265                 return "PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE";
266             case PRIORITY_LIMIT_MODE:
267                 return "PRIORITY_LIMIT_MODE";
268             case PRIORITY_SYNCHRONIZED_REFRESH_RATE:
269                 return "PRIORITY_SYNCHRONIZED_REFRESH_RATE";
270             case PRIORITY_USER_SETTING_PEAK_REFRESH_RATE:
271                 return "PRIORITY_USER_SETTING_PEAK_REFRESH_RATE";
272             case PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE:
273                 return "PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE";
274             case PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE:
275                 return "PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE";
276             case PRIORITY_LAYOUT_LIMITED_FRAME_RATE:
277                 return "PRIORITY_LAYOUT_LIMITED_FRAME_RATE";
278             case PRIORITY_SYSTEM_REQUESTED_MODES:
279                 return "PRIORITY_SYSTEM_REQUESTED_MODES";
280             default:
281                 return Integer.toString(priority);
282         }
283     }
284 }
285