1 /* 2 * Copyright (C) 2020 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; 18 19 import android.annotation.NonNull; 20 import android.content.Context; 21 import android.content.res.Configuration; 22 import android.content.res.Resources; 23 import android.content.res.TypedArray; 24 import android.hardware.display.DisplayManagerInternal; 25 import android.hardware.display.DisplayManagerInternal.RefreshRateLimitation; 26 import android.os.Environment; 27 import android.os.PowerManager; 28 import android.text.TextUtils; 29 import android.util.MathUtils; 30 import android.util.Pair; 31 import android.util.Slog; 32 import android.util.Spline; 33 import android.view.DisplayAddress; 34 35 import com.android.internal.R; 36 import com.android.internal.annotations.VisibleForTesting; 37 import com.android.internal.display.BrightnessSynchronizer; 38 import com.android.server.display.config.AutoBrightness; 39 import com.android.server.display.config.BlockingZoneConfig; 40 import com.android.server.display.config.BrightnessThresholds; 41 import com.android.server.display.config.BrightnessThrottlingMap; 42 import com.android.server.display.config.BrightnessThrottlingPoint; 43 import com.android.server.display.config.Density; 44 import com.android.server.display.config.DisplayBrightnessPoint; 45 import com.android.server.display.config.DisplayConfiguration; 46 import com.android.server.display.config.DisplayQuirks; 47 import com.android.server.display.config.HbmTiming; 48 import com.android.server.display.config.HighBrightnessMode; 49 import com.android.server.display.config.IntegerArray; 50 import com.android.server.display.config.NitsMap; 51 import com.android.server.display.config.Point; 52 import com.android.server.display.config.RefreshRateConfigs; 53 import com.android.server.display.config.RefreshRateRange; 54 import com.android.server.display.config.SdrHdrRatioMap; 55 import com.android.server.display.config.SdrHdrRatioPoint; 56 import com.android.server.display.config.SensorDetails; 57 import com.android.server.display.config.ThermalStatus; 58 import com.android.server.display.config.ThermalThrottling; 59 import com.android.server.display.config.ThresholdPoint; 60 import com.android.server.display.config.XmlParser; 61 62 import org.xmlpull.v1.XmlPullParserException; 63 64 import java.io.BufferedInputStream; 65 import java.io.File; 66 import java.io.FileInputStream; 67 import java.io.IOException; 68 import java.io.InputStream; 69 import java.math.BigDecimal; 70 import java.math.BigInteger; 71 import java.util.ArrayList; 72 import java.util.Arrays; 73 import java.util.Collection; 74 import java.util.List; 75 import java.util.Locale; 76 77 import javax.xml.datatype.DatatypeConfigurationException; 78 79 /** 80 * Reads and stores display-specific configurations. File format: 81 * <pre> 82 * {@code 83 * <displayConfiguration> 84 * <densityMapping> 85 * <density> 86 * <height>480</height> 87 * <width>720</width> 88 * <density>120</density> 89 * </density> 90 * <density> 91 * <height>720</height> 92 * <width>1280</width> 93 * <density>213</density> 94 * </density> 95 * <density> 96 * <height>1080</height> 97 * <width>1920</width> 98 * <density>320</density> 99 * </density> 100 * <density> 101 * <height>2160</height> 102 * <width>3840</width> 103 * <density>640</density> 104 * </density> 105 * </densityMapping> 106 * 107 * <screenBrightnessMap> 108 * <point> 109 * <value>0.0</value> 110 * <nits>2.0</nits> 111 * </point> 112 * <point> 113 * <value>0.62</value> 114 * <nits>500.0</nits> 115 * </point> 116 * <point> 117 * <value>1.0</value> 118 * <nits>800.0</nits> 119 * </point> 120 * </screenBrightnessMap> 121 * 122 * <screenBrightnessDefault>0.65</screenBrightnessDefault> 123 * 124 * <thermalThrottling> 125 * <brightnessThrottlingMap> 126 * <brightnessThrottlingPoint> 127 * <thermalStatus>severe</thermalStatus> 128 * <brightness>0.1</brightness> 129 * </brightnessThrottlingPoint> 130 * <brightnessThrottlingPoint> 131 * <thermalStatus>critical</thermalStatus> 132 * <brightness>0.01</brightness> 133 * </brightnessThrottlingPoint> 134 * </brightnessThrottlingMap> 135 * </thermalThrottling> 136 * 137 * <refreshRate> 138 * <defaultRefreshRateInHbmHdr>75</defaultRefreshRateInHbmHdr> 139 * <defaultRefreshRateInHbmSunlight>75</defaultRefreshRateInHbmSunlight> 140 * <lowerBlockingZoneConfigs> 141 * <defaultRefreshRate>75</defaultRefreshRate> 142 * <blockingZoneThreshold> 143 * <displayBrightnessPoint> 144 * <lux>50</lux> 145 * <nits>45.3</nits> 146 * </displayBrightnessPoint> 147 * <displayBrightnessPoint> 148 * <lux>60</lux> 149 * <nits>55.2</nits> 150 * </displayBrightnessPoint> 151 * </blockingZoneThreshold> 152 * </lowerBlockingZoneConfigs> 153 * <higherBlockingZoneConfigs> 154 * <defaultRefreshRate>90</defaultRefreshRate> 155 * <blockingZoneThreshold> 156 * <displayBrightnessPoint> 157 * <lux>500</lux> 158 * <nits>245.3</nits> 159 * </displayBrightnessPoint> 160 * <displayBrightnessPoint> 161 * <lux>600</lux> 162 * <nits>232.3</nits> 163 * </displayBrightnessPoint> 164 * </blockingZoneThreshold> 165 * </higherBlockingZoneConfigs> 166 * </refreshRate> 167 * 168 * <highBrightnessMode enabled="true"> 169 * <transitionPoint>0.62</transitionPoint> 170 * <minimumLux>10000</minimumLux> 171 * <timing> 172 * <timeWindowSecs>1800</timeWindowSecs> // Window in which we restrict HBM. 173 * <timeMaxSecs>300</timeMaxSecs> // Maximum time of HBM allowed in that window. 174 * <timeMinSecs>60</timeMinSecs> // Minimum time remaining required to switch 175 * </timing> // HBM on for. 176 * <refreshRate> 177 * <minimum>120</minimum> 178 * <maximum>120</maximum> 179 * </refreshRate> 180 * <thermalStatusLimit>light</thermalStatusLimit> 181 * <allowInLowPowerMode>false</allowInLowPowerMode> 182 * </highBrightnessMode> 183 * 184 * <quirks> 185 * <quirk>canSetBrightnessViaHwc</quirk> 186 * </quirks> 187 * 188 * <autoBrightness enable="true"> 189 * <brighteningLightDebounceMillis> 190 * 2000 191 * </brighteningLightDebounceMillis> 192 * <darkeningLightDebounceMillis> 193 * 1000 194 * </darkeningLightDebounceMillis> 195 * <displayBrightnessMapping> 196 * <displayBrightnessPoint> 197 * <lux>50</lux> 198 * <nits>45.32</nits> 199 * </displayBrightnessPoint> 200 * <displayBrightnessPoint> 201 * <lux>80</lux> 202 * <nits>75.43</nits> 203 * </displayBrightnessPoint> 204 * </displayBrightnessMapping> 205 * </autoBrightness> 206 * 207 * <screenBrightnessRampFastDecrease>0.01</screenBrightnessRampFastDecrease> 208 * <screenBrightnessRampFastIncrease>0.02</screenBrightnessRampFastIncrease> 209 * <screenBrightnessRampSlowDecrease>0.03</screenBrightnessRampSlowDecrease> 210 * <screenBrightnessRampSlowIncrease>0.04</screenBrightnessRampSlowIncrease> 211 * 212 * <screenBrightnessRampIncreaseMaxMillis>2000</screenBrightnessRampIncreaseMaxMillis> 213 * <screenBrightnessRampDecreaseMaxMillis>3000</screenBrightnessRampDecreaseMaxMillis> 214 * 215 * <lightSensor> 216 * <type>android.sensor.light</type> 217 * <name>1234 Ambient Light Sensor</name> 218 * </lightSensor> 219 * <screenOffBrightnessSensor> 220 * <type>com.google.sensor.binned_brightness</type> 221 * <name>Binned Brightness 0 (wake-up)</name> 222 * </screenOffBrightnessSensor> 223 * <proxSensor> 224 * <type>android.sensor.proximity</type> 225 * <name>1234 Proximity Sensor</name> 226 * </proxSensor> 227 * 228 * <ambientLightHorizonLong>10001</ambientLightHorizonLong> 229 * <ambientLightHorizonShort>2001</ambientLightHorizonShort> 230 * 231 * <ambientBrightnessChangeThresholds> // Thresholds for lux changes 232 * <brighteningThresholds> 233 * // Minimum change needed in ambient brightness to brighten screen. 234 * <minimum>10</minimum> 235 * // Percentage increase of lux needed to increase the screen brightness at a lux range 236 * // above the specified threshold. 237 * <brightnessThresholdPoints> 238 * <brightnessThresholdPoint> 239 * <threshold>0</threshold><percentage>13</percentage> 240 * </brightnessThresholdPoint> 241 * <brightnessThresholdPoint> 242 * <threshold>100</threshold><percentage>14</percentage> 243 * </brightnessThresholdPoint> 244 * <brightnessThresholdPoint> 245 * <threshold>200</threshold><percentage>15</percentage> 246 * </brightnessThresholdPoint> 247 * </brightnessThresholdPoints> 248 * </brighteningThresholds> 249 * <darkeningThresholds> 250 * // Minimum change needed in ambient brightness to darken screen. 251 * <minimum>30</minimum> 252 * // Percentage increase of lux needed to decrease the screen brightness at a lux range 253 * // above the specified threshold. 254 * <brightnessThresholdPoints> 255 * <brightnessThresholdPoint> 256 * <threshold>0</threshold><percentage>15</percentage> 257 * </brightnessThresholdPoint> 258 * <brightnessThresholdPoint> 259 * <threshold>300</threshold><percentage>16</percentage> 260 * </brightnessThresholdPoint> 261 * <brightnessThresholdPoint> 262 * <threshold>400</threshold><percentage>17</percentage> 263 * </brightnessThresholdPoint> 264 * </brightnessThresholdPoints> 265 * </darkeningThresholds> 266 * </ambientBrightnessChangeThresholds> 267 * <displayBrightnessChangeThresholds> // Thresholds for screen brightness changes 268 * <brighteningThresholds> 269 * // Minimum change needed in screen brightness to brighten screen. 270 * <minimum>0.1</minimum> 271 * // Percentage increase of screen brightness needed to increase the screen brightness 272 * // at a lux range above the specified threshold. 273 * <brightnessThresholdPoints> 274 * <brightnessThresholdPoint> 275 * <threshold>0</threshold> 276 * <percentage>9</percentage> 277 * </brightnessThresholdPoint> 278 * <brightnessThresholdPoint> 279 * <threshold>0.10</threshold> 280 * <percentage>10</percentage> 281 * </brightnessThresholdPoint> 282 * <brightnessThresholdPoint> 283 * <threshold>0.20</threshold> 284 * <percentage>11</percentage> 285 * </brightnessThresholdPoint> 286 * </brightnessThresholdPoints> 287 * </brighteningThresholds> 288 * <darkeningThresholds> 289 * // Minimum change needed in screen brightness to darken screen. 290 * <minimum>0.3</minimum> 291 * // Percentage increase of screen brightness needed to decrease the screen brightness 292 * // at a lux range above the specified threshold. 293 * <brightnessThresholdPoints> 294 * <brightnessThresholdPoint> 295 * <threshold>0</threshold><percentage>11</percentage> 296 * </brightnessThresholdPoint> 297 * <brightnessThresholdPoint> 298 * <threshold>0.11</threshold><percentage>12</percentage> 299 * </brightnessThresholdPoint> 300 * <brightnessThresholdPoint> 301 * <threshold>0.21</threshold><percentage>13</percentage> 302 * </brightnessThresholdPoint> 303 * </brightnessThresholdPoints> 304 * </darkeningThresholds> 305 * </displayBrightnessChangeThresholds> 306 * <ambientBrightnessChangeThresholdsIdle> // Thresholds for lux changes in idle mode 307 * <brighteningThresholds> 308 * // Minimum change needed in ambient brightness to brighten screen in idle mode 309 * <minimum>20</minimum> 310 * // Percentage increase of lux needed to increase the screen brightness at a lux range 311 * // above the specified threshold whilst in idle mode. 312 * <brightnessThresholdPoints> 313 * <brightnessThresholdPoint> 314 * <threshold>0</threshold><percentage>21</percentage> 315 * </brightnessThresholdPoint> 316 * <brightnessThresholdPoint> 317 * <threshold>500</threshold><percentage>22</percentage> 318 * </brightnessThresholdPoint> 319 * <brightnessThresholdPoint> 320 * <threshold>600</threshold><percentage>23</percentage> 321 * </brightnessThresholdPoint> 322 * </brightnessThresholdPoints> 323 * </brighteningThresholds> 324 * <darkeningThresholds> 325 * // Minimum change needed in ambient brightness to darken screen in idle mode 326 * <minimum>40</minimum> 327 * // Percentage increase of lux needed to decrease the screen brightness at a lux range 328 * // above the specified threshold whilst in idle mode. 329 * <brightnessThresholdPoints> 330 * <brightnessThresholdPoint> 331 * <threshold>0</threshold><percentage>23</percentage> 332 * </brightnessThresholdPoint> 333 * <brightnessThresholdPoint> 334 * <threshold>700</threshold><percentage>24</percentage> 335 * </brightnessThresholdPoint> 336 * <brightnessThresholdPoint> 337 * <threshold>800</threshold><percentage>25</percentage> 338 * </brightnessThresholdPoint> 339 * </brightnessThresholdPoints> 340 * </darkeningThresholds> 341 * </ambientBrightnessChangeThresholdsIdle> 342 * <displayBrightnessChangeThresholdsIdle> // Thresholds for idle screen brightness changes 343 * <brighteningThresholds> 344 * // Minimum change needed in screen brightness to brighten screen in idle mode 345 * <minimum>0.2</minimum> 346 * // Percentage increase of screen brightness needed to increase the screen brightness 347 * // at a lux range above the specified threshold whilst in idle mode 348 * <brightnessThresholdPoints> 349 * <brightnessThresholdPoint> 350 * <threshold>0</threshold><percentage>17</percentage> 351 * </brightnessThresholdPoint> 352 * <brightnessThresholdPoint> 353 * <threshold>0.12</threshold><percentage>18</percentage> 354 * </brightnessThresholdPoint> 355 * <brightnessThresholdPoint> 356 * <threshold>0.22</threshold><percentage>19</percentage> 357 * </brightnessThresholdPoint> 358 * </brightnessThresholdPoints> 359 * </brighteningThresholds> 360 * <darkeningThresholds> 361 * // Minimum change needed in screen brightness to darken screen in idle mode 362 * <minimum>0.4</minimum> 363 * // Percentage increase of screen brightness needed to decrease the screen brightness 364 * // at a lux range above the specified threshold whilst in idle mode 365 * <brightnessThresholdPoints> 366 * <brightnessThresholdPoint> 367 * <threshold>0</threshold><percentage>19</percentage> 368 * </brightnessThresholdPoint> 369 * <brightnessThresholdPoint> 370 * <threshold>0.13</threshold><percentage>20</percentage> 371 * </brightnessThresholdPoint> 372 * <brightnessThresholdPoint> 373 * <threshold>0.23</threshold><percentage>21</percentage> 374 * </brightnessThresholdPoint> 375 * </brightnessThresholdPoints> 376 * </darkeningThresholds> 377 * </displayBrightnessChangeThresholdsIdle> 378 * <screenOffBrightnessSensorValueToLux> 379 * <item>-1</item> 380 * <item>0</item> 381 * <item>5</item> 382 * <item>80</item> 383 * <item>1500</item> 384 * </screenOffBrightnessSensorValueToLux> 385 * </displayConfiguration> 386 * } 387 * </pre> 388 */ 389 public class DisplayDeviceConfig { 390 private static final String TAG = "DisplayDeviceConfig"; 391 private static final boolean DEBUG = false; 392 393 public static final float HIGH_BRIGHTNESS_MODE_UNSUPPORTED = Float.NaN; 394 395 public static final String QUIRK_CAN_SET_BRIGHTNESS_VIA_HWC = "canSetBrightnessViaHwc"; 396 397 private static final float BRIGHTNESS_DEFAULT = 0.5f; 398 private static final String ETC_DIR = "etc"; 399 private static final String DISPLAY_CONFIG_DIR = "displayconfig"; 400 private static final String CONFIG_FILE_FORMAT = "display_%s.xml"; 401 private static final String DEFAULT_CONFIG_FILE = "default.xml"; 402 private static final String DEFAULT_CONFIG_FILE_WITH_UIMODE_FORMAT = "default_%s.xml"; 403 private static final String PORT_SUFFIX_FORMAT = "port_%d"; 404 private static final String STABLE_ID_SUFFIX_FORMAT = "id_%d"; 405 private static final String NO_SUFFIX_FORMAT = "%d"; 406 private static final long STABLE_FLAG = 1L << 62; 407 private static final int DEFAULT_PEAK_REFRESH_RATE = 0; 408 private static final int DEFAULT_REFRESH_RATE = 60; 409 private static final int DEFAULT_REFRESH_RATE_IN_HBM = 0; 410 private static final int DEFAULT_LOW_REFRESH_RATE = 60; 411 private static final int DEFAULT_HIGH_REFRESH_RATE = 0; 412 private static final int[] DEFAULT_BRIGHTNESS_THRESHOLDS = new int[]{}; 413 414 private static final float[] DEFAULT_AMBIENT_THRESHOLD_LEVELS = new float[]{0f}; 415 private static final float[] DEFAULT_AMBIENT_BRIGHTENING_THRESHOLDS = new float[]{100f}; 416 private static final float[] DEFAULT_AMBIENT_DARKENING_THRESHOLDS = new float[]{200f}; 417 private static final float[] DEFAULT_SCREEN_THRESHOLD_LEVELS = new float[]{0f}; 418 private static final float[] DEFAULT_SCREEN_BRIGHTENING_THRESHOLDS = new float[]{100f}; 419 private static final float[] DEFAULT_SCREEN_DARKENING_THRESHOLDS = new float[]{200f}; 420 421 private static final int INTERPOLATION_DEFAULT = 0; 422 private static final int INTERPOLATION_LINEAR = 1; 423 424 // Float.NaN (used as invalid for brightness) cannot be stored in config.xml 425 // so -2 is used instead 426 private static final float INVALID_BRIGHTNESS_IN_CONFIG = -2f; 427 428 private static final float NITS_INVALID = -1; 429 430 // Length of the ambient light horizon used to calculate the long term estimate of ambient 431 // light. 432 private static final int AMBIENT_LIGHT_LONG_HORIZON_MILLIS = 10000; 433 434 // Length of the ambient light horizon used to calculate short-term estimate of ambient light. 435 private static final int AMBIENT_LIGHT_SHORT_HORIZON_MILLIS = 2000; 436 437 // Invalid value of AutoBrightness brightening and darkening light debounce 438 private static final int INVALID_AUTO_BRIGHTNESS_LIGHT_DEBOUNCE = -1; 439 440 @VisibleForTesting 441 static final float HDR_PERCENT_OF_SCREEN_REQUIRED_DEFAULT = 0.5f; 442 443 private final Context mContext; 444 445 // The details of the ambient light sensor associated with this display. 446 private final SensorData mAmbientLightSensor = new SensorData(); 447 448 // The details of the doze brightness sensor associated with this display. 449 private final SensorData mScreenOffBrightnessSensor = new SensorData(); 450 451 // The details of the proximity sensor associated with this display. 452 private final SensorData mProximitySensor = new SensorData(); 453 454 private final List<RefreshRateLimitation> mRefreshRateLimitations = 455 new ArrayList<>(2 /*initialCapacity*/); 456 457 // Nits and backlight values that are loaded from either the display device config file, or 458 // config.xml. These are the raw values and just used for the dumpsys 459 private float[] mRawNits; 460 private float[] mRawBacklight; 461 private int mInterpolationType; 462 463 // These arrays are calculated from the raw arrays, but clamped to contain values equal to and 464 // between mBacklightMinimum and mBacklightMaximum. These three arrays should all be the same 465 // length 466 // Nits array that is used to store the entire range of nits values that the device supports 467 private float[] mNits; 468 // Backlight array holds the values that the HAL uses to display the corresponding nits values 469 private float[] mBacklight; 470 // Purely an array that covers the ranges of values 0.0 - 1.0, indicating the system brightness 471 // for the corresponding values above 472 private float[] mBrightness; 473 474 475 /** 476 * Array of desired screen brightness in nits corresponding to the lux values 477 * in the mBrightnessLevelsLux array. The display brightness is defined as the 478 * measured brightness of an all-white image. The brightness values must be non-negative and 479 * non-decreasing. This must be overridden in platform specific overlays 480 */ 481 private float[] mBrightnessLevelsNits; 482 483 /** 484 * Array of light sensor lux values to define our levels for auto backlight 485 * brightness support. 486 487 * The N + 1 entries of this array define N control points defined in mBrightnessLevelsNits, 488 * with first value always being 0 lux 489 490 * The control points must be strictly increasing. Each control point 491 * corresponds to an entry in the brightness backlight values arrays. 492 * For example, if lux == level[1] (second element of the levels array) 493 * then the brightness will be determined by value[0] (first element 494 * of the brightness values array). 495 * 496 * Spline interpolation is used to determine the auto-brightness 497 * backlight values for lux levels between these control points. 498 * 499 */ 500 private float[] mBrightnessLevelsLux; 501 502 private float mBacklightMinimum = Float.NaN; 503 private float mBacklightMaximum = Float.NaN; 504 private float mBrightnessDefault = Float.NaN; 505 private float mBrightnessRampFastDecrease = Float.NaN; 506 private float mBrightnessRampFastIncrease = Float.NaN; 507 private float mBrightnessRampSlowDecrease = Float.NaN; 508 private float mBrightnessRampSlowIncrease = Float.NaN; 509 private long mBrightnessRampDecreaseMaxMillis = 0; 510 private long mBrightnessRampIncreaseMaxMillis = 0; 511 private int mAmbientHorizonLong = AMBIENT_LIGHT_LONG_HORIZON_MILLIS; 512 private int mAmbientHorizonShort = AMBIENT_LIGHT_SHORT_HORIZON_MILLIS; 513 private float mScreenBrighteningMinThreshold = 0.0f; // Retain behaviour as though there is 514 private float mScreenBrighteningMinThresholdIdle = 0.0f; // no minimum threshold for change in 515 private float mScreenDarkeningMinThreshold = 0.0f; // screen brightness or ambient 516 private float mScreenDarkeningMinThresholdIdle = 0.0f; // brightness. 517 private float mAmbientLuxBrighteningMinThreshold = 0.0f; 518 private float mAmbientLuxBrighteningMinThresholdIdle = 0.0f; 519 private float mAmbientLuxDarkeningMinThreshold = 0.0f; 520 private float mAmbientLuxDarkeningMinThresholdIdle = 0.0f; 521 522 // Screen brightness thresholds levels & percentages 523 private float[] mScreenBrighteningLevels = DEFAULT_SCREEN_THRESHOLD_LEVELS; 524 private float[] mScreenBrighteningPercentages = DEFAULT_SCREEN_BRIGHTENING_THRESHOLDS; 525 private float[] mScreenDarkeningLevels = DEFAULT_SCREEN_THRESHOLD_LEVELS; 526 private float[] mScreenDarkeningPercentages = DEFAULT_SCREEN_DARKENING_THRESHOLDS; 527 528 // Screen brightness thresholds levels & percentages for idle mode 529 private float[] mScreenBrighteningLevelsIdle = DEFAULT_SCREEN_THRESHOLD_LEVELS; 530 private float[] mScreenBrighteningPercentagesIdle = DEFAULT_SCREEN_BRIGHTENING_THRESHOLDS; 531 private float[] mScreenDarkeningLevelsIdle = DEFAULT_SCREEN_THRESHOLD_LEVELS; 532 private float[] mScreenDarkeningPercentagesIdle = DEFAULT_SCREEN_DARKENING_THRESHOLDS; 533 534 // Ambient brightness thresholds levels & percentages 535 private float[] mAmbientBrighteningLevels = DEFAULT_AMBIENT_THRESHOLD_LEVELS; 536 private float[] mAmbientBrighteningPercentages = DEFAULT_AMBIENT_BRIGHTENING_THRESHOLDS; 537 private float[] mAmbientDarkeningLevels = DEFAULT_AMBIENT_THRESHOLD_LEVELS; 538 private float[] mAmbientDarkeningPercentages = DEFAULT_AMBIENT_DARKENING_THRESHOLDS; 539 540 // Ambient brightness thresholds levels & percentages for idle mode 541 private float[] mAmbientBrighteningLevelsIdle = DEFAULT_AMBIENT_THRESHOLD_LEVELS; 542 private float[] mAmbientBrighteningPercentagesIdle = DEFAULT_AMBIENT_BRIGHTENING_THRESHOLDS; 543 private float[] mAmbientDarkeningLevelsIdle = DEFAULT_AMBIENT_THRESHOLD_LEVELS; 544 private float[] mAmbientDarkeningPercentagesIdle = DEFAULT_AMBIENT_DARKENING_THRESHOLDS; 545 546 // A mapping between screen off sensor values and lux values 547 private int[] mScreenOffBrightnessSensorValueToLux; 548 549 private Spline mBrightnessToBacklightSpline; 550 private Spline mBacklightToBrightnessSpline; 551 private Spline mBacklightToNitsSpline; 552 private Spline mNitsToBacklightSpline; 553 private List<String> mQuirks; 554 private boolean mIsHighBrightnessModeEnabled = false; 555 private HighBrightnessModeData mHbmData; 556 private DensityMapping mDensityMapping; 557 private String mLoadedFrom = null; 558 private Spline mSdrToHdrRatioSpline; 559 560 // Represents the auto-brightness brightening light debounce. 561 private long mAutoBrightnessBrighteningLightDebounce = 562 INVALID_AUTO_BRIGHTNESS_LIGHT_DEBOUNCE; 563 564 // Represents the auto-brightness darkening light debounce. 565 private long mAutoBrightnessDarkeningLightDebounce = 566 INVALID_AUTO_BRIGHTNESS_LIGHT_DEBOUNCE; 567 568 // This setting allows non-default displays to have autobrightness enabled. 569 private boolean mAutoBrightnessAvailable = false; 570 // This stores the raw value loaded from the config file - true if not written. 571 private boolean mDdcAutoBrightnessAvailable = true; 572 573 /** 574 * The default peak refresh rate for a given device. This value prevents the framework from 575 * using higher refresh rates, even if display modes with higher refresh rates are available 576 * from hardware composer. Only has an effect if the value is non-zero. 577 */ 578 private int mDefaultPeakRefreshRate = DEFAULT_PEAK_REFRESH_RATE; 579 580 /** 581 * The default refresh rate for a given device. This value sets the higher default 582 * refresh rate. If the hardware composer on the device supports display modes with 583 * a higher refresh rate than the default value specified here, the framework may use those 584 * higher refresh rate modes if an app chooses one by setting preferredDisplayModeId or calling 585 * setFrameRate(). We have historically allowed fallback to mDefaultPeakRefreshRate if 586 * mDefaultRefreshRate is set to 0, but this is not supported anymore. 587 */ 588 private int mDefaultRefreshRate = DEFAULT_REFRESH_RATE; 589 590 /** 591 * Default refresh rate while the device has high brightness mode enabled for HDR. 592 */ 593 private int mDefaultRefreshRateInHbmHdr = DEFAULT_REFRESH_RATE_IN_HBM; 594 595 /** 596 * Default refresh rate while the device has high brightness mode enabled for Sunlight. 597 */ 598 private int mDefaultRefreshRateInHbmSunlight = DEFAULT_REFRESH_RATE_IN_HBM; 599 /** 600 * Default refresh rate in the high zone defined by brightness and ambient thresholds. 601 * If non-positive, then the refresh rate is unchanged even if thresholds are configured. 602 */ 603 private int mDefaultHighBlockingZoneRefreshRate = DEFAULT_HIGH_REFRESH_RATE; 604 605 /** 606 * Default refresh rate in the zone defined by brightness and ambient thresholds. 607 * If non-positive, then the refresh rate is unchanged even if thresholds are configured. 608 */ 609 private int mDefaultLowBlockingZoneRefreshRate = DEFAULT_LOW_REFRESH_RATE; 610 611 /** 612 * The display uses different gamma curves for different refresh rates. It's hard for panel 613 * vendors to tune the curves to have exact same brightness for different refresh rate. So 614 * brightness flickers could be observed at switch time. The issue is worse at the gamma lower 615 * end. In addition, human eyes are more sensitive to the flicker at darker environment. To 616 * prevent flicker, we only support higher refresh rates if the display brightness is above a 617 * threshold. For example, no higher refresh rate if display brightness <= disp0 && ambient 618 * brightness <= amb0 || display brightness <= disp1 && ambient brightness <= amb1 619 */ 620 private int[] mLowDisplayBrightnessThresholds = DEFAULT_BRIGHTNESS_THRESHOLDS; 621 private int[] mLowAmbientBrightnessThresholds = DEFAULT_BRIGHTNESS_THRESHOLDS; 622 623 /** 624 * The display uses different gamma curves for different refresh rates. It's hard for panel 625 * vendors to tune the curves to have exact same brightness for different refresh rate. So 626 * brightness flickers could be observed at switch time. The issue can be observed on the screen 627 * with even full white content at the high brightness. To prevent flickering, we support fixed 628 * refresh rates if the display and ambient brightness are equal to or above the provided 629 * thresholds. You can define multiple threshold levels as higher brightness environments may 630 * have lower display brightness requirements for the flickering is visible. For example, fixed 631 * refresh rate if display brightness >= disp0 && ambient brightness >= amb0 || display 632 * brightness >= disp1 && ambient brightness >= amb1 633 */ 634 private int[] mHighDisplayBrightnessThresholds = DEFAULT_BRIGHTNESS_THRESHOLDS; 635 private int[] mHighAmbientBrightnessThresholds = DEFAULT_BRIGHTNESS_THRESHOLDS; 636 637 // Brightness Throttling data may be updated via the DeviceConfig. Here we store the original 638 // data, which comes from the ddc, and the current one, which may be the DeviceConfig 639 // overwritten value. 640 private BrightnessThrottlingData mBrightnessThrottlingData; 641 private BrightnessThrottlingData mOriginalBrightnessThrottlingData; 642 643 @VisibleForTesting DisplayDeviceConfig(Context context)644 DisplayDeviceConfig(Context context) { 645 mContext = context; 646 } 647 648 /** 649 * Creates an instance for the specified display. Tries to find a file with identifier in the 650 * following priority order: 651 * <ol> 652 * <li>physicalDisplayId</li> 653 * <li>physicalDisplayId without a stable flag (old system)</li> 654 * <li>portId</li> 655 * </ol> 656 * 657 * @param physicalDisplayId The display ID for which to load the configuration. 658 * @return A configuration instance for the specified display. 659 */ create(Context context, long physicalDisplayId, boolean isFirstDisplay)660 public static DisplayDeviceConfig create(Context context, long physicalDisplayId, 661 boolean isFirstDisplay) { 662 final DisplayDeviceConfig config = createWithoutDefaultValues(context, physicalDisplayId, 663 isFirstDisplay); 664 665 config.copyUninitializedValuesFromSecondaryConfig(loadDefaultConfigurationXml(context)); 666 return config; 667 } 668 669 /** 670 * Creates an instance using global values since no display device config xml exists. Uses 671 * values from config or PowerManager. 672 * 673 * @param context The context from which the DisplayDeviceConfig is to be constructed. 674 * @param useConfigXml A flag indicating if values are to be loaded from the configuration file, 675 * or the default values. 676 * @return A configuration instance. 677 */ create(Context context, boolean useConfigXml)678 public static DisplayDeviceConfig create(Context context, boolean useConfigXml) { 679 final DisplayDeviceConfig config; 680 if (useConfigXml) { 681 config = getConfigFromGlobalXml(context); 682 } else { 683 config = getConfigFromPmValues(context); 684 } 685 return config; 686 } 687 createWithoutDefaultValues(Context context, long physicalDisplayId, boolean isFirstDisplay)688 private static DisplayDeviceConfig createWithoutDefaultValues(Context context, 689 long physicalDisplayId, boolean isFirstDisplay) { 690 DisplayDeviceConfig config; 691 692 config = loadConfigFromDirectory(context, Environment.getProductDirectory(), 693 physicalDisplayId); 694 if (config != null) { 695 return config; 696 } 697 698 config = loadConfigFromDirectory(context, Environment.getVendorDirectory(), 699 physicalDisplayId); 700 if (config != null) { 701 return config; 702 } 703 704 // If no config can be loaded from any ddc xml at all, 705 // prepare a whole config using the global config.xml. 706 // Guaranteed not null 707 return create(context, isFirstDisplay); 708 } 709 loadDefaultConfigurationXml(Context context)710 private static DisplayConfiguration loadDefaultConfigurationXml(Context context) { 711 List<File> defaultXmlLocations = new ArrayList<>(); 712 defaultXmlLocations.add(Environment.buildPath(Environment.getProductDirectory(), 713 ETC_DIR, DISPLAY_CONFIG_DIR, DEFAULT_CONFIG_FILE)); 714 defaultXmlLocations.add(Environment.buildPath(Environment.getVendorDirectory(), 715 ETC_DIR, DISPLAY_CONFIG_DIR, DEFAULT_CONFIG_FILE)); 716 717 // Read config_defaultUiModeType directly because UiModeManager hasn't started yet. 718 final int uiModeType = context.getResources() 719 .getInteger(com.android.internal.R.integer.config_defaultUiModeType); 720 final String uiModeTypeStr = Configuration.getUiModeTypeString(uiModeType); 721 if (uiModeTypeStr != null) { 722 defaultXmlLocations.add(Environment.buildPath(Environment.getRootDirectory(), 723 ETC_DIR, DISPLAY_CONFIG_DIR, 724 String.format(DEFAULT_CONFIG_FILE_WITH_UIMODE_FORMAT, uiModeTypeStr))); 725 } 726 defaultXmlLocations.add(Environment.buildPath(Environment.getRootDirectory(), 727 ETC_DIR, DISPLAY_CONFIG_DIR, DEFAULT_CONFIG_FILE)); 728 729 final File configFile = getFirstExistingFile(defaultXmlLocations); 730 if (configFile == null) { 731 // Display configuration files aren't required to exist. 732 return null; 733 } 734 735 DisplayConfiguration defaultConfig = null; 736 737 try (InputStream in = new BufferedInputStream(new FileInputStream(configFile))) { 738 defaultConfig = XmlParser.read(in); 739 if (defaultConfig == null) { 740 Slog.i(TAG, "Default DisplayDeviceConfig file is null"); 741 } 742 } catch (IOException | DatatypeConfigurationException | XmlPullParserException e) { 743 Slog.e(TAG, "Encountered an error while reading/parsing display config file: " 744 + configFile, e); 745 } 746 747 return defaultConfig; 748 } 749 getFirstExistingFile(Collection<File> files)750 private static File getFirstExistingFile(Collection<File> files) { 751 for (File file : files) { 752 if (file.exists() && file.isFile()) { 753 return file; 754 } 755 } 756 return null; 757 } 758 loadConfigFromDirectory(Context context, File baseDirectory, long physicalDisplayId)759 private static DisplayDeviceConfig loadConfigFromDirectory(Context context, 760 File baseDirectory, long physicalDisplayId) { 761 DisplayDeviceConfig config; 762 // Create config using filename from physical ID (including "stable" bit). 763 config = getConfigFromSuffix(context, baseDirectory, STABLE_ID_SUFFIX_FORMAT, 764 physicalDisplayId); 765 if (config != null) { 766 return config; 767 } 768 769 // Create config using filename from physical ID (excluding "stable" bit). 770 final long withoutStableFlag = physicalDisplayId & ~STABLE_FLAG; 771 config = getConfigFromSuffix(context, baseDirectory, NO_SUFFIX_FORMAT, withoutStableFlag); 772 if (config != null) { 773 return config; 774 } 775 776 // Create config using filename from port ID. 777 final DisplayAddress.Physical physicalAddress = 778 DisplayAddress.fromPhysicalDisplayId(physicalDisplayId); 779 int port = physicalAddress.getPort(); 780 config = getConfigFromSuffix(context, baseDirectory, PORT_SUFFIX_FORMAT, port); 781 return config; 782 } 783 setBrightnessThrottlingData(BrightnessThrottlingData brightnessThrottlingData)784 void setBrightnessThrottlingData(BrightnessThrottlingData brightnessThrottlingData) { 785 mBrightnessThrottlingData = brightnessThrottlingData; 786 } 787 788 /** 789 * Return the brightness mapping nits array. 790 * 791 * @return The brightness mapping nits array. 792 */ getNits()793 public float[] getNits() { 794 return mNits; 795 } 796 797 /** 798 * Return the brightness mapping backlight array. 799 * 800 * @return The backlight mapping value array. 801 */ getBacklight()802 public float[] getBacklight() { 803 return mBacklight; 804 } 805 806 /** 807 * Calculates the backlight value, as recognised by the HAL, from the brightness value given 808 * that the rest of the system deals with. 809 * 810 * @param brightness value on the framework scale of 0-1 811 * @return backlight value on the HAL scale of 0-1 812 */ getBacklightFromBrightness(float brightness)813 public float getBacklightFromBrightness(float brightness) { 814 return mBrightnessToBacklightSpline.interpolate(brightness); 815 } 816 817 /** 818 * Calculates the nits value for the specified backlight value if a mapping exists. 819 * 820 * @return The mapped nits or 0 if no mapping exits. 821 */ getNitsFromBacklight(float backlight)822 public float getNitsFromBacklight(float backlight) { 823 if (mBacklightToNitsSpline == null) { 824 Slog.wtf(TAG, "requesting nits when no mapping exists."); 825 return NITS_INVALID; 826 } 827 backlight = Math.max(backlight, mBacklightMinimum); 828 return mBacklightToNitsSpline.interpolate(backlight); 829 } 830 831 /** 832 * Calculate the HDR brightness for the specified SDR brightenss. 833 * 834 * @return the HDR brightness or BRIGHTNESS_INVALID when no mapping exists. 835 */ getHdrBrightnessFromSdr(float brightness)836 public float getHdrBrightnessFromSdr(float brightness) { 837 if (mSdrToHdrRatioSpline == null) { 838 return PowerManager.BRIGHTNESS_INVALID; 839 } 840 841 float backlight = getBacklightFromBrightness(brightness); 842 float nits = getNitsFromBacklight(backlight); 843 if (nits == NITS_INVALID) { 844 return PowerManager.BRIGHTNESS_INVALID; 845 } 846 847 float ratio = mSdrToHdrRatioSpline.interpolate(nits); 848 float hdrNits = nits * ratio; 849 if (mNitsToBacklightSpline == null) { 850 return PowerManager.BRIGHTNESS_INVALID; 851 } 852 853 float hdrBacklight = mNitsToBacklightSpline.interpolate(hdrNits); 854 hdrBacklight = Math.max(mBacklightMinimum, Math.min(mBacklightMaximum, hdrBacklight)); 855 float hdrBrightness = mBacklightToBrightnessSpline.interpolate(hdrBacklight); 856 857 if (DEBUG) { 858 Slog.d(TAG, "getHdrBrightnessFromSdr: sdr brightness " + brightness 859 + " backlight " + backlight 860 + " nits " + nits 861 + " ratio " + ratio 862 + " hdrNits " + hdrNits 863 + " hdrBacklight " + hdrBacklight 864 + " hdrBrightness " + hdrBrightness 865 ); 866 } 867 return hdrBrightness; 868 } 869 870 /** 871 * Return an array of equal length to backlight and nits, that covers the entire system 872 * brightness range of 0.0-1.0. 873 * 874 * @return brightness array 875 */ getBrightness()876 public float[] getBrightness() { 877 return mBrightness; 878 } 879 880 /** 881 * Return the default brightness on a scale of 0.0f - 1.0f 882 * 883 * @return default brightness 884 */ getBrightnessDefault()885 public float getBrightnessDefault() { 886 return mBrightnessDefault; 887 } 888 getBrightnessRampFastDecrease()889 public float getBrightnessRampFastDecrease() { 890 return mBrightnessRampFastDecrease; 891 } 892 getBrightnessRampFastIncrease()893 public float getBrightnessRampFastIncrease() { 894 return mBrightnessRampFastIncrease; 895 } 896 getBrightnessRampSlowDecrease()897 public float getBrightnessRampSlowDecrease() { 898 return mBrightnessRampSlowDecrease; 899 } 900 getBrightnessRampSlowIncrease()901 public float getBrightnessRampSlowIncrease() { 902 return mBrightnessRampSlowIncrease; 903 } 904 getBrightnessRampDecreaseMaxMillis()905 public long getBrightnessRampDecreaseMaxMillis() { 906 return mBrightnessRampDecreaseMaxMillis; 907 } 908 getBrightnessRampIncreaseMaxMillis()909 public long getBrightnessRampIncreaseMaxMillis() { 910 return mBrightnessRampIncreaseMaxMillis; 911 } 912 getAmbientHorizonLong()913 public int getAmbientHorizonLong() { 914 return mAmbientHorizonLong; 915 } 916 getAmbientHorizonShort()917 public int getAmbientHorizonShort() { 918 return mAmbientHorizonShort; 919 } 920 921 /** 922 * The minimum value for the screen brightness increase to actually occur. 923 * @return float value in brightness scale of 0 - 1. 924 */ getScreenBrighteningMinThreshold()925 public float getScreenBrighteningMinThreshold() { 926 return mScreenBrighteningMinThreshold; 927 } 928 929 /** 930 * The minimum value for the screen brightness decrease to actually occur. 931 * @return float value in brightness scale of 0 - 1. 932 */ getScreenDarkeningMinThreshold()933 public float getScreenDarkeningMinThreshold() { 934 return mScreenDarkeningMinThreshold; 935 } 936 937 /** 938 * The minimum value for the screen brightness increase to actually occur while in idle screen 939 * brightness mode. 940 * @return float value in brightness scale of 0 - 1. 941 */ getScreenBrighteningMinThresholdIdle()942 public float getScreenBrighteningMinThresholdIdle() { 943 return mScreenBrighteningMinThresholdIdle; 944 } 945 946 /** 947 * The minimum value for the screen brightness decrease to actually occur while in idle screen 948 * brightness mode. 949 * @return float value in brightness scale of 0 - 1. 950 */ getScreenDarkeningMinThresholdIdle()951 public float getScreenDarkeningMinThresholdIdle() { 952 return mScreenDarkeningMinThresholdIdle; 953 } 954 955 /** 956 * The minimum value for the ambient lux increase for a screen brightness change to actually 957 * occur. 958 * @return float value in lux. 959 */ getAmbientLuxBrighteningMinThreshold()960 public float getAmbientLuxBrighteningMinThreshold() { 961 return mAmbientLuxBrighteningMinThreshold; 962 } 963 964 /** 965 * The minimum value for the ambient lux decrease for a screen brightness change to actually 966 * occur. 967 * @return float value in lux. 968 */ getAmbientLuxDarkeningMinThreshold()969 public float getAmbientLuxDarkeningMinThreshold() { 970 return mAmbientLuxDarkeningMinThreshold; 971 } 972 973 /** 974 * The minimum value for the ambient lux increase for a screen brightness change to actually 975 * occur while in idle screen brightness mode. 976 * @return float value in lux. 977 */ getAmbientLuxBrighteningMinThresholdIdle()978 public float getAmbientLuxBrighteningMinThresholdIdle() { 979 return mAmbientLuxBrighteningMinThresholdIdle; 980 } 981 982 /** 983 * The minimum value for the ambient lux decrease for a screen brightness change to actually 984 * occur while in idle screen brightness mode. 985 * @return float value in lux. 986 */ getAmbientLuxDarkeningMinThresholdIdle()987 public float getAmbientLuxDarkeningMinThresholdIdle() { 988 return mAmbientLuxDarkeningMinThresholdIdle; 989 } 990 991 /** 992 * The array that describes the range of screen brightness that each threshold percentage 993 * applies within. 994 * 995 * The (zero-based) index is calculated as follows 996 * value = current screen brightness value 997 * level = mScreenBrighteningLevels 998 * 999 * condition return 1000 * value < level[0] = 0.0f 1001 * level[n] <= value < level[n+1] = mScreenBrighteningPercentages[n] 1002 * level[MAX] <= value = mScreenBrighteningPercentages[MAX] 1003 * 1004 * @return the screen brightness levels between 0.0 and 1.0 for which each 1005 * mScreenBrighteningPercentages applies 1006 */ getScreenBrighteningLevels()1007 public float[] getScreenBrighteningLevels() { 1008 return mScreenBrighteningLevels; 1009 } 1010 1011 /** 1012 * The array that describes the screen brightening threshold percentage change at each screen 1013 * brightness level described in mScreenBrighteningLevels. 1014 * 1015 * @return the percentages between 0 and 100 of brightness increase required in order for the 1016 * screen brightness to change 1017 */ getScreenBrighteningPercentages()1018 public float[] getScreenBrighteningPercentages() { 1019 return mScreenBrighteningPercentages; 1020 } 1021 1022 /** 1023 * The array that describes the range of screen brightness that each threshold percentage 1024 * applies within. 1025 * 1026 * The (zero-based) index is calculated as follows 1027 * value = current screen brightness value 1028 * level = mScreenDarkeningLevels 1029 * 1030 * condition return 1031 * value < level[0] = 0.0f 1032 * level[n] <= value < level[n+1] = mScreenDarkeningPercentages[n] 1033 * level[MAX] <= value = mScreenDarkeningPercentages[MAX] 1034 * 1035 * @return the screen brightness levels between 0.0 and 1.0 for which each 1036 * mScreenDarkeningPercentages applies 1037 */ getScreenDarkeningLevels()1038 public float[] getScreenDarkeningLevels() { 1039 return mScreenDarkeningLevels; 1040 } 1041 1042 /** 1043 * The array that describes the screen darkening threshold percentage change at each screen 1044 * brightness level described in mScreenDarkeningLevels. 1045 * 1046 * @return the percentages between 0 and 100 of brightness decrease required in order for the 1047 * screen brightness to change 1048 */ getScreenDarkeningPercentages()1049 public float[] getScreenDarkeningPercentages() { 1050 return mScreenDarkeningPercentages; 1051 } 1052 1053 /** 1054 * The array that describes the range of ambient brightness that each threshold 1055 * percentage applies within. 1056 * 1057 * The (zero-based) index is calculated as follows 1058 * value = current ambient brightness value 1059 * level = mAmbientBrighteningLevels 1060 * 1061 * condition return 1062 * value < level[0] = 0.0f 1063 * level[n] <= value < level[n+1] = mAmbientBrighteningPercentages[n] 1064 * level[MAX] <= value = mAmbientBrighteningPercentages[MAX] 1065 * 1066 * @return the ambient brightness levels from 0 lux upwards for which each 1067 * mAmbientBrighteningPercentages applies 1068 */ getAmbientBrighteningLevels()1069 public float[] getAmbientBrighteningLevels() { 1070 return mAmbientBrighteningLevels; 1071 } 1072 1073 /** 1074 * The array that describes the ambient brightening threshold percentage change at each ambient 1075 * brightness level described in mAmbientBrighteningLevels. 1076 * 1077 * @return the percentages between 0 and 100 of brightness increase required in order for the 1078 * screen brightness to change 1079 */ getAmbientBrighteningPercentages()1080 public float[] getAmbientBrighteningPercentages() { 1081 return mAmbientBrighteningPercentages; 1082 } 1083 1084 /** 1085 * The array that describes the range of ambient brightness that each threshold percentage 1086 * applies within. 1087 * 1088 * The (zero-based) index is calculated as follows 1089 * value = current ambient brightness value 1090 * level = mAmbientDarkeningLevels 1091 * 1092 * condition return 1093 * value < level[0] = 0.0f 1094 * level[n] <= value < level[n+1] = mAmbientDarkeningPercentages[n] 1095 * level[MAX] <= value = mAmbientDarkeningPercentages[MAX] 1096 * 1097 * @return the ambient brightness levels from 0 lux upwards for which each 1098 * mAmbientDarkeningPercentages applies 1099 */ getAmbientDarkeningLevels()1100 public float[] getAmbientDarkeningLevels() { 1101 return mAmbientDarkeningLevels; 1102 } 1103 1104 /** 1105 * The array that describes the ambient darkening threshold percentage change at each ambient 1106 * brightness level described in mAmbientDarkeningLevels. 1107 * 1108 * @return the percentages between 0 and 100 of brightness decrease required in order for the 1109 * screen brightness to change 1110 */ getAmbientDarkeningPercentages()1111 public float[] getAmbientDarkeningPercentages() { 1112 return mAmbientDarkeningPercentages; 1113 } 1114 1115 /** 1116 * The array that describes the range of screen brightness that each threshold percentage 1117 * applies within whilst in idle screen brightness mode. 1118 * 1119 * The (zero-based) index is calculated as follows 1120 * value = current screen brightness value 1121 * level = mScreenBrighteningLevelsIdle 1122 * 1123 * condition return 1124 * value < level[0] = 0.0f 1125 * level[n] <= value < level[n+1] = mScreenBrighteningPercentagesIdle[n] 1126 * level[MAX] <= value = mScreenBrighteningPercentagesIdle[MAX] 1127 * 1128 * @return the screen brightness levels between 0.0 and 1.0 for which each 1129 * mScreenBrighteningPercentagesIdle applies 1130 */ getScreenBrighteningLevelsIdle()1131 public float[] getScreenBrighteningLevelsIdle() { 1132 return mScreenBrighteningLevelsIdle; 1133 } 1134 1135 /** 1136 * The array that describes the screen brightening threshold percentage change at each screen 1137 * brightness level described in mScreenBrighteningLevelsIdle. 1138 * 1139 * @return the percentages between 0 and 100 of brightness increase required in order for the 1140 * screen brightness to change while in idle mode. 1141 */ getScreenBrighteningPercentagesIdle()1142 public float[] getScreenBrighteningPercentagesIdle() { 1143 return mScreenBrighteningPercentagesIdle; 1144 } 1145 1146 /** 1147 * The array that describes the range of screen brightness that each threshold percentage 1148 * applies within whilst in idle screen brightness mode. 1149 * 1150 * The (zero-based) index is calculated as follows 1151 * value = current screen brightness value 1152 * level = mScreenDarkeningLevelsIdle 1153 * 1154 * condition return 1155 * value < level[0] = 0.0f 1156 * level[n] <= value < level[n+1] = mScreenDarkeningPercentagesIdle[n] 1157 * level[MAX] <= value = mScreenDarkeningPercentagesIdle[MAX] 1158 * 1159 * @return the screen brightness levels between 0.0 and 1.0 for which each 1160 * mScreenDarkeningPercentagesIdle applies 1161 */ getScreenDarkeningLevelsIdle()1162 public float[] getScreenDarkeningLevelsIdle() { 1163 return mScreenDarkeningLevelsIdle; 1164 } 1165 1166 /** 1167 * The array that describes the screen darkening threshold percentage change at each screen 1168 * brightness level described in mScreenDarkeningLevelsIdle. 1169 * 1170 * @return the percentages between 0 and 100 of brightness decrease required in order for the 1171 * screen brightness to change while in idle mode. 1172 */ getScreenDarkeningPercentagesIdle()1173 public float[] getScreenDarkeningPercentagesIdle() { 1174 return mScreenDarkeningPercentagesIdle; 1175 } 1176 1177 /** 1178 * The array that describes the range of ambient brightness that each threshold percentage 1179 * applies within whilst in idle screen brightness mode. 1180 * 1181 * The (zero-based) index is calculated as follows 1182 * value = current ambient brightness value 1183 * level = mAmbientBrighteningLevelsIdle 1184 * 1185 * condition return 1186 * value < level[0] = 0.0f 1187 * level[n] <= value < level[n+1] = mAmbientBrighteningPercentagesIdle[n] 1188 * level[MAX] <= value = mAmbientBrighteningPercentagesIdle[MAX] 1189 * 1190 * @return the ambient brightness levels from 0 lux upwards for which each 1191 * mAmbientBrighteningPercentagesIdle applies 1192 */ getAmbientBrighteningLevelsIdle()1193 public float[] getAmbientBrighteningLevelsIdle() { 1194 return mAmbientBrighteningLevelsIdle; 1195 } 1196 1197 /** 1198 * The array that describes the ambient brightness threshold percentage change whilst in 1199 * idle screen brightness mode at each ambient brightness level described in 1200 * mAmbientBrighteningLevelsIdle. 1201 * 1202 * @return the percentages between 0 and 100 of ambient brightness increase required in order 1203 * for the screen brightness to change 1204 */ getAmbientBrighteningPercentagesIdle()1205 public float[] getAmbientBrighteningPercentagesIdle() { 1206 return mAmbientBrighteningPercentagesIdle; 1207 } 1208 1209 /** 1210 * The array that describes the range of ambient brightness that each threshold percentage 1211 * applies within whilst in idle screen brightness mode. 1212 * 1213 * The (zero-based) index is calculated as follows 1214 * value = current ambient brightness value 1215 * level = mAmbientDarkeningLevelsIdle 1216 * 1217 * condition return 1218 * value < level[0] = 0.0f 1219 * level[n] <= value < level[n+1] = mAmbientDarkeningPercentagesIdle[n] 1220 * level[MAX] <= value = mAmbientDarkeningPercentagesIdle[MAX] 1221 * 1222 * @return the ambient brightness levels from 0 lux upwards for which each 1223 * mAmbientDarkeningPercentagesIdle applies 1224 */ getAmbientDarkeningLevelsIdle()1225 public float[] getAmbientDarkeningLevelsIdle() { 1226 return mAmbientDarkeningLevelsIdle; 1227 } 1228 1229 /** 1230 * The array that describes the ambient brightness threshold percentage change whilst in 1231 * idle screen brightness mode at each ambient brightness level described in 1232 * mAmbientDarkeningLevelsIdle. 1233 * 1234 * @return the percentages between 0 and 100 of ambient brightness decrease required in order 1235 * for the screen brightness to change 1236 */ getAmbientDarkeningPercentagesIdle()1237 public float[] getAmbientDarkeningPercentagesIdle() { 1238 return mAmbientDarkeningPercentagesIdle; 1239 } 1240 getAmbientLightSensor()1241 SensorData getAmbientLightSensor() { 1242 return mAmbientLightSensor; 1243 } 1244 getScreenOffBrightnessSensor()1245 SensorData getScreenOffBrightnessSensor() { 1246 return mScreenOffBrightnessSensor; 1247 } 1248 getProximitySensor()1249 SensorData getProximitySensor() { 1250 return mProximitySensor; 1251 } 1252 isAutoBrightnessAvailable()1253 boolean isAutoBrightnessAvailable() { 1254 return mAutoBrightnessAvailable; 1255 } 1256 1257 /** 1258 * @param quirkValue The quirk to test. 1259 * @return {@code true} if the specified quirk is present in this configuration, {@code false} 1260 * otherwise. 1261 */ hasQuirk(String quirkValue)1262 public boolean hasQuirk(String quirkValue) { 1263 return mQuirks != null && mQuirks.contains(quirkValue); 1264 } 1265 1266 /** 1267 * @return high brightness mode configuration data for the display. 1268 */ getHighBrightnessModeData()1269 public HighBrightnessModeData getHighBrightnessModeData() { 1270 if (!mIsHighBrightnessModeEnabled || mHbmData == null) { 1271 return null; 1272 } 1273 1274 HighBrightnessModeData hbmData = new HighBrightnessModeData(); 1275 mHbmData.copyTo(hbmData); 1276 return hbmData; 1277 } 1278 getRefreshRateLimitations()1279 public List<RefreshRateLimitation> getRefreshRateLimitations() { 1280 return mRefreshRateLimitations; 1281 } 1282 getDensityMapping()1283 public DensityMapping getDensityMapping() { 1284 return mDensityMapping; 1285 } 1286 1287 /** 1288 * @return brightness throttling data configuration data for the display. 1289 */ getBrightnessThrottlingData()1290 public BrightnessThrottlingData getBrightnessThrottlingData() { 1291 return BrightnessThrottlingData.create(mBrightnessThrottlingData); 1292 } 1293 1294 /** 1295 * @return Auto brightness darkening light debounce 1296 */ getAutoBrightnessDarkeningLightDebounce()1297 public long getAutoBrightnessDarkeningLightDebounce() { 1298 return mAutoBrightnessDarkeningLightDebounce; 1299 } 1300 1301 /** 1302 * @return Auto brightness brightening light debounce 1303 */ getAutoBrightnessBrighteningLightDebounce()1304 public long getAutoBrightnessBrighteningLightDebounce() { 1305 return mAutoBrightnessBrighteningLightDebounce; 1306 } 1307 1308 /** 1309 * @return Auto brightness brightening ambient lux levels 1310 */ getAutoBrightnessBrighteningLevelsLux()1311 public float[] getAutoBrightnessBrighteningLevelsLux() { 1312 return mBrightnessLevelsLux; 1313 } 1314 1315 /** 1316 * @return Auto brightness brightening nits levels 1317 */ getAutoBrightnessBrighteningLevelsNits()1318 public float[] getAutoBrightnessBrighteningLevelsNits() { 1319 return mBrightnessLevelsNits; 1320 } 1321 1322 /** 1323 * @return Default peak refresh rate of the associated display 1324 */ getDefaultPeakRefreshRate()1325 public int getDefaultPeakRefreshRate() { 1326 return mDefaultPeakRefreshRate; 1327 } 1328 1329 /** 1330 * @return Default refresh rate of the associated display 1331 */ getDefaultRefreshRate()1332 public int getDefaultRefreshRate() { 1333 return mDefaultRefreshRate; 1334 } 1335 1336 /** 1337 * @return Default refresh rate while the device has high brightness mode enabled for HDR. 1338 */ getDefaultRefreshRateInHbmHdr()1339 public int getDefaultRefreshRateInHbmHdr() { 1340 return mDefaultRefreshRateInHbmHdr; 1341 } 1342 1343 /** 1344 * @return Default refresh rate while the device has high brightness mode enabled because of 1345 * high lux. 1346 */ getDefaultRefreshRateInHbmSunlight()1347 public int getDefaultRefreshRateInHbmSunlight() { 1348 return mDefaultRefreshRateInHbmSunlight; 1349 } 1350 1351 /** 1352 * @return Default refresh rate in the higher blocking zone of the associated display 1353 */ getDefaultHighBlockingZoneRefreshRate()1354 public int getDefaultHighBlockingZoneRefreshRate() { 1355 return mDefaultHighBlockingZoneRefreshRate; 1356 } 1357 1358 /** 1359 * @return Default refresh rate in the lower blocking zone of the associated display 1360 */ getDefaultLowBlockingZoneRefreshRate()1361 public int getDefaultLowBlockingZoneRefreshRate() { 1362 return mDefaultLowBlockingZoneRefreshRate; 1363 } 1364 1365 /** 1366 * @return An array of lower display brightness thresholds. This, in combination with lower 1367 * ambient brightness thresholds help define buckets in which the refresh rate switching is not 1368 * allowed 1369 */ getLowDisplayBrightnessThresholds()1370 public int[] getLowDisplayBrightnessThresholds() { 1371 return mLowDisplayBrightnessThresholds; 1372 } 1373 1374 /** 1375 * @return An array of lower ambient brightness thresholds. This, in combination with lower 1376 * display brightness thresholds help define buckets in which the refresh rate switching is not 1377 * allowed 1378 */ getLowAmbientBrightnessThresholds()1379 public int[] getLowAmbientBrightnessThresholds() { 1380 return mLowAmbientBrightnessThresholds; 1381 } 1382 1383 /** 1384 * @return An array of high display brightness thresholds. This, in combination with high 1385 * ambient brightness thresholds help define buckets in which the refresh rate switching is not 1386 * allowed 1387 */ getHighDisplayBrightnessThresholds()1388 public int[] getHighDisplayBrightnessThresholds() { 1389 return mHighDisplayBrightnessThresholds; 1390 } 1391 1392 /** 1393 * @return An array of high ambient brightness thresholds. This, in combination with high 1394 * display brightness thresholds help define buckets in which the refresh rate switching is not 1395 * allowed 1396 */ getHighAmbientBrightnessThresholds()1397 public int[] getHighAmbientBrightnessThresholds() { 1398 return mHighAmbientBrightnessThresholds; 1399 } 1400 1401 /** 1402 * @return A mapping from screen off brightness sensor readings to lux values. This estimates 1403 * the ambient lux when the screen is off to determine the initial brightness 1404 */ getScreenOffBrightnessSensorValueToLux()1405 public int[] getScreenOffBrightnessSensorValueToLux() { 1406 return mScreenOffBrightnessSensorValueToLux; 1407 } 1408 1409 @Override toString()1410 public String toString() { 1411 return "DisplayDeviceConfig{" 1412 + "mLoadedFrom=" + mLoadedFrom 1413 + ", mBacklight=" + Arrays.toString(mBacklight) 1414 + ", mNits=" + Arrays.toString(mNits) 1415 + ", mRawBacklight=" + Arrays.toString(mRawBacklight) 1416 + ", mRawNits=" + Arrays.toString(mRawNits) 1417 + ", mInterpolationType=" + mInterpolationType 1418 + ", mBrightness=" + Arrays.toString(mBrightness) 1419 + ", mBrightnessToBacklightSpline=" + mBrightnessToBacklightSpline 1420 + ", mBacklightToBrightnessSpline=" + mBacklightToBrightnessSpline 1421 + ", mNitsToBacklightSpline=" + mNitsToBacklightSpline 1422 + ", mBacklightMinimum=" + mBacklightMinimum 1423 + ", mBacklightMaximum=" + mBacklightMaximum 1424 + ", mBrightnessDefault=" + mBrightnessDefault 1425 + ", mQuirks=" + mQuirks 1426 + ", isHbmEnabled=" + mIsHighBrightnessModeEnabled 1427 + ", mHbmData=" + mHbmData 1428 + ", mSdrToHdrRatioSpline=" + mSdrToHdrRatioSpline 1429 + ", mBrightnessThrottlingData=" + mBrightnessThrottlingData 1430 + ", mOriginalBrightnessThrottlingData=" + mOriginalBrightnessThrottlingData 1431 + "\n" 1432 + ", mBrightnessRampFastDecrease=" + mBrightnessRampFastDecrease 1433 + ", mBrightnessRampFastIncrease=" + mBrightnessRampFastIncrease 1434 + ", mBrightnessRampSlowDecrease=" + mBrightnessRampSlowDecrease 1435 + ", mBrightnessRampSlowIncrease=" + mBrightnessRampSlowIncrease 1436 + ", mBrightnessRampDecreaseMaxMillis=" + mBrightnessRampDecreaseMaxMillis 1437 + ", mBrightnessRampIncreaseMaxMillis=" + mBrightnessRampIncreaseMaxMillis 1438 + "\n" 1439 + ", mAmbientHorizonLong=" + mAmbientHorizonLong 1440 + ", mAmbientHorizonShort=" + mAmbientHorizonShort 1441 + "\n" 1442 + ", mScreenDarkeningMinThreshold=" + mScreenDarkeningMinThreshold 1443 + ", mScreenDarkeningMinThresholdIdle=" + mScreenDarkeningMinThresholdIdle 1444 + ", mScreenBrighteningMinThreshold=" + mScreenBrighteningMinThreshold 1445 + ", mScreenBrighteningMinThresholdIdle=" + mScreenBrighteningMinThresholdIdle 1446 + ", mAmbientLuxDarkeningMinThreshold=" + mAmbientLuxDarkeningMinThreshold 1447 + ", mAmbientLuxDarkeningMinThresholdIdle=" + mAmbientLuxDarkeningMinThresholdIdle 1448 + ", mAmbientLuxBrighteningMinThreshold=" + mAmbientLuxBrighteningMinThreshold 1449 + ", mAmbientLuxBrighteningMinThresholdIdle=" 1450 + mAmbientLuxBrighteningMinThresholdIdle 1451 + "\n" 1452 + ", mScreenBrighteningLevels=" + Arrays.toString( 1453 mScreenBrighteningLevels) 1454 + ", mScreenBrighteningPercentages=" + Arrays.toString( 1455 mScreenBrighteningPercentages) 1456 + ", mScreenDarkeningLevels=" + Arrays.toString( 1457 mScreenDarkeningLevels) 1458 + ", mScreenDarkeningPercentages=" + Arrays.toString( 1459 mScreenDarkeningPercentages) 1460 + ", mAmbientBrighteningLevels=" + Arrays.toString( 1461 mAmbientBrighteningLevels) 1462 + ", mAmbientBrighteningPercentages=" + Arrays.toString( 1463 mAmbientBrighteningPercentages) 1464 + ", mAmbientDarkeningLevels=" + Arrays.toString( 1465 mAmbientDarkeningLevels) 1466 + ", mAmbientDarkeningPercentages=" + Arrays.toString( 1467 mAmbientDarkeningPercentages) 1468 + "\n" 1469 + ", mAmbientBrighteningLevelsIdle=" + Arrays.toString( 1470 mAmbientBrighteningLevelsIdle) 1471 + ", mAmbientBrighteningPercentagesIdle=" + Arrays.toString( 1472 mAmbientBrighteningPercentagesIdle) 1473 + ", mAmbientDarkeningLevelsIdle=" + Arrays.toString( 1474 mAmbientDarkeningLevelsIdle) 1475 + ", mAmbientDarkeningPercentagesIdle=" + Arrays.toString( 1476 mAmbientDarkeningPercentagesIdle) 1477 + ", mScreenBrighteningLevelsIdle=" + Arrays.toString( 1478 mScreenBrighteningLevelsIdle) 1479 + ", mScreenBrighteningPercentagesIdle=" + Arrays.toString( 1480 mScreenBrighteningPercentagesIdle) 1481 + ", mScreenDarkeningLevelsIdle=" + Arrays.toString( 1482 mScreenDarkeningLevelsIdle) 1483 + ", mScreenDarkeningPercentagesIdle=" + Arrays.toString( 1484 mScreenDarkeningPercentagesIdle) 1485 + "\n" 1486 + ", mAmbientLightSensor=" + mAmbientLightSensor 1487 + ", mScreenOffBrightnessSensor=" + mScreenOffBrightnessSensor 1488 + ", mProximitySensor=" + mProximitySensor 1489 + ", mRefreshRateLimitations= " + Arrays.toString(mRefreshRateLimitations.toArray()) 1490 + ", mDensityMapping= " + mDensityMapping 1491 + ", mAutoBrightnessBrighteningLightDebounce= " 1492 + mAutoBrightnessBrighteningLightDebounce 1493 + ", mAutoBrightnessDarkeningLightDebounce= " 1494 + mAutoBrightnessDarkeningLightDebounce 1495 + ", mBrightnessLevelsLux= " + Arrays.toString(mBrightnessLevelsLux) 1496 + ", mBrightnessLevelsNits= " + Arrays.toString(mBrightnessLevelsNits) 1497 + ", mDdcAutoBrightnessAvailable= " + mDdcAutoBrightnessAvailable 1498 + ", mAutoBrightnessAvailable= " + mAutoBrightnessAvailable 1499 + "\n" 1500 + ", mDefaultLowBlockingZoneRefreshRate= " + mDefaultLowBlockingZoneRefreshRate 1501 + ", mDefaultHighBlockingZoneRefreshRate= " + mDefaultHighBlockingZoneRefreshRate 1502 + ", mDefaultPeakRefreshRate= " + mDefaultPeakRefreshRate 1503 + ", mDefaultRefreshRate= " + mDefaultRefreshRate 1504 + ", mDefaultRefreshRateInHbmHdr= " + mDefaultRefreshRateInHbmHdr 1505 + ", mDefaultRefreshRateInHbmSunlight= " + mDefaultRefreshRateInHbmSunlight 1506 + ", mLowDisplayBrightnessThresholds= " 1507 + Arrays.toString(mLowDisplayBrightnessThresholds) 1508 + ", mLowAmbientBrightnessThresholds= " 1509 + Arrays.toString(mLowAmbientBrightnessThresholds) 1510 + ", mHighDisplayBrightnessThresholds= " 1511 + Arrays.toString(mHighDisplayBrightnessThresholds) 1512 + ", mHighAmbientBrightnessThresholds= " 1513 + Arrays.toString(mHighAmbientBrightnessThresholds) 1514 + "\n" 1515 + ", mScreenOffBrightnessSensorValueToLux=" + Arrays.toString( 1516 mScreenOffBrightnessSensorValueToLux) 1517 + "}"; 1518 } 1519 getConfigFromSuffix(Context context, File baseDirectory, String suffixFormat, long idNumber)1520 private static DisplayDeviceConfig getConfigFromSuffix(Context context, File baseDirectory, 1521 String suffixFormat, long idNumber) { 1522 1523 final String suffix = String.format(Locale.ROOT, suffixFormat, idNumber); 1524 final String filename = String.format(Locale.ROOT, CONFIG_FILE_FORMAT, suffix); 1525 final File filePath = Environment.buildPath( 1526 baseDirectory, ETC_DIR, DISPLAY_CONFIG_DIR, filename); 1527 final DisplayDeviceConfig config = new DisplayDeviceConfig(context); 1528 if (config.initFromFile(filePath)) { 1529 return config; 1530 } 1531 return null; 1532 } 1533 getConfigFromGlobalXml(Context context)1534 private static DisplayDeviceConfig getConfigFromGlobalXml(Context context) { 1535 DisplayDeviceConfig config = new DisplayDeviceConfig(context); 1536 config.initFromGlobalXml(); 1537 return config; 1538 } 1539 getConfigFromPmValues(Context context)1540 private static DisplayDeviceConfig getConfigFromPmValues(Context context) { 1541 DisplayDeviceConfig config = new DisplayDeviceConfig(context); 1542 config.initFromDefaultValues(); 1543 return config; 1544 } 1545 1546 @VisibleForTesting initFromFile(File configFile)1547 boolean initFromFile(File configFile) { 1548 if (!configFile.exists()) { 1549 // Display configuration files aren't required to exist. 1550 return false; 1551 } 1552 1553 if (!configFile.isFile()) { 1554 Slog.e(TAG, "Display configuration is not a file: " + configFile + ", skipping"); 1555 return false; 1556 } 1557 1558 try (InputStream in = new BufferedInputStream(new FileInputStream(configFile))) { 1559 final DisplayConfiguration config = XmlParser.read(in); 1560 if (config != null) { 1561 loadDensityMapping(config); 1562 loadBrightnessDefaultFromDdcXml(config); 1563 loadBrightnessConstraintsFromConfigXml(); 1564 loadBrightnessMap(config); 1565 loadBrightnessThrottlingMap(config); 1566 loadHighBrightnessModeData(config); 1567 loadQuirks(config); 1568 loadBrightnessRamps(config); 1569 loadAmbientLightSensorFromDdc(config); 1570 loadScreenOffBrightnessSensorFromDdc(config); 1571 loadProxSensorFromDdc(config); 1572 loadAmbientHorizonFromDdc(config); 1573 loadBrightnessChangeThresholds(config); 1574 loadAutoBrightnessConfigValues(config); 1575 loadRefreshRateSetting(config); 1576 loadScreenOffBrightnessSensorValueToLuxFromDdc(config); 1577 } else { 1578 Slog.w(TAG, "DisplayDeviceConfig file is null"); 1579 } 1580 } catch (IOException | DatatypeConfigurationException | XmlPullParserException e) { 1581 Slog.e(TAG, "Encountered an error while reading/parsing display config file: " 1582 + configFile, e); 1583 } 1584 mLoadedFrom = configFile.toString(); 1585 return true; 1586 } 1587 initFromGlobalXml()1588 private void initFromGlobalXml() { 1589 // If no ddc exists, use config.xml 1590 loadBrightnessDefaultFromConfigXml(); 1591 loadBrightnessConstraintsFromConfigXml(); 1592 loadBrightnessMapFromConfigXml(); 1593 loadBrightnessRampsFromConfigXml(); 1594 loadAmbientLightSensorFromConfigXml(); 1595 loadBrightnessChangeThresholdsFromXml(); 1596 useFallbackProxSensor(); 1597 loadAutoBrightnessConfigsFromConfigXml(); 1598 loadAutoBrightnessAvailableFromConfigXml(); 1599 loadRefreshRateSetting(null); 1600 mLoadedFrom = "<config.xml>"; 1601 } 1602 initFromDefaultValues()1603 private void initFromDefaultValues() { 1604 // Set all to basic values 1605 mLoadedFrom = "Static values"; 1606 mBacklightMinimum = PowerManager.BRIGHTNESS_MIN; 1607 mBacklightMaximum = PowerManager.BRIGHTNESS_MAX; 1608 mBrightnessDefault = BRIGHTNESS_DEFAULT; 1609 mBrightnessRampFastDecrease = PowerManager.BRIGHTNESS_MAX; 1610 mBrightnessRampFastIncrease = PowerManager.BRIGHTNESS_MAX; 1611 mBrightnessRampSlowDecrease = PowerManager.BRIGHTNESS_MAX; 1612 mBrightnessRampSlowIncrease = PowerManager.BRIGHTNESS_MAX; 1613 mBrightnessRampDecreaseMaxMillis = 0; 1614 mBrightnessRampIncreaseMaxMillis = 0; 1615 setSimpleMappingStrategyValues(); 1616 loadAmbientLightSensorFromConfigXml(); 1617 useFallbackProxSensor(); 1618 loadAutoBrightnessAvailableFromConfigXml(); 1619 } 1620 copyUninitializedValuesFromSecondaryConfig(DisplayConfiguration defaultConfig)1621 private void copyUninitializedValuesFromSecondaryConfig(DisplayConfiguration defaultConfig) { 1622 if (defaultConfig == null) { 1623 return; 1624 } 1625 1626 if (mDensityMapping == null) { 1627 loadDensityMapping(defaultConfig); 1628 } 1629 } 1630 loadDensityMapping(DisplayConfiguration config)1631 private void loadDensityMapping(DisplayConfiguration config) { 1632 if (config.getDensityMapping() == null) { 1633 return; 1634 } 1635 1636 final List<Density> entriesFromXml = config.getDensityMapping().getDensity(); 1637 1638 final DensityMapping.Entry[] entries = 1639 new DensityMapping.Entry[entriesFromXml.size()]; 1640 for (int i = 0; i < entriesFromXml.size(); i++) { 1641 final Density density = entriesFromXml.get(i); 1642 entries[i] = new DensityMapping.Entry( 1643 density.getWidth().intValue(), 1644 density.getHeight().intValue(), 1645 density.getDensity().intValue()); 1646 } 1647 mDensityMapping = DensityMapping.createByOwning(entries); 1648 } 1649 loadBrightnessDefaultFromDdcXml(DisplayConfiguration config)1650 private void loadBrightnessDefaultFromDdcXml(DisplayConfiguration config) { 1651 // Default brightness values are stored in the displayDeviceConfig file, 1652 // Or we fallback standard values if not. 1653 // Priority 1: Value in the displayDeviceConfig 1654 // Priority 2: Value in the config.xml (float) 1655 // Priority 3: Value in the config.xml (int) 1656 if (config != null) { 1657 BigDecimal configBrightnessDefault = config.getScreenBrightnessDefault(); 1658 if (configBrightnessDefault != null) { 1659 mBrightnessDefault = configBrightnessDefault.floatValue(); 1660 } else { 1661 loadBrightnessDefaultFromConfigXml(); 1662 } 1663 } 1664 } 1665 loadBrightnessDefaultFromConfigXml()1666 private void loadBrightnessDefaultFromConfigXml() { 1667 // Priority 1: Value in the config.xml (float) 1668 // Priority 2: Value in the config.xml (int) 1669 final float def = mContext.getResources().getFloat(com.android.internal.R.dimen 1670 .config_screenBrightnessSettingDefaultFloat); 1671 if (def == INVALID_BRIGHTNESS_IN_CONFIG) { 1672 mBrightnessDefault = BrightnessSynchronizer.brightnessIntToFloat( 1673 mContext.getResources().getInteger(com.android.internal.R.integer 1674 .config_screenBrightnessSettingDefault)); 1675 } else { 1676 mBrightnessDefault = def; 1677 } 1678 } 1679 loadBrightnessConstraintsFromConfigXml()1680 private void loadBrightnessConstraintsFromConfigXml() { 1681 // TODO(b/175373898) add constraints (min / max) to ddc. 1682 final float min = mContext.getResources().getFloat(com.android.internal.R.dimen 1683 .config_screenBrightnessSettingMinimumFloat); 1684 final float max = mContext.getResources().getFloat(com.android.internal.R.dimen 1685 .config_screenBrightnessSettingMaximumFloat); 1686 if (min == INVALID_BRIGHTNESS_IN_CONFIG || max == INVALID_BRIGHTNESS_IN_CONFIG) { 1687 mBacklightMinimum = BrightnessSynchronizer.brightnessIntToFloat( 1688 mContext.getResources().getInteger(com.android.internal.R.integer 1689 .config_screenBrightnessSettingMinimum)); 1690 mBacklightMaximum = BrightnessSynchronizer.brightnessIntToFloat( 1691 mContext.getResources().getInteger(com.android.internal.R.integer 1692 .config_screenBrightnessSettingMaximum)); 1693 } else { 1694 mBacklightMinimum = min; 1695 mBacklightMaximum = max; 1696 } 1697 } 1698 loadBrightnessMap(DisplayConfiguration config)1699 private void loadBrightnessMap(DisplayConfiguration config) { 1700 final NitsMap map = config.getScreenBrightnessMap(); 1701 // Map may not exist in display device config 1702 if (map == null) { 1703 loadBrightnessMapFromConfigXml(); 1704 return; 1705 } 1706 1707 // Use the (preferred) display device config mapping 1708 final List<Point> points = map.getPoint(); 1709 final int size = points.size(); 1710 1711 float[] nits = new float[size]; 1712 float[] backlight = new float[size]; 1713 1714 mInterpolationType = convertInterpolationType(map.getInterpolation()); 1715 int i = 0; 1716 for (Point point : points) { 1717 nits[i] = point.getNits().floatValue(); 1718 backlight[i] = point.getValue().floatValue(); 1719 if (i > 0) { 1720 if (nits[i] < nits[i - 1]) { 1721 Slog.e(TAG, "screenBrightnessMap must be non-decreasing, ignoring rest " 1722 + " of configuration. Nits: " + nits[i] + " < " + nits[i - 1]); 1723 return; 1724 } 1725 1726 if (backlight[i] < backlight[i - 1]) { 1727 Slog.e(TAG, "screenBrightnessMap must be non-decreasing, ignoring rest " 1728 + " of configuration. Value: " + backlight[i] + " < " 1729 + backlight[i - 1]); 1730 return; 1731 } 1732 } 1733 ++i; 1734 } 1735 mRawNits = nits; 1736 mRawBacklight = backlight; 1737 constrainNitsAndBacklightArrays(); 1738 } 1739 loadSdrHdrRatioMap(HighBrightnessMode hbmConfig)1740 private Spline loadSdrHdrRatioMap(HighBrightnessMode hbmConfig) { 1741 final SdrHdrRatioMap sdrHdrRatioMap = hbmConfig.getSdrHdrRatioMap_all(); 1742 1743 if (sdrHdrRatioMap == null) { 1744 return null; 1745 } 1746 1747 final List<SdrHdrRatioPoint> points = sdrHdrRatioMap.getPoint(); 1748 final int size = points.size(); 1749 if (size <= 0) { 1750 return null; 1751 } 1752 1753 float[] nits = new float[size]; 1754 float[] ratios = new float[size]; 1755 1756 int i = 0; 1757 for (SdrHdrRatioPoint point : points) { 1758 nits[i] = point.getSdrNits().floatValue(); 1759 if (i > 0) { 1760 if (nits[i] < nits[i - 1]) { 1761 Slog.e(TAG, "sdrHdrRatioMap must be non-decreasing, ignoring rest " 1762 + " of configuration. nits: " + nits[i] + " < " 1763 + nits[i - 1]); 1764 return null; 1765 } 1766 } 1767 ratios[i] = point.getHdrRatio().floatValue(); 1768 ++i; 1769 } 1770 1771 return Spline.createSpline(nits, ratios); 1772 } 1773 loadBrightnessThrottlingMap(DisplayConfiguration config)1774 private void loadBrightnessThrottlingMap(DisplayConfiguration config) { 1775 final ThermalThrottling throttlingConfig = config.getThermalThrottling(); 1776 if (throttlingConfig == null) { 1777 Slog.i(TAG, "no thermal throttling config found"); 1778 return; 1779 } 1780 1781 final BrightnessThrottlingMap map = throttlingConfig.getBrightnessThrottlingMap(); 1782 if (map == null) { 1783 Slog.i(TAG, "no brightness throttling map found"); 1784 return; 1785 } 1786 1787 final List<BrightnessThrottlingPoint> points = map.getBrightnessThrottlingPoint(); 1788 // At least 1 point is guaranteed by the display device config schema 1789 List<BrightnessThrottlingData.ThrottlingLevel> throttlingLevels = 1790 new ArrayList<>(points.size()); 1791 1792 boolean badConfig = false; 1793 for (BrightnessThrottlingPoint point : points) { 1794 ThermalStatus status = point.getThermalStatus(); 1795 if (!thermalStatusIsValid(status)) { 1796 badConfig = true; 1797 break; 1798 } 1799 1800 throttlingLevels.add(new BrightnessThrottlingData.ThrottlingLevel( 1801 convertThermalStatus(status), point.getBrightness().floatValue())); 1802 } 1803 1804 if (!badConfig) { 1805 mBrightnessThrottlingData = BrightnessThrottlingData.create(throttlingLevels); 1806 mOriginalBrightnessThrottlingData = mBrightnessThrottlingData; 1807 } 1808 } 1809 loadRefreshRateSetting(DisplayConfiguration config)1810 private void loadRefreshRateSetting(DisplayConfiguration config) { 1811 final RefreshRateConfigs refreshRateConfigs = 1812 (config == null) ? null : config.getRefreshRate(); 1813 BlockingZoneConfig lowerBlockingZoneConfig = 1814 (refreshRateConfigs == null) ? null 1815 : refreshRateConfigs.getLowerBlockingZoneConfigs(); 1816 BlockingZoneConfig higherBlockingZoneConfig = 1817 (refreshRateConfigs == null) ? null 1818 : refreshRateConfigs.getHigherBlockingZoneConfigs(); 1819 loadPeakDefaultRefreshRate(refreshRateConfigs); 1820 loadDefaultRefreshRate(refreshRateConfigs); 1821 loadDefaultRefreshRateInHbm(refreshRateConfigs); 1822 loadLowerRefreshRateBlockingZones(lowerBlockingZoneConfig); 1823 loadHigherRefreshRateBlockingZones(higherBlockingZoneConfig); 1824 } 1825 loadPeakDefaultRefreshRate(RefreshRateConfigs refreshRateConfigs)1826 private void loadPeakDefaultRefreshRate(RefreshRateConfigs refreshRateConfigs) { 1827 if (refreshRateConfigs == null || refreshRateConfigs.getDefaultPeakRefreshRate() == null) { 1828 mDefaultPeakRefreshRate = mContext.getResources().getInteger( 1829 R.integer.config_defaultPeakRefreshRate); 1830 } else { 1831 mDefaultPeakRefreshRate = 1832 refreshRateConfigs.getDefaultPeakRefreshRate().intValue(); 1833 } 1834 } 1835 loadDefaultRefreshRate(RefreshRateConfigs refreshRateConfigs)1836 private void loadDefaultRefreshRate(RefreshRateConfigs refreshRateConfigs) { 1837 if (refreshRateConfigs == null || refreshRateConfigs.getDefaultRefreshRate() == null) { 1838 mDefaultRefreshRate = mContext.getResources().getInteger( 1839 R.integer.config_defaultRefreshRate); 1840 } else { 1841 mDefaultRefreshRate = 1842 refreshRateConfigs.getDefaultRefreshRate().intValue(); 1843 } 1844 } 1845 loadDefaultRefreshRateInHbm(RefreshRateConfigs refreshRateConfigs)1846 private void loadDefaultRefreshRateInHbm(RefreshRateConfigs refreshRateConfigs) { 1847 if (refreshRateConfigs != null 1848 && refreshRateConfigs.getDefaultRefreshRateInHbmHdr() != null) { 1849 mDefaultRefreshRateInHbmHdr = refreshRateConfigs.getDefaultRefreshRateInHbmHdr() 1850 .intValue(); 1851 } else { 1852 mDefaultRefreshRateInHbmHdr = mContext.getResources().getInteger( 1853 R.integer.config_defaultRefreshRateInHbmHdr); 1854 } 1855 1856 if (refreshRateConfigs != null 1857 && refreshRateConfigs.getDefaultRefreshRateInHbmSunlight() != null) { 1858 mDefaultRefreshRateInHbmSunlight = 1859 refreshRateConfigs.getDefaultRefreshRateInHbmSunlight().intValue(); 1860 } else { 1861 mDefaultRefreshRateInHbmSunlight = mContext.getResources().getInteger( 1862 R.integer.config_defaultRefreshRateInHbmSunlight); 1863 } 1864 } 1865 1866 /** 1867 * Loads the refresh rate configurations pertaining to the upper blocking zones. 1868 */ loadLowerRefreshRateBlockingZones(BlockingZoneConfig lowerBlockingZoneConfig)1869 private void loadLowerRefreshRateBlockingZones(BlockingZoneConfig lowerBlockingZoneConfig) { 1870 loadLowerBlockingZoneDefaultRefreshRate(lowerBlockingZoneConfig); 1871 loadLowerBrightnessThresholds(lowerBlockingZoneConfig); 1872 } 1873 1874 /** 1875 * Loads the refresh rate configurations pertaining to the upper blocking zones. 1876 */ loadHigherRefreshRateBlockingZones(BlockingZoneConfig upperBlockingZoneConfig)1877 private void loadHigherRefreshRateBlockingZones(BlockingZoneConfig upperBlockingZoneConfig) { 1878 loadHigherBlockingZoneDefaultRefreshRate(upperBlockingZoneConfig); 1879 loadHigherBrightnessThresholds(upperBlockingZoneConfig); 1880 } 1881 1882 /** 1883 * Loads the default peak refresh rate. Internally, this takes care of loading 1884 * the value from the display config, and if not present, falls back to config.xml. 1885 */ loadHigherBlockingZoneDefaultRefreshRate( BlockingZoneConfig upperBlockingZoneConfig)1886 private void loadHigherBlockingZoneDefaultRefreshRate( 1887 BlockingZoneConfig upperBlockingZoneConfig) { 1888 if (upperBlockingZoneConfig == null) { 1889 mDefaultHighBlockingZoneRefreshRate = mContext.getResources().getInteger( 1890 com.android.internal.R.integer.config_fixedRefreshRateInHighZone); 1891 } else { 1892 mDefaultHighBlockingZoneRefreshRate = 1893 upperBlockingZoneConfig.getDefaultRefreshRate().intValue(); 1894 } 1895 } 1896 1897 /** 1898 * Loads the default refresh rate. Internally, this takes care of loading 1899 * the value from the display config, and if not present, falls back to config.xml. 1900 */ loadLowerBlockingZoneDefaultRefreshRate( BlockingZoneConfig lowerBlockingZoneConfig)1901 private void loadLowerBlockingZoneDefaultRefreshRate( 1902 BlockingZoneConfig lowerBlockingZoneConfig) { 1903 if (lowerBlockingZoneConfig == null) { 1904 mDefaultLowBlockingZoneRefreshRate = mContext.getResources().getInteger( 1905 com.android.internal.R.integer.config_defaultRefreshRateInZone); 1906 } else { 1907 mDefaultLowBlockingZoneRefreshRate = 1908 lowerBlockingZoneConfig.getDefaultRefreshRate().intValue(); 1909 } 1910 } 1911 1912 /** 1913 * Loads the lower brightness thresholds for refresh rate switching. Internally, this takes care 1914 * of loading the value from the display config, and if not present, falls back to config.xml. 1915 */ loadLowerBrightnessThresholds(BlockingZoneConfig lowerBlockingZoneConfig)1916 private void loadLowerBrightnessThresholds(BlockingZoneConfig lowerBlockingZoneConfig) { 1917 if (lowerBlockingZoneConfig == null) { 1918 mLowDisplayBrightnessThresholds = mContext.getResources().getIntArray( 1919 R.array.config_brightnessThresholdsOfPeakRefreshRate); 1920 mLowAmbientBrightnessThresholds = mContext.getResources().getIntArray( 1921 R.array.config_ambientThresholdsOfPeakRefreshRate); 1922 if (mLowDisplayBrightnessThresholds == null || mLowAmbientBrightnessThresholds == null 1923 || mLowDisplayBrightnessThresholds.length 1924 != mLowAmbientBrightnessThresholds.length) { 1925 throw new RuntimeException("display low brightness threshold array and ambient " 1926 + "brightness threshold array have different length: " 1927 + "mLowDisplayBrightnessThresholds=" 1928 + Arrays.toString(mLowDisplayBrightnessThresholds) 1929 + ", mLowAmbientBrightnessThresholds=" 1930 + Arrays.toString(mLowAmbientBrightnessThresholds)); 1931 } 1932 } else { 1933 List<DisplayBrightnessPoint> lowerThresholdDisplayBrightnessPoints = 1934 lowerBlockingZoneConfig.getBlockingZoneThreshold().getDisplayBrightnessPoint(); 1935 int size = lowerThresholdDisplayBrightnessPoints.size(); 1936 mLowDisplayBrightnessThresholds = new int[size]; 1937 mLowAmbientBrightnessThresholds = new int[size]; 1938 for (int i = 0; i < size; i++) { 1939 // We are explicitly casting this value to an integer to be able to reuse the 1940 // existing DisplayBrightnessPoint type. It is fine to do this because the round off 1941 // will have the negligible and unnoticeable impact on the loaded thresholds. 1942 mLowDisplayBrightnessThresholds[i] = (int) lowerThresholdDisplayBrightnessPoints 1943 .get(i).getNits().floatValue(); 1944 mLowAmbientBrightnessThresholds[i] = lowerThresholdDisplayBrightnessPoints 1945 .get(i).getLux().intValue(); 1946 } 1947 } 1948 } 1949 1950 /** 1951 * Loads the higher brightness thresholds for refresh rate switching. Internally, this takes 1952 * care of loading the value from the display config, and if not present, falls back to 1953 * config.xml. 1954 */ loadHigherBrightnessThresholds(BlockingZoneConfig blockingZoneConfig)1955 private void loadHigherBrightnessThresholds(BlockingZoneConfig blockingZoneConfig) { 1956 if (blockingZoneConfig == null) { 1957 mHighDisplayBrightnessThresholds = mContext.getResources().getIntArray( 1958 R.array.config_highDisplayBrightnessThresholdsOfFixedRefreshRate); 1959 mHighAmbientBrightnessThresholds = mContext.getResources().getIntArray( 1960 R.array.config_highAmbientBrightnessThresholdsOfFixedRefreshRate); 1961 if (mHighAmbientBrightnessThresholds == null || mHighDisplayBrightnessThresholds == null 1962 || mHighAmbientBrightnessThresholds.length 1963 != mHighDisplayBrightnessThresholds.length) { 1964 throw new RuntimeException("display high brightness threshold array and ambient " 1965 + "brightness threshold array have different length: " 1966 + "mHighDisplayBrightnessThresholds=" 1967 + Arrays.toString(mHighDisplayBrightnessThresholds) 1968 + ", mHighAmbientBrightnessThresholds=" 1969 + Arrays.toString(mHighAmbientBrightnessThresholds)); 1970 } 1971 } else { 1972 List<DisplayBrightnessPoint> higherThresholdDisplayBrightnessPoints = 1973 blockingZoneConfig.getBlockingZoneThreshold().getDisplayBrightnessPoint(); 1974 int size = higherThresholdDisplayBrightnessPoints.size(); 1975 mHighDisplayBrightnessThresholds = new int[size]; 1976 mHighAmbientBrightnessThresholds = new int[size]; 1977 for (int i = 0; i < size; i++) { 1978 // We are explicitly casting this value to an integer to be able to reuse the 1979 // existing DisplayBrightnessPoint type. It is fine to do this because the round off 1980 // will have the negligible and unnoticeable impact on the loaded thresholds. 1981 mHighDisplayBrightnessThresholds[i] = (int) higherThresholdDisplayBrightnessPoints 1982 .get(i).getNits().floatValue(); 1983 mHighAmbientBrightnessThresholds[i] = higherThresholdDisplayBrightnessPoints 1984 .get(i).getLux().intValue(); 1985 } 1986 } 1987 } 1988 loadAutoBrightnessConfigValues(DisplayConfiguration config)1989 private void loadAutoBrightnessConfigValues(DisplayConfiguration config) { 1990 final AutoBrightness autoBrightness = config.getAutoBrightness(); 1991 loadAutoBrightnessBrighteningLightDebounce(autoBrightness); 1992 loadAutoBrightnessDarkeningLightDebounce(autoBrightness); 1993 loadAutoBrightnessDisplayBrightnessMapping(autoBrightness); 1994 loadEnableAutoBrightness(autoBrightness); 1995 } 1996 1997 /** 1998 * Loads the auto-brightness brightening light debounce. Internally, this takes care of loading 1999 * the value from the display config, and if not present, falls back to config.xml. 2000 */ loadAutoBrightnessBrighteningLightDebounce(AutoBrightness autoBrightnessConfig)2001 private void loadAutoBrightnessBrighteningLightDebounce(AutoBrightness autoBrightnessConfig) { 2002 if (autoBrightnessConfig == null 2003 || autoBrightnessConfig.getBrighteningLightDebounceMillis() == null) { 2004 mAutoBrightnessBrighteningLightDebounce = mContext.getResources().getInteger( 2005 com.android.internal.R.integer.config_autoBrightnessBrighteningLightDebounce); 2006 } else { 2007 mAutoBrightnessBrighteningLightDebounce = 2008 autoBrightnessConfig.getBrighteningLightDebounceMillis().intValue(); 2009 } 2010 } 2011 2012 /** 2013 * Loads the auto-brightness darkening light debounce. Internally, this takes care of loading 2014 * the value from the display config, and if not present, falls back to config.xml. 2015 */ loadAutoBrightnessDarkeningLightDebounce(AutoBrightness autoBrightnessConfig)2016 private void loadAutoBrightnessDarkeningLightDebounce(AutoBrightness autoBrightnessConfig) { 2017 if (autoBrightnessConfig == null 2018 || autoBrightnessConfig.getDarkeningLightDebounceMillis() == null) { 2019 mAutoBrightnessDarkeningLightDebounce = mContext.getResources().getInteger( 2020 com.android.internal.R.integer.config_autoBrightnessDarkeningLightDebounce); 2021 } else { 2022 mAutoBrightnessDarkeningLightDebounce = 2023 autoBrightnessConfig.getDarkeningLightDebounceMillis().intValue(); 2024 } 2025 } 2026 2027 /** 2028 * Loads the auto-brightness display brightness mappings. Internally, this takes care of 2029 * loading the value from the display config, and if not present, falls back to config.xml. 2030 */ loadAutoBrightnessDisplayBrightnessMapping(AutoBrightness autoBrightnessConfig)2031 private void loadAutoBrightnessDisplayBrightnessMapping(AutoBrightness autoBrightnessConfig) { 2032 if (autoBrightnessConfig == null 2033 || autoBrightnessConfig.getDisplayBrightnessMapping() == null) { 2034 mBrightnessLevelsNits = getFloatArray(mContext.getResources() 2035 .obtainTypedArray(com.android.internal.R.array 2036 .config_autoBrightnessDisplayValuesNits), PowerManager 2037 .BRIGHTNESS_OFF_FLOAT); 2038 mBrightnessLevelsLux = getLuxLevels(mContext.getResources() 2039 .getIntArray(com.android.internal.R.array 2040 .config_autoBrightnessLevels)); 2041 } else { 2042 final int size = autoBrightnessConfig.getDisplayBrightnessMapping() 2043 .getDisplayBrightnessPoint().size(); 2044 mBrightnessLevelsNits = new float[size]; 2045 // The first control point is implicit and always at 0 lux. 2046 mBrightnessLevelsLux = new float[size + 1]; 2047 for (int i = 0; i < size; i++) { 2048 mBrightnessLevelsNits[i] = autoBrightnessConfig.getDisplayBrightnessMapping() 2049 .getDisplayBrightnessPoint().get(i).getNits().floatValue(); 2050 mBrightnessLevelsLux[i + 1] = autoBrightnessConfig.getDisplayBrightnessMapping() 2051 .getDisplayBrightnessPoint().get(i).getLux().floatValue(); 2052 } 2053 } 2054 } 2055 loadAutoBrightnessAvailableFromConfigXml()2056 private void loadAutoBrightnessAvailableFromConfigXml() { 2057 mAutoBrightnessAvailable = mContext.getResources().getBoolean( 2058 R.bool.config_automatic_brightness_available); 2059 } 2060 loadBrightnessMapFromConfigXml()2061 private void loadBrightnessMapFromConfigXml() { 2062 // Use the config.xml mapping 2063 final Resources res = mContext.getResources(); 2064 final float[] sysNits = BrightnessMappingStrategy.getFloatArray(res.obtainTypedArray( 2065 com.android.internal.R.array.config_screenBrightnessNits)); 2066 final int[] sysBrightness = res.getIntArray( 2067 com.android.internal.R.array.config_screenBrightnessBacklight); 2068 final float[] sysBrightnessFloat = new float[sysBrightness.length]; 2069 2070 for (int i = 0; i < sysBrightness.length; i++) { 2071 sysBrightnessFloat[i] = BrightnessSynchronizer.brightnessIntToFloat( 2072 sysBrightness[i]); 2073 } 2074 2075 // These arrays are allowed to be empty, we set null values so that 2076 // BrightnessMappingStrategy will create a SimpleMappingStrategy instead. 2077 if (sysBrightnessFloat.length == 0 || sysNits.length == 0) { 2078 setSimpleMappingStrategyValues(); 2079 return; 2080 } 2081 2082 mRawNits = sysNits; 2083 mRawBacklight = sysBrightnessFloat; 2084 constrainNitsAndBacklightArrays(); 2085 } 2086 setSimpleMappingStrategyValues()2087 private void setSimpleMappingStrategyValues() { 2088 // No translation from backlight to brightness should occur if we are using a 2089 // SimpleMappingStrategy (ie they should be the same) so the splines are 2090 // set to be linear, between 0.0 and 1.0 2091 mNits = null; 2092 mBacklight = null; 2093 float[] simpleMappingStrategyArray = new float[]{0.0f, 1.0f}; 2094 mBrightnessToBacklightSpline = Spline.createSpline(simpleMappingStrategyArray, 2095 simpleMappingStrategyArray); 2096 mBacklightToBrightnessSpline = Spline.createSpline(simpleMappingStrategyArray, 2097 simpleMappingStrategyArray); 2098 } 2099 2100 /** 2101 * Change the nits and backlight arrays, so that they cover only the allowed backlight values 2102 * Use the brightness minimum and maximum values to clamp these arrays. 2103 */ constrainNitsAndBacklightArrays()2104 private void constrainNitsAndBacklightArrays() { 2105 if (mRawBacklight[0] > mBacklightMinimum 2106 || mRawBacklight[mRawBacklight.length - 1] < mBacklightMaximum 2107 || mBacklightMinimum > mBacklightMaximum) { 2108 throw new IllegalStateException("Min or max values are invalid" 2109 + "; raw min=" + mRawBacklight[0] 2110 + "; raw max=" + mRawBacklight[mRawBacklight.length - 1] 2111 + "; backlight min=" + mBacklightMinimum 2112 + "; backlight max=" + mBacklightMaximum); 2113 } 2114 2115 float[] newNits = new float[mRawBacklight.length]; 2116 float[] newBacklight = new float[mRawBacklight.length]; 2117 // Find the starting index of the clamped arrays. This may be less than the min so 2118 // we'll need to clamp this value still when actually doing the remapping. 2119 int newStart = 0; 2120 for (int i = 0; i < mRawBacklight.length - 1; i++) { 2121 if (mRawBacklight[i + 1] > mBacklightMinimum) { 2122 newStart = i; 2123 break; 2124 } 2125 } 2126 2127 boolean isLastValue = false; 2128 int newIndex = 0; 2129 for (int i = newStart; i < mRawBacklight.length && !isLastValue; i++) { 2130 newIndex = i - newStart; 2131 final float newBacklightVal; 2132 final float newNitsVal; 2133 isLastValue = mRawBacklight[i] >= mBacklightMaximum 2134 || i >= mRawBacklight.length - 1; 2135 // Clamp beginning and end to valid backlight values. 2136 if (newIndex == 0) { 2137 newBacklightVal = MathUtils.max(mRawBacklight[i], mBacklightMinimum); 2138 newNitsVal = rawBacklightToNits(i, newBacklightVal); 2139 } else if (isLastValue) { 2140 newBacklightVal = MathUtils.min(mRawBacklight[i], mBacklightMaximum); 2141 newNitsVal = rawBacklightToNits(i - 1, newBacklightVal); 2142 } else { 2143 newBacklightVal = mRawBacklight[i]; 2144 newNitsVal = mRawNits[i]; 2145 } 2146 newBacklight[newIndex] = newBacklightVal; 2147 newNits[newIndex] = newNitsVal; 2148 } 2149 mBacklight = Arrays.copyOf(newBacklight, newIndex + 1); 2150 mNits = Arrays.copyOf(newNits, newIndex + 1); 2151 createBacklightConversionSplines(); 2152 } 2153 rawBacklightToNits(int i, float backlight)2154 private float rawBacklightToNits(int i, float backlight) { 2155 return MathUtils.map(mRawBacklight[i], mRawBacklight[i + 1], 2156 mRawNits[i], mRawNits[i + 1], backlight); 2157 } 2158 2159 // This method creates a brightness spline that is of equal length with proportional increments 2160 // to the backlight spline. The values of this array range from 0.0f to 1.0f instead of the 2161 // potential constrained range that the backlight array covers 2162 // These splines are used to convert from the system brightness value to the HAL backlight 2163 // value createBacklightConversionSplines()2164 private void createBacklightConversionSplines() { 2165 mBrightness = new float[mBacklight.length]; 2166 for (int i = 0; i < mBrightness.length; i++) { 2167 mBrightness[i] = MathUtils.map(mBacklight[0], 2168 mBacklight[mBacklight.length - 1], 2169 PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX, mBacklight[i]); 2170 } 2171 mBrightnessToBacklightSpline = mInterpolationType == INTERPOLATION_LINEAR 2172 ? Spline.createLinearSpline(mBrightness, mBacklight) 2173 : Spline.createSpline(mBrightness, mBacklight); 2174 mBacklightToBrightnessSpline = mInterpolationType == INTERPOLATION_LINEAR 2175 ? Spline.createLinearSpline(mBacklight, mBrightness) 2176 : Spline.createSpline(mBacklight, mBrightness); 2177 mBacklightToNitsSpline = mInterpolationType == INTERPOLATION_LINEAR 2178 ? Spline.createLinearSpline(mBacklight, mNits) 2179 : Spline.createSpline(mBacklight, mNits); 2180 mNitsToBacklightSpline = mInterpolationType == INTERPOLATION_LINEAR 2181 ? Spline.createLinearSpline(mNits, mBacklight) 2182 : Spline.createSpline(mNits, mBacklight); 2183 } 2184 loadQuirks(DisplayConfiguration config)2185 private void loadQuirks(DisplayConfiguration config) { 2186 final DisplayQuirks quirks = config.getQuirks(); 2187 if (quirks != null) { 2188 mQuirks = new ArrayList<>(quirks.getQuirk()); 2189 } 2190 } 2191 loadHighBrightnessModeData(DisplayConfiguration config)2192 private void loadHighBrightnessModeData(DisplayConfiguration config) { 2193 final HighBrightnessMode hbm = config.getHighBrightnessMode(); 2194 if (hbm != null) { 2195 mIsHighBrightnessModeEnabled = hbm.getEnabled(); 2196 mHbmData = new HighBrightnessModeData(); 2197 mHbmData.minimumLux = hbm.getMinimumLux_all().floatValue(); 2198 float transitionPointBacklightScale = hbm.getTransitionPoint_all().floatValue(); 2199 if (transitionPointBacklightScale >= mBacklightMaximum) { 2200 throw new IllegalArgumentException("HBM transition point invalid. " 2201 + mHbmData.transitionPoint + " is not less than " 2202 + mBacklightMaximum); 2203 } 2204 mHbmData.transitionPoint = 2205 mBacklightToBrightnessSpline.interpolate(transitionPointBacklightScale); 2206 final HbmTiming hbmTiming = hbm.getTiming_all(); 2207 mHbmData.timeWindowMillis = hbmTiming.getTimeWindowSecs_all().longValue() * 1000; 2208 mHbmData.timeMaxMillis = hbmTiming.getTimeMaxSecs_all().longValue() * 1000; 2209 mHbmData.timeMinMillis = hbmTiming.getTimeMinSecs_all().longValue() * 1000; 2210 mHbmData.thermalStatusLimit = convertThermalStatus(hbm.getThermalStatusLimit_all()); 2211 mHbmData.allowInLowPowerMode = hbm.getAllowInLowPowerMode_all(); 2212 final RefreshRateRange rr = hbm.getRefreshRate_all(); 2213 if (rr != null) { 2214 final float min = rr.getMinimum().floatValue(); 2215 final float max = rr.getMaximum().floatValue(); 2216 mRefreshRateLimitations.add(new RefreshRateLimitation( 2217 DisplayManagerInternal.REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE, min, max)); 2218 } 2219 BigDecimal minHdrPctOfScreen = hbm.getMinimumHdrPercentOfScreen_all(); 2220 if (minHdrPctOfScreen != null) { 2221 mHbmData.minimumHdrPercentOfScreen = minHdrPctOfScreen.floatValue(); 2222 if (mHbmData.minimumHdrPercentOfScreen > 1 2223 || mHbmData.minimumHdrPercentOfScreen < 0) { 2224 Slog.w(TAG, "Invalid minimum HDR percent of screen: " 2225 + String.valueOf(mHbmData.minimumHdrPercentOfScreen)); 2226 mHbmData.minimumHdrPercentOfScreen = HDR_PERCENT_OF_SCREEN_REQUIRED_DEFAULT; 2227 } 2228 } else { 2229 mHbmData.minimumHdrPercentOfScreen = HDR_PERCENT_OF_SCREEN_REQUIRED_DEFAULT; 2230 } 2231 2232 mSdrToHdrRatioSpline = loadSdrHdrRatioMap(hbm); 2233 } 2234 } 2235 loadBrightnessRamps(DisplayConfiguration config)2236 private void loadBrightnessRamps(DisplayConfiguration config) { 2237 // Priority 1: Value in the display device config (float) 2238 // Priority 2: Value in the config.xml (int) 2239 final BigDecimal fastDownDecimal = config.getScreenBrightnessRampFastDecrease(); 2240 final BigDecimal fastUpDecimal = config.getScreenBrightnessRampFastIncrease(); 2241 final BigDecimal slowDownDecimal = config.getScreenBrightnessRampSlowDecrease(); 2242 final BigDecimal slowUpDecimal = config.getScreenBrightnessRampSlowIncrease(); 2243 2244 if (fastDownDecimal != null && fastUpDecimal != null && slowDownDecimal != null 2245 && slowUpDecimal != null) { 2246 mBrightnessRampFastDecrease = fastDownDecimal.floatValue(); 2247 mBrightnessRampFastIncrease = fastUpDecimal.floatValue(); 2248 mBrightnessRampSlowDecrease = slowDownDecimal.floatValue(); 2249 mBrightnessRampSlowIncrease = slowUpDecimal.floatValue(); 2250 } else { 2251 if (fastDownDecimal != null || fastUpDecimal != null || slowDownDecimal != null 2252 || slowUpDecimal != null) { 2253 Slog.w(TAG, "Per display brightness ramp values ignored because not all " 2254 + "values are present in display device config"); 2255 } 2256 loadBrightnessRampsFromConfigXml(); 2257 } 2258 2259 final BigInteger increaseMax = config.getScreenBrightnessRampIncreaseMaxMillis(); 2260 if (increaseMax != null) { 2261 mBrightnessRampIncreaseMaxMillis = increaseMax.intValue(); 2262 } 2263 final BigInteger decreaseMax = config.getScreenBrightnessRampDecreaseMaxMillis(); 2264 if (decreaseMax != null) { 2265 mBrightnessRampDecreaseMaxMillis = decreaseMax.intValue(); 2266 } 2267 } 2268 loadBrightnessRampsFromConfigXml()2269 private void loadBrightnessRampsFromConfigXml() { 2270 mBrightnessRampFastIncrease = BrightnessSynchronizer.brightnessIntToFloat( 2271 mContext.getResources().getInteger(R.integer.config_brightness_ramp_rate_fast)); 2272 mBrightnessRampSlowIncrease = BrightnessSynchronizer.brightnessIntToFloat( 2273 mContext.getResources().getInteger(R.integer.config_brightness_ramp_rate_slow)); 2274 // config.xml uses the same values for both increasing and decreasing brightness 2275 // transitions so we assign them to the same values here. 2276 mBrightnessRampFastDecrease = mBrightnessRampFastIncrease; 2277 mBrightnessRampSlowDecrease = mBrightnessRampSlowIncrease; 2278 } 2279 loadAmbientLightSensorFromConfigXml()2280 private void loadAmbientLightSensorFromConfigXml() { 2281 mAmbientLightSensor.name = ""; 2282 mAmbientLightSensor.type = mContext.getResources().getString( 2283 com.android.internal.R.string.config_displayLightSensorType); 2284 } 2285 loadAutoBrightnessConfigsFromConfigXml()2286 private void loadAutoBrightnessConfigsFromConfigXml() { 2287 loadAutoBrightnessDisplayBrightnessMapping(null /*AutoBrightnessConfig*/); 2288 } 2289 loadAmbientLightSensorFromDdc(DisplayConfiguration config)2290 private void loadAmbientLightSensorFromDdc(DisplayConfiguration config) { 2291 final SensorDetails sensorDetails = config.getLightSensor(); 2292 if (sensorDetails != null) { 2293 mAmbientLightSensor.type = sensorDetails.getType(); 2294 mAmbientLightSensor.name = sensorDetails.getName(); 2295 final RefreshRateRange rr = sensorDetails.getRefreshRate(); 2296 if (rr != null) { 2297 mAmbientLightSensor.minRefreshRate = rr.getMinimum().floatValue(); 2298 mAmbientLightSensor.maxRefreshRate = rr.getMaximum().floatValue(); 2299 } 2300 } else { 2301 loadAmbientLightSensorFromConfigXml(); 2302 } 2303 } 2304 useFallbackProxSensor()2305 private void useFallbackProxSensor() { 2306 mProximitySensor.name = null; 2307 mProximitySensor.type = null; 2308 } 2309 useNullProxSensor()2310 private void useNullProxSensor() { 2311 mProximitySensor.name = ""; 2312 mProximitySensor.type = ""; 2313 } 2314 loadScreenOffBrightnessSensorFromDdc(DisplayConfiguration config)2315 private void loadScreenOffBrightnessSensorFromDdc(DisplayConfiguration config) { 2316 final SensorDetails sensorDetails = config.getScreenOffBrightnessSensor(); 2317 if (sensorDetails != null) { 2318 mScreenOffBrightnessSensor.type = sensorDetails.getType(); 2319 mScreenOffBrightnessSensor.name = sensorDetails.getName(); 2320 } 2321 } 2322 loadProxSensorFromDdc(DisplayConfiguration config)2323 private void loadProxSensorFromDdc(DisplayConfiguration config) { 2324 SensorDetails sensorDetails = config.getProxSensor(); 2325 if (sensorDetails != null) { 2326 if (sensorDetails.getName() == null && sensorDetails.getType() == null) { 2327 // If prox sensor is defined, but no details given, this is assumed that 2328 // the display does not have or wish to use a prox sensor for it. 2329 useNullProxSensor(); 2330 return; 2331 } 2332 mProximitySensor.name = sensorDetails.getName(); 2333 mProximitySensor.type = sensorDetails.getType(); 2334 final RefreshRateRange rr = sensorDetails.getRefreshRate(); 2335 if (rr != null) { 2336 mProximitySensor.minRefreshRate = rr.getMinimum().floatValue(); 2337 mProximitySensor.maxRefreshRate = rr.getMaximum().floatValue(); 2338 } 2339 } else { 2340 // If prox sensor is unspecified, then use a fallback. 2341 useFallbackProxSensor(); 2342 } 2343 } 2344 loadBrightnessChangeThresholdsFromXml()2345 private void loadBrightnessChangeThresholdsFromXml() { 2346 loadBrightnessChangeThresholds(/* config= */ null); 2347 } 2348 loadBrightnessChangeThresholds(DisplayConfiguration config)2349 private void loadBrightnessChangeThresholds(DisplayConfiguration config) { 2350 loadDisplayBrightnessThresholds(config); 2351 loadAmbientBrightnessThresholds(config); 2352 loadDisplayBrightnessThresholdsIdle(config); 2353 loadAmbientBrightnessThresholdsIdle(config); 2354 } 2355 loadDisplayBrightnessThresholds(DisplayConfiguration config)2356 private void loadDisplayBrightnessThresholds(DisplayConfiguration config) { 2357 BrightnessThresholds brighteningScreen = null; 2358 BrightnessThresholds darkeningScreen = null; 2359 if (config != null && config.getDisplayBrightnessChangeThresholds() != null) { 2360 brighteningScreen = 2361 config.getDisplayBrightnessChangeThresholds().getBrighteningThresholds(); 2362 darkeningScreen = 2363 config.getDisplayBrightnessChangeThresholds().getDarkeningThresholds(); 2364 2365 } 2366 2367 // Screen bright/darkening threshold levels for active mode 2368 Pair<float[], float[]> screenBrighteningPair = getBrightnessLevelAndPercentage( 2369 brighteningScreen, 2370 com.android.internal.R.array.config_screenThresholdLevels, 2371 com.android.internal.R.array.config_screenBrighteningThresholds, 2372 DEFAULT_SCREEN_THRESHOLD_LEVELS, DEFAULT_SCREEN_BRIGHTENING_THRESHOLDS, 2373 /* potentialOldBrightnessScale= */ true); 2374 2375 mScreenBrighteningLevels = screenBrighteningPair.first; 2376 mScreenBrighteningPercentages = screenBrighteningPair.second; 2377 2378 Pair<float[], float[]> screenDarkeningPair = getBrightnessLevelAndPercentage( 2379 darkeningScreen, 2380 com.android.internal.R.array.config_screenThresholdLevels, 2381 com.android.internal.R.array.config_screenDarkeningThresholds, 2382 DEFAULT_SCREEN_THRESHOLD_LEVELS, DEFAULT_SCREEN_DARKENING_THRESHOLDS, 2383 /* potentialOldBrightnessScale= */ true); 2384 mScreenDarkeningLevels = screenDarkeningPair.first; 2385 mScreenDarkeningPercentages = screenDarkeningPair.second; 2386 2387 // Screen bright/darkening threshold minimums for active mode 2388 if (brighteningScreen != null && brighteningScreen.getMinimum() != null) { 2389 mScreenBrighteningMinThreshold = brighteningScreen.getMinimum().floatValue(); 2390 } 2391 if (darkeningScreen != null && darkeningScreen.getMinimum() != null) { 2392 mScreenDarkeningMinThreshold = darkeningScreen.getMinimum().floatValue(); 2393 } 2394 } 2395 loadAmbientBrightnessThresholds(DisplayConfiguration config)2396 private void loadAmbientBrightnessThresholds(DisplayConfiguration config) { 2397 // Ambient Brightness Threshold Levels 2398 BrightnessThresholds brighteningAmbientLux = null; 2399 BrightnessThresholds darkeningAmbientLux = null; 2400 if (config != null && config.getAmbientBrightnessChangeThresholds() != null) { 2401 brighteningAmbientLux = 2402 config.getAmbientBrightnessChangeThresholds().getBrighteningThresholds(); 2403 darkeningAmbientLux = 2404 config.getAmbientBrightnessChangeThresholds().getDarkeningThresholds(); 2405 } 2406 2407 // Ambient bright/darkening threshold levels for active mode 2408 Pair<float[], float[]> ambientBrighteningPair = getBrightnessLevelAndPercentage( 2409 brighteningAmbientLux, 2410 com.android.internal.R.array.config_ambientThresholdLevels, 2411 com.android.internal.R.array.config_ambientBrighteningThresholds, 2412 DEFAULT_AMBIENT_THRESHOLD_LEVELS, DEFAULT_AMBIENT_BRIGHTENING_THRESHOLDS); 2413 mAmbientBrighteningLevels = ambientBrighteningPair.first; 2414 mAmbientBrighteningPercentages = ambientBrighteningPair.second; 2415 2416 Pair<float[], float[]> ambientDarkeningPair = getBrightnessLevelAndPercentage( 2417 darkeningAmbientLux, 2418 com.android.internal.R.array.config_ambientThresholdLevels, 2419 com.android.internal.R.array.config_ambientDarkeningThresholds, 2420 DEFAULT_AMBIENT_THRESHOLD_LEVELS, DEFAULT_AMBIENT_DARKENING_THRESHOLDS); 2421 mAmbientDarkeningLevels = ambientDarkeningPair.first; 2422 mAmbientDarkeningPercentages = ambientDarkeningPair.second; 2423 2424 // Ambient bright/darkening threshold minimums for active/idle mode 2425 if (brighteningAmbientLux != null && brighteningAmbientLux.getMinimum() != null) { 2426 mAmbientLuxBrighteningMinThreshold = 2427 brighteningAmbientLux.getMinimum().floatValue(); 2428 } 2429 2430 if (darkeningAmbientLux != null && darkeningAmbientLux.getMinimum() != null) { 2431 mAmbientLuxDarkeningMinThreshold = darkeningAmbientLux.getMinimum().floatValue(); 2432 } 2433 } 2434 loadDisplayBrightnessThresholdsIdle(DisplayConfiguration config)2435 private void loadDisplayBrightnessThresholdsIdle(DisplayConfiguration config) { 2436 BrightnessThresholds brighteningScreenIdle = null; 2437 BrightnessThresholds darkeningScreenIdle = null; 2438 if (config != null && config.getDisplayBrightnessChangeThresholdsIdle() != null) { 2439 brighteningScreenIdle = 2440 config.getDisplayBrightnessChangeThresholdsIdle().getBrighteningThresholds(); 2441 darkeningScreenIdle = 2442 config.getDisplayBrightnessChangeThresholdsIdle().getDarkeningThresholds(); 2443 } 2444 2445 Pair<float[], float[]> screenBrighteningPair = getBrightnessLevelAndPercentage( 2446 brighteningScreenIdle, 2447 com.android.internal.R.array.config_screenThresholdLevels, 2448 com.android.internal.R.array.config_screenBrighteningThresholds, 2449 DEFAULT_SCREEN_THRESHOLD_LEVELS, DEFAULT_SCREEN_BRIGHTENING_THRESHOLDS, 2450 /* potentialOldBrightnessScale= */ true); 2451 mScreenBrighteningLevelsIdle = screenBrighteningPair.first; 2452 mScreenBrighteningPercentagesIdle = screenBrighteningPair.second; 2453 2454 Pair<float[], float[]> screenDarkeningPair = getBrightnessLevelAndPercentage( 2455 darkeningScreenIdle, 2456 com.android.internal.R.array.config_screenThresholdLevels, 2457 com.android.internal.R.array.config_screenDarkeningThresholds, 2458 DEFAULT_SCREEN_THRESHOLD_LEVELS, DEFAULT_SCREEN_DARKENING_THRESHOLDS, 2459 /* potentialOldBrightnessScale= */ true); 2460 mScreenDarkeningLevelsIdle = screenDarkeningPair.first; 2461 mScreenDarkeningPercentagesIdle = screenDarkeningPair.second; 2462 2463 if (brighteningScreenIdle != null 2464 && brighteningScreenIdle.getMinimum() != null) { 2465 mScreenBrighteningMinThresholdIdle = 2466 brighteningScreenIdle.getMinimum().floatValue(); 2467 } 2468 if (darkeningScreenIdle != null && darkeningScreenIdle.getMinimum() != null) { 2469 mScreenDarkeningMinThresholdIdle = 2470 darkeningScreenIdle.getMinimum().floatValue(); 2471 } 2472 } 2473 loadAmbientBrightnessThresholdsIdle(DisplayConfiguration config)2474 private void loadAmbientBrightnessThresholdsIdle(DisplayConfiguration config) { 2475 BrightnessThresholds brighteningAmbientLuxIdle = null; 2476 BrightnessThresholds darkeningAmbientLuxIdle = null; 2477 if (config != null && config.getAmbientBrightnessChangeThresholdsIdle() != null) { 2478 brighteningAmbientLuxIdle = 2479 config.getAmbientBrightnessChangeThresholdsIdle().getBrighteningThresholds(); 2480 darkeningAmbientLuxIdle = 2481 config.getAmbientBrightnessChangeThresholdsIdle().getDarkeningThresholds(); 2482 } 2483 2484 Pair<float[], float[]> ambientBrighteningPair = getBrightnessLevelAndPercentage( 2485 brighteningAmbientLuxIdle, 2486 com.android.internal.R.array.config_ambientThresholdLevels, 2487 com.android.internal.R.array.config_ambientBrighteningThresholds, 2488 DEFAULT_AMBIENT_THRESHOLD_LEVELS, DEFAULT_AMBIENT_BRIGHTENING_THRESHOLDS); 2489 mAmbientBrighteningLevelsIdle = ambientBrighteningPair.first; 2490 mAmbientBrighteningPercentagesIdle = ambientBrighteningPair.second; 2491 2492 Pair<float[], float[]> ambientDarkeningPair = getBrightnessLevelAndPercentage( 2493 darkeningAmbientLuxIdle, 2494 com.android.internal.R.array.config_ambientThresholdLevels, 2495 com.android.internal.R.array.config_ambientDarkeningThresholds, 2496 DEFAULT_AMBIENT_THRESHOLD_LEVELS, DEFAULT_AMBIENT_DARKENING_THRESHOLDS); 2497 mAmbientDarkeningLevelsIdle = ambientDarkeningPair.first; 2498 mAmbientDarkeningPercentagesIdle = ambientDarkeningPair.second; 2499 2500 if (brighteningAmbientLuxIdle != null 2501 && brighteningAmbientLuxIdle.getMinimum() != null) { 2502 mAmbientLuxBrighteningMinThresholdIdle = 2503 brighteningAmbientLuxIdle.getMinimum().floatValue(); 2504 } 2505 2506 if (darkeningAmbientLuxIdle != null && darkeningAmbientLuxIdle.getMinimum() != null) { 2507 mAmbientLuxDarkeningMinThresholdIdle = 2508 darkeningAmbientLuxIdle.getMinimum().floatValue(); 2509 } 2510 } 2511 getBrightnessLevelAndPercentage(BrightnessThresholds thresholds, int configFallbackThreshold, int configFallbackPercentage, float[] defaultLevels, float[] defaultPercentage)2512 private Pair<float[], float[]> getBrightnessLevelAndPercentage(BrightnessThresholds thresholds, 2513 int configFallbackThreshold, int configFallbackPercentage, float[] defaultLevels, 2514 float[] defaultPercentage) { 2515 return getBrightnessLevelAndPercentage(thresholds, configFallbackThreshold, 2516 configFallbackPercentage, defaultLevels, defaultPercentage, false); 2517 } 2518 2519 // Returns two float arrays, one of the brightness levels and one of the corresponding threshold 2520 // percentages for brightness levels at or above the lux value. 2521 // Historically, config.xml would have an array for brightness levels that was 1 shorter than 2522 // the levels array. Now we prepend a 0 to this array so they can be treated the same in the 2523 // rest of the framework. Values were also defined in different units (permille vs percent). getBrightnessLevelAndPercentage(BrightnessThresholds thresholds, int configFallbackThreshold, int configFallbackPermille, float[] defaultLevels, float[] defaultPercentage, boolean potentialOldBrightnessScale)2524 private Pair<float[], float[]> getBrightnessLevelAndPercentage(BrightnessThresholds thresholds, 2525 int configFallbackThreshold, int configFallbackPermille, 2526 float[] defaultLevels, float[] defaultPercentage, 2527 boolean potentialOldBrightnessScale) { 2528 if (thresholds != null 2529 && thresholds.getBrightnessThresholdPoints() != null 2530 && thresholds.getBrightnessThresholdPoints() 2531 .getBrightnessThresholdPoint().size() != 0) { 2532 2533 // The level and percentages arrays are equal length in the ddc (new system) 2534 List<ThresholdPoint> points = 2535 thresholds.getBrightnessThresholdPoints().getBrightnessThresholdPoint(); 2536 final int size = points.size(); 2537 2538 float[] thresholdLevels = new float[size]; 2539 float[] thresholdPercentages = new float[size]; 2540 2541 int i = 0; 2542 for (ThresholdPoint point : points) { 2543 thresholdLevels[i] = point.getThreshold().floatValue(); 2544 thresholdPercentages[i] = point.getPercentage().floatValue(); 2545 i++; 2546 } 2547 return new Pair<>(thresholdLevels, thresholdPercentages); 2548 } else { 2549 // The level and percentages arrays are unequal length in config.xml (old system) 2550 // We prefix the array with a 0 value to ensure they can be handled consistently 2551 // with the new system. 2552 2553 // Load levels array 2554 int[] configThresholdArray = mContext.getResources().getIntArray( 2555 configFallbackThreshold); 2556 int configThresholdsSize; 2557 if (configThresholdArray == null || configThresholdArray.length == 0) { 2558 configThresholdsSize = 1; 2559 } else { 2560 configThresholdsSize = configThresholdArray.length + 1; 2561 } 2562 2563 2564 // Load percentage array 2565 int[] configPermille = mContext.getResources().getIntArray( 2566 configFallbackPermille); 2567 2568 // Ensure lengths match up 2569 boolean emptyArray = configPermille == null || configPermille.length == 0; 2570 if (emptyArray && configThresholdsSize == 1) { 2571 return new Pair<>(defaultLevels, defaultPercentage); 2572 } 2573 if (emptyArray || configPermille.length != configThresholdsSize) { 2574 throw new IllegalArgumentException( 2575 "Brightness threshold arrays do not align in length"); 2576 } 2577 2578 // Calculate levels array 2579 float[] configThresholdWithZeroPrefixed = new float[configThresholdsSize]; 2580 // Start at 1, so that 0 index value is 0.0f (default) 2581 for (int i = 1; i < configThresholdsSize; i++) { 2582 configThresholdWithZeroPrefixed[i] = (float) configThresholdArray[i - 1]; 2583 } 2584 if (potentialOldBrightnessScale) { 2585 configThresholdWithZeroPrefixed = 2586 constraintInRangeIfNeeded(configThresholdWithZeroPrefixed); 2587 } 2588 2589 // Calculate percentages array 2590 float[] configPercentage = new float[configThresholdsSize]; 2591 for (int i = 0; i < configPermille.length; i++) { 2592 configPercentage[i] = configPermille[i] / 10.0f; 2593 } 2594 return new Pair<>(configThresholdWithZeroPrefixed, configPercentage); 2595 } 2596 } 2597 2598 /** 2599 * This check is due to historical reasons, where screen thresholdLevels used to be 2600 * integer values in the range of [0-255], but then was changed to be float values from [0,1]. 2601 * To accommodate both the possibilities, we first check if all the thresholdLevels are in 2602 * [0,1], and if not, we divide all the levels with 255 to bring them down to the same scale. 2603 */ constraintInRangeIfNeeded(float[] thresholdLevels)2604 private float[] constraintInRangeIfNeeded(float[] thresholdLevels) { 2605 if (isAllInRange(thresholdLevels, /* minValueInclusive= */ 0.0f, 2606 /* maxValueInclusive= */ 1.0f)) { 2607 return thresholdLevels; 2608 } 2609 2610 Slog.w(TAG, "Detected screen thresholdLevels on a deprecated brightness scale"); 2611 float[] thresholdLevelsScaled = new float[thresholdLevels.length]; 2612 for (int index = 0; thresholdLevels.length > index; ++index) { 2613 thresholdLevelsScaled[index] = thresholdLevels[index] / 255.0f; 2614 } 2615 return thresholdLevelsScaled; 2616 } 2617 isAllInRange(float[] configArray, float minValueInclusive, float maxValueInclusive)2618 private boolean isAllInRange(float[] configArray, float minValueInclusive, 2619 float maxValueInclusive) { 2620 for (float v : configArray) { 2621 if (v < minValueInclusive || v > maxValueInclusive) { 2622 return false; 2623 } 2624 } 2625 return true; 2626 } 2627 thermalStatusIsValid(ThermalStatus value)2628 private boolean thermalStatusIsValid(ThermalStatus value) { 2629 if (value == null) { 2630 return false; 2631 } 2632 2633 switch (value) { 2634 case none: 2635 case light: 2636 case moderate: 2637 case severe: 2638 case critical: 2639 case emergency: 2640 case shutdown: 2641 return true; 2642 default: 2643 return false; 2644 } 2645 } 2646 convertThermalStatus(ThermalStatus value)2647 private @PowerManager.ThermalStatus int convertThermalStatus(ThermalStatus value) { 2648 if (value == null) { 2649 return PowerManager.THERMAL_STATUS_NONE; 2650 } 2651 switch (value) { 2652 case none: 2653 return PowerManager.THERMAL_STATUS_NONE; 2654 case light: 2655 return PowerManager.THERMAL_STATUS_LIGHT; 2656 case moderate: 2657 return PowerManager.THERMAL_STATUS_MODERATE; 2658 case severe: 2659 return PowerManager.THERMAL_STATUS_SEVERE; 2660 case critical: 2661 return PowerManager.THERMAL_STATUS_CRITICAL; 2662 case emergency: 2663 return PowerManager.THERMAL_STATUS_EMERGENCY; 2664 case shutdown: 2665 return PowerManager.THERMAL_STATUS_SHUTDOWN; 2666 default: 2667 Slog.wtf(TAG, "Unexpected Thermal Status: " + value); 2668 return PowerManager.THERMAL_STATUS_NONE; 2669 } 2670 } 2671 convertInterpolationType(String value)2672 private int convertInterpolationType(String value) { 2673 if (TextUtils.isEmpty(value)) { 2674 return INTERPOLATION_DEFAULT; 2675 } 2676 2677 if ("linear".equals(value)) { 2678 return INTERPOLATION_LINEAR; 2679 } 2680 2681 Slog.wtf(TAG, "Unexpected Interpolation Type: " + value); 2682 return INTERPOLATION_DEFAULT; 2683 } 2684 loadAmbientHorizonFromDdc(DisplayConfiguration config)2685 private void loadAmbientHorizonFromDdc(DisplayConfiguration config) { 2686 final BigInteger configLongHorizon = config.getAmbientLightHorizonLong(); 2687 if (configLongHorizon != null) { 2688 mAmbientHorizonLong = configLongHorizon.intValue(); 2689 } 2690 final BigInteger configShortHorizon = config.getAmbientLightHorizonShort(); 2691 if (configShortHorizon != null) { 2692 mAmbientHorizonShort = configShortHorizon.intValue(); 2693 } 2694 } 2695 2696 /** 2697 * Extracts a float array from the specified {@link TypedArray}. 2698 * 2699 * @param array The array to convert. 2700 * @return the given array as a float array. 2701 */ getFloatArray(TypedArray array, float defaultValue)2702 public static float[] getFloatArray(TypedArray array, float defaultValue) { 2703 final int n = array.length(); 2704 float[] vals = new float[n]; 2705 for (int i = 0; i < n; i++) { 2706 vals[i] = array.getFloat(i, defaultValue); 2707 } 2708 array.recycle(); 2709 return vals; 2710 } 2711 getLuxLevels(int[] lux)2712 private static float[] getLuxLevels(int[] lux) { 2713 // The first control point is implicit and always at 0 lux. 2714 float[] levels = new float[lux.length + 1]; 2715 for (int i = 0; i < lux.length; i++) { 2716 levels[i + 1] = (float) lux[i]; 2717 } 2718 return levels; 2719 } 2720 loadEnableAutoBrightness(AutoBrightness autobrightness)2721 private void loadEnableAutoBrightness(AutoBrightness autobrightness) { 2722 // mDdcAutoBrightnessAvailable is initialised to true, so that we fallback to using the 2723 // config.xml values if the autobrightness tag is not defined in the ddc file. 2724 // Autobrightness can still be turned off globally via config_automatic_brightness_available 2725 mDdcAutoBrightnessAvailable = true; 2726 if (autobrightness != null) { 2727 mDdcAutoBrightnessAvailable = autobrightness.getEnabled(); 2728 } 2729 2730 mAutoBrightnessAvailable = mContext.getResources().getBoolean( 2731 com.android.internal.R.bool.config_automatic_brightness_available) 2732 && mDdcAutoBrightnessAvailable; 2733 } 2734 loadScreenOffBrightnessSensorValueToLuxFromDdc(DisplayConfiguration config)2735 private void loadScreenOffBrightnessSensorValueToLuxFromDdc(DisplayConfiguration config) { 2736 IntegerArray sensorValueToLux = config.getScreenOffBrightnessSensorValueToLux(); 2737 if (sensorValueToLux == null) { 2738 return; 2739 } 2740 2741 List<BigInteger> items = sensorValueToLux.getItem(); 2742 mScreenOffBrightnessSensorValueToLux = new int[items.size()]; 2743 for (int i = 0; i < items.size(); i++) { 2744 mScreenOffBrightnessSensorValueToLux[i] = items.get(i).intValue(); 2745 } 2746 } 2747 2748 /** 2749 * Uniquely identifies a Sensor, with the combination of Type and Name. 2750 */ 2751 static class SensorData { 2752 public String type; 2753 public String name; 2754 public float minRefreshRate = 0.0f; 2755 public float maxRefreshRate = Float.POSITIVE_INFINITY; 2756 2757 @Override toString()2758 public String toString() { 2759 return "Sensor{" 2760 + "type: " + type 2761 + ", name: " + name 2762 + ", refreshRateRange: [" + minRefreshRate + ", " + maxRefreshRate + "]" 2763 + "} "; 2764 } 2765 2766 /** 2767 * @return True if the sensor matches both the specified name and type, or one if only one 2768 * is specified (not-empty). Always returns false if both parameters are null or empty. 2769 */ matches(String sensorName, String sensorType)2770 public boolean matches(String sensorName, String sensorType) { 2771 final boolean isNameSpecified = !TextUtils.isEmpty(sensorName); 2772 final boolean isTypeSpecified = !TextUtils.isEmpty(sensorType); 2773 return (isNameSpecified || isTypeSpecified) 2774 && (!isNameSpecified || sensorName.equals(name)) 2775 && (!isTypeSpecified || sensorType.equals(type)); 2776 } 2777 } 2778 2779 /** 2780 * Container for high brightness mode configuration data. 2781 */ 2782 static class HighBrightnessModeData { 2783 /** Minimum lux needed to enter high brightness mode */ 2784 public float minimumLux; 2785 2786 /** Brightness level at which we transition from normal to high-brightness. */ 2787 public float transitionPoint; 2788 2789 /** Enable HBM only if the thermal status is not higher than this. */ 2790 public @PowerManager.ThermalStatus int thermalStatusLimit; 2791 2792 /** Whether HBM is allowed when {@code Settings.Global.LOW_POWER_MODE} is active. */ 2793 public boolean allowInLowPowerMode; 2794 2795 /** Time window for HBM. */ 2796 public long timeWindowMillis; 2797 2798 /** Maximum time HBM is allowed to be during in a {@code timeWindowMillis}. */ 2799 public long timeMaxMillis; 2800 2801 /** Minimum time that HBM can be on before being enabled. */ 2802 public long timeMinMillis; 2803 2804 /** Minimum HDR video size to enter high brightness mode */ 2805 public float minimumHdrPercentOfScreen; 2806 HighBrightnessModeData()2807 HighBrightnessModeData() {} 2808 HighBrightnessModeData(float minimumLux, float transitionPoint, long timeWindowMillis, long timeMaxMillis, long timeMinMillis, @PowerManager.ThermalStatus int thermalStatusLimit, boolean allowInLowPowerMode, float minimumHdrPercentOfScreen)2809 HighBrightnessModeData(float minimumLux, float transitionPoint, long timeWindowMillis, 2810 long timeMaxMillis, long timeMinMillis, 2811 @PowerManager.ThermalStatus int thermalStatusLimit, boolean allowInLowPowerMode, 2812 float minimumHdrPercentOfScreen) { 2813 this.minimumLux = minimumLux; 2814 this.transitionPoint = transitionPoint; 2815 this.timeWindowMillis = timeWindowMillis; 2816 this.timeMaxMillis = timeMaxMillis; 2817 this.timeMinMillis = timeMinMillis; 2818 this.thermalStatusLimit = thermalStatusLimit; 2819 this.allowInLowPowerMode = allowInLowPowerMode; 2820 this.minimumHdrPercentOfScreen = minimumHdrPercentOfScreen; 2821 } 2822 2823 /** 2824 * Copies the HBM data to the specified parameter instance. 2825 * @param other the instance to copy data to. 2826 */ copyTo(@onNull HighBrightnessModeData other)2827 public void copyTo(@NonNull HighBrightnessModeData other) { 2828 other.minimumLux = minimumLux; 2829 other.timeWindowMillis = timeWindowMillis; 2830 other.timeMaxMillis = timeMaxMillis; 2831 other.timeMinMillis = timeMinMillis; 2832 other.transitionPoint = transitionPoint; 2833 other.thermalStatusLimit = thermalStatusLimit; 2834 other.allowInLowPowerMode = allowInLowPowerMode; 2835 other.minimumHdrPercentOfScreen = minimumHdrPercentOfScreen; 2836 } 2837 2838 @Override toString()2839 public String toString() { 2840 return "HBM{" 2841 + "minLux: " + minimumLux 2842 + ", transition: " + transitionPoint 2843 + ", timeWindow: " + timeWindowMillis + "ms" 2844 + ", timeMax: " + timeMaxMillis + "ms" 2845 + ", timeMin: " + timeMinMillis + "ms" 2846 + ", thermalStatusLimit: " + thermalStatusLimit 2847 + ", allowInLowPowerMode: " + allowInLowPowerMode 2848 + ", minimumHdrPercentOfScreen: " + minimumHdrPercentOfScreen 2849 + "} "; 2850 } 2851 } 2852 2853 /** 2854 * Container for brightness throttling data. 2855 */ 2856 public static class BrightnessThrottlingData { 2857 public List<ThrottlingLevel> throttlingLevels; 2858 2859 static class ThrottlingLevel { 2860 public @PowerManager.ThermalStatus int thermalStatus; 2861 public float brightness; 2862 ThrottlingLevel(@owerManager.ThermalStatus int thermalStatus, float brightness)2863 ThrottlingLevel(@PowerManager.ThermalStatus int thermalStatus, float brightness) { 2864 this.thermalStatus = thermalStatus; 2865 this.brightness = brightness; 2866 } 2867 2868 @Override toString()2869 public String toString() { 2870 return "[" + thermalStatus + "," + brightness + "]"; 2871 } 2872 2873 @Override equals(Object obj)2874 public boolean equals(Object obj) { 2875 if (!(obj instanceof ThrottlingLevel)) { 2876 return false; 2877 } 2878 ThrottlingLevel otherThrottlingLevel = (ThrottlingLevel) obj; 2879 2880 return otherThrottlingLevel.thermalStatus == this.thermalStatus 2881 && otherThrottlingLevel.brightness == this.brightness; 2882 } 2883 2884 @Override hashCode()2885 public int hashCode() { 2886 int result = 1; 2887 result = 31 * result + thermalStatus; 2888 result = 31 * result + Float.hashCode(brightness); 2889 return result; 2890 } 2891 } 2892 2893 2894 /** 2895 * Creates multiple teperature based throttling levels of brightness 2896 */ create(List<ThrottlingLevel> throttlingLevels)2897 public static BrightnessThrottlingData create(List<ThrottlingLevel> throttlingLevels) { 2898 if (throttlingLevels == null || throttlingLevels.size() == 0) { 2899 Slog.e(TAG, "BrightnessThrottlingData received null or empty throttling levels"); 2900 return null; 2901 } 2902 2903 ThrottlingLevel prevLevel = throttlingLevels.get(0); 2904 final int numLevels = throttlingLevels.size(); 2905 for (int i = 1; i < numLevels; i++) { 2906 ThrottlingLevel thisLevel = throttlingLevels.get(i); 2907 2908 if (thisLevel.thermalStatus <= prevLevel.thermalStatus) { 2909 Slog.e(TAG, "brightnessThrottlingMap must be strictly increasing, ignoring " 2910 + "configuration. ThermalStatus " + thisLevel.thermalStatus + " <= " 2911 + prevLevel.thermalStatus); 2912 return null; 2913 } 2914 2915 if (thisLevel.brightness >= prevLevel.brightness) { 2916 Slog.e(TAG, "brightnessThrottlingMap must be strictly decreasing, ignoring " 2917 + "configuration. Brightness " + thisLevel.brightness + " >= " 2918 + thisLevel.brightness); 2919 return null; 2920 } 2921 2922 prevLevel = thisLevel; 2923 } 2924 2925 for (ThrottlingLevel level : throttlingLevels) { 2926 // Non-negative brightness values are enforced by device config schema 2927 if (level.brightness > PowerManager.BRIGHTNESS_MAX) { 2928 Slog.e(TAG, "brightnessThrottlingMap contains a brightness value exceeding " 2929 + "system max. Brightness " + level.brightness + " > " 2930 + PowerManager.BRIGHTNESS_MAX); 2931 return null; 2932 } 2933 } 2934 2935 return new BrightnessThrottlingData(throttlingLevels); 2936 } 2937 create(BrightnessThrottlingData other)2938 static public BrightnessThrottlingData create(BrightnessThrottlingData other) { 2939 if (other == null) { 2940 return null; 2941 } 2942 2943 return BrightnessThrottlingData.create(other.throttlingLevels); 2944 } 2945 2946 2947 @Override toString()2948 public String toString() { 2949 return "BrightnessThrottlingData{" 2950 + "throttlingLevels:" + throttlingLevels 2951 + "} "; 2952 } 2953 2954 @Override equals(Object obj)2955 public boolean equals(Object obj) { 2956 if (this == obj) { 2957 return true; 2958 } 2959 2960 if (!(obj instanceof BrightnessThrottlingData)) { 2961 return false; 2962 } 2963 2964 BrightnessThrottlingData otherBrightnessThrottlingData = (BrightnessThrottlingData) obj; 2965 return throttlingLevels.equals(otherBrightnessThrottlingData.throttlingLevels); 2966 } 2967 2968 @Override hashCode()2969 public int hashCode() { 2970 return throttlingLevels.hashCode(); 2971 } 2972 BrightnessThrottlingData(List<ThrottlingLevel> inLevels)2973 private BrightnessThrottlingData(List<ThrottlingLevel> inLevels) { 2974 throttlingLevels = new ArrayList<>(inLevels.size()); 2975 for (ThrottlingLevel level : inLevels) { 2976 throttlingLevels.add(new ThrottlingLevel(level.thermalStatus, level.brightness)); 2977 } 2978 } 2979 } 2980 } 2981