Merge "Added hysteresis check to screen brightness." into pi-dev

This commit is contained in:
TreeHugger Robot
2019-02-13 15:31:32 +00:00
committed by Android (Google) Code Review
5 changed files with 185 additions and 112 deletions

View File

@@ -1436,26 +1436,6 @@
<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>
<!-- An array describing the screen's backlight values corresponding to the brightness
values in the config_screenBrightnessNits array.
@@ -1473,19 +1453,73 @@
<array name="config_screenBrightnessNits">
</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.
is the n-th element of config_ambientBrighteningThresholds, and the new darkening
hysteresis constraint value is the n-th element of config_ambientDarkeningThresholds.
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">
condition calculated index
value < level[0] 0
level[n] <= value < level[n+1] n+1
level[MAX] <= value MAX+1 -->
<integer-array name="config_ambientThresholdLevels">
</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_ambientThresholdLevels. 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_ambientThresholdLevels
description for how the constraint value is chosen. -->
<integer-array name="config_ambientBrighteningThresholds">
<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_ambientThresholdLevels. 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_ambientThresholdLevels
description for how the constraint value is chosen. -->
<integer-array name="config_ambientDarkeningThresholds">
<item>200</item>
</integer-array>
<!-- Array of screen brightness 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_screenBrighteningThresholds, and the new
darkening hysteresis constraint value is the n-th element of
config_screenDarkeningThresholds.
The (zero-based) index is calculated as follows: (MAX is the largest index of the array)
condition calculated index
value < level[0] 0
level[n] <= value < level[n+1] n+1
level[MAX] <= value MAX+1 -->
<integer-array name="config_screenThresholdLevels">
</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_screenThresholdLevels. The brightening threshold is calculated as
screenBrightness * (1.0f + CONSTRAINT_VALUE). When the new screen brightness is higher
than this threshold, it is applied. See the config_screenThresholdLevels description for
how the constraint value is chosen. -->
<integer-array name="config_screenBrighteningThresholds">
<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_screenThresholdLevels. The darkening threshold is calculated as
screenBrightness * (1.0f - CONSTRAINT_VALUE). When the new screen brightness is lower than
this threshold, it is applied. See the config_screenThresholdLevels description for how
the constraint value is chosen. -->
<integer-array name="config_screenDarkeningThresholds">
<item>200</item>
</integer-array>
<!-- Amount of time it takes for the light sensor to warm up in milliseconds.

View File

@@ -1823,9 +1823,12 @@
<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_ambientThresholdLevels" />
<java-symbol type="array" name="config_ambientBrighteningThresholds" />
<java-symbol type="array" name="config_ambientDarkeningThresholds" />
<java-symbol type="array" name="config_screenThresholdLevels" />
<java-symbol type="array" name="config_screenBrighteningThresholds" />
<java-symbol type="array" name="config_screenDarkeningThresholds" />
<java-symbol type="array" name="config_minimumBrightnessCurveLux" />
<java-symbol type="array" name="config_minimumBrightnessCurveNits" />
<java-symbol type="array" name="config_protectedNetworks" />

View File

