Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4db91e1e authored by Santos Cordon's avatar Santos Cordon
Browse files

Clamp manual brightness on high brightness mode devices.

Test: manually check that brightness stays within the
non-HBM bounds
Test: atest com.android.server.display
Bug: 168219311

Change-Id: Id54bdbf40b68064f6d1896a0ef638c8799995697
parent 85399be2
Loading
Loading
Loading
Loading
+8 −18
Original line number Diff line number Diff line
@@ -46,7 +46,6 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.display.BrightnessSynchronizer;
import com.android.internal.os.BackgroundThread;
import com.android.server.EventLogTags;
import com.android.server.display.DisplayDeviceConfig.HighBrightnessModeData;

import java.io.PrintWriter;

@@ -220,12 +219,14 @@ class AutomaticBrightnessController {
            float dozeScaleFactor, int lightSensorRate, int initialLightSensorRate,
            long brighteningLightDebounceConfig, long darkeningLightDebounceConfig,
            boolean resetAmbientLuxAfterWarmUpConfig, HysteresisLevels ambientBrightnessThresholds,
            HysteresisLevels screenBrightnessThresholds, LogicalDisplay display, Context context) {
            HysteresisLevels screenBrightnessThresholds, LogicalDisplay display, Context context,
            HighBrightnessModeController hbmController) {
        this(new Injector(), callbacks, looper, sensorManager, lightSensor, mapper,
                lightSensorWarmUpTime, brightnessMin, brightnessMax, dozeScaleFactor,
                lightSensorRate, initialLightSensorRate, brighteningLightDebounceConfig,
                darkeningLightDebounceConfig, resetAmbientLuxAfterWarmUpConfig,
                ambientBrightnessThresholds, screenBrightnessThresholds, display, context
                ambientBrightnessThresholds, screenBrightnessThresholds, display, context,
                hbmController
        );
    }

