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

Commit 0db446ad authored by Santos Cordon's avatar Santos Cordon
Browse files

Fix HDR for app-override brightness.

- HBMController no longer listens to changes on the brightness setting
directly, and instead gets brightness updates from DPC. This was
necessary since some of the brightness-sources (such as app-override)
are not reflected in the actual setting.
- Clamp override and temporary brightness sources so that they cannot
push brightness beyond the bounds set by HbmController.
- Always save away the actual brightness setting in BrightnessInfo
cache, ignoring any temporary or override brightness values. This ensures
that Display.getBrightnessInfo() reflects the user setting, and not some
temporary brightness state.

Bug: 193392737
Test: manually test HDR with app-override
Test: atest HighBrightnessModeControllerTest
Change-Id: Iffe777a22d058ddb779dc6fc22c2382f6bbac1ab
parent 0077afd8
Loading
Loading
Loading
Loading
+18 −12
Original line number Diff line number Diff line
@@ -776,7 +776,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
        setUpAutoBrightness(mContext.getResources(), mHandler);
        reloadReduceBrightColours();
        mHbmController.resetHbmData(info.width, info.height, token,
                mDisplayDeviceConfig.getHighBrightnessModeData(), mBrightnessSetting);
                mDisplayDeviceConfig.getHighBrightnessModeData());
    }

    private void sendUpdatePowerState() {
@@ -966,7 +966,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
        final boolean mustNotify;
        final int previousPolicy;
        boolean mustInitialize = false;
        boolean shouldSaveBrightnessInfo = true;
        int brightnessAdjustmentFlags = 0;
        mBrightnessReasonTemp.set(null);
        synchronized (mLock) {
@@ -1097,7 +1096,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
        if (state == Display.STATE_OFF) {
            brightnessState = PowerManager.BRIGHTNESS_OFF_FLOAT;
            mBrightnessReasonTemp.setReason(BrightnessReason.REASON_SCREEN_OFF);
            shouldSaveBrightnessInfo = false;
        }

        // Always use the VR brightness when in the VR state.
@@ -1215,6 +1213,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
                brightnessAdjustmentFlags = 0;
            }
        } else {
            // Any non-auto-brightness values such as override or temporary should still be subject
            // to clamping so that they don't go beyond the current max as specified by HBM
            // Controller.
            brightnessState = clampScreenBrightness(brightnessState);
            mAppliedAutoBrightness = false;
            brightnessAdjustmentFlags = 0;
        }
@@ -1222,9 +1224,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
        // Use default brightness when dozing unless overridden.
        if ((Float.isNaN(brightnessState))
                && Display.isDozeState(state)) {
            brightnessState = mScreenBrightnessDozeConfig;
            brightnessState = clampScreenBrightness(mScreenBrightnessDozeConfig);
            mBrightnessReasonTemp.setReason(BrightnessReason.REASON_DOZE_DEFAULT);
            shouldSaveBrightnessInfo = false;
        }

        // Apply manual brightness.
@@ -1239,12 +1240,13 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
            mBrightnessReasonTemp.setReason(BrightnessReason.REASON_MANUAL);
        }

        // Save out the brightness info now that the brightness state for this iteration has been
        // finalized and before we send out notifications about the brightness changing.
        if (shouldSaveBrightnessInfo) {
            saveBrightnessInfo(brightnessState);

        }
        // The current brightness to use has been calculated at this point (minus the adjustments
        // like low-power and dim), and HbmController should be notified so that it can accurately
        // calculate HDR or HBM levels. We specifically do it here instead of having HbmController
        // listen to the brightness setting because certain brightness sources (just as an app
        // override) are not saved to the setting, but should be reflected in HBM
        // calculations.
        mHbmController.onBrightnessChanged(brightnessState);

        if (updateScreenBrightnessSetting) {
            // Tell the rest of the system about the new brightness in case we had to change it
@@ -1255,6 +1257,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
            putScreenBrightnessSetting(brightnessState, /* updateCurrent */ true);
        }

        // We save the brightness info *after* the brightness setting has been changed so that
        // the brightness info reflects the latest value.
        saveBrightnessInfo(getScreenBrightnessSetting());

        // Apply dimming by at least some minimum amount when user activity
        // timeout is about to expire.
        if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
