DO NOT MERGE ANYWHERE: Add dynamic illuminance hysteresis support

Bug: 18572096

Change-Id: Ie0ff1990b8f4a3d435328834871f04a6e2bd5e97
This commit is contained in:
Julius D'souza
2016-08-07 19:08:30 -07:00
parent ddf70b9195
commit 3275a3a5a5
5 changed files with 161 additions and 12 deletions

View File

@@ -1082,6 +1082,40 @@
<integer-array name="config_autoBrightnessKeyboardBacklightValues">
</integer-array>
<!-- Array of hysteresis constraint values for brightening, represented as tenths of a
percent. The length of this array is assumed to be one greater than
config_dynamicHysteresisLuxLevels. The brightening threshold is calculated as
lux * (1.0f + CONSTRAINT_VALUE). When the current lux is higher than this threshold,
the screen brightness is recalculated. See the config_dynamicHysteresisLuxLevels
description for how the constraint value is chosen. -->
<integer-array name="config_dynamicHysteresisBrightLevels">
<item>100</item>
</integer-array>
<!-- Array of hysteresis constraint values for darkening, represented as tenths of a
percent. The length of this array is assumed to be one greater than
config_dynamicHysteresisLuxLevels. The darkening threshold is calculated as
lux * (1.0f - CONSTRAINT_VALUE). When the current lux is lower than this threshold,
the screen brightness is recalculated. See the config_dynamicHysteresisLuxLevels
description for how the constraint value is chosen. -->
<integer-array name="config_dynamicHysteresisDarkLevels">
<item>200</item>
</integer-array>
<!-- Array of ambient lux threshold values. This is used for determining hysteresis constraint
values by calculating the index to use for lookup and then setting the constraint value
to the corresponding value of the array. The new brightening hysteresis constraint value
is the n-th element of config_dynamicHysteresisBrightLevels, and the new darkening
hysteresis constraint value is the n-th element of config_dynamicHysteresisDarkLevels.
The (zero-based) index is calculated as follows: (MAX is the largest index of the array)
condition calculated index
value < lux[0] 0
lux[n] <= value < lux[n+1] n+1
lux[MAX] <= value MAX+1 -->
<integer-array name="config_dynamicHysteresisLuxLevels">
</integer-array>
<!-- Amount of time it takes for the light sensor to warm up in milliseconds.
For this time after the screen turns on, the Power Manager
will not debounce light sensor readings -->

View File

@@ -1607,6 +1607,9 @@
<java-symbol type="array" name="config_autoBrightnessKeyboardBacklightValues" />
<java-symbol type="array" name="config_autoBrightnessLcdBacklightValues" />
<java-symbol type="array" name="config_autoBrightnessLevels" />
<java-symbol type="array" name="config_dynamicHysteresisBrightLevels" />
<java-symbol type="array" name="config_dynamicHysteresisDarkLevels" />
<java-symbol type="array" name="config_dynamicHysteresisLuxLevels" />
<java-symbol type="array" name="config_protectedNetworks" />
<java-symbol type="array" name="config_statusBarIcons" />
<java-symbol type="array" name="config_tether_bluetooth_regexs" />

View File

