• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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.whitebalance;
18 
19 import android.annotation.NonNull;
20 import android.util.Slog;
21 import android.util.Spline;
22 
23 import com.android.internal.annotations.VisibleForTesting;
24 import com.android.server.LocalServices;
25 import com.android.server.display.color.ColorDisplayService.ColorDisplayServiceInternal;
26 import com.android.server.display.utils.AmbientFilter;
27 import com.android.server.display.utils.History;
28 
29 import java.io.PrintWriter;
30 import java.util.Objects;
31 
32 /**
33  * The DisplayWhiteBalanceController drives display white-balance (automatically correcting the
34  * display color temperature depending on the ambient color temperature).
35  *
36  * The DisplayWhiteBalanceController:
37  * - Uses the AmbientColorTemperatureSensor to detect changes in the ambient color temperature;
38  * - Uses the AmbientColorTemperatureFilter to average these changes over time, filter out the
39  *   noise, and arrive at an estimate of the actual ambient color temperature;
40  * - Uses the DisplayWhiteBalanceThrottler to decide whether the display color tempearture should
41  *   be updated, suppressing changes that are too frequent or too minor.
42  */
43 public class DisplayWhiteBalanceController implements
44         AmbientSensor.AmbientBrightnessSensor.Callbacks,
45         AmbientSensor.AmbientColorTemperatureSensor.Callbacks {
46 
47     private static final String TAG = "DisplayWhiteBalanceController";
48     private boolean mLoggingEnabled;
49 
50     private final ColorDisplayServiceInternal mColorDisplayServiceInternal;
51 
52     private final AmbientSensor.AmbientBrightnessSensor mBrightnessSensor;
53     @VisibleForTesting
54     AmbientFilter mBrightnessFilter;
55     private final AmbientSensor.AmbientColorTemperatureSensor mColorTemperatureSensor;
56     @VisibleForTesting
57     AmbientFilter mColorTemperatureFilter;
58     private final DisplayWhiteBalanceThrottler mThrottler;
59     // In low brightness conditions the ALS readings are more noisy and produce
60     // high errors. This default is introduced to provide a fixed display color
61     // temperature when sensor readings become unreliable.
62     private final float mLowLightAmbientColorTemperature;
63     // In high brightness conditions certain color temperatures can cause peak display
64     // brightness to drop. This fixed color temperature can be used to compensate for
65     // this effect.
66     private final float mHighLightAmbientColorTemperature;
67 
68     private final boolean mLightModeAllowed;
69 
70     private float mAmbientColorTemperature;
71     @VisibleForTesting
72     float mPendingAmbientColorTemperature;
73     private float mLastAmbientColorTemperature;
74 
75     // The most recent ambient color temperature values are kept for debugging purposes.
76     private final History mAmbientColorTemperatureHistory;
77 
78     // Override the ambient color temperature for debugging purposes.
79     private float mAmbientColorTemperatureOverride;
80 
81     // A piecewise linear relationship between ambient and display color temperatures.
82     private Spline.LinearSpline mAmbientToDisplayColorTemperatureSpline;
83 
84     // A piecewise linear relationship between ambient and display color temperatures, with a
85     // stronger change between the two sets of values.
86     private Spline.LinearSpline mStrongAmbientToDisplayColorTemperatureSpline;
87 
88     // In very low or very high brightness conditions Display White Balance should
89     // be to set to a default instead of using mAmbientToDisplayColorTemperatureSpline.
90     // However, setting Display White Balance based on thresholds can cause the
91     // display to rapidly change color temperature. To solve this,
92     // mLowLightAmbientBrightnessToBiasSpline and
93     // mHighLightAmbientBrightnessToBiasSpline are used to smoothly interpolate from
94     // ambient color temperature to the defaults. A piecewise linear relationship
95     // between low light brightness and low light bias.
96     private Spline.LinearSpline mLowLightAmbientBrightnessToBiasSpline;
97 
98     // A piecewise linear relationship between high light brightness and high light bias.
99     private Spline.LinearSpline mHighLightAmbientBrightnessToBiasSpline;
100 
101     private float mLatestAmbientColorTemperature;
102     private float mLatestAmbientBrightness;
103     private float mLatestLowLightBias;
104     private float mLatestHighLightBias;
105 
106     private boolean mEnabled;
107 
108     // Whether a higher-strength adjustment should be applied; this must be enabled in addition to
109     // mEnabled in order to be applied.
110     private boolean mStrongModeEnabled;
111 
112     // To decouple the DisplayPowerController from the DisplayWhiteBalanceController, the DPC
113     // implements Callbacks and passes itself to the DWBC so it can call back into it without
114     // knowing about it.
115     private Callbacks mDisplayPowerControllerCallbacks;
116 
117     /**
118      * @param brightnessSensor
119      *      The sensor used to detect changes in the ambient brightness.
120      * @param brightnessFilter
121      *      The filter used to avergae ambient brightness changes over time, filter out the noise
122      *      and arrive at an estimate of the actual ambient brightness.
123      * @param colorTemperatureSensor
124      *      The sensor used to detect changes in the ambient color temperature.
125      * @param colorTemperatureFilter
126      *      The filter used to average ambient color temperature changes over time, filter out the
127      *      noise and arrive at an estimate of the actual ambient color temperature.
128      * @param throttler
129      *      The throttler used to determine whether the new display color temperature should be
130      *      updated or not.
131      * @param lowLightAmbientBrightnesses
132      *      The ambient brightness used to map the ambient brightnesses to the biases used to
133      *      interpolate to lowLightAmbientColorTemperature.
134      * @param lowLightAmbientBiases
135      *      The biases used to map the ambient brightnesses to the biases used to interpolate to
136      *      lowLightAmbientColorTemperature.
137      * @param lowLightAmbientColorTemperature
138      *      The ambient color temperature to which we interpolate to based on the low light curve.
139      * @param highLightAmbientBrightnesses
140      *      The ambient brightness used to map the ambient brightnesses to the biases used to
141      *      interpolate to highLightAmbientColorTemperature.
142      * @param highLightAmbientBiases
143      *      The biases used to map the ambient brightnesses to the biases used to interpolate to
144      *      highLightAmbientColorTemperature.
145      * @param highLightAmbientColorTemperature
146      *      The ambient color temperature to which we interpolate to based on the high light curve.
147      * @param ambientColorTemperatures
148      *      The ambient color tempeartures used to map the ambient color temperature to the display
149      *      color temperature (or null if no mapping is necessary).
150      * @param displayColorTemperatures
151      *      The display color temperatures used to map the ambient color temperature to the display
152      *      color temperature (or null if no mapping is necessary).
153      * @param lightModeAllowed
154      *      Whether a lighter version should be applied when Strong Mode is not enabled.
155      *
156      * @throws NullPointerException
157      *      - brightnessSensor is null;
158      *      - brightnessFilter is null;
159      *      - colorTemperatureSensor is null;
160      *      - colorTemperatureFilter is null;
161      *      - throttler is null.
162      */
DisplayWhiteBalanceController( @onNull AmbientSensor.AmbientBrightnessSensor brightnessSensor, @NonNull AmbientFilter brightnessFilter, @NonNull AmbientSensor.AmbientColorTemperatureSensor colorTemperatureSensor, @NonNull AmbientFilter colorTemperatureFilter, @NonNull DisplayWhiteBalanceThrottler throttler, float[] lowLightAmbientBrightnesses, float[] lowLightAmbientBiases, float lowLightAmbientColorTemperature, float[] highLightAmbientBrightnesses, float[] highLightAmbientBiases, float highLightAmbientColorTemperature, float[] ambientColorTemperatures, float[] displayColorTemperatures, float[] strongAmbientColorTemperatures, float[] strongDisplayColorTemperatures, boolean lightModeAllowed)163     public DisplayWhiteBalanceController(
164             @NonNull AmbientSensor.AmbientBrightnessSensor brightnessSensor,
165             @NonNull AmbientFilter brightnessFilter,
166             @NonNull AmbientSensor.AmbientColorTemperatureSensor colorTemperatureSensor,
167             @NonNull AmbientFilter colorTemperatureFilter,
168             @NonNull DisplayWhiteBalanceThrottler throttler,
169             float[] lowLightAmbientBrightnesses,
170             float[] lowLightAmbientBiases,
171             float lowLightAmbientColorTemperature,
172             float[] highLightAmbientBrightnesses,
173             float[] highLightAmbientBiases,
174             float highLightAmbientColorTemperature,
175             float[] ambientColorTemperatures,
176             float[] displayColorTemperatures,
177             float[] strongAmbientColorTemperatures,
178             float[] strongDisplayColorTemperatures,
179             boolean lightModeAllowed) {
180         validateArguments(brightnessSensor, brightnessFilter, colorTemperatureSensor,
181                 colorTemperatureFilter, throttler);
182         mBrightnessSensor = brightnessSensor;
183         mBrightnessFilter = brightnessFilter;
184         mColorTemperatureSensor = colorTemperatureSensor;
185         mColorTemperatureFilter = colorTemperatureFilter;
186         mThrottler = throttler;
187         mLowLightAmbientColorTemperature = lowLightAmbientColorTemperature;
188         mHighLightAmbientColorTemperature = highLightAmbientColorTemperature;
189         mAmbientColorTemperature = -1.0f;
190         mPendingAmbientColorTemperature = -1.0f;
191         mLastAmbientColorTemperature = -1.0f;
192         mAmbientColorTemperatureHistory = new History(/* size= */ 50);
193         mAmbientColorTemperatureOverride = -1.0f;
194         mLightModeAllowed = lightModeAllowed;
195 
196         try {
197             mLowLightAmbientBrightnessToBiasSpline = new Spline.LinearSpline(
198                     lowLightAmbientBrightnesses, lowLightAmbientBiases);
199         } catch (Exception e) {
200             Slog.e(TAG, "failed to create low light ambient brightness to bias spline.", e);
201             mLowLightAmbientBrightnessToBiasSpline = null;
202         }
203         if (mLowLightAmbientBrightnessToBiasSpline != null) {
204             if (mLowLightAmbientBrightnessToBiasSpline.interpolate(0.0f) != 0.0f ||
205                     mLowLightAmbientBrightnessToBiasSpline.interpolate(Float.POSITIVE_INFINITY)
206                     != 1.0f) {
207                 Slog.d(TAG, "invalid low light ambient brightness to bias spline, "
208                         + "bias must begin at 0.0 and end at 1.0.");
209                 mLowLightAmbientBrightnessToBiasSpline = null;
210             }
211         }
212 
213         try {
214             mHighLightAmbientBrightnessToBiasSpline = new Spline.LinearSpline(
215                     highLightAmbientBrightnesses, highLightAmbientBiases);
216         } catch (Exception e) {
217             Slog.e(TAG, "failed to create high light ambient brightness to bias spline.", e);
218             mHighLightAmbientBrightnessToBiasSpline = null;
219         }
220         if (mHighLightAmbientBrightnessToBiasSpline != null) {
221             if (mHighLightAmbientBrightnessToBiasSpline.interpolate(0.0f) != 0.0f ||
222                     mHighLightAmbientBrightnessToBiasSpline.interpolate(Float.POSITIVE_INFINITY)
223                     != 1.0f) {
224                 Slog.d(TAG, "invalid high light ambient brightness to bias spline, "
225                         + "bias must begin at 0.0 and end at 1.0.");
226                 mHighLightAmbientBrightnessToBiasSpline = null;
227             }
228         }
229 
230         if (mLowLightAmbientBrightnessToBiasSpline != null &&
231                 mHighLightAmbientBrightnessToBiasSpline != null) {
232             if (lowLightAmbientBrightnesses[lowLightAmbientBrightnesses.length - 1] >
233                     highLightAmbientBrightnesses[0]) {
234                 Slog.d(TAG, "invalid low light and high light ambient brightness to bias spline "
235                         + "combination, defined domains must not intersect.");
236                 mLowLightAmbientBrightnessToBiasSpline = null;
237                 mHighLightAmbientBrightnessToBiasSpline = null;
238             }
239         }
240 
241         try {
242             mAmbientToDisplayColorTemperatureSpline = new Spline.LinearSpline(
243                     ambientColorTemperatures, displayColorTemperatures);
244         } catch (Exception e) {
245             Slog.e(TAG, "failed to create ambient to display color temperature spline.", e);
246             mAmbientToDisplayColorTemperatureSpline = null;
247         }
248 
249         try {
250             mStrongAmbientToDisplayColorTemperatureSpline = new Spline.LinearSpline(
251                     strongAmbientColorTemperatures, strongDisplayColorTemperatures);
252         } catch (Exception e) {
253             Slog.e(TAG, "Failed to create strong ambient to display color temperature spline", e);
254         }
255 
256         mColorDisplayServiceInternal = LocalServices.getService(ColorDisplayServiceInternal.class);
257     }
258 
259     /**
260      * Enable/disable the controller.
261      *
262      * @param enabled
263      *      Whether the controller should be on/off.
264      *
265      * @return Whether the method succeeded or not.
266      */
setEnabled(boolean enabled)267     public boolean setEnabled(boolean enabled) {
268         if (enabled) {
269             return enable();
270         } else {
271             return disable();
272         }
273     }
274 
275     /**
276      * Enable/disable the stronger adjustment option.
277      *
278      * @param enabled whether the stronger adjustment option should be turned on
279      */
setStrongModeEnabled(boolean enabled)280     public void setStrongModeEnabled(boolean enabled) {
281         mStrongModeEnabled = enabled;
282         mColorDisplayServiceInternal.setDisplayWhiteBalanceAllowed(mLightModeAllowed
283                 || mStrongModeEnabled);
284         if (mEnabled) {
285             updateAmbientColorTemperature();
286             updateDisplayColorTemperature();
287         }
288     }
289 
290     /**
291      * Set an object to call back to when the display color temperature should be updated.
292      *
293      * @param callbacks
294      *      The object to call back to.
295      *
296      * @return Whether the method succeeded or not.
297      */
setCallbacks(Callbacks callbacks)298     public boolean setCallbacks(Callbacks callbacks) {
299         if (mDisplayPowerControllerCallbacks == callbacks) {
300             return false;
301         }
302         mDisplayPowerControllerCallbacks = callbacks;
303         return true;
304     }
305 
306     /**
307      * Enable/disable logging.
308      *
309      * @param loggingEnabled
310      *      Whether logging should be on/off.
311      *
312      * @return Whether the method succeeded or not.
313      */
setLoggingEnabled(boolean loggingEnabled)314     public boolean setLoggingEnabled(boolean loggingEnabled) {
315         if (mLoggingEnabled == loggingEnabled) {
316             return false;
317         }
318         mLoggingEnabled = loggingEnabled;
319         mBrightnessSensor.setLoggingEnabled(loggingEnabled);
320         mBrightnessFilter.setLoggingEnabled(loggingEnabled);
321         mColorTemperatureSensor.setLoggingEnabled(loggingEnabled);
322         mColorTemperatureFilter.setLoggingEnabled(loggingEnabled);
323         mThrottler.setLoggingEnabled(loggingEnabled);
324         return true;
325     }
326 
327     /**
328      * Set the ambient color temperature override.
329      *
330      * This is only applied when the ambient color temperature changes or is updated (in which case
331      * it overrides the ambient color temperature estimate); in other words, it doesn't necessarily
332      * change the display color temperature immediately.
333      *
334      * @param ambientColorTemperatureOverride
335      *      The ambient color temperature override.
336      *
337      * @return Whether the method succeeded or not.
338      */
setAmbientColorTemperatureOverride(float ambientColorTemperatureOverride)339     public boolean setAmbientColorTemperatureOverride(float ambientColorTemperatureOverride) {
340         if (mAmbientColorTemperatureOverride == ambientColorTemperatureOverride) {
341             return false;
342         }
343         mAmbientColorTemperatureOverride = ambientColorTemperatureOverride;
344         return true;
345     }
346 
347     /**
348      * Dump the state.
349      *
350      * @param writer
351      *      The writer used to dump the state.
352      */
dump(PrintWriter writer)353     public void dump(PrintWriter writer) {
354         writer.println("DisplayWhiteBalanceController");
355         writer.println("  mLoggingEnabled=" + mLoggingEnabled);
356         writer.println("  mEnabled=" + mEnabled);
357         writer.println("  mStrongModeEnabled=" + mStrongModeEnabled);
358         writer.println("  mDisplayPowerControllerCallbacks=" + mDisplayPowerControllerCallbacks);
359         mBrightnessSensor.dump(writer);
360         mBrightnessFilter.dump(writer);
361         mColorTemperatureSensor.dump(writer);
362         mColorTemperatureFilter.dump(writer);
363         mThrottler.dump(writer);
364         writer.println("  mLowLightAmbientColorTemperature=" + mLowLightAmbientColorTemperature);
365         writer.println("  mHighLightAmbientColorTemperature=" + mHighLightAmbientColorTemperature);
366         writer.println("  mAmbientColorTemperature=" + mAmbientColorTemperature);
367         writer.println("  mPendingAmbientColorTemperature=" + mPendingAmbientColorTemperature);
368         writer.println("  mLastAmbientColorTemperature=" + mLastAmbientColorTemperature);
369         writer.println("  mAmbientColorTemperatureHistory=" + mAmbientColorTemperatureHistory);
370         writer.println("  mAmbientColorTemperatureOverride=" + mAmbientColorTemperatureOverride);
371         writer.println("  mAmbientToDisplayColorTemperatureSpline="
372                 + mAmbientToDisplayColorTemperatureSpline);
373         writer.println("  mStrongAmbientToDisplayColorTemperatureSpline="
374                 + mStrongAmbientToDisplayColorTemperatureSpline);
375         writer.println("  mLowLightAmbientBrightnessToBiasSpline="
376                 + mLowLightAmbientBrightnessToBiasSpline);
377         writer.println("  mHighLightAmbientBrightnessToBiasSpline="
378                 + mHighLightAmbientBrightnessToBiasSpline);
379     }
380 
381     @Override // AmbientSensor.AmbientBrightnessSensor.Callbacks
onAmbientBrightnessChanged(float value)382     public void onAmbientBrightnessChanged(float value) {
383         final long time = System.currentTimeMillis();
384         mBrightnessFilter.addValue(time, value);
385         updateAmbientColorTemperature();
386     }
387 
388     @Override // AmbientSensor.AmbientColorTemperatureSensor.Callbacks
onAmbientColorTemperatureChanged(float value)389     public void onAmbientColorTemperatureChanged(float value) {
390         final long time = System.currentTimeMillis();
391         mColorTemperatureFilter.addValue(time, value);
392         updateAmbientColorTemperature();
393     }
394 
395     /**
396      * Updates the ambient color temperature.
397      */
updateAmbientColorTemperature()398     public void updateAmbientColorTemperature() {
399         final long time = System.currentTimeMillis();
400         float ambientColorTemperature = mColorTemperatureFilter.getEstimate(time);
401         mLatestAmbientColorTemperature = ambientColorTemperature;
402 
403         if (mStrongModeEnabled) {
404             if (mStrongAmbientToDisplayColorTemperatureSpline != null
405                     && ambientColorTemperature != -1.0f) {
406                 ambientColorTemperature =
407                         mStrongAmbientToDisplayColorTemperatureSpline.interpolate(
408                                 ambientColorTemperature);
409             }
410         } else {
411             if (mAmbientToDisplayColorTemperatureSpline != null
412                     && ambientColorTemperature != -1.0f) {
413                 ambientColorTemperature =
414                         mAmbientToDisplayColorTemperatureSpline.interpolate(
415                                 ambientColorTemperature);
416             }
417         }
418 
419         float ambientBrightness = mBrightnessFilter.getEstimate(time);
420         mLatestAmbientBrightness = ambientBrightness;
421 
422         if (ambientColorTemperature != -1.0f && ambientBrightness != -1.0f
423                 && mLowLightAmbientBrightnessToBiasSpline != null) {
424             float bias = mLowLightAmbientBrightnessToBiasSpline.interpolate(ambientBrightness);
425             ambientColorTemperature =
426                     bias * ambientColorTemperature + (1.0f - bias)
427                     * mLowLightAmbientColorTemperature;
428             mLatestLowLightBias = bias;
429         }
430         if (ambientColorTemperature != -1.0f && ambientBrightness != -1.0f
431                 && mHighLightAmbientBrightnessToBiasSpline != null) {
432             float bias = mHighLightAmbientBrightnessToBiasSpline.interpolate(ambientBrightness);
433             ambientColorTemperature =
434                     (1.0f - bias) * ambientColorTemperature + bias
435                     * mHighLightAmbientColorTemperature;
436             mLatestHighLightBias = bias;
437         }
438 
439         if (mAmbientColorTemperatureOverride != -1.0f) {
440             if (mLoggingEnabled) {
441                 Slog.d(TAG, "override ambient color temperature: " + ambientColorTemperature
442                         + " => " + mAmbientColorTemperatureOverride);
443             }
444             ambientColorTemperature = mAmbientColorTemperatureOverride;
445         }
446 
447         // When the display color temperature needs to be updated, we call DisplayPowerController to
448         // call our updateColorTemperature. The reason we don't call it directly is that we want
449         // all changes to the system to happen in a predictable order in DPC's main loop
450         // (updatePowerState).
451         if (ambientColorTemperature == -1.0f || mThrottler.throttle(ambientColorTemperature)) {
452             return;
453         }
454 
455         if (mLoggingEnabled) {
456             Slog.d(TAG, "pending ambient color temperature: " + ambientColorTemperature);
457         }
458         mPendingAmbientColorTemperature = ambientColorTemperature;
459         if (mDisplayPowerControllerCallbacks != null) {
460             mDisplayPowerControllerCallbacks.updateWhiteBalance();
461         }
462     }
463 
464     /**
465      * Updates the display color temperature.
466      */
updateDisplayColorTemperature()467     public void updateDisplayColorTemperature() {
468         float ambientColorTemperature = -1.0f;
469 
470         // If both the pending and the current ambient color temperatures are -1, it means the DWBC
471         // was just enabled, and we use the last ambient color temperature until new sensor events
472         // give us a better estimate.
473         if (mAmbientColorTemperature == -1.0f && mPendingAmbientColorTemperature == -1.0f) {
474             ambientColorTemperature = mLastAmbientColorTemperature;
475         }
476 
477         // Otherwise, we use the pending ambient color temperature, but only if it's non-trivial
478         // and different than the current one.
479         if (mPendingAmbientColorTemperature != -1.0f
480                 && mPendingAmbientColorTemperature != mAmbientColorTemperature) {
481             ambientColorTemperature = mPendingAmbientColorTemperature;
482         }
483 
484         if (ambientColorTemperature == -1.0f) {
485             return;
486         }
487 
488         mAmbientColorTemperature = ambientColorTemperature;
489         if (mLoggingEnabled) {
490             Slog.d(TAG, "ambient color temperature: " + mAmbientColorTemperature);
491         }
492         mPendingAmbientColorTemperature = -1.0f;
493         mAmbientColorTemperatureHistory.add(mAmbientColorTemperature);
494         Slog.d(TAG, "Display cct: " + mAmbientColorTemperature
495                 + " Latest ambient cct: " + mLatestAmbientColorTemperature
496                 + " Latest ambient lux: " + mLatestAmbientBrightness
497                 + " Latest low light bias: " + mLatestLowLightBias
498                 + " Latest high light bias: " + mLatestHighLightBias);
499         mColorDisplayServiceInternal.setDisplayWhiteBalanceColorTemperature(
500                 (int) mAmbientColorTemperature);
501         mLastAmbientColorTemperature = mAmbientColorTemperature;
502     }
503 
504     /**
505      * Calculate the adjusted brightness, in nits, due to the DWB color adaptation
506      *
507      * @param requestedBrightnessNits brightness the framework requires to be output
508      * @return the adjusted brightness the framework needs to output to counter the drop in
509      *         brightness due to DWB, or the requestedBrightnessNits if an adjustment cannot be made
510      */
calculateAdjustedBrightnessNits(float requestedBrightnessNits)511     public float calculateAdjustedBrightnessNits(float requestedBrightnessNits) {
512         float luminance = mColorDisplayServiceInternal.getDisplayWhiteBalanceLuminance();
513         if (luminance == -1) {
514             return requestedBrightnessNits;
515         }
516         float effectiveBrightness = requestedBrightnessNits * luminance;
517         return (requestedBrightnessNits - effectiveBrightness) + requestedBrightnessNits;
518     }
519 
520     /**
521      * The DisplayWhiteBalanceController decouples itself from its parent (DisplayPowerController)
522      * by providing this interface to implement (and a method to set its callbacks object), and
523      * calling these methods.
524      */
525     public interface Callbacks {
526 
527         /**
528          * Called whenever the display white-balance state has changed.
529          *
530          * Usually, this means the estimated ambient color temperature has changed enough, and the
531          * display color temperature should be updated; but it is also called if settings change.
532          */
updateWhiteBalance()533         void updateWhiteBalance();
534     }
535 
validateArguments(AmbientSensor.AmbientBrightnessSensor brightnessSensor, AmbientFilter brightnessFilter, AmbientSensor.AmbientColorTemperatureSensor colorTemperatureSensor, AmbientFilter colorTemperatureFilter, DisplayWhiteBalanceThrottler throttler)536     private void validateArguments(AmbientSensor.AmbientBrightnessSensor brightnessSensor,
537             AmbientFilter brightnessFilter,
538             AmbientSensor.AmbientColorTemperatureSensor colorTemperatureSensor,
539             AmbientFilter colorTemperatureFilter,
540             DisplayWhiteBalanceThrottler throttler) {
541         Objects.requireNonNull(brightnessSensor, "brightnessSensor must not be null");
542         Objects.requireNonNull(brightnessFilter, "brightnessFilter must not be null");
543         Objects.requireNonNull(colorTemperatureSensor,
544                 "colorTemperatureSensor must not be null");
545         Objects.requireNonNull(colorTemperatureFilter,
546                 "colorTemperatureFilter must not be null");
547         Objects.requireNonNull(throttler, "throttler cannot be null");
548     }
549 
enable()550     private boolean enable() {
551         if (mEnabled) {
552             return false;
553         }
554         if (mLoggingEnabled) {
555             Slog.d(TAG, "enabling");
556         }
557         mEnabled = true;
558         mBrightnessSensor.setEnabled(true);
559         mColorTemperatureSensor.setEnabled(true);
560         return true;
561     }
562 
disable()563     private boolean disable() {
564         if (!mEnabled) {
565             return false;
566         }
567         if (mLoggingEnabled) {
568             Slog.d(TAG, "disabling");
569         }
570         mEnabled = false;
571         mBrightnessSensor.setEnabled(false);
572         mBrightnessFilter.clear();
573         mColorTemperatureSensor.setEnabled(false);
574         mColorTemperatureFilter.clear();
575         mThrottler.clear();
576         mAmbientColorTemperature = -1.0f;
577         mPendingAmbientColorTemperature = -1.0f;
578         mColorDisplayServiceInternal.resetDisplayWhiteBalanceColorTemperature();
579         return true;
580     }
581 
582 }
583