AutomaticBrightnessController.java revision 908b86c796443ba4ec55c669e8a0297fc80574a6
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 Wrightimport com.android.server.twilight.TwilightListener; 22639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wrightimport com.android.server.twilight.TwilightManager; 23639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wrightimport com.android.server.twilight.TwilightState; 24639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 25908b86c796443ba4ec55c669e8a0297fc80574a6Justin Klaassenimport android.annotation.Nullable; 26639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wrightimport android.hardware.Sensor; 27639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wrightimport android.hardware.SensorEvent; 28639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wrightimport android.hardware.SensorEventListener; 29639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wrightimport android.hardware.SensorManager; 30639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wrightimport android.os.Handler; 31639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wrightimport android.os.Looper; 32639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wrightimport android.os.Message; 33639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wrightimport android.os.PowerManager; 34639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wrightimport android.os.SystemClock; 35639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wrightimport android.text.format.DateUtils; 36a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brownimport android.util.EventLog; 37639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wrightimport android.util.MathUtils; 38639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wrightimport android.util.Spline; 39639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wrightimport android.util.Slog; 40639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wrightimport android.util.TimeUtils; 41639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 42639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wrightimport java.io.PrintWriter; 43639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 44639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wrightclass AutomaticBrightnessController { 45639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private static final String TAG = "AutomaticBrightnessController"; 46639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 47639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private static final boolean DEBUG = false; 48639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private static final boolean DEBUG_PRETEND_LIGHT_SENSOR_ABSENT = false; 49639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 50639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // If true, enables the use of the screen auto-brightness adjustment setting. 51daf7d410fc97647f2b3ab4254f73c09c923018deAdrian Roos private static final boolean USE_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT = true; 52639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 53639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // Hysteresis constraints for brightening or darkening. 54639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The recent lux must have changed by at least this fraction relative to the 55639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // current ambient lux before a change will be considered. 56639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private static final float BRIGHTENING_LIGHT_HYSTERESIS = 0.10f; 57639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private static final float DARKENING_LIGHT_HYSTERESIS = 0.20f; 58639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 59639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // How long the current sensor reading is assumed to be valid beyond the current time. 60639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // This provides a bit of prediction, as well as ensures that the weight for the last sample is 61639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // non-zero, which in turn ensures that the total weight is non-zero. 62639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private static final long AMBIENT_LIGHT_PREDICTION_TIME_MILLIS = 100; 63639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 64639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // Specifies the maximum magnitude of the time of day adjustment. 655dbd4aad809e6fec51df62280bcc1bfe05cc7df5Jason Monk private static final float TWILIGHT_ADJUSTMENT_MAX_GAMMA = 1f; 66639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 67a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown // Debounce for sampling user-initiated changes in display brightness to ensure 68a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown // the user is satisfied with the result before storing the sample. 69a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown private static final int BRIGHTNESS_ADJUSTMENT_SAMPLE_DEBOUNCE_MILLIS = 10000; 70a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown 71639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private static final int MSG_UPDATE_AMBIENT_LUX = 1; 72a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown private static final int MSG_BRIGHTNESS_ADJUSTMENT_SAMPLE = 2; 73639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 74639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // Callbacks for requesting updates to the the display's power state 75639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private final Callbacks mCallbacks; 76639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 77639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The sensor manager. 78639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private final SensorManager mSensorManager; 79639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 80639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The light sensor, or null if not available or needed. 81639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private final Sensor mLightSensor; 82639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 83639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The twilight service. 84639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private final TwilightManager mTwilight; 85639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 86639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The auto-brightness spline adjustment. 87639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The brightness values have been scaled to a range of 0..1. 88639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private final Spline mScreenAutoBrightnessSpline; 89639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 90639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The minimum and maximum screen brightnesses. 91639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private final int mScreenBrightnessRangeMinimum; 92639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private final int mScreenBrightnessRangeMaximum; 93a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski private final float mDozeScaleFactor; 94639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 95d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski // Light sensor event rate in milliseconds. 96d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski private final int mLightSensorRate; 97d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski 98d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski // Stability requirements in milliseconds for accepting a new brightness level. This is used 99d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski // for debouncing the light sensor. Different constants are used to debounce the light sensor 100d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski // when adapting to brighter or darker environments. This parameter controls how quickly 101d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski // brightness changes occur in response to an observed change in light level that exceeds the 102d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski // hysteresis threshold. 103d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski private final long mBrighteningLightDebounceConfig; 104d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski private final long mDarkeningLightDebounceConfig; 105d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski 106d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski // If true immediately after the screen is turned on the controller will try to adjust the 107d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski // brightness based on the current sensor reads. If false, the controller will collect more data 108d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski // and only then decide whether to change brightness. 109d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski private final boolean mResetAmbientLuxAfterWarmUpConfig; 110d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski 1116fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic // Period of time in which to consider light samples in milliseconds. 1126fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic private final int mAmbientLightHorizon; 1136fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic 1146fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic // The intercept used for the weighting calculation. This is used in order to keep all possible 1156fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic // weighting values positive. 1166fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic private final int mWeightingIntercept; 1176fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic 118639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // Amount of time to delay auto-brightness after screen on while waiting for 119639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // the light sensor to warm-up in milliseconds. 120639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // May be 0 if no warm-up is required. 121639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private int mLightSensorWarmUpTimeConfig; 122639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 123639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // Set to true if the light sensor is enabled. 124639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private boolean mLightSensorEnabled; 125639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 126639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The time when the light sensor was enabled. 127639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private long mLightSensorEnableTime; 128639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 129639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The currently accepted nominal ambient light level. 130639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private float mAmbientLux; 131639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 132639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // True if mAmbientLux holds a valid value. 133639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private boolean mAmbientLuxValid; 134639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 135639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The ambient light level threshold at which to brighten or darken the screen. 136639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private float mBrighteningLuxThreshold; 137639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private float mDarkeningLuxThreshold; 138639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 139639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The most recent light sample. 140639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private float mLastObservedLux; 141639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 142639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The time of the most light recent sample. 143639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private long mLastObservedLuxTime; 144639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 145639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The number of light samples collected since the light sensor was enabled. 146639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private int mRecentLightSamples; 147639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 148639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // A ring buffer containing all of the recent ambient light sensor readings. 149639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private AmbientLightRingBuffer mAmbientLightRingBuffer; 150639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 151103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright // A ring buffer containing the light sensor readings for the initial horizon period. 152103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright private AmbientLightRingBuffer mInitialHorizonAmbientLightRingBuffer; 153103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright 154639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The handler 155639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private AutomaticBrightnessHandler mHandler; 156639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 157639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The screen brightness level that has been chosen by the auto-brightness 158639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // algorithm. The actual brightness should ramp towards this value. 159639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // We preserve this value even when we stop using the light sensor so 160639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // that we can quickly revert to the previous auto-brightness level 161639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // while the light sensor warms up. 162639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // Use -1 if there is no current auto-brightness value available. 163639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private int mScreenAutoBrightness = -1; 164639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 165639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The screen auto-brightness adjustment factor in the range -1 (dimmer) to 1 (brighter) 166639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private float mScreenAutoBrightnessAdjustment = 0.0f; 167639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 1686fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic // The maximum range of gamma adjustment possible using the screen 1696fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic // auto-brightness adjustment setting. 1706fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic private float mScreenAutoBrightnessAdjustmentMaxGamma; 1716fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic 172639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The last screen auto-brightness gamma. (For printing in dump() only.) 173639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private float mLastScreenAutoBrightnessGamma = 1.0f; 174639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 175a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski // Are we going to adjust brightness while dozing. 176a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski private boolean mDozing; 177a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski 178a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown // True if we are collecting a brightness adjustment sample, along with some data 179a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown // for the initial state of the sample. 180a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown private boolean mBrightnessAdjustmentSamplePending; 181a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown private float mBrightnessAdjustmentSampleOldAdjustment; 182a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown private float mBrightnessAdjustmentSampleOldLux; 183a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown private int mBrightnessAdjustmentSampleOldBrightness; 184a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown private float mBrightnessAdjustmentSampleOldGamma; 185a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown 1865dbd4aad809e6fec51df62280bcc1bfe05cc7df5Jason Monk private boolean mUseTwilight; 1875dbd4aad809e6fec51df62280bcc1bfe05cc7df5Jason Monk 188639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public AutomaticBrightnessController(Callbacks callbacks, Looper looper, 189a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski SensorManager sensorManager, Spline autoBrightnessSpline, int lightSensorWarmUpTime, 190d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski int brightnessMin, int brightnessMax, float dozeScaleFactor, 191d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski int lightSensorRate, long brighteningLightDebounceConfig, 1926fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic long darkeningLightDebounceConfig, boolean resetAmbientLuxAfterWarmUpConfig, 1936fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic int ambientLightHorizon, float autoBrightnessAdjustmentMaxGamma ) { 194639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mCallbacks = callbacks; 195131206b8a9d07400d7c98aea50cc45c38769448fJeff Brown mTwilight = LocalServices.getService(TwilightManager.class); 196639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mSensorManager = sensorManager; 197639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mScreenAutoBrightnessSpline = autoBrightnessSpline; 198639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mScreenBrightnessRangeMinimum = brightnessMin; 199639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mScreenBrightnessRangeMaximum = brightnessMax; 200639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mLightSensorWarmUpTimeConfig = lightSensorWarmUpTime; 201a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski mDozeScaleFactor = dozeScaleFactor; 202d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski mLightSensorRate = lightSensorRate; 203d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski mBrighteningLightDebounceConfig = brighteningLightDebounceConfig; 204d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski mDarkeningLightDebounceConfig = darkeningLightDebounceConfig; 205d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski mResetAmbientLuxAfterWarmUpConfig = resetAmbientLuxAfterWarmUpConfig; 2066fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic mAmbientLightHorizon = ambientLightHorizon; 2076fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic mWeightingIntercept = ambientLightHorizon; 2086fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic mScreenAutoBrightnessAdjustmentMaxGamma = autoBrightnessAdjustmentMaxGamma; 209639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 210639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mHandler = new AutomaticBrightnessHandler(looper); 211103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright mAmbientLightRingBuffer = 212103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright new AmbientLightRingBuffer(mLightSensorRate, mAmbientLightHorizon); 213103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright mInitialHorizonAmbientLightRingBuffer = 214103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright new AmbientLightRingBuffer(mLightSensorRate, mAmbientLightHorizon); 215639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 216639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (!DEBUG_PRETEND_LIGHT_SENSOR_ABSENT) { 217639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); 218639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 219639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 220639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 221639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public int getAutomaticScreenBrightness() { 222a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski if (mDozing) { 223a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski return (int) (mScreenAutoBrightness * mDozeScaleFactor); 224a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski } 225639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return mScreenAutoBrightness; 226639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 227639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 228a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown public void configure(boolean enable, float adjustment, boolean dozing, 2295dbd4aad809e6fec51df62280bcc1bfe05cc7df5Jason Monk boolean userInitiatedChange, boolean useTwilight) { 230a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski // While dozing, the application processor may be suspended which will prevent us from 231a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski // receiving new information from the light sensor. On some devices, we may be able to 232a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski // switch to a wake-up light sensor instead but for now we will simply disable the sensor 233a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski // and hold onto the last computed screen auto brightness. We save the dozing flag for 234a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski // debugging purposes. 235a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski mDozing = dozing; 236a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski boolean changed = setLightSensorEnabled(enable && !dozing); 237970d4132ea28e748c1010be39450a98bbf7466f3Jeff Brown changed |= setScreenAutoBrightnessAdjustment(adjustment); 2385dbd4aad809e6fec51df62280bcc1bfe05cc7df5Jason Monk changed |= setUseTwilight(useTwilight); 239970d4132ea28e748c1010be39450a98bbf7466f3Jeff Brown if (changed) { 240639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright updateAutoBrightness(false /*sendUpdate*/); 241639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 242a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown if (enable && !dozing && userInitiatedChange) { 243a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown prepareBrightnessAdjustmentSample(); 244a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown } 245639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 246639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 2475dbd4aad809e6fec51df62280bcc1bfe05cc7df5Jason Monk private boolean setUseTwilight(boolean useTwilight) { 2485dbd4aad809e6fec51df62280bcc1bfe05cc7df5Jason Monk if (mUseTwilight == useTwilight) return false; 2495dbd4aad809e6fec51df62280bcc1bfe05cc7df5Jason Monk if (useTwilight) { 2505dbd4aad809e6fec51df62280bcc1bfe05cc7df5Jason Monk mTwilight.registerListener(mTwilightListener, mHandler); 2515dbd4aad809e6fec51df62280bcc1bfe05cc7df5Jason Monk } else { 2525dbd4aad809e6fec51df62280bcc1bfe05cc7df5Jason Monk mTwilight.unregisterListener(mTwilightListener); 2535dbd4aad809e6fec51df62280bcc1bfe05cc7df5Jason Monk } 2545dbd4aad809e6fec51df62280bcc1bfe05cc7df5Jason Monk mUseTwilight = useTwilight; 2555dbd4aad809e6fec51df62280bcc1bfe05cc7df5Jason Monk return true; 2565dbd4aad809e6fec51df62280bcc1bfe05cc7df5Jason Monk } 2575dbd4aad809e6fec51df62280bcc1bfe05cc7df5Jason Monk 258639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public void dump(PrintWriter pw) { 259639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(); 260639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println("Automatic Brightness Controller Configuration:"); 261639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mScreenAutoBrightnessSpline=" + mScreenAutoBrightnessSpline); 262639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum); 263639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum); 264639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mLightSensorWarmUpTimeConfig=" + mLightSensorWarmUpTimeConfig); 265d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski pw.println(" mBrighteningLightDebounceConfig=" + mBrighteningLightDebounceConfig); 266d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski pw.println(" mDarkeningLightDebounceConfig=" + mDarkeningLightDebounceConfig); 267d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski pw.println(" mResetAmbientLuxAfterWarmUpConfig=" + mResetAmbientLuxAfterWarmUpConfig); 268639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 269639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(); 270639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println("Automatic Brightness Controller State:"); 271639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mLightSensor=" + mLightSensor); 272908b86c796443ba4ec55c669e8a0297fc80574a6Justin Klaassen pw.println(" mTwilight.getLastTwilightState()=" + mTwilight.getLastTwilightState()); 273639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mLightSensorEnabled=" + mLightSensorEnabled); 274639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mLightSensorEnableTime=" + TimeUtils.formatUptime(mLightSensorEnableTime)); 275639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mAmbientLux=" + mAmbientLux); 2766fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic pw.println(" mAmbientLightHorizon=" + mAmbientLightHorizon); 277639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mBrighteningLuxThreshold=" + mBrighteningLuxThreshold); 278639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mDarkeningLuxThreshold=" + mDarkeningLuxThreshold); 279639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mLastObservedLux=" + mLastObservedLux); 280639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mLastObservedLuxTime=" + TimeUtils.formatUptime(mLastObservedLuxTime)); 281639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mRecentLightSamples=" + mRecentLightSamples); 282639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mAmbientLightRingBuffer=" + mAmbientLightRingBuffer); 283103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright pw.println(" mInitialHorizonAmbientLightRingBuffer=" + 284103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright mInitialHorizonAmbientLightRingBuffer); 285639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mScreenAutoBrightness=" + mScreenAutoBrightness); 286639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mScreenAutoBrightnessAdjustment=" + mScreenAutoBrightnessAdjustment); 2876fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic pw.println(" mScreenAutoBrightnessAdjustmentMaxGamma=" + mScreenAutoBrightnessAdjustmentMaxGamma); 288639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mLastScreenAutoBrightnessGamma=" + mLastScreenAutoBrightnessGamma); 289a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski pw.println(" mDozing=" + mDozing); 290639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 291639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 292639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private boolean setLightSensorEnabled(boolean enable) { 293639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (enable) { 294639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (!mLightSensorEnabled) { 295639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mLightSensorEnabled = true; 296639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mLightSensorEnableTime = SystemClock.uptimeMillis(); 297639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mSensorManager.registerListener(mLightSensorListener, mLightSensor, 298d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski mLightSensorRate * 1000, mHandler); 299639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return true; 300639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 301639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } else { 302639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (mLightSensorEnabled) { 303639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mLightSensorEnabled = false; 304d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski mAmbientLuxValid = !mResetAmbientLuxAfterWarmUpConfig; 305639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mRecentLightSamples = 0; 306639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mAmbientLightRingBuffer.clear(); 307103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright mInitialHorizonAmbientLightRingBuffer.clear(); 308639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mHandler.removeMessages(MSG_UPDATE_AMBIENT_LUX); 309639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mSensorManager.unregisterListener(mLightSensorListener); 310639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 311639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 312639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return false; 313639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 314639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 315639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private void handleLightSensorEvent(long time, float lux) { 316639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mHandler.removeMessages(MSG_UPDATE_AMBIENT_LUX); 317639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 318639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright applyLightSensorMeasurement(time, lux); 319639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright updateAmbientLux(time); 320639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 321639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 322639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private void applyLightSensorMeasurement(long time, float lux) { 323639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mRecentLightSamples++; 324103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright // Store all of the light measurements for the intial horizon period. This is to help 325103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright // diagnose dim wake ups and slow responses in b/27951906. 326103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright if (time <= mLightSensorEnableTime + mAmbientLightHorizon) { 327103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright mInitialHorizonAmbientLightRingBuffer.push(time, lux); 328103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright } 3296fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic mAmbientLightRingBuffer.prune(time - mAmbientLightHorizon); 330639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mAmbientLightRingBuffer.push(time, lux); 331639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 332639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // Remember this sample value. 333639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mLastObservedLux = lux; 334639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mLastObservedLuxTime = time; 335639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 336639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 337639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private boolean setScreenAutoBrightnessAdjustment(float adjustment) { 338639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (adjustment != mScreenAutoBrightnessAdjustment) { 339639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mScreenAutoBrightnessAdjustment = adjustment; 340639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return true; 341639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 342639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return false; 343639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 344639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 345639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private void setAmbientLux(float lux) { 346639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mAmbientLux = lux; 347639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mBrighteningLuxThreshold = mAmbientLux * (1.0f + BRIGHTENING_LIGHT_HYSTERESIS); 348639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mDarkeningLuxThreshold = mAmbientLux * (1.0f - DARKENING_LIGHT_HYSTERESIS); 349639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 350639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 351639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private float calculateAmbientLux(long now) { 352639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright final int N = mAmbientLightRingBuffer.size(); 353639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (N == 0) { 354639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright Slog.e(TAG, "calculateAmbientLux: No ambient light readings available"); 355639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return -1; 356639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 357639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright float sum = 0; 358639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright float totalWeight = 0; 359639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright long endTime = AMBIENT_LIGHT_PREDICTION_TIME_MILLIS; 360639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright for (int i = N - 1; i >= 0; i--) { 361639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright long startTime = (mAmbientLightRingBuffer.getTime(i) - now); 362639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright float weight = calculateWeight(startTime, endTime); 363639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright float lux = mAmbientLightRingBuffer.getLux(i); 364639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (DEBUG) { 365639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright Slog.d(TAG, "calculateAmbientLux: [" + 366639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright (startTime) + ", " + 367639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright (endTime) + "]: lux=" + lux + ", weight=" + weight); 368639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 369639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright totalWeight += weight; 370639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright sum += mAmbientLightRingBuffer.getLux(i) * weight; 371639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright endTime = startTime; 372639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 373639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (DEBUG) { 374639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright Slog.d(TAG, "calculateAmbientLux: totalWeight=" + totalWeight + 375639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright ", newAmbientLux=" + (sum / totalWeight)); 376639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 377639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return sum / totalWeight; 378639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 379639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 3806fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic private float calculateWeight(long startDelta, long endDelta) { 381639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return weightIntegral(endDelta) - weightIntegral(startDelta); 382639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 383639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 3846fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic // Evaluates the integral of y = x + mWeightingIntercept. This is always positive for the 385639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // horizon we're looking at and provides a non-linear weighting for light samples. 3866fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic private float weightIntegral(long x) { 3876fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic return x * (x * 0.5f + mWeightingIntercept); 388639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 389639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 390639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private long nextAmbientLightBrighteningTransition(long time) { 391639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright final int N = mAmbientLightRingBuffer.size(); 392639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright long earliestValidTime = time; 393639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright for (int i = N - 1; i >= 0; i--) { 394639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (mAmbientLightRingBuffer.getLux(i) <= mBrighteningLuxThreshold) { 395639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright break; 396639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 397639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright earliestValidTime = mAmbientLightRingBuffer.getTime(i); 398639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 399d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski return earliestValidTime + mBrighteningLightDebounceConfig; 400639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 401639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 402639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private long nextAmbientLightDarkeningTransition(long time) { 403639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright final int N = mAmbientLightRingBuffer.size(); 404639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright long earliestValidTime = time; 405639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright for (int i = N - 1; i >= 0; i--) { 406639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (mAmbientLightRingBuffer.getLux(i) >= mDarkeningLuxThreshold) { 407639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright break; 408639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 409639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright earliestValidTime = mAmbientLightRingBuffer.getTime(i); 410639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 411d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski return earliestValidTime + mDarkeningLightDebounceConfig; 412639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 413639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 414639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private void updateAmbientLux() { 415639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright long time = SystemClock.uptimeMillis(); 4166fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic mAmbientLightRingBuffer.prune(time - mAmbientLightHorizon); 417639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright updateAmbientLux(time); 418639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 419639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 420639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private void updateAmbientLux(long time) { 421639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // If the light sensor was just turned on then immediately update our initial 422639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // estimate of the current ambient light level. 423639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (!mAmbientLuxValid) { 424639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright final long timeWhenSensorWarmedUp = 425639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mLightSensorWarmUpTimeConfig + mLightSensorEnableTime; 426639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (time < timeWhenSensorWarmedUp) { 427639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (DEBUG) { 428639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright Slog.d(TAG, "updateAmbientLux: Sensor not ready yet: " 429639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + "time=" + time 430639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + ", timeWhenSensorWarmedUp=" + timeWhenSensorWarmedUp); 431639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 432639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mHandler.sendEmptyMessageAtTime(MSG_UPDATE_AMBIENT_LUX, 433639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright timeWhenSensorWarmedUp); 434639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return; 435639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 436639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright setAmbientLux(calculateAmbientLux(time)); 437639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mAmbientLuxValid = true; 438639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (DEBUG) { 439639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright Slog.d(TAG, "updateAmbientLux: Initializing: " 440639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + "mAmbientLightRingBuffer=" + mAmbientLightRingBuffer 441639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + ", mAmbientLux=" + mAmbientLux); 442639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 443639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright updateAutoBrightness(true); 444639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 445639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 446639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright long nextBrightenTransition = nextAmbientLightBrighteningTransition(time); 447639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright long nextDarkenTransition = nextAmbientLightDarkeningTransition(time); 448639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright float ambientLux = calculateAmbientLux(time); 449639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 450639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (ambientLux >= mBrighteningLuxThreshold && nextBrightenTransition <= time 451639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright || ambientLux <= mDarkeningLuxThreshold && nextDarkenTransition <= time) { 452639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright setAmbientLux(ambientLux); 453639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (DEBUG) { 454639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright Slog.d(TAG, "updateAmbientLux: " 455639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + ((ambientLux > mAmbientLux) ? "Brightened" : "Darkened") + ": " 456639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + "mBrighteningLuxThreshold=" + mBrighteningLuxThreshold 457639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + ", mAmbientLightRingBuffer=" + mAmbientLightRingBuffer 458639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + ", mAmbientLux=" + mAmbientLux); 459639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 460639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright updateAutoBrightness(true); 461639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright nextBrightenTransition = nextAmbientLightBrighteningTransition(time); 462639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright nextDarkenTransition = nextAmbientLightDarkeningTransition(time); 463639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 464639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright long nextTransitionTime = Math.min(nextDarkenTransition, nextBrightenTransition); 465639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // If one of the transitions is ready to occur, but the total weighted ambient lux doesn't 466639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // exceed the necessary threshold, then it's possible we'll get a transition time prior to 467639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // now. Rather than continually checking to see whether the weighted lux exceeds the 468639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // threshold, schedule an update for when we'd normally expect another light sample, which 469639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // should be enough time to decide whether we should actually transition to the new 470639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // weighted ambient lux or not. 471639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright nextTransitionTime = 472d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski nextTransitionTime > time ? nextTransitionTime : time + mLightSensorRate; 473639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (DEBUG) { 474639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright Slog.d(TAG, "updateAmbientLux: Scheduling ambient lux update for " 475639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + nextTransitionTime + TimeUtils.formatUptime(nextTransitionTime)); 476639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 477639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mHandler.sendEmptyMessageAtTime(MSG_UPDATE_AMBIENT_LUX, nextTransitionTime); 478639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 479639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 480639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private void updateAutoBrightness(boolean sendUpdate) { 481639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (!mAmbientLuxValid) { 482639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return; 483639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 484639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 485639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright float value = mScreenAutoBrightnessSpline.interpolate(mAmbientLux); 486639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright float gamma = 1.0f; 487639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 488639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (USE_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT 489639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright && mScreenAutoBrightnessAdjustment != 0.0f) { 4906fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic final float adjGamma = MathUtils.pow(mScreenAutoBrightnessAdjustmentMaxGamma, 491639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright Math.min(1.0f, Math.max(-1.0f, -mScreenAutoBrightnessAdjustment))); 492639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright gamma *= adjGamma; 493639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (DEBUG) { 494639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright Slog.d(TAG, "updateAutoBrightness: adjGamma=" + adjGamma); 495639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 496639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 497639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 4985dbd4aad809e6fec51df62280bcc1bfe05cc7df5Jason Monk if (mUseTwilight) { 499908b86c796443ba4ec55c669e8a0297fc80574a6Justin Klaassen TwilightState state = mTwilight.getLastTwilightState(); 500639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (state != null && state.isNight()) { 501908b86c796443ba4ec55c669e8a0297fc80574a6Justin Klaassen final long duration = state.sunriseTimeMillis() - state.sunsetTimeMillis(); 502908b86c796443ba4ec55c669e8a0297fc80574a6Justin Klaassen final long progress = System.currentTimeMillis() - state.sunsetTimeMillis(); 503908b86c796443ba4ec55c669e8a0297fc80574a6Justin Klaassen final float amount = (float) Math.pow(2.0 * progress / duration - 1.0, 2.0); 504908b86c796443ba4ec55c669e8a0297fc80574a6Justin Klaassen gamma *= 1 + amount * TWILIGHT_ADJUSTMENT_MAX_GAMMA; 505639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (DEBUG) { 506908b86c796443ba4ec55c669e8a0297fc80574a6Justin Klaassen Slog.d(TAG, "updateAutoBrightness: twilight amount=" + amount); 507639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 508639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 509639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 510639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 511639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (gamma != 1.0f) { 512639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright final float in = value; 513639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright value = MathUtils.pow(value, gamma); 514639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (DEBUG) { 515639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright Slog.d(TAG, "updateAutoBrightness: gamma=" + gamma 516639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + ", in=" + in + ", out=" + value); 517639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 518639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 519639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 520639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright int newScreenAutoBrightness = 521a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown clampScreenBrightness(Math.round(value * PowerManager.BRIGHTNESS_ON)); 522639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (mScreenAutoBrightness != newScreenAutoBrightness) { 523639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (DEBUG) { 524639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright Slog.d(TAG, "updateAutoBrightness: mScreenAutoBrightness=" 525639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + mScreenAutoBrightness + ", newScreenAutoBrightness=" 526639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + newScreenAutoBrightness); 527639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 528639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 529639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mScreenAutoBrightness = newScreenAutoBrightness; 530639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mLastScreenAutoBrightnessGamma = gamma; 531639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (sendUpdate) { 532639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mCallbacks.updateBrightness(); 533639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 534639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 535639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 536639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 537639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private int clampScreenBrightness(int value) { 538639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return MathUtils.constrain(value, 539639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mScreenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum); 540639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 541639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 542a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown private void prepareBrightnessAdjustmentSample() { 543a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown if (!mBrightnessAdjustmentSamplePending) { 544a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mBrightnessAdjustmentSamplePending = true; 545a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mBrightnessAdjustmentSampleOldAdjustment = mScreenAutoBrightnessAdjustment; 546a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mBrightnessAdjustmentSampleOldLux = mAmbientLuxValid ? mAmbientLux : -1; 547a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mBrightnessAdjustmentSampleOldBrightness = mScreenAutoBrightness; 548a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mBrightnessAdjustmentSampleOldGamma = mLastScreenAutoBrightnessGamma; 549a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown } else { 550a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mHandler.removeMessages(MSG_BRIGHTNESS_ADJUSTMENT_SAMPLE); 551a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown } 552a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown 553a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mHandler.sendEmptyMessageDelayed(MSG_BRIGHTNESS_ADJUSTMENT_SAMPLE, 554a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown BRIGHTNESS_ADJUSTMENT_SAMPLE_DEBOUNCE_MILLIS); 555a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown } 556a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown 557a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown private void cancelBrightnessAdjustmentSample() { 558a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown if (mBrightnessAdjustmentSamplePending) { 559a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mBrightnessAdjustmentSamplePending = false; 560a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mHandler.removeMessages(MSG_BRIGHTNESS_ADJUSTMENT_SAMPLE); 561a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown } 562a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown } 563a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown 564a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown private void collectBrightnessAdjustmentSample() { 565a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown if (mBrightnessAdjustmentSamplePending) { 566a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mBrightnessAdjustmentSamplePending = false; 567a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown if (mAmbientLuxValid && mScreenAutoBrightness >= 0) { 568a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown if (DEBUG) { 569a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown Slog.d(TAG, "Auto-brightness adjustment changed by user: " 570a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown + "adj=" + mScreenAutoBrightnessAdjustment 571a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown + ", lux=" + mAmbientLux 572a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown + ", brightness=" + mScreenAutoBrightness 573a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown + ", gamma=" + mLastScreenAutoBrightnessGamma 574a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown + ", ring=" + mAmbientLightRingBuffer); 575a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown } 576a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown 577a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown EventLog.writeEvent(EventLogTags.AUTO_BRIGHTNESS_ADJ, 578a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mBrightnessAdjustmentSampleOldAdjustment, 579a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mBrightnessAdjustmentSampleOldLux, 580a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mBrightnessAdjustmentSampleOldBrightness, 581a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mBrightnessAdjustmentSampleOldGamma, 582a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mScreenAutoBrightnessAdjustment, 583a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mAmbientLux, 584a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mScreenAutoBrightness, 585a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mLastScreenAutoBrightnessGamma); 586a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown } 587a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown } 588a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown } 589a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown 590639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private final class AutomaticBrightnessHandler extends Handler { 591639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public AutomaticBrightnessHandler(Looper looper) { 592639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright super(looper, null, true /*async*/); 593639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 594639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 595639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright @Override 596639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public void handleMessage(Message msg) { 597639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright switch (msg.what) { 598639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright case MSG_UPDATE_AMBIENT_LUX: 599639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright updateAmbientLux(); 600639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright break; 601a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown 602a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown case MSG_BRIGHTNESS_ADJUSTMENT_SAMPLE: 603a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown collectBrightnessAdjustmentSample(); 604a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown break; 605639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 606639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 607639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 608639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 609639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private final SensorEventListener mLightSensorListener = new SensorEventListener() { 610639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright @Override 611639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public void onSensorChanged(SensorEvent event) { 612639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (mLightSensorEnabled) { 613639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright final long time = SystemClock.uptimeMillis(); 614639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright final float lux = event.values[0]; 615639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright handleLightSensorEvent(time, lux); 616639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 617639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 618639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 619639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright @Override 620639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public void onAccuracyChanged(Sensor sensor, int accuracy) { 621639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // Not used. 622639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 623639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright }; 624639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 625639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private final TwilightListener mTwilightListener = new TwilightListener() { 626639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright @Override 627908b86c796443ba4ec55c669e8a0297fc80574a6Justin Klaassen public void onTwilightStateChanged(@Nullable TwilightState state) { 628639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright updateAutoBrightness(true /*sendUpdate*/); 629639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 630639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright }; 631639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 632639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright /** Callbacks to request updates to the display's power state. */ 633639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright interface Callbacks { 634639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright void updateBrightness(); 635639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 636639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 637103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright private static final class AmbientLightRingBuffer { 638639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // Proportional extra capacity of the buffer beyond the expected number of light samples 639639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // in the horizon 640639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private static final float BUFFER_SLACK = 1.5f; 641639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private float[] mRingLux; 642639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private long[] mRingTime; 643639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private int mCapacity; 644639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 645639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The first valid element and the next open slot. 646639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // Note that if mCount is zero then there are no valid elements. 647639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private int mStart; 648639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private int mEnd; 649639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private int mCount; 650639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 6516fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic public AmbientLightRingBuffer(long lightSensorRate, int ambientLightHorizon) { 6526fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic mCapacity = (int) Math.ceil(ambientLightHorizon * BUFFER_SLACK / lightSensorRate); 653639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mRingLux = new float[mCapacity]; 654639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mRingTime = new long[mCapacity]; 655639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 656639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 657639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public float getLux(int index) { 658639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return mRingLux[offsetOf(index)]; 659639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 660639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 661639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public long getTime(int index) { 662639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return mRingTime[offsetOf(index)]; 663639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 664639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 665639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public void push(long time, float lux) { 666639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright int next = mEnd; 667639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (mCount == mCapacity) { 668639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright int newSize = mCapacity * 2; 669639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 670639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright float[] newRingLux = new float[newSize]; 671639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright long[] newRingTime = new long[newSize]; 672639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright int length = mCapacity - mStart; 673639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright System.arraycopy(mRingLux, mStart, newRingLux, 0, length); 674639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright System.arraycopy(mRingTime, mStart, newRingTime, 0, length); 675639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (mStart != 0) { 676639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright System.arraycopy(mRingLux, 0, newRingLux, length, mStart); 677639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright System.arraycopy(mRingTime, 0, newRingTime, length, mStart); 678639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 679639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mRingLux = newRingLux; 680639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mRingTime = newRingTime; 681639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 682639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright next = mCapacity; 683639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mCapacity = newSize; 684639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mStart = 0; 685639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 686639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mRingTime[next] = time; 687639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mRingLux[next] = lux; 688639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mEnd = next + 1; 689639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (mEnd == mCapacity) { 690639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mEnd = 0; 691639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 692639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mCount++; 693639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 694639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 695639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public void prune(long horizon) { 696639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (mCount == 0) { 697639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return; 698639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 699639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 700639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright while (mCount > 1) { 701639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright int next = mStart + 1; 702639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (next >= mCapacity) { 703639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright next -= mCapacity; 704639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 705639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (mRingTime[next] > horizon) { 706639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // Some light sensors only produce data upon a change in the ambient light 707639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // levels, so we need to consider the previous measurement as the ambient light 708639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // level for all points in time up until we receive a new measurement. Thus, we 709639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // always want to keep the youngest element that would be removed from the 710639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // buffer and just set its measurement time to the horizon time since at that 711639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // point it is the ambient light level, and to remove it would be to drop a 712639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // valid data point within our horizon. 713639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright break; 714639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 715639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mStart = next; 716639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mCount -= 1; 717639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 718639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 719639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (mRingTime[mStart] < horizon) { 720639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mRingTime[mStart] = horizon; 721639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 722639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 723639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 724639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public int size() { 725639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return mCount; 726639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 727639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 728639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public void clear() { 729639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mStart = 0; 730639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mEnd = 0; 731639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mCount = 0; 732639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 733639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 734639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright @Override 735639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public String toString() { 736a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown StringBuffer buf = new StringBuffer(); 737a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown buf.append('['); 738a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown for (int i = 0; i < mCount; i++) { 739a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown final long next = i + 1 < mCount ? getTime(i + 1) : SystemClock.uptimeMillis(); 740a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown if (i != 0) { 741a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown buf.append(", "); 742a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown } 743a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown buf.append(getLux(i)); 744a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown buf.append(" / "); 745a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown buf.append(next - getTime(i)); 746a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown buf.append("ms"); 747639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 748a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown buf.append(']'); 749a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown return buf.toString(); 750639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 751639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 752639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private int offsetOf(int index) { 753639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (index >= mCount || index < 0) { 754639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright throw new ArrayIndexOutOfBoundsException(index); 755639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 756639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright index += mStart; 757639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (index >= mCapacity) { 758639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright index -= mCapacity; 759639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 760639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return index; 761639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 762639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 763639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright} 764