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

Commit 0818e3ad authored by petsjonkin's avatar petsjonkin
Browse files

HdrBoostOverride integration with HdrBrightnessModifier

Bug: b/426488652
Test: atest HdrBrightnessModifierTest
Flag: com.android.server.display.feature.flags.enable_hdr_override_plugin_type
Change-Id: I1aea7e701a58775eb0d62fa5fbbd03c6db87a649
parent 69716fca
Loading
Loading
Loading
Loading
+34 −12
Original line number Diff line number Diff line
@@ -1230,7 +1230,7 @@ public class DisplayDeviceConfig {
    }

    /**
     * Calculate the HDR brightness for the specified SDR brightenss, restricted by the
     * Calculate the HDR brightness for the specified SDR brightness, restricted by the
     * maxDesiredHdrSdrRatio (the ratio between the HDR luminance and SDR luminance) and specific
     * sdrToHdrSpline
     *
@@ -1241,30 +1241,52 @@ public class DisplayDeviceConfig {
        if (sdrToHdrSpline == null) {
            return PowerManager.BRIGHTNESS_INVALID;
        }

        float backlight = getBacklightFromBrightness(brightness);
        float nits = getNitsFromBacklight(backlight);
        if (nits == INVALID_NITS) {
            return PowerManager.BRIGHTNESS_INVALID;
        }

        float rawRatio = sdrToHdrSpline.interpolate(nits);
        float scaledRatio = (rawRatio - 1) * ratioScaleFactor + 1;
        float ratio = Math.min(scaledRatio, maxDesiredHdrSdrRatio);
        float hdrNits = nits * ratio;
        if (DEBUG) {
            Slog.d(TAG, "getHdrBrightnessFromSdr: sdr brightness " + brightness
                    + " backlight " + backlight
                    + " nits " + nits
            );
        }
        return getHdrBrightnessFromSdrFromNits(nits, ratio);
    }

    /**
     * Calculate the HDR brightness for the specified SDR brightness
     *
     * @return the HDR brightness or BRIGHTNESS_INVALID when no mapping exists.
     */
    public float getHdrBrightnessFromSdr(float brightness, float hdrSdrRatio) {
        float backlight = getBacklightFromBrightness(brightness);
        float nits = getNitsFromBacklight(backlight);
        if (DEBUG) {
            Slog.d(TAG, "getHdrBrightnessFromSdr: sdr brightness " + brightness
                    + " backlight " + backlight
                    + " nits " + nits
            );
        }
        return getHdrBrightnessFromSdrFromNits(nits, hdrSdrRatio);
    }

    private float getHdrBrightnessFromSdrFromNits(float nits, float hdrSdrRatio) {
        if (nits == INVALID_NITS) {
            return PowerManager.BRIGHTNESS_INVALID;
        }
        float hdrNits = nits * hdrSdrRatio;
        if (getNitsToBacklightSpline() == null) {
            return PowerManager.BRIGHTNESS_INVALID;
        }

        float hdrBacklight = getBacklightFromNits(hdrNits);
        hdrBacklight = Math.max(mBacklightMinimum, Math.min(mBacklightMaximum, hdrBacklight));
        float hdrBrightness = getBrightnessFromBacklight(hdrBacklight);

        if (DEBUG) {
            Slog.d(TAG, "getHdrBrightnessFromSdr: sdr brightness " + brightness
                    + " backlight " + backlight
                    + " nits " + nits
                    + " ratio " + ratio
            Slog.d(TAG, "getHdrBrightnessFromSdr:"
                    + " hdrSdrRatio " + hdrSdrRatio
                    + " hdrNits " + hdrNits
                    + " hdrBacklight " + hdrBacklight
                    + " hdrBrightness " + hdrBrightness
+4 −3
Original line number Diff line number Diff line
@@ -4110,10 +4110,10 @@ public final class DisplayManagerService extends SystemService {
                SensorManager sensorManager, DisplayBlanker blanker, LogicalDisplay logicalDisplay,
                BrightnessTracker brightnessTracker, BrightnessSetting brightnessSetting,
                Runnable onBrightnessChangeRunnable, HighBrightnessModeMetadata hbmMetadata,
                boolean bootCompleted, DisplayManagerFlags flags) {
                boolean bootCompleted, DisplayManagerFlags flags, PluginManager pluginManager) {
            return new DisplayPowerController(context, injector, callbacks, handler, sensorManager,
                    blanker, logicalDisplay, brightnessTracker, brightnessSetting,
                    onBrightnessChangeRunnable, hbmMetadata, bootCompleted, flags);
                    onBrightnessChangeRunnable, hbmMetadata, bootCompleted, flags, pluginManager);
        }

        boolean isDesktopModeSupportedOnInternalDisplay(Context context) {
@@ -4178,7 +4178,8 @@ public final class DisplayManagerService extends SystemService {
        displayPowerController = mInjector.getDisplayPowerController(
                mContext, /* injector= */ null, mDisplayPowerCallbacks, mPowerHandler,
                mSensorManager, mDisplayBlanker, display, mBrightnessTracker, brightnessSetting,
                () -> handleBrightnessChange(display), hbmMetadata, mBootCompleted, mFlags);
                () -> handleBrightnessChange(display), hbmMetadata, mBootCompleted, mFlags,
                mPluginManager);
        mDisplayPowerControllers.append(display.getDisplayIdLocked(), displayPowerController);
        return displayPowerController;
    }
+6 −4
Original line number Diff line number Diff line
@@ -95,6 +95,7 @@ import com.android.server.display.config.HighBrightnessModeData;
import com.android.server.display.config.HysteresisLevels;
import com.android.server.display.feature.DisplayManagerFlags;
import com.android.server.display.layout.Layout;
import com.android.server.display.plugin.PluginManager;
import com.android.server.display.state.DisplayStateController;
import com.android.server.display.utils.DebugUtils;
import com.android.server.display.utils.SensorUtils;
@@ -515,7 +516,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
            SensorManager sensorManager, DisplayBlanker blanker, LogicalDisplay logicalDisplay,
            BrightnessTracker brightnessTracker, BrightnessSetting brightnessSetting,
            Runnable onBrightnessChangeRunnable, HighBrightnessModeMetadata hbmMetadata,
            boolean bootCompleted, DisplayManagerFlags flags) {
            boolean bootCompleted, DisplayManagerFlags flags, PluginManager pluginManager) {
        final Resources resources = context.getResources();

        mFlags = flags;
@@ -611,7 +612,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
                        thermalBrightnessThrottlingDataId,
                        logicalDisplay.getPowerThrottlingDataIdLocked(),
                        mDisplayDeviceConfig, displayDeviceInfo.width, displayDeviceInfo.height,
                        displayToken, mDisplayId), mContext, flags, mSensorManager,
                        displayToken, mDisplayId), mContext, flags, mSensorManager, pluginManager,
                        mDisplayBrightnessController.getCurrentBrightness());
        // Seed the cached brightness
        saveBrightnessInfo(getScreenBrightnessSetting());
