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

Commit 221ed8b5 authored by Daniel Solomon's avatar Daniel Solomon
Browse files

Add BrightnessThrottler data to display device config

Brightness throttler, which will be added in a future change, will be
responsible for limiting the usable range of display brightness based on
various events, such as thermal throttling. This change adds the
necessary data containers in display device config.

Bug: 206857086
Bug: 212634465
Test: atest BrightnessThrottlerTest
Change-Id: Iadff7e4c16127ccddff34a1660d13c3e00584c9a
parent 18c3cd01
Loading
Loading
Loading
Loading
+155 −0
Original line number Original line Diff line number Diff line
@@ -33,6 +33,8 @@ import android.view.DisplayAddress;
import com.android.internal.R;
import com.android.internal.R;
import com.android.internal.display.BrightnessSynchronizer;
import com.android.internal.display.BrightnessSynchronizer;
import com.android.server.display.config.BrightnessThresholds;
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.Density;
import com.android.server.display.config.DisplayConfiguration;
import com.android.server.display.config.DisplayConfiguration;
import com.android.server.display.config.DisplayQuirks;
import com.android.server.display.config.DisplayQuirks;
@@ -43,6 +45,7 @@ import com.android.server.display.config.Point;
import com.android.server.display.config.RefreshRateRange;
import com.android.server.display.config.RefreshRateRange;
import com.android.server.display.config.SensorDetails;
import com.android.server.display.config.SensorDetails;
import com.android.server.display.config.ThermalStatus;
import com.android.server.display.config.ThermalStatus;
import com.android.server.display.config.ThermalThrottling;
import com.android.server.display.config.Thresholds;
import com.android.server.display.config.Thresholds;
import com.android.server.display.config.XmlParser;
import com.android.server.display.config.XmlParser;


