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

Commit 7bbb49fb authored by John Reck's avatar John Reck
Browse files

Fix that changes in desiredHdrSdrRatio doesn't update brightness

When onHdrInfoChanged is received from SF and the resulting
maxDesiredHdrSdrRatio changes ensure that the hbmChanged
callback is invoked even though the high-level mode did not
otherwise change. Otherwise the display brightness does not
react to the change, and so changes in the desired HDR headroom
does not result in changes to the actual display brightness.

Bug: 234181960
Test: HighBrightnessModeControllerTest#testHdrRespectsChangingDesiredHdrSdrRatio
Change-Id: I41f8062781493a73d4f1752c6c88d38dfad74909
parent af3eb24f
Loading
Loading
Loading
Loading
+16 −6
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.MathUtils;
@@ -33,6 +34,7 @@ import android.util.TimeUtils;
import android.view.SurfaceControlHdrLayerInfoListener;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.display.BrightnessSynchronizer;
import com.android.internal.util.FrameworkStatsLog;
import com.android.server.display.DisplayDeviceConfig.HighBrightnessModeData;
import com.android.server.display.DisplayManagerService.Clock;
@@ -99,6 +101,7 @@ class HighBrightnessModeController {
    private boolean mIsHdrLayerPresent = false;
    // mMaxDesiredHdrSdrRatio should only be applied when there is a valid backlight->nits mapping
    private float mMaxDesiredHdrSdrRatio = DEFAULT_MAX_DESIRED_HDR_SDR_RATIO;
    private boolean mForceHbmChangeCallback = false;
    private boolean mIsBlockedByLowPowerMode = false;
    private int mWidth;
    private int mHeight;
@@ -484,7 +487,8 @@ class HighBrightnessModeController {
    private void updateHbmMode() {
        int newHbmMode = calculateHighBrightnessMode();
        updateHbmStats(newHbmMode);
        if (mHbmMode != newHbmMode) {
        if (mHbmMode != newHbmMode || mForceHbmChangeCallback) {
            mForceHbmChangeCallback = false;
            mHbmMode = newHbmMode;
            mHbmChangeCallback.run();
        }
@@ -600,26 +604,32 @@ class HighBrightnessModeController {
        public void onHdrInfoChanged(IBinder displayToken, int numberOfHdrLayers,
                int maxW, int maxH, int flags, float maxDesiredHdrSdrRatio) {
            mHandler.post(() -> {
                Trace.traceBegin(Trace.TRACE_TAG_POWER, "HBMController#onHdrInfoChanged");
                mIsHdrLayerPresent = numberOfHdrLayers > 0
                        && (float) (maxW * maxH) >= ((float) (mWidth * mHeight)
                                   * mHbmData.minimumHdrPercentOfScreen);

                final float candidateDesiredHdrSdrRatio =
                float candidateDesiredHdrSdrRatio =
                        mIsHdrLayerPresent && mHdrBrightnessCfg != null
                                ? maxDesiredHdrSdrRatio
                                : DEFAULT_MAX_DESIRED_HDR_SDR_RATIO;

                if (candidateDesiredHdrSdrRatio >= 1.0f) {
                    mMaxDesiredHdrSdrRatio = candidateDesiredHdrSdrRatio;
                } else {
                if (candidateDesiredHdrSdrRatio < 1.0f) {
                    Slog.w(TAG, "Ignoring invalid desired HDR/SDR Ratio: "
                            + candidateDesiredHdrSdrRatio);
                    mMaxDesiredHdrSdrRatio = DEFAULT_MAX_DESIRED_HDR_SDR_RATIO;
                    candidateDesiredHdrSdrRatio = DEFAULT_MAX_DESIRED_HDR_SDR_RATIO;
                }

                if (!BrightnessSynchronizer.floatEquals(
                        mMaxDesiredHdrSdrRatio, candidateDesiredHdrSdrRatio)) {
                    mForceHbmChangeCallback = true;
                    mMaxDesiredHdrSdrRatio = candidateDesiredHdrSdrRatio;
                }

                // Calling the brightness update so that we can recalculate
                // brightness with HDR in mind.
                onBrightnessChanged(mBrightness, mUnthrottledBrightness, mThrottlingReason);
                Trace.traceEnd(Trace.TRACE_TAG_POWER);
            });
        }
    }
+39 −2
Original line number Diff line number Diff line
@@ -32,8 +32,10 @@ import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.anyFloat;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@@ -390,6 +392,35 @@ public class HighBrightnessModeControllerTest {
        assertEquals(Float.POSITIVE_INFINITY, hbmc.getHdrBrightnessValue(), 0.0);
    }

    @Test
    public void testHdrRespectsChangingDesiredHdrSdrRatio() {
        final Runnable hbmChangedCallback = mock(Runnable.class);
        final HighBrightnessModeController hbmc = new TestHbmBuilder()
                .setClock(new OffsettableClock())
                .setHdrBrightnessConfig(mHdrBrightnessDeviceConfigMock)
                .setHbmChangedCallback(hbmChangedCallback)
                .build();

        // Passthrough return the max desired hdr/sdr ratio
        when(mHdrBrightnessDeviceConfigMock.getHdrBrightnessFromSdr(anyFloat(), anyFloat()))
                .thenAnswer(i -> i.getArgument(1));

        hbmc.getHdrListener().onHdrInfoChanged(null /*displayToken*/, 1 /*numberOfHdrLayers*/,
                DISPLAY_WIDTH, DISPLAY_HEIGHT, 0 /*flags*/, 2.0f /*maxDesiredHdrSdrRatio*/);
        advanceTime(0);
        assertEquals(2.0f, hbmc.getHdrBrightnessValue(), EPSILON);
        verify(hbmChangedCallback, times(1)).run();

        // Verify that a change in only the desired hdrSdrRatio still results in the changed
        // callback being invoked
        hbmc.getHdrListener().onHdrInfoChanged(null /*displayToken*/, 1 /*numberOfHdrLayers*/,
                DISPLAY_WIDTH, DISPLAY_HEIGHT, 0 /*flags*/,
                3.0f /*maxDesiredHdrSdrRatio*/);
        advanceTime(0);
        assertEquals(3.0f, hbmc.getHdrBrightnessValue(), 0.0);
        verify(hbmChangedCallback, times(2)).run();
    }


    @Test
    public void testHdrTrumpsSunlight() {
@@ -698,6 +729,7 @@ public class HighBrightnessModeControllerTest {
    private class TestHbmBuilder {
        OffsettableClock mClock;
        HighBrightnessModeController.HdrBrightnessDeviceConfig mHdrBrightnessCfg;
        Runnable mHdrChangedCallback = () -> {};

        TestHbmBuilder setClock(OffsettableClock clock) {
            mClock = clock;
@@ -711,6 +743,11 @@ public class HighBrightnessModeControllerTest {
            return this;
        }

        TestHbmBuilder setHbmChangedCallback(Runnable runnable) {
            mHdrChangedCallback = runnable;
            return this;
        }

        HighBrightnessModeController build() {
            initHandler(mClock);
            if (mHighBrightnessModeMetadata == null) {
@@ -718,8 +755,8 @@ public class HighBrightnessModeControllerTest {
            }
            return new HighBrightnessModeController(mInjectorMock, mHandler, DISPLAY_WIDTH,
                    DISPLAY_HEIGHT, mDisplayToken, mDisplayUniqueId, DEFAULT_MIN, DEFAULT_MAX,
                    DEFAULT_HBM_DATA, mHdrBrightnessCfg, () -> {}, mHighBrightnessModeMetadata,
                    mContextSpy);
                    DEFAULT_HBM_DATA, mHdrBrightnessCfg, mHdrChangedCallback,
                    mHighBrightnessModeMetadata, mContextSpy);
        }

    }