@@ -3377,10 +3378,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
        BrightnessClamperController getBrightnessClamperController(Handler handler,
                BrightnessClamperController.ClamperChangeListener clamperChangeListener,
                BrightnessClamperController.DisplayDeviceData data, Context context,
                DisplayManagerFlags flags, SensorManager sensorManager, float currentBrightness) {
                DisplayManagerFlags flags, SensorManager sensorManager,
                PluginManager pluginManager, float currentBrightness) {

            return new BrightnessClamperController(handler, clamperChangeListener, data, context,
                    flags, sensorManager, currentBrightness);
                    flags, sensorManager, pluginManager, currentBrightness);
        }

        DisplayWhiteBalanceController getDisplayWhiteBalanceController(Handler handler,
+11 −7
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlin
import com.android.server.display.config.SensorData;
import com.android.server.display.feature.DeviceConfigParameterProvider;
import com.android.server.display.feature.DisplayManagerFlags;
import com.android.server.display.plugin.PluginManager;

import java.io.PrintWriter;
import java.util.ArrayList;
@@ -91,15 +92,17 @@ public class BrightnessClamperController {

    public BrightnessClamperController(Handler handler,
            ClamperChangeListener clamperChangeListener, DisplayDeviceData data, Context context,
            DisplayManagerFlags flags, SensorManager sensorManager, float currentBrightness) {
            DisplayManagerFlags flags, SensorManager sensorManager, PluginManager pluginManager,
            float currentBrightness) {
        this(new Injector(), handler, clamperChangeListener, data, context, flags, sensorManager,
                currentBrightness);
                pluginManager, currentBrightness);
    }

    @VisibleForTesting
    BrightnessClamperController(Injector injector, Handler handler,
            ClamperChangeListener clamperChangeListener, DisplayDeviceData data, Context context,
            DisplayManagerFlags flags, SensorManager sensorManager, float currentBrightness) {
            DisplayManagerFlags flags, SensorManager sensorManager, PluginManager pluginManager,
            float currentBrightness) {
        mDeviceConfigParameterProvider = injector.getDeviceConfigParameterProvider();
        mHandler = handler;
        mLightSensorController = injector.getLightSensorController(sensorManager, context,
@@ -115,8 +118,8 @@ public class BrightnessClamperController {
            }
        };

        mModifiers = injector.getModifiers(flags, context, handler, clamperChangeListenerInternal,
                data, currentBrightness);
        mModifiers = injector.getModifiers(flags, context, pluginManager, handler,
                clamperChangeListenerInternal, data, currentBrightness);

        mModifiers.forEach(
                m -> {
@@ -296,7 +299,7 @@ public class BrightnessClamperController {
        }

        List<BrightnessStateModifier> getModifiers(DisplayManagerFlags flags, Context context,
                Handler handler, ClamperChangeListener listener,
                PluginManager pluginManager, Handler handler, ClamperChangeListener listener,
                DisplayDeviceData data, float currentBrightness) {
            List<BrightnessStateModifier> modifiers = new ArrayList<>();
            modifiers.add(new BrightnessThermalModifier(handler, listener, data));
@@ -323,7 +326,8 @@ public class BrightnessClamperController {
                        data.mDisplayDeviceConfig));
            }
            if (flags.useNewHdrBrightnessModifier()) {
                modifiers.add(new HdrBrightnessModifier(handler, context, flags, listener, data));
                modifiers.add(new HdrBrightnessModifier(
                        handler, context, flags, pluginManager, listener, data));
            }
            return modifiers;
        }
+140 −32
Original line number Diff line number Diff line
@@ -40,9 +40,14 @@ import com.android.server.display.DisplayDeviceConfig;
import com.android.server.display.brightness.BrightnessReason;
import com.android.server.display.config.HdrBrightnessData;
import com.android.server.display.feature.DisplayManagerFlags;
import com.android.server.display.plugin.PluginManager;
import com.android.server.display.plugin.PluginType;
import com.android.server.display.plugin.types.HdrBoostOverride;


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

public class HdrBrightnessModifier implements BrightnessStateModifier,
        BrightnessClamperController.DisplayDeviceDataListener,
@@ -63,6 +68,13 @@ public class HdrBrightnessModifier implements BrightnessStateModifier,
                                    DEFAULT_MAX_HDR_SDR_RATIO) : DEFAULT_MAX_HDR_SDR_RATIO));
                }
            };
    private final PluginManager.PluginChangeListener<HdrBoostOverride> mHdrOverrideListener =
            new PluginManager.PluginChangeListener<>() {
                @Override
                public void onChanged(@Nullable HdrBoostOverride value) {
                    mHandler.post(() -> HdrBrightnessModifier.this.onHdrBoostOverride(value));
                }
            };

    private final Handler mHandler;
    private final BrightnessClamperController.ClamperChangeListener mClamperChangeListener;
