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.view.SurfaceControl; 20 21 final class Vote { 22 // DEFAULT_RENDER_FRAME_RATE votes for render frame rate [0, DEFAULT]. As the lowest 23 // priority vote, it's overridden by all other considerations. It acts to set a default 24 // frame rate for a device. 25 static final int PRIORITY_DEFAULT_RENDER_FRAME_RATE = 0; 26 27 // PRIORITY_FLICKER_REFRESH_RATE votes for a single refresh rate like [60,60], [90,90] or 28 // null. It is used to set a preferred refresh rate value in case the higher priority votes 29 // result is a range. 30 static final int PRIORITY_FLICKER_REFRESH_RATE = 1; 31 32 // High-brightness-mode may need a specific range of refresh-rates to function properly. 33 static final int PRIORITY_HIGH_BRIGHTNESS_MODE = 2; 34 35 // SETTING_MIN_RENDER_FRAME_RATE is used to propose a lower bound of the render frame rate. 36 // It votes [minRefreshRate, Float.POSITIVE_INFINITY] 37 static final int PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE = 3; 38 39 // APP_REQUEST_RENDER_FRAME_RATE_RANGE is used to for internal apps to limit the render 40 // frame rate in certain cases, mostly to preserve power. 41 // @see android.view.WindowManager.LayoutParams#preferredMinRefreshRate 42 // @see android.view.WindowManager.LayoutParams#preferredMaxRefreshRate 43 // It votes to [preferredMinRefreshRate, preferredMaxRefreshRate]. 44 static final int PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE = 4; 45 46 // We split the app request into different priorities in case we can satisfy one desire 47 // without the other. 48 49 // Application can specify preferred refresh rate with below attrs. 50 // @see android.view.WindowManager.LayoutParams#preferredRefreshRate 51 // @see android.view.WindowManager.LayoutParams#preferredDisplayModeId 52 // 53 // When the app specifies a LayoutParams#preferredDisplayModeId, in addition to the 54 // refresh rate, it also chooses a preferred size (resolution) as part of the selected 55 // mode id. The app preference is then translated to APP_REQUEST_BASE_MODE_REFRESH_RATE and 56 // optionally to APP_REQUEST_SIZE as well, if a mode id was selected. 57 // The system also forces some apps like denylisted app to run at a lower refresh rate. 58 // @see android.R.array#config_highRefreshRateBlacklist 59 // 60 // When summarizing the votes and filtering the allowed display modes, these votes determine 61 // which mode id should be the base mode id to be sent to SurfaceFlinger: 62 // - APP_REQUEST_BASE_MODE_REFRESH_RATE is used to validate the vote summary. If a summary 63 // includes a base mode refresh rate, but it is not in the refresh rate range, then the 64 // summary is considered invalid so we could drop a lower priority vote and try again. 65 // - APP_REQUEST_SIZE is used to filter out display modes of a different size. 66 // 67 // The preferred refresh rate is set on the main surface of the app outside of 68 // DisplayModeDirector. 69 // @see com.android.server.wm.WindowState#updateFrameRateSelectionPriorityIfNeeded 70 static final int PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE = 5; 71 static final int PRIORITY_APP_REQUEST_SIZE = 6; 72 73 // SETTING_PEAK_RENDER_FRAME_RATE has a high priority and will restrict the bounds of the 74 // rest of low priority voters. It votes [0, max(PEAK, MIN)] 75 static final int PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE = 7; 76 77 // To avoid delay in switching between 60HZ -> 90HZ when activating LHBM, set refresh 78 // rate to max value (same as for PRIORITY_UDFPS) on lock screen 79 static final int PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE = 8; 80 81 // For concurrent displays we want to limit refresh rate on all displays 82 static final int PRIORITY_LAYOUT_LIMITED_FRAME_RATE = 9; 83 84 // LOW_POWER_MODE force the render frame rate to [0, 60HZ] if 85 // Settings.Global.LOW_POWER_MODE is on. 86 static final int PRIORITY_LOW_POWER_MODE = 10; 87 88 // PRIORITY_FLICKER_REFRESH_RATE_SWITCH votes for disabling refresh rate switching. If the 89 // higher priority voters' result is a range, it will fix the rate to a single choice. 90 // It's used to avoid refresh rate switches in certain conditions which may result in the 91 // user seeing the display flickering when the switches occur. 92 static final int PRIORITY_FLICKER_REFRESH_RATE_SWITCH = 11; 93 94 // Force display to [0, 60HZ] if skin temperature is at or above CRITICAL. 95 static final int PRIORITY_SKIN_TEMPERATURE = 12; 96 97 // The proximity sensor needs the refresh rate to be locked in order to function, so this is 98 // set to a high priority. 99 static final int PRIORITY_PROXIMITY = 13; 100 101 // The Under-Display Fingerprint Sensor (UDFPS) needs the refresh rate to be locked in order 102 // to function, so this needs to be the highest priority of all votes. 103 static final int PRIORITY_UDFPS = 14; 104 105 // Whenever a new priority is added, remember to update MIN_PRIORITY, MAX_PRIORITY, and 106 // APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF, as well as priorityToString. 107 108 static final int MIN_PRIORITY = PRIORITY_DEFAULT_RENDER_FRAME_RATE; 109 static final int MAX_PRIORITY = PRIORITY_UDFPS; 110 111 // The cutoff for the app request refresh rate range. Votes with priorities lower than this 112 // value will not be considered when constructing the app request refresh rate range. 113 static final int APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF = 114 PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE; 115 116 /** 117 * A value signifying an invalid width or height in a vote. 118 */ 119 static final int INVALID_SIZE = -1; 120 121 /** 122 * The requested width of the display in pixels, or INVALID_SIZE; 123 */ 124 public final int width; 125 /** 126 * The requested height of the display in pixels, or INVALID_SIZE; 127 */ 128 public final int height; 129 /** 130 * Information about the refresh rate frame rate ranges DM would like to set the display to. 131 */ 132 public final SurfaceControl.RefreshRateRanges refreshRateRanges; 133 134 /** 135 * Whether refresh rate switching should be disabled (i.e. the refresh rate range is 136 * a single value). 137 */ 138 public final boolean disableRefreshRateSwitching; 139 140 /** 141 * The preferred refresh rate selected by the app. It is used to validate that the summary 142 * refresh rate ranges include this value, and are not restricted by a lower priority vote. 143 */ 144 public final float appRequestBaseModeRefreshRate; 145 forPhysicalRefreshRates(float minRefreshRate, float maxRefreshRate)146 static Vote forPhysicalRefreshRates(float minRefreshRate, float maxRefreshRate) { 147 return new Vote(INVALID_SIZE, INVALID_SIZE, minRefreshRate, maxRefreshRate, 0, 148 Float.POSITIVE_INFINITY, 149 minRefreshRate == maxRefreshRate, 0f); 150 } 151 forRenderFrameRates(float minFrameRate, float maxFrameRate)152 static Vote forRenderFrameRates(float minFrameRate, float maxFrameRate) { 153 return new Vote(INVALID_SIZE, INVALID_SIZE, 0, Float.POSITIVE_INFINITY, minFrameRate, 154 maxFrameRate, 155 false, 0f); 156 } 157 forSize(int width, int height)158 static Vote forSize(int width, int height) { 159 return new Vote(width, height, 0, Float.POSITIVE_INFINITY, 0, Float.POSITIVE_INFINITY, 160 false, 161 0f); 162 } 163 forDisableRefreshRateSwitching()164 static Vote forDisableRefreshRateSwitching() { 165 return new Vote(INVALID_SIZE, INVALID_SIZE, 0, Float.POSITIVE_INFINITY, 0, 166 Float.POSITIVE_INFINITY, true, 167 0f); 168 } 169 forBaseModeRefreshRate(float baseModeRefreshRate)170 static Vote forBaseModeRefreshRate(float baseModeRefreshRate) { 171 return new Vote(INVALID_SIZE, INVALID_SIZE, 0, Float.POSITIVE_INFINITY, 0, 172 Float.POSITIVE_INFINITY, false, 173 baseModeRefreshRate); 174 } 175 Vote(int width, int height, float minPhysicalRefreshRate, float maxPhysicalRefreshRate, float minRenderFrameRate, float maxRenderFrameRate, boolean disableRefreshRateSwitching, float baseModeRefreshRate)176 private Vote(int width, int height, 177 float minPhysicalRefreshRate, 178 float maxPhysicalRefreshRate, 179 float minRenderFrameRate, 180 float maxRenderFrameRate, 181 boolean disableRefreshRateSwitching, 182 float baseModeRefreshRate) { 183 this.width = width; 184 this.height = height; 185 this.refreshRateRanges = new SurfaceControl.RefreshRateRanges( 186 new SurfaceControl.RefreshRateRange(minPhysicalRefreshRate, maxPhysicalRefreshRate), 187 new SurfaceControl.RefreshRateRange(minRenderFrameRate, maxRenderFrameRate)); 188 this.disableRefreshRateSwitching = disableRefreshRateSwitching; 189 this.appRequestBaseModeRefreshRate = baseModeRefreshRate; 190 } 191 priorityToString(int priority)192 static String priorityToString(int priority) { 193 switch (priority) { 194 case PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE: 195 return "PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE"; 196 case PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE: 197 return "PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE"; 198 case PRIORITY_APP_REQUEST_SIZE: 199 return "PRIORITY_APP_REQUEST_SIZE"; 200 case PRIORITY_DEFAULT_RENDER_FRAME_RATE: 201 return "PRIORITY_DEFAULT_REFRESH_RATE"; 202 case PRIORITY_FLICKER_REFRESH_RATE: 203 return "PRIORITY_FLICKER_REFRESH_RATE"; 204 case PRIORITY_FLICKER_REFRESH_RATE_SWITCH: 205 return "PRIORITY_FLICKER_REFRESH_RATE_SWITCH"; 206 case PRIORITY_HIGH_BRIGHTNESS_MODE: 207 return "PRIORITY_HIGH_BRIGHTNESS_MODE"; 208 case PRIORITY_PROXIMITY: 209 return "PRIORITY_PROXIMITY"; 210 case PRIORITY_LOW_POWER_MODE: 211 return "PRIORITY_LOW_POWER_MODE"; 212 case PRIORITY_SKIN_TEMPERATURE: 213 return "PRIORITY_SKIN_TEMPERATURE"; 214 case PRIORITY_UDFPS: 215 return "PRIORITY_UDFPS"; 216 case PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE: 217 return "PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE"; 218 case PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE: 219 return "PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE"; 220 case PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE: 221 return "PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE"; 222 case PRIORITY_LAYOUT_LIMITED_FRAME_RATE: 223 return "PRIORITY_LAYOUT_LIMITED_FRAME_RATE"; 224 default: 225 return Integer.toString(priority); 226 } 227 } 228 229 @Override toString()230 public String toString() { 231 return "Vote: {" 232 + "width: " + width + ", height: " + height 233 + ", refreshRateRanges: " + refreshRateRanges 234 + ", disableRefreshRateSwitching: " + disableRefreshRateSwitching 235 + ", appRequestBaseModeRefreshRate: " + appRequestBaseModeRefreshRate + "}"; 236 } 237 } 238