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