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

Commit 93fc0868 authored by Piotr Wilczyński's avatar Piotr Wilczyński Committed by Android (Google) Code Review
Browse files

Merge "Named brightness mappings" into main

parents 44189612 c9a7e6e8
Loading
Loading
Loading
Loading
+4 −21
Original line number Diff line number Diff line
@@ -35,7 +35,6 @@ import android.util.Slog;
import android.util.Spline;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.display.BrightnessSynchronizer;
import com.android.internal.display.BrightnessUtils;
import com.android.internal.util.Preconditions;
import com.android.server.display.utils.Plog;
@@ -97,28 +96,17 @@ public abstract class BrightnessMappingStrategy {
        float[] brightnessLevels = null;
        float[] luxLevels = null;
        switch (mode) {
            case AUTO_BRIGHTNESS_MODE_DEFAULT:
            case AUTO_BRIGHTNESS_MODE_DEFAULT -> {
                brightnessLevelsNits = displayDeviceConfig.getAutoBrightnessBrighteningLevelsNits();
                luxLevels = displayDeviceConfig.getAutoBrightnessBrighteningLevelsLux();

                brightnessLevels = displayDeviceConfig.getAutoBrightnessBrighteningLevels();
                if (brightnessLevels == null || brightnessLevels.length == 0) {
                    // Load the old configuration in the range [0, 255]. The values need to be
                    // normalized to the range [0, 1].
                    int[] brightnessLevelsInt = resources.getIntArray(
                            com.android.internal.R.array.config_autoBrightnessLcdBacklightValues);
                    brightnessLevels = new float[brightnessLevelsInt.length];
                    for (int i = 0; i < brightnessLevels.length; i++) {
                        brightnessLevels[i] = normalizeAbsoluteBrightness(brightnessLevelsInt[i]);
                    }
            }
                break;
            case AUTO_BRIGHTNESS_MODE_IDLE:
            case AUTO_BRIGHTNESS_MODE_IDLE -> {
                brightnessLevelsNits = getFloatArray(resources.obtainTypedArray(
                        com.android.internal.R.array.config_autoBrightnessDisplayValuesNitsIdle));
                luxLevels = getLuxLevels(resources.getIntArray(
                        com.android.internal.R.array.config_autoBrightnessLevelsIdle));
                break;
            }
        }

        // Display independent, mode independent values
@@ -426,11 +414,6 @@ public abstract class BrightnessMappingStrategy {
        }
    }

    // Normalize entire brightness range to 0 - 1.
    protected static float normalizeAbsoluteBrightness(int brightness) {
        return BrightnessSynchronizer.brightnessIntToFloat(brightness);
    }

    private Pair<float[], float[]> insertControlPoint(
            float[] luxLevels, float[] brightnessLevels, float lux, float brightness) {
        final int idx = findInsertionPoint(luxLevels, lux);
+67 −74
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ import com.android.server.display.config.BrightnessThresholds;
import com.android.server.display.config.BrightnessThrottlingMap;
import com.android.server.display.config.BrightnessThrottlingPoint;
import com.android.server.display.config.Density;
import com.android.server.display.config.DisplayBrightnessMappingConfig;
import com.android.server.display.config.DisplayBrightnessPoint;
import com.android.server.display.config.DisplayConfiguration;
import com.android.server.display.config.DisplayQuirks;
@@ -57,7 +58,6 @@ import com.android.server.display.config.HdrBrightnessData;
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.LuxToBrightnessMapping;
import com.android.server.display.config.NitsMap;
import com.android.server.display.config.NonNegativeFloatToFloatPoint;
import com.android.server.display.config.Point;
@@ -313,6 +313,21 @@ import javax.xml.datatype.DatatypeConfigurationException;
 *              1000
 *          </darkeningLightDebounceIdleMillis>
 *          <luxToBrightnessMapping>
 *            <mode>default</mode>
 *            <map>
 *              <point>
 *                <first>0</first>
 *                <second>0.2</second>
 *              </point>
 *              <point>
 *                <first>80</first>
 *                <second>0.3</second>
 *              </point>
 *            </map>
 *          </luxToBrightnessMapping>
 *          <luxToBrightnessMapping>
 *            <mode>doze</mode>
 *            <setting>dim</setting>
 *            <map>
 *              <point>
 *                <first>0</first>
@@ -634,36 +649,8 @@ public class DisplayDeviceConfig {
    // for the corresponding values above
    private float[] mBrightness;

    /**
     * Array of desired screen brightness in nits corresponding to the lux values
     * in the mBrightnessLevelsLux array. The display brightness is defined as the
     * measured brightness of an all-white image. The brightness values must be non-negative and
     * non-decreasing. This must be overridden in platform specific overlays
     */
    private float[] mBrightnessLevelsNits;

    /**
     * Array of desired screen brightness corresponding to the lux values
     * in the mBrightnessLevelsLux array. The brightness values must be non-negative and
     * non-decreasing. They must be between {@link PowerManager.BRIGHTNESS_MIN} and
     * {@link PowerManager.BRIGHTNESS_MAX}. This must be overridden in platform specific overlays
     */
    private float[] mBrightnessLevels;

    /**
     * Array of light sensor lux values to define our levels for auto-brightness support.
     *
     * The first lux value is always 0.
     *
     * The control points must be strictly increasing. Each control point corresponds to an entry
     * in the brightness values arrays. For example, if lux == luxLevels[1] (second element
     * of the levels array) then the brightness will be determined by brightnessLevels[1] (second
     * element of the brightness values array).
     *
     * Spline interpolation is used to determine the auto-brightness values for lux levels between
     * these control points.
     */
    private float[] mBrightnessLevelsLux;
    @Nullable
    private DisplayBrightnessMappingConfig mDisplayBrightnessMapping;

    private float mBacklightMinimum = Float.NaN;
    private float mBacklightMaximum = Float.NaN;
@@ -1604,24 +1591,57 @@ public class DisplayDeviceConfig {
    }

    /**
     * @return Auto brightness brightening ambient lux levels
     * @return The default auto-brightness brightening ambient lux levels
     */
    public float[] getAutoBrightnessBrighteningLevelsLux() {
        return mBrightnessLevelsLux;
        if (mDisplayBrightnessMapping == null) {
            return null;
        }
        return mDisplayBrightnessMapping.getLuxArray();
    }

    /**
     * @param mode The auto-brightness mode
     * @param setting The brightness setting
     * @return Auto brightness brightening ambient lux levels for the specified mode and setting
     */
    public float[] getAutoBrightnessBrighteningLevelsLux(String mode, String setting) {
        if (mDisplayBrightnessMapping == null) {
            return null;
        }
        return mDisplayBrightnessMapping.getLuxArray(mode, setting);
    }

    /**
     * @return Auto brightness brightening nits levels
     */
    public float[] getAutoBrightnessBrighteningLevelsNits() {
        return mBrightnessLevelsNits;
        if (mDisplayBrightnessMapping == null) {
            return null;
        }
        return mDisplayBrightnessMapping.getNitsArray();
    }

    /**
     * @return Auto brightness brightening levels
     * @return The default auto-brightness brightening levels
     */
    public float[] getAutoBrightnessBrighteningLevels() {
        return mBrightnessLevels;
        if (mDisplayBrightnessMapping == null) {
            return null;
        }
        return mDisplayBrightnessMapping.getBrightnessArray();
    }

    /**
     * @param mode The auto-brightness mode
     * @param setting The brightness setting
     * @return Auto brightness brightening backlight levels for the specified mode and setting
     */
    public float[] getAutoBrightnessBrighteningLevels(String mode, String setting) {
        if (mDisplayBrightnessMapping == null) {
            return null;
        }
        return mDisplayBrightnessMapping.getBrightnessArray(mode, setting);
    }

    /**
@@ -1875,9 +1895,7 @@ public class DisplayDeviceConfig {
                + mAutoBrightnessBrighteningLightDebounceIdle
                + ", mAutoBrightnessDarkeningLightDebounceIdle= "
                + mAutoBrightnessDarkeningLightDebounceIdle
                + ", mBrightnessLevelsLux= " + Arrays.toString(mBrightnessLevelsLux)
                + ", mBrightnessLevelsNits= " + Arrays.toString(mBrightnessLevelsNits)
                + ", mBrightnessLevels= " + Arrays.toString(mBrightnessLevels)
                + ", mDisplayBrightnessMapping= " + mDisplayBrightnessMapping
                + ", mDdcAutoBrightnessAvailable= " + mDdcAutoBrightnessAvailable
                + ", mAutoBrightnessAvailable= " + mAutoBrightnessAvailable
                + "\n"
@@ -2568,7 +2586,8 @@ public class DisplayDeviceConfig {
        // Idle must be called after interactive, since we fall back to it if needed.
        loadAutoBrightnessBrighteningLightDebounceIdle(autoBrightness);
        loadAutoBrightnessDarkeningLightDebounceIdle(autoBrightness);
        loadAutoBrightnessDisplayBrightnessMapping(autoBrightness);
        mDisplayBrightnessMapping = new DisplayBrightnessMappingConfig(mContext, mFlags,
                autoBrightness, mBacklightToBrightnessSpline);
        loadEnableAutoBrightness(autoBrightness);
    }

@@ -2633,38 +2652,6 @@ public class DisplayDeviceConfig {
        }
    }

    /**
     * Loads the auto-brightness display brightness mappings. Internally, this takes care of
     * loading the value from the display config, and if not present, falls back to config.xml.
     */
    private void loadAutoBrightnessDisplayBrightnessMapping(AutoBrightness autoBrightnessConfig) {
        if (mFlags.areAutoBrightnessModesEnabled() && autoBrightnessConfig != null
                && autoBrightnessConfig.getLuxToBrightnessMapping() != null) {
            LuxToBrightnessMapping mapping = autoBrightnessConfig.getLuxToBrightnessMapping();
            final int size = mapping.getMap().getPoint().size();
            mBrightnessLevels = new float[size];
            mBrightnessLevelsLux = new float[size];
            for (int i = 0; i < size; i++) {
                float backlight = mapping.getMap().getPoint().get(i).getSecond().floatValue();
                mBrightnessLevels[i] = mBacklightToBrightnessSpline.interpolate(backlight);
                mBrightnessLevelsLux[i] = mapping.getMap().getPoint().get(i).getFirst()
                        .floatValue();
            }
            if (size > 0 && mBrightnessLevelsLux[0] != 0) {
                throw new IllegalArgumentException(
                        "The first lux value in the display brightness mapping must be 0");
            }
        } else {
            mBrightnessLevelsNits = getFloatArray(mContext.getResources()
                    .obtainTypedArray(com.android.internal.R.array
                            .config_autoBrightnessDisplayValuesNits), PowerManager
                    .BRIGHTNESS_OFF_FLOAT);
            mBrightnessLevelsLux = getLuxLevels(mContext.getResources()
                    .getIntArray(com.android.internal.R.array
                            .config_autoBrightnessLevels));
        }
    }

    private void loadAutoBrightnessAvailableFromConfigXml() {
        mAutoBrightnessAvailable = mContext.getResources().getBoolean(
                R.bool.config_automatic_brightness_available);
@@ -2977,7 +2964,8 @@ public class DisplayDeviceConfig {
    }

    private void loadAutoBrightnessConfigsFromConfigXml() {
        loadAutoBrightnessDisplayBrightnessMapping(null /*AutoBrightnessConfig*/);
        mDisplayBrightnessMapping = new DisplayBrightnessMappingConfig(mContext, mFlags,
                /* autoBrightnessConfig= */ null, mBacklightToBrightnessSpline);
    }

    private void loadBrightnessChangeThresholdsFromXml() {
@@ -3347,7 +3335,12 @@ public class DisplayDeviceConfig {
        return vals;
    }

    private static float[] getLuxLevels(int[] lux) {
    /**
     * @param lux The lux array
     * @return The lux array with 0 appended at the beginning - the first lux value should always
     * be 0
     */
    public static float[] getLuxLevels(int[] lux) {
        // The first control point is implicit and always at 0 lux.
        float[] levels = new float[lux.length + 1];
        for (int i = 0; i < lux.length; i++) {
+217 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.config;

import android.content.Context;
import android.os.PowerManager;
import android.util.Spline;

import com.android.internal.display.BrightnessSynchronizer;
import com.android.server.display.DisplayDeviceConfig;
import com.android.server.display.feature.DisplayManagerFlags;

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

/**
 * Provides a mapping between lux and brightness values in order to support auto-brightness.
 */
public class DisplayBrightnessMappingConfig {

    private static final String DEFAULT_BRIGHTNESS_MAPPING_KEY = "default_normal";

    /**
     * Array of desired screen brightness in nits corresponding to the lux values
     * in the mBrightnessLevelsLuxMap.get(DEFAULT_ID) array. The display brightness is defined as
     * the measured brightness of an all-white image. The brightness values must be non-negative and
     * non-decreasing. This must be overridden in platform specific overlays
     */
    private float[] mBrightnessLevelsNits;

    /**
     * Map of arrays of desired screen brightness corresponding to the lux values
     * in mBrightnessLevelsLuxMap, indexed by the auto-brightness mode and the brightness setting.
     * The brightness values must be non-negative and non-decreasing. They must be between
     * {@link PowerManager.BRIGHTNESS_MIN} and {@link PowerManager.BRIGHTNESS_MAX}.
     *
     * The keys are a concatenation of the auto-brightness mode and the brightness setting
     * separated by an underscore, e.g. default_normal, default_dim, default_bright, doze_normal,
     * doze_dim, doze_bright.
     */
    private final Map<String, float[]> mBrightnessLevelsMap = new HashMap<>();

    /**
     * Map of arrays of light sensor lux values to define our levels for auto-brightness support,
     * indexed by the auto-brightness mode and the brightness setting.
     *
     * The first lux value in every array is always 0.
     *
     * The control points must be strictly increasing. Each control point corresponds to an entry
     * in the brightness values arrays. For example, if lux == luxLevels[1] (second element
     * of the levels array) then the brightness will be determined by brightnessLevels[1] (second
     * element of the brightness values array).
     *
     * Spline interpolation is used to determine the auto-brightness values for lux levels between
     * these control points.
     *
     * The keys are a concatenation of the auto-brightness mode and the brightness setting
     * separated by an underscore, e.g. default_normal, default_dim, default_bright, doze_normal,
     * doze_dim, doze_bright.
     */
    private final Map<String, float[]> mBrightnessLevelsLuxMap = new HashMap<>();

    /**
     * Loads the auto-brightness display brightness mappings. Internally, this takes care of
     * loading the value from the display config, and if not present, falls back to config.xml.
     */
    public DisplayBrightnessMappingConfig(Context context, DisplayManagerFlags flags,
            AutoBrightness autoBrightnessConfig, Spline backlightToBrightnessSpline) {
        if (flags.areAutoBrightnessModesEnabled() && autoBrightnessConfig != null
                && autoBrightnessConfig.getLuxToBrightnessMapping() != null
                && autoBrightnessConfig.getLuxToBrightnessMapping().size() > 0) {
            for (LuxToBrightnessMapping mapping
                    : autoBrightnessConfig.getLuxToBrightnessMapping()) {
                final int size = mapping.getMap().getPoint().size();
                float[] brightnessLevels = new float[size];
                float[] brightnessLevelsLux = new float[size];
                for (int i = 0; i < size; i++) {
                    float backlight = mapping.getMap().getPoint().get(i).getSecond().floatValue();
                    brightnessLevels[i] = backlightToBrightnessSpline.interpolate(backlight);
                    brightnessLevelsLux[i] = mapping.getMap().getPoint().get(i).getFirst()
                            .floatValue();
                }
                if (size == 0) {
                    throw new IllegalArgumentException(
                            "A display brightness mapping should not be empty");
                }
                if (brightnessLevelsLux[0] != 0) {
                    throw new IllegalArgumentException(
                            "The first lux value in the display brightness mapping must be 0");
                }

                String key = (mapping.getMode() == null ? "default" : mapping.getMode()) + "_"
                        + (mapping.getSetting() == null ? "normal" : mapping.getSetting());
                if (mBrightnessLevelsMap.containsKey(key)
                        || mBrightnessLevelsLuxMap.containsKey(key)) {
                    throw new IllegalArgumentException(
                            "A display brightness mapping with key " + key + " already exists");
                }
                mBrightnessLevelsMap.put(key, brightnessLevels);
                mBrightnessLevelsLuxMap.put(key, brightnessLevelsLux);
            }
        }

        if (!mBrightnessLevelsMap.containsKey(DEFAULT_BRIGHTNESS_MAPPING_KEY)
                || !mBrightnessLevelsLuxMap.containsKey(DEFAULT_BRIGHTNESS_MAPPING_KEY)) {
            mBrightnessLevelsNits = DisplayDeviceConfig.getFloatArray(context.getResources()
                    .obtainTypedArray(com.android.internal.R.array
                            .config_autoBrightnessDisplayValuesNits), PowerManager
                    .BRIGHTNESS_OFF_FLOAT);

            float[] brightnessLevelsLux = DisplayDeviceConfig.getLuxLevels(context.getResources()
                    .getIntArray(com.android.internal.R.array
                            .config_autoBrightnessLevels));
            mBrightnessLevelsLuxMap.put(DEFAULT_BRIGHTNESS_MAPPING_KEY, brightnessLevelsLux);

            // Load the old configuration in the range [0, 255]. The values need to be normalized
            // to the range [0, 1].
            int[] brightnessLevels = context.getResources().getIntArray(
                    com.android.internal.R.array.config_autoBrightnessLcdBacklightValues);
            mBrightnessLevelsMap.put(DEFAULT_BRIGHTNESS_MAPPING_KEY,
                    brightnessArrayIntToFloat(brightnessLevels, backlightToBrightnessSpline));
        }
    }

    /**
     * @return The default auto-brightness brightening ambient lux levels
     */
    public float[] getLuxArray() {
        return mBrightnessLevelsLuxMap.get(DEFAULT_BRIGHTNESS_MAPPING_KEY);
    }

    /**
     * @param mode The auto-brightness mode
     * @param setting The brightness setting
     * @return Auto brightness brightening ambient lux levels for the specified mode and setting
     */
    public float[] getLuxArray(String mode, String setting) {
        return mBrightnessLevelsLuxMap.get(mode + "_" + setting);
    }

    /**
     * @return Auto brightness brightening nits levels
     */
    public float[] getNitsArray() {
        return mBrightnessLevelsNits;
    }

    /**
     * @return The default auto-brightness brightening levels
     */
    public float[] getBrightnessArray() {
        return mBrightnessLevelsMap.get(DEFAULT_BRIGHTNESS_MAPPING_KEY);
    }

    /**
     * @param mode The auto-brightness mode
     * @param setting The brightness setting
     * @return Auto brightness brightening ambient lux levels for the specified mode and setting
     */
    public float[] getBrightnessArray(String mode, String setting) {
        return mBrightnessLevelsMap.get(mode + "_" + setting);
    }

    @Override
    public String toString() {
        StringBuilder brightnessLevelsLuxMapString = new StringBuilder("{");
        for (Map.Entry<String, float[]> entry : mBrightnessLevelsLuxMap.entrySet()) {
            brightnessLevelsLuxMapString.append(entry.getKey()).append("=").append(
                    Arrays.toString(entry.getValue())).append(", ");
        }
        if (brightnessLevelsLuxMapString.length() > 2) {
            brightnessLevelsLuxMapString.delete(brightnessLevelsLuxMapString.length() - 2,
                    brightnessLevelsLuxMapString.length());
        }
        brightnessLevelsLuxMapString.append("}");

        StringBuilder brightnessLevelsMapString = new StringBuilder("{");
        for (Map.Entry<String, float[]> entry : mBrightnessLevelsMap.entrySet()) {
            brightnessLevelsMapString.append(entry.getKey()).append("=").append(
                    Arrays.toString(entry.getValue())).append(", ");
        }
        if (brightnessLevelsMapString.length() > 2) {
            brightnessLevelsMapString.delete(brightnessLevelsMapString.length() - 2,
                    brightnessLevelsMapString.length());
        }
        brightnessLevelsMapString.append("}");

        return "mBrightnessLevelsNits= " + Arrays.toString(mBrightnessLevelsNits)
                + ", mBrightnessLevelsLuxMap= " + brightnessLevelsLuxMapString
                + ", mBrightnessLevelsMap= " + brightnessLevelsMapString;
    }

    private float[] brightnessArrayIntToFloat(int[] brightnessInt,
            Spline backlightToBrightnessSpline) {
        float[] brightnessFloat = new float[brightnessInt.length];
        for (int i = 0; i < brightnessInt.length; i++) {
            brightnessFloat[i] = backlightToBrightnessSpline.interpolate(
                    BrightnessSynchronizer.brightnessIntToFloat(brightnessInt[i]));
        }
        return brightnessFloat;
    }
}
+9 −1
Original line number Diff line number Diff line
@@ -595,7 +595,7 @@
            <!-- Sets the brightness mapping of the desired screen brightness to the corresponding
            lux for the current display -->
            <xs:element name="luxToBrightnessMapping" type="luxToBrightnessMapping"
                        minOccurs="0" maxOccurs="1">
                        minOccurs="0" maxOccurs="unbounded">
                <xs:annotation name="final"/>
            </xs:element>
        </xs:sequence>
@@ -619,12 +619,20 @@

    This is used in place of config_autoBrightnessLevels and config_autoBrightnessLcdBacklightValues
    defined in the config XML resource.

    On devices that allow users to choose from a set of predefined options in display
    auto-brightness settings, multiple mappings for different modes and settings can be defined.

    If no mode is specified, the mapping will be used for the default mode.
    If no setting is specified, the mapping will be used for the normal brightness setting.
    -->
    <xs:complexType name="luxToBrightnessMapping">
        <xs:element name="map" type="nonNegativeFloatToFloatMap">
            <xs:annotation name="nonnull"/>
            <xs:annotation name="final"/>
        </xs:element>
        <xs:element name="mode" type="xs:string" minOccurs="0"/>
        <xs:element name="setting" type="xs:string" minOccurs="0"/>
    </xs:complexType>

    <!-- Represents a point in the display brightness mapping, representing the lux level from the
+5 −2
Original line number Diff line number Diff line
@@ -8,13 +8,12 @@ package com.android.server.display.config {
    method public final java.math.BigInteger getDarkeningLightDebounceIdleMillis();
    method public final java.math.BigInteger getDarkeningLightDebounceMillis();
    method public boolean getEnabled();
    method public final com.android.server.display.config.LuxToBrightnessMapping getLuxToBrightnessMapping();
    method public final java.util.List<com.android.server.display.config.LuxToBrightnessMapping> getLuxToBrightnessMapping();
    method public final void setBrighteningLightDebounceIdleMillis(java.math.BigInteger);
    method public final void setBrighteningLightDebounceMillis(java.math.BigInteger);
    method public final void setDarkeningLightDebounceIdleMillis(java.math.BigInteger);
    method public final void setDarkeningLightDebounceMillis(java.math.BigInteger);
    method public void setEnabled(boolean);
    method public final void setLuxToBrightnessMapping(com.android.server.display.config.LuxToBrightnessMapping);
  }

  public class BlockingZoneConfig {
@@ -220,7 +219,11 @@ package com.android.server.display.config {
  public class LuxToBrightnessMapping {
    ctor public LuxToBrightnessMapping();
    method @NonNull public final com.android.server.display.config.NonNegativeFloatToFloatMap getMap();
    method public String getMode();
    method public String getSetting();
    method public final void setMap(@NonNull com.android.server.display.config.NonNegativeFloatToFloatMap);
    method public void setMode(String);
    method public void setSetting(String);
  }

  public class NitsMap {
Loading