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

Commit 2d467a4d authored by Oleg Petsjonkin's avatar Oleg Petsjonkin
Browse files

NormalBrightnessModeController configuration

Bug: b/277877297
Test: atest DisplayDeviceCongigTest, atest NormalBrightnessControllerTest
Change-Id: I8681d009336d22206db355e6a18a79bc89c39603
parent 1981dd3b
Loading
Loading
Loading
Loading
+33 −19
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.hardware.display.BrightnessInfo;
import android.os.IBinder;

import java.io.PrintWriter;
import java.util.function.BooleanSupplier;

class BrightnessRangeController {

@@ -43,20 +44,10 @@ class BrightnessRangeController {
    }

    void onAmbientLuxChange(float ambientLux) {
        if (NBM_FEATURE_FLAG) {
            boolean nbmTransitionChanged = mNormalBrightnessModeController.onAmbientLuxChange(
                    ambientLux);
            int previousHbm = mHbmController.getHighBrightnessMode();
            mHbmController.onAmbientLuxChange(ambientLux);
            int nextHbm = mHbmController.getHighBrightnessMode();
            // if hbm changed - callback was triggered in mHbmController.onAmbientLuxChange
            // if nbm transition not changed - no need to trigger callback
            if (previousHbm == nextHbm && nbmTransitionChanged) {
                mModeChangeCallback.run();
            }
        } else {
            mHbmController.onAmbientLuxChange(ambientLux);
        }
        applyChanges(
                () -> mNormalBrightnessModeController.onAmbientLuxChange(ambientLux),
                () -> mHbmController.onAmbientLuxChange(ambientLux)
        );
    }