@@ -56,12 +56,6 @@ class AutomaticBrightnessController {
// Period of time in which to consider light samples in milliseconds.
private static final int AMBIENT_LIGHT_HORIZON = 10000;
// Hysteresis constraints for brightening or darkening.
// The recent lux must have changed by at least this fraction relative to the
// current ambient lux before a change will be considered.
private static final float BRIGHTENING_LIGHT_HYSTERESIS = 0.10f;
private static final float DARKENING_LIGHT_HYSTERESIS = 0.20f;
// The intercept used for the weighting calculation. This is used in order to keep all possible
// weighting values positive.
private static final int WEIGHTING_INTERCEPT = AMBIENT_LIGHT_HORIZON;
@@ -95,7 +89,7 @@ class AutomaticBrightnessController {
private static final int MSG_UPDATE_AMBIENT_LUX = 1;
private static final int MSG_BRIGHTNESS_ADJUSTMENT_SAMPLE = 2;
// Callbacks for requesting updates to the the display's power state
// Callbacks for requesting updates to the display's power state
private final Callbacks mCallbacks;
// The sensor manager.
@@ -132,6 +126,9 @@ class AutomaticBrightnessController {
// and only then decide whether to change brightness.
private final boolean mResetAmbientLuxAfterWarmUpConfig;
// accessor object for determining thresholds to change brightness dynamically
private final HysteresisLevels mDynamicHysteresis;
// Amount of time to delay auto-brightness after screen on while waiting for
// the light sensor to warm-up in milliseconds.
// May be 0 if no warm-up is required.
@@ -197,7 +194,8 @@ class AutomaticBrightnessController {
SensorManager sensorManager, Spline autoBrightnessSpline, int lightSensorWarmUpTime,
int brightnessMin, int brightnessMax, float dozeScaleFactor,
int lightSensorRate, long brighteningLightDebounceConfig,
long darkeningLightDebounceConfig, boolean resetAmbientLuxAfterWarmUpConfig) {
long darkeningLightDebounceConfig, boolean resetAmbientLuxAfterWarmUpConfig,
HysteresisLevels dynamicHysteresis) {
mCallbacks = callbacks;
mTwilight = LocalServices.getService(TwilightManager.class);
mSensorManager = sensorManager;
@@ -210,6 +208,7 @@ class AutomaticBrightnessController {
mBrighteningLightDebounceConfig = brighteningLightDebounceConfig;
mDarkeningLightDebounceConfig = darkeningLightDebounceConfig;
mResetAmbientLuxAfterWarmUpConfig = resetAmbientLuxAfterWarmUpConfig;
mDynamicHysteresis = dynamicHysteresis;
mHandler = new AutomaticBrightnessHandler(looper);
mAmbientLightRingBuffer = new AmbientLightRingBuffer(mLightSensorRate);
@@ -327,8 +326,8 @@ class AutomaticBrightnessController {
private void setAmbientLux(float lux) {
mAmbientLux = lux;
mBrighteningLuxThreshold = mAmbientLux * (1.0f + BRIGHTENING_LIGHT_HYSTERESIS);
mDarkeningLuxThreshold = mAmbientLux * (1.0f - DARKENING_LIGHT_HYSTERESIS);
mBrighteningLuxThreshold = mDynamicHysteresis.getBrighteningThreshold(lux);
mDarkeningLuxThreshold = mDynamicHysteresis.getDarkeningThreshold(lux);
}
private float calculateAmbientLux(long now) {

View File

@@ -72,7 +72,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
private static final String TAG = "DisplayPowerController";
private static final String SCREEN_ON_BLOCKED_TRACE_NAME = "Screen on blocked";
private static boolean DEBUG = false;
private static final boolean DEBUG = false;
private static final boolean DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT = false;
// If true, uses the color fade on animation.
@@ -317,6 +317,15 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
boolean autoBrightnessResetAmbientLuxAfterWarmUp = resources.getBoolean(
com.android.internal.R.bool.config_autoBrightnessResetAmbientLuxAfterWarmUp);
int[] brightLevels = resources.getIntArray(
com.android.internal.R.array.config_dynamicHysteresisBrightLevels);
int[] darkLevels = resources.getIntArray(
com.android.internal.R.array.config_dynamicHysteresisDarkLevels);
int[] luxLevels = resources.getIntArray(
com.android.internal.R.array.config_dynamicHysteresisLuxLevels);
HysteresisLevels dynamicHysteresis = new HysteresisLevels(
brightLevels, darkLevels, luxLevels);
if (mUseSoftwareAutoBrightnessConfig) {
int[] lux = resources.getIntArray(
com.android.internal.R.array.config_autoBrightnessLevels);
@@ -353,7 +362,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
lightSensorWarmUpTimeConfig, screenBrightnessRangeMinimum,
mScreenBrightnessRangeMaximum, dozeScaleFactor, lightSensorRate,
brighteningLightDebounce, darkeningLightDebounce,
autoBrightnessResetAmbientLuxAfterWarmUp);
autoBrightnessResetAmbientLuxAfterWarmUp, dynamicHysteresis);
}
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.display;
import android.util.Slog;
/**
* A helper class for handling access to illuminance hysteresis level values.
*/
final class HysteresisLevels {
private static final String TAG = "HysteresisLevels";
// Default hysteresis constraints for brightening or darkening.
// The recent lux must have changed by at least this fraction relative to the
// current ambient lux before a change will be considered.
private static final float DEFAULT_BRIGHTENING_HYSTERESIS = 0.10f;
private static final float DEFAULT_DARKENING_HYSTERESIS = 0.20f;
private static final boolean DEBUG = false;
private final float[] mBrightLevels;
private final float[] mDarkLevels;
private final float[] mLuxLevels;
/**
* Creates a {@code HysteresisLevels} object with the given equal-length
* integer arrays.
* @param brightLevels an array of brightening hysteresis constraint constants
* @param darkLevels an array of darkening hysteresis constraint constants
* @param luxLevels a monotonically increasing array of illuminance
* thresholds in units of lux
*/
public HysteresisLevels(int[] brightLevels, int[] darkLevels, int[] luxLevels) {
if (brightLevels.length != darkLevels.length || darkLevels.length != luxLevels.length + 1) {
throw new IllegalArgumentException("Mismatch between hysteresis array lengths.");
}
mBrightLevels = setArrayFormat(brightLevels, 1000.0f);
mDarkLevels = setArrayFormat(darkLevels, 1000.0f);
mLuxLevels = setArrayFormat(luxLevels, 1.0f);
}
/**
* Return the brightening hysteresis threshold for the given lux level.
*/
public float getBrighteningThreshold(float lux) {
float brightConstant = getReferenceLevel(lux, mBrightLevels);
float brightThreshold = lux * (1.0f + brightConstant);
if (DEBUG) {
Slog.d(TAG, "bright hysteresis constant=: " + brightConstant + ", threshold="
+ brightThreshold + ", lux=" + lux);
}
return brightThreshold;
}
/**
* Return the darkening hysteresis threshold for the given lux level.
*/
public float getDarkeningThreshold(float lux) {
float darkConstant = getReferenceLevel(lux, mDarkLevels);
float darkThreshold = lux * (1.0f - darkConstant);
if (DEBUG) {
Slog.d(TAG, "dark hysteresis constant=: " + darkConstant + ", threshold="
+ darkThreshold + ", lux=" + lux);
}
return darkThreshold;
}
/**
* Return the hysteresis constant for the closest lux threshold value to the
* current illuminance from the given array.
*/
private float getReferenceLevel(float lux, float[] referenceLevels) {
int index = 0;
while (mLuxLevels.length > index && lux >= mLuxLevels[index]) {
++index;
}
return referenceLevels[index];
}
/**
* Return a float array where each i-th element equals {@code configArray[i]/divideFactor}.
*/
private float[] setArrayFormat(int[] configArray, float divideFactor) {
float[] levelArray = new float[configArray.length];
for (int index = 0; levelArray.length > index; ++index) {
levelArray[index] = (float)configArray[index] / divideFactor;
}
return levelArray;
}
}