@@ -236,7 +237,8 @@ class AutomaticBrightnessController {
            float dozeScaleFactor, int lightSensorRate, int initialLightSensorRate,
            long brighteningLightDebounceConfig, long darkeningLightDebounceConfig,
            boolean resetAmbientLuxAfterWarmUpConfig, HysteresisLevels ambientBrightnessThresholds,
            HysteresisLevels screenBrightnessThresholds, LogicalDisplay display, Context context) {
            HysteresisLevels screenBrightnessThresholds, LogicalDisplay display, Context context,
            HighBrightnessModeController hbmController) {
        mInjector = injector;
        mContext = context;
        mCallbacks = callbacks;
@@ -273,20 +275,7 @@ class AutomaticBrightnessController {
        mPendingForegroundAppPackageName = null;
        mForegroundAppCategory = ApplicationInfo.CATEGORY_UNDEFINED;
        mPendingForegroundAppCategory = ApplicationInfo.CATEGORY_UNDEFINED;

        final DisplayDeviceConfig ddConfig =
                display.getPrimaryDisplayDeviceLocked().getDisplayDeviceConfig();
        HighBrightnessModeData hbmData =
                ddConfig != null ? ddConfig.getHighBrightnessModeData() : null;

        final Runnable hbmChangeCallback = () -> {
            updateAutoBrightness(true /*sendUpdate*/, false /*userInitiatedChange*/);
            // TODO: b/175937645 - Callback to DisplayManagerService to indicate a change to the HBM
            // allowance has been made so that the brightness limits can be calculated
            // appropriately.
        };
        mHbmController = new HighBrightnessModeController(mHandler, brightnessMin, brightnessMax,
                hbmData, hbmChangeCallback);
        mHbmController = hbmController;
    }

    /**
@@ -327,6 +316,7 @@ class AutomaticBrightnessController {
    public void configure(boolean enable, @Nullable BrightnessConfiguration configuration,
            float brightness, boolean userChangedBrightness, float adjustment,
            boolean userChangedAutoBrightnessAdjustment, int displayPolicy) {
        mHbmController.setAutoBrightnessEnabled(enable);
        // While dozing, the application processor may be suspended which will prevent us from
        // receiving new information from the light sensor. On some devices, we may be able to
        // switch to a wake-up light sensor instead but for now we will simply disable the sensor
+42 −12
Original line number Diff line number Diff line
@@ -350,12 +350,15 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
    private final ColorDisplayServiceInternal mCdsi;
    private final float[] mNitsRange;

    private final HighBrightnessModeController mHbmController;

    // A record of state for skipping brightness ramps.
    private int mSkipRampState = RAMP_STATE_SKIP_NONE;

    // The first autobrightness value set when entering RAMP_STATE_SKIP_INITIAL.
    private float mInitialAutoBrightness;


    // The controller for the automatic brightness level.
    private AutomaticBrightnessController mAutomaticBrightnessController;

@@ -433,6 +436,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
        mBlanker = blanker;
        mContext = context;


        PowerManager pm = context.getSystemService(PowerManager.class);

        final Resources resources = context.getResources();
@@ -476,6 +480,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
        mSkipScreenOnBrightnessRamp = resources.getBoolean(
                com.android.internal.R.bool.config_skipScreenOnBrightnessRamp);

        mHbmController = createHbmController();

        if (mUseSoftwareAutoBrightnessConfig) {
            final float dozeScaleFactor = resources.getFraction(
                    com.android.internal.R.fraction.config_screenAutoBrightnessDozeScaleFactor,
@@ -535,7 +541,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
                        PowerManager.BRIGHTNESS_MAX, dozeScaleFactor, lightSensorRate,
                        initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce,
                        autoBrightnessResetAmbientLuxAfterWarmUp, ambientBrightnessThresholds,
                        screenBrightnessThresholds, logicalDisplay, context);
                        screenBrightnessThresholds, logicalDisplay, context, mHbmController);
            } else {
                mUseSoftwareAutoBrightnessConfig = false;
            }
@@ -1080,6 +1086,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
            mBrightnessTracker.setBrightnessConfiguration(mBrightnessConfiguration);
        }

        boolean updateScreenBrightnessSetting = false;

        // Apply auto-brightness.
        boolean slowChange = false;
        if (Float.isNaN(brightnessState)) {
@@ -1096,11 +1104,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
                if (mAppliedAutoBrightness && !autoBrightnessAdjustmentChanged) {
                    slowChange = true; // slowly adapt to auto-brightness
                }
                // Tell the rest of the system about the new brightness. Note that we do this
                // before applying the low power or dim transformations so that the slider
                // accurately represents the full possible range, even if they range changes what
                // it means in absolute terms.
                putScreenBrightnessSetting(brightnessState);
                updateScreenBrightnessSetting = true;
                mAppliedAutoBrightness = true;
                mBrightnessReasonTemp.setReason(BrightnessReason.REASON_AUTOMATIC);
            } else {
@@ -1118,6 +1122,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
            mAppliedAutoBrightness = false;
            brightnessAdjustmentFlags = 0;
        }

        // Use default brightness when dozing unless overridden.
        if ((Float.isNaN(brightnessState))
                && Display.isDozeState(state)) {
@@ -1128,9 +1133,24 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
        // Apply manual brightness.
        if (Float.isNaN(brightnessState)) {
            brightnessState = clampScreenBrightness(mCurrentScreenBrightnessSetting);
            if (brightnessState != mCurrentScreenBrightnessSetting) {
                // The manually chosen screen brightness is outside of the currently allowed
                // range (i.e., high-brightness-mode), make sure we tell the rest of the system
                // by updating the setting.
                updateScreenBrightnessSetting = true;
            }
            mBrightnessReasonTemp.setReason(BrightnessReason.REASON_MANUAL);
        }

        if (updateScreenBrightnessSetting) {
            // Tell the rest of the system about the new brightness in case we had to change it
            // for things like auto-brightness or high-brightness-mode. Note that we do this
            // before applying the low power or dim transformations so that the slider
            // accurately represents the full possible range, even if they range changes what
            // it means in absolute terms.
            putScreenBrightnessSetting(brightnessState);
        }

        // Apply dimming by at least some minimum amount when user activity
        // timeout is about to expire.
        if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
@@ -1208,9 +1228,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
            // animate to. To avoid this, we check the value first.
            // If the brightnessState is off (-1.0f) we still want to animate to the minimum
            // brightness (0.0f) to accommodate for LED displays, which can appear bright to the
            // user even when the display is all black.
            float animateValue = brightnessState == PowerManager.BRIGHTNESS_OFF_FLOAT
                    ? PowerManager.BRIGHTNESS_MIN : brightnessState;
            // user even when the display is all black. We also clamp here in case some
            // transformations to the brightness have pushed it outside of the currently
            // allowed range.
            float animateValue = clampScreenBrightness(brightnessState);
            final float currentBrightness = mPowerState.getScreenBrightness();
            if (isValidBrightnessValue(animateValue)
                    && !BrightnessSynchronizer.floatEquals(animateValue, currentBrightness)) {
@@ -1353,6 +1374,15 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
        msg.sendToTarget();
    }

    private HighBrightnessModeController createHbmController() {
        final DisplayDeviceConfig ddConfig =
                mLogicalDisplay.getPrimaryDisplayDeviceLocked().getDisplayDeviceConfig();
        final DisplayDeviceConfig.HighBrightnessModeData hbmData =
                ddConfig != null ? ddConfig.getHighBrightnessModeData() : null;
        return new HighBrightnessModeController(mHandler, PowerManager.BRIGHTNESS_MIN,
                PowerManager.BRIGHTNESS_MAX, hbmData, () -> sendUpdatePowerStateLocked());
    }

    private void blockScreenOn() {
        if (mPendingScreenOnUnblocker == null) {
            Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
@@ -1468,10 +1498,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call

    private float clampScreenBrightness(float value) {
        if (Float.isNaN(value)) {
            return PowerManager.BRIGHTNESS_MIN;
            value = PowerManager.BRIGHTNESS_MIN;
        }
        return MathUtils.constrain(
                value, PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX);
        return MathUtils.constrain(value,
                mHbmController.getCurrentBrightnessMin(), mHbmController.getCurrentBrightnessMax());
    }

    // Checks whether the brightness is within the valid brightness range, not including the off or
+19 −7
Original line number Diff line number Diff line
@@ -37,7 +37,7 @@ import java.util.LinkedList;
class HighBrightnessModeController {
    private static final String TAG = "HighBrightnessModeController";

    private static final boolean DEBUG_HBM = false;
    private static final boolean DEBUG = false;

    private final float mBrightnessMin;
    private final float mBrightnessMax;
@@ -48,6 +48,7 @@ class HighBrightnessModeController {

    private boolean mIsInAllowedAmbientRange = false;
    private boolean mIsTimeAvailable = false;
    private boolean mIsAutoBrightnessEnabled = false;
    private float mAutoBrightness;

    /**
@@ -84,6 +85,17 @@ class HighBrightnessModeController {
        };
    }

    void setAutoBrightnessEnabled(boolean isEnabled) {
        if (isEnabled == mIsAutoBrightnessEnabled) {
            return;
        }
        if (DEBUG) {
            Slog.d(TAG, "setAutoBrightness( " + isEnabled + " )");
        }
        mIsAutoBrightnessEnabled = isEnabled;
        mIsInAllowedAmbientRange = false; // reset when auto-brightness switches
    }

    float getCurrentBrightnessMin() {
        return mBrightnessMin;
    }
@@ -102,7 +114,7 @@ class HighBrightnessModeController {
    }

    void onAmbientLuxChange(float ambientLux) {
        if (!deviceSupportsHbm()) {
        if (!deviceSupportsHbm() || !mIsAutoBrightnessEnabled) {
            return;
        }

@@ -132,7 +144,7 @@ class HighBrightnessModeController {
                mEvents.addFirst(new HbmEvent(mRunningStartTimeMillis, currentTime));
                mRunningStartTimeMillis = -1;

                if (DEBUG_HBM) {
                if (DEBUG) {
                    Slog.d(TAG, "New HBM event: " + mEvents.getFirst());
                }
            }
@@ -142,7 +154,7 @@ class HighBrightnessModeController {
    }

    private boolean isCurrentlyAllowed() {
        return mIsTimeAvailable && mIsInAllowedAmbientRange;
        return mIsAutoBrightnessEnabled && mIsTimeAvailable && mIsInAllowedAmbientRange;
    }

    private boolean deviceSupportsHbm() {
@@ -167,7 +179,7 @@ class HighBrightnessModeController {
            timeAlreadyUsed = currentTime - mRunningStartTimeMillis;
        }

        if (DEBUG_HBM) {
        if (DEBUG) {
            Slog.d(TAG, "Time already used after current session: " + timeAlreadyUsed);
        }

@@ -187,7 +199,7 @@ class HighBrightnessModeController {
            timeAlreadyUsed += event.endTimeMillis - startTimeMillis;
        }

        if (DEBUG_HBM) {
        if (DEBUG) {
            Slog.d(TAG, "Time already used after all sessions: " + timeAlreadyUsed);
        }

@@ -220,7 +232,7 @@ class HighBrightnessModeController {
            nextTimeout = timeWhenMinIsGainedBack;
        }

        if (DEBUG_HBM) {
        if (DEBUG) {
            Slog.d(TAG, "HBM recalculated.  IsAllowedWithoutRestrictions: "
                    + isAllowedWithoutRestrictions
                    + ", isOnlyAllowedToStayOn: " + isOnlyAllowedToStayOn
+3 −1
Original line number Diff line number Diff line
@@ -65,6 +65,7 @@ public class AutomaticBrightnessControllerTest {
    @Mock HysteresisLevels mScreenBrightnessThresholds;
    @Mock Handler mNoOpHandler;
    @Mock DisplayDevice mDisplayDevice;
    @Mock HighBrightnessModeController mHbmController;

    private static final int LIGHT_SENSOR_WARMUP_TIME = 0;
    @Before
@@ -90,7 +91,8 @@ public class AutomaticBrightnessControllerTest {
                BRIGHTNESS_MAX_FLOAT, DOZE_SCALE_FACTOR, LIGHT_SENSOR_RATE,
                INITIAL_LIGHT_SENSOR_RATE, BRIGHTENING_LIGHT_DEBOUNCE_CONFIG,
                DARKENING_LIGHT_DEBOUNCE_CONFIG, RESET_AMBIENT_LUX_AFTER_WARMUP_CONFIG,
                mAmbientBrightnessThresholds, mScreenBrightnessThresholds, mLogicalDisplay, mContext
                mAmbientBrightnessThresholds, mScreenBrightnessThresholds, mLogicalDisplay,
                mContext, mHbmController
        );
        controller.setLoggingEnabled(true);