@@ -1531,7 +1537,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
                    mHandler.post(mOnBrightnessChangeRunnable);
                    // TODO(b/192258832): Switch the HBMChangeCallback to a listener pattern.
                    mAutomaticBrightnessController.update();
                }, mContext, mBrightnessSetting);
                }, mContext);
    }

    private void blockScreenOn() {
+12 −24
Original line number Diff line number Diff line
@@ -37,7 +37,6 @@ import android.util.TimeUtils;
import android.view.SurfaceControlHdrLayerInfoListener;

import com.android.internal.annotations.VisibleForTesting;
import com.android.server.display.BrightnessSetting.BrightnessSettingListener;
import com.android.server.display.DisplayDeviceConfig.HighBrightnessModeData;
import com.android.server.display.DisplayManagerService.Clock;

@@ -70,7 +69,6 @@ class HighBrightnessModeController {
    private final Context mContext;
    private final SettingsObserver mSettingsObserver;
    private final Injector mInjector;
    private final BrightnessSettingListener mBrightnessSettingListener = this::onBrightnessChanged;

    private HdrListener mHdrListener;
    private HighBrightnessModeData mHbmData;
@@ -86,7 +84,6 @@ class HighBrightnessModeController {
    private boolean mIsBlockedByLowPowerMode = false;
    private int mWidth;
    private int mHeight;
    private BrightnessSetting mBrightnessSetting;
    private float mAmbientLux;

    /**
@@ -103,30 +100,30 @@ class HighBrightnessModeController {

    HighBrightnessModeController(Handler handler, int width, int height, IBinder displayToken,
            float brightnessMin, float brightnessMax, HighBrightnessModeData hbmData,
            Runnable hbmChangeCallback, Context context, BrightnessSetting brightnessSetting) {
            Runnable hbmChangeCallback, Context context) {
        this(new Injector(), handler, width, height, displayToken, brightnessMin, brightnessMax,
                hbmData, hbmChangeCallback, context, brightnessSetting);
                hbmData, hbmChangeCallback, context);
    }

    @VisibleForTesting
    HighBrightnessModeController(Injector injector, Handler handler, int width, int height,
            IBinder displayToken, float brightnessMin, float brightnessMax,
            HighBrightnessModeData hbmData, Runnable hbmChangeCallback,
            Context context, BrightnessSetting brightnessSetting) {
            Context context) {
        mInjector = injector;
        mContext = context;
        mClock = injector.getClock();
        mHandler = handler;
        mBrightness = brightnessMin;
        mBrightnessMin = brightnessMin;
        mBrightnessMax = brightnessMax;
        mBrightness = brightnessSetting.getBrightness();
        mHbmChangeCallback = hbmChangeCallback;
        mSkinThermalStatusObserver = new SkinThermalStatusObserver(mInjector, mHandler);
        mSettingsObserver = new SettingsObserver(mHandler);
        mRecalcRunnable = this::recalculateTimeAllowance;
        mHdrListener = new HdrListener();

        resetHbmData(width, height, displayToken, hbmData, brightnessSetting);
        resetHbmData(width, height, displayToken, hbmData);
    }

    void setAutoBrightnessEnabled(boolean isEnabled) {
@@ -185,7 +182,6 @@ class HighBrightnessModeController {
        }
    }

    @VisibleForTesting
    void onBrightnessChanged(float brightness) {
        if (!deviceSupportsHbm()) {
            return;
@@ -224,12 +220,11 @@ class HighBrightnessModeController {
        mSettingsObserver.stopObserving();
    }

    void resetHbmData(int width, int height, IBinder displayToken, HighBrightnessModeData hbmData,
            BrightnessSetting brightnessSetting) {
    void resetHbmData(int width, int height, IBinder displayToken, HighBrightnessModeData hbmData) {
        mWidth = width;
        mHeight = height;
        mHbmData = hbmData;
        resetBrightnessSetting(brightnessSetting);

        unregisterHdrListener();
        mSkinThermalStatusObserver.stopObserving();
        mSettingsObserver.stopObserving();
@@ -261,9 +256,12 @@ class HighBrightnessModeController {
        pw.println("  mBrightness=" + mBrightness);
        pw.println("  mCurrentMin=" + getCurrentBrightnessMin());
        pw.println("  mCurrentMax=" + getCurrentBrightnessMax());
        pw.println("  mHbmMode=" + BrightnessInfo.hbmToString(mHbmMode));
        pw.println("  mHbmMode=" + BrightnessInfo.hbmToString(mHbmMode)
                + (mHbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR
                ? "(" + getHdrBrightnessValue() + ")" : ""));
        pw.println("  mHbmData=" + mHbmData);
        pw.println("  mAmbientLux=" + mAmbientLux);
        pw.println("  mAmbientLux=" + mAmbientLux
                + (mIsAutoBrightnessEnabled ? "" : " (old/invalid)"));
        pw.println("  mIsInAllowedAmbientRange=" + mIsInAllowedAmbientRange);
        pw.println("  mIsAutoBrightnessEnabled=" + mIsAutoBrightnessEnabled);
        pw.println("  mIsHdrLayerPresent=" + mIsHdrLayerPresent);
@@ -301,16 +299,6 @@ class HighBrightnessModeController {
        return event.startTimeMillis;
    }

    private void resetBrightnessSetting(BrightnessSetting brightnessSetting) {
        if (mBrightnessSetting != null) {
            mBrightnessSetting.unregisterListener(mBrightnessSettingListener);
        }
        mBrightnessSetting = brightnessSetting;
        if (mBrightnessSetting != null) {
            mBrightnessSetting.registerListener(mBrightnessSettingListener);
        }
    }

    private boolean isCurrentlyAllowed() {
        // 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
+3 −4
Original line number Diff line number Diff line
@@ -92,7 +92,6 @@ public class HighBrightnessModeControllerTest {

    @Mock IThermalService mThermalServiceMock;
    @Mock Injector mInjectorMock;
    @Mock BrightnessSetting mBrightnessSetting;

    @Captor ArgumentCaptor<IThermalEventListener> mThermalEventListenerCaptor;

@@ -123,7 +122,7 @@ public class HighBrightnessModeControllerTest {
        initHandler(null);
        final HighBrightnessModeController hbmc = new HighBrightnessModeController(
                mInjectorMock, mHandler, DISPLAY_WIDTH, DISPLAY_HEIGHT, mDisplayToken, DEFAULT_MIN,
                DEFAULT_MAX, null, () -> {}, mContextSpy, mBrightnessSetting);
                DEFAULT_MAX, null, () -> {}, mContextSpy);
        assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_OFF);
    }

@@ -132,7 +131,7 @@ public class HighBrightnessModeControllerTest {
        initHandler(null);
        final HighBrightnessModeController hbmc = new HighBrightnessModeController(
                mInjectorMock, mHandler, DISPLAY_WIDTH, DISPLAY_HEIGHT, mDisplayToken, DEFAULT_MIN,
                DEFAULT_MAX, null, () -> {}, mContextSpy, mBrightnessSetting);
                DEFAULT_MAX, null, () -> {}, mContextSpy);
        hbmc.setAutoBrightnessEnabled(true);
        hbmc.onAmbientLuxChange(MINIMUM_LUX - 1); // below allowed range
        assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_OFF);
@@ -464,7 +463,7 @@ public class HighBrightnessModeControllerTest {
        initHandler(clock);
        return new HighBrightnessModeController(mInjectorMock, mHandler, DISPLAY_WIDTH,
                DISPLAY_HEIGHT, mDisplayToken, DEFAULT_MIN, DEFAULT_MAX, DEFAULT_HBM_DATA, () -> {},
                mContextSpy, mBrightnessSetting);
                mContextSpy);
    }

    private void initHandler(OffsettableClock clock) {