Merge "Add HDR-HBM support into framework." into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
35ab69b632
@@ -33,7 +33,8 @@ public final class BrightnessInfo implements Parcelable {
|
||||
|
||||
@IntDef(prefix = {"HIGH_BRIGHTNESS_MODE_"}, value = {
|
||||
HIGH_BRIGHTNESS_MODE_OFF,
|
||||
HIGH_BRIGHTNESS_MODE_SUNLIGHT
|
||||
HIGH_BRIGHTNESS_MODE_SUNLIGHT,
|
||||
HIGH_BRIGHTNESS_MODE_HDR
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface HighBrightnessMode {}
|
||||
@@ -50,6 +51,12 @@ public final class BrightnessInfo implements Parcelable {
|
||||
*/
|
||||
public static final int HIGH_BRIGHTNESS_MODE_SUNLIGHT = 1;
|
||||
|
||||
/**
|
||||
* High brightness mode is ON due to high ambient light (sunlight). The high brightness range is
|
||||
* currently accessible to the user.
|
||||
*/
|
||||
public static final int HIGH_BRIGHTNESS_MODE_HDR = 2;
|
||||
|
||||
/** Brightness */
|
||||
public final float brightness;
|
||||
|
||||
@@ -73,6 +80,21 @@ public final class BrightnessInfo implements Parcelable {
|
||||
this.highBrightnessMode = highBrightnessMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return User-friendly string for specified {@link HighBrightnessMode} parameter.
|
||||
*/
|
||||
public static String hbmToString(@HighBrightnessMode int highBrightnessMode) {
|
||||
switch (highBrightnessMode) {
|
||||
case HIGH_BRIGHTNESS_MODE_OFF:
|
||||
return "off";
|
||||
case HIGH_BRIGHTNESS_MODE_HDR:
|
||||
return "hdr";
|
||||
case HIGH_BRIGHTNESS_MODE_SUNLIGHT:
|
||||
return "sunlight";
|
||||
}
|
||||
return "invalid";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
|
||||
@@ -738,13 +738,19 @@ class AutomaticBrightnessController {
|
||||
float value = mBrightnessMapper.getBrightness(mAmbientLux, mForegroundAppPackageName,
|
||||
mForegroundAppCategory);
|
||||
float newScreenAutoBrightness = clampScreenBrightness(value);
|
||||
|
||||
// The min/max range can change for brightness due to HBM. See if the current brightness
|
||||
// value still falls within the current range (which could have changed).
|
||||
final boolean currentBrightnessWithinAllowedRange = BrightnessSynchronizer.floatEquals(
|
||||
mScreenAutoBrightness, clampScreenBrightness(mScreenAutoBrightness));
|
||||
// If screenAutoBrightness 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 (!Float.isNaN(mScreenAutoBrightness)
|
||||
&& !isManuallySet
|
||||
&& newScreenAutoBrightness > mScreenDarkeningThreshold
|
||||
&& newScreenAutoBrightness < mScreenBrighteningThreshold) {
|
||||
&& newScreenAutoBrightness < mScreenBrighteningThreshold
|
||||
&& currentBrightnessWithinAllowedRange) {
|
||||
if (mLoggingEnabled) {
|
||||
Slog.d(TAG, "ignoring newScreenAutoBrightness: "
|
||||
+ mScreenDarkeningThreshold + " < " + newScreenAutoBrightness
|
||||
|
||||
@@ -20,5 +20,8 @@ package com.android.server.display;
|
||||
* Interface used to update the actual display state.
|
||||
*/
|
||||
public interface DisplayBlanker {
|
||||
void requestDisplayState(int displayId, int state, float brightness);
|
||||
/**
|
||||
* Requests the specified display state and brightness levels for the specified displayId.
|
||||
*/
|
||||
void requestDisplayState(int displayId, int state, float brightness, float sdrBrightness);
|
||||
}
|
||||
|
||||
@@ -156,10 +156,12 @@ abstract class DisplayDevice {
|
||||
*
|
||||
* @param state The new display state.
|
||||
* @param brightnessState The new display brightnessState.
|
||||
* @param sdrBrightnessState The new display brightnessState for SDR layers.
|
||||
* @return A runnable containing work to be deferred until after we have
|
||||
* exited the critical section, or null if none.
|
||||
*/
|
||||
public Runnable requestDisplayStateLocked(int state, float brightnessState) {
|
||||
public Runnable requestDisplayStateLocked(int state, float brightnessState,
|
||||
float sdrBrightnessState) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -104,6 +104,7 @@ public class DisplayDeviceConfig {
|
||||
private float mBrightnessRampSlowIncrease = Float.NaN;
|
||||
private Spline mBrightnessToBacklightSpline;
|
||||
private Spline mBacklightToBrightnessSpline;
|
||||
private Spline mBacklightToNitsSpline;
|
||||
private List<String> mQuirks;
|
||||
private boolean mIsHighBrightnessModeEnabled = false;
|
||||
private HighBrightnessModeData mHbmData;
|
||||
@@ -218,6 +219,20 @@ public class DisplayDeviceConfig {
|
||||
return mBrightnessToBacklightSpline.interpolate(brightness);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the nits value for the specified backlight value if a mapping exists.
|
||||
*
|
||||
* @return The mapped nits or 0 if no mapping exits.
|
||||
*/
|
||||
public float getNitsFromBacklight(float backlight) {
|
||||
if (mBacklightToNitsSpline == null) {
|
||||
Slog.wtf(TAG, "requesting nits when no mapping exists.");
|
||||
return -1;
|
||||
}
|
||||
backlight = Math.max(backlight, mBacklightMinimum);
|
||||
return mBacklightToNitsSpline.interpolate(backlight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array of equal length to backlight and nits, that covers the entire system
|
||||
* brightness range of 0.0-1.0.
|
||||
@@ -257,6 +272,13 @@ public class DisplayDeviceConfig {
|
||||
return mAmbientLightSensor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if a nits to backlight mapping is defined in this config, false otherwise.
|
||||
*/
|
||||
public boolean hasNitsMapping() {
|
||||
return mBacklightToNitsSpline != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param quirkValue The quirk to test.
|
||||
* @return {@code true} if the specified quirk is present in this configuration,
|
||||
@@ -584,6 +606,7 @@ public class DisplayDeviceConfig {
|
||||
}
|
||||
mBrightnessToBacklightSpline = Spline.createSpline(mBrightness, mBacklight);
|
||||
mBacklightToBrightnessSpline = Spline.createSpline(mBacklight, mBrightness);
|
||||
mBacklightToNitsSpline = Spline.createSpline(mBacklight, mNits);
|
||||
}
|
||||
|
||||
private void loadQuirks(DisplayConfiguration config) {
|
||||
|
||||
@@ -257,7 +257,8 @@ public final class DisplayManagerService extends SystemService {
|
||||
private final DisplayBlanker mDisplayBlanker = new DisplayBlanker() {
|
||||
// Synchronized to avoid race conditions when updating multiple display states.
|
||||
@Override
|
||||
public synchronized void requestDisplayState(int displayId, int state, float brightness) {
|
||||
public synchronized void requestDisplayState(int displayId, int state, float brightness,
|
||||
float sdrBrightness) {
|
||||
boolean allInactive = true;
|
||||
boolean allOff = true;
|
||||
final boolean stateChanged;
|
||||
@@ -288,7 +289,7 @@ public final class DisplayManagerService extends SystemService {
|
||||
|
||||
// The order of operations is important for legacy reasons.
|
||||
if (state == Display.STATE_OFF) {
|
||||
requestDisplayStateInternal(displayId, state, brightness);
|
||||
requestDisplayStateInternal(displayId, state, brightness, sdrBrightness);
|
||||
}
|
||||
|
||||
if (stateChanged) {
|
||||
@@ -296,7 +297,7 @@ public final class DisplayManagerService extends SystemService {
|
||||
}
|
||||
|
||||
if (state != Display.STATE_OFF) {
|
||||
requestDisplayStateInternal(displayId, state, brightness);
|
||||
requestDisplayStateInternal(displayId, state, brightness, sdrBrightness);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -316,7 +317,7 @@ public final class DisplayManagerService extends SystemService {
|
||||
|
||||
// A map from LogicalDisplay ID to display brightness.
|
||||
@GuardedBy("mSyncRoot")
|
||||
private final SparseArray<Float> mDisplayBrightnesses = new SparseArray<>();
|
||||
private final SparseArray<BrightnessPair> mDisplayBrightnesses = new SparseArray<>();
|
||||
|
||||
// Set to true when there are pending display changes that have yet to be applied
|
||||
// to the surface flinger state.
|
||||
@@ -667,11 +668,8 @@ public final class DisplayManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
private void requestDisplayStateInternal(int displayId, int state, float brightnessState) {
|
||||
if (state == Display.STATE_UNKNOWN) {
|
||||
state = Display.STATE_ON;
|
||||
}
|
||||
if (state == Display.STATE_OFF) {
|
||||
private float clampBrightness(int displayState, float brightnessState) {
|
||||
if (displayState == Display.STATE_OFF) {
|
||||
brightnessState = PowerManager.BRIGHTNESS_OFF_FLOAT;
|
||||
} else if (brightnessState != PowerManager.BRIGHTNESS_OFF_FLOAT
|
||||
&& brightnessState < PowerManager.BRIGHTNESS_MIN) {
|
||||
@@ -679,6 +677,17 @@ public final class DisplayManagerService extends SystemService {
|
||||
} else if (brightnessState > PowerManager.BRIGHTNESS_MAX) {
|
||||
brightnessState = PowerManager.BRIGHTNESS_MAX;
|
||||
}
|
||||
return brightnessState;
|
||||
}
|
||||
|
||||
private void requestDisplayStateInternal(int displayId, int state, float brightnessState,
|
||||
float sdrBrightnessState) {
|
||||
if (state == Display.STATE_UNKNOWN) {
|
||||
state = Display.STATE_ON;
|
||||
}
|
||||
|
||||
brightnessState = clampBrightness(state, brightnessState);
|
||||
sdrBrightnessState = clampBrightness(state, sdrBrightnessState);
|
||||
|
||||
// Update the display state within the lock.
|
||||
// Note that we do not need to schedule traversals here although it
|
||||
@@ -688,20 +697,26 @@ public final class DisplayManagerService extends SystemService {
|
||||
synchronized (mSyncRoot) {
|
||||
final int index = mDisplayStates.indexOfKey(displayId);
|
||||
|
||||
final BrightnessPair brightnessPair =
|
||||
index < 0 ? null : mDisplayBrightnesses.valueAt(index);
|
||||
if (index < 0 || (mDisplayStates.valueAt(index) == state
|
||||
&& BrightnessSynchronizer.floatEquals(mDisplayBrightnesses.valueAt(index),
|
||||
brightnessState))) {
|
||||
&& BrightnessSynchronizer.floatEquals(
|
||||
brightnessPair.brightness, brightnessState)
|
||||
&& BrightnessSynchronizer.floatEquals(
|
||||
brightnessPair.sdrBrightness, sdrBrightnessState))) {
|
||||
return; // Display no longer exists or no change.
|
||||
}
|
||||
|
||||
traceMessage = "requestDisplayStateInternal("
|
||||
+ displayId + ", "
|
||||
+ Display.stateToString(state)
|
||||
+ ", brightness=" + brightnessState + ")";
|
||||
+ ", brightness=" + brightnessState
|
||||
+ ", sdrBrightness=" + sdrBrightnessState + ")";
|
||||
Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, traceMessage, displayId);
|
||||
|
||||
mDisplayStates.setValueAt(index, state);
|
||||
mDisplayBrightnesses.setValueAt(index, brightnessState);
|
||||
brightnessPair.brightness = brightnessState;
|
||||
brightnessPair.sdrBrightness = sdrBrightnessState;
|
||||
runnable = updateDisplayStateLocked(mLogicalDisplayMapper.getDisplayLocked(displayId)
|
||||
.getPrimaryDisplayDeviceLocked());
|
||||
}
|
||||
@@ -1235,7 +1250,9 @@ public final class DisplayManagerService extends SystemService {
|
||||
addDisplayPowerControllerLocked(display);
|
||||
mDisplayStates.append(displayId, Display.STATE_UNKNOWN);
|
||||
|
||||
mDisplayBrightnesses.append(displayId, display.getDisplayInfoLocked().brightnessDefault);
|
||||
final float brightnessDefault = display.getDisplayInfoLocked().brightnessDefault;
|
||||
mDisplayBrightnesses.append(displayId,
|
||||
new BrightnessPair(brightnessDefault, brightnessDefault));
|
||||
|
||||
DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();
|
||||
|
||||
@@ -1265,11 +1282,6 @@ public final class DisplayManagerService extends SystemService {
|
||||
// this point.
|
||||
sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
|
||||
scheduleTraversalLocked(false);
|
||||
|
||||
DisplayPowerController dpc = mDisplayPowerControllers.get(displayId);
|
||||
if (dpc != null) {
|
||||
dpc.onDisplayChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleLogicalDisplayFrameRateOverridesChangedLocked(
|
||||
@@ -1301,6 +1313,11 @@ public final class DisplayManagerService extends SystemService {
|
||||
if (work != null) {
|
||||
mHandler.post(work);
|
||||
}
|
||||
final int displayId = display.getDisplayIdLocked();
|
||||
DisplayPowerController dpc = mDisplayPowerControllers.get(displayId);
|
||||
if (dpc != null) {
|
||||
dpc.onDisplayChanged();
|
||||
}
|
||||
handleLogicalDisplayChangedLocked(display);
|
||||
}
|
||||
|
||||
@@ -1326,8 +1343,9 @@ public final class DisplayManagerService extends SystemService {
|
||||
|
||||
// Only send a request for display state if display state has already been initialized.
|
||||
if (state != Display.STATE_UNKNOWN) {
|
||||
final float brightness = mDisplayBrightnesses.get(displayId);
|
||||
return device.requestDisplayStateLocked(state, brightness);
|
||||
final BrightnessPair brightnessPair = mDisplayBrightnesses.get(displayId);
|
||||
return device.requestDisplayStateLocked(state, brightnessPair.brightness,
|
||||
brightnessPair.sdrBrightness);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -1935,10 +1953,11 @@ public final class DisplayManagerService extends SystemService {
|
||||
for (int i = 0; i < displayStateCount; i++) {
|
||||
final int displayId = mDisplayStates.keyAt(i);
|
||||
final int displayState = mDisplayStates.valueAt(i);
|
||||
final float brightness = mDisplayBrightnesses.valueAt(i);
|
||||
final BrightnessPair brightnessPair = mDisplayBrightnesses.valueAt(i);
|
||||
pw.println(" Display Id=" + displayId);
|
||||
pw.println(" Display State=" + Display.stateToString(displayState));
|
||||
pw.println(" Display Brightness=" + brightness);
|
||||
pw.println(" Display Brightness=" + brightnessPair.brightness);
|
||||
pw.println(" Display SdrBrightness=" + brightnessPair.sdrBrightness);
|
||||
}
|
||||
|
||||
IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
|
||||
@@ -3277,6 +3296,16 @@ public final class DisplayManagerService extends SystemService {
|
||||
}
|
||||
};
|
||||
|
||||
private class BrightnessPair {
|
||||
public float brightness;
|
||||
public float sdrBrightness;
|
||||
|
||||
BrightnessPair(float brightness, float sdrBrightness) {
|
||||
this.brightness = brightness;
|
||||
this.sdrBrightness = sdrBrightness;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Functional interface for providing time.
|
||||
* TODO(b/184781936): merge with PowerManagerService.Clock
|
||||
@@ -3288,5 +3317,4 @@ public final class DisplayManagerService extends SystemService {
|
||||
*/
|
||||
long uptimeMillis();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
|
||||
import android.metrics.LogMaker;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.PowerManager;
|
||||
@@ -61,6 +62,7 @@ import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.am.BatteryStatsService;
|
||||
import com.android.server.display.RampAnimator.DualRampAnimator;
|
||||
import com.android.server.display.color.ColorDisplayService.ColorDisplayServiceInternal;
|
||||
import com.android.server.display.color.ColorDisplayService.ReduceBrightColorsListener;
|
||||
import com.android.server.display.whitebalance.DisplayWhiteBalanceController;
|
||||
@@ -223,6 +225,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
@GuardedBy("mCachedBrightnessInfo")
|
||||
private final CachedBrightnessInfo mCachedBrightnessInfo = new CachedBrightnessInfo();
|
||||
|
||||
private DisplayDevice mDisplayDevice;
|
||||
|
||||
// True if we should fade the screen while turning it off, false if we should play
|
||||
// a stylish color fade animation instead.
|
||||
private boolean mColorFadeFadesConfig;
|
||||
@@ -424,7 +428,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
// Animators.
|
||||
private ObjectAnimator mColorFadeOnAnimator;
|
||||
private ObjectAnimator mColorFadeOffAnimator;
|
||||
private RampAnimator<DisplayPowerState> mScreenBrightnessRampAnimator;
|
||||
private DualRampAnimator<DisplayPowerState> mScreenBrightnessRampAnimator;
|
||||
private BrightnessSetting.BrightnessSettingListener mBrightnessSettingListener;
|
||||
|
||||
// True if this DisplayPowerController has been stopped and should no longer be running.
|
||||
@@ -442,6 +446,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
Runnable onBrightnessChangeRunnable) {
|
||||
mLogicalDisplay = logicalDisplay;
|
||||
mDisplayId = mLogicalDisplay.getDisplayIdLocked();
|
||||
mDisplayDevice = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
|
||||
mHandler = new DisplayControllerHandler(handler.getLooper());
|
||||
|
||||
if (mDisplayId == Display.DEFAULT_DISPLAY) {
|
||||
@@ -780,12 +785,29 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
* when displays get swapped on foldable devices. For example, different brightness properties
|
||||
* of each display need to be properly reflected in AutomaticBrightnessController.
|
||||
*/
|
||||
@GuardedBy("DisplayManagerService.mSyncRoot")
|
||||
public void onDisplayChanged() {
|
||||
// TODO: b/175821789 - Support high brightness on multiple (folding) displays
|
||||
mUniqueDisplayId = mLogicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId();
|
||||
mDisplayDeviceConfig = mLogicalDisplay.getPrimaryDisplayDeviceLocked()
|
||||
.getDisplayDeviceConfig();
|
||||
loadAmbientLightSensor();
|
||||
final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
|
||||
if (device == null) {
|
||||
Slog.wtf(TAG, "Display Device is null in DisplayPowerController for display: "
|
||||
+ mLogicalDisplay.getDisplayIdLocked());
|
||||
return;
|
||||
}
|
||||
|
||||
final String uniqueId = device.getUniqueId();
|
||||
final DisplayDeviceConfig config = device.getDisplayDeviceConfig();
|
||||
final IBinder token = device.getDisplayTokenLocked();
|
||||
mHandler.post(() -> {
|
||||
if (mDisplayDevice == device) {
|
||||
return;
|
||||
}
|
||||
mDisplayDevice = device;
|
||||
mUniqueDisplayId = uniqueId;
|
||||
mDisplayDeviceConfig = config;
|
||||
|
||||
loadAmbientLightSensor();
|
||||
mHbmController.resetHbmData(token, config.getHighBrightnessModeData());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -855,8 +877,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
mColorFadeOffAnimator.addListener(mAnimatorListener);
|
||||
}
|
||||
|
||||
mScreenBrightnessRampAnimator = new RampAnimator<>(
|
||||
mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS_FLOAT);
|
||||
mScreenBrightnessRampAnimator = new DualRampAnimator<>(mPowerState,
|
||||
DisplayPowerState.SCREEN_BRIGHTNESS_FLOAT,
|
||||
DisplayPowerState.SCREEN_SDR_BRIGHTNESS_FLOAT);
|
||||
mScreenBrightnessRampAnimator.setListener(mRampAnimatorListener);
|
||||
|
||||
noteScreenState(mPowerState.getScreenState());
|
||||
@@ -902,6 +925,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
/** Clean up all resources that are accessed via the {@link #mHandler} thread. */
|
||||
private void cleanupHandlerThreadAfterStop() {
|
||||
setProximitySensorEnabled(false);
|
||||
mHbmController.stop();
|
||||
mHandler.removeCallbacksAndMessages(null);
|
||||
if (mUnfinishedBusiness) {
|
||||
mCallbacks.releaseSuspendBlocker();
|
||||
@@ -1205,9 +1229,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
// timeout is about to expire.
|
||||
if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
|
||||
if (brightnessState > PowerManager.BRIGHTNESS_MIN) {
|
||||
brightnessState = Math.max(Math.min(brightnessState
|
||||
- SCREEN_DIM_MINIMUM_REDUCTION_FLOAT,
|
||||
mScreenBrightnessDimConfig), PowerManager.BRIGHTNESS_MIN);
|
||||
brightnessState = Math.max(
|
||||
Math.min(brightnessState - SCREEN_DIM_MINIMUM_REDUCTION_FLOAT,
|
||||
mScreenBrightnessDimConfig),
|
||||
PowerManager.BRIGHTNESS_MIN);
|
||||
mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_DIMMED);
|
||||
}
|
||||
if (!mAppliedDimming) {
|
||||
@@ -1282,12 +1307,27 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
// transformations to the brightness have pushed it outside of the currently
|
||||
// allowed range.
|
||||
float animateValue = clampScreenBrightness(brightnessState);
|
||||
|
||||
// If there are any HDR layers on the screen, we have a special brightness value that we
|
||||
// use instead. We still preserve the calculated brightness for Standard Dynamic Range
|
||||
// (SDR) layers, but the main brightness value will be the one for HDR.
|
||||
float sdrAnimateValue = animateValue;
|
||||
if (mHbmController.getHighBrightnessMode() == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR
|
||||
&& ((mBrightnessReason.modifier & BrightnessReason.MODIFIER_DIMMED) == 0
|
||||
|| (mBrightnessReason.modifier & BrightnessReason.MODIFIER_LOW_POWER) == 0)) {
|
||||
animateValue = mHbmController.getHdrBrightnessValue();
|
||||
}
|
||||
|
||||
final float currentBrightness = mPowerState.getScreenBrightness();
|
||||
final float currentSdrBrightness = mPowerState.getSdrScreenBrightness();
|
||||
if (isValidBrightnessValue(animateValue)
|
||||
&& !BrightnessSynchronizer.floatEquals(animateValue, currentBrightness)) {
|
||||
&& (!BrightnessSynchronizer.floatEquals(animateValue, currentBrightness)
|
||||
|| !BrightnessSynchronizer.floatEquals(
|
||||
sdrAnimateValue, currentSdrBrightness))) {
|
||||
if (initialRampSkip || hasBrightnessBuckets
|
||||
|| wasOrWillBeInVr || !isDisplayContentVisible || brightnessIsTemporary) {
|
||||
animateScreenBrightness(animateValue, SCREEN_ANIMATION_RATE_MINIMUM);
|
||||
animateScreenBrightness(animateValue, sdrAnimateValue,
|
||||
SCREEN_ANIMATION_RATE_MINIMUM);
|
||||
} else {
|
||||
boolean isIncreasing = animateValue > currentBrightness;
|
||||
final float rampSpeed;
|
||||
@@ -1300,7 +1340,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
} else {
|
||||
rampSpeed = mBrightnessRampRateFastDecrease;
|
||||
}
|
||||
animateScreenBrightness(animateValue, rampSpeed);
|
||||
animateScreenBrightness(animateValue, sdrAnimateValue, rampSpeed);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1446,9 +1486,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
private HighBrightnessModeController createHbmController() {
|
||||
final DisplayDeviceConfig ddConfig =
|
||||
mLogicalDisplay.getPrimaryDisplayDeviceLocked().getDisplayDeviceConfig();
|
||||
final IBinder displayToken =
|
||||
mLogicalDisplay.getPrimaryDisplayDeviceLocked().getDisplayTokenLocked();
|
||||
final DisplayDeviceConfig.HighBrightnessModeData hbmData =
|
||||
ddConfig != null ? ddConfig.getHighBrightnessModeData() : null;
|
||||
return new HighBrightnessModeController(mHandler, PowerManager.BRIGHTNESS_MIN,
|
||||
return new HighBrightnessModeController(mHandler, displayToken, PowerManager.BRIGHTNESS_MIN,
|
||||
PowerManager.BRIGHTNESS_MAX, hbmData,
|
||||
() -> {
|
||||
sendUpdatePowerStateLocked();
|
||||
@@ -1596,11 +1638,12 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
&& brightnessState <= PowerManager.BRIGHTNESS_MAX;
|
||||
}
|
||||
|
||||
private void animateScreenBrightness(float target, float rate) {
|
||||
private void animateScreenBrightness(float target, float sdrTarget, float rate) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Animating brightness: target=" + target +", rate=" + rate);
|
||||
Slog.d(TAG, "Animating brightness: target=" + target + ", sdrTarget=" + sdrTarget
|
||||
+ ", rate=" + rate);
|
||||
}
|
||||
if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {
|
||||
if (mScreenBrightnessRampAnimator.animateTo(target, sdrTarget, rate)) {
|
||||
Trace.traceCounter(Trace.TRACE_TAG_POWER, "TargetScreenBrightness", (int) target);
|
||||
// TODO(b/153319140) remove when we can get this from the above trace invocation
|
||||
SystemProperties.set("debug.tracing.screen_brightness", String.valueOf(target));
|
||||
@@ -2295,6 +2338,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
return;
|
||||
}
|
||||
handleSettingsChange(false /*userSwitch*/);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2392,7 +2436,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
|
||||
static final int MODIFIER_DIMMED = 0x1;
|
||||
static final int MODIFIER_LOW_POWER = 0x2;
|
||||
static final int MODIFIER_MASK = 0x3;
|
||||
static final int MODIFIER_HDR = 0x4;
|
||||
static final int MODIFIER_MASK = MODIFIER_DIMMED | MODIFIER_LOW_POWER | MODIFIER_HDR;
|
||||
|
||||
// ADJUSTMENT_*
|
||||
// These things can happen at any point, even if the main brightness reason doesn't
|
||||
@@ -2464,6 +2509,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
if ((modifier & MODIFIER_DIMMED) != 0) {
|
||||
sb.append(" dim");
|
||||
}
|
||||
if ((modifier & MODIFIER_HDR) != 0) {
|
||||
sb.append(" hdr");
|
||||
}
|
||||
int strlen = sb.length();
|
||||
if (sb.charAt(strlen - 1) == '[') {
|
||||
sb.setLength(strlen - 2);
|
||||
|
||||
@@ -62,6 +62,7 @@ final class DisplayPowerState {
|
||||
|
||||
private int mScreenState;
|
||||
private float mScreenBrightness;
|
||||
private float mSdrScreenBrightness;
|
||||
private boolean mScreenReady;
|
||||
private boolean mScreenUpdatePending;
|
||||
|
||||
@@ -92,6 +93,7 @@ final class DisplayPowerState {
|
||||
mScreenState = displayState;
|
||||
mScreenBrightness = (displayState != Display.STATE_OFF) ? PowerManager.BRIGHTNESS_MAX
|
||||
: PowerManager.BRIGHTNESS_OFF_FLOAT;
|
||||
mSdrScreenBrightness = mScreenBrightness;
|
||||
scheduleScreenUpdate();
|
||||
|
||||
mColorFadePrepared = false;
|
||||
@@ -126,6 +128,19 @@ final class DisplayPowerState {
|
||||
}
|
||||
};
|
||||
|
||||
public static final FloatProperty<DisplayPowerState> SCREEN_SDR_BRIGHTNESS_FLOAT =
|
||||
new FloatProperty<DisplayPowerState>("sdrScreenBrightnessFloat") {
|
||||
@Override
|
||||
public void setValue(DisplayPowerState object, float value) {
|
||||
object.setSdrScreenBrightness(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float get(DisplayPowerState object) {
|
||||
return object.getSdrScreenBrightness();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets whether the screen is on, off, or dozing.
|
||||
*/
|
||||
@@ -148,13 +163,39 @@ final class DisplayPowerState {
|
||||
return mScreenState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the display's SDR brightness.
|
||||
*
|
||||
* @param brightness The brightness, ranges from 0.0f (minimum / off) to 1.0f (brightest).
|
||||
*/
|
||||
public void setSdrScreenBrightness(float brightness) {
|
||||
if (!BrightnessSynchronizer.floatEquals(mSdrScreenBrightness, brightness)) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "setSdrScreenBrightness: brightness=" + brightness);
|
||||
}
|
||||
|
||||
mSdrScreenBrightness = brightness;
|
||||
if (mScreenState != Display.STATE_OFF) {
|
||||
mScreenReady = false;
|
||||
scheduleScreenUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the screen SDR brightness.
|
||||
*/
|
||||
public float getSdrScreenBrightness() {
|
||||
return mSdrScreenBrightness;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the display brightness.
|
||||
*
|
||||
* @param brightness The brightness, ranges from 0.0f (minimum / off) to 1.0f (brightest).
|
||||
*/
|
||||
public void setScreenBrightness(float brightness) {
|
||||
if (mScreenBrightness != brightness) {
|
||||
if (!BrightnessSynchronizer.floatEquals(mScreenBrightness, brightness)) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "setScreenBrightness: brightness=" + brightness);
|
||||
}
|
||||
@@ -286,6 +327,7 @@ final class DisplayPowerState {
|
||||
pw.println(" mStopped=" + mStopped);
|
||||
pw.println(" mScreenState=" + Display.stateToString(mScreenState));
|
||||
pw.println(" mScreenBrightness=" + mScreenBrightness);
|
||||
pw.println(" mSdrScreenBrightness=" + mSdrScreenBrightness);
|
||||
pw.println(" mScreenReady=" + mScreenReady);
|
||||
pw.println(" mScreenUpdatePending=" + mScreenUpdatePending);
|
||||
pw.println(" mColorFadePrepared=" + mColorFadePrepared);
|
||||
@@ -332,7 +374,10 @@ final class DisplayPowerState {
|
||||
|
||||
float brightnessState = mScreenState != Display.STATE_OFF
|
||||
&& mColorFadeLevel > 0f ? mScreenBrightness : PowerManager.BRIGHTNESS_OFF_FLOAT;
|
||||
if (mPhotonicModulator.setState(mScreenState, brightnessState)) {
|
||||
float sdrBrightnessState = mScreenState != Display.STATE_OFF
|
||||
&& mColorFadeLevel > 0f
|
||||
? mSdrScreenBrightness : PowerManager.BRIGHTNESS_OFF_FLOAT;
|
||||
if (mPhotonicModulator.setState(mScreenState, brightnessState, sdrBrightnessState)) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Screen ready");
|
||||
}
|
||||
@@ -373,8 +418,10 @@ final class DisplayPowerState {
|
||||
|
||||
private int mPendingState = INITIAL_SCREEN_STATE;
|
||||
private float mPendingBacklight = INITIAL_BACKLIGHT_FLOAT;
|
||||
private float mPendingSdrBacklight = INITIAL_BACKLIGHT_FLOAT;
|
||||
private int mActualState = INITIAL_SCREEN_STATE;
|
||||
private float mActualBacklight = INITIAL_BACKLIGHT_FLOAT;
|
||||
private float mActualSdrBacklight = INITIAL_BACKLIGHT_FLOAT;
|
||||
private boolean mStateChangeInProgress;
|
||||
private boolean mBacklightChangeInProgress;
|
||||
|
||||
@@ -382,11 +429,13 @@ final class DisplayPowerState {
|
||||
super("PhotonicModulator");
|
||||
}
|
||||
|
||||
public boolean setState(int state, float brightnessState) {
|
||||
public boolean setState(int state, float brightnessState, float sdrBrightnessState) {
|
||||
synchronized (mLock) {
|
||||
boolean stateChanged = state != mPendingState;
|
||||
boolean backlightChanged = !BrightnessSynchronizer.floatEquals(
|
||||
brightnessState, mPendingBacklight);
|
||||
boolean backlightChanged =
|
||||
!BrightnessSynchronizer.floatEquals(brightnessState, mPendingBacklight)
|
||||
|| !BrightnessSynchronizer.floatEquals(
|
||||
sdrBrightnessState, mPendingSdrBacklight);
|
||||
if (stateChanged || backlightChanged) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Requesting new screen state: state="
|
||||
@@ -395,6 +444,7 @@ final class DisplayPowerState {
|
||||
|
||||
mPendingState = state;
|
||||
mPendingBacklight = brightnessState;
|
||||
mPendingSdrBacklight = sdrBrightnessState;
|
||||
boolean changeInProgress = mStateChangeInProgress || mBacklightChangeInProgress;
|
||||
mStateChangeInProgress = stateChanged || mStateChangeInProgress;
|
||||
mBacklightChangeInProgress = backlightChanged || mBacklightChangeInProgress;
|
||||
@@ -413,8 +463,10 @@ final class DisplayPowerState {
|
||||
pw.println("Photonic Modulator State:");
|
||||
pw.println(" mPendingState=" + Display.stateToString(mPendingState));
|
||||
pw.println(" mPendingBacklight=" + mPendingBacklight);
|
||||
pw.println(" mPendingSdrBacklight=" + mPendingSdrBacklight);
|
||||
pw.println(" mActualState=" + Display.stateToString(mActualState));
|
||||
pw.println(" mActualBacklight=" + mActualBacklight);
|
||||
pw.println(" mActualSdrBacklight=" + mActualSdrBacklight);
|
||||
pw.println(" mStateChangeInProgress=" + mStateChangeInProgress);
|
||||
pw.println(" mBacklightChangeInProgress=" + mBacklightChangeInProgress);
|
||||
}
|
||||
@@ -427,13 +479,17 @@ final class DisplayPowerState {
|
||||
final int state;
|
||||
final boolean stateChanged;
|
||||
final float brightnessState;
|
||||
final float sdrBrightnessState;
|
||||
final boolean backlightChanged;
|
||||
synchronized (mLock) {
|
||||
state = mPendingState;
|
||||
stateChanged = (state != mActualState);
|
||||
brightnessState = mPendingBacklight;
|
||||
backlightChanged = !BrightnessSynchronizer.floatEquals(
|
||||
brightnessState, mActualBacklight);
|
||||
sdrBrightnessState = mPendingSdrBacklight;
|
||||
backlightChanged =
|
||||
!BrightnessSynchronizer.floatEquals(brightnessState, mActualBacklight)
|
||||
|| !BrightnessSynchronizer.floatEquals(
|
||||
sdrBrightnessState, mActualSdrBacklight);
|
||||
if (!stateChanged) {
|
||||
// State changed applied, notify outer class.
|
||||
postScreenUpdateThreadSafe();
|
||||
@@ -454,14 +510,17 @@ final class DisplayPowerState {
|
||||
}
|
||||
mActualState = state;
|
||||
mActualBacklight = brightnessState;
|
||||
mActualSdrBacklight = sdrBrightnessState;
|
||||
}
|
||||
|
||||
// Apply pending change.
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Updating screen state: id=" + mDisplayId + ", state="
|
||||
+ Display.stateToString(state) + ", backlight=" + brightnessState);
|
||||
+ Display.stateToString(state) + ", backlight=" + brightnessState
|
||||
+ ", sdrBacklight=" + sdrBrightnessState);
|
||||
}
|
||||
mBlanker.requestDisplayState(mDisplayId, state, brightnessState);
|
||||
mBlanker.requestDisplayState(mDisplayId, state, brightnessState,
|
||||
sdrBrightnessState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,9 +18,11 @@ package com.android.server.display;
|
||||
|
||||
import android.hardware.display.BrightnessInfo;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.PowerManager;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Slog;
|
||||
import android.view.SurfaceControlHdrLayerInfoListener;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.display.DisplayDeviceConfig.HighBrightnessModeData;
|
||||
@@ -45,17 +47,21 @@ class HighBrightnessModeController {
|
||||
|
||||
private final float mBrightnessMin;
|
||||
private final float mBrightnessMax;
|
||||
private final HighBrightnessModeData mHbmData;
|
||||
private final Handler mHandler;
|
||||
private final Runnable mHbmChangeCallback;
|
||||
private final Runnable mRecalcRunnable;
|
||||
private final Clock mClock;
|
||||
|
||||
private SurfaceControlHdrLayerInfoListener mHdrListener;
|
||||
private HighBrightnessModeData mHbmData;
|
||||
private IBinder mRegisteredDisplayToken;
|
||||
|
||||
private boolean mIsInAllowedAmbientRange = false;
|
||||
private boolean mIsTimeAvailable = false;
|
||||
private boolean mIsAutoBrightnessEnabled = false;
|
||||
private float mAutoBrightness;
|
||||
private int mHbmMode = BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF;
|
||||
private boolean mIsHdrLayerPresent = false;
|
||||
|
||||
/**
|
||||
* If HBM is currently running, this is the start time for the current HBM session.
|
||||
@@ -69,23 +75,26 @@ class HighBrightnessModeController {
|
||||
*/
|
||||
private LinkedList<HbmEvent> mEvents = new LinkedList<>();
|
||||
|
||||
HighBrightnessModeController(Handler handler, float brightnessMin, float brightnessMax,
|
||||
HighBrightnessModeData hbmData, Runnable hbmChangeCallback) {
|
||||
this(SystemClock::uptimeMillis, handler, brightnessMin, brightnessMax, hbmData,
|
||||
hbmChangeCallback);
|
||||
HighBrightnessModeController(Handler handler, IBinder displayToken, float brightnessMin,
|
||||
float brightnessMax, HighBrightnessModeData hbmData, Runnable hbmChangeCallback) {
|
||||
this(SystemClock::uptimeMillis, handler, displayToken, brightnessMin, brightnessMax,
|
||||
hbmData, hbmChangeCallback);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
HighBrightnessModeController(Clock clock, Handler handler, float brightnessMin,
|
||||
float brightnessMax, HighBrightnessModeData hbmData, Runnable hbmChangeCallback) {
|
||||
HighBrightnessModeController(Clock clock, Handler handler, IBinder displayToken,
|
||||
float brightnessMin, float brightnessMax, HighBrightnessModeData hbmData,
|
||||
Runnable hbmChangeCallback) {
|
||||
mClock = clock;
|
||||
mHandler = handler;
|
||||
mBrightnessMin = brightnessMin;
|
||||
mBrightnessMax = brightnessMax;
|
||||
mHbmData = hbmData;
|
||||
mHbmChangeCallback = hbmChangeCallback;
|
||||
mAutoBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
|
||||
mRecalcRunnable = this::recalculateTimeAllowance;
|
||||
mHdrListener = new HdrListener();
|
||||
|
||||
resetHbmData(displayToken, hbmData);
|
||||
}
|
||||
|
||||
void setAutoBrightnessEnabled(boolean isEnabled) {
|
||||
@@ -117,6 +126,10 @@ class HighBrightnessModeController {
|
||||
}
|
||||
}
|
||||
|
||||
float getHdrBrightnessValue() {
|
||||
return mBrightnessMax;
|
||||
}
|
||||
|
||||
void onAmbientLuxChange(float ambientLux) {
|
||||
if (!deviceSupportsHbm() || !mIsAutoBrightnessEnabled) {
|
||||
return;
|
||||
@@ -138,11 +151,12 @@ class HighBrightnessModeController {
|
||||
|
||||
// If we are starting or ending a high brightness mode session, store the current
|
||||
// session in mRunningStartTimeMillis, or the old one in mEvents.
|
||||
final boolean wasOldBrightnessHigh = oldAutoBrightness > mHbmData.transitionPoint;
|
||||
final boolean isNewBrightnessHigh = mAutoBrightness > mHbmData.transitionPoint;
|
||||
if (wasOldBrightnessHigh != isNewBrightnessHigh) {
|
||||
final boolean wasHbmDrainingAvailableTime = mRunningStartTimeMillis != -1;
|
||||
final boolean shouldHbmDrainAvailableTime = mAutoBrightness > mHbmData.transitionPoint
|
||||
&& !mIsHdrLayerPresent;
|
||||
if (wasHbmDrainingAvailableTime != shouldHbmDrainAvailableTime) {
|
||||
final long currentTime = mClock.uptimeMillis();
|
||||
if (isNewBrightnessHigh) {
|
||||
if (shouldHbmDrainAvailableTime) {
|
||||
mRunningStartTimeMillis = currentTime;
|
||||
} else {
|
||||
mEvents.addFirst(new HbmEvent(mRunningStartTimeMillis, currentTime));
|
||||
@@ -161,30 +175,49 @@ class HighBrightnessModeController {
|
||||
return mHbmMode;
|
||||
}
|
||||
|
||||
void stop() {
|
||||
registerHdrListener(null /*displayToken*/);
|
||||
}
|
||||
|
||||
void resetHbmData(IBinder displayToken, HighBrightnessModeData hbmData) {
|
||||
mHbmData = hbmData;
|
||||
unregisterHdrListener();
|
||||
if (deviceSupportsHbm()) {
|
||||
registerHdrListener(displayToken);
|
||||
recalculateTimeAllowance();
|
||||
}
|
||||
}
|
||||
|
||||
void dump(PrintWriter pw) {
|
||||
pw.println("HighBrightnessModeController:");
|
||||
pw.println(" mBrightnessMin=" + mBrightnessMin);
|
||||
pw.println(" mBrightnessMax=" + mBrightnessMax);
|
||||
pw.println(" mCurrentMin=" + getCurrentBrightnessMin());
|
||||
pw.println(" mCurrentMax=" + getCurrentBrightnessMax());
|
||||
pw.println(" mHbmMode=" + BrightnessInfo.hbmToString(mHbmMode));
|
||||
pw.println(" remainingTime=" + calculateRemainingTime(mClock.uptimeMillis()));
|
||||
pw.println(" mHbmData=" + mHbmData);
|
||||
pw.println(" mIsInAllowedAmbientRange=" + mIsInAllowedAmbientRange);
|
||||
pw.println(" mIsTimeAvailable= " + mIsTimeAvailable);
|
||||
pw.println(" mIsAutoBrightnessEnabled=" + mIsAutoBrightnessEnabled);
|
||||
pw.println(" mAutoBrightness=" + mAutoBrightness);
|
||||
pw.println(" mIsHdrLayerPresent=" + mIsHdrLayerPresent);
|
||||
pw.println(" mBrightnessMin=" + mBrightnessMin);
|
||||
pw.println(" mBrightnessMax=" + mBrightnessMax);
|
||||
}
|
||||
|
||||
private boolean isCurrentlyAllowed() {
|
||||
return mIsAutoBrightnessEnabled && mIsTimeAvailable && mIsInAllowedAmbientRange;
|
||||
return mIsHdrLayerPresent
|
||||
|| (mIsAutoBrightnessEnabled && mIsTimeAvailable && mIsInAllowedAmbientRange);
|
||||
}
|
||||
|
||||
private boolean deviceSupportsHbm() {
|
||||
return mHbmData != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recalculates the allowable HBM time.
|
||||
*/
|
||||
private void recalculateTimeAllowance() {
|
||||
final long currentTime = mClock.uptimeMillis();
|
||||
private long calculateRemainingTime(long currentTime) {
|
||||
if (!deviceSupportsHbm()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
long timeAlreadyUsed = 0;
|
||||
|
||||
// First, lets see how much time we've taken for any currently running
|
||||
@@ -222,8 +255,15 @@ class HighBrightnessModeController {
|
||||
Slog.d(TAG, "Time already used after all sessions: " + timeAlreadyUsed);
|
||||
}
|
||||
|
||||
// See how much allowable time we have left.
|
||||
final long remainingTime = Math.max(0, mHbmData.timeMaxMillis - timeAlreadyUsed);
|
||||
return Math.max(0, mHbmData.timeMaxMillis - timeAlreadyUsed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recalculates the allowable HBM time.
|
||||
*/
|
||||
private void recalculateTimeAllowance() {
|
||||
final long currentTime = mClock.uptimeMillis();
|
||||
final long remainingTime = calculateRemainingTime(currentTime);
|
||||
|
||||
// We allow HBM if there is more than the minimum required time available
|
||||
// or if brightness is already in the high range, if there is any time left at all.
|
||||
@@ -242,6 +282,7 @@ class HighBrightnessModeController {
|
||||
// If we are not allowed...timeout when the oldest event moved outside of the timing
|
||||
// window by at least minTime. Basically, we're calculating the soonest time we can
|
||||
// get {@code timeMinMillis} back to us.
|
||||
final long windowstartTimeMillis = currentTime - mHbmData.timeWindowMillis;
|
||||
final HbmEvent lastEvent = mEvents.getLast();
|
||||
final long startTimePlusMinMillis =
|
||||
Math.max(windowstartTimeMillis, lastEvent.startTimeMillis)
|
||||
@@ -278,12 +319,36 @@ class HighBrightnessModeController {
|
||||
}
|
||||
|
||||
private int calculateHighBrightnessMode() {
|
||||
if (deviceSupportsHbm() && isCurrentlyAllowed()) {
|
||||
if (!deviceSupportsHbm()) {
|
||||
return BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF;
|
||||
} else if (mIsHdrLayerPresent) {
|
||||
return BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR;
|
||||
} else if (isCurrentlyAllowed()) {
|
||||
return BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT;
|
||||
}
|
||||
|
||||
return BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF;
|
||||
}
|
||||
|
||||
private void registerHdrListener(IBinder displayToken) {
|
||||
if (mRegisteredDisplayToken == displayToken) {
|
||||
return;
|
||||
}
|
||||
|
||||
unregisterHdrListener();
|
||||
mRegisteredDisplayToken = displayToken;
|
||||
if (mRegisteredDisplayToken != null) {
|
||||
mHdrListener.register(mRegisteredDisplayToken);
|
||||
}
|
||||
}
|
||||
|
||||
private void unregisterHdrListener() {
|
||||
if (mRegisteredDisplayToken != null) {
|
||||
mHdrListener.unregister(mRegisteredDisplayToken);
|
||||
mIsHdrLayerPresent = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an event in which High Brightness Mode was enabled.
|
||||
*/
|
||||
@@ -302,4 +367,18 @@ class HighBrightnessModeController {
|
||||
+ ((endTimeMillis - startTimeMillis) / 1000) + "]";
|
||||
}
|
||||
}
|
||||
|
||||
private class HdrListener extends SurfaceControlHdrLayerInfoListener {
|
||||
@Override
|
||||
public void onHdrInfoChanged(IBinder displayToken, int numberOfHdrLayers,
|
||||
int maxW, int maxH, int flags) {
|
||||
mHandler.post(() -> {
|
||||
mIsHdrLayerPresent = numberOfHdrLayers > 0;
|
||||
// Calling the auto-brightness update so that we can recalculate
|
||||
// auto-brightness with HDR in mind. When HDR layers are present,
|
||||
// we don't limit auto-brightness' HBM time limits.
|
||||
onAutoBrightnessChanged(mAutoBrightness);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,6 +67,8 @@ final class LocalDisplayAdapter extends DisplayAdapter {
|
||||
|
||||
private static final int NO_DISPLAY_MODE_ID = 0;
|
||||
|
||||
private static final float NITS_INVALID = -1;
|
||||
|
||||
private final LongSparseArray<LocalDisplayDevice> mDevices = new LongSparseArray<>();
|
||||
|
||||
private final Injector mInjector;
|
||||
@@ -190,6 +192,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
|
||||
private int mState = Display.STATE_UNKNOWN;
|
||||
// This is only set in the runnable returned from requestDisplayStateLocked.
|
||||
private float mBrightnessState = PowerManager.BRIGHTNESS_INVALID_FLOAT;
|
||||
private float mSdrBrightnessState = PowerManager.BRIGHTNESS_INVALID_FLOAT;
|
||||
private int mDefaultModeId;
|
||||
private int mDefaultModeGroup;
|
||||
private int mActiveModeId;
|
||||
@@ -644,13 +647,15 @@ final class LocalDisplayAdapter extends DisplayAdapter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Runnable requestDisplayStateLocked(final int state, final float brightnessState) {
|
||||
public Runnable requestDisplayStateLocked(final int state, final float brightnessState,
|
||||
final float sdrBrightnessState) {
|
||||
// Assume that the brightness is off if the display is being turned off.
|
||||
assert state != Display.STATE_OFF || BrightnessSynchronizer.floatEquals(
|
||||
brightnessState, PowerManager.BRIGHTNESS_OFF_FLOAT);
|
||||
final boolean stateChanged = (mState != state);
|
||||
final boolean brightnessChanged = (!BrightnessSynchronizer.floatEquals(
|
||||
mBrightnessState, brightnessState));
|
||||
final boolean brightnessChanged =
|
||||
!(BrightnessSynchronizer.floatEquals(mBrightnessState, brightnessState)
|
||||
&& BrightnessSynchronizer.floatEquals(mSdrBrightnessState, sdrBrightnessState));
|
||||
if (stateChanged || brightnessChanged) {
|
||||
final long physicalDisplayId = mPhysicalDisplayId;
|
||||
final IBinder token = getDisplayTokenLocked();
|
||||
@@ -702,8 +707,9 @@ final class LocalDisplayAdapter extends DisplayAdapter {
|
||||
|
||||
// Apply brightness changes given that we are in a non-suspended state.
|
||||
if (brightnessChanged || vrModeChange) {
|
||||
setDisplayBrightness(brightnessState);
|
||||
setDisplayBrightness(brightnessState, sdrBrightnessState);
|
||||
mBrightnessState = brightnessState;
|
||||
mSdrBrightnessState = sdrBrightnessState;
|
||||
}
|
||||
|
||||
// Enter the final desired state, possibly suspended.
|
||||
@@ -764,8 +770,8 @@ final class LocalDisplayAdapter extends DisplayAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
private void setDisplayBrightness(float brightness) {
|
||||
// Ensure brightnessState is valid, before processing and sending to
|
||||
private void setDisplayBrightness(float brightness, float sdrBrightness) {
|
||||
// Ensure brightnessState is valid before processing and sending to
|
||||
// surface control
|
||||
if (Float.isNaN(brightness)) {
|
||||
return;
|
||||
@@ -774,17 +780,31 @@ final class LocalDisplayAdapter extends DisplayAdapter {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "setDisplayBrightness("
|
||||
+ "id=" + physicalDisplayId
|
||||
+ ", brightness=" + brightness + ")");
|
||||
+ ", brightness=" + brightness
|
||||
+ ", sdrBrightness=" + sdrBrightness + ")");
|
||||
}
|
||||
|
||||
Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayBrightness("
|
||||
+ "id=" + physicalDisplayId + ", brightness=" + brightness + ")");
|
||||
+ "id=" + physicalDisplayId + ", brightness=" + brightness
|
||||
+ ", sdrBrightness=" + sdrBrightness + ")");
|
||||
try {
|
||||
float backlight = brightnessToBacklight(brightness);
|
||||
mBacklightAdapter.setBacklight(backlight);
|
||||
final float backlight = brightnessToBacklight(brightness);
|
||||
float nits = NITS_INVALID;
|
||||
float sdrBacklight = PowerManager.BRIGHTNESS_INVALID_FLOAT;
|
||||
float sdrNits = NITS_INVALID;
|
||||
if (getDisplayDeviceConfig().hasNitsMapping()
|
||||
&& sdrBrightness != PowerManager.BRIGHTNESS_INVALID_FLOAT) {
|
||||
nits = backlightToNits(backlight);
|
||||
sdrBacklight = brightnessToBacklight(sdrBrightness);
|
||||
sdrNits = backlightToNits(sdrBacklight);
|
||||
}
|
||||
mBacklightAdapter.setBacklight(sdrBacklight, sdrNits, backlight, nits);
|
||||
Trace.traceCounter(Trace.TRACE_TAG_POWER,
|
||||
"ScreenBrightness",
|
||||
BrightnessSynchronizer.brightnessFloatToInt(brightness));
|
||||
Trace.traceCounter(Trace.TRACE_TAG_POWER,
|
||||
"SdrScreenBrightness",
|
||||
BrightnessSynchronizer.brightnessFloatToInt(sdrBrightness));
|
||||
} finally {
|
||||
Trace.traceEnd(Trace.TRACE_TAG_POWER);
|
||||
}
|
||||
@@ -793,6 +813,10 @@ final class LocalDisplayAdapter extends DisplayAdapter {
|
||||
private float brightnessToBacklight(float brightness) {
|
||||
return getDisplayDeviceConfig().getBacklightFromBrightness(brightness);
|
||||
}
|
||||
|
||||
private float backlightToNits(float backlight) {
|
||||
return getDisplayDeviceConfig().getNitsFromBacklight(backlight);
|
||||
}
|
||||
};
|
||||
}
|
||||
return null;
|
||||
@@ -1242,6 +1266,13 @@ final class LocalDisplayAdapter extends DisplayAdapter {
|
||||
public boolean setDisplayBrightness(IBinder displayToken, float brightness) {
|
||||
return SurfaceControl.setDisplayBrightness(displayToken, brightness);
|
||||
}
|
||||
|
||||
public boolean setDisplayBrightness(IBinder displayToken, float sdrBacklight,
|
||||
float sdrNits, float displayBacklight, float displayNits) {
|
||||
return SurfaceControl.setDisplayBrightness(displayToken, sdrBacklight, sdrNits,
|
||||
displayBacklight, displayNits);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class BacklightAdapter {
|
||||
@@ -1273,9 +1304,14 @@ final class LocalDisplayAdapter extends DisplayAdapter {
|
||||
}
|
||||
|
||||
// Set backlight within min and max backlight values
|
||||
void setBacklight(float backlight) {
|
||||
void setBacklight(float sdrBacklight, float sdrNits, float backlight, float nits) {
|
||||
if (mUseSurfaceControlBrightness || mForceSurfaceControl) {
|
||||
mSurfaceControlProxy.setDisplayBrightness(mDisplayToken, backlight);
|
||||
if (sdrBacklight == PowerManager.BRIGHTNESS_INVALID_FLOAT) {
|
||||
mSurfaceControlProxy.setDisplayBrightness(mDisplayToken, backlight);
|
||||
} else {
|
||||
mSurfaceControlProxy.setDisplayBrightness(mDisplayToken, sdrBacklight, sdrNits,
|
||||
backlight, nits);
|
||||
}
|
||||
} else if (mBacklight != null) {
|
||||
mBacklight.setBrightness(backlight);
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ import com.android.internal.display.BrightnessSynchronizer;
|
||||
* A custom animator that progressively updates a property value at
|
||||
* a given variable rate until it reaches a particular target value.
|
||||
*/
|
||||
final class RampAnimator<T> {
|
||||
class RampAnimator<T> {
|
||||
private final T mObject;
|
||||
private final FloatProperty<T> mProperty;
|
||||
private final Choreographer mChoreographer;
|
||||
@@ -174,4 +174,52 @@ final class RampAnimator<T> {
|
||||
public interface Listener {
|
||||
void onAnimationEnd();
|
||||
}
|
||||
|
||||
static class DualRampAnimator<T> {
|
||||
private final RampAnimator<T> mFirst;
|
||||
private final RampAnimator<T> mSecond;
|
||||
private final Listener mInternalListener = new Listener() {
|
||||
@Override
|
||||
public void onAnimationEnd() {
|
||||
if (mListener != null && !isAnimating()) {
|
||||
mListener.onAnimationEnd();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private Listener mListener;
|
||||
|
||||
DualRampAnimator(T object, FloatProperty<T> firstProperty,
|
||||
FloatProperty<T> secondProperty) {
|
||||
mFirst = new RampAnimator(object, firstProperty);
|
||||
mFirst.setListener(mInternalListener);
|
||||
mSecond = new RampAnimator(object, secondProperty);
|
||||
mSecond.setListener(mInternalListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts animating towards the specified values.
|
||||
*
|
||||
* If this is the first time the property is being set or if the rate is 0,
|
||||
* the value jumps directly to the target.
|
||||
*
|
||||
* @param firstTarget The first target value.
|
||||
* @param secondTarget The second target value.
|
||||
* @param rate The convergence rate in units per second, or 0 to set the value immediately.
|
||||
* @return True if either target differs from the previous target.
|
||||
*/
|
||||
public boolean animateTo(float firstTarget, float secondTarget, float rate) {
|
||||
final boolean firstRetval = mFirst.animateTo(firstTarget, rate);
|
||||
final boolean secondRetval = mSecond.animateTo(secondTarget, rate);
|
||||
return firstRetval && secondRetval;
|
||||
}
|
||||
|
||||
public void setListener(Listener listener) {
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
public boolean isAnimating() {
|
||||
return mFirst.isAnimating() && mSecond.isAnimating();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -293,7 +293,8 @@ public class VirtualDisplayAdapter extends DisplayAdapter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Runnable requestDisplayStateLocked(int state, float brightnessState) {
|
||||
public Runnable requestDisplayStateLocked(int state, float brightnessState,
|
||||
float sdrBrightnessState) {
|
||||
if (state != mDisplayState) {
|
||||
mDisplayState = state;
|
||||
if (state == Display.STATE_OFF) {
|
||||
|
||||
@@ -649,14 +649,14 @@ public class LocalDisplayAdapterTest {
|
||||
// Test as default display
|
||||
BacklightAdapter ba = new BacklightAdapter(displayToken, true /*isDefault*/,
|
||||
mSurfaceControlProxy);
|
||||
ba.setBacklight(0.514f);
|
||||
verify(mSurfaceControlProxy).setDisplayBrightness(displayToken, 0.514f);
|
||||
ba.setBacklight(0.514f, 100f, 0.614f, 500f);
|
||||
verify(mSurfaceControlProxy).setDisplayBrightness(displayToken, 0.514f, 100f, 0.614f, 500f);
|
||||
|
||||
// Test as not default display
|
||||
BacklightAdapter ba2 = new BacklightAdapter(displayToken, false /*isDefault*/,
|
||||
mSurfaceControlProxy);
|
||||
ba2.setBacklight(0.323f);
|
||||
verify(mSurfaceControlProxy).setDisplayBrightness(displayToken, 0.323f);
|
||||
ba2.setBacklight(0.323f, 101f, 0.723f, 601f);
|
||||
verify(mSurfaceControlProxy).setDisplayBrightness(displayToken, 0.323f, 101f, 0.723f, 601f);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -668,7 +668,7 @@ public class LocalDisplayAdapterTest {
|
||||
|
||||
BacklightAdapter ba = new BacklightAdapter(displayToken, true /*isDefault*/,
|
||||
mSurfaceControlProxy);
|
||||
ba.setBacklight(0.123f);
|
||||
ba.setBacklight(1f, 1f, 0.123f, 1f);
|
||||
verify(mMockedBacklight).setBrightness(0.123f);
|
||||
}
|
||||
|
||||
@@ -681,7 +681,7 @@ public class LocalDisplayAdapterTest {
|
||||
|
||||
BacklightAdapter ba = new BacklightAdapter(displayToken, false /*isDefault*/,
|
||||
mSurfaceControlProxy);
|
||||
ba.setBacklight(0.456f);
|
||||
ba.setBacklight(0.456f, 1f, 1f, 1f);
|
||||
|
||||
// Adapter does not forward any brightness in this case.
|
||||
verify(mMockedBacklight, never()).setBrightness(anyFloat());
|
||||
|
||||
@@ -21,6 +21,7 @@ import static android.hardware.display.BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLI
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import android.os.Binder;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.test.TestLooper;
|
||||
@@ -55,6 +56,7 @@ public class HighBrightnessModeControllerTest {
|
||||
private OffsettableClock mClock;
|
||||
private TestLooper mTestLooper;
|
||||
private Handler mHandler;
|
||||
private Binder mDisplayToken;
|
||||
|
||||
private static final HighBrightnessModeData DEFAULT_HBM_DATA =
|
||||
new HighBrightnessModeData(MINIMUM_LUX, TRANSITION_POINT, TIME_WINDOW_MILLIS,
|
||||
@@ -64,6 +66,7 @@ public class HighBrightnessModeControllerTest {
|
||||
public void setUp() {
|
||||
mClock = new OffsettableClock.Stopped();
|
||||
mTestLooper = new TestLooper(mClock::now);
|
||||
mDisplayToken = null;
|
||||
mHandler = new Handler(mTestLooper.getLooper(), new Handler.Callback() {
|
||||
@Override
|
||||
public boolean handleMessage(Message msg) {
|
||||
@@ -79,14 +82,14 @@ public class HighBrightnessModeControllerTest {
|
||||
@Test
|
||||
public void testNoHbmData() {
|
||||
final HighBrightnessModeController hbmc = new HighBrightnessModeController(
|
||||
mClock::now, mHandler, DEFAULT_MIN, DEFAULT_MAX, null, () -> {});
|
||||
mClock::now, mHandler, mDisplayToken, DEFAULT_MIN, DEFAULT_MAX, null, () -> {});
|
||||
assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_OFF);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoHbmData_Enabled() {
|
||||
final HighBrightnessModeController hbmc = new HighBrightnessModeController(
|
||||
mClock::now, mHandler, DEFAULT_MIN, DEFAULT_MAX, null, () -> {});
|
||||
mClock::now, mHandler, mDisplayToken, DEFAULT_MIN, DEFAULT_MAX, null, () -> {});
|
||||
hbmc.setAutoBrightnessEnabled(true);
|
||||
hbmc.onAmbientLuxChange(MINIMUM_LUX - 1); // below allowed range
|
||||
assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_OFF);
|
||||
@@ -264,8 +267,8 @@ public class HighBrightnessModeControllerTest {
|
||||
|
||||
// Creates instance with standard initialization values.
|
||||
private HighBrightnessModeController createDefaultHbm() {
|
||||
return new HighBrightnessModeController(mClock::now, mHandler, DEFAULT_MIN, DEFAULT_MAX,
|
||||
DEFAULT_HBM_DATA, () -> {});
|
||||
return new HighBrightnessModeController(mClock::now, mHandler, mDisplayToken, DEFAULT_MIN,
|
||||
DEFAULT_MAX, DEFAULT_HBM_DATA, () -> {});
|
||||
}
|
||||
|
||||
private void advanceTime(long timeMs) {
|
||||
|
||||
Reference in New Issue
Block a user