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

Commit b0c75b2d authored by Oleg Petšjonkin's avatar Oleg Petšjonkin Committed by Android (Google) Code Review
Browse files

Merge "Moving HDR logic from HDRClamper to HDRModifier" into main

parents 9b37843d 4f14640b
Loading
Loading
Loading
Loading
+7 −4
Original line number Diff line number Diff line
@@ -99,6 +99,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.function.Function;

import javax.xml.datatype.DatatypeConfigurationException;

@@ -1798,15 +1799,17 @@ public class DisplayDeviceConfig {
                loadThermalThrottlingConfig(config);
                loadPowerThrottlingConfigData(config);
                // Backlight and evenDimmer data should be loaded for HbmData
                mHbmData = HighBrightnessModeData.loadHighBrightnessModeData(config, (hbm) -> {
                Function<HighBrightnessMode, Float> transitionPointProvider = (hbm) -> {
                    float transitionPointBacklightScale = hbm.getTransitionPoint_all().floatValue();
                    if (transitionPointBacklightScale >= mBacklightMaximum) {
                        throw new IllegalArgumentException("HBM transition point invalid. "
                                + mHbmData.transitionPoint + " is not less than "
                                + transitionPointBacklightScale + " is not less than "
                                + mBacklightMaximum);
                    }
                    return  getBrightnessFromBacklight(transitionPointBacklightScale);
                });
                };
                mHbmData = HighBrightnessModeData.loadHighBrightnessModeData(config,
                        transitionPointProvider);
                if (mHbmData.isHighBrightnessModeEnabled && mHbmData.refreshRateLimit != null) {
                    // TODO(b/331650248): cleanup, DMD can use mHbmData.refreshRateLimit
                    mRefreshRateLimitations.add(new RefreshRateLimitation(
@@ -1830,7 +1833,7 @@ public class DisplayDeviceConfig {
                loadRefreshRateSetting(config);
                loadScreenOffBrightnessSensorValueToLuxFromDdc(config);
                loadUsiVersion(config);
                mHdrBrightnessData = HdrBrightnessData.loadConfig(config);
                mHdrBrightnessData = HdrBrightnessData.loadConfig(config, transitionPointProvider);
                loadBrightnessCapForWearBedtimeMode(config);
                loadIdleScreenRefreshRateTimeoutConfigs(config);
                mVrrSupportEnabled = config.getSupportsVrr();
+4 −3
Original line number Diff line number Diff line
@@ -271,8 +271,9 @@ public class BrightnessClamperController {
            ModifiersAggregatedState state2) {
        return !BrightnessSynchronizer.floatEquals(state1.mMaxDesiredHdrRatio,
                state2.mMaxDesiredHdrRatio)
                || state1.mSdrHdrRatioSpline != state2.mSdrHdrRatioSpline
                || state1.mHdrHbmEnabled != state2.mHdrHbmEnabled;
                || !BrightnessSynchronizer.floatEquals(state1.mMaxHdrBrightness,
                state2.mMaxHdrBrightness)
                || state1.mSdrHdrRatioSpline != state2.mSdrHdrRatioSpline;
    }

    private void start() {
@@ -470,8 +471,8 @@ public class BrightnessClamperController {
     */
    public static class ModifiersAggregatedState {
        float mMaxDesiredHdrRatio = HdrBrightnessModifier.DEFAULT_MAX_HDR_SDR_RATIO;
        float mMaxHdrBrightness = PowerManager.BRIGHTNESS_MAX;
        @Nullable
        Spline mSdrHdrRatioSpline = null;
        boolean mHdrHbmEnabled = false;
    }
}
+119 −13
Original line number Diff line number Diff line
@@ -16,11 +16,15 @@

package com.android.server.display.brightness.clamper;

import static com.android.server.display.DisplayBrightnessState.CUSTOM_ANIMATION_RATE_NOT_SET;
import static com.android.server.display.brightness.clamper.LightSensorController.INVALID_LUX;

import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.hardware.display.DisplayManagerInternal;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManager;
import android.view.SurfaceControlHdrLayerInfoListener;

import com.android.internal.annotations.VisibleForTesting;
@@ -30,6 +34,7 @@ import com.android.server.display.DisplayDeviceConfig;
import com.android.server.display.config.HdrBrightnessData;

import java.io.PrintWriter;
import java.util.Map;

public class HdrBrightnessModifier implements BrightnessStateModifier,
        BrightnessClamperController.DisplayDeviceDataListener,
@@ -53,20 +58,32 @@ public class HdrBrightnessModifier implements BrightnessStateModifier,
    private final Handler mHandler;
    private final BrightnessClamperController.ClamperChangeListener mClamperChangeListener;
    private final Injector mInjector;
    private final Runnable mDebouncer;

    private IBinder mRegisteredDisplayToken;

    private float mScreenSize;
    private float mHdrLayerSize = DEFAULT_HDR_LAYER_SIZE;
    private HdrBrightnessData mHdrBrightnessData;
    private DisplayDeviceConfig mDisplayDeviceConfig;
    @Nullable
    private HdrBrightnessData mHdrBrightnessData;
    private float mScreenSize;

    private float mMaxDesiredHdrRatio = DEFAULT_MAX_HDR_SDR_RATIO;
    private float mHdrLayerSize = DEFAULT_HDR_LAYER_SIZE;

    private float mAmbientLux = INVALID_LUX;

    private Mode mMode = Mode.NO_HDR;
    // The maximum brightness allowed for current lux
    private float mMaxBrightness = PowerManager.BRIGHTNESS_MAX;
    private float mPendingMaxBrightness = PowerManager.BRIGHTNESS_MAX;
    // brightness change speed, in units per seconds. Applied only on ambient lux changes
    private float mTransitionRate = CUSTOM_ANIMATION_RATE_NOT_SET;
    private float mPendingTransitionRate = CUSTOM_ANIMATION_RATE_NOT_SET;

    HdrBrightnessModifier(Handler handler,
            BrightnessClamperController.ClamperChangeListener clamperChangeListener,
            BrightnessClamperController.DisplayDeviceData displayData) {
        this(handler, clamperChangeListener, new Injector(), displayData);
        this(new Handler(handler.getLooper()), clamperChangeListener, new Injector(), displayData);
    }

    @VisibleForTesting
@@ -77,6 +94,11 @@ public class HdrBrightnessModifier implements BrightnessStateModifier,
        mHandler = handler;
        mClamperChangeListener = clamperChangeListener;
        mInjector = injector;
        mDebouncer = () -> {
            mTransitionRate = mPendingTransitionRate;
            mMaxBrightness = mPendingMaxBrightness;
            mClamperChangeListener.onChanged();
        };
        onDisplayChanged(displayData);
    }

@@ -90,33 +112,60 @@ public class HdrBrightnessModifier implements BrightnessStateModifier,
        if (mMode == Mode.NO_HDR) {
            return;
        }

        float hdrBrightness = mDisplayDeviceConfig.getHdrBrightnessFromSdr(
                stateBuilder.getBrightness(), mMaxDesiredHdrRatio,
                mHdrBrightnessData.sdrToHdrRatioSpline);
        float maxBrightness = getMaxBrightness(mMode, mMaxBrightness, mHdrBrightnessData);
        hdrBrightness = Math.min(hdrBrightness, maxBrightness);

        stateBuilder.setHdrBrightness(hdrBrightness);
        stateBuilder.setCustomAnimationRate(mTransitionRate);
        // transition rate applied, reset
        mTransitionRate = CUSTOM_ANIMATION_RATE_NOT_SET;
    }

    @Override
    public void dump(PrintWriter printWriter) {
        // noop
    public void dump(PrintWriter pw) {
        pw.println("HdrBrightnessModifier:");
        pw.println("  mHdrBrightnessData=" + mHdrBrightnessData);
        pw.println("  mScreenSize=" + mScreenSize);
        pw.println("  mMaxDesiredHdrRatio=" + mMaxDesiredHdrRatio);
        pw.println("  mHdrLayerSize=" + mHdrLayerSize);
        pw.println("  mAmbientLux=" + mAmbientLux);
        pw.println("  mMode=" + mMode);
        pw.println("  mMaxBrightness=" + mMaxBrightness);
        pw.println("  mPendingMaxBrightness=" + mPendingMaxBrightness);
        pw.println("  mTransitionRate=" + mTransitionRate);
        pw.println("  mPendingTransitionRate=" + mPendingTransitionRate);
        pw.println("  mHdrListener registered=" + (mRegisteredDisplayToken != null));
    }

    // Called in DisplayControllerHandler
    @Override
    public void stop() {
        unregisterHdrListener();
        mHandler.removeCallbacksAndMessages(null);
    }


    // Called in DisplayControllerHandler
    @Override
    public boolean shouldListenToLightSensor() {
        return false;
        return hasBrightnessLimits();
    }

    // Called in DisplayControllerHandler
    @Override
    public void setAmbientLux(float lux) {
        // noop
        mAmbientLux = lux;
        if (!hasBrightnessLimits()) {
            return;
        }
        float desiredMaxBrightness = findBrightnessLimit(mHdrBrightnessData, lux);
        if (mMode == Mode.NO_HDR) {
            mMaxBrightness = desiredMaxBrightness;
        } else {
            scheduleMaxBrightnessUpdate(desiredMaxBrightness, mHdrBrightnessData);
        }
    }

    @Override
@@ -125,15 +174,44 @@ public class HdrBrightnessModifier implements BrightnessStateModifier,
                displayData.mHeight, displayData.mDisplayDeviceConfig));
    }

    // Called in DisplayControllerHandler
    // Called in DisplayControllerHandler, when any modifier state changes
    @Override
    public void applyStateChange(
            BrightnessClamperController.ModifiersAggregatedState aggregatedState) {
        if (mMode != Mode.NO_HDR) {
        if (mMode != Mode.NO_HDR && mHdrBrightnessData != null) {
            aggregatedState.mMaxDesiredHdrRatio = mMaxDesiredHdrRatio;
            aggregatedState.mSdrHdrRatioSpline = mHdrBrightnessData.sdrToHdrRatioSpline;
            aggregatedState.mHdrHbmEnabled = (mMode == Mode.HBM_HDR);
            aggregatedState.mMaxHdrBrightness = getMaxBrightness(
                    mMode, mMaxBrightness, mHdrBrightnessData);
        }
    }

    private boolean hasBrightnessLimits() {
        return mHdrBrightnessData != null && !mHdrBrightnessData.maxBrightnessLimits.isEmpty();
    }

    private void scheduleMaxBrightnessUpdate(float desiredMaxBrightness, HdrBrightnessData data) {
        if (mMaxBrightness == desiredMaxBrightness) {
            mPendingMaxBrightness = mMaxBrightness;
            mPendingTransitionRate = -1f;
            mTransitionRate = -1f;
            mHandler.removeCallbacks(mDebouncer);
        } else if (mPendingMaxBrightness != desiredMaxBrightness) {
            mPendingMaxBrightness = desiredMaxBrightness;
            long debounceTime;
            if (mPendingMaxBrightness > mMaxBrightness) {
                debounceTime = data.brightnessIncreaseDebounceMillis;
                mPendingTransitionRate = data.screenBrightnessRampIncrease;
            } else {
                debounceTime = data.brightnessDecreaseDebounceMillis;
                mPendingTransitionRate = data.screenBrightnessRampDecrease;
            }

            mHandler.removeCallbacks(mDebouncer);
            mHandler.postDelayed(mDebouncer, debounceTime);
        }
        // do nothing if expectedMaxBrightness == mDesiredMaxBrightness
        // && expectedMaxBrightness != mMaxBrightness
    }

    // Called in DisplayControllerHandler
@@ -168,6 +246,8 @@ public class HdrBrightnessModifier implements BrightnessStateModifier,
        mMaxDesiredHdrRatio = maxDesiredHdrRatio;

        if (needToNotifyChange) {
            // data or hdr layer changed, reset custom transition rate
            mTransitionRate = CUSTOM_ANIMATION_RATE_NOT_SET;
            mClamperChangeListener.onChanged();
        }
    }
@@ -190,6 +270,32 @@ public class HdrBrightnessModifier implements BrightnessStateModifier,
        return Mode.HBM_HDR;
    }

    private float getMaxBrightness(Mode mode, float maxBrightness, HdrBrightnessData data) {
        if (mode == Mode.NBM_HDR) {
            return Math.min(data.hbmTransitionPoint, maxBrightness);
        } else if (mode == Mode.HBM_HDR) {
            return maxBrightness;
        } else {
            return PowerManager.BRIGHTNESS_MAX;
        }
    }

    // Called in DisplayControllerHandler
    private float findBrightnessLimit(HdrBrightnessData data, float ambientLux) {
        float foundAmbientBoundary = Float.MAX_VALUE;
        float foundMaxBrightness = PowerManager.BRIGHTNESS_MAX;
        for (Map.Entry<Float, Float> brightnessPoint :
                data.maxBrightnessLimits.entrySet()) {
            float ambientBoundary = brightnessPoint.getKey();
            // find ambient lux upper boundary closest to current ambient lux
            if (ambientBoundary > ambientLux && ambientBoundary < foundAmbientBoundary) {
                foundMaxBrightness = brightnessPoint.getValue();
                foundAmbientBoundary = ambientBoundary;
            }
        }
        return foundMaxBrightness;
    }

    // Called in DisplayControllerHandler
    private void onHdrInfoChanged(float hdrLayerSize, float maxDesiredHdrSdrRatio) {
        mHdrLayerSize = hdrLayerSize;
+35 −6
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.server.display.config;
import static com.android.server.display.config.HighBrightnessModeData.HDR_PERCENT_OF_SCREEN_REQUIRED_DEFAULT;

import android.annotation.Nullable;
import android.os.PowerManager;
import android.util.Spline;

import com.android.internal.annotations.VisibleForTesting;
@@ -29,6 +30,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

/**
 * Brightness config for HDR content
@@ -48,9 +50,9 @@ import java.util.Map;
 *             </point>
 *         </brightnessMap>
 *         <brightnessIncreaseDebounceMillis>1000</brightnessIncreaseDebounceMillis>
 *         <brightnessIncreaseDurationMillis>10000</brightnessIncreaseDurationMillis>
 *         <screenBrightnessRampIncrease>0.04</brightnessIncreaseDurationMillis>
 *         <brightnessDecreaseDebounceMillis>13000</brightnessDecreaseDebounceMillis>
 *         <brightnessDecreaseDurationMillis>10000</brightnessDecreaseDurationMillis>
 *         <screenBrightnessRampDecrease>0.03</brightnessDecreaseDurationMillis>
 *         <minimumHdrPercentOfScreenForNbm>0.2</minimumHdrPercentOfScreenForNbm>
 *         <minimumHdrPercentOfScreenForHbm>0.5</minimumHdrPercentOfScreenForHbm>
 *         <allowInLowPowerMode>true</allowInLowPowerMode>
@@ -98,6 +100,11 @@ public class HdrBrightnessData {
     */
    public final float screenBrightnessRampDecrease;

    /**
     * Brightness level at which we transition from normal to high-brightness
     */
    public final float hbmTransitionPoint;

    /**
     * Min Hdr layer size to start hdr brightness boost up to high brightness mode transition point
     */
@@ -123,6 +130,7 @@ public class HdrBrightnessData {
    public HdrBrightnessData(Map<Float, Float> maxBrightnessLimits,
            long brightnessIncreaseDebounceMillis, float screenBrightnessRampIncrease,
            long brightnessDecreaseDebounceMillis, float screenBrightnessRampDecrease,
            float hbmTransitionPoint,
            float minimumHdrPercentOfScreenForNbm, float minimumHdrPercentOfScreenForHbm,
            boolean allowInLowPowerMode, @Nullable Spline sdrToHdrRatioSpline) {
        this.maxBrightnessLimits = maxBrightnessLimits;
@@ -130,6 +138,7 @@ public class HdrBrightnessData {
        this.screenBrightnessRampIncrease = screenBrightnessRampIncrease;
        this.brightnessDecreaseDebounceMillis = brightnessDecreaseDebounceMillis;
        this.screenBrightnessRampDecrease = screenBrightnessRampDecrease;
        this.hbmTransitionPoint = hbmTransitionPoint;
        this.minimumHdrPercentOfScreenForNbm = minimumHdrPercentOfScreenForNbm;
        this.minimumHdrPercentOfScreenForHbm = minimumHdrPercentOfScreenForHbm;
        this.allowInLowPowerMode = allowInLowPowerMode;
@@ -144,6 +153,7 @@ public class HdrBrightnessData {
                + ", mScreenBrightnessRampIncrease: " + screenBrightnessRampIncrease
                + ", mBrightnessDecreaseDebounceMillis: " + brightnessDecreaseDebounceMillis
                + ", mScreenBrightnessRampDecrease: " + screenBrightnessRampDecrease
                + ", transitionPoint: " + hbmTransitionPoint
                + ", minimumHdrPercentOfScreenForNbm: " + minimumHdrPercentOfScreenForNbm
                + ", minimumHdrPercentOfScreenForHbm: " + minimumHdrPercentOfScreenForHbm
                + ", allowInLowPowerMode: " + allowInLowPowerMode
@@ -155,10 +165,12 @@ public class HdrBrightnessData {
     * Loads HdrBrightnessData from DisplayConfiguration
     */
    @Nullable
    public static HdrBrightnessData loadConfig(DisplayConfiguration config) {
    public static HdrBrightnessData loadConfig(DisplayConfiguration config,
            Function<HighBrightnessMode, Float> transitionPointProvider) {
        HighBrightnessMode hbmConfig = config.getHighBrightnessMode();
        HdrBrightnessConfig hdrConfig = config.getHdrBrightnessConfig();
        if (hdrConfig == null) {
            return getFallbackData(config.getHighBrightnessMode());
            return getFallbackData(hbmConfig, transitionPointProvider);
        }

        List<NonNegativeFloatToFloatPoint> points = hdrConfig.getBrightnessMap().getPoint();
@@ -169,22 +181,38 @@ public class HdrBrightnessData {

        float minHdrPercentForHbm = hdrConfig.getMinimumHdrPercentOfScreenForHbm() != null
                ? hdrConfig.getMinimumHdrPercentOfScreenForHbm().floatValue()
                : getFallbackHdrPercent(config.getHighBrightnessMode());
                : getFallbackHdrPercent(hbmConfig);

        float minHdrPercentForNbm = hdrConfig.getMinimumHdrPercentOfScreenForNbm() != null
                ? hdrConfig.getMinimumHdrPercentOfScreenForNbm().floatValue() : minHdrPercentForHbm;

        if (minHdrPercentForNbm > minHdrPercentForHbm) {
            throw new IllegalArgumentException(
                    "minHdrPercentForHbm should be >= minHdrPercentForNbm");
        }

        return new HdrBrightnessData(brightnessLimits,
                hdrConfig.getBrightnessIncreaseDebounceMillis().longValue(),
                hdrConfig.getScreenBrightnessRampIncrease().floatValue(),
                hdrConfig.getBrightnessDecreaseDebounceMillis().longValue(),
                hdrConfig.getScreenBrightnessRampDecrease().floatValue(),
                getTransitionPoint(hbmConfig, transitionPointProvider),
                minHdrPercentForNbm, minHdrPercentForHbm, hdrConfig.getAllowInLowPowerMode(),
                getSdrHdrRatioSpline(hdrConfig, config.getHighBrightnessMode()));
    }

    private static float getTransitionPoint(@Nullable HighBrightnessMode hbm,
            Function<HighBrightnessMode, Float> transitionPointProvider) {
        if (hbm == null) {
            return PowerManager.BRIGHTNESS_MAX;
        } else {
            return transitionPointProvider.apply(hbm);
        }
    }

    @Nullable
    private static HdrBrightnessData getFallbackData(HighBrightnessMode hbm) {
    private static HdrBrightnessData getFallbackData(@Nullable HighBrightnessMode hbm,
            Function<HighBrightnessMode, Float> transitionPointProvider) {
        if (hbm == null) {
            return null;
        }
@@ -193,6 +221,7 @@ public class HdrBrightnessData {
        return new HdrBrightnessData(Collections.emptyMap(),
                0, DisplayBrightnessState.CUSTOM_ANIMATION_RATE_NOT_SET,
                0, DisplayBrightnessState.CUSTOM_ANIMATION_RATE_NOT_SET,
                getTransitionPoint(hbm, transitionPointProvider),
                fallbackPercent, fallbackPercent, false, fallbackSpline);
    }

+2 −1
Original line number Diff line number Diff line
@@ -353,7 +353,8 @@ public class BrightnessClamperControllerTest {
    public void test_notifiesExternalListener_aggregatedStateChanged() {
        doAnswer((invocation) -> {
            ModifiersAggregatedState argument = invocation.getArgument(0);
            argument.mHdrHbmEnabled = true;
            // we need to do changes in AggregatedState to trigger onChange
            argument.mMaxHdrBrightness = 0.5f;
            return null;
        }).when(mMockStatefulModifier).applyStateChange(any());
        mTestInjector.mCapturedChangeListener.onChanged();
Loading