@@ -16,30 +16,26 @@
package com.android.server.display;
import com.android.server.EventLogTags;
import com.android.server.LocalServices;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.hardware.display.BrightnessConfiguration;
import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.SystemClock;
import android.os.Trace;
import android.text.format.DateUtils;
import android.util.EventLog;
import android.util.MathUtils;
import android.util.Slog;
import android.util.TimeUtils;
import com.android.server.EventLogTags;
import java.io.PrintWriter;
class AutomaticBrightnessController {
@@ -127,7 +123,8 @@ class AutomaticBrightnessController {
private final int mWeightingIntercept;
// Configuration object for determining thresholds to change brightness dynamically
private final HysteresisLevels mHysteresisLevels;
private final HysteresisLevels mAmbientBrightnessThresholds;
private final HysteresisLevels mScreenBrightnessThresholds;
// Amount of time to delay auto-brightness after screen on while waiting for
// the light sensor to warm-up in milliseconds.
@@ -147,8 +144,12 @@ class AutomaticBrightnessController {
private boolean mAmbientLuxValid;
// The ambient light level threshold at which to brighten or darken the screen.
private float mBrighteningLuxThreshold;
private float mDarkeningLuxThreshold;
private float mAmbientBrighteningThreshold;
private float mAmbientDarkeningThreshold;
// The screen light level threshold at which to brighten or darken the screen.
private float mScreenBrighteningThreshold;
private float mScreenDarkeningThreshold;
// The most recent light sample.
private float mLastObservedLux;
@@ -196,7 +197,8 @@ class AutomaticBrightnessController {
int lightSensorWarmUpTime, int brightnessMin, int brightnessMax, float dozeScaleFactor,
int lightSensorRate, int initialLightSensorRate, long brighteningLightDebounceConfig,
long darkeningLightDebounceConfig, boolean resetAmbientLuxAfterWarmUpConfig,
HysteresisLevels hysteresisLevels) {
HysteresisLevels ambientBrightnessThresholds,
HysteresisLevels screenBrightnessThresholds) {
mCallbacks = callbacks;
mSensorManager = sensorManager;
mBrightnessMapper = mapper;
@@ -212,7 +214,8 @@ class AutomaticBrightnessController {
mResetAmbientLuxAfterWarmUpConfig = resetAmbientLuxAfterWarmUpConfig;
mAmbientLightHorizon = AMBIENT_LIGHT_LONG_HORIZON_MILLIS;
mWeightingIntercept = AMBIENT_LIGHT_LONG_HORIZON_MILLIS;
mHysteresisLevels = hysteresisLevels;
mAmbientBrightnessThresholds = ambientBrightnessThresholds;
mScreenBrightnessThresholds = screenBrightnessThresholds;
mShortTermModelValid = true;
mShortTermModelAnchor = -1;
@@ -364,8 +367,10 @@ class AutomaticBrightnessController {
pw.println(" mCurrentLightSensorRate=" + mCurrentLightSensorRate);
pw.println(" mAmbientLux=" + mAmbientLux);
pw.println(" mAmbientLuxValid=" + mAmbientLuxValid);
pw.println(" mBrighteningLuxThreshold=" + mBrighteningLuxThreshold);
pw.println(" mDarkeningLuxThreshold=" + mDarkeningLuxThreshold);
pw.println(" mAmbientBrighteningThreshold=" + mAmbientBrighteningThreshold);
pw.println(" mAmbientDarkeningThreshold=" + mAmbientDarkeningThreshold);
pw.println(" mScreenBrighteningThreshold=" + mScreenBrighteningThreshold);
pw.println(" mScreenDarkeningThreshold=" + mScreenDarkeningThreshold);
pw.println(" mLastObservedLux=" + mLastObservedLux);
pw.println(" mLastObservedLuxTime=" + TimeUtils.formatUptime(mLastObservedLuxTime));
pw.println(" mRecentLightSamples=" + mRecentLightSamples);
@@ -384,7 +389,8 @@ class AutomaticBrightnessController {
mBrightnessMapper.dump(pw);
pw.println();
mHysteresisLevels.dump(pw);
mAmbientBrightnessThresholds.dump(pw);
mScreenBrightnessThresholds.dump(pw);
}
private boolean setLightSensorEnabled(boolean enable) {
@@ -459,8 +465,8 @@ class AutomaticBrightnessController {
lux = 0;
}
mAmbientLux = lux;
mBrighteningLuxThreshold = mHysteresisLevels.getBrighteningThreshold(lux);
mDarkeningLuxThreshold = mHysteresisLevels.getDarkeningThreshold(lux);
mAmbientBrighteningThreshold = mAmbientBrightnessThresholds.getBrighteningThreshold(lux);
mAmbientDarkeningThreshold = mAmbientBrightnessThresholds.getDarkeningThreshold(lux);
// If the short term model was invalidated and the change is drastic enough, reset it.
if (!mShortTermModelValid && mShortTermModelAnchor != -1) {
@@ -551,7 +557,7 @@ class AutomaticBrightnessController {
final int N = mAmbientLightRingBuffer.size();
long earliestValidTime = time;
for (int i = N - 1; i >= 0; i--) {
if (mAmbientLightRingBuffer.getLux(i) <= mBrighteningLuxThreshold) {
if (mAmbientLightRingBuffer.getLux(i) <= mAmbientBrighteningThreshold) {
break;
}
earliestValidTime = mAmbientLightRingBuffer.getTime(i);
@@ -563,7 +569,7 @@ class AutomaticBrightnessController {
final int N = mAmbientLightRingBuffer.size();
long earliestValidTime = time;
for (int i = N - 1; i >= 0; i--) {
if (mAmbientLightRingBuffer.getLux(i) >= mDarkeningLuxThreshold) {
if (mAmbientLightRingBuffer.getLux(i) >= mAmbientDarkeningThreshold) {
break;
}
earliestValidTime = mAmbientLightRingBuffer.getTime(i);
@@ -616,20 +622,19 @@ class AutomaticBrightnessController {
float slowAmbientLux = calculateAmbientLux(time, AMBIENT_LIGHT_LONG_HORIZON_MILLIS);
float fastAmbientLux = calculateAmbientLux(time, AMBIENT_LIGHT_SHORT_HORIZON_MILLIS);
if ((slowAmbientLux >= mBrighteningLuxThreshold &&
fastAmbientLux >= mBrighteningLuxThreshold &&
nextBrightenTransition <= time)
||
(slowAmbientLux <= mDarkeningLuxThreshold &&
fastAmbientLux <= mDarkeningLuxThreshold &&
nextDarkenTransition <= time)) {
if ((slowAmbientLux >= mAmbientBrighteningThreshold
&& fastAmbientLux >= mAmbientBrighteningThreshold
&& nextBrightenTransition <= time)
|| (slowAmbientLux <= mAmbientDarkeningThreshold
&& fastAmbientLux <= mAmbientDarkeningThreshold
&& nextDarkenTransition <= time)) {
setAmbientLux(fastAmbientLux);
if (DEBUG) {
Slog.d(TAG, "updateAmbientLux: " +
((fastAmbientLux > mAmbientLux) ? "Brightened" : "Darkened") + ": " +
"mBrighteningLuxThreshold=" + mBrighteningLuxThreshold + ", " +
"mAmbientLightRingBuffer=" + mAmbientLightRingBuffer + ", " +
"mAmbientLux=" + mAmbientLux);
((fastAmbientLux > mAmbientLux) ? "Brightened" : "Darkened") + ": "
+ "mAmbientBrighteningThreshold=" + mAmbientBrighteningThreshold + ", "
+ "mAmbientLightRingBuffer=" + mAmbientLightRingBuffer + ", "
+ "mAmbientLux=" + mAmbientLux);
}
updateAutoBrightness(true);
nextBrightenTransition = nextAmbientLightBrighteningTransition(time);
@@ -660,6 +665,20 @@ class AutomaticBrightnessController {
int newScreenAutoBrightness =
clampScreenBrightness(Math.round(value * PowerManager.BRIGHTNESS_ON));
// If mScreenAutoBrightness is set, we should have screen{Brightening,Darkening}Threshold,
// in which case we ignore the new screen brightness if it doesn't differ enough from the
// previous one.
if (mScreenAutoBrightness != -1
&& newScreenAutoBrightness > mScreenDarkeningThreshold
&& newScreenAutoBrightness < mScreenBrighteningThreshold) {
if (DEBUG) {
Slog.d(TAG, "ignoring newScreenAutoBrightness: " + mScreenDarkeningThreshold
+ " < " + newScreenAutoBrightness + " < " + mScreenBrighteningThreshold);
}
return;
}
if (mScreenAutoBrightness != newScreenAutoBrightness) {
if (DEBUG) {
Slog.d(TAG, "updateAutoBrightness: " +
@@ -668,6 +687,11 @@ class AutomaticBrightnessController {
}
mScreenAutoBrightness = newScreenAutoBrightness;
mScreenBrighteningThreshold =
mScreenBrightnessThresholds.getBrighteningThreshold(newScreenAutoBrightness);
mScreenDarkeningThreshold =
mScreenBrightnessThresholds.getDarkeningThreshold(newScreenAutoBrightness);
if (sendUpdate) {
mCallbacks.updateBrightness();
}

View File

@@ -16,16 +16,11 @@
package com.android.server.display;
import android.app.ActivityManager;
import com.android.internal.app.IBatteryStats;
import com.android.server.LocalServices;
import com.android.server.am.BatteryStatsService;
import com.android.server.policy.WindowManagerPolicy;
import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.ParceledListSlice;
import android.content.res.Resources;
@@ -54,6 +49,11 @@ import android.util.Slog;
import android.util.TimeUtils;
import android.view.Display;
import com.android.internal.app.IBatteryStats;
import com.android.server.LocalServices;
import com.android.server.am.BatteryStatsService;
import com.android.server.policy.WindowManagerPolicy;
import java.io.PrintWriter;
/**
@@ -422,14 +422,25 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
com.android.internal.R.fraction.config_screenAutoBrightnessDozeScaleFactor,
1, 1);
int[] brightLevels = resources.getIntArray(
com.android.internal.R.array.config_dynamicHysteresisBrightLevels);
int[] darkLevels = resources.getIntArray(
com.android.internal.R.array.config_dynamicHysteresisDarkLevels);
int[] luxHysteresisLevels = resources.getIntArray(
com.android.internal.R.array.config_dynamicHysteresisLuxLevels);
HysteresisLevels hysteresisLevels = new HysteresisLevels(
brightLevels, darkLevels, luxHysteresisLevels);
int[] ambientBrighteningThresholds = resources.getIntArray(
com.android.internal.R.array.config_ambientBrighteningThresholds);
int[] ambientDarkeningThresholds = resources.getIntArray(
com.android.internal.R.array.config_ambientDarkeningThresholds);
int[] ambientThresholdLevels = resources.getIntArray(
com.android.internal.R.array.config_ambientThresholdLevels);
HysteresisLevels ambientBrightnessThresholds = new HysteresisLevels(
ambientBrighteningThresholds, ambientDarkeningThresholds,
ambientThresholdLevels);
int[] screenBrighteningThresholds = resources.getIntArray(
com.android.internal.R.array.config_screenBrighteningThresholds);
int[] screenDarkeningThresholds = resources.getIntArray(
com.android.internal.R.array.config_screenDarkeningThresholds);
int[] screenThresholdLevels = resources.getIntArray(
com.android.internal.R.array.config_screenThresholdLevels);
HysteresisLevels screenBrightnessThresholds = new HysteresisLevels(
screenBrighteningThresholds, screenDarkeningThresholds, screenThresholdLevels);
long brighteningLightDebounce = resources.getInteger(
com.android.internal.R.integer.config_autoBrightnessBrighteningLightDebounce);
@@ -459,7 +470,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
lightSensorWarmUpTimeConfig, mScreenBrightnessRangeMinimum,
mScreenBrightnessRangeMaximum, dozeScaleFactor, lightSensorRate,
initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce,
autoBrightnessResetAmbientLuxAfterWarmUp, hysteresisLevels);
autoBrightnessResetAmbientLuxAfterWarmUp, ambientBrightnessThresholds,
screenBrightnessThresholds);
} else {
mUseSoftwareAutoBrightnessConfig = false;
}

View File

@@ -28,67 +28,67 @@ 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.
// The recent value must have changed by at least this fraction relative to the
// current value 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;
private final float[] mBrighteningThresholds;
private final float[] mDarkeningThresholds;
private final float[] mThresholdLevels;
/**
* 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) {
/**
* Creates a {@code HysteresisLevels} object with the given equal-length
* integer arrays.
* @param brighteningThresholds an array of brightening hysteresis constraint constants.
* @param darkeningThresholds an array of darkening hysteresis constraint constants.
* @param thresholdLevels a monotonically increasing array of threshold levels.
*/
HysteresisLevels(int[] brighteningThresholds, int[] darkeningThresholds,
int[] thresholdLevels) {
if (brighteningThresholds.length != darkeningThresholds.length
|| darkeningThresholds.length != thresholdLevels.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);
mBrighteningThresholds = setArrayFormat(brighteningThresholds, 1000.0f);
mDarkeningThresholds = setArrayFormat(darkeningThresholds, 1000.0f);
mThresholdLevels = setArrayFormat(thresholdLevels, 1.0f);
}
/**
* Return the brightening hysteresis threshold for the given lux level.
* Return the brightening hysteresis threshold for the given value level.
*/
public float getBrighteningThreshold(float lux) {
float brightConstant = getReferenceLevel(lux, mBrightLevels);
float brightThreshold = lux * (1.0f + brightConstant);
float getBrighteningThreshold(float value) {
float brightConstant = getReferenceLevel(value, mBrighteningThresholds);
float brightThreshold = value * (1.0f + brightConstant);
if (DEBUG) {
Slog.d(TAG, "bright hysteresis constant=: " + brightConstant + ", threshold="
+ brightThreshold + ", lux=" + lux);
Slog.d(TAG, "bright hysteresis constant=" + brightConstant + ", threshold="
+ brightThreshold + ", value=" + value);
}
return brightThreshold;
}
/**
* Return the darkening hysteresis threshold for the given lux level.
* Return the darkening hysteresis threshold for the given value level.
*/
public float getDarkeningThreshold(float lux) {
float darkConstant = getReferenceLevel(lux, mDarkLevels);
float darkThreshold = lux * (1.0f - darkConstant);
float getDarkeningThreshold(float value) {
float darkConstant = getReferenceLevel(value, mDarkeningThresholds);
float darkThreshold = value * (1.0f - darkConstant);
if (DEBUG) {
Slog.d(TAG, "dark hysteresis constant=: " + darkConstant + ", threshold="
+ darkThreshold + ", lux=" + lux);
+ darkThreshold + ", value=" + value);
}
return darkThreshold;
}
/**
* Return the hysteresis constant for the closest lux threshold value to the
* current illuminance from the given array.
* Return the hysteresis constant for the closest threshold value from the given array.
*/
private float getReferenceLevel(float lux, float[] referenceLevels) {
private float getReferenceLevel(float value, float[] referenceLevels) {
int index = 0;
while (mLuxLevels.length > index && lux >= mLuxLevels[index]) {
while (mThresholdLevels.length > index && value >= mThresholdLevels[index]) {
++index;
}
return referenceLevels[index];
@@ -105,10 +105,10 @@ final class HysteresisLevels {
return levelArray;
}
public void dump(PrintWriter pw) {
void dump(PrintWriter pw) {
pw.println("HysteresisLevels");
pw.println(" mBrightLevels=" + Arrays.toString(mBrightLevels));
pw.println(" mDarkLevels=" + Arrays.toString(mDarkLevels));
pw.println(" mLuxLevels=" + Arrays.toString(mLuxLevels));
pw.println(" mBrighteningThresholds=" + Arrays.toString(mBrighteningThresholds));
pw.println(" mDarkeningThresholds=" + Arrays.toString(mDarkeningThresholds));
pw.println(" mThresholdLevels=" + Arrays.toString(mThresholdLevels));
}
}