Merge "Added gamma correction to autobrightness." into pi-dev
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index 45c9a71..48bb409 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -219,7 +219,7 @@
# DisplayManagerService.java
# ---------------------------
# Auto-brightness adjustments by the user.
-35000 auto_brightness_adj (old_adj|5),(old_lux|5),(old_brightness|5),(old_gamma|5),(new_adj|5),(new_lux|5),(new_brightness|5),(new_gamma|5)
+35000 auto_brightness_adj (old_lux|5),(old_brightness|5),(new_lux|5),(new_brightness|5)
# ---------------------------
# ConnectivityService.java
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 5e1afeb..bfd34ac 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -169,16 +169,6 @@
// Use -1 if there is no current auto-brightness value available.
private int mScreenAutoBrightness = -1;
- // The screen auto-brightness adjustment factor in the range -1 (dimmer) to 1 (brighter)
- private float mScreenAutoBrightnessAdjustment = 0.0f;
-
- // The maximum range of gamma adjustment possible using the screen
- // auto-brightness adjustment setting.
- private float mScreenAutoBrightnessAdjustmentMaxGamma;
-
- // The last screen auto-brightness gamma. (For printing in dump() only.)
- private float mLastScreenAutoBrightnessGamma = 1.0f;
-
// The current display policy. This is useful, for example, for knowing when we're dozing,
// where the light sensor may not be available.
private int mDisplayPolicy = DisplayPowerRequest.POLICY_OFF;
@@ -186,10 +176,8 @@
// True if we are collecting a brightness adjustment sample, along with some data
// for the initial state of the sample.
private boolean mBrightnessAdjustmentSamplePending;
- private float mBrightnessAdjustmentSampleOldAdjustment;
private float mBrightnessAdjustmentSampleOldLux;
private int mBrightnessAdjustmentSampleOldBrightness;
- private float mBrightnessAdjustmentSampleOldGamma;
// When the short term model is invalidated, we don't necessarily reset it (i.e. clear the
// user's adjustment) immediately, but wait for a drastic enough change in the ambient light.
@@ -200,12 +188,11 @@
private float SHORT_TERM_MODEL_THRESHOLD_RATIO = 0.6f;
public AutomaticBrightnessController(Callbacks callbacks, Looper looper,
- SensorManager sensorManager, BrightnessMappingStrategy mapper, int lightSensorWarmUpTime,
- int brightnessMin, int brightnessMax, float dozeScaleFactor,
+ SensorManager sensorManager, BrightnessMappingStrategy mapper,
+ int lightSensorWarmUpTime, int brightnessMin, int brightnessMax, float dozeScaleFactor,
int lightSensorRate, int initialLightSensorRate, long brighteningLightDebounceConfig,
long darkeningLightDebounceConfig, boolean resetAmbientLuxAfterWarmUpConfig,
- int ambientLightHorizon, float autoBrightnessAdjustmentMaxGamma,
- HysteresisLevels dynamicHysteresis) {
+ int ambientLightHorizon, HysteresisLevels dynamicHysteresis) {
mCallbacks = callbacks;
mSensorManager = sensorManager;
mBrightnessMapper = mapper;
@@ -221,7 +208,6 @@
mResetAmbientLuxAfterWarmUpConfig = resetAmbientLuxAfterWarmUpConfig;
mAmbientLightHorizon = ambientLightHorizon;
mWeightingIntercept = ambientLightHorizon;
- mScreenAutoBrightnessAdjustmentMaxGamma = autoBrightnessAdjustmentMaxGamma;
mDynamicHysteresis = dynamicHysteresis;
mShortTermModelValid = true;
mShortTermModelAnchor = -1;
@@ -243,7 +229,7 @@
}
public float getAutomaticScreenBrightnessAdjustment() {
- return mScreenAutoBrightnessAdjustment;
+ return mBrightnessMapper.getAutoBrightnessAdjustment();
}
public void configure(boolean enable, @Nullable BrightnessConfiguration configuration,
@@ -257,7 +243,9 @@
boolean dozing = (displayPolicy == DisplayPowerRequest.POLICY_DOZE);
boolean changed = setBrightnessConfiguration(configuration);
changed |= setDisplayPolicy(displayPolicy);
- changed |= setScreenAutoBrightnessAdjustment(adjustment);
+ if (userChangedAutoBrightnessAdjustment) {
+ changed |= setAutoBrightnessAdjustment(adjustment);
+ }
if (userChangedBrightness && enable) {
// Update the brightness curve with the new user control point. It's critical this
// happens after we update the autobrightness adjustment since it may reset it.
@@ -322,9 +310,6 @@
if (DEBUG) {
Slog.d(TAG, "ShortTermModel: anchor=" + mShortTermModelAnchor);
}
- // Reset the brightness adjustment so that the next time we're queried for brightness we
- // return the value the user set.
- mScreenAutoBrightnessAdjustment = 0.0f;
return true;
}
@@ -369,10 +354,6 @@
pw.println(" mRecentLightSamples=" + mRecentLightSamples);
pw.println(" mAmbientLightRingBuffer=" + mAmbientLightRingBuffer);
pw.println(" mScreenAutoBrightness=" + mScreenAutoBrightness);
- pw.println(" mScreenAutoBrightnessAdjustment=" + mScreenAutoBrightnessAdjustment);
- pw.println(" mScreenAutoBrightnessAdjustmentMaxGamma="
- + mScreenAutoBrightnessAdjustmentMaxGamma);
- pw.println(" mLastScreenAutoBrightnessGamma=" + mLastScreenAutoBrightnessGamma);
pw.println(" mDisplayPolicy=" + mDisplayPolicy);
pw.println(" mShortTermModelAnchor=" + mShortTermModelAnchor);
@@ -429,8 +410,8 @@
if (lightSensorRate != mCurrentLightSensorRate) {
if (DEBUG) {
Slog.d(TAG, "adjustLightSensorRate: " +
- "previousRate=" + mCurrentLightSensorRate + ", " +
- "currentRate=" + lightSensorRate);
+ "previousRate=" + mCurrentLightSensorRate + ", " +
+ "currentRate=" + lightSensorRate);
}
mCurrentLightSensorRate = lightSensorRate;
mSensorManager.unregisterListener(mLightSensorListener);
@@ -439,12 +420,8 @@
}
}
- private boolean setScreenAutoBrightnessAdjustment(float adjustment) {
- if (adjustment != mScreenAutoBrightnessAdjustment) {
- mScreenAutoBrightnessAdjustment = adjustment;
- return true;
- }
- return false;
+ private boolean setAutoBrightnessAdjustment(float adjustment) {
+ return mBrightnessMapper.setAutoBrightnessAdjustment(adjustment);
}
private void setAmbientLux(float lux) {
@@ -466,12 +443,14 @@
final float maxAmbientLux =
mShortTermModelAnchor + mShortTermModelAnchor * SHORT_TERM_MODEL_THRESHOLD_RATIO;
if (minAmbientLux < mAmbientLux && mAmbientLux < maxAmbientLux) {
- Slog.d(TAG, "ShortTermModel: re-validate user data, ambient lux is " +
- minAmbientLux + " < " + mAmbientLux + " < " + maxAmbientLux);
+ if (DEBUG) {
+ Slog.d(TAG, "ShortTermModel: re-validate user data, ambient lux is " +
+ minAmbientLux + " < " + mAmbientLux + " < " + maxAmbientLux);
+ }
mShortTermModelValid = true;
} else {
Slog.d(TAG, "ShortTermModel: reset data, ambient lux is " + mAmbientLux +
- "(" + minAmbientLux + ", " + maxAmbientLux + ")");
+ "(" + minAmbientLux + ", " + maxAmbientLux + ")");
resetShortTermModel();
}
}
@@ -498,9 +477,9 @@
}
}
if (DEBUG) {
- Slog.d(TAG, "calculateAmbientLux: selected endIndex=" + endIndex + ", point=("
- + mAmbientLightRingBuffer.getTime(endIndex) + ", "
- + mAmbientLightRingBuffer.getLux(endIndex) + ")");
+ Slog.d(TAG, "calculateAmbientLux: selected endIndex=" + endIndex + ", point=(" +
+ mAmbientLightRingBuffer.getTime(endIndex) + ", " +
+ mAmbientLightRingBuffer.getLux(endIndex) + ")");
}
float sum = 0;
float totalWeight = 0;
@@ -517,8 +496,8 @@
float lux = mAmbientLightRingBuffer.getLux(i);
if (DEBUG) {
Slog.d(TAG, "calculateAmbientLux: [" + startTime + ", " + endTime + "]: " +
- "lux=" + lux + ", " +
- "weight=" + weight);
+ "lux=" + lux + ", " +
+ "weight=" + weight);
}
totalWeight += weight;
sum += lux * weight;
@@ -526,8 +505,8 @@
}
if (DEBUG) {
Slog.d(TAG, "calculateAmbientLux: " +
- "totalWeight=" + totalWeight + ", " +
- "newAmbientLux=" + (sum / totalWeight));
+ "totalWeight=" + totalWeight + ", " +
+ "newAmbientLux=" + (sum / totalWeight));
}
return sum / totalWeight;
}
@@ -581,8 +560,8 @@
if (time < timeWhenSensorWarmedUp) {
if (DEBUG) {
Slog.d(TAG, "updateAmbientLux: Sensor not ready yet: " +
- "time=" + time + ", " +
- "timeWhenSensorWarmedUp=" + timeWhenSensorWarmedUp);
+ "time=" + time + ", " +
+ "timeWhenSensorWarmedUp=" + timeWhenSensorWarmedUp);
}
mHandler.sendEmptyMessageAtTime(MSG_UPDATE_AMBIENT_LUX,
timeWhenSensorWarmedUp);
@@ -621,10 +600,10 @@
setAmbientLux(fastAmbientLux);
if (DEBUG) {
Slog.d(TAG, "updateAmbientLux: " +
- ((fastAmbientLux > mAmbientLux) ? "Brightened" : "Darkened") + ": " +
- "mBrighteningLuxThreshold=" + mBrighteningLuxThreshold + ", " +
- "mAmbientLightRingBuffer=" + mAmbientLightRingBuffer + ", " +
- "mAmbientLux=" + mAmbientLux);
+ ((fastAmbientLux > mAmbientLux) ? "Brightened" : "Darkened") + ": " +
+ "mBrighteningLuxThreshold=" + mBrighteningLuxThreshold + ", " +
+ "mAmbientLightRingBuffer=" + mAmbientLightRingBuffer + ", " +
+ "mAmbientLux=" + mAmbientLux);
}
updateAutoBrightness(true);
nextBrightenTransition = nextAmbientLightBrighteningTransition(time);
@@ -641,7 +620,7 @@
nextTransitionTime > time ? nextTransitionTime : time + mNormalLightSensorRate;
if (DEBUG) {
Slog.d(TAG, "updateAmbientLux: Scheduling ambient lux update for " +
- nextTransitionTime + TimeUtils.formatUptime(nextTransitionTime));
+ nextTransitionTime + TimeUtils.formatUptime(nextTransitionTime));
}
mHandler.sendEmptyMessageAtTime(MSG_UPDATE_AMBIENT_LUX, nextTransitionTime);
}
@@ -652,40 +631,17 @@
}
float value = mBrightnessMapper.getBrightness(mAmbientLux);
- float gamma = 1.0f;
-
- if (USE_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT
- && mScreenAutoBrightnessAdjustment != 0.0f) {
- final float adjGamma = MathUtils.pow(mScreenAutoBrightnessAdjustmentMaxGamma,
- Math.min(1.0f, Math.max(-1.0f, -mScreenAutoBrightnessAdjustment)));
- gamma *= adjGamma;
- if (DEBUG) {
- Slog.d(TAG, "updateAutoBrightness: adjGamma=" + adjGamma);
- }
- }
-
- if (gamma != 1.0f) {
- final float in = value;
- value = MathUtils.pow(value, gamma);
- if (DEBUG) {
- Slog.d(TAG, "updateAutoBrightness: " +
- "gamma=" + gamma + ", " +
- "in=" + in + ", " +
- "out=" + value);
- }
- }
int newScreenAutoBrightness =
clampScreenBrightness(Math.round(value * PowerManager.BRIGHTNESS_ON));
if (mScreenAutoBrightness != newScreenAutoBrightness) {
if (DEBUG) {
Slog.d(TAG, "updateAutoBrightness: " +
- "mScreenAutoBrightness=" + mScreenAutoBrightness + ", " +
- "newScreenAutoBrightness=" + newScreenAutoBrightness);
+ "mScreenAutoBrightness=" + mScreenAutoBrightness + ", " +
+ "newScreenAutoBrightness=" + newScreenAutoBrightness);
}
mScreenAutoBrightness = newScreenAutoBrightness;
- mLastScreenAutoBrightnessGamma = gamma;
if (sendUpdate) {
mCallbacks.updateBrightness();
}
@@ -700,10 +656,8 @@
private void prepareBrightnessAdjustmentSample() {
if (!mBrightnessAdjustmentSamplePending) {
mBrightnessAdjustmentSamplePending = true;
- mBrightnessAdjustmentSampleOldAdjustment = mScreenAutoBrightnessAdjustment;
mBrightnessAdjustmentSampleOldLux = mAmbientLuxValid ? mAmbientLux : -1;
mBrightnessAdjustmentSampleOldBrightness = mScreenAutoBrightness;
- mBrightnessAdjustmentSampleOldGamma = mLastScreenAutoBrightnessGamma;
} else {
mHandler.removeMessages(MSG_BRIGHTNESS_ADJUSTMENT_SAMPLE);
}
@@ -725,22 +679,16 @@
if (mAmbientLuxValid && mScreenAutoBrightness >= 0) {
if (DEBUG) {
Slog.d(TAG, "Auto-brightness adjustment changed by user: " +
- "adj=" + mScreenAutoBrightnessAdjustment + ", " +
- "lux=" + mAmbientLux + ", " +
- "brightness=" + mScreenAutoBrightness + ", " +
- "gamma=" + mLastScreenAutoBrightnessGamma + ", " +
- "ring=" + mAmbientLightRingBuffer);
+ "lux=" + mAmbientLux + ", " +
+ "brightness=" + mScreenAutoBrightness + ", " +
+ "ring=" + mAmbientLightRingBuffer);
}
EventLog.writeEvent(EventLogTags.AUTO_BRIGHTNESS_ADJ,
- mBrightnessAdjustmentSampleOldAdjustment,
mBrightnessAdjustmentSampleOldLux,
mBrightnessAdjustmentSampleOldBrightness,
- mBrightnessAdjustmentSampleOldGamma,
- mScreenAutoBrightnessAdjustment,
mAmbientLux,
- mScreenAutoBrightness,
- mLastScreenAutoBrightnessGamma);
+ mScreenAutoBrightness);
}
}
}
diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
index 4313d17..f74daf2 100644
--- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
+++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
@@ -28,6 +28,7 @@
import com.android.internal.util.Preconditions;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.display.utils.Plog;
import java.io.PrintWriter;
import java.util.Arrays;
@@ -46,6 +47,8 @@
private static final float LUX_GRAD_SMOOTHING = 0.25f;
private static final float MAX_GRAD = 1.0f;
+ private static final Plog PLOG = Plog.createSystemPlog(TAG);
+
@Nullable
public static BrightnessMappingStrategy create(Resources resources) {
float[] luxLevels = getLuxLevels(resources.getIntArray(
@@ -54,6 +57,9 @@
com.android.internal.R.array.config_autoBrightnessLcdBacklightValues);
float[] brightnessLevelsNits = getFloatArray(resources.obtainTypedArray(
com.android.internal.R.array.config_autoBrightnessDisplayValuesNits));
+ float autoBrightnessAdjustmentMaxGamma = resources.getFraction(
+ com.android.internal.R.fraction.config_autoBrightnessAdjustmentMaxGamma,
+ 1, 1);
float[] nitsRange = getFloatArray(resources.obtainTypedArray(
com.android.internal.R.array.config_screenBrightnessNits));
@@ -68,14 +74,16 @@
com.android.internal.R.integer.config_screenBrightnessSettingMaximum);
if (backlightRange[0] > minimumBacklight
|| backlightRange[backlightRange.length - 1] < maximumBacklight) {
- Slog.w(TAG, "Screen brightness mapping does not cover whole range of available"
- + " backlight values, autobrightness functionality may be impaired.");
+ Slog.w(TAG, "Screen brightness mapping does not cover whole range of available " +
+ "backlight values, autobrightness functionality may be impaired.");
}
BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
builder.setCurve(luxLevels, brightnessLevelsNits);
- return new PhysicalMappingStrategy(builder.build(), nitsRange, backlightRange);
+ return new PhysicalMappingStrategy(builder.build(), nitsRange, backlightRange,
+ autoBrightnessAdjustmentMaxGamma);
} else if (isValidMapping(luxLevels, brightnessLevelsBacklight)) {
- return new SimpleMappingStrategy(luxLevels, brightnessLevelsBacklight);
+ return new SimpleMappingStrategy(luxLevels, brightnessLevelsBacklight,
+ autoBrightnessAdjustmentMaxGamma);
} else {
return null;
}
@@ -173,6 +181,26 @@
public abstract float getBrightness(float lux);
/**
+ * Returns the current auto-brightness adjustment.
+ *
+ * The returned adjustment is a value in the range [-1.0, 1.0] such that
+ * {@code config_autoBrightnessAdjustmentMaxGamma<sup>-adjustment</sup>} is used to gamma
+ * correct the brightness curve.
+ */
+ public abstract float getAutoBrightnessAdjustment();
+
+ /**
+ * Sets the auto-brightness adjustment.
+ *
+ * @param adjustment The desired auto-brightness adjustment.
+ * @return Whether the auto-brightness adjustment has changed.
+ *
+ * @Deprecated The auto-brightness adjustment should not be set directly, but rather inferred
+ * from user data points.
+ */
+ public abstract boolean setAutoBrightnessAdjustment(float adjustment);
+
+ /**
* Converts the provided backlight value to nits if possible.
*
* Returns -1.0f if there's no available mapping for the backlight to nits.
@@ -200,12 +228,13 @@
*/
public abstract void clearUserDataPoints();
- /** @return true if there are any short term adjustments applied to the curve */
+ /** @return True if there are any short term adjustments applied to the curve. */
public abstract boolean hasUserDataPoints();
- /** @return true if the current brightness config is the default one */
+ /** @return True if the current brightness configuration is the default one. */
public abstract boolean isDefaultConfig();
+ /** @return The default brightness configuration. */
public abstract BrightnessConfiguration getDefaultConfig();
public abstract void dump(PrintWriter pw);
@@ -216,22 +245,8 @@
return (float) brightness / PowerManager.BRIGHTNESS_ON;
}
- private static Spline createSpline(float[] x, float[] y) {
- Spline spline = Spline.createSpline(x, y);
- if (DEBUG) {
- Slog.d(TAG, "Spline: " + spline);
- for (float v = 1f; v < x[x.length - 1] * 1.25f; v *= 1.25f) {
- Slog.d(TAG, String.format(" %7.1f: %7.1f", v, spline.interpolate(v)));
- }
- }
- return spline;
- }
-
private static Pair<float[], float[]> insertControlPoint(
float[] luxLevels, float[] brightnessLevels, float lux, float brightness) {
- if (DEBUG) {
- Slog.d(TAG, "Inserting new control point at (" + lux + ", " + brightness + ")");
- }
final int idx = findInsertionPoint(luxLevels, lux);
final float[] newLuxLevels;
final float[] newBrightnessLevels;
@@ -274,9 +289,7 @@
private static void smoothCurve(float[] lux, float[] brightness, int idx) {
if (DEBUG) {
- Slog.d(TAG, "smoothCurve(lux=" + Arrays.toString(lux)
- + ", brightness=" + Arrays.toString(brightness)
- + ", idx=" + idx + ")");
+ PLOG.logCurve("unsmoothed curve", lux, brightness);
}
float prevLux = lux[idx];
float prevBrightness = brightness[idx];
@@ -294,7 +307,6 @@
prevBrightness = newBrightness;
brightness[i] = newBrightness;
}
-
// Smooth curve for data points below the newly introduced point
prevLux = lux[idx];
prevBrightness = brightness[idx];
@@ -312,8 +324,7 @@
brightness[i] = newBrightness;
}
if (DEBUG) {
- Slog.d(TAG, "Smoothed Curve: lux=" + Arrays.toString(lux)
- + ", brightness=" + Arrays.toString(brightness));
+ PLOG.logCurve("smoothed curve", lux, brightness);
}
}
@@ -323,6 +334,72 @@
- MathUtils.log(prevLux + LUX_GRAD_SMOOTHING)));
}
+ private static float inferAutoBrightnessAdjustment(float maxGamma,
+ float desiredBrightness, float currentBrightness) {
+ float adjustment = 0;
+ float gamma = Float.NaN;
+ // Extreme edge cases: use a simpler heuristic, as proper gamma correction around the edges
+ // affects the curve rather drastically.
+ if (currentBrightness <= 0.1f || currentBrightness >= 0.9f) {
+ adjustment = (desiredBrightness - currentBrightness) * 2;
+ // Edge case: darkest adjustment possible.
+ } else if (desiredBrightness == 0) {
+ adjustment = -1;
+ // Edge case: brightest adjustment possible.
+ } else if (desiredBrightness == 1) {
+ adjustment = +1;
+ } else {
+ // current^gamma = desired => gamma = log[current](desired)
+ gamma = MathUtils.log(desiredBrightness) / MathUtils.log(currentBrightness);
+ // max^-adjustment = gamma => adjustment = -log[max](gamma)
+ adjustment = -MathUtils.constrain(
+ MathUtils.log(gamma) / MathUtils.log(maxGamma), -1, 1);
+ }
+ if (DEBUG) {
+ Slog.d(TAG, "inferAutoBrightnessAdjustment: " + maxGamma + "^" + -adjustment + "=" +
+ MathUtils.pow(maxGamma, -adjustment) + " == " + gamma);
+ Slog.d(TAG, "inferAutoBrightnessAdjustment: " + currentBrightness + "^" + gamma + "=" +
+ MathUtils.pow(currentBrightness, gamma) + " == " + desiredBrightness);
+ }
+ return adjustment;
+ }
+
+ private static Pair<float[], float[]> getAdjustedCurve(float[] lux, float[] brightness,
+ float userLux, float userBrightness, float adjustment, float maxGamma) {
+ float[] newLux = lux;
+ float[] newBrightness = Arrays.copyOf(brightness, brightness.length);
+ if (DEBUG) {
+ PLOG.logCurve("unadjusted curve", newLux, newBrightness);
+ }
+ adjustment = MathUtils.constrain(adjustment, -1, 1);
+ float gamma = MathUtils.pow(maxGamma, -adjustment);
+ if (DEBUG) {
+ Slog.d(TAG, "getAdjustedCurve: " + maxGamma + "^" + -adjustment + "=" +
+ MathUtils.pow(maxGamma, -adjustment) + " == " + gamma);
+ }
+ if (gamma != 1) {
+ for (int i = 0; i < newBrightness.length; i++) {
+ newBrightness[i] = MathUtils.pow(newBrightness[i], gamma);
+ }
+ }
+ if (DEBUG) {
+ PLOG.logCurve("gamma adjusted curve", newLux, newBrightness);
+ }
+ if (userLux != -1) {
+ Pair<float[], float[]> curve = insertControlPoint(newLux, newBrightness, userLux,
+ userBrightness);
+ newLux = curve.first;
+ newBrightness = curve.second;
+ if (DEBUG) {
+ PLOG.logCurve("gamma and user adjusted curve", newLux, newBrightness);
+ // This is done for comparison.
+ curve = insertControlPoint(lux, brightness, userLux, userBrightness);
+ PLOG.logCurve("user adjusted curve", curve.first ,curve.second);
+ }
+ }
+ return Pair.create(newLux, newBrightness);
+ }
+
/**
* A {@link BrightnessMappingStrategy} that maps from ambient room brightness directly to the
* backlight of the display.
@@ -337,10 +414,12 @@
private final float[] mBrightness;
private Spline mSpline;
+ private float mMaxGamma;
+ private float mAutoBrightnessAdjustment;
private float mUserLux;
private float mUserBrightness;
- public SimpleMappingStrategy(float[] lux, int[] brightness) {
+ public SimpleMappingStrategy(float[] lux, int[] brightness, float maxGamma) {
Preconditions.checkArgument(lux.length != 0 && brightness.length != 0,
"Lux and brightness arrays must not be empty!");
Preconditions.checkArgument(lux.length == brightness.length,
@@ -357,9 +436,14 @@
mBrightness[i] = normalizeAbsoluteBrightness(brightness[i]);
}
- mSpline = createSpline(mLux, mBrightness);
+ mMaxGamma = maxGamma;
+ mAutoBrightnessAdjustment = 0;
mUserLux = -1;
mUserBrightness = -1;
+ if (DEBUG) {
+ PLOG.start("simple mapping strategy");
+ }
+ computeSpline();
}
@Override
@@ -373,27 +457,65 @@
}
@Override
+ public float getAutoBrightnessAdjustment() {
+ return mAutoBrightnessAdjustment;
+ }
+
+ @Override
+ public boolean setAutoBrightnessAdjustment(float adjustment) {
+ adjustment = MathUtils.constrain(adjustment, -1, 1);
+ if (adjustment == mAutoBrightnessAdjustment) {
+ return false;
+ }
+ if (DEBUG) {
+ Slog.d(TAG, "setAutoBrightnessAdjustment: " + mAutoBrightnessAdjustment + " => " +
+ adjustment);
+ PLOG.start("auto-brightness adjustment");
+ }
+ mAutoBrightnessAdjustment = adjustment;
+ computeSpline();
+ return true;
+ }
+
+ @Override
public float convertToNits(int backlight) {
return -1.0f;
}
@Override
public void addUserDataPoint(float lux, float brightness) {
+ float unadjustedBrightness = getUnadjustedBrightness(lux);
if (DEBUG){
- Slog.d(TAG, "addUserDataPoint(lux=" + lux + ", brightness=" + brightness + ")");
+ Slog.d(TAG, "addUserDataPoint: (" + lux + "," + brightness + ")");
+ PLOG.start("add user data point")
+ .logPoint("user data point", lux, brightness)
+ .logPoint("current brightness", lux, unadjustedBrightness);
}
- Pair<float[], float[]> curve = insertControlPoint(mLux, mBrightness, lux, brightness);
- mSpline = createSpline(curve.first, curve.second);
+ float adjustment = inferAutoBrightnessAdjustment(mMaxGamma,
+ brightness /* desiredBrightness */,
+ unadjustedBrightness /* currentBrightness */);
+ if (DEBUG) {
+ Slog.d(TAG, "addUserDataPoint: " + mAutoBrightnessAdjustment + " => " +
+ adjustment);
+ }
+ mAutoBrightnessAdjustment = adjustment;
mUserLux = lux;
mUserBrightness = brightness;
+ computeSpline();
}
@Override
public void clearUserDataPoints() {
if (mUserLux != -1) {
- mSpline = createSpline(mLux, mBrightness);
+ if (DEBUG) {
+ Slog.d(TAG, "clearUserDataPoints: " + mAutoBrightnessAdjustment + " => 0");
+ PLOG.start("clear user data points")
+ .logPoint("user data point", mUserLux, mUserBrightness);
+ }
+ mAutoBrightnessAdjustment = 0;
mUserLux = -1;
mUserBrightness = -1;
+ computeSpline();
}
}
@@ -408,15 +530,30 @@
}
@Override
- public BrightnessConfiguration getDefaultConfig() { return null; }
+ public BrightnessConfiguration getDefaultConfig() {
+ return null;
+ }
@Override
public void dump(PrintWriter pw) {
pw.println("SimpleMappingStrategy");
pw.println(" mSpline=" + mSpline);
+ pw.println(" mMaxGamma=" + mMaxGamma);
+ pw.println(" mAutoBrightnessAdjustment=" + mAutoBrightnessAdjustment);
pw.println(" mUserLux=" + mUserLux);
pw.println(" mUserBrightness=" + mUserBrightness);
}
+
+ private void computeSpline() {
+ Pair<float[], float[]> curve = getAdjustedCurve(mLux, mBrightness, mUserLux,
+ mUserBrightness, mAutoBrightnessAdjustment, mMaxGamma);
+ mSpline = Spline.createSpline(curve.first, curve.second);
+ }
+
+ private float getUnadjustedBrightness(float lux) {
+ Spline spline = Spline.createSpline(mLux, mBrightness);
+ return spline.interpolate(lux);
+ }
}
/** A {@link BrightnessMappingStrategy} that maps from ambient room brightness to the physical
@@ -445,11 +582,13 @@
// a brightness in nits.
private Spline mBacklightToNitsSpline;
+ private float mMaxGamma;
+ private float mAutoBrightnessAdjustment;
private float mUserLux;
private float mUserBrightness;
- public PhysicalMappingStrategy(BrightnessConfiguration config,
- float[] nits, int[] backlight) {
+ public PhysicalMappingStrategy(BrightnessConfiguration config, float[] nits,
+ int[] backlight, float maxGamma) {
Preconditions.checkArgument(nits.length != 0 && backlight.length != 0,
"Nits and backlight arrays must not be empty!");
Preconditions.checkArgument(nits.length == backlight.length,
@@ -459,6 +598,8 @@
Preconditions.checkArrayElementsInRange(backlight,
PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON, "backlight");
+ mMaxGamma = maxGamma;
+ mAutoBrightnessAdjustment = 0;
mUserLux = -1;
mUserBrightness = -1;
@@ -469,11 +610,15 @@
normalizedBacklight[i] = normalizeAbsoluteBrightness(backlight[i]);
}
- mNitsToBacklightSpline = createSpline(nits, normalizedBacklight);
- mBacklightToNitsSpline = createSpline(normalizedBacklight, nits);
+ mNitsToBacklightSpline = Spline.createSpline(nits, normalizedBacklight);
+ mBacklightToNitsSpline = Spline.createSpline(normalizedBacklight, nits);
mDefaultConfig = config;
- setBrightnessConfiguration(config);
+ if (DEBUG) {
+ PLOG.start("physical mapping strategy");
+ }
+ mConfig = config;
+ computeSpline();
}
@Override
@@ -484,10 +629,11 @@
if (config.equals(mConfig)) {
return false;
}
-
- Pair<float[], float[]> curve = config.getCurve();
- mBrightnessSpline = createSpline(curve.first /*lux*/, curve.second /*nits*/);
+ if (DEBUG) {
+ PLOG.start("brightness configuration");
+ }
mConfig = config;
+ computeSpline();
return true;
}
@@ -499,31 +645,65 @@
}
@Override
+ public float getAutoBrightnessAdjustment() {
+ return mAutoBrightnessAdjustment;
+ }
+
+ @Override
+ public boolean setAutoBrightnessAdjustment(float adjustment) {
+ adjustment = MathUtils.constrain(adjustment, -1, 1);
+ if (adjustment == mAutoBrightnessAdjustment) {
+ return false;
+ }
+ if (DEBUG) {
+ Slog.d(TAG, "setAutoBrightnessAdjustment: " + mAutoBrightnessAdjustment + " => " +
+ adjustment);
+ PLOG.start("auto-brightness adjustment");
+ }
+ mAutoBrightnessAdjustment = adjustment;
+ computeSpline();
+ return true;
+ }
+
+ @Override
public float convertToNits(int backlight) {
return mBacklightToNitsSpline.interpolate(normalizeAbsoluteBrightness(backlight));
}
@Override
- public void addUserDataPoint(float lux, float backlight) {
+ public void addUserDataPoint(float lux, float brightness) {
+ float unadjustedBrightness = getUnadjustedBrightness(lux);
if (DEBUG){
- Slog.d(TAG, "addUserDataPoint(lux=" + lux + ", backlight=" + backlight + ")");
+ Slog.d(TAG, "addUserDataPoint: (" + lux + "," + brightness + ")");
+ PLOG.start("add user data point")
+ .logPoint("user data point", lux, brightness)
+ .logPoint("current brightness", lux, unadjustedBrightness);
}
- float brightness = mBacklightToNitsSpline.interpolate(backlight);
- Pair<float[], float[]> defaultCurve = mConfig.getCurve();
- Pair<float[], float[]> newCurve =
- insertControlPoint(defaultCurve.first, defaultCurve.second, lux, brightness);
- mBrightnessSpline = createSpline(newCurve.first, newCurve.second);
+ float adjustment = inferAutoBrightnessAdjustment(mMaxGamma,
+ brightness /* desiredBrightness */,
+ unadjustedBrightness /* currentBrightness */);
+ if (DEBUG) {
+ Slog.d(TAG, "addUserDataPoint: " + mAutoBrightnessAdjustment + " => " +
+ adjustment);
+ }
+ mAutoBrightnessAdjustment = adjustment;
mUserLux = lux;
mUserBrightness = brightness;
+ computeSpline();
}
@Override
public void clearUserDataPoints() {
if (mUserLux != -1) {
- Pair<float[], float[]> defaultCurve = mConfig.getCurve();
- mBrightnessSpline = createSpline(defaultCurve.first, defaultCurve.second);
+ if (DEBUG) {
+ Slog.d(TAG, "clearUserDataPoints: " + mAutoBrightnessAdjustment + " => 0");
+ PLOG.start("clear user data points")
+ .logPoint("user data point", mUserLux, mUserBrightness);
+ }
+ mAutoBrightnessAdjustment = 0;
mUserLux = -1;
mUserBrightness = -1;
+ computeSpline();
}
}
@@ -538,7 +718,9 @@
}
@Override
- public BrightnessConfiguration getDefaultConfig() { return mDefaultConfig; }
+ public BrightnessConfiguration getDefaultConfig() {
+ return mDefaultConfig;
+ }
@Override
public void dump(PrintWriter pw) {
@@ -546,8 +728,35 @@
pw.println(" mConfig=" + mConfig);
pw.println(" mBrightnessSpline=" + mBrightnessSpline);
pw.println(" mNitsToBacklightSpline=" + mNitsToBacklightSpline);
+ pw.println(" mMaxGamma=" + mMaxGamma);
+ pw.println(" mAutoBrightnessAdjustment=" + mAutoBrightnessAdjustment);
pw.println(" mUserLux=" + mUserLux);
pw.println(" mUserBrightness=" + mUserBrightness);
}
+
+ private void computeSpline() {
+ Pair<float[], float[]> defaultCurve = mConfig.getCurve();
+ float[] defaultLux = defaultCurve.first;
+ float[] defaultNits = defaultCurve.second;
+ float[] defaultBacklight = new float[defaultNits.length];
+ for (int i = 0; i < defaultBacklight.length; i++) {
+ defaultBacklight[i] = mNitsToBacklightSpline.interpolate(defaultNits[i]);
+ }
+ Pair<float[], float[]> curve = getAdjustedCurve(defaultLux, defaultBacklight, mUserLux,
+ mUserBrightness, mAutoBrightnessAdjustment, mMaxGamma);
+ float[] lux = curve.first;
+ float[] backlight = curve.second;
+ float[] nits = new float[backlight.length];
+ for (int i = 0; i < nits.length; i++) {
+ nits[i] = mBacklightToNitsSpline.interpolate(backlight[i]);
+ }
+ mBrightnessSpline = Spline.createSpline(lux, nits);
+ }
+
+ private float getUnadjustedBrightness(float lux) {
+ Pair<float[], float[]> curve = mConfig.getCurve();
+ Spline spline = Spline.createSpline(curve.first, curve.second);
+ return mNitsToBacklightSpline.interpolate(spline.interpolate(lux));
+ }
}
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 1784ef1..5f4c8ef 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -424,9 +424,6 @@
com.android.internal.R.bool.config_autoBrightnessResetAmbientLuxAfterWarmUp);
int ambientLightHorizon = resources.getInteger(
com.android.internal.R.integer.config_autoBrightnessAmbientLightHorizon);
- float autoBrightnessAdjustmentMaxGamma = resources.getFraction(
- com.android.internal.R.fraction.config_autoBrightnessAdjustmentMaxGamma,
- 1, 1);
int lightSensorWarmUpTimeConfig = resources.getInteger(
com.android.internal.R.integer.config_lightSensorWarmupTime);
@@ -450,7 +447,7 @@
mScreenBrightnessRangeMaximum, dozeScaleFactor, lightSensorRate,
initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce,
autoBrightnessResetAmbientLuxAfterWarmUp, ambientLightHorizon,
- autoBrightnessAdjustmentMaxGamma, dynamicHysteresis);
+ dynamicHysteresis);
} else {
mUseSoftwareAutoBrightnessConfig = false;
}
diff --git a/services/core/java/com/android/server/display/utils/Plog.java b/services/core/java/com/android/server/display/utils/Plog.java
new file mode 100644
index 0000000..3a18387
--- /dev/null
+++ b/services/core/java/com/android/server/display/utils/Plog.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2018 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.utils;
+
+
+import java.lang.StringBuilder;
+import java.lang.System;
+
+import android.util.Slog;
+
+/**
+ * A utility to log multiple points and curves in a structured way so they can be easily consumed
+ * by external tooling
+ *
+ * To start a plot, call {@link Plog.start} with the plot's title; to add a point to it, call
+ * {@link Plog.logPoint} with the point name (that will appear in the legend) and coordinates; and
+ * to log a curve, call {@link Plog.logCurve} with its name and points.
+ */
+public abstract class Plog {
+ // A unique identifier used to group points and curves that belong on the same plot.
+ private long mId;
+
+ /**
+ * Returns a Plog instance that emits messages to the system log.
+ *
+ * @param tag The tag of the emitted messages in the system log.
+ * @return A plog instance that emits messages to the system log.
+ */
+ public static Plog createSystemPlog(String tag) {
+ return new SystemPlog(tag);
+ }
+
+ /**
+ * Start a new plot.
+ *
+ * @param title The plot title.
+ * @return The Plog instance (for chaining).
+ */
+ public Plog start(String title) {
+ mId = System.currentTimeMillis();
+ write(formatTitle(title));
+ return this;
+ }
+
+ /**
+ * Adds a point to the current plot.
+ *
+ * @param name The point name (that will appear in the legend).
+ * @param x The point x coordinate.
+ * @param y The point y coordinate.
+ * @return The Plog instance (for chaining).
+ */
+ public Plog logPoint(String name, float x, float y) {
+ write(formatPoint(name, x, y));
+ return this;
+ }
+
+ /**
+ * Adds a curve to the current plot.
+ *
+ * @param name The curve name (that will appear in the legend).
+ * @param xs The curve x coordinates.
+ * @param ys The curve y coordinates.
+ * @return The Plog instance (for chaining).
+ */
+ public Plog logCurve(String name, float[] xs, float[] ys) {
+ write(formatCurve(name, xs, ys));
+ return this;
+ }
+
+ private String formatTitle(String title) {
+ return "title: " + title;
+ }
+
+ private String formatPoint(String name, float x, float y) {
+ return "point: " + name + ": (" + x + "," + y + ")";
+ }
+
+ private String formatCurve(String name, float[] xs, float[] ys) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("curve: " + name + ": [");
+ int n = xs.length <= ys.length ? xs.length : ys.length;
+ for (int i = 0; i < n; i++) {
+ sb.append("(" + xs[i] + "," + ys[i] + "),");
+ }
+ sb.append("]");
+ return sb.toString();
+ }
+
+ private void write(String message) {
+ emit("[PLOG " + mId + "] " + message);
+ }
+
+ /**
+ * Emits a message (depending on the concrete Plog implementation).
+ *
+ * @param message The message.
+ */
+ protected abstract void emit(String message);
+
+ /**
+ * A Plog that emits messages to the system log.
+ */
+ public static class SystemPlog extends Plog {
+ // The tag of the emitted messages in the system log.
+ private final String mTag;
+
+ /**
+ * Returns a Plog instance that emits messages to the system log.
+ *
+ * @param tag The tag of the emitted messages in the system log.
+ * @return A Plog instance that emits messages to the system log.
+ */
+ public SystemPlog(String tag) {
+ mTag = tag;
+ }
+
+ /**
+ * Emits a message to the system log.
+ *
+ * @param message The message.
+ */
+ protected void emit(String message) {
+ Slog.d(mTag, message);
+ }
+ }
+}