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