diff --git a/services/core/java/com/android/server/display/BrightnessRangeController.java b/services/core/java/com/android/server/display/BrightnessRangeController.java
index 12813c82bfff5..47cde15174509 100644
--- a/services/core/java/com/android/server/display/BrightnessRangeController.java
+++ b/services/core/java/com/android/server/display/BrightnessRangeController.java
@@ -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,10 +56,16 @@ class BrightnessRangeController {
void loadFromConfig(HighBrightnessModeMetadata hbmMetadata, IBinder token,
DisplayDeviceInfo info, DisplayDeviceConfig displayDeviceConfig) {
- mHbmController.setHighBrightnessModeMetadata(hbmMetadata);
- mHbmController.resetHbmData(info.width, info.height, token, info.uniqueId,
- displayDeviceConfig.getHighBrightnessModeData(),
- displayDeviceConfig::getHdrBrightnessFromSdr);
+ applyChanges(
+ () -> mNormalBrightnessModeController.resetNbmData(
+ displayDeviceConfig.getLuxThrottlingData()),
+ () -> {
+ mHbmController.setHighBrightnessModeMetadata(hbmMetadata);
+ mHbmController.resetHbmData(info.width, info.height, token, info.uniqueId,
+ displayDeviceConfig.getHighBrightnessModeData(),
+ displayDeviceConfig::getHdrBrightnessFromSdr);
+ }
+ );
}
void stop() {
@@ -76,7 +73,10 @@ class BrightnessRangeController {
}
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();
+ }
+ }
}
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index 7a797dd2250ce..7ccfb448cf613 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -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;
* false
*
*
+ *
+ *
+ * default
+ *
+ *
+ *
+ *
*
* canSetBrightnessViaHwc
*
@@ -693,6 +713,9 @@ public class DisplayDeviceConfig {
private final Map>
mRefreshRateThrottlingMap = new HashMap<>();
+ private final Map>
+ mLuxThrottlingData = new HashMap<>();
+
@Nullable
private HostUsiVersion mHostUsiVersion;
@@ -1344,6 +1367,11 @@ public class DisplayDeviceConfig {
return hbmData;
}
+ @NonNull
+ public Map> getLuxThrottlingData() {
+ return mLuxThrottlingData;
+ }
+
public List 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 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 luxToTransitionPointMap = new HashMap<>();
+
+ List 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;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 2b5523ae52b0c..f6e074f41743a 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -2141,7 +2141,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
void postBrightnessChangeRunnable() {
- mHandler.post(mOnBrightnessChangeRunnable);
+ if (!mHandler.hasCallbacks(mOnBrightnessChangeRunnable)) {
+ mHandler.post(mOnBrightnessChangeRunnable);
+ }
}
private HighBrightnessModeController createHbmControllerLocked(
diff --git a/services/core/java/com/android/server/display/DisplayPowerController2.java b/services/core/java/com/android/server/display/DisplayPowerController2.java
index cc9f5394df9be..2e8c3420c3175 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController2.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController2.java
@@ -1788,7 +1788,9 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
}
void postBrightnessChangeRunnable() {
- mHandler.post(mOnBrightnessChangeRunnable);
+ if (!mHandler.hasCallbacks(mOnBrightnessChangeRunnable)) {
+ mHandler.post(mOnBrightnessChangeRunnable);
+ }
}
private HighBrightnessModeController createHbmControllerLocked(
diff --git a/services/core/java/com/android/server/display/NormalBrightnessModeController.java b/services/core/java/com/android/server/display/NormalBrightnessModeController.java
index 91e4a9e407db1..dbabc24412242 100644
--- a/services/core/java/com/android/server/display/NormalBrightnessModeController.java
+++ b/services/core/java/com/android/server/display/NormalBrightnessModeController.java
@@ -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 mTransitionPoints = new HashMap<>();
+ @NonNull
+ private Map> 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 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;
- }
- }
- if (mVirtualTransitionPoint != currentTransitionPoint) {
- mVirtualTransitionPoint = currentTransitionPoint;
- return true;
+ mAmbientLux = ambientLux;
+ return recalculateMaxBrightness();
+ }
+
+ 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> maxBrightnessLimits) {
+ mMaxBrightnessLimits = maxBrightnessLimits;
+ return recalculateMaxBrightness();
+ }
+
+ private boolean recalculateMaxBrightness() {
+ float foundAmbientBoundary = Float.MAX_VALUE;
+ float foundMaxBrightness = PowerManager.BRIGHTNESS_MAX;
+
+ Map maxBrightnessPoints = null;
+
+ if (mAutoBrightnessEnabled) {
+ maxBrightnessPoints = mMaxBrightnessLimits.get(BrightnessLimitMapType.ADAPTIVE);
+ }
+
+ if (maxBrightnessPoints == null) {
+ maxBrightnessPoints = mMaxBrightnessLimits.get(BrightnessLimitMapType.DEFAULT);
+ }
+
+ if (maxBrightnessPoints != null) {
+ for (Map.Entry 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;
}
}
diff --git a/services/core/xsd/display-device-config/display-device-config.xsd b/services/core/xsd/display-device-config/display-device-config.xsd
index f96ca582c28f3..7104a80c668d1 100644
--- a/services/core/xsd/display-device-config/display-device-config.xsd
+++ b/services/core/xsd/display-device-config/display-device-config.xsd
@@ -46,6 +46,8 @@
+
@@ -137,6 +139,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt
index ad6434e0c545e..507c9dccda59b 100644
--- a/services/core/xsd/display-device-config/schema/current.txt
+++ b/services/core/xsd/display-device-config/schema/current.txt
@@ -26,6 +26,14 @@ package com.android.server.display.config {
method public final java.util.List getDisplayBrightnessPoint();
}
+ public class BrightnessLimitMap {
+ ctor public BrightnessLimitMap();
+ method @NonNull public final com.android.server.display.config.NonNegativeFloatToFloatMap getMap();
+ method @NonNull public final com.android.server.display.config.PredefinedBrightnessLimitNames getType();
+ method public final void setMap(@NonNull com.android.server.display.config.NonNegativeFloatToFloatMap);
+ method public final void setType(@NonNull com.android.server.display.config.PredefinedBrightnessLimitNames);
+ }
+
public class BrightnessThresholds {
ctor public BrightnessThresholds();
method public final com.android.server.display.config.ThresholdPoints getBrightnessThresholdPoints();
@@ -89,6 +97,7 @@ package com.android.server.display.config {
method public final com.android.server.display.config.Thresholds getDisplayBrightnessChangeThresholdsIdle();
method public com.android.server.display.config.HighBrightnessMode getHighBrightnessMode();
method public final com.android.server.display.config.SensorDetails getLightSensor();
+ method public com.android.server.display.config.LuxThrottling getLuxThrottling();
method @Nullable public final String getName();
method public final com.android.server.display.config.SensorDetails getProxSensor();
method public com.android.server.display.config.DisplayQuirks getQuirks();
@@ -115,6 +124,7 @@ package com.android.server.display.config {
method public final void setDisplayBrightnessChangeThresholdsIdle(com.android.server.display.config.Thresholds);
method public void setHighBrightnessMode(com.android.server.display.config.HighBrightnessMode);
method public final void setLightSensor(com.android.server.display.config.SensorDetails);
+ method public void setLuxThrottling(com.android.server.display.config.LuxThrottling);
method public final void setName(@Nullable String);
method public final void setProxSensor(com.android.server.display.config.SensorDetails);
method public void setQuirks(com.android.server.display.config.DisplayQuirks);
@@ -173,6 +183,11 @@ package com.android.server.display.config {
method public java.util.List getItem();
}
+ public class LuxThrottling {
+ ctor public LuxThrottling();
+ method @NonNull public final java.util.List getBrightnessLimitMap();
+ }
+
public class NitsMap {
ctor public NitsMap();
method public String getInterpolation();
@@ -180,6 +195,19 @@ package com.android.server.display.config {
method public void setInterpolation(String);
}
+ public class NonNegativeFloatToFloatMap {
+ ctor public NonNegativeFloatToFloatMap();
+ method @NonNull public final java.util.List getPoint();
+ }
+
+ public class NonNegativeFloatToFloatPoint {
+ ctor public NonNegativeFloatToFloatPoint();
+ method @NonNull public final java.math.BigDecimal getFirst();
+ method @NonNull public final java.math.BigDecimal getSecond();
+ method public final void setFirst(@NonNull java.math.BigDecimal);
+ method public final void setSecond(@NonNull java.math.BigDecimal);
+ }
+
public class Point {
ctor public Point();
method @NonNull public final java.math.BigDecimal getNits();
@@ -188,6 +216,12 @@ package com.android.server.display.config {
method public final void setValue(@NonNull java.math.BigDecimal);
}
+ public enum PredefinedBrightnessLimitNames {
+ method public String getRawName();
+ enum_constant public static final com.android.server.display.config.PredefinedBrightnessLimitNames _default;
+ enum_constant public static final com.android.server.display.config.PredefinedBrightnessLimitNames adaptive;
+ }
+
public class RefreshRateConfigs {
ctor public RefreshRateConfigs();
method public final java.math.BigInteger getDefaultPeakRefreshRate();
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java
index 5837b21b89fd4..708421d2a431b 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java
@@ -52,6 +52,7 @@ 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)
@@ -376,6 +377,116 @@ public final class DisplayDeviceConfigTest {
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);
+ }
+
+ private String getValidLuxThrottling() {
+ return "\n"
+ + " \n"
+ + " adaptive\n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + " default\n"
+ + " \n"
+ + " \n"
+ + "";
+ }
+
+ private String getInvalidLuxThrottling() {
+ return "\n"
+ + " \n"
+ + " adaptive\n"
+ + " \n"
+ + " \n"
+ + " \n" // Same type, skipped
+ + " adaptive\n"
+ + " \n"
+ + " \n"
+ + " \n" // Invalid points only, skipped
+ + " default\n"
+ + " \n"
+ + " \n"
+ + "";
+ }
+
private String getRefreshThermalThrottlingMaps() {
return "\n"
+ " \n"
@@ -405,6 +516,10 @@ public final class DisplayDeviceConfigTest {
}
private String getContent() {
+ return getContent(getValidLuxThrottling());
+ }
+
+ private String getContent(String brightnessCapConfig) {
return "\n"
+ "\n"
+ "Example Display"
@@ -462,6 +577,7 @@ public final class DisplayDeviceConfigTest {
+ "\n"
+ "\n"
+ "\n"
+ + brightnessCapConfig
+ "\n"
+ "sensor_12345\n"
+ "Sensor 12345\n"
@@ -731,8 +847,12 @@ public final class DisplayDeviceConfigTest {
}
private void setupDisplayDeviceConfigFromDisplayConfigFile() throws IOException {
+ setupDisplayDeviceConfigFromDisplayConfigFile(getContent());
+ }
+
+ private void setupDisplayDeviceConfigFromDisplayConfigFile(String content) throws IOException {
Path tempFile = Files.createTempFile("display_config", ".tmp");
- Files.write(tempFile, getContent().getBytes(StandardCharsets.UTF_8));
+ Files.write(tempFile, content.getBytes(StandardCharsets.UTF_8));
mDisplayDeviceConfig = new DisplayDeviceConfig(mContext);
mDisplayDeviceConfig.initFromFile(tempFile.toFile());
}
diff --git a/services/tests/servicestests/src/com/android/server/display/NormalBrightnessModeControllerTest.java b/services/tests/servicestests/src/com/android/server/display/NormalBrightnessModeControllerTest.java
new file mode 100644
index 0000000000000..c379d6b79ee78
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/display/NormalBrightnessModeControllerTest.java
@@ -0,0 +1,116 @@
+/*
+ * 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;
+
+import static org.junit.Assert.assertEquals;
+
+import android.os.PowerManager;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.annotations.Keep;
+import com.android.server.display.DisplayDeviceConfig.BrightnessLimitMapType;
+
+import com.google.common.collect.ImmutableMap;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import junitparams.JUnitParamsRunner;
+import junitparams.Parameters;
+
+@SmallTest
+@RunWith(JUnitParamsRunner.class)
+public class NormalBrightnessModeControllerTest {
+ private static final float FLOAT_TOLERANCE = 0.001f;
+
+ private final NormalBrightnessModeController mController = new NormalBrightnessModeController();
+
+ @Keep
+ private static Object[][] brightnessData() {
+ return new Object[][]{
+ // no brightness config
+ {0, AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED, new HashMap<>(),
+ PowerManager.BRIGHTNESS_MAX},
+ {0, AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED, new HashMap<>(),
+ PowerManager.BRIGHTNESS_MAX},
+ {100, AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED, new HashMap<>(),
+ PowerManager.BRIGHTNESS_MAX},
+ // Auto brightness - on, config only for default
+ {100, AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED, ImmutableMap.of(
+ BrightnessLimitMapType.DEFAULT,
+ ImmutableMap.of(99f, 0.1f, 101f, 0.2f)
+ ), 0.2f},
+ // Auto brightness - off, config only for default
+ {100, AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED, ImmutableMap.of(
+ BrightnessLimitMapType.DEFAULT,
+ ImmutableMap.of(99f, 0.1f, 101f, 0.2f)
+ ), 0.2f},
+ // Auto brightness - off, config only for adaptive
+ {100, AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED, ImmutableMap.of(
+ BrightnessLimitMapType.ADAPTIVE,
+ ImmutableMap.of(99f, 0.1f, 101f, 0.2f)
+ ), PowerManager.BRIGHTNESS_MAX},
+ // Auto brightness - on, config only for adaptive
+ {100, AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED, ImmutableMap.of(
+ BrightnessLimitMapType.ADAPTIVE,
+ ImmutableMap.of(99f, 0.1f, 101f, 0.2f)
+ ), 0.2f},
+ // Auto brightness - on, config for both
+ {100, AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED, ImmutableMap.of(
+ BrightnessLimitMapType.DEFAULT,
+ ImmutableMap.of(99f, 0.1f, 101f, 0.2f),
+ BrightnessLimitMapType.ADAPTIVE,
+ ImmutableMap.of(99f, 0.3f, 101f, 0.4f)
+ ), 0.4f},
+ // Auto brightness - off, config for both
+ {100, AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED, ImmutableMap.of(
+ BrightnessLimitMapType.DEFAULT,
+ ImmutableMap.of(99f, 0.1f, 101f, 0.2f),
+ BrightnessLimitMapType.ADAPTIVE,
+ ImmutableMap.of(99f, 0.3f, 101f, 0.4f)
+ ), 0.2f},
+ // Auto brightness - on, config for both, ambient high
+ {1000, AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED, ImmutableMap.of(
+ BrightnessLimitMapType.DEFAULT,
+ ImmutableMap.of(1000f, 0.1f, 2000f, 0.2f),
+ BrightnessLimitMapType.ADAPTIVE,
+ ImmutableMap.of(99f, 0.3f, 101f, 0.4f)
+ ), PowerManager.BRIGHTNESS_MAX},
+ };
+ }
+
+ @Test
+ @Parameters(method = "brightnessData")
+ public void testReturnsCorrectMaxBrightness(float ambientLux, int autoBrightnessState,
+ Map> maxBrightnessConfig,
+ float expectedBrightness) {
+ setupController(ambientLux, autoBrightnessState, maxBrightnessConfig);
+
+ assertEquals(expectedBrightness, mController.getCurrentBrightnessMax(), FLOAT_TOLERANCE);
+ }
+
+ private void setupController(float ambientLux, int autoBrightnessState,
+ Map> maxBrightnessConfig) {
+ mController.onAmbientLuxChange(ambientLux);
+ mController.setAutoBrightnessState(autoBrightnessState);
+ mController.resetNbmData(maxBrightnessConfig);
+ }
+}