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