@@ -70,7 +82,10 @@ public class HdrBrightnessModifier implements BrightnessStateModifier,
    private final DisplayManagerFlags mFlags;
    private final Runnable mDebouncer;

    // display token for HDRLayerListener subscription
    private IBinder mRegisteredDisplayToken;
    // unique displayId for PluginChangeListener subscription
    private String mRegisteredUniqueDisplayId;

    private DisplayDeviceConfig mDisplayDeviceConfig;
    @Nullable
@@ -85,6 +100,7 @@ public class HdrBrightnessModifier implements BrightnessStateModifier,
    private boolean mLowPowerMode = false;
    private final LowPowerModeSettingObserver mLowPowerModeSettingObserver;

    private @Nullable HdrBoostOverride mHdrBoostOverride = null;
    private Mode mMode = Mode.NO_HDR;
    // The maximum brightness allowed for current lux
    private float mMaxBrightness = PowerManager.BRIGHTNESS_MAX;
@@ -98,10 +114,11 @@ public class HdrBrightnessModifier implements BrightnessStateModifier,
    private final HdrSettingsObserver mHdrSettingsObserver;

    HdrBrightnessModifier(Handler handler, Context context, DisplayManagerFlags flags,
            PluginManager pluginManager,
            BrightnessClamperController.ClamperChangeListener clamperChangeListener,
            BrightnessClamperController.DisplayDeviceData displayData) {
        this(new Handler(handler.getLooper()), flags, clamperChangeListener,
                new Injector(context), displayData);
                new Injector(context, pluginManager), displayData);
    }

    @VisibleForTesting