@@ -145,6 +148,8 @@ public class DisplayDeviceConfig {
    private DensityMap mDensityMap;
    private DensityMap mDensityMap;
    private String mLoadedFrom = null;
    private String mLoadedFrom = null;


    private BrightnessThrottlingData mBrightnessThrottlingData;

    private DisplayDeviceConfig(Context context) {
    private DisplayDeviceConfig(Context context) {
        mContext = context;
        mContext = context;
    }
    }
@@ -424,6 +429,13 @@ public class DisplayDeviceConfig {
        return mDensityMap;
        return mDensityMap;
    }
    }


    /**
     * @return brightness throttling data configuration data for the display.
     */
    public BrightnessThrottlingData getBrightnessThrottlingData() {
        return BrightnessThrottlingData.create(mBrightnessThrottlingData);
    }

    @Override
    @Override
    public String toString() {
    public String toString() {
        return "DisplayDeviceConfig{"
        return "DisplayDeviceConfig{"
@@ -441,6 +453,7 @@ public class DisplayDeviceConfig {
                + ", mQuirks=" + mQuirks
                + ", mQuirks=" + mQuirks
                + ", isHbmEnabled=" + mIsHighBrightnessModeEnabled
                + ", isHbmEnabled=" + mIsHighBrightnessModeEnabled
                + ", mHbmData=" + mHbmData
                + ", mHbmData=" + mHbmData
                + ", mBrightnessThrottlingData=" + mBrightnessThrottlingData
                + ", mBrightnessRampFastDecrease=" + mBrightnessRampFastDecrease
                + ", mBrightnessRampFastDecrease=" + mBrightnessRampFastDecrease
                + ", mBrightnessRampFastIncrease=" + mBrightnessRampFastIncrease
                + ", mBrightnessRampFastIncrease=" + mBrightnessRampFastIncrease
                + ", mBrightnessRampSlowDecrease=" + mBrightnessRampSlowDecrease
                + ", mBrightnessRampSlowDecrease=" + mBrightnessRampSlowDecrease
@@ -502,6 +515,7 @@ public class DisplayDeviceConfig {
                loadBrightnessDefaultFromDdcXml(config);
                loadBrightnessDefaultFromDdcXml(config);
                loadBrightnessConstraintsFromConfigXml();
                loadBrightnessConstraintsFromConfigXml();
                loadBrightnessMap(config);
                loadBrightnessMap(config);
                loadBrightnessThrottlingMap(config);
                loadHighBrightnessModeData(config);
                loadHighBrightnessModeData(config);
                loadQuirks(config);
                loadQuirks(config);
                loadBrightnessRamps(config);
                loadBrightnessRamps(config);
@@ -664,6 +678,41 @@ public class DisplayDeviceConfig {
        constrainNitsAndBacklightArrays();
        constrainNitsAndBacklightArrays();
    }
    }


    private void loadBrightnessThrottlingMap(DisplayConfiguration config) {
        final ThermalThrottling throttlingConfig = config.getThermalThrottling();
        if (throttlingConfig == null) {
            Slog.i(TAG, "no thermal throttling config found");
            return;
        }

        final BrightnessThrottlingMap map = throttlingConfig.getBrightnessThrottlingMap();
        if (map == null) {
            Slog.i(TAG, "no brightness throttling map found");
            return;
        }

        final List<BrightnessThrottlingPoint> points = map.getBrightnessThrottlingPoint();
        // At least 1 point is guaranteed by the display device config schema
        List<BrightnessThrottlingData.ThrottlingLevel> throttlingLevels =
            new ArrayList<>(points.size());

        boolean badConfig = false;
        for (BrightnessThrottlingPoint point : points) {
            ThermalStatus status = point.getThermalStatus();
            if (!thermalStatusIsValid(status)) {
                badConfig = true;
                break;
            }

            throttlingLevels.add(new BrightnessThrottlingData.ThrottlingLevel(
                convertThermalStatus(status), point.getBrightness().floatValue()));
        }

        if (!badConfig) {
            mBrightnessThrottlingData = BrightnessThrottlingData.create(throttlingLevels);
        }
    }

    private void loadBrightnessMapFromConfigXml() {
    private void loadBrightnessMapFromConfigXml() {
        // Use the config.xml mapping
        // Use the config.xml mapping
        final Resources res = mContext.getResources();
        final Resources res = mContext.getResources();
@@ -931,6 +980,25 @@ public class DisplayDeviceConfig {
        }
        }
    }
    }


    private boolean thermalStatusIsValid(ThermalStatus value) {
        if (value == null) {
            return false;
        }

        switch (value) {
            case none:
            case light:
            case moderate:
            case severe:
            case critical:
            case emergency:
            case shutdown:
                return true;
            default:
                return false;
        }
    }

    private @PowerManager.ThermalStatus int convertThermalStatus(ThermalStatus value) {
    private @PowerManager.ThermalStatus int convertThermalStatus(ThermalStatus value) {
        if (value == null) {
        if (value == null) {
            return PowerManager.THERMAL_STATUS_NONE;
            return PowerManager.THERMAL_STATUS_NONE;
@@ -1061,4 +1129,91 @@ public class DisplayDeviceConfig {
                    + "} ";
                    + "} ";
        }
        }
    }
    }

    /**
     * Container for brightness throttling data.
     */
    static class BrightnessThrottlingData {
        static class ThrottlingLevel {
            public @PowerManager.ThermalStatus int thermalStatus;
            public float brightness;

            ThrottlingLevel(@PowerManager.ThermalStatus int thermalStatus, float brightness) {
                this.thermalStatus = thermalStatus;
                this.brightness = brightness;
            }

            @Override
            public String toString() {
                return "[" + thermalStatus + "," + brightness + "]";
            }
        }

        public List<ThrottlingLevel> throttlingLevels;

        static public BrightnessThrottlingData create(List<ThrottlingLevel> throttlingLevels)
        {
            if (throttlingLevels == null || throttlingLevels.size() == 0) {
                Slog.e(TAG, "BrightnessThrottlingData received null or empty throttling levels");
                return null;
            }

            ThrottlingLevel prevLevel = throttlingLevels.get(0);
            final int numLevels = throttlingLevels.size();
            for (int i = 1; i < numLevels; i++) {
                ThrottlingLevel thisLevel = throttlingLevels.get(i);

                if (thisLevel.thermalStatus <= prevLevel.thermalStatus) {
                    Slog.e(TAG, "brightnessThrottlingMap must be strictly increasing, ignoring "
                            + "configuration. ThermalStatus " + thisLevel.thermalStatus + " <= "
                            + prevLevel.thermalStatus);
                    return null;
                }

                if (thisLevel.brightness >= prevLevel.brightness) {
                    Slog.e(TAG, "brightnessThrottlingMap must be strictly decreasing, ignoring "
                            + "configuration. Brightness " + thisLevel.brightness + " >= "
                            + thisLevel.brightness);
                    return null;
                }

                prevLevel = thisLevel;
            }

            for (ThrottlingLevel level : throttlingLevels) {
                // Non-negative brightness values are enforced by device config schema
                if (level.brightness > PowerManager.BRIGHTNESS_MAX) {
                    Slog.e(TAG, "brightnessThrottlingMap contains a brightness value exceeding "
                            + "system max. Brightness " + level.brightness + " > "
                            + PowerManager.BRIGHTNESS_MAX);
                    return null;
                }
            }

            return new BrightnessThrottlingData(throttlingLevels);
        }

        static public BrightnessThrottlingData create(BrightnessThrottlingData other) {
            if (other == null)
                return null;

            return BrightnessThrottlingData.create(other.throttlingLevels);
        }


        @Override
        public String toString() {
            return "BrightnessThrottlingData{"
                + "throttlingLevels:" + throttlingLevels
                + "} ";
        }

        private BrightnessThrottlingData(List<ThrottlingLevel> inLevels) {
            throttlingLevels = new ArrayList<>(inLevels.size());
            for (ThrottlingLevel level : inLevels) {
                throttlingLevels.add(new ThrottlingLevel(level.thermalStatus, level.brightness));
            }
        }

    }
}
}
+35 −0
Original line number Original line Diff line number Diff line
@@ -38,6 +38,10 @@
                    <xs:annotation name="nonnull"/>
                    <xs:annotation name="nonnull"/>
                    <xs:annotation name="final"/>
                    <xs:annotation name="final"/>
                </xs:element>
                </xs:element>
                <xs:element type="thermalThrottling" name="thermalThrottling">
                    <xs:annotation name="nonnull"/>
                    <xs:annotation name="final"/>
                </xs:element>
                <xs:element type="highBrightnessMode" name="highBrightnessMode" minOccurs="0"
                <xs:element type="highBrightnessMode" name="highBrightnessMode" minOccurs="0"
                            maxOccurs="1"/>
                            maxOccurs="1"/>
                <xs:element type="displayQuirks" name="quirks" minOccurs="0" maxOccurs="1" />
                <xs:element type="displayQuirks" name="quirks" minOccurs="0" maxOccurs="1" />
@@ -154,6 +158,37 @@
        </xs:restriction>
        </xs:restriction>
    </xs:simpleType>
    </xs:simpleType>


    <xs:complexType name="thermalThrottling">
        <xs:complexType>
            <xs:element type="brightnessThrottlingMap" name="brightnessThrottlingMap">
                <xs:annotation name="nonnull"/>
                <xs:annotation name="final"/>
            </xs:element>
        </xs:complexType>
    </xs:complexType>

    <xs:complexType name="brightnessThrottlingMap">
        <xs:sequence>
            <xs:element name="brightnessThrottlingPoint" type="brightnessThrottlingPoint" maxOccurs="unbounded" minOccurs="1">
                <xs:annotation name="nonnull"/>
                <xs:annotation name="final"/>
            </xs:element>
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="brightnessThrottlingPoint">
        <xs:sequence>
            <xs:element type="thermalStatus" name="thermalStatus">
                <xs:annotation name="nonnull"/>
                <xs:annotation name="final"/>
            </xs:element>
            <xs:element type="nonNegativeDecimal" name="brightness">
                <xs:annotation name="nonnull"/>
                <xs:annotation name="final"/>
            </xs:element>
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="nitsMap">
    <xs:complexType name="nitsMap">
        <xs:sequence>
        <xs:sequence>
            <xs:element name="point" type="point" maxOccurs="unbounded" minOccurs="2">
            <xs:element name="point" type="point" maxOccurs="unbounded" minOccurs="2">
+21 −0
Original line number Original line Diff line number Diff line
@@ -7,6 +7,19 @@ package com.android.server.display.config {
    method public final void setMinimum(@NonNull java.math.BigDecimal);
    method public final void setMinimum(@NonNull java.math.BigDecimal);
  }
  }


  public class BrightnessThrottlingMap {
    ctor public BrightnessThrottlingMap();
    method @NonNull public final java.util.List<com.android.server.display.config.BrightnessThrottlingPoint> getBrightnessThrottlingPoint();
  }

  public class BrightnessThrottlingPoint {
    ctor public BrightnessThrottlingPoint();
    method @NonNull public final java.math.BigDecimal getBrightness();
    method @NonNull public final com.android.server.display.config.ThermalStatus getThermalStatus();
    method public final void setBrightness(@NonNull java.math.BigDecimal);
    method public final void setThermalStatus(@NonNull com.android.server.display.config.ThermalStatus);
  }

  public class Density {
  public class Density {
    ctor public Density();
    ctor public Density();
    method @NonNull public final java.math.BigInteger getDensity();
    method @NonNull public final java.math.BigInteger getDensity();
@@ -39,6 +52,7 @@ package com.android.server.display.config {
    method public final java.math.BigDecimal getScreenBrightnessRampFastIncrease();
    method public final java.math.BigDecimal getScreenBrightnessRampFastIncrease();
    method public final java.math.BigDecimal getScreenBrightnessRampSlowDecrease();
    method public final java.math.BigDecimal getScreenBrightnessRampSlowDecrease();
    method public final java.math.BigDecimal getScreenBrightnessRampSlowIncrease();
    method public final java.math.BigDecimal getScreenBrightnessRampSlowIncrease();
    method @NonNull public final com.android.server.display.config.ThermalThrottling getThermalThrottling();
    method public final void setAmbientBrightnessChangeThresholds(@NonNull com.android.server.display.config.Thresholds);
    method public final void setAmbientBrightnessChangeThresholds(@NonNull com.android.server.display.config.Thresholds);
    method public final void setAmbientLightHorizonLong(java.math.BigInteger);
    method public final void setAmbientLightHorizonLong(java.math.BigInteger);
    method public final void setAmbientLightHorizonShort(java.math.BigInteger);
    method public final void setAmbientLightHorizonShort(java.math.BigInteger);
@@ -54,6 +68,7 @@ package com.android.server.display.config {
    method public final void setScreenBrightnessRampFastIncrease(java.math.BigDecimal);
    method public final void setScreenBrightnessRampFastIncrease(java.math.BigDecimal);
    method public final void setScreenBrightnessRampSlowDecrease(java.math.BigDecimal);
    method public final void setScreenBrightnessRampSlowDecrease(java.math.BigDecimal);
    method public final void setScreenBrightnessRampSlowIncrease(java.math.BigDecimal);
    method public final void setScreenBrightnessRampSlowIncrease(java.math.BigDecimal);
    method public final void setThermalThrottling(@NonNull com.android.server.display.config.ThermalThrottling);
  }
  }


  public class DisplayQuirks {
  public class DisplayQuirks {
@@ -131,6 +146,12 @@ package com.android.server.display.config {
    enum_constant public static final com.android.server.display.config.ThermalStatus shutdown;
    enum_constant public static final com.android.server.display.config.ThermalStatus shutdown;
  }
  }


  public class ThermalThrottling {
    ctor public ThermalThrottling();
    method @NonNull public final com.android.server.display.config.BrightnessThrottlingMap getBrightnessThrottlingMap();
    method public final void setBrightnessThrottlingMap(@NonNull com.android.server.display.config.BrightnessThrottlingMap);
  }

  public class Thresholds {
  public class Thresholds {
    ctor public Thresholds();
    ctor public Thresholds();
    method @NonNull public final com.android.server.display.config.BrightnessThresholds getBrighteningThresholds();
    method @NonNull public final com.android.server.display.config.BrightnessThresholds getBrighteningThresholds();
+118 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2022 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 static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;

import android.os.PowerManager;
import android.platform.test.annotations.Presubmit;

import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;

import com.android.server.display.DisplayDeviceConfig.BrightnessThrottlingData.ThrottlingLevel;
import com.android.server.display.DisplayDeviceConfig.BrightnessThrottlingData;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@SmallTest
@Presubmit
@RunWith(AndroidJUnit4.class)
public class BrightnessThrottlerTest {

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
    }

    /////////////////
    // Test Methods
    /////////////////

    @Test
    public void testBrightnessThrottlingData() {
        List<ThrottlingLevel> singleLevel = new ArrayList<>();
        singleLevel.add(new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.25f));

        List<ThrottlingLevel> validLevels = new ArrayList<>();
        validLevels.add(new ThrottlingLevel(PowerManager.THERMAL_STATUS_MODERATE, 0.62f));
        validLevels.add(new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.25f));

        List<ThrottlingLevel> invalidThermalLevels = new ArrayList<>();
        invalidThermalLevels.add(new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.62f));
        invalidThermalLevels.add(new ThrottlingLevel(PowerManager.THERMAL_STATUS_MODERATE, 0.25f));

        List<ThrottlingLevel> invalidBrightnessLevels = new ArrayList<>();
        invalidBrightnessLevels.add(
                new ThrottlingLevel(PowerManager.THERMAL_STATUS_MODERATE, 0.25f));
        invalidBrightnessLevels.add(
                new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.62f));

        List<ThrottlingLevel> invalidLevels = new ArrayList<>();
        invalidLevels.add(new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.25f));
        invalidLevels.add(new ThrottlingLevel(PowerManager.THERMAL_STATUS_MODERATE, 0.62f));

        // Test invalid data
        BrightnessThrottlingData data;
        data = BrightnessThrottlingData.create((List<ThrottlingLevel>)null);
        assertEquals(data, null);
        data = BrightnessThrottlingData.create((BrightnessThrottlingData)null);
        assertEquals(data, null);
        data = BrightnessThrottlingData.create(new ArrayList<ThrottlingLevel>());
        assertEquals(data, null);
        data = BrightnessThrottlingData.create(invalidThermalLevels);
        assertEquals(data, null);
        data = BrightnessThrottlingData.create(invalidBrightnessLevels);
        assertEquals(data, null);
        data = BrightnessThrottlingData.create(invalidLevels);
        assertEquals(data, null);

        // Test valid data
        data = BrightnessThrottlingData.create(singleLevel);
        assertNotEquals(data, null);
        assertThrottlingLevelsEquals(singleLevel, data.throttlingLevels);

        data = BrightnessThrottlingData.create(validLevels);
        assertNotEquals(data, null);
        assertThrottlingLevelsEquals(validLevels, data.throttlingLevels);
    }

    private void assertThrottlingLevelsEquals(
            List<ThrottlingLevel> expected,
            List<ThrottlingLevel> actual) {
        assertEquals(expected.size(), actual.size());

        for (int i = 0; i < expected.size(); i++) {
            ThrottlingLevel expectedLevel = expected.get(i);
            ThrottlingLevel actualLevel = actual.get(i);

            assertEquals(expectedLevel.thermalStatus, actualLevel.thermalStatus);
            assertEquals(expectedLevel.brightness, actualLevel.brightness, 0.0f);
        }
    }

}