/* * 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 com.android.server.display.utils.DeviceConfigParsingUtils.ambientBrightnessThresholdsIntToFloat; import static com.android.server.display.utils.DeviceConfigParsingUtils.displayBrightnessThresholdsIntToFloat; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.mockito.ArgumentMatchers.anyFloat; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; import android.os.Temperature; import android.util.SparseArray; import android.util.Spline; import android.view.SurfaceControl; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.internal.R; import com.android.server.display.config.ThermalStatus; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @SmallTest @RunWith(AndroidJUnit4.class) public final class DisplayDeviceConfigTest { private static final int DEFAULT_PEAK_REFRESH_RATE = 75; private static final int DEFAULT_REFRESH_RATE = 120; private static final int DEFAULT_HIGH_BLOCKING_ZONE_REFRESH_RATE = 55; private static final int DEFAULT_LOW_BLOCKING_ZONE_REFRESH_RATE = 95; private static final int DEFAULT_REFRESH_RATE_IN_HBM_HDR = 90; private static final int DEFAULT_REFRESH_RATE_IN_HBM_SUNLIGHT = 100; private static final int[] LOW_BRIGHTNESS_THRESHOLD_OF_PEAK_REFRESH_RATE = new int[]{10, 30, -1}; private static final int[] LOW_AMBIENT_THRESHOLD_OF_PEAK_REFRESH_RATE = new int[]{-1, 1, 21}; private static final int[] HIGH_BRIGHTNESS_THRESHOLD_OF_PEAK_REFRESH_RATE = new int[]{160, -1}; private static final int[] HIGH_AMBIENT_THRESHOLD_OF_PEAK_REFRESH_RATE = new int[]{-1, 30000}; private static final float[] NITS = {2, 500, 800}; private static final float[] BRIGHTNESS = {0, 0.62f, 1}; private static final Spline NITS_TO_BRIGHTNESS_SPLINE = Spline.createSpline(NITS, BRIGHTNESS); private DisplayDeviceConfig mDisplayDeviceConfig; private static final float ZERO_DELTA = 0.0f; private static final float SMALL_DELTA = 0.0001f; @Mock private Context mContext; @Mock private Resources mResources; @Before public void setUp() { MockitoAnnotations.initMocks(this); when(mContext.getResources()).thenReturn(mResources); mockDeviceConfigs(); } @Test public void testConfigValuesFromDisplayConfig() throws IOException { setupDisplayDeviceConfigFromDisplayConfigFile(); assertEquals(mDisplayDeviceConfig.getName(), "Example Display"); assertEquals(mDisplayDeviceConfig.getAmbientHorizonLong(), 5000); assertEquals(mDisplayDeviceConfig.getAmbientHorizonShort(), 50); assertEquals(mDisplayDeviceConfig.getBrightnessRampDecreaseMaxMillis(), 3000); assertEquals(mDisplayDeviceConfig.getBrightnessRampIncreaseMaxMillis(), 2000); assertEquals(mDisplayDeviceConfig.getBrightnessRampFastDecrease(), 0.01f, ZERO_DELTA); assertEquals(mDisplayDeviceConfig.getBrightnessRampFastIncrease(), 0.02f, ZERO_DELTA); assertEquals(mDisplayDeviceConfig.getBrightnessRampSlowIncrease(), 0.04f, ZERO_DELTA); assertEquals(mDisplayDeviceConfig.getBrightnessRampSlowDecrease(), 0.03f, ZERO_DELTA); assertEquals(mDisplayDeviceConfig.getBrightnessDefault(), 0.5f, ZERO_DELTA); assertArrayEquals(mDisplayDeviceConfig.getBrightness(), BRIGHTNESS, ZERO_DELTA); assertArrayEquals(mDisplayDeviceConfig.getNits(), NITS, ZERO_DELTA); assertArrayEquals(mDisplayDeviceConfig.getBacklight(), BRIGHTNESS, ZERO_DELTA); assertEquals(mDisplayDeviceConfig.getAutoBrightnessBrighteningLightDebounce(), 2000); assertEquals(mDisplayDeviceConfig.getAutoBrightnessDarkeningLightDebounce(), 1000); assertArrayEquals(mDisplayDeviceConfig.getAutoBrightnessBrighteningLevelsLux(), new float[]{0.0f, 50.0f, 80.0f}, ZERO_DELTA); assertArrayEquals(mDisplayDeviceConfig.getAutoBrightnessBrighteningLevelsNits(), new float[]{45.32f, 75.43f}, ZERO_DELTA); // Test thresholds assertEquals(10, mDisplayDeviceConfig.getAmbientLuxBrighteningMinThreshold(), ZERO_DELTA); assertEquals(20, mDisplayDeviceConfig.getAmbientLuxBrighteningMinThresholdIdle(), ZERO_DELTA); assertEquals(30, mDisplayDeviceConfig.getAmbientLuxDarkeningMinThreshold(), ZERO_DELTA); assertEquals(40, mDisplayDeviceConfig.getAmbientLuxDarkeningMinThresholdIdle(), ZERO_DELTA); assertEquals(0.1f, mDisplayDeviceConfig.getScreenBrighteningMinThreshold(), ZERO_DELTA); assertEquals(0.2f, mDisplayDeviceConfig.getScreenBrighteningMinThresholdIdle(), ZERO_DELTA); assertEquals(0.3f, mDisplayDeviceConfig.getScreenDarkeningMinThreshold(), ZERO_DELTA); assertEquals(0.4f, mDisplayDeviceConfig.getScreenDarkeningMinThresholdIdle(), ZERO_DELTA); assertArrayEquals(new float[]{0, 0.10f, 0.20f}, mDisplayDeviceConfig.getScreenBrighteningLevels(), ZERO_DELTA); assertArrayEquals(new float[]{9, 10, 11}, mDisplayDeviceConfig.getScreenBrighteningPercentages(), ZERO_DELTA); assertArrayEquals(new float[]{0, 0.11f, 0.21f}, mDisplayDeviceConfig.getScreenDarkeningLevels(), ZERO_DELTA); assertArrayEquals(new float[]{11, 12, 13}, mDisplayDeviceConfig.getScreenDarkeningPercentages(), ZERO_DELTA); assertArrayEquals(new float[]{0, 100, 200}, mDisplayDeviceConfig.getAmbientBrighteningLevels(), ZERO_DELTA); assertArrayEquals(new float[]{13, 14, 15}, mDisplayDeviceConfig.getAmbientBrighteningPercentages(), ZERO_DELTA); assertArrayEquals(new float[]{0, 300, 400}, mDisplayDeviceConfig.getAmbientDarkeningLevels(), ZERO_DELTA); assertArrayEquals(new float[]{15, 16, 17}, mDisplayDeviceConfig.getAmbientDarkeningPercentages(), ZERO_DELTA); assertArrayEquals(new float[]{0, 0.12f, 0.22f}, mDisplayDeviceConfig.getScreenBrighteningLevelsIdle(), ZERO_DELTA); assertArrayEquals(new float[]{17, 18, 19}, mDisplayDeviceConfig.getScreenBrighteningPercentagesIdle(), ZERO_DELTA); assertArrayEquals(new float[]{0, 0.13f, 0.23f}, mDisplayDeviceConfig.getScreenDarkeningLevelsIdle(), ZERO_DELTA); assertArrayEquals(new float[]{19, 20, 21}, mDisplayDeviceConfig.getScreenDarkeningPercentagesIdle(), ZERO_DELTA); assertArrayEquals(new float[]{0, 500, 600}, mDisplayDeviceConfig.getAmbientBrighteningLevelsIdle(), ZERO_DELTA); assertArrayEquals(new float[]{21, 22, 23}, mDisplayDeviceConfig.getAmbientBrighteningPercentagesIdle(), ZERO_DELTA); assertArrayEquals(new float[]{0, 700, 800}, mDisplayDeviceConfig.getAmbientDarkeningLevelsIdle(), ZERO_DELTA); assertArrayEquals(new float[]{23, 24, 25}, mDisplayDeviceConfig.getAmbientDarkeningPercentagesIdle(), ZERO_DELTA); assertEquals(75, mDisplayDeviceConfig.getDefaultLowBlockingZoneRefreshRate()); assertEquals(90, mDisplayDeviceConfig.getDefaultHighBlockingZoneRefreshRate()); assertEquals(85, mDisplayDeviceConfig.getDefaultPeakRefreshRate()); assertEquals(45, mDisplayDeviceConfig.getDefaultRefreshRate()); assertEquals(2, mDisplayDeviceConfig.getRefreshRangeProfiles().size()); assertEquals(60, mDisplayDeviceConfig.getRefreshRange("test1").min, SMALL_DELTA); assertEquals(60, mDisplayDeviceConfig.getRefreshRange("test1").max, SMALL_DELTA); assertEquals(80, mDisplayDeviceConfig.getRefreshRange("test2").min, SMALL_DELTA); assertEquals(90, mDisplayDeviceConfig.getRefreshRange("test2").max, SMALL_DELTA); assertEquals(82, mDisplayDeviceConfig.getDefaultRefreshRateInHbmHdr()); assertEquals(83, mDisplayDeviceConfig.getDefaultRefreshRateInHbmSunlight()); assertEquals("sensor_12345", mDisplayDeviceConfig.getScreenOffBrightnessSensor().type); assertEquals("Sensor 12345", mDisplayDeviceConfig.getScreenOffBrightnessSensor().name); assertArrayEquals(new int[]{-1, 10, 20, 30, 40}, mDisplayDeviceConfig.getScreenOffBrightnessSensorValueToLux()); List defaultThrottlingLevels = new ArrayList<>(); defaultThrottlingLevels.add( new DisplayDeviceConfig.ThermalBrightnessThrottlingData.ThrottlingLevel( DisplayDeviceConfig.convertThermalStatus(ThermalStatus.light), 0.4f )); defaultThrottlingLevels.add( new DisplayDeviceConfig.ThermalBrightnessThrottlingData.ThrottlingLevel( DisplayDeviceConfig.convertThermalStatus(ThermalStatus.moderate), 0.3f )); defaultThrottlingLevels.add( new DisplayDeviceConfig.ThermalBrightnessThrottlingData.ThrottlingLevel( DisplayDeviceConfig.convertThermalStatus(ThermalStatus.severe), 0.2f )); defaultThrottlingLevels.add( new DisplayDeviceConfig.ThermalBrightnessThrottlingData.ThrottlingLevel( DisplayDeviceConfig.convertThermalStatus(ThermalStatus.critical), 0.1f )); defaultThrottlingLevels.add( new DisplayDeviceConfig.ThermalBrightnessThrottlingData.ThrottlingLevel( DisplayDeviceConfig.convertThermalStatus(ThermalStatus.emergency), 0.05f )); defaultThrottlingLevels.add( new DisplayDeviceConfig.ThermalBrightnessThrottlingData.ThrottlingLevel( DisplayDeviceConfig.convertThermalStatus(ThermalStatus.shutdown), 0.025f )); DisplayDeviceConfig.ThermalBrightnessThrottlingData defaultThrottlingData = new DisplayDeviceConfig.ThermalBrightnessThrottlingData(defaultThrottlingLevels); List concurrentThrottlingLevels = new ArrayList<>(); concurrentThrottlingLevels.add( new DisplayDeviceConfig.ThermalBrightnessThrottlingData.ThrottlingLevel( DisplayDeviceConfig.convertThermalStatus(ThermalStatus.light), 0.2f )); concurrentThrottlingLevels.add( new DisplayDeviceConfig.ThermalBrightnessThrottlingData.ThrottlingLevel( DisplayDeviceConfig.convertThermalStatus(ThermalStatus.moderate), 0.15f )); concurrentThrottlingLevels.add( new DisplayDeviceConfig.ThermalBrightnessThrottlingData.ThrottlingLevel( DisplayDeviceConfig.convertThermalStatus(ThermalStatus.severe), 0.1f )); concurrentThrottlingLevels.add( new DisplayDeviceConfig.ThermalBrightnessThrottlingData.ThrottlingLevel( DisplayDeviceConfig.convertThermalStatus(ThermalStatus.critical), 0.05f )); concurrentThrottlingLevels.add( new DisplayDeviceConfig.ThermalBrightnessThrottlingData.ThrottlingLevel( DisplayDeviceConfig.convertThermalStatus(ThermalStatus.emergency), 0.025f )); concurrentThrottlingLevels.add( new DisplayDeviceConfig.ThermalBrightnessThrottlingData.ThrottlingLevel( DisplayDeviceConfig.convertThermalStatus(ThermalStatus.shutdown), 0.0125f )); DisplayDeviceConfig.ThermalBrightnessThrottlingData concurrentThrottlingData = new DisplayDeviceConfig.ThermalBrightnessThrottlingData(concurrentThrottlingLevels); HashMap throttlingDataMap = new HashMap<>(2); throttlingDataMap.put("default", defaultThrottlingData); throttlingDataMap.put("concurrent", concurrentThrottlingData); assertEquals(throttlingDataMap, mDisplayDeviceConfig.getThermalBrightnessThrottlingDataMapByThrottlingId()); assertNotNull(mDisplayDeviceConfig.getHostUsiVersion()); assertEquals(mDisplayDeviceConfig.getHostUsiVersion().getMajorVersion(), 2); assertEquals(mDisplayDeviceConfig.getHostUsiVersion().getMinorVersion(), 0); // Max desired Hdr/SDR ratio upper-bounds the HDR brightness. assertEquals(1.0f, mDisplayDeviceConfig.getHdrBrightnessFromSdr(0.62f, Float.POSITIVE_INFINITY), ZERO_DELTA); assertEquals(0.62f, mDisplayDeviceConfig.getHdrBrightnessFromSdr(0.62f, 1.0f), ZERO_DELTA); assertEquals(0.77787f, mDisplayDeviceConfig.getHdrBrightnessFromSdr(0.62f, 1.25f), SMALL_DELTA); // Low/High zone thermal maps assertEquals(new SurfaceControl.RefreshRateRange(30, 40), mDisplayDeviceConfig.getLowBlockingZoneThermalMap() .get(Temperature.THROTTLING_CRITICAL)); assertEquals(new SurfaceControl.RefreshRateRange(40, 60), mDisplayDeviceConfig.getHighBlockingZoneThermalMap() .get(Temperature.THROTTLING_EMERGENCY)); // Todo: Add asserts for DensityMapping, // HighBrightnessModeData AmbientLightSensor, RefreshRateLimitations and ProximitySensor. } @Test public void testConfigValuesFromConfigResource() { setupDisplayDeviceConfigFromConfigResourceFile(); assertNull(mDisplayDeviceConfig.getName()); assertArrayEquals(mDisplayDeviceConfig.getAutoBrightnessBrighteningLevelsNits(), new float[]{2.0f, 200.0f, 600.0f}, ZERO_DELTA); assertArrayEquals(mDisplayDeviceConfig.getAutoBrightnessBrighteningLevelsLux(), new float[]{0.0f, 0.0f, 110.0f, 500.0f}, ZERO_DELTA); // Test thresholds assertEquals(0, mDisplayDeviceConfig.getAmbientLuxBrighteningMinThreshold(), ZERO_DELTA); assertEquals(0, mDisplayDeviceConfig.getAmbientLuxBrighteningMinThresholdIdle(), ZERO_DELTA); assertEquals(0, mDisplayDeviceConfig.getAmbientLuxDarkeningMinThreshold(), ZERO_DELTA); assertEquals(0, mDisplayDeviceConfig.getAmbientLuxDarkeningMinThresholdIdle(), ZERO_DELTA); assertEquals(0, mDisplayDeviceConfig.getScreenBrighteningMinThreshold(), ZERO_DELTA); assertEquals(0, mDisplayDeviceConfig.getScreenBrighteningMinThresholdIdle(), ZERO_DELTA); assertEquals(0, mDisplayDeviceConfig.getScreenDarkeningMinThreshold(), ZERO_DELTA); assertEquals(0, mDisplayDeviceConfig.getScreenDarkeningMinThresholdIdle(), ZERO_DELTA); // screen levels will be considered "old screen brightness scale" // and therefore will divide by 255 assertArrayEquals(new float[]{0, 42 / 255f, 43 / 255f}, mDisplayDeviceConfig.getScreenBrighteningLevels(), SMALL_DELTA); assertArrayEquals(new float[]{35, 36, 37}, mDisplayDeviceConfig.getScreenBrighteningPercentages(), ZERO_DELTA); assertArrayEquals(new float[]{0, 42 / 255f, 43 / 255f}, mDisplayDeviceConfig.getScreenDarkeningLevels(), SMALL_DELTA); assertArrayEquals(new float[]{37, 38, 39}, mDisplayDeviceConfig.getScreenDarkeningPercentages(), ZERO_DELTA); assertArrayEquals(new float[]{0, 30, 31}, mDisplayDeviceConfig.getAmbientBrighteningLevels(), ZERO_DELTA); assertArrayEquals(new float[]{27, 28, 29}, mDisplayDeviceConfig.getAmbientBrighteningPercentages(), ZERO_DELTA); assertArrayEquals(new float[]{0, 30, 31}, mDisplayDeviceConfig.getAmbientDarkeningLevels(), ZERO_DELTA); assertArrayEquals(new float[]{29, 30, 31}, mDisplayDeviceConfig.getAmbientDarkeningPercentages(), ZERO_DELTA); assertArrayEquals(new float[]{0, 42 / 255f, 43 / 255f}, mDisplayDeviceConfig.getScreenBrighteningLevelsIdle(), SMALL_DELTA); assertArrayEquals(new float[]{35, 36, 37}, mDisplayDeviceConfig.getScreenBrighteningPercentagesIdle(), ZERO_DELTA); assertArrayEquals(new float[]{0, 42 / 255f, 43 / 255f}, mDisplayDeviceConfig.getScreenDarkeningLevelsIdle(), SMALL_DELTA); assertArrayEquals(new float[]{37, 38, 39}, mDisplayDeviceConfig.getScreenDarkeningPercentagesIdle(), ZERO_DELTA); assertArrayEquals(new float[]{0, 30, 31}, mDisplayDeviceConfig.getAmbientBrighteningLevelsIdle(), ZERO_DELTA); assertArrayEquals(new float[]{27, 28, 29}, mDisplayDeviceConfig.getAmbientBrighteningPercentagesIdle(), ZERO_DELTA); assertArrayEquals(new float[]{0, 30, 31}, mDisplayDeviceConfig.getAmbientDarkeningLevelsIdle(), ZERO_DELTA); assertArrayEquals(new float[]{29, 30, 31}, mDisplayDeviceConfig.getAmbientDarkeningPercentagesIdle(), ZERO_DELTA); assertEquals(mDisplayDeviceConfig.getDefaultLowBlockingZoneRefreshRate(), DEFAULT_LOW_BLOCKING_ZONE_REFRESH_RATE); assertEquals(mDisplayDeviceConfig.getDefaultHighBlockingZoneRefreshRate(), DEFAULT_HIGH_BLOCKING_ZONE_REFRESH_RATE); assertEquals(mDisplayDeviceConfig.getDefaultPeakRefreshRate(), DEFAULT_PEAK_REFRESH_RATE); assertEquals(mDisplayDeviceConfig.getDefaultRefreshRate(), DEFAULT_REFRESH_RATE); assertEquals(0, mDisplayDeviceConfig.getRefreshRangeProfiles().size()); assertEquals(mDisplayDeviceConfig.getDefaultRefreshRateInHbmSunlight(), DEFAULT_REFRESH_RATE_IN_HBM_SUNLIGHT); assertEquals(mDisplayDeviceConfig.getDefaultRefreshRateInHbmHdr(), DEFAULT_REFRESH_RATE_IN_HBM_HDR); // Todo: Add asserts for ThermalBrightnessThrottlingData, DensityMapping, // HighBrightnessModeData AmbientLightSensor, RefreshRateLimitations and ProximitySensor. } @Test public void testThermalRefreshRateThrottlingFromDisplayConfig() throws IOException { setupDisplayDeviceConfigFromDisplayConfigFile(); SparseArray defaultMap = mDisplayDeviceConfig.getThermalRefreshRateThrottlingData(null); assertNotNull(defaultMap); assertEquals(2, defaultMap.size()); assertEquals(30, defaultMap.get(Temperature.THROTTLING_CRITICAL).min, SMALL_DELTA); assertEquals(60, defaultMap.get(Temperature.THROTTLING_CRITICAL).max, SMALL_DELTA); assertEquals(0, defaultMap.get(Temperature.THROTTLING_SHUTDOWN).min, SMALL_DELTA); assertEquals(30, defaultMap.get(Temperature.THROTTLING_SHUTDOWN).max, SMALL_DELTA); SparseArray testMap = mDisplayDeviceConfig.getThermalRefreshRateThrottlingData("test"); assertNotNull(testMap); assertEquals(1, testMap.size()); assertEquals(60, testMap.get(Temperature.THROTTLING_EMERGENCY).min, SMALL_DELTA); assertEquals(90, testMap.get(Temperature.THROTTLING_EMERGENCY).max, SMALL_DELTA); } @Test public void testValidLuxThrottling() throws Exception { setupDisplayDeviceConfigFromDisplayConfigFile(); Map> luxThrottlingData = mDisplayDeviceConfig.getLuxThrottlingData(); assertEquals(2, luxThrottlingData.size()); Map adaptiveOnBrightnessPoints = luxThrottlingData.get( DisplayDeviceConfig.BrightnessLimitMapType.ADAPTIVE); assertEquals(2, adaptiveOnBrightnessPoints.size()); assertEquals(0.3f, adaptiveOnBrightnessPoints.get(1000f), SMALL_DELTA); assertEquals(0.5f, adaptiveOnBrightnessPoints.get(5000f), SMALL_DELTA); Map adaptiveOffBrightnessPoints = luxThrottlingData.get( DisplayDeviceConfig.BrightnessLimitMapType.DEFAULT); assertEquals(2, adaptiveOffBrightnessPoints.size()); assertEquals(0.35f, adaptiveOffBrightnessPoints.get(1500f), SMALL_DELTA); assertEquals(0.55f, adaptiveOffBrightnessPoints.get(5500f), SMALL_DELTA); } @Test public void testInvalidLuxThrottling() throws Exception { setupDisplayDeviceConfigFromDisplayConfigFile(getContent(getInvalidLuxThrottling())); Map> luxThrottlingData = mDisplayDeviceConfig.getLuxThrottlingData(); assertEquals(1, luxThrottlingData.size()); Map adaptiveOnBrightnessPoints = luxThrottlingData.get( DisplayDeviceConfig.BrightnessLimitMapType.ADAPTIVE); assertEquals(1, adaptiveOnBrightnessPoints.size()); assertEquals(0.3f, adaptiveOnBrightnessPoints.get(1000f), SMALL_DELTA); } @Test public void testBlockingZoneThresholdsFromDisplayConfig() throws IOException { setupDisplayDeviceConfigFromDisplayConfigFile(); assertArrayEquals(new float[]{ NITS_TO_BRIGHTNESS_SPLINE.interpolate(50), NITS_TO_BRIGHTNESS_SPLINE.interpolate(300), NITS_TO_BRIGHTNESS_SPLINE.interpolate(300), -1}, mDisplayDeviceConfig.getLowDisplayBrightnessThresholds(), SMALL_DELTA); assertArrayEquals(new float[]{50, 60, -1, 60}, mDisplayDeviceConfig.getLowAmbientBrightnessThresholds(), ZERO_DELTA); assertArrayEquals(new float[]{ NITS_TO_BRIGHTNESS_SPLINE.interpolate(80), NITS_TO_BRIGHTNESS_SPLINE.interpolate(100), NITS_TO_BRIGHTNESS_SPLINE.interpolate(100), -1}, mDisplayDeviceConfig.getHighDisplayBrightnessThresholds(), SMALL_DELTA); assertArrayEquals(new float[]{70, 80, -1, 80}, mDisplayDeviceConfig.getHighAmbientBrightnessThresholds(), ZERO_DELTA); } @Test public void testBlockingZoneThresholdsFromConfigResource() { setupDisplayDeviceConfigFromConfigResourceFile(); assertArrayEquals(displayBrightnessThresholdsIntToFloat( LOW_BRIGHTNESS_THRESHOLD_OF_PEAK_REFRESH_RATE), mDisplayDeviceConfig.getLowDisplayBrightnessThresholds(), SMALL_DELTA); assertArrayEquals(ambientBrightnessThresholdsIntToFloat( LOW_AMBIENT_THRESHOLD_OF_PEAK_REFRESH_RATE), mDisplayDeviceConfig.getLowAmbientBrightnessThresholds(), ZERO_DELTA); assertArrayEquals(displayBrightnessThresholdsIntToFloat( HIGH_BRIGHTNESS_THRESHOLD_OF_PEAK_REFRESH_RATE), mDisplayDeviceConfig.getHighDisplayBrightnessThresholds(), SMALL_DELTA); assertArrayEquals(ambientBrightnessThresholdsIntToFloat( HIGH_AMBIENT_THRESHOLD_OF_PEAK_REFRESH_RATE), mDisplayDeviceConfig.getHighAmbientBrightnessThresholds(), ZERO_DELTA); } private String getValidLuxThrottling() { return "\n" + " \n" + " adaptive\n" + " \n" + " " + " 1000\n" + " 0.3\n" + " " + " " + " 5000\n" + " 0.5\n" + " " + " \n" + " \n" + " \n" + " default\n" + " \n" + " " + " 1500\n" + " 0.35\n" + " " + " " + " 5500\n" + " 0.55\n" + " " + " \n" + " \n" + ""; } private String getInvalidLuxThrottling() { return "\n" + " \n" + " adaptive\n" + " \n" + " " + " 1000\n" + " 0.3\n" + " " + " " // second > hbm.transitionPoint, skipped + " 1500\n" + " 0.9\n" + " " + " " // same lux value, skipped + " 1000\n" + " 0.5\n" + " " + " \n" + " \n" + " \n" // Same type, skipped + " adaptive\n" + " \n" + " " + " 2000\n" + " 0.35\n" + " " + " " + " 6000\n" + " 0.55\n" + " " + " \n" + " \n" + " \n" // Invalid points only, skipped + " default\n" + " \n" + " " + " 2500\n" + " 0.99\n" + " " + " \n" + " \n" + ""; } private String getRefreshThermalThrottlingMaps() { return "\n" + " \n" + " critical\n" + " \n" + " 30\n" + " 60\n" + " \n" + " \n" + " \n" + " shutdown\n" + " \n" + " 0\n" + " 30\n" + " \n" + " \n" + "\n" + "\n" + " \n" + " critical\n" + " \n" + " 30\n" + " 40\n" + " \n" + " \n" + "\n" + "\n" + " \n" + " emergency\n" + " \n" + " 40\n" + " 60\n" + " \n" + " \n" + "\n" + "\n" + " \n" + " emergency\n" + " \n" + " 60\n" + " 90\n" + " \n" + " \n" + "\n"; } private String getContent() { return getContent(getValidLuxThrottling()); } private String getContent(String brightnessCapConfig) { return "\n" + "\n" + "Example Display" + "\n" + "\n" + "" + BRIGHTNESS[0] + "\n" + "" + NITS[0] + "\n" + "\n" + "\n" + "" + BRIGHTNESS[1] + "\n" + "" + NITS[1] + "\n" + "\n" + "\n" + "" + BRIGHTNESS[2] + "\n" + "" + NITS[2] + "\n" + "\n" + "\n" + "\n" + "2000\n" + "1000\n" + "\n" + "\n" + "50\n" + "45.32\n" + "\n" + "\n" + "80\n" + "75.43\n" + "\n" + "\n" + "\n" + "\n" + "0.62\n" + "10000\n" + "\n" + "\n" + "1800\n" + "300\n" + "60\n" + "\n" + "\n" + "120\n" + "120\n" + "\n" + "light\n" + "false\n" + "\n" + "\n" + "2.000\n" + "4.000\n" + "\n" + "\n" + "500.0\n" + "1.6\n" + "\n" + "\n" + "\n" + brightnessCapConfig + "\n" + "sensor_12345\n" + "Sensor 12345\n" + "\n" + "\n" + "\n" + "10\n" + "\n" + "\n" + "013\n" + "\n" + "\n" + "10014\n" + "\n" + "\n" + "20015\n" + "\n" + "\n" + "\n" + "\n" + "30\n" + "\n" + "\n" + "015\n" + "\n" + "\n" + "30016\n" + "\n" + "\n" + "40017\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "0.1\n" + "\n" + "\n" + "0\n" + "9\n" + "\n" + "\n" + "0.10\n" + "10\n" + "\n" + "\n" + "0.20\n" + "11\n" + "\n" + "\n" + "\n" + "\n" + "0.3\n" + "\n" + "\n" + "011\n" + "\n" + "\n" + "0.1112\n" + "\n" + "\n" + "0.2113\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "20\n" + "\n" + "\n" + "021\n" + "\n" + "\n" + "50022\n" + "\n" + "\n" + "60023\n" + "\n" + "\n" + "\n" + "\n" + "40\n" + "\n" + "\n" + "023\n" + "\n" + "\n" + "70024\n" + "\n" + "\n" + "80025\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "0.2\n" + "\n" + "\n" + "017\n" + "\n" + "\n" + "0.1218\n" + "\n" + "\n" + "0.2219\n" + "\n" + "\n" + "\n" + "\n" + "0.4\n" + "\n" + "\n" + "019\n" + "\n" + "\n" + "0.1320\n" + "\n" + "\n" + "0.2321\n" + "\n" + "\n" + "\n" + "\n" + "0.01 " + "0.02 " + "0.03" + "0.04" + "" + "2000" + "" + "" + "3000" + "" + "5000\n" + "50\n" + "" + "2000" + "\n" + "\n" + "\n" + "\n" + "light\n" + "0.4\n" + "\n" + "\n" + "moderate\n" + "0.3\n" + "\n" + "\n" + "severe\n" + "0.2\n" + "\n" + "\n" + "critical\n" + "0.1\n" + "\n" + "\n" + "emergency\n" + "0.05\n" + "\n" + "\n" + "shutdown\n" + "0.025\n" + "\n" + "\n" + "\n" + "\n" + "light\n" + "0.2\n" + "\n" + "\n" + "moderate\n" + "0.15\n" + "\n" + "\n" + "severe\n" + "0.1\n" + "\n" + "\n" + "critical\n" + "0.05\n" + "\n" + "\n" + "emergency\n" + "0.025\n" + "\n" + "\n" + "shutdown\n" + "0.0125\n" + "\n" + "\n" + getRefreshThermalThrottlingMaps() + "\n" + "\n" + "45\n" + "85\n" + "" + "" + "\n" + "60\n" + "60\n" + "\n" + "\n" + "" + "\n" + "80\n" + "90\n" + "\n" + "\n" + "" + "82\n" + "83\n" + "\n" + "75\n" + "thermalLow" + "\n" + "\n" + "\n" + "50\n" + "50\n" + "\n" + "\n" + "60\n" + "300\n" + "\n" + "\n" + "-1\n" + "300\n" + "\n" + "\n" + "60\n" + "-1\n" + "\n" + "\n" + "\n" + "\n" + "90\n" + "thermalHigh" + "\n" + "\n" + "\n" + "70\n" + "80\n" + "\n" + "\n" + "80\n" + "100\n" + "\n" + "\n" + "-1\n" + "100\n" + "\n" + "\n" + "80\n" + "-1\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "-1\n" + "10\n" + "20\n" + "30\n" + "40\n" + "\n" + "\n" + "2\n" + "0\n" + "\n" + "\n"; } private void mockDeviceConfigs() { when(mResources.getFloat(com.android.internal.R.dimen .config_screenBrightnessSettingDefaultFloat)).thenReturn(0.5f); when(mResources.getFloat(com.android.internal.R.dimen .config_screenBrightnessSettingMaximumFloat)).thenReturn(1.0f); } private void setupDisplayDeviceConfigFromDisplayConfigFile() throws IOException { setupDisplayDeviceConfigFromDisplayConfigFile(getContent()); } private void setupDisplayDeviceConfigFromDisplayConfigFile(String content) throws IOException { Path tempFile = Files.createTempFile("display_config", ".tmp"); Files.write(tempFile, content.getBytes(StandardCharsets.UTF_8)); mDisplayDeviceConfig = new DisplayDeviceConfig(mContext); mDisplayDeviceConfig.initFromFile(tempFile.toFile()); } private void setupDisplayDeviceConfigFromConfigResourceFile() { TypedArray screenBrightnessNits = createFloatTypedArray(new float[]{2.0f, 250.0f, 650.0f}); when(mResources.obtainTypedArray( com.android.internal.R.array.config_screenBrightnessNits)) .thenReturn(screenBrightnessNits); TypedArray screenBrightnessBacklight = createFloatTypedArray(new float[]{0.0f, 120.0f, 255.0f}); when(mResources.obtainTypedArray( com.android.internal.R.array.config_screenBrightnessBacklight)) .thenReturn(screenBrightnessBacklight); when(mResources.getIntArray(com.android.internal.R.array .config_screenBrightnessBacklight)).thenReturn(new int[]{0, 120, 255}); when(mResources.getIntArray(com.android.internal.R.array .config_autoBrightnessLevels)).thenReturn(new int[]{30, 80}); when(mResources.getIntArray(com.android.internal.R.array .config_autoBrightnessDisplayValuesNits)).thenReturn(new int[]{25, 55}); TypedArray screenBrightnessLevelNits = createFloatTypedArray(new float[]{2.0f, 200.0f, 600.0f}); when(mResources.obtainTypedArray( com.android.internal.R.array.config_autoBrightnessDisplayValuesNits)) .thenReturn(screenBrightnessLevelNits); int[] screenBrightnessLevelLux = new int[]{0, 110, 500}; when(mResources.getIntArray( com.android.internal.R.array.config_autoBrightnessLevels)) .thenReturn(screenBrightnessLevelLux); // Thresholds // Config.xml requires the levels arrays to be of length N and the thresholds arrays to be // of length N+1 when(mResources.getIntArray(com.android.internal.R.array.config_ambientThresholdLevels)) .thenReturn(new int[]{30, 31}); when(mResources.getIntArray(com.android.internal.R.array.config_screenThresholdLevels)) .thenReturn(new int[]{42, 43}); when(mResources.getIntArray( com.android.internal.R.array.config_ambientBrighteningThresholds)) .thenReturn(new int[]{270, 280, 290}); when(mResources.getIntArray(com.android.internal.R.array.config_ambientDarkeningThresholds)) .thenReturn(new int[]{290, 300, 310}); when(mResources.getIntArray(R.array.config_screenBrighteningThresholds)) .thenReturn(new int[]{350, 360, 370}); when(mResources.getIntArray(R.array.config_screenDarkeningThresholds)) .thenReturn(new int[]{370, 380, 390}); // Configs related to refresh rates and blocking zones when(mResources.getInteger(R.integer.config_defaultPeakRefreshRate)) .thenReturn(DEFAULT_PEAK_REFRESH_RATE); when(mResources.getInteger(R.integer.config_defaultRefreshRate)) .thenReturn(DEFAULT_REFRESH_RATE); when(mResources.getInteger(R.integer.config_fixedRefreshRateInHighZone)) .thenReturn(DEFAULT_HIGH_BLOCKING_ZONE_REFRESH_RATE); when(mResources.getInteger(R.integer.config_defaultRefreshRateInZone)) .thenReturn(DEFAULT_LOW_BLOCKING_ZONE_REFRESH_RATE); when(mResources.getIntArray(R.array.config_brightnessThresholdsOfPeakRefreshRate)) .thenReturn(LOW_BRIGHTNESS_THRESHOLD_OF_PEAK_REFRESH_RATE); when(mResources.getIntArray(R.array.config_ambientThresholdsOfPeakRefreshRate)) .thenReturn(LOW_AMBIENT_THRESHOLD_OF_PEAK_REFRESH_RATE); when(mResources.getIntArray( R.array.config_highDisplayBrightnessThresholdsOfFixedRefreshRate)) .thenReturn(HIGH_BRIGHTNESS_THRESHOLD_OF_PEAK_REFRESH_RATE); when(mResources.getIntArray( R.array.config_highAmbientBrightnessThresholdsOfFixedRefreshRate)) .thenReturn(HIGH_AMBIENT_THRESHOLD_OF_PEAK_REFRESH_RATE); when(mResources.getInteger( R.integer.config_defaultRefreshRateInHbmHdr)) .thenReturn(DEFAULT_REFRESH_RATE_IN_HBM_HDR); when(mResources.getInteger( R.integer.config_defaultRefreshRateInHbmSunlight)) .thenReturn(DEFAULT_REFRESH_RATE_IN_HBM_SUNLIGHT); mDisplayDeviceConfig = DisplayDeviceConfig.create(mContext, true); } private TypedArray createFloatTypedArray(float[] vals) { TypedArray mockArray = mock(TypedArray.class); when(mockArray.length()).thenAnswer(invocation -> { return vals.length; }); when(mockArray.getFloat(anyInt(), anyFloat())).thenAnswer(invocation -> { final float def = (float) invocation.getArguments()[1]; if (vals == null) { return def; } int idx = (int) invocation.getArguments()[0]; if (idx >= 0 && idx < vals.length) { return vals[idx]; } else { return def; } }); return mockArray; } }