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

Commit 682503a3 authored by petsjonkin's avatar petsjonkin Committed by Oleg Petšjonkin
Browse files

Max brightness fix in normal brightness mode and HDR content shown

Fixed inconsistency in HBMController and BrightnessRangeControlller current maxBrightness selection
Before: BrightnessRangeController was taking into account NBC only if HBMController mode was HBM_OFF,
However HBMController was selecting transitionPoint as maxBrightness aslo in case e.g. HDR was shown, or low power mode.
Now: BrightnessRangeController takes into account NBC in sync with HBMController

Bug: b/326872826
Test: atest BrightnessRangeControllerTest, manually tested brightness slider behavior
Change-Id: I9071b27769b6a357ca9b2b7f6aa609ab0672467e
(cherry picked from commit 7d313a09)
parent ce4f1155
Loading
Loading
Loading
Loading
+11 −4
Original line number Original line Diff line number Diff line
@@ -21,6 +21,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.PowerManager;


import com.android.internal.annotations.VisibleForTesting;
import com.android.server.display.brightness.clamper.HdrClamper;
import com.android.server.display.brightness.clamper.HdrClamper;
import com.android.server.display.feature.DisplayManagerFlags;
import com.android.server.display.feature.DisplayManagerFlags;


@@ -30,8 +31,7 @@ import java.util.function.BooleanSupplier;
class BrightnessRangeController {
class BrightnessRangeController {


    private final HighBrightnessModeController mHbmController;
    private final HighBrightnessModeController mHbmController;
    private final NormalBrightnessModeController mNormalBrightnessModeController =
    private final NormalBrightnessModeController mNormalBrightnessModeController;
            new NormalBrightnessModeController();


    private final HdrClamper mHdrClamper;
    private final HdrClamper mHdrClamper;


@@ -45,17 +45,21 @@ class BrightnessRangeController {
            Runnable modeChangeCallback, DisplayDeviceConfig displayDeviceConfig, Handler handler,
            Runnable modeChangeCallback, DisplayDeviceConfig displayDeviceConfig, Handler handler,
            DisplayManagerFlags flags, IBinder displayToken, DisplayDeviceInfo info) {
            DisplayManagerFlags flags, IBinder displayToken, DisplayDeviceInfo info) {
        this(hbmController, modeChangeCallback, displayDeviceConfig,
        this(hbmController, modeChangeCallback, displayDeviceConfig,
                new NormalBrightnessModeController(),
                new HdrClamper(modeChangeCallback::run, new Handler(handler.getLooper())), flags,
                new HdrClamper(modeChangeCallback::run, new Handler(handler.getLooper())), flags,
                displayToken, info);
                displayToken, info);
    }
    }


