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