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