AutomaticBrightnessController.java revision b0a1d3d08fc459e0d9937e299e16de17d1388ac4
1639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright/* 2639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright * Copyright (C) 2014 The Android Open Source Project 3639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright * 4639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright * Licensed under the Apache License, Version 2.0 (the "License"); 5639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright * you may not use this file except in compliance with the License. 6639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright * You may obtain a copy of the License at 7639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright * 8639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright * http://www.apache.org/licenses/LICENSE-2.0 9639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright * 10639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright * Unless required by applicable law or agreed to in writing, software 11639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright * distributed under the License is distributed on an "AS IS" BASIS, 12639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright * See the License for the specific language governing permissions and 14639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright * limitations under the License. 15639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright */ 16639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 17131206b8a9d07400d7c98aea50cc45c38769448fJeff Brownpackage com.android.server.display; 18639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 19a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brownimport com.android.server.EventLogTags; 20131206b8a9d07400d7c98aea50cc45c38769448fJeff Brownimport com.android.server.LocalServices; 21639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 22908b86c796443ba4ec55c669e8a0297fc80574a6Justin Klaassenimport android.annotation.Nullable; 23639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wrightimport android.hardware.Sensor; 24639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wrightimport android.hardware.SensorEvent; 25639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wrightimport android.hardware.SensorEventListener; 26639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wrightimport android.hardware.SensorManager; 27639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wrightimport android.os.Handler; 28639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wrightimport android.os.Looper; 29639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wrightimport android.os.Message; 30639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wrightimport android.os.PowerManager; 31639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wrightimport android.os.SystemClock; 32b0a1d3d08fc459e0d9937e299e16de17d1388ac4Michael Wrightimport android.os.Trace; 33639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wrightimport android.text.format.DateUtils; 34a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brownimport android.util.EventLog; 35639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wrightimport android.util.MathUtils; 36639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wrightimport android.util.Slog; 37a8edffd804d3940dec1fa5c9777d10beccb2f6a6Soroosh Mariooryadimport android.util.Spline; 38639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wrightimport android.util.TimeUtils; 39639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 40639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wrightimport java.io.PrintWriter; 41639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 42639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wrightclass AutomaticBrightnessController { 43639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private static final String TAG = "AutomaticBrightnessController"; 44639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 45639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private static final boolean DEBUG = false; 46639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private static final boolean DEBUG_PRETEND_LIGHT_SENSOR_ABSENT = false; 47639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 48639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // If true, enables the use of the screen auto-brightness adjustment setting. 49daf7d410fc97647f2b3ab4254f73c09c923018deAdrian Roos private static final boolean USE_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT = true; 50639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 51639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // How long the current sensor reading is assumed to be valid beyond the current time. 52639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // This provides a bit of prediction, as well as ensures that the weight for the last sample is 53639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // non-zero, which in turn ensures that the total weight is non-zero. 54639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private static final long AMBIENT_LIGHT_PREDICTION_TIME_MILLIS = 100; 55639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 56a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown // Debounce for sampling user-initiated changes in display brightness to ensure 57a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown // the user is satisfied with the result before storing the sample. 58a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown private static final int BRIGHTNESS_ADJUSTMENT_SAMPLE_DEBOUNCE_MILLIS = 10000; 59a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown 60639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private static final int MSG_UPDATE_AMBIENT_LUX = 1; 61a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown private static final int MSG_BRIGHTNESS_ADJUSTMENT_SAMPLE = 2; 62639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 630a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright // Length of the ambient light horizon used to calculate the long term estimate of ambient 640a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright // light. 650a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright private static final int AMBIENT_LIGHT_LONG_HORIZON_MILLIS = 10000; 660a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright 670a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright // Length of the ambient light horizon used to calculate short-term estimate of ambient light. 680a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright private static final int AMBIENT_LIGHT_SHORT_HORIZON_MILLIS = 2000; 690a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright 70428aed01e1e2923968027dff57132d8d8d5c4905Julius D'souza // Callbacks for requesting updates to the display's power state 71639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private final Callbacks mCallbacks; 72639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 73639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The sensor manager. 74639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private final SensorManager mSensorManager; 75639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 76639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The light sensor, or null if not available or needed. 77639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private final Sensor mLightSensor; 78639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 79639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The auto-brightness spline adjustment. 80639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The brightness values have been scaled to a range of 0..1. 81639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private final Spline mScreenAutoBrightnessSpline; 82639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 83639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The minimum and maximum screen brightnesses. 84639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private final int mScreenBrightnessRangeMinimum; 85639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private final int mScreenBrightnessRangeMaximum; 86a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski private final float mDozeScaleFactor; 87639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 885d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza // Initial light sensor event rate in milliseconds. 895d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza private final int mInitialLightSensorRate; 905d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza 915d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza // Steady-state light sensor event rate in milliseconds. 925d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza private final int mNormalLightSensorRate; 935d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza 945d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza // The current light sensor event rate in milliseconds. 955d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza private int mCurrentLightSensorRate; 96d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski 97d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski // Stability requirements in milliseconds for accepting a new brightness level. This is used 98d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski // for debouncing the light sensor. Different constants are used to debounce the light sensor 99d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski // when adapting to brighter or darker environments. This parameter controls how quickly 100d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski // brightness changes occur in response to an observed change in light level that exceeds the 101d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski // hysteresis threshold. 102d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski private final long mBrighteningLightDebounceConfig; 103d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski private final long mDarkeningLightDebounceConfig; 104d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski 105d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski // If true immediately after the screen is turned on the controller will try to adjust the 106d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski // brightness based on the current sensor reads. If false, the controller will collect more data 107d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski // and only then decide whether to change brightness. 108d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski private final boolean mResetAmbientLuxAfterWarmUpConfig; 109d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski 1106fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic // Period of time in which to consider light samples in milliseconds. 1116fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic private final int mAmbientLightHorizon; 1126fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic 1136fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic // The intercept used for the weighting calculation. This is used in order to keep all possible 1146fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic // weighting values positive. 1156fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic private final int mWeightingIntercept; 1166fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic 117428aed01e1e2923968027dff57132d8d8d5c4905Julius D'souza // accessor object for determining thresholds to change brightness dynamically 118428aed01e1e2923968027dff57132d8d8d5c4905Julius D'souza private final HysteresisLevels mDynamicHysteresis; 119428aed01e1e2923968027dff57132d8d8d5c4905Julius D'souza 120639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // Amount of time to delay auto-brightness after screen on while waiting for 121639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // the light sensor to warm-up in milliseconds. 122639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // May be 0 if no warm-up is required. 123639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private int mLightSensorWarmUpTimeConfig; 124639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 125639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // Set to true if the light sensor is enabled. 126639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private boolean mLightSensorEnabled; 127639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 128639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The time when the light sensor was enabled. 129639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private long mLightSensorEnableTime; 130639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 131639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The currently accepted nominal ambient light level. 132639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private float mAmbientLux; 133639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 134639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // True if mAmbientLux holds a valid value. 135639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private boolean mAmbientLuxValid; 136639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 137639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The ambient light level threshold at which to brighten or darken the screen. 138639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private float mBrighteningLuxThreshold; 139639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private float mDarkeningLuxThreshold; 140639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 141639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The most recent light sample. 142639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private float mLastObservedLux; 143639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 144639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The time of the most light recent sample. 145639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private long mLastObservedLuxTime; 146639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 147639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The number of light samples collected since the light sensor was enabled. 148639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private int mRecentLightSamples; 149639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 150639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // A ring buffer containing all of the recent ambient light sensor readings. 151639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private AmbientLightRingBuffer mAmbientLightRingBuffer; 152639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 153103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright // A ring buffer containing the light sensor readings for the initial horizon period. 154103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright private AmbientLightRingBuffer mInitialHorizonAmbientLightRingBuffer; 155103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright 156639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The handler 157639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private AutomaticBrightnessHandler mHandler; 158639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 159639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The screen brightness level that has been chosen by the auto-brightness 160639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // algorithm. The actual brightness should ramp towards this value. 161639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // We preserve this value even when we stop using the light sensor so 162639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // that we can quickly revert to the previous auto-brightness level 163639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // while the light sensor warms up. 164639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // Use -1 if there is no current auto-brightness value available. 165639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private int mScreenAutoBrightness = -1; 166639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 167639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The screen auto-brightness adjustment factor in the range -1 (dimmer) to 1 (brighter) 168639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private float mScreenAutoBrightnessAdjustment = 0.0f; 169639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 1706fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic // The maximum range of gamma adjustment possible using the screen 1716fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic // auto-brightness adjustment setting. 1726fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic private float mScreenAutoBrightnessAdjustmentMaxGamma; 1736fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic 174639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The last screen auto-brightness gamma. (For printing in dump() only.) 175639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private float mLastScreenAutoBrightnessGamma = 1.0f; 176639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 177a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski // Are we going to adjust brightness while dozing. 178a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski private boolean mDozing; 179a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski 180a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown // True if we are collecting a brightness adjustment sample, along with some data 181a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown // for the initial state of the sample. 182a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown private boolean mBrightnessAdjustmentSamplePending; 183a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown private float mBrightnessAdjustmentSampleOldAdjustment; 184a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown private float mBrightnessAdjustmentSampleOldLux; 185a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown private int mBrightnessAdjustmentSampleOldBrightness; 186a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown private float mBrightnessAdjustmentSampleOldGamma; 187a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown 188639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public AutomaticBrightnessController(Callbacks callbacks, Looper looper, 189a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski SensorManager sensorManager, Spline autoBrightnessSpline, int lightSensorWarmUpTime, 190d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski int brightnessMin, int brightnessMax, float dozeScaleFactor, 1915d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza int lightSensorRate, int initialLightSensorRate, long brighteningLightDebounceConfig, 1926fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic long darkeningLightDebounceConfig, boolean resetAmbientLuxAfterWarmUpConfig, 193428aed01e1e2923968027dff57132d8d8d5c4905Julius D'souza int ambientLightHorizon, float autoBrightnessAdjustmentMaxGamma, 194428aed01e1e2923968027dff57132d8d8d5c4905Julius D'souza HysteresisLevels dynamicHysteresis) { 195639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mCallbacks = callbacks; 196639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mSensorManager = sensorManager; 197639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mScreenAutoBrightnessSpline = autoBrightnessSpline; 198639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mScreenBrightnessRangeMinimum = brightnessMin; 199639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mScreenBrightnessRangeMaximum = brightnessMax; 200639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mLightSensorWarmUpTimeConfig = lightSensorWarmUpTime; 201a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski mDozeScaleFactor = dozeScaleFactor; 2025d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza mNormalLightSensorRate = lightSensorRate; 2035d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza mInitialLightSensorRate = initialLightSensorRate; 2045d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza mCurrentLightSensorRate = -1; 205d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski mBrighteningLightDebounceConfig = brighteningLightDebounceConfig; 206d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski mDarkeningLightDebounceConfig = darkeningLightDebounceConfig; 207d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski mResetAmbientLuxAfterWarmUpConfig = resetAmbientLuxAfterWarmUpConfig; 2086fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic mAmbientLightHorizon = ambientLightHorizon; 2096fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic mWeightingIntercept = ambientLightHorizon; 2106fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic mScreenAutoBrightnessAdjustmentMaxGamma = autoBrightnessAdjustmentMaxGamma; 211428aed01e1e2923968027dff57132d8d8d5c4905Julius D'souza mDynamicHysteresis = dynamicHysteresis; 212639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 213639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mHandler = new AutomaticBrightnessHandler(looper); 214103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright mAmbientLightRingBuffer = 2155d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza new AmbientLightRingBuffer(mNormalLightSensorRate, mAmbientLightHorizon); 216103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright mInitialHorizonAmbientLightRingBuffer = 2175d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza new AmbientLightRingBuffer(mNormalLightSensorRate, mAmbientLightHorizon); 218639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 219639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (!DEBUG_PRETEND_LIGHT_SENSOR_ABSENT) { 220639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); 221639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 222639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 223639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 224639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public int getAutomaticScreenBrightness() { 225a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski if (mDozing) { 226a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski return (int) (mScreenAutoBrightness * mDozeScaleFactor); 227a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski } 228639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return mScreenAutoBrightness; 229639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 230639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 231a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown public void configure(boolean enable, float adjustment, boolean dozing, 2325483cea67a60d3c5012fa7120f62e6eacc6ad3baJustin Klaassen boolean userInitiatedChange) { 233a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski // While dozing, the application processor may be suspended which will prevent us from 234a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski // receiving new information from the light sensor. On some devices, we may be able to 235a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski // switch to a wake-up light sensor instead but for now we will simply disable the sensor 236a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski // and hold onto the last computed screen auto brightness. We save the dozing flag for 237a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski // debugging purposes. 238a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski mDozing = dozing; 239a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski boolean changed = setLightSensorEnabled(enable && !dozing); 240a8edffd804d3940dec1fa5c9777d10beccb2f6a6Soroosh Mariooryad if (enable && !dozing && userInitiatedChange) { 241a8edffd804d3940dec1fa5c9777d10beccb2f6a6Soroosh Mariooryad prepareBrightnessAdjustmentSample(); 242a8edffd804d3940dec1fa5c9777d10beccb2f6a6Soroosh Mariooryad } 243970d4132ea28e748c1010be39450a98bbf7466f3Jeff Brown changed |= setScreenAutoBrightnessAdjustment(adjustment); 244970d4132ea28e748c1010be39450a98bbf7466f3Jeff Brown if (changed) { 245639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright updateAutoBrightness(false /*sendUpdate*/); 246639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 247639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 248639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 249639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public void dump(PrintWriter pw) { 250639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(); 251639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println("Automatic Brightness Controller Configuration:"); 252639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mScreenAutoBrightnessSpline=" + mScreenAutoBrightnessSpline); 253639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum); 254639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum); 255639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mLightSensorWarmUpTimeConfig=" + mLightSensorWarmUpTimeConfig); 256d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski pw.println(" mBrighteningLightDebounceConfig=" + mBrighteningLightDebounceConfig); 257d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski pw.println(" mDarkeningLightDebounceConfig=" + mDarkeningLightDebounceConfig); 258d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski pw.println(" mResetAmbientLuxAfterWarmUpConfig=" + mResetAmbientLuxAfterWarmUpConfig); 259639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 260639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(); 261639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println("Automatic Brightness Controller State:"); 262639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mLightSensor=" + mLightSensor); 263639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mLightSensorEnabled=" + mLightSensorEnabled); 264639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mLightSensorEnableTime=" + TimeUtils.formatUptime(mLightSensorEnableTime)); 265639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mAmbientLux=" + mAmbientLux); 2666fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic pw.println(" mAmbientLightHorizon=" + mAmbientLightHorizon); 267639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mBrighteningLuxThreshold=" + mBrighteningLuxThreshold); 268639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mDarkeningLuxThreshold=" + mDarkeningLuxThreshold); 269639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mLastObservedLux=" + mLastObservedLux); 270639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mLastObservedLuxTime=" + TimeUtils.formatUptime(mLastObservedLuxTime)); 271639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mRecentLightSamples=" + mRecentLightSamples); 272639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mAmbientLightRingBuffer=" + mAmbientLightRingBuffer); 273103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright pw.println(" mInitialHorizonAmbientLightRingBuffer=" + 274103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright mInitialHorizonAmbientLightRingBuffer); 275639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mScreenAutoBrightness=" + mScreenAutoBrightness); 276639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mScreenAutoBrightnessAdjustment=" + mScreenAutoBrightnessAdjustment); 2776fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic pw.println(" mScreenAutoBrightnessAdjustmentMaxGamma=" + mScreenAutoBrightnessAdjustmentMaxGamma); 278639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mLastScreenAutoBrightnessGamma=" + mLastScreenAutoBrightnessGamma); 279a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski pw.println(" mDozing=" + mDozing); 280639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 281639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 282639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private boolean setLightSensorEnabled(boolean enable) { 283639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (enable) { 284639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (!mLightSensorEnabled) { 285639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mLightSensorEnabled = true; 286639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mLightSensorEnableTime = SystemClock.uptimeMillis(); 2875d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza mCurrentLightSensorRate = mInitialLightSensorRate; 288639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mSensorManager.registerListener(mLightSensorListener, mLightSensor, 2895d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza mCurrentLightSensorRate * 1000, mHandler); 290639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return true; 291639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 292639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } else { 293639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (mLightSensorEnabled) { 294639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mLightSensorEnabled = false; 295d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski mAmbientLuxValid = !mResetAmbientLuxAfterWarmUpConfig; 296639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mRecentLightSamples = 0; 297639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mAmbientLightRingBuffer.clear(); 298103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright mInitialHorizonAmbientLightRingBuffer.clear(); 2995d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza mCurrentLightSensorRate = -1; 300639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mHandler.removeMessages(MSG_UPDATE_AMBIENT_LUX); 301639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mSensorManager.unregisterListener(mLightSensorListener); 302639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 303639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 304639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return false; 305639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 306639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 307639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private void handleLightSensorEvent(long time, float lux) { 308b0a1d3d08fc459e0d9937e299e16de17d1388ac4Michael Wright Trace.traceCounter(Trace.TRACE_TAG_POWER, "ALS", (int) lux); 309639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mHandler.removeMessages(MSG_UPDATE_AMBIENT_LUX); 310639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 3115d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza if (mAmbientLightRingBuffer.size() == 0) { 3125d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza // switch to using the steady-state sample rate after grabbing the initial light sample 3135d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza adjustLightSensorRate(mNormalLightSensorRate); 3145d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza } 315639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright applyLightSensorMeasurement(time, lux); 316639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright updateAmbientLux(time); 317639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 318639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 319639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private void applyLightSensorMeasurement(long time, float lux) { 320639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mRecentLightSamples++; 321103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright // Store all of the light measurements for the intial horizon period. This is to help 322103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright // diagnose dim wake ups and slow responses in b/27951906. 323103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright if (time <= mLightSensorEnableTime + mAmbientLightHorizon) { 324103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright mInitialHorizonAmbientLightRingBuffer.push(time, lux); 325103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright } 3266fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic mAmbientLightRingBuffer.prune(time - mAmbientLightHorizon); 327639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mAmbientLightRingBuffer.push(time, lux); 328639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 329639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // Remember this sample value. 330639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mLastObservedLux = lux; 331639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mLastObservedLuxTime = time; 332639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 333639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 3345d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza private void adjustLightSensorRate(int lightSensorRate) { 3355d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza // if the light sensor rate changed, update the sensor listener 3365d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza if (lightSensorRate != mCurrentLightSensorRate) { 3375d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza if (DEBUG) { 3385d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza Slog.d(TAG, "adjustLightSensorRate: previousRate=" + mCurrentLightSensorRate 3395d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza + ", currentRate=" + lightSensorRate); 3405d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza } 3415d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza mCurrentLightSensorRate = lightSensorRate; 3425d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza mSensorManager.unregisterListener(mLightSensorListener); 3435d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza mSensorManager.registerListener(mLightSensorListener, mLightSensor, 3445d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza lightSensorRate * 1000, mHandler); 3455d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza } 3465d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza } 3475d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza 348639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private boolean setScreenAutoBrightnessAdjustment(float adjustment) { 349639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (adjustment != mScreenAutoBrightnessAdjustment) { 350639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mScreenAutoBrightnessAdjustment = adjustment; 351639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return true; 352639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 353639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return false; 354639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 355639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 356639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private void setAmbientLux(float lux) { 3570a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright if (DEBUG) { 3580a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright Slog.d(TAG, "setAmbientLux(" + lux + ")"); 3590a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright } 360639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mAmbientLux = lux; 361428aed01e1e2923968027dff57132d8d8d5c4905Julius D'souza mBrighteningLuxThreshold = mDynamicHysteresis.getBrighteningThreshold(lux); 362428aed01e1e2923968027dff57132d8d8d5c4905Julius D'souza mDarkeningLuxThreshold = mDynamicHysteresis.getDarkeningThreshold(lux); 363639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 364639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 3650a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright private float calculateAmbientLux(long now, long horizon) { 3660a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright if (DEBUG) { 3670a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright Slog.d(TAG, "calculateAmbientLux(" + now + ", " + horizon + ")"); 3680a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright } 369639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright final int N = mAmbientLightRingBuffer.size(); 370639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (N == 0) { 371639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright Slog.e(TAG, "calculateAmbientLux: No ambient light readings available"); 372639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return -1; 373639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 3740a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright 3750a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright // Find the first measurement that is just outside of the horizon. 3760a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright int endIndex = 0; 3770a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright final long horizonStartTime = now - horizon; 3780a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright for (int i = 0; i < N-1; i++) { 3790a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright if (mAmbientLightRingBuffer.getTime(i + 1) <= horizonStartTime) { 3800a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright endIndex++; 3810a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright } else { 3820a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright break; 3830a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright } 3840a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright } 3850a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright if (DEBUG) { 3860a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright Slog.d(TAG, "calculateAmbientLux: selected endIndex=" + endIndex + ", point=(" 3870a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright + mAmbientLightRingBuffer.getTime(endIndex) + ", " 3880a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright + mAmbientLightRingBuffer.getLux(endIndex) 3890a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright + ")"); 3900a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright } 391639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright float sum = 0; 392639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright float totalWeight = 0; 393639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright long endTime = AMBIENT_LIGHT_PREDICTION_TIME_MILLIS; 3940a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright for (int i = N - 1; i >= endIndex; i--) { 3950a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright long eventTime = mAmbientLightRingBuffer.getTime(i); 3960a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright if (i == endIndex && eventTime < horizonStartTime) { 3970a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright // If we're at the final value, make sure we only consider the part of the sample 3980a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright // within our desired horizon. 3990a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright eventTime = horizonStartTime; 4000a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright } 4010a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright final long startTime = eventTime - now; 402639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright float weight = calculateWeight(startTime, endTime); 403639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright float lux = mAmbientLightRingBuffer.getLux(i); 404639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (DEBUG) { 405639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright Slog.d(TAG, "calculateAmbientLux: [" + 406639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright (startTime) + ", " + 407639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright (endTime) + "]: lux=" + lux + ", weight=" + weight); 408639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 409639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright totalWeight += weight; 410639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright sum += mAmbientLightRingBuffer.getLux(i) * weight; 411639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright endTime = startTime; 412639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 413639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (DEBUG) { 414639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright Slog.d(TAG, "calculateAmbientLux: totalWeight=" + totalWeight + 415639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright ", newAmbientLux=" + (sum / totalWeight)); 416639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 417639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return sum / totalWeight; 418639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 419639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 4206fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic private float calculateWeight(long startDelta, long endDelta) { 421639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return weightIntegral(endDelta) - weightIntegral(startDelta); 422639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 423639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 4246fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic // Evaluates the integral of y = x + mWeightingIntercept. This is always positive for the 425639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // horizon we're looking at and provides a non-linear weighting for light samples. 4266fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic private float weightIntegral(long x) { 4276fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic return x * (x * 0.5f + mWeightingIntercept); 428639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 429639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 430639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private long nextAmbientLightBrighteningTransition(long time) { 431639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright final int N = mAmbientLightRingBuffer.size(); 432639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright long earliestValidTime = time; 433639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright for (int i = N - 1; i >= 0; i--) { 434639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (mAmbientLightRingBuffer.getLux(i) <= mBrighteningLuxThreshold) { 435639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright break; 436639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 437639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright earliestValidTime = mAmbientLightRingBuffer.getTime(i); 438639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 439d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski return earliestValidTime + mBrighteningLightDebounceConfig; 440639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 441639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 442639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private long nextAmbientLightDarkeningTransition(long time) { 443639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright final int N = mAmbientLightRingBuffer.size(); 444639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright long earliestValidTime = time; 445639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright for (int i = N - 1; i >= 0; i--) { 446639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (mAmbientLightRingBuffer.getLux(i) >= mDarkeningLuxThreshold) { 447639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright break; 448639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 449639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright earliestValidTime = mAmbientLightRingBuffer.getTime(i); 450639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 451d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski return earliestValidTime + mDarkeningLightDebounceConfig; 452639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 453639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 454639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private void updateAmbientLux() { 455639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright long time = SystemClock.uptimeMillis(); 4566fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic mAmbientLightRingBuffer.prune(time - mAmbientLightHorizon); 457639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright updateAmbientLux(time); 458639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 459639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 460639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private void updateAmbientLux(long time) { 461639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // If the light sensor was just turned on then immediately update our initial 462639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // estimate of the current ambient light level. 463639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (!mAmbientLuxValid) { 464639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright final long timeWhenSensorWarmedUp = 465639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mLightSensorWarmUpTimeConfig + mLightSensorEnableTime; 466639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (time < timeWhenSensorWarmedUp) { 467639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (DEBUG) { 468639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright Slog.d(TAG, "updateAmbientLux: Sensor not ready yet: " 469639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + "time=" + time 470639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + ", timeWhenSensorWarmedUp=" + timeWhenSensorWarmedUp); 471639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 472639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mHandler.sendEmptyMessageAtTime(MSG_UPDATE_AMBIENT_LUX, 473639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright timeWhenSensorWarmedUp); 474639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return; 475639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 4760a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright setAmbientLux(calculateAmbientLux(time, AMBIENT_LIGHT_SHORT_HORIZON_MILLIS)); 477639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mAmbientLuxValid = true; 478639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (DEBUG) { 479639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright Slog.d(TAG, "updateAmbientLux: Initializing: " 480639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + "mAmbientLightRingBuffer=" + mAmbientLightRingBuffer 481639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + ", mAmbientLux=" + mAmbientLux); 482639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 483639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright updateAutoBrightness(true); 484639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 485639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 486639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright long nextBrightenTransition = nextAmbientLightBrighteningTransition(time); 487639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright long nextDarkenTransition = nextAmbientLightDarkeningTransition(time); 4880a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright // Essentially, we calculate both a slow ambient lux, to ensure there's a true long-term 4890a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright // change in lighting conditions, and a fast ambient lux to determine what the new 4900a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright // brightness situation is since the slow lux can be quite slow to converge. 4910a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright // 4920a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright // Note that both values need to be checked for sufficient change before updating the 4930a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright // proposed ambient light value since the slow value might be sufficiently far enough away 4940a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright // from the fast value to cause a recalculation while its actually just converging on 4950a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright // the fast value still. 4960a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright float slowAmbientLux = calculateAmbientLux(time, AMBIENT_LIGHT_LONG_HORIZON_MILLIS); 4970a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright float fastAmbientLux = calculateAmbientLux(time, AMBIENT_LIGHT_SHORT_HORIZON_MILLIS); 4980a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright 4990a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright if (slowAmbientLux >= mBrighteningLuxThreshold && 5000a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright fastAmbientLux >= mBrighteningLuxThreshold && nextBrightenTransition <= time 5010a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright || slowAmbientLux <= mDarkeningLuxThreshold 5020a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright && fastAmbientLux <= mDarkeningLuxThreshold && nextDarkenTransition <= time) { 5030a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright setAmbientLux(fastAmbientLux); 504639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (DEBUG) { 505639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright Slog.d(TAG, "updateAmbientLux: " 5060a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright + ((fastAmbientLux > mAmbientLux) ? "Brightened" : "Darkened") + ": " 507639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + "mBrighteningLuxThreshold=" + mBrighteningLuxThreshold 508639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + ", mAmbientLightRingBuffer=" + mAmbientLightRingBuffer 509639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + ", mAmbientLux=" + mAmbientLux); 510639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 511639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright updateAutoBrightness(true); 512639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright nextBrightenTransition = nextAmbientLightBrighteningTransition(time); 513639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright nextDarkenTransition = nextAmbientLightDarkeningTransition(time); 514639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 515639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright long nextTransitionTime = Math.min(nextDarkenTransition, nextBrightenTransition); 516639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // If one of the transitions is ready to occur, but the total weighted ambient lux doesn't 517639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // exceed the necessary threshold, then it's possible we'll get a transition time prior to 518639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // now. Rather than continually checking to see whether the weighted lux exceeds the 519639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // threshold, schedule an update for when we'd normally expect another light sample, which 520639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // should be enough time to decide whether we should actually transition to the new 521639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // weighted ambient lux or not. 522639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright nextTransitionTime = 5235d7170963ac0cfa30400292841c3673b8cdea5b5Julius D'souza nextTransitionTime > time ? nextTransitionTime : time + mNormalLightSensorRate; 524639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (DEBUG) { 525639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright Slog.d(TAG, "updateAmbientLux: Scheduling ambient lux update for " 526639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + nextTransitionTime + TimeUtils.formatUptime(nextTransitionTime)); 527639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 528639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mHandler.sendEmptyMessageAtTime(MSG_UPDATE_AMBIENT_LUX, nextTransitionTime); 529639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 530639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 531639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private void updateAutoBrightness(boolean sendUpdate) { 532639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (!mAmbientLuxValid) { 533639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return; 534639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 535639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 536639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright float value = mScreenAutoBrightnessSpline.interpolate(mAmbientLux); 537639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright float gamma = 1.0f; 538639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 539639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (USE_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT 540639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright && mScreenAutoBrightnessAdjustment != 0.0f) { 5416fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic final float adjGamma = MathUtils.pow(mScreenAutoBrightnessAdjustmentMaxGamma, 542639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright Math.min(1.0f, Math.max(-1.0f, -mScreenAutoBrightnessAdjustment))); 543639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright gamma *= adjGamma; 544639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (DEBUG) { 545639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright Slog.d(TAG, "updateAutoBrightness: adjGamma=" + adjGamma); 546639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 547639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 548639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 549639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (gamma != 1.0f) { 550639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright final float in = value; 551639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright value = MathUtils.pow(value, gamma); 552639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (DEBUG) { 553639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright Slog.d(TAG, "updateAutoBrightness: gamma=" + gamma 554639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + ", in=" + in + ", out=" + value); 555639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 556639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 557639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 558639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright int newScreenAutoBrightness = 559a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown clampScreenBrightness(Math.round(value * PowerManager.BRIGHTNESS_ON)); 560639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (mScreenAutoBrightness != newScreenAutoBrightness) { 561639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (DEBUG) { 562639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright Slog.d(TAG, "updateAutoBrightness: mScreenAutoBrightness=" 563639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + mScreenAutoBrightness + ", newScreenAutoBrightness=" 564639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + newScreenAutoBrightness); 565639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 566639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 567639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mScreenAutoBrightness = newScreenAutoBrightness; 568639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mLastScreenAutoBrightnessGamma = gamma; 569639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (sendUpdate) { 570639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mCallbacks.updateBrightness(); 571639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 572639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 573639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 574639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 575639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private int clampScreenBrightness(int value) { 576639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return MathUtils.constrain(value, 577639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mScreenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum); 578639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 579639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 580a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown private void prepareBrightnessAdjustmentSample() { 581a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown if (!mBrightnessAdjustmentSamplePending) { 582a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mBrightnessAdjustmentSamplePending = true; 583a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mBrightnessAdjustmentSampleOldAdjustment = mScreenAutoBrightnessAdjustment; 584a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mBrightnessAdjustmentSampleOldLux = mAmbientLuxValid ? mAmbientLux : -1; 585a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mBrightnessAdjustmentSampleOldBrightness = mScreenAutoBrightness; 586a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mBrightnessAdjustmentSampleOldGamma = mLastScreenAutoBrightnessGamma; 587a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown } else { 588a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mHandler.removeMessages(MSG_BRIGHTNESS_ADJUSTMENT_SAMPLE); 589a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown } 590a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown 591a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mHandler.sendEmptyMessageDelayed(MSG_BRIGHTNESS_ADJUSTMENT_SAMPLE, 592a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown BRIGHTNESS_ADJUSTMENT_SAMPLE_DEBOUNCE_MILLIS); 593a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown } 594a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown 595a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown private void cancelBrightnessAdjustmentSample() { 596a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown if (mBrightnessAdjustmentSamplePending) { 597a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mBrightnessAdjustmentSamplePending = false; 598a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mHandler.removeMessages(MSG_BRIGHTNESS_ADJUSTMENT_SAMPLE); 599a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown } 600a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown } 601a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown 602a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown private void collectBrightnessAdjustmentSample() { 603a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown if (mBrightnessAdjustmentSamplePending) { 604a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mBrightnessAdjustmentSamplePending = false; 605a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown if (mAmbientLuxValid && mScreenAutoBrightness >= 0) { 606a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown if (DEBUG) { 607a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown Slog.d(TAG, "Auto-brightness adjustment changed by user: " 608a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown + "adj=" + mScreenAutoBrightnessAdjustment 609a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown + ", lux=" + mAmbientLux 610a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown + ", brightness=" + mScreenAutoBrightness 611a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown + ", gamma=" + mLastScreenAutoBrightnessGamma 612a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown + ", ring=" + mAmbientLightRingBuffer); 613a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown } 614a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown 615a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown EventLog.writeEvent(EventLogTags.AUTO_BRIGHTNESS_ADJ, 616a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mBrightnessAdjustmentSampleOldAdjustment, 617a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mBrightnessAdjustmentSampleOldLux, 618a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mBrightnessAdjustmentSampleOldBrightness, 619a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mBrightnessAdjustmentSampleOldGamma, 620a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mScreenAutoBrightnessAdjustment, 621a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mAmbientLux, 622a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mScreenAutoBrightness, 623a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mLastScreenAutoBrightnessGamma); 624a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown } 625a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown } 626a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown } 627a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown 628639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private final class AutomaticBrightnessHandler extends Handler { 629639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public AutomaticBrightnessHandler(Looper looper) { 630639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright super(looper, null, true /*async*/); 631639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 632639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 633639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright @Override 634639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public void handleMessage(Message msg) { 635639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright switch (msg.what) { 636639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright case MSG_UPDATE_AMBIENT_LUX: 637639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright updateAmbientLux(); 638639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright break; 639a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown 640a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown case MSG_BRIGHTNESS_ADJUSTMENT_SAMPLE: 641a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown collectBrightnessAdjustmentSample(); 642a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown break; 643639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 644639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 645639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 646639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 647639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private final SensorEventListener mLightSensorListener = new SensorEventListener() { 648639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright @Override 649639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public void onSensorChanged(SensorEvent event) { 650639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (mLightSensorEnabled) { 651639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright final long time = SystemClock.uptimeMillis(); 652639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright final float lux = event.values[0]; 653639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright handleLightSensorEvent(time, lux); 654639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 655639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 656639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 657639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright @Override 658639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public void onAccuracyChanged(Sensor sensor, int accuracy) { 659639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // Not used. 660639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 661639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright }; 662639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 663639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright /** Callbacks to request updates to the display's power state. */ 664639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright interface Callbacks { 665639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright void updateBrightness(); 666639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 667639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 6680a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright /** 6690a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright * A ring buffer of ambient light measurements sorted by time. 6700a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright * 6710a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright * Each entry consists of a timestamp and a lux measurement, and the overall buffer is sorted 6720a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright * from oldest to newest. 6730a933141e2dd72bc868598cfa2146b2c72b85d5dMichael Wright */ 674103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright private static final class AmbientLightRingBuffer { 675639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // Proportional extra capacity of the buffer beyond the expected number of light samples 676639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // in the horizon 677639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private static final float BUFFER_SLACK = 1.5f; 678639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private float[] mRingLux; 679639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private long[] mRingTime; 680639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private int mCapacity; 681639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 682639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The first valid element and the next open slot. 683639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // Note that if mCount is zero then there are no valid elements. 684639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private int mStart; 685639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private int mEnd; 686639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private int mCount; 687639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 6886fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic public AmbientLightRingBuffer(long lightSensorRate, int ambientLightHorizon) { 6896fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic mCapacity = (int) Math.ceil(ambientLightHorizon * BUFFER_SLACK / lightSensorRate); 690639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mRingLux = new float[mCapacity]; 691639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mRingTime = new long[mCapacity]; 692639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 693639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 694639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public float getLux(int index) { 695639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return mRingLux[offsetOf(index)]; 696639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 697639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 698639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public long getTime(int index) { 699639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return mRingTime[offsetOf(index)]; 700639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 701639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 702639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public void push(long time, float lux) { 703639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright int next = mEnd; 704639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (mCount == mCapacity) { 705639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright int newSize = mCapacity * 2; 706639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 707639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright float[] newRingLux = new float[newSize]; 708639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright long[] newRingTime = new long[newSize]; 709639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright int length = mCapacity - mStart; 710639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright System.arraycopy(mRingLux, mStart, newRingLux, 0, length); 711639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright System.arraycopy(mRingTime, mStart, newRingTime, 0, length); 712639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (mStart != 0) { 713639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright System.arraycopy(mRingLux, 0, newRingLux, length, mStart); 714639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright System.arraycopy(mRingTime, 0, newRingTime, length, mStart); 715639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 716639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mRingLux = newRingLux; 717639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mRingTime = newRingTime; 718639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 719639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright next = mCapacity; 720639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mCapacity = newSize; 721639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mStart = 0; 722639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 723639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mRingTime[next] = time; 724639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mRingLux[next] = lux; 725639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mEnd = next + 1; 726639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (mEnd == mCapacity) { 727639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mEnd = 0; 728639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 729639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mCount++; 730639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 731639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 732639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public void prune(long horizon) { 733639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (mCount == 0) { 734639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return; 735639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 736639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 737639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright while (mCount > 1) { 738639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright int next = mStart + 1; 739639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (next >= mCapacity) { 740639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright next -= mCapacity; 741639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 742639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (mRingTime[next] > horizon) { 743639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // Some light sensors only produce data upon a change in the ambient light 744639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // levels, so we need to consider the previous measurement as the ambient light 745639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // level for all points in time up until we receive a new measurement. Thus, we 746639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // always want to keep the youngest element that would be removed from the 747639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // buffer and just set its measurement time to the horizon time since at that 748639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // point it is the ambient light level, and to remove it would be to drop a 749639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // valid data point within our horizon. 750639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright break; 751639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 752639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mStart = next; 753639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mCount -= 1; 754639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 755639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 756639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (mRingTime[mStart] < horizon) { 757639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mRingTime[mStart] = horizon; 758639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 759639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 760639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 761639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public int size() { 762639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return mCount; 763639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 764639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 765639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public void clear() { 766639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mStart = 0; 767639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mEnd = 0; 768639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mCount = 0; 769639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 770639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 771639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright @Override 772639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public String toString() { 773a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown StringBuffer buf = new StringBuffer(); 774a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown buf.append('['); 775a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown for (int i = 0; i < mCount; i++) { 776a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown final long next = i + 1 < mCount ? getTime(i + 1) : SystemClock.uptimeMillis(); 777a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown if (i != 0) { 778a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown buf.append(", "); 779a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown } 780a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown buf.append(getLux(i)); 781a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown buf.append(" / "); 782a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown buf.append(next - getTime(i)); 783a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown buf.append("ms"); 784639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 785a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown buf.append(']'); 786a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown return buf.toString(); 787639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 788639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 789639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private int offsetOf(int index) { 790639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (index >= mCount || index < 0) { 791639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright throw new ArrayIndexOutOfBoundsException(index); 792639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 793639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright index += mStart; 794639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (index >= mCapacity) { 795639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright index -= mCapacity; 796639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 797639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return index; 798639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 799639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 800639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright} 801