AutomaticBrightnessController.java revision 428aed01e1e2923968027dff57132d8d8d5c4905
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 // How long the current sensor reading is assumed to be valid beyond the current time. 54639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // This provides a bit of prediction, as well as ensures that the weight for the last sample is 55639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // non-zero, which in turn ensures that the total weight is non-zero. 56639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private static final long AMBIENT_LIGHT_PREDICTION_TIME_MILLIS = 100; 57639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 58639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // Specifies the maximum magnitude of the time of day adjustment. 595dbd4aad809e6fec51df62280bcc1bfe05cc7df5Jason Monk private static final float TWILIGHT_ADJUSTMENT_MAX_GAMMA = 1f; 60639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 61a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown // Debounce for sampling user-initiated changes in display brightness to ensure 62a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown // the user is satisfied with the result before storing the sample. 63a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown private static final int BRIGHTNESS_ADJUSTMENT_SAMPLE_DEBOUNCE_MILLIS = 10000; 64a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown 65639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private static final int MSG_UPDATE_AMBIENT_LUX = 1; 66a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown private static final int MSG_BRIGHTNESS_ADJUSTMENT_SAMPLE = 2; 67639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 68428aed01e1e2923968027dff57132d8d8d5c4905Julius D'souza // Callbacks for requesting updates to the display's power state 69639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private final Callbacks mCallbacks; 70639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 71639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The sensor manager. 72639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private final SensorManager mSensorManager; 73639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 74639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The light sensor, or null if not available or needed. 75639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private final Sensor mLightSensor; 76639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 77639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The twilight service. 78639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private final TwilightManager mTwilight; 79639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 80639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The auto-brightness spline adjustment. 81639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The brightness values have been scaled to a range of 0..1. 82639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private final Spline mScreenAutoBrightnessSpline; 83639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 84639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The minimum and maximum screen brightnesses. 85639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private final int mScreenBrightnessRangeMinimum; 86639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private final int mScreenBrightnessRangeMaximum; 87a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski private final float mDozeScaleFactor; 88639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 89d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski // Light sensor event rate in milliseconds. 90d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski private final int mLightSensorRate; 91d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski 92d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski // Stability requirements in milliseconds for accepting a new brightness level. This is used 93d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski // for debouncing the light sensor. Different constants are used to debounce the light sensor 94d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski // when adapting to brighter or darker environments. This parameter controls how quickly 95d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski // brightness changes occur in response to an observed change in light level that exceeds the 96d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski // hysteresis threshold. 97d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski private final long mBrighteningLightDebounceConfig; 98d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski private final long mDarkeningLightDebounceConfig; 99d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski 100d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski // If true immediately after the screen is turned on the controller will try to adjust the 101d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski // brightness based on the current sensor reads. If false, the controller will collect more data 102d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski // and only then decide whether to change brightness. 103d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski private final boolean mResetAmbientLuxAfterWarmUpConfig; 104d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski 1056fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic // Period of time in which to consider light samples in milliseconds. 1066fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic private final int mAmbientLightHorizon; 1076fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic 1086fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic // The intercept used for the weighting calculation. This is used in order to keep all possible 1096fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic // weighting values positive. 1106fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic private final int mWeightingIntercept; 1116fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic 112428aed01e1e2923968027dff57132d8d8d5c4905Julius D'souza // accessor object for determining thresholds to change brightness dynamically 113428aed01e1e2923968027dff57132d8d8d5c4905Julius D'souza private final HysteresisLevels mDynamicHysteresis; 114428aed01e1e2923968027dff57132d8d8d5c4905Julius D'souza 115639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // Amount of time to delay auto-brightness after screen on while waiting for 116639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // the light sensor to warm-up in milliseconds. 117639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // May be 0 if no warm-up is required. 118639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private int mLightSensorWarmUpTimeConfig; 119639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 120639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // Set to true if the light sensor is enabled. 121639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private boolean mLightSensorEnabled; 122639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 123639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The time when the light sensor was enabled. 124639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private long mLightSensorEnableTime; 125639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 126639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The currently accepted nominal ambient light level. 127639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private float mAmbientLux; 128639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 129639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // True if mAmbientLux holds a valid value. 130639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private boolean mAmbientLuxValid; 131639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 132639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The ambient light level threshold at which to brighten or darken the screen. 133639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private float mBrighteningLuxThreshold; 134639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private float mDarkeningLuxThreshold; 135639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 136639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The most recent light sample. 137639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private float mLastObservedLux; 138639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 139639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The time of the most light recent sample. 140639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private long mLastObservedLuxTime; 141639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 142639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The number of light samples collected since the light sensor was enabled. 143639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private int mRecentLightSamples; 144639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 145639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // A ring buffer containing all of the recent ambient light sensor readings. 146639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private AmbientLightRingBuffer mAmbientLightRingBuffer; 147639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 148103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright // A ring buffer containing the light sensor readings for the initial horizon period. 149103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright private AmbientLightRingBuffer mInitialHorizonAmbientLightRingBuffer; 150103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright 151639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The handler 152639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private AutomaticBrightnessHandler mHandler; 153639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 154639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The screen brightness level that has been chosen by the auto-brightness 155639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // algorithm. The actual brightness should ramp towards this value. 156639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // We preserve this value even when we stop using the light sensor so 157639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // that we can quickly revert to the previous auto-brightness level 158639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // while the light sensor warms up. 159639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // Use -1 if there is no current auto-brightness value available. 160639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private int mScreenAutoBrightness = -1; 161639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 162639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The screen auto-brightness adjustment factor in the range -1 (dimmer) to 1 (brighter) 163639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private float mScreenAutoBrightnessAdjustment = 0.0f; 164639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 1656fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic // The maximum range of gamma adjustment possible using the screen 1666fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic // auto-brightness adjustment setting. 1676fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic private float mScreenAutoBrightnessAdjustmentMaxGamma; 1686fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic 169639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The last screen auto-brightness gamma. (For printing in dump() only.) 170639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private float mLastScreenAutoBrightnessGamma = 1.0f; 171639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 172a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski // Are we going to adjust brightness while dozing. 173a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski private boolean mDozing; 174a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski 175a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown // True if we are collecting a brightness adjustment sample, along with some data 176a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown // for the initial state of the sample. 177a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown private boolean mBrightnessAdjustmentSamplePending; 178a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown private float mBrightnessAdjustmentSampleOldAdjustment; 179a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown private float mBrightnessAdjustmentSampleOldLux; 180a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown private int mBrightnessAdjustmentSampleOldBrightness; 181a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown private float mBrightnessAdjustmentSampleOldGamma; 182a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown 1835dbd4aad809e6fec51df62280bcc1bfe05cc7df5Jason Monk private boolean mUseTwilight; 1845dbd4aad809e6fec51df62280bcc1bfe05cc7df5Jason Monk 185639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public AutomaticBrightnessController(Callbacks callbacks, Looper looper, 186a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski SensorManager sensorManager, Spline autoBrightnessSpline, int lightSensorWarmUpTime, 187d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski int brightnessMin, int brightnessMax, float dozeScaleFactor, 188d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski int lightSensorRate, long brighteningLightDebounceConfig, 1896fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic long darkeningLightDebounceConfig, boolean resetAmbientLuxAfterWarmUpConfig, 190428aed01e1e2923968027dff57132d8d8d5c4905Julius D'souza int ambientLightHorizon, float autoBrightnessAdjustmentMaxGamma, 191428aed01e1e2923968027dff57132d8d8d5c4905Julius D'souza HysteresisLevels dynamicHysteresis) { 192639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mCallbacks = callbacks; 193131206b8a9d07400d7c98aea50cc45c38769448fJeff Brown mTwilight = LocalServices.getService(TwilightManager.class); 194639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mSensorManager = sensorManager; 195639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mScreenAutoBrightnessSpline = autoBrightnessSpline; 196639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mScreenBrightnessRangeMinimum = brightnessMin; 197639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mScreenBrightnessRangeMaximum = brightnessMax; 198639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mLightSensorWarmUpTimeConfig = lightSensorWarmUpTime; 199a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski mDozeScaleFactor = dozeScaleFactor; 200d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski mLightSensorRate = lightSensorRate; 201d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski mBrighteningLightDebounceConfig = brighteningLightDebounceConfig; 202d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski mDarkeningLightDebounceConfig = darkeningLightDebounceConfig; 203d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski mResetAmbientLuxAfterWarmUpConfig = resetAmbientLuxAfterWarmUpConfig; 2046fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic mAmbientLightHorizon = ambientLightHorizon; 2056fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic mWeightingIntercept = ambientLightHorizon; 2066fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic mScreenAutoBrightnessAdjustmentMaxGamma = autoBrightnessAdjustmentMaxGamma; 207428aed01e1e2923968027dff57132d8d8d5c4905Julius D'souza mDynamicHysteresis = dynamicHysteresis; 208639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 209639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mHandler = new AutomaticBrightnessHandler(looper); 210103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright mAmbientLightRingBuffer = 211103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright new AmbientLightRingBuffer(mLightSensorRate, mAmbientLightHorizon); 212103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright mInitialHorizonAmbientLightRingBuffer = 213103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright new AmbientLightRingBuffer(mLightSensorRate, mAmbientLightHorizon); 214639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 215639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (!DEBUG_PRETEND_LIGHT_SENSOR_ABSENT) { 216639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); 217639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 218639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 219639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 220639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public int getAutomaticScreenBrightness() { 221a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski if (mDozing) { 222a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski return (int) (mScreenAutoBrightness * mDozeScaleFactor); 223a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski } 224639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return mScreenAutoBrightness; 225639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 226639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 227a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown public void configure(boolean enable, float adjustment, boolean dozing, 2285dbd4aad809e6fec51df62280bcc1bfe05cc7df5Jason Monk boolean userInitiatedChange, boolean useTwilight) { 229a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski // While dozing, the application processor may be suspended which will prevent us from 230a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski // receiving new information from the light sensor. On some devices, we may be able to 231a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski // switch to a wake-up light sensor instead but for now we will simply disable the sensor 232a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski // and hold onto the last computed screen auto brightness. We save the dozing flag for 233a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski // debugging purposes. 234a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski mDozing = dozing; 235a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski boolean changed = setLightSensorEnabled(enable && !dozing); 236970d4132ea28e748c1010be39450a98bbf7466f3Jeff Brown changed |= setScreenAutoBrightnessAdjustment(adjustment); 2375dbd4aad809e6fec51df62280bcc1bfe05cc7df5Jason Monk changed |= setUseTwilight(useTwilight); 238970d4132ea28e748c1010be39450a98bbf7466f3Jeff Brown if (changed) { 239639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright updateAutoBrightness(false /*sendUpdate*/); 240639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 241a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown if (enable && !dozing && userInitiatedChange) { 242a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown prepareBrightnessAdjustmentSample(); 243a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown } 244639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 245639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 2465dbd4aad809e6fec51df62280bcc1bfe05cc7df5Jason Monk private boolean setUseTwilight(boolean useTwilight) { 2475dbd4aad809e6fec51df62280bcc1bfe05cc7df5Jason Monk if (mUseTwilight == useTwilight) return false; 2485dbd4aad809e6fec51df62280bcc1bfe05cc7df5Jason Monk if (useTwilight) { 2495dbd4aad809e6fec51df62280bcc1bfe05cc7df5Jason Monk mTwilight.registerListener(mTwilightListener, mHandler); 2505dbd4aad809e6fec51df62280bcc1bfe05cc7df5Jason Monk } else { 2515dbd4aad809e6fec51df62280bcc1bfe05cc7df5Jason Monk mTwilight.unregisterListener(mTwilightListener); 2525dbd4aad809e6fec51df62280bcc1bfe05cc7df5Jason Monk } 2535dbd4aad809e6fec51df62280bcc1bfe05cc7df5Jason Monk mUseTwilight = useTwilight; 2545dbd4aad809e6fec51df62280bcc1bfe05cc7df5Jason Monk return true; 2555dbd4aad809e6fec51df62280bcc1bfe05cc7df5Jason Monk } 2565dbd4aad809e6fec51df62280bcc1bfe05cc7df5Jason Monk 257639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public void dump(PrintWriter pw) { 258639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(); 259639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println("Automatic Brightness Controller Configuration:"); 260639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mScreenAutoBrightnessSpline=" + mScreenAutoBrightnessSpline); 261639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum); 262639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum); 263639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mLightSensorWarmUpTimeConfig=" + mLightSensorWarmUpTimeConfig); 264d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski pw.println(" mBrighteningLightDebounceConfig=" + mBrighteningLightDebounceConfig); 265d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski pw.println(" mDarkeningLightDebounceConfig=" + mDarkeningLightDebounceConfig); 266d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski pw.println(" mResetAmbientLuxAfterWarmUpConfig=" + mResetAmbientLuxAfterWarmUpConfig); 267639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 268639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(); 269639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println("Automatic Brightness Controller State:"); 270639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mLightSensor=" + mLightSensor); 271908b86c796443ba4ec55c669e8a0297fc80574a6Justin Klaassen pw.println(" mTwilight.getLastTwilightState()=" + mTwilight.getLastTwilightState()); 272639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mLightSensorEnabled=" + mLightSensorEnabled); 273639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mLightSensorEnableTime=" + TimeUtils.formatUptime(mLightSensorEnableTime)); 274639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mAmbientLux=" + mAmbientLux); 2756fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic pw.println(" mAmbientLightHorizon=" + mAmbientLightHorizon); 276639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mBrighteningLuxThreshold=" + mBrighteningLuxThreshold); 277639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mDarkeningLuxThreshold=" + mDarkeningLuxThreshold); 278639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mLastObservedLux=" + mLastObservedLux); 279639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mLastObservedLuxTime=" + TimeUtils.formatUptime(mLastObservedLuxTime)); 280639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mRecentLightSamples=" + mRecentLightSamples); 281639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mAmbientLightRingBuffer=" + mAmbientLightRingBuffer); 282103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright pw.println(" mInitialHorizonAmbientLightRingBuffer=" + 283103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright mInitialHorizonAmbientLightRingBuffer); 284639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mScreenAutoBrightness=" + mScreenAutoBrightness); 285639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mScreenAutoBrightnessAdjustment=" + mScreenAutoBrightnessAdjustment); 2866fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic pw.println(" mScreenAutoBrightnessAdjustmentMaxGamma=" + mScreenAutoBrightnessAdjustmentMaxGamma); 287639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright pw.println(" mLastScreenAutoBrightnessGamma=" + mLastScreenAutoBrightnessGamma); 288a15aa7d426972daecc0e8cd31dcf4d6bc656f1e9Filip Gruszczynski pw.println(" mDozing=" + mDozing); 289639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 290639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 291639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private boolean setLightSensorEnabled(boolean enable) { 292639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (enable) { 293639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (!mLightSensorEnabled) { 294639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mLightSensorEnabled = true; 295639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mLightSensorEnableTime = SystemClock.uptimeMillis(); 296639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mSensorManager.registerListener(mLightSensorListener, mLightSensor, 297d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski mLightSensorRate * 1000, mHandler); 298639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return true; 299639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 300639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } else { 301639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (mLightSensorEnabled) { 302639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mLightSensorEnabled = false; 303d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski mAmbientLuxValid = !mResetAmbientLuxAfterWarmUpConfig; 304639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mRecentLightSamples = 0; 305639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mAmbientLightRingBuffer.clear(); 306103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright mInitialHorizonAmbientLightRingBuffer.clear(); 307639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mHandler.removeMessages(MSG_UPDATE_AMBIENT_LUX); 308639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mSensorManager.unregisterListener(mLightSensorListener); 309639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 310639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 311639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return false; 312639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 313639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 314639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private void handleLightSensorEvent(long time, float lux) { 315639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mHandler.removeMessages(MSG_UPDATE_AMBIENT_LUX); 316639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 317639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright applyLightSensorMeasurement(time, lux); 318639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright updateAmbientLux(time); 319639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 320639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 321639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private void applyLightSensorMeasurement(long time, float lux) { 322639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mRecentLightSamples++; 323103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright // Store all of the light measurements for the intial horizon period. This is to help 324103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright // diagnose dim wake ups and slow responses in b/27951906. 325103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright if (time <= mLightSensorEnableTime + mAmbientLightHorizon) { 326103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright mInitialHorizonAmbientLightRingBuffer.push(time, lux); 327103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright } 3286fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic mAmbientLightRingBuffer.prune(time - mAmbientLightHorizon); 329639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mAmbientLightRingBuffer.push(time, lux); 330639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 331639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // Remember this sample value. 332639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mLastObservedLux = lux; 333639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mLastObservedLuxTime = time; 334639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 335639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 336639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private boolean setScreenAutoBrightnessAdjustment(float adjustment) { 337639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (adjustment != mScreenAutoBrightnessAdjustment) { 338639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mScreenAutoBrightnessAdjustment = adjustment; 339639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return true; 340639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 341639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return false; 342639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 343639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 344639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private void setAmbientLux(float lux) { 345639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mAmbientLux = lux; 346428aed01e1e2923968027dff57132d8d8d5c4905Julius D'souza mBrighteningLuxThreshold = mDynamicHysteresis.getBrighteningThreshold(lux); 347428aed01e1e2923968027dff57132d8d8d5c4905Julius D'souza mDarkeningLuxThreshold = mDynamicHysteresis.getDarkeningThreshold(lux); 348639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 349639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 350639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private float calculateAmbientLux(long now) { 351639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright final int N = mAmbientLightRingBuffer.size(); 352639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (N == 0) { 353639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright Slog.e(TAG, "calculateAmbientLux: No ambient light readings available"); 354639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return -1; 355639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 356639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright float sum = 0; 357639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright float totalWeight = 0; 358639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright long endTime = AMBIENT_LIGHT_PREDICTION_TIME_MILLIS; 359639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright for (int i = N - 1; i >= 0; i--) { 360639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright long startTime = (mAmbientLightRingBuffer.getTime(i) - now); 361639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright float weight = calculateWeight(startTime, endTime); 362639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright float lux = mAmbientLightRingBuffer.getLux(i); 363639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (DEBUG) { 364639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright Slog.d(TAG, "calculateAmbientLux: [" + 365639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright (startTime) + ", " + 366639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright (endTime) + "]: lux=" + lux + ", weight=" + weight); 367639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 368639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright totalWeight += weight; 369639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright sum += mAmbientLightRingBuffer.getLux(i) * weight; 370639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright endTime = startTime; 371639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 372639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (DEBUG) { 373639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright Slog.d(TAG, "calculateAmbientLux: totalWeight=" + totalWeight + 374639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright ", newAmbientLux=" + (sum / totalWeight)); 375639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 376639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return sum / totalWeight; 377639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 378639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 3796fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic private float calculateWeight(long startDelta, long endDelta) { 380639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return weightIntegral(endDelta) - weightIntegral(startDelta); 381639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 382639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 3836fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic // Evaluates the integral of y = x + mWeightingIntercept. This is always positive for the 384639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // horizon we're looking at and provides a non-linear weighting for light samples. 3856fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic private float weightIntegral(long x) { 3866fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic return x * (x * 0.5f + mWeightingIntercept); 387639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 388639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 389639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private long nextAmbientLightBrighteningTransition(long time) { 390639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright final int N = mAmbientLightRingBuffer.size(); 391639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright long earliestValidTime = time; 392639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright for (int i = N - 1; i >= 0; i--) { 393639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (mAmbientLightRingBuffer.getLux(i) <= mBrighteningLuxThreshold) { 394639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright break; 395639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 396639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright earliestValidTime = mAmbientLightRingBuffer.getTime(i); 397639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 398d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski return earliestValidTime + mBrighteningLightDebounceConfig; 399639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 400639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 401639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private long nextAmbientLightDarkeningTransition(long time) { 402639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright final int N = mAmbientLightRingBuffer.size(); 403639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright long earliestValidTime = time; 404639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright for (int i = N - 1; i >= 0; i--) { 405639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (mAmbientLightRingBuffer.getLux(i) >= mDarkeningLuxThreshold) { 406639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright break; 407639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 408639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright earliestValidTime = mAmbientLightRingBuffer.getTime(i); 409639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 410d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski return earliestValidTime + mDarkeningLightDebounceConfig; 411639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 412639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 413639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private void updateAmbientLux() { 414639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright long time = SystemClock.uptimeMillis(); 4156fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic mAmbientLightRingBuffer.prune(time - mAmbientLightHorizon); 416639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright updateAmbientLux(time); 417639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 418639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 419639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private void updateAmbientLux(long time) { 420639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // If the light sensor was just turned on then immediately update our initial 421639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // estimate of the current ambient light level. 422639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (!mAmbientLuxValid) { 423639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright final long timeWhenSensorWarmedUp = 424639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mLightSensorWarmUpTimeConfig + mLightSensorEnableTime; 425639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (time < timeWhenSensorWarmedUp) { 426639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (DEBUG) { 427639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright Slog.d(TAG, "updateAmbientLux: Sensor not ready yet: " 428639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + "time=" + time 429639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + ", timeWhenSensorWarmedUp=" + timeWhenSensorWarmedUp); 430639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 431639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mHandler.sendEmptyMessageAtTime(MSG_UPDATE_AMBIENT_LUX, 432639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright timeWhenSensorWarmedUp); 433639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return; 434639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 435639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright setAmbientLux(calculateAmbientLux(time)); 436639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mAmbientLuxValid = true; 437639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (DEBUG) { 438639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright Slog.d(TAG, "updateAmbientLux: Initializing: " 439639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + "mAmbientLightRingBuffer=" + mAmbientLightRingBuffer 440639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + ", mAmbientLux=" + mAmbientLux); 441639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 442639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright updateAutoBrightness(true); 443639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 444639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 445639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright long nextBrightenTransition = nextAmbientLightBrighteningTransition(time); 446639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright long nextDarkenTransition = nextAmbientLightDarkeningTransition(time); 447639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright float ambientLux = calculateAmbientLux(time); 448639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 449639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (ambientLux >= mBrighteningLuxThreshold && nextBrightenTransition <= time 450639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright || ambientLux <= mDarkeningLuxThreshold && nextDarkenTransition <= time) { 451639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright setAmbientLux(ambientLux); 452639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (DEBUG) { 453639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright Slog.d(TAG, "updateAmbientLux: " 454639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + ((ambientLux > mAmbientLux) ? "Brightened" : "Darkened") + ": " 455639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + "mBrighteningLuxThreshold=" + mBrighteningLuxThreshold 456639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + ", mAmbientLightRingBuffer=" + mAmbientLightRingBuffer 457639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + ", mAmbientLux=" + mAmbientLux); 458639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 459639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright updateAutoBrightness(true); 460639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright nextBrightenTransition = nextAmbientLightBrighteningTransition(time); 461639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright nextDarkenTransition = nextAmbientLightDarkeningTransition(time); 462639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 463639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright long nextTransitionTime = Math.min(nextDarkenTransition, nextBrightenTransition); 464639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // If one of the transitions is ready to occur, but the total weighted ambient lux doesn't 465639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // exceed the necessary threshold, then it's possible we'll get a transition time prior to 466639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // now. Rather than continually checking to see whether the weighted lux exceeds the 467639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // threshold, schedule an update for when we'd normally expect another light sample, which 468639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // should be enough time to decide whether we should actually transition to the new 469639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // weighted ambient lux or not. 470639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright nextTransitionTime = 471d81ecd12cec5e1efa8ca49036bb023746f63d90aFilip Gruszczynski nextTransitionTime > time ? nextTransitionTime : time + mLightSensorRate; 472639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (DEBUG) { 473639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright Slog.d(TAG, "updateAmbientLux: Scheduling ambient lux update for " 474639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + nextTransitionTime + TimeUtils.formatUptime(nextTransitionTime)); 475639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 476639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mHandler.sendEmptyMessageAtTime(MSG_UPDATE_AMBIENT_LUX, nextTransitionTime); 477639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 478639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 479639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private void updateAutoBrightness(boolean sendUpdate) { 480639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (!mAmbientLuxValid) { 481639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return; 482639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 483639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 484639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright float value = mScreenAutoBrightnessSpline.interpolate(mAmbientLux); 485639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright float gamma = 1.0f; 486639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 487639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (USE_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT 488639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright && mScreenAutoBrightnessAdjustment != 0.0f) { 4896fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic final float adjGamma = MathUtils.pow(mScreenAutoBrightnessAdjustmentMaxGamma, 490639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright Math.min(1.0f, Math.max(-1.0f, -mScreenAutoBrightnessAdjustment))); 491639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright gamma *= adjGamma; 492639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (DEBUG) { 493639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright Slog.d(TAG, "updateAutoBrightness: adjGamma=" + adjGamma); 494639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 495639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 496639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 4975dbd4aad809e6fec51df62280bcc1bfe05cc7df5Jason Monk if (mUseTwilight) { 498908b86c796443ba4ec55c669e8a0297fc80574a6Justin Klaassen TwilightState state = mTwilight.getLastTwilightState(); 499639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (state != null && state.isNight()) { 500908b86c796443ba4ec55c669e8a0297fc80574a6Justin Klaassen final long duration = state.sunriseTimeMillis() - state.sunsetTimeMillis(); 501908b86c796443ba4ec55c669e8a0297fc80574a6Justin Klaassen final long progress = System.currentTimeMillis() - state.sunsetTimeMillis(); 502908b86c796443ba4ec55c669e8a0297fc80574a6Justin Klaassen final float amount = (float) Math.pow(2.0 * progress / duration - 1.0, 2.0); 503908b86c796443ba4ec55c669e8a0297fc80574a6Justin Klaassen gamma *= 1 + amount * TWILIGHT_ADJUSTMENT_MAX_GAMMA; 504639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (DEBUG) { 505908b86c796443ba4ec55c669e8a0297fc80574a6Justin Klaassen Slog.d(TAG, "updateAutoBrightness: twilight amount=" + amount); 506639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 507639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 508639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 509639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 510639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (gamma != 1.0f) { 511639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright final float in = value; 512639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright value = MathUtils.pow(value, gamma); 513639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (DEBUG) { 514639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright Slog.d(TAG, "updateAutoBrightness: gamma=" + gamma 515639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + ", in=" + in + ", out=" + value); 516639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 517639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 518639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 519639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright int newScreenAutoBrightness = 520a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown clampScreenBrightness(Math.round(value * PowerManager.BRIGHTNESS_ON)); 521639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (mScreenAutoBrightness != newScreenAutoBrightness) { 522639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (DEBUG) { 523639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright Slog.d(TAG, "updateAutoBrightness: mScreenAutoBrightness=" 524639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + mScreenAutoBrightness + ", newScreenAutoBrightness=" 525639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright + newScreenAutoBrightness); 526639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 527639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 528639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mScreenAutoBrightness = newScreenAutoBrightness; 529639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mLastScreenAutoBrightnessGamma = gamma; 530639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (sendUpdate) { 531639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mCallbacks.updateBrightness(); 532639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 533639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 534639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 535639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 536639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private int clampScreenBrightness(int value) { 537639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return MathUtils.constrain(value, 538639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mScreenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum); 539639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 540639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 541a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown private void prepareBrightnessAdjustmentSample() { 542a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown if (!mBrightnessAdjustmentSamplePending) { 543a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mBrightnessAdjustmentSamplePending = true; 544a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mBrightnessAdjustmentSampleOldAdjustment = mScreenAutoBrightnessAdjustment; 545a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mBrightnessAdjustmentSampleOldLux = mAmbientLuxValid ? mAmbientLux : -1; 546a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mBrightnessAdjustmentSampleOldBrightness = mScreenAutoBrightness; 547a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mBrightnessAdjustmentSampleOldGamma = mLastScreenAutoBrightnessGamma; 548a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown } else { 549a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mHandler.removeMessages(MSG_BRIGHTNESS_ADJUSTMENT_SAMPLE); 550a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown } 551a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown 552a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mHandler.sendEmptyMessageDelayed(MSG_BRIGHTNESS_ADJUSTMENT_SAMPLE, 553a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown BRIGHTNESS_ADJUSTMENT_SAMPLE_DEBOUNCE_MILLIS); 554a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown } 555a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown 556a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown private void cancelBrightnessAdjustmentSample() { 557a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown if (mBrightnessAdjustmentSamplePending) { 558a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mBrightnessAdjustmentSamplePending = false; 559a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mHandler.removeMessages(MSG_BRIGHTNESS_ADJUSTMENT_SAMPLE); 560a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown } 561a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown } 562a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown 563a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown private void collectBrightnessAdjustmentSample() { 564a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown if (mBrightnessAdjustmentSamplePending) { 565a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mBrightnessAdjustmentSamplePending = false; 566a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown if (mAmbientLuxValid && mScreenAutoBrightness >= 0) { 567a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown if (DEBUG) { 568a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown Slog.d(TAG, "Auto-brightness adjustment changed by user: " 569a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown + "adj=" + mScreenAutoBrightnessAdjustment 570a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown + ", lux=" + mAmbientLux 571a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown + ", brightness=" + mScreenAutoBrightness 572a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown + ", gamma=" + mLastScreenAutoBrightnessGamma 573a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown + ", ring=" + mAmbientLightRingBuffer); 574a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown } 575a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown 576a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown EventLog.writeEvent(EventLogTags.AUTO_BRIGHTNESS_ADJ, 577a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mBrightnessAdjustmentSampleOldAdjustment, 578a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mBrightnessAdjustmentSampleOldLux, 579a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mBrightnessAdjustmentSampleOldBrightness, 580a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mBrightnessAdjustmentSampleOldGamma, 581a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mScreenAutoBrightnessAdjustment, 582a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mAmbientLux, 583a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mScreenAutoBrightness, 584a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown mLastScreenAutoBrightnessGamma); 585a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown } 586a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown } 587a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown } 588a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown 589639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private final class AutomaticBrightnessHandler extends Handler { 590639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public AutomaticBrightnessHandler(Looper looper) { 591639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright super(looper, null, true /*async*/); 592639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 593639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 594639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright @Override 595639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public void handleMessage(Message msg) { 596639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright switch (msg.what) { 597639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright case MSG_UPDATE_AMBIENT_LUX: 598639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright updateAmbientLux(); 599639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright break; 600a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown 601a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown case MSG_BRIGHTNESS_ADJUSTMENT_SAMPLE: 602a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown collectBrightnessAdjustmentSample(); 603a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown break; 604639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 605639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 606639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 607639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 608639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private final SensorEventListener mLightSensorListener = new SensorEventListener() { 609639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright @Override 610639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public void onSensorChanged(SensorEvent event) { 611639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (mLightSensorEnabled) { 612639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright final long time = SystemClock.uptimeMillis(); 613639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright final float lux = event.values[0]; 614639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright handleLightSensorEvent(time, lux); 615639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 616639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 617639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 618639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright @Override 619639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public void onAccuracyChanged(Sensor sensor, int accuracy) { 620639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // Not used. 621639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 622639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright }; 623639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 624639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private final TwilightListener mTwilightListener = new TwilightListener() { 625639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright @Override 626908b86c796443ba4ec55c669e8a0297fc80574a6Justin Klaassen public void onTwilightStateChanged(@Nullable TwilightState state) { 627639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright updateAutoBrightness(true /*sendUpdate*/); 628639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 629639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright }; 630639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 631639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright /** Callbacks to request updates to the display's power state. */ 632639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright interface Callbacks { 633639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright void updateBrightness(); 634639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 635639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 636103fb78ac1b91874f8b90cc5a165e6f0502179c4Michael Wright private static final class AmbientLightRingBuffer { 637639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // Proportional extra capacity of the buffer beyond the expected number of light samples 638639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // in the horizon 639639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private static final float BUFFER_SLACK = 1.5f; 640639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private float[] mRingLux; 641639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private long[] mRingTime; 642639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private int mCapacity; 643639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 644639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // The first valid element and the next open slot. 645639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // Note that if mCount is zero then there are no valid elements. 646639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private int mStart; 647639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private int mEnd; 648639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private int mCount; 649639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 6506fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic public AmbientLightRingBuffer(long lightSensorRate, int ambientLightHorizon) { 6516fc42f549a6a67fe48e6e8e368dc2b164030d7c3Zoran Jovanovic mCapacity = (int) Math.ceil(ambientLightHorizon * BUFFER_SLACK / lightSensorRate); 652639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mRingLux = new float[mCapacity]; 653639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mRingTime = new long[mCapacity]; 654639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 655639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 656639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public float getLux(int index) { 657639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return mRingLux[offsetOf(index)]; 658639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 659639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 660639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public long getTime(int index) { 661639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return mRingTime[offsetOf(index)]; 662639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 663639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 664639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public void push(long time, float lux) { 665639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright int next = mEnd; 666639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (mCount == mCapacity) { 667639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright int newSize = mCapacity * 2; 668639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 669639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright float[] newRingLux = new float[newSize]; 670639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright long[] newRingTime = new long[newSize]; 671639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright int length = mCapacity - mStart; 672639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright System.arraycopy(mRingLux, mStart, newRingLux, 0, length); 673639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright System.arraycopy(mRingTime, mStart, newRingTime, 0, length); 674639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (mStart != 0) { 675639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright System.arraycopy(mRingLux, 0, newRingLux, length, mStart); 676639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright System.arraycopy(mRingTime, 0, newRingTime, length, mStart); 677639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 678639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mRingLux = newRingLux; 679639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mRingTime = newRingTime; 680639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 681639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright next = mCapacity; 682639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mCapacity = newSize; 683639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mStart = 0; 684639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 685639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mRingTime[next] = time; 686639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mRingLux[next] = lux; 687639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mEnd = next + 1; 688639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (mEnd == mCapacity) { 689639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mEnd = 0; 690639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 691639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mCount++; 692639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 693639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 694639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public void prune(long horizon) { 695639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (mCount == 0) { 696639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return; 697639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 698639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 699639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright while (mCount > 1) { 700639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright int next = mStart + 1; 701639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (next >= mCapacity) { 702639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright next -= mCapacity; 703639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 704639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (mRingTime[next] > horizon) { 705639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // Some light sensors only produce data upon a change in the ambient light 706639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // levels, so we need to consider the previous measurement as the ambient light 707639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // level for all points in time up until we receive a new measurement. Thus, we 708639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // always want to keep the youngest element that would be removed from the 709639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // buffer and just set its measurement time to the horizon time since at that 710639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // point it is the ambient light level, and to remove it would be to drop a 711639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright // valid data point within our horizon. 712639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright break; 713639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 714639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mStart = next; 715639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mCount -= 1; 716639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 717639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 718639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (mRingTime[mStart] < horizon) { 719639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mRingTime[mStart] = horizon; 720639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 721639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 722639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 723639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public int size() { 724639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return mCount; 725639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 726639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 727639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public void clear() { 728639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mStart = 0; 729639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mEnd = 0; 730639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright mCount = 0; 731639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 732639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 733639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright @Override 734639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright public String toString() { 735a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown StringBuffer buf = new StringBuffer(); 736a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown buf.append('['); 737a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown for (int i = 0; i < mCount; i++) { 738a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown final long next = i + 1 < mCount ? getTime(i + 1) : SystemClock.uptimeMillis(); 739a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown if (i != 0) { 740a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown buf.append(", "); 741a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown } 742a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown buf.append(getLux(i)); 743a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown buf.append(" / "); 744a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown buf.append(next - getTime(i)); 745a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown buf.append("ms"); 746639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 747a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown buf.append(']'); 748a576b4d3be8687f0a65fc5777424955d551604e4Jeff Brown return buf.toString(); 749639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 750639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright 751639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright private int offsetOf(int index) { 752639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (index >= mCount || index < 0) { 753639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright throw new ArrayIndexOutOfBoundsException(index); 754639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 755639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright index += mStart; 756639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright if (index >= mCapacity) { 757639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright index -= mCapacity; 758639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 759639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright return index; 760639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 761639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright } 762639c8becc6d0efe9c205f3abf1e9347464a95020Michael Wright} 763