    float getNormalBrightnessMax() {
@@ -65,18 +56,27 @@ class BrightnessRangeController {

    void loadFromConfig(HighBrightnessModeMetadata hbmMetadata, IBinder token,
            DisplayDeviceInfo info, DisplayDeviceConfig displayDeviceConfig) {
        applyChanges(
                () -> mNormalBrightnessModeController.resetNbmData(
                        displayDeviceConfig.getLuxThrottlingData()),
                () -> {
                    mHbmController.setHighBrightnessModeMetadata(hbmMetadata);
                    mHbmController.resetHbmData(info.width, info.height, token, info.uniqueId,
                            displayDeviceConfig.getHighBrightnessModeData(),
                            displayDeviceConfig::getHdrBrightnessFromSdr);
                }
        );
    }

    void stop() {
        mHbmController.stop();
    }

    void setAutoBrightnessEnabled(int state) {
        mHbmController.setAutoBrightnessEnabled(state);
        applyChanges(
                () -> mNormalBrightnessModeController.setAutoBrightnessState(state),
                () ->  mHbmController.setAutoBrightnessEnabled(state)
        );
    }

    void onBrightnessChanged(float brightness, float unthrottledBrightness,
@@ -109,4 +109,18 @@ class BrightnessRangeController {
    float getTransitionPoint() {
        return mHbmController.getTransitionPoint();
    }

    private void applyChanges(BooleanSupplier nbmChangesFunc, Runnable hbmChangesFunc) {
        if (NBM_FEATURE_FLAG) {
            boolean nbmTransitionChanged = nbmChangesFunc.getAsBoolean();
            hbmChangesFunc.run();
            // if nbm transition changed - trigger callback
            // HighBrightnessModeController handles sending changes itself
            if (nbmTransitionChanged) {
                mModeChangeCallback.run();
            }
        } else {
            hbmChangesFunc.run();
        }
    }
}
+93 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.display.BrightnessSynchronizer;
import com.android.server.display.config.AutoBrightness;
import com.android.server.display.config.BlockingZoneConfig;
import com.android.server.display.config.BrightnessLimitMap;
import com.android.server.display.config.BrightnessThresholds;
import com.android.server.display.config.BrightnessThrottlingMap;
import com.android.server.display.config.BrightnessThrottlingPoint;
@@ -51,8 +52,11 @@ import com.android.server.display.config.DisplayQuirks;
import com.android.server.display.config.HbmTiming;
import com.android.server.display.config.HighBrightnessMode;
import com.android.server.display.config.IntegerArray;
import com.android.server.display.config.LuxThrottling;
import com.android.server.display.config.NitsMap;
import com.android.server.display.config.NonNegativeFloatToFloatPoint;
import com.android.server.display.config.Point;
import com.android.server.display.config.PredefinedBrightnessLimitNames;
import com.android.server.display.config.RefreshRateConfigs;
import com.android.server.display.config.RefreshRateRange;
import com.android.server.display.config.RefreshRateThrottlingMap;
@@ -219,6 +223,22 @@ import javax.xml.datatype.DatatypeConfigurationException;
 *        <allowInLowPowerMode>false</allowInLowPowerMode>
 *      </highBrightnessMode>
 *
 *      <luxThrottling>
 *        <brightnessLimitMap>
 *          <type>default</type>
 *          <map>
 *            <point>
 *                <first>5000</first>
 *                <second>0.3</second>
 *            </point>
 *            <point>
 *               <first>5000</first>
 *               <second>0.3</second>
 *            </point>
 *          </map>
 *        </brightnessPeakMap>
 *      </luxThrottling>
 *
 *      <quirks>
 *       <quirk>canSetBrightnessViaHwc</quirk>
 *      </quirks>
@@ -693,6 +713,9 @@ public class DisplayDeviceConfig {
    private final Map<String, SparseArray<SurfaceControl.RefreshRateRange>>
            mRefreshRateThrottlingMap = new HashMap<>();

    private final Map<BrightnessLimitMapType, Map<Float, Float>>
            mLuxThrottlingData = new HashMap<>();

    @Nullable
    private HostUsiVersion mHostUsiVersion;

@@ -1344,6 +1367,11 @@ public class DisplayDeviceConfig {
        return hbmData;
    }

    @NonNull
    public Map<BrightnessLimitMapType, Map<Float, Float>> getLuxThrottlingData() {
        return mLuxThrottlingData;
    }

    public List<RefreshRateLimitation> getRefreshRateLimitations() {
        return mRefreshRateLimitations;
    }
@@ -1530,6 +1558,7 @@ public class DisplayDeviceConfig {
                + ", mBrightnessDefault=" + mBrightnessDefault
                + ", mQuirks=" + mQuirks
                + ", isHbmEnabled=" + mIsHighBrightnessModeEnabled
                + ", mLuxThrottlingData=" + mLuxThrottlingData
                + ", mHbmData=" + mHbmData
                + ", mSdrToHdrRatioSpline=" + mSdrToHdrRatioSpline
                + ", mThermalBrightnessThrottlingDataMapByThrottlingId="
@@ -1676,6 +1705,7 @@ public class DisplayDeviceConfig {
                loadBrightnessMap(config);
                loadThermalThrottlingConfig(config);
                loadHighBrightnessModeData(config);
                loadLuxThrottling(config);
                loadQuirks(config);
                loadBrightnessRamps(config);
                loadAmbientLightSensorFromDdc(config);
@@ -2428,6 +2458,54 @@ public class DisplayDeviceConfig {
        }
    }

    private void loadLuxThrottling(DisplayConfiguration config) {
        LuxThrottling cfg = config.getLuxThrottling();
        if (cfg != null) {
            HighBrightnessMode hbm = config.getHighBrightnessMode();
            float hbmTransitionPoint = hbm != null ? hbm.getTransitionPoint_all().floatValue()
                    : PowerManager.BRIGHTNESS_MAX;
            List<BrightnessLimitMap> limitMaps = cfg.getBrightnessLimitMap();
            for (BrightnessLimitMap map : limitMaps) {
                PredefinedBrightnessLimitNames type = map.getType();
                BrightnessLimitMapType mappedType = BrightnessLimitMapType.convert(type);
                if (mappedType == null) {
                    Slog.wtf(TAG, "Invalid NBM config: unsupported map type=" + type);
                    continue;
                }
                if (mLuxThrottlingData.containsKey(mappedType)) {
                    Slog.wtf(TAG, "Invalid NBM config: duplicate map type=" + mappedType);
                    continue;
                }
                Map<Float, Float> luxToTransitionPointMap = new HashMap<>();

                List<NonNegativeFloatToFloatPoint> points = map.getMap().getPoint();
                for (NonNegativeFloatToFloatPoint point : points) {
                    float lux = point.getFirst().floatValue();
                    float maxBrightness = point.getSecond().floatValue();
                    if (maxBrightness > hbmTransitionPoint) {
                        Slog.wtf(TAG,
                                "Invalid NBM config: maxBrightness is greater than hbm"
                                        + ".transitionPoint. type="
                                        + type + "; lux=" + lux + "; maxBrightness="
                                        + maxBrightness);
                        continue;
                    }
                    if (luxToTransitionPointMap.containsKey(lux)) {
                        Slog.wtf(TAG,
                                "Invalid NBM config: duplicate lux key. type=" + type + "; lux="
                                        + lux);
                        continue;
                    }
                    luxToTransitionPointMap.put(lux,
                            mBacklightToBrightnessSpline.interpolate(maxBrightness));
                }
                if (!luxToTransitionPointMap.isEmpty()) {
                    mLuxThrottlingData.put(mappedType, luxToTransitionPointMap);
                }
            }
        }
    }

    private void loadBrightnessRamps(DisplayConfiguration config) {
        // Priority 1: Value in the display device config (float)
        // Priority 2: Value in the config.xml (int)
@@ -3155,4 +3233,19 @@ public class DisplayDeviceConfig {
            }
        }
    }

    public enum BrightnessLimitMapType {
        DEFAULT, ADAPTIVE;

        @Nullable
        private static BrightnessLimitMapType convert(PredefinedBrightnessLimitNames type) {
            switch (type) {
                case _default:
                    return DEFAULT;
                case adaptive:
                    return ADAPTIVE;
            }
            return null;
        }
    }
}
+3 −1
Original line number Diff line number Diff line
@@ -2141,8 +2141,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
    }

    void postBrightnessChangeRunnable() {
        if (!mHandler.hasCallbacks(mOnBrightnessChangeRunnable)) {
            mHandler.post(mOnBrightnessChangeRunnable);
        }
    }

    private HighBrightnessModeController createHbmControllerLocked(
            Runnable modeChangeCallback) {
+3 −1
Original line number Diff line number Diff line
@@ -1788,8 +1788,10 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
    }

    void postBrightnessChangeRunnable() {
        if (!mHandler.hasCallbacks(mOnBrightnessChangeRunnable)) {
            mHandler.post(mOnBrightnessChangeRunnable);
        }
    }

    private HighBrightnessModeController createHbmControllerLocked(
            HighBrightnessModeMetadata hbmMetadata, Runnable modeChangeCallback) {
+59 −16
Original line number Diff line number Diff line
@@ -16,36 +16,79 @@

package com.android.server.display;

import android.annotation.NonNull;
import android.os.PowerManager;

import com.android.server.display.DisplayDeviceConfig.BrightnessLimitMapType;

import java.util.HashMap;
import java.util.Map;

/**
 * Limits brightness for normal-brightness mode, based on ambient lux
 **/
class NormalBrightnessModeController {
    private Map<Float, Float> mTransitionPoints = new HashMap<>();
    @NonNull
    private Map<BrightnessLimitMapType, Map<Float, Float>> mMaxBrightnessLimits = new HashMap<>();
    private float mAmbientLux = Float.MAX_VALUE;
    private boolean mAutoBrightnessEnabled = false;

    // brightness limit in normal brightness mode, based on ambient lux.
    private float mVirtualTransitionPoint = PowerManager.BRIGHTNESS_MAX;
    private float mMaxBrightness = PowerManager.BRIGHTNESS_MAX;

    boolean onAmbientLuxChange(float ambientLux) {
        float currentAmbientBoundary = Float.MAX_VALUE;
        float currentTransitionPoint = PowerManager.BRIGHTNESS_MAX;
        for (Map.Entry<Float, Float> transitionPoint: mTransitionPoints.entrySet()) {
            float ambientBoundary = transitionPoint.getKey();
            // find ambient lux upper boundary closest to current ambient lux
            if (ambientBoundary > ambientLux && ambientBoundary < currentAmbientBoundary) {
                currentTransitionPoint = transitionPoint.getValue();
                currentAmbientBoundary = ambientBoundary;
            }
        mAmbientLux = ambientLux;
        return recalculateMaxBrightness();
    }
        if (mVirtualTransitionPoint != currentTransitionPoint) {
            mVirtualTransitionPoint = currentTransitionPoint;
            return true;

    boolean setAutoBrightnessState(int state) {
        boolean isEnabled = state == AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED;
        if (isEnabled != mAutoBrightnessEnabled) {
            mAutoBrightnessEnabled = isEnabled;
            return recalculateMaxBrightness();
        }
        return false;
    }

    float getCurrentBrightnessMax() {
        return mVirtualTransitionPoint;
        return mMaxBrightness;
    }

    boolean resetNbmData(
            @NonNull Map<BrightnessLimitMapType, Map<Float, Float>> maxBrightnessLimits) {
        mMaxBrightnessLimits = maxBrightnessLimits;
        return recalculateMaxBrightness();
    }

    private boolean recalculateMaxBrightness() {
        float foundAmbientBoundary = Float.MAX_VALUE;
        float foundMaxBrightness = PowerManager.BRIGHTNESS_MAX;

        Map<Float, Float> maxBrightnessPoints = null;

        if (mAutoBrightnessEnabled) {
            maxBrightnessPoints = mMaxBrightnessLimits.get(BrightnessLimitMapType.ADAPTIVE);
        }

        if (maxBrightnessPoints == null) {
            maxBrightnessPoints = mMaxBrightnessLimits.get(BrightnessLimitMapType.DEFAULT);
        }

        if (maxBrightnessPoints != null) {
            for (Map.Entry<Float, Float> brightnessPoint : maxBrightnessPoints.entrySet()) {
                float ambientBoundary = brightnessPoint.getKey();
                // find ambient lux upper boundary closest to current ambient lux
                if (ambientBoundary > mAmbientLux && ambientBoundary < foundAmbientBoundary) {
                    foundMaxBrightness = brightnessPoint.getValue();
                    foundAmbientBoundary = ambientBoundary;
                }
            }
        }

        if (mMaxBrightness != foundMaxBrightness) {
            mMaxBrightness = foundMaxBrightness;
            return true;
        }
        return false;
    }
}
Loading