    @VisibleForTesting
    BrightnessRangeController(HighBrightnessModeController hbmController,
    BrightnessRangeController(HighBrightnessModeController hbmController,
            Runnable modeChangeCallback, DisplayDeviceConfig displayDeviceConfig,
            Runnable modeChangeCallback, DisplayDeviceConfig displayDeviceConfig,
            NormalBrightnessModeController normalBrightnessModeController,
            HdrClamper hdrClamper, DisplayManagerFlags flags, IBinder displayToken,
            HdrClamper hdrClamper, DisplayManagerFlags flags, IBinder displayToken,
            DisplayDeviceInfo info) {
            DisplayDeviceInfo info) {
        mHbmController = hbmController;
        mHbmController = hbmController;
        mModeChangeCallback = modeChangeCallback;
        mModeChangeCallback = modeChangeCallback;
        mHdrClamper = hdrClamper;
        mHdrClamper = hdrClamper;
        mNormalBrightnessModeController = normalBrightnessModeController;
        mUseHdrClamper = flags.isHdrClamperEnabled();
        mUseHdrClamper = flags.isHdrClamperEnabled();
        mUseNbmController = flags.isNbmControllerEnabled();
        mUseNbmController = flags.isNbmControllerEnabled();
        if (mUseNbmController) {
        if (mUseNbmController) {
@@ -126,8 +130,11 @@ class BrightnessRangeController {




    float getCurrentBrightnessMax() {
    float getCurrentBrightnessMax() {
        if (mUseNbmController && mHbmController.getHighBrightnessMode()
        // nbmController might adjust maxBrightness only if device does not support HBM or
                == BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF) {
        // hbm is currently not allowed
        if (mUseNbmController
                && (!mHbmController.deviceSupportsHbm()
                || !mHbmController.isHbmCurrentlyAllowed())) {
            return Math.min(mHbmController.getCurrentBrightnessMax(),
            return Math.min(mHbmController.getCurrentBrightnessMax(),
                    mNormalBrightnessModeController.getCurrentBrightnessMax());
                    mNormalBrightnessModeController.getCurrentBrightnessMax());
        }
        }
+5 −5
Original line number Original line Diff line number Diff line
@@ -168,7 +168,7 @@ class HighBrightnessModeController {
    }
    }


    float getCurrentBrightnessMax() {
    float getCurrentBrightnessMax() {
        if (!deviceSupportsHbm() || isCurrentlyAllowed()) {
        if (!deviceSupportsHbm() || isHbmCurrentlyAllowed()) {
            // Either the device doesn't support HBM, or HBM range is currently allowed (device
            // Either the device doesn't support HBM, or HBM range is currently allowed (device
            // it in a high-lux environment). In either case, return the highest brightness
            // it in a high-lux environment). In either case, return the highest brightness
            // level supported by the device.
            // level supported by the device.
@@ -356,7 +356,7 @@ class HighBrightnessModeController {
        return event.getStartTimeMillis();
        return event.getStartTimeMillis();
    }
    }


    private boolean isCurrentlyAllowed() {
    boolean isHbmCurrentlyAllowed() {
        // Returns true if HBM is allowed (above the ambient lux threshold) and there's still
        // Returns true if HBM is allowed (above the ambient lux threshold) and there's still
        // time within the current window for additional HBM usage. We return false if there is an
        // time within the current window for additional HBM usage. We return false if there is an
        // HDR layer because we don't want the brightness MAX to change for HDR, which has its
        // HDR layer because we don't want the brightness MAX to change for HDR, which has its
@@ -369,7 +369,7 @@ class HighBrightnessModeController {
                && !mIsBlockedByLowPowerMode);
                && !mIsBlockedByLowPowerMode);
    }
    }


    private boolean deviceSupportsHbm() {
    boolean deviceSupportsHbm() {
        return mHbmData != null && mHighBrightnessModeMetadata != null;
        return mHbmData != null && mHighBrightnessModeMetadata != null;
    }
    }


@@ -462,7 +462,7 @@ class HighBrightnessModeController {
                    + ", isOnlyAllowedToStayOn: " + isOnlyAllowedToStayOn
                    + ", isOnlyAllowedToStayOn: " + isOnlyAllowedToStayOn
                    + ", remainingAllowedTime: " + remainingTime
                    + ", remainingAllowedTime: " + remainingTime
                    + ", isLuxHigh: " + mIsInAllowedAmbientRange
                    + ", isLuxHigh: " + mIsInAllowedAmbientRange
                    + ", isHBMCurrentlyAllowed: " + isCurrentlyAllowed()
                    + ", isHBMCurrentlyAllowed: " + isHbmCurrentlyAllowed()
                    + ", isHdrLayerPresent: " + mIsHdrLayerPresent
                    + ", isHdrLayerPresent: " + mIsHdrLayerPresent
                    + ", mMaxDesiredHdrSdrRatio: " + mMaxDesiredHdrSdrRatio
                    + ", mMaxDesiredHdrSdrRatio: " + mMaxDesiredHdrSdrRatio
                    + ", isAutoBrightnessEnabled: " +  mIsAutoBrightnessEnabled
                    + ", isAutoBrightnessEnabled: " +  mIsAutoBrightnessEnabled
@@ -575,7 +575,7 @@ class HighBrightnessModeController {
            return BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF;
            return BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF;
        } else if (mIsHdrLayerPresent) {
        } else if (mIsHdrLayerPresent) {
            return BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR;
            return BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR;
        } else if (isCurrentlyAllowed()) {
        } else if (isHbmCurrentlyAllowed()) {
            return BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT;
            return BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT;
        }
        }


+95 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.display

import android.os.IBinder
import androidx.test.filters.SmallTest
import com.android.server.display.brightness.clamper.HdrClamper
import com.android.server.display.feature.DisplayManagerFlags
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever

private const val MAX_BRIGHTNESS = 1.0f
private const val TRANSITION_POINT = 0.7f
private const val NORMAL_BRIGHTNESS_HIGH = 0.8f
private const val NORMAL_BRIGHTNESS_LOW = 0.6f

@SmallTest
class BrightnessRangeControllerTest {

    private val mockHbmController = mock<HighBrightnessModeController>()
    private val mockCallback = mock<Runnable>()
    private val mockConfig = mock<DisplayDeviceConfig>()
    private val mockNormalBrightnessController = mock<NormalBrightnessModeController>()
    private val mockHdrClamper = mock<HdrClamper>()
    private val mockFlags = mock<DisplayManagerFlags>()
    private val mockToken = mock<IBinder>()

    @Test
    fun `returns HBC max brightness if HBM supported and ON`() {
        val controller = createController()
        assertThat(controller.currentBrightnessMax).isEqualTo(MAX_BRIGHTNESS)
    }

    @Test
    fun `returns NBC max brightness if device does not support HBM`() {
        val controller = createController(hbmSupported = false)
        assertThat(controller.currentBrightnessMax).isEqualTo(NORMAL_BRIGHTNESS_LOW)
    }

    @Test
    fun `returns NBC max brightness if HBM not allowed`() {
        val controller = createController(hbmAllowed = false)
        assertThat(controller.currentBrightnessMax).isEqualTo(NORMAL_BRIGHTNESS_LOW)
    }

    @Test
    fun `returns HBC max brightness if NBM is disabled`() {
        val controller = createController(nbmEnabled = false, hbmAllowed = false)
        assertThat(controller.currentBrightnessMax).isEqualTo(MAX_BRIGHTNESS)
    }

    @Test
    fun `returns HBC max brightness if lower than NBC max brightness`() {
        val controller = createController(
            hbmAllowed = false,
            hbmMaxBrightness = TRANSITION_POINT,
            nbmMaxBrightness = NORMAL_BRIGHTNESS_HIGH
        )
        assertThat(controller.currentBrightnessMax).isEqualTo(TRANSITION_POINT)
    }

    private fun createController(
        nbmEnabled: Boolean = true,
        hbmSupported: Boolean = true,
        hbmAllowed: Boolean = true,
        hbmMaxBrightness: Float = MAX_BRIGHTNESS,
        nbmMaxBrightness: Float = NORMAL_BRIGHTNESS_LOW
    ): BrightnessRangeController {
        whenever(mockFlags.isNbmControllerEnabled).thenReturn(nbmEnabled)
        whenever(mockHbmController.deviceSupportsHbm()).thenReturn(hbmSupported)
        whenever(mockHbmController.isHbmCurrentlyAllowed).thenReturn(hbmAllowed)
        whenever(mockHbmController.currentBrightnessMax).thenReturn(hbmMaxBrightness)
        whenever(mockNormalBrightnessController.currentBrightnessMax).thenReturn(nbmMaxBrightness)

        return BrightnessRangeController(mockHbmController, mockCallback, mockConfig,
            mockNormalBrightnessController, mockHdrClamper, mockFlags, mockToken,
            DisplayDeviceInfo())
    }
}
 No newline at end of file
+10 −2
Original line number Original line Diff line number Diff line
@@ -1850,6 +1850,8 @@ public final class DisplayPowerControllerTest {
                mock(ScreenOffBrightnessSensorController.class);
                mock(ScreenOffBrightnessSensorController.class);
        final HighBrightnessModeController hbmController = mock(HighBrightnessModeController.class);
        final HighBrightnessModeController hbmController = mock(HighBrightnessModeController.class);
        final HdrClamper hdrClamper = mock(HdrClamper.class);
        final HdrClamper hdrClamper = mock(HdrClamper.class);
        final NormalBrightnessModeController normalBrightnessModeController = mock(
                NormalBrightnessModeController.class);
        BrightnessClamperController clamperController = mock(BrightnessClamperController.class);
        BrightnessClamperController clamperController = mock(BrightnessClamperController.class);


        when(hbmController.getCurrentBrightnessMax()).thenReturn(PowerManager.BRIGHTNESS_MAX);
        when(hbmController.getCurrentBrightnessMax()).thenReturn(PowerManager.BRIGHTNESS_MAX);
@@ -1862,7 +1864,8 @@ public final class DisplayPowerControllerTest {


        TestInjector injector = spy(new TestInjector(displayPowerState, animator,
        TestInjector injector = spy(new TestInjector(displayPowerState, animator,
                automaticBrightnessController, wakelockController, brightnessMappingStrategy,
                automaticBrightnessController, wakelockController, brightnessMappingStrategy,
                hysteresisLevels, screenOffBrightnessSensorController, hbmController, hdrClamper,
                hysteresisLevels, screenOffBrightnessSensorController,
                hbmController, normalBrightnessModeController, hdrClamper,
                clamperController, mDisplayManagerFlagsMock));
                clamperController, mDisplayManagerFlagsMock));


        final LogicalDisplay display = mock(LogicalDisplay.class);
        final LogicalDisplay display = mock(LogicalDisplay.class);
@@ -1950,6 +1953,8 @@ public final class DisplayPowerControllerTest {
        private final ScreenOffBrightnessSensorController mScreenOffBrightnessSensorController;
        private final ScreenOffBrightnessSensorController mScreenOffBrightnessSensorController;
        private final HighBrightnessModeController mHighBrightnessModeController;
        private final HighBrightnessModeController mHighBrightnessModeController;


        private final NormalBrightnessModeController mNormalBrightnessModeController;

        private final HdrClamper mHdrClamper;
        private final HdrClamper mHdrClamper;


        private final BrightnessClamperController mClamperController;
        private final BrightnessClamperController mClamperController;
@@ -1963,6 +1968,7 @@ public final class DisplayPowerControllerTest {
                HysteresisLevels hysteresisLevels,
                HysteresisLevels hysteresisLevels,
                ScreenOffBrightnessSensorController screenOffBrightnessSensorController,
                ScreenOffBrightnessSensorController screenOffBrightnessSensorController,
                HighBrightnessModeController highBrightnessModeController,
                HighBrightnessModeController highBrightnessModeController,
                NormalBrightnessModeController normalBrightnessModeController,
                HdrClamper hdrClamper,
                HdrClamper hdrClamper,
                BrightnessClamperController clamperController,
                BrightnessClamperController clamperController,
                DisplayManagerFlags flags) {
                DisplayManagerFlags flags) {
@@ -1974,6 +1980,7 @@ public final class DisplayPowerControllerTest {
            mHysteresisLevels = hysteresisLevels;
            mHysteresisLevels = hysteresisLevels;
            mScreenOffBrightnessSensorController = screenOffBrightnessSensorController;
            mScreenOffBrightnessSensorController = screenOffBrightnessSensorController;
            mHighBrightnessModeController = highBrightnessModeController;
            mHighBrightnessModeController = highBrightnessModeController;
            mNormalBrightnessModeController = normalBrightnessModeController;
            mHdrClamper = hdrClamper;
            mHdrClamper = hdrClamper;
            mClamperController = clamperController;
            mClamperController = clamperController;
            mFlags = flags;
            mFlags = flags;
@@ -2086,7 +2093,8 @@ public final class DisplayPowerControllerTest {
                DisplayDeviceConfig displayDeviceConfig, Handler handler,
                DisplayDeviceConfig displayDeviceConfig, Handler handler,
                DisplayManagerFlags flags, IBinder displayToken, DisplayDeviceInfo info) {
                DisplayManagerFlags flags, IBinder displayToken, DisplayDeviceInfo info) {
            return new BrightnessRangeController(hbmController, modeChangeCallback,
            return new BrightnessRangeController(hbmController, modeChangeCallback,
                    displayDeviceConfig, mHdrClamper, mFlags, displayToken, info);
                    displayDeviceConfig, mNormalBrightnessModeController, mHdrClamper,
                    mFlags, displayToken, info);
        }
        }


        @Override
        @Override