@@ -132,6 +149,17 @@ public class HdrBrightnessModifier implements BrightnessStateModifier,
        if (mMode == Mode.NO_HDR) {
            return;
        }
        if (mMode == Mode.OVERRIDE_HDR && mHdrBoostOverride != null) {
            float hdrBrightness = mDisplayDeviceConfig.getHdrBrightnessFromSdr(
                    stateBuilder.getBrightness(), mHdrBoostOverride.sdrHdrRatio());
            hdrBrightness = Math.min(hdrBrightness, mHdrBoostOverride.maxHdrBrightness());

            stateBuilder.setHdrBrightness(hdrBrightness);
            stateBuilder.setCustomAnimationRate(mTransitionRate);
            stateBuilder.getBrightnessReason().addModifier(BrightnessReason.MODIFIER_HDR);
            // transition rate applied, reset
            mTransitionRate = CUSTOM_ANIMATION_RATE_NOT_SET;
        } else if (isNbmOrHbmHdr()) {
            float hdrBrightness = mDisplayDeviceConfig.getHdrBrightnessFromSdr(
                    stateBuilder.getBrightness(), mMaxDesiredHdrRatio, getRatioScaleFactor(),
                    mHdrBrightnessData.sdrToHdrRatioSpline);
@@ -141,10 +169,10 @@ public class HdrBrightnessModifier implements BrightnessStateModifier,
            stateBuilder.setHdrBrightness(hdrBrightness);
            stateBuilder.setCustomAnimationRate(mTransitionRate);
            stateBuilder.getBrightnessReason().addModifier(BrightnessReason.MODIFIER_HDR);

            // transition rate applied, reset
            mTransitionRate = CUSTOM_ANIMATION_RATE_NOT_SET;
        }
    }

    @Override
    public void dump(PrintWriter pw) {
@@ -161,18 +189,21 @@ public class HdrBrightnessModifier implements BrightnessStateModifier,
        pw.println("  mTransitionRate=" + mTransitionRate);
        pw.println("  mPendingTransitionRate=" + mPendingTransitionRate);
        pw.println("  mHdrListener registered=" + (mRegisteredDisplayToken != null));
        pw.println("  mHdrOverrideListener registered=" + (mRegisteredUniqueDisplayId != null));
        pw.println("  mLowPowerModeSettingObserver.mRegistered="
                + mLowPowerModeSettingObserver.mRegistered);
        pw.println("  mHdrSettingsObserver.mRegistered=" + mHdrSettingsObserver.mRegistered);
        pw.println("  mHdrBrightnessEnabled=" + mHdrBrightnessEnabled);
        pw.println("  mHdrBrightnessBoostLevel=" + mHdrBrightnessBoostLevel);
        pw.println("  ratioScaleFactor=" + getRatioScaleFactor());
        pw.println("  mHdrBoostOverride=" + mHdrBoostOverride);
    }

    // Called in DisplayControllerHandler
    @Override
    public void stop() {
        unregisterHdrListener();
        unregisterHdrBoostOverrideListener();
        mLowPowerModeSettingObserver.unregister();
        mHdrSettingsObserver.unregister();
        mHandler.removeCallbacksAndMessages(null);
@@ -192,7 +223,7 @@ public class HdrBrightnessModifier implements BrightnessStateModifier,
            return;
        }
        float desiredMaxBrightness = findBrightnessLimit(mHdrBrightnessData, lux);
        if (mMode == Mode.NO_HDR) {
        if (!isNbmOrHbmHdr()) {
            mMaxBrightness = desiredMaxBrightness;
        } else {
            scheduleMaxBrightnessUpdate(desiredMaxBrightness, mHdrBrightnessData);
@@ -207,9 +238,11 @@ public class HdrBrightnessModifier implements BrightnessStateModifier,
        HdrBrightnessData data = mDisplayDeviceConfig.getHdrBrightnessData();
        if (data == null) {
            unregisterHdrListener();
            unregisterHdrBoostOverrideListener();
            mHdrSettingsObserver.unregister();
        } else {
            registerHdrListener(displayData.mDisplayToken);
            registerHdrBoostOverrideListener(displayData.getUniqueDisplayId());
            if (mFlags.isHdrBrightnessSettingEnabled()) {
                mHdrSettingsObserver.register();
            }
@@ -220,10 +253,10 @@ public class HdrBrightnessModifier implements BrightnessStateModifier,
            mLowPowerModeSettingObserver.register();
        }

        Mode newMode = recalculateMode(data);
        Mode newMode = recalculateMode(data, mHdrBoostOverride);
        // mode changed, or mode was HDR  and HdrBrightnessData changed
        boolean needToNotifyChange = mMode != newMode
                || (mMode != Mode.NO_HDR && data != mHdrBrightnessData);
                || (isNbmOrHbmHdr() && data != mHdrBrightnessData);
        mMode = newMode;
        mHdrBrightnessData = data;
        mMaxBrightness = findBrightnessLimit(mHdrBrightnessData, mAmbientLux);
@@ -239,7 +272,10 @@ public class HdrBrightnessModifier implements BrightnessStateModifier,
    @Override
    public void applyStateChange(
            BrightnessClamperController.ModifiersAggregatedState aggregatedState) {
        if (mMode != Mode.NO_HDR && mHdrBrightnessData != null) {
        if (mMode == Mode.OVERRIDE_HDR && mHdrBoostOverride != null) {
            aggregatedState.mMaxDesiredHdrRatio = mHdrBoostOverride.sdrHdrRatio();
            aggregatedState.mMaxHdrBrightness = mHdrBoostOverride.maxHdrBrightness();
        } else if (isNbmOrHbmHdr() && mHdrBrightnessData != null) {
            aggregatedState.mMaxDesiredHdrRatio = mMaxDesiredHdrRatio;
            aggregatedState.mSdrHdrRatioSpline = mHdrBrightnessData.sdrToHdrRatioSpline;
            aggregatedState.mMaxHdrBrightness = getMaxBrightness(
@@ -248,6 +284,21 @@ public class HdrBrightnessModifier implements BrightnessStateModifier,
        }
    }

    // Called in DisplayControllerHandler
    private void onHdrBoostOverride(@Nullable HdrBoostOverride hdrBoostOverride) {
        Mode newMode = recalculateMode(mHdrBrightnessData, hdrBoostOverride);
        boolean needToNotifyChange = newMode != mMode
                || !Objects.equals(mHdrBoostOverride, hdrBoostOverride);
        mMode = newMode;
        mHdrBoostOverride = hdrBoostOverride;
        if (needToNotifyChange) {
            if (mHdrBoostOverride != null) {
                mTransitionRate = mHdrBoostOverride.customTransitionRate();
            }
            mClamperChangeListener.onChanged();
        }
    }

    private boolean hasBrightnessLimits() {
        return mHdrBrightnessData != null && !mHdrBrightnessData.maxBrightnessLimits.isEmpty();
    }
@@ -255,8 +306,8 @@ public class HdrBrightnessModifier implements BrightnessStateModifier,
    private void scheduleMaxBrightnessUpdate(float desiredMaxBrightness, HdrBrightnessData data) {
        if (mMaxBrightness == desiredMaxBrightness) {
            mPendingMaxBrightness = mMaxBrightness;
            mPendingTransitionRate = -1f;
            mTransitionRate = -1f;
            mPendingTransitionRate = CUSTOM_ANIMATION_RATE_NOT_SET;
            mTransitionRate = CUSTOM_ANIMATION_RATE_NOT_SET;
            mHandler.removeCallbacks(mDebouncer);
        } else if (mPendingMaxBrightness != desiredMaxBrightness) {
            mPendingMaxBrightness = desiredMaxBrightness;
@@ -277,7 +328,8 @@ public class HdrBrightnessModifier implements BrightnessStateModifier,
    }

    // Called in DisplayControllerHandler
    private Mode recalculateMode(@Nullable HdrBrightnessData data) {
    private Mode recalculateMode(@Nullable HdrBrightnessData data,
            @Nullable HdrBoostOverride hdrBoostOverride) {
        // no config
        if (data == null) {
            return Mode.NO_HDR;
@@ -294,6 +346,18 @@ public class HdrBrightnessModifier implements BrightnessStateModifier,
        if (mHdrLayerSize < mScreenSize * data.minimumHdrPercentOfScreenForNbm) {
            return Mode.NO_HDR;
        }
        // HDR brightness boost disabled from settings
        if (!mHdrBrightnessEnabled) {
            return Mode.NO_HDR;
        }
        // HDR boost overridden and OFF
        if (hdrBoostOverride != null && hdrBoostOverride.sdrHdrRatio() < 1) {
            return Mode.NO_HDR;
        }
        // HDR boost overridden
        if (hdrBoostOverride != null) {
            return Mode.OVERRIDE_HDR;
        }
        // HDR layer < minHdr % for Hbm, and HDR layer >= that minHdr % for Nbm
        if (mHdrLayerSize < mScreenSize * data.minimumHdrPercentOfScreenForHbm) {
            return Mode.NBM_HDR;
@@ -337,10 +401,10 @@ public class HdrBrightnessModifier implements BrightnessStateModifier,
    // Called in DisplayControllerHandler
    private void onHdrInfoChanged(float hdrLayerSize, float maxDesiredHdrSdrRatio) {
        mHdrLayerSize = hdrLayerSize;
        Mode newMode = recalculateMode(mHdrBrightnessData);
        Mode newMode = recalculateMode(mHdrBrightnessData, mHdrBoostOverride);
        // mode changed, or mode was HDR  and maxDesiredHdrRatio changed
        boolean needToNotifyChange = mMode != newMode
                || (mMode != HdrBrightnessModifier.Mode.NO_HDR
                || (isNbmOrHbmHdr()
                && !BrightnessSynchronizer.floatEquals(mMaxDesiredHdrRatio, maxDesiredHdrSdrRatio));
        mMode = newMode;
        mMaxDesiredHdrRatio = maxDesiredHdrSdrRatio;
@@ -371,17 +435,40 @@ public class HdrBrightnessModifier implements BrightnessStateModifier,
        }
    }

    // Called in DisplayControllerHandler
    private void registerHdrBoostOverrideListener(String uniqueDisplayId) {
        if (Objects.equals(mRegisteredUniqueDisplayId, uniqueDisplayId)) {
            return;
        }
        unregisterHdrBoostOverrideListener();
        if (uniqueDisplayId != null) {
            mInjector.registerHdrBoostOverrideListener(uniqueDisplayId, mHdrOverrideListener);
            mRegisteredUniqueDisplayId = uniqueDisplayId;
        }
    }

    // Called in DisplayControllerHandler
    private void unregisterHdrBoostOverrideListener() {
        if (mRegisteredUniqueDisplayId != null) {
            mInjector.unregisterHdrBoostOverrideListener(
                    mRegisteredUniqueDisplayId, mHdrOverrideListener);
            mRegisteredUniqueDisplayId = null;
            mHdrBoostOverride = null;
        }

    }

    private float getRatioScaleFactor() {
        if (mFlags.isHdrBrightnessSettingEnabled()) {
            return mHdrBrightnessEnabled ? BrightnessUtils.convertGammaToLinear(
                    mHdrBrightnessBoostLevel) : 0;
        } else {
            return 1;
        return mFlags.isHdrBrightnessSettingEnabled() ? BrightnessUtils
                .convertGammaToLinear(mHdrBrightnessBoostLevel) : 1;
    }

    private boolean isNbmOrHbmHdr() {
        return mMode == Mode.NBM_HDR || mMode == Mode.HBM_HDR;
    }

    private enum Mode {
        NO_HDR, NBM_HDR, HBM_HDR
        NO_HDR, NBM_HDR, HBM_HDR, OVERRIDE_HDR
    }

    private final class LowPowerModeSettingObserver extends ContentObserver {
@@ -414,9 +501,10 @@ public class HdrBrightnessModifier implements BrightnessStateModifier,
            }
        }

        // Called in DisplayControllerHandler
        private void onLowPowerModeChange() {
            mLowPowerMode = mInjector.isLowPowerMode();
            Mode newMode = recalculateMode(mHdrBrightnessData);
            Mode newMode = recalculateMode(mHdrBrightnessData, mHdrBoostOverride);
            if (newMode != mMode) {
                mMode = newMode;
                mTransitionRate = CUSTOM_ANIMATION_RATE_NOT_SET;
@@ -464,17 +552,22 @@ public class HdrBrightnessModifier implements BrightnessStateModifier,
            }
        }

        // Called in DisplayControllerHandler
        private void updateHdrBrightnessEnabled() {
            mHdrBrightnessEnabled = mInjector.isHdrBrightnessEnabled();
            if (mMode != Mode.NO_HDR) {
            Mode newMode = recalculateMode(mHdrBrightnessData, mHdrBoostOverride);
            if (newMode != mMode) {
                mMode = newMode;
                mTransitionRate = CUSTOM_ANIMATION_RATE_NOT_SET;
                mClamperChangeListener.onChanged();
            }
        }

        // Called in DisplayControllerHandler
        private void updateHdrBrightnessBoostLevel() {
            mHdrBrightnessBoostLevel = mInjector.getHdrBrightnessBoostLevel();
            if (mMode != Mode.NO_HDR) {
            // boost level changed from settings
            if (isNbmOrHbmHdr()) {
                mTransitionRate = CUSTOM_ANIMATION_RATE_NOT_SET;
                mClamperChangeListener.onChanged();
            }
@@ -484,9 +577,24 @@ public class HdrBrightnessModifier implements BrightnessStateModifier,
    @SuppressLint("MissingPermission")
    static class Injector {
        private final Context mContext;
        private final PluginManager mPluginManager;

        Injector(Context context) {
        Injector(Context context, PluginManager pluginManager) {
            mContext = context;
            mPluginManager = pluginManager;
        }

        void registerHdrBoostOverrideListener(String uniqueDisplayId,
                PluginManager.PluginChangeListener<HdrBoostOverride> hdrOverrideListener) {
            // TODO(b/426122363): subscribe with handler
            mPluginManager.subscribe(
                    PluginType.HDR_BOOST_OVERRIDE, uniqueDisplayId, hdrOverrideListener);
        }

        void unregisterHdrBoostOverrideListener(String uniqueDisplayId,
                PluginManager.PluginChangeListener<HdrBoostOverride> hdrOverrideListener) {
            mPluginManager.unsubscribe(
                    PluginType.HDR_BOOST_OVERRIDE, uniqueDisplayId, hdrOverrideListener);
        }

        void registerHdrListener(SurfaceControlHdrLayerInfoListener listener, IBinder token) {
Loading