Introducing HDRClamper

Bug: b/283447291
Test: atest HdrClamperTest, see bug comment 9 for manual testing

Change-Id: I9e0ae3a02cd9427644ea133a131010ff5a4763ae
diff --git a/services/core/java/com/android/server/display/BrightnessRangeController.java b/services/core/java/com/android/server/display/BrightnessRangeController.java
index 4bfc090..64d2314 100644
--- a/services/core/java/com/android/server/display/BrightnessRangeController.java
+++ b/services/core/java/com/android/server/display/BrightnessRangeController.java
@@ -17,9 +17,11 @@
 package com.android.server.display;
 
 import android.hardware.display.BrightnessInfo;
+import android.os.Handler;
 import android.os.IBinder;
 import android.provider.DeviceConfigInterface;
 
+import com.android.server.display.brightness.clamper.HdrClamper;
 import com.android.server.display.feature.DeviceConfigParameterProvider;
 
 import java.io.PrintWriter;
@@ -31,23 +33,30 @@
     private final NormalBrightnessModeController mNormalBrightnessModeController =
             new NormalBrightnessModeController();
 
+    private final HdrClamper mHdrClamper;
+
     private final Runnable mModeChangeCallback;
     private final boolean mUseNbmController;
 
+    private final boolean mUseHdrClamper;
+
 
     BrightnessRangeController(HighBrightnessModeController hbmController,
-            Runnable modeChangeCallback, DisplayDeviceConfig displayDeviceConfig) {
+            Runnable modeChangeCallback, DisplayDeviceConfig displayDeviceConfig, Handler handler) {
         this(hbmController, modeChangeCallback, displayDeviceConfig,
+                new HdrClamper(modeChangeCallback::run, new Handler(handler.getLooper())),
                 new DeviceConfigParameterProvider(DeviceConfigInterface.REAL));
     }
 
     BrightnessRangeController(HighBrightnessModeController hbmController,
             Runnable modeChangeCallback, DisplayDeviceConfig displayDeviceConfig,
-            DeviceConfigParameterProvider configParameterProvider) {
+            HdrClamper hdrClamper, DeviceConfigParameterProvider configParameterProvider) {
         mHbmController = hbmController;
         mModeChangeCallback = modeChangeCallback;
         mUseNbmController = configParameterProvider.isNormalBrightnessControllerFeatureEnabled();
+        mUseHdrClamper = false;
         mNormalBrightnessModeController.resetNbmData(displayDeviceConfig.getLuxThrottlingData());
+        mHdrClamper = hdrClamper;
     }
 
     void dump(PrintWriter pw) {
@@ -63,6 +72,9 @@
                 () -> mNormalBrightnessModeController.onAmbientLuxChange(ambientLux),
                 () -> mHbmController.onAmbientLuxChange(ambientLux)
         );
+        if (mUseHdrClamper) {
+            mHdrClamper.onAmbientLuxChange(ambientLux);
+        }
     }
 
     float getNormalBrightnessMax() {
@@ -118,7 +130,8 @@
     }
 
     float getHdrBrightnessValue() {
-        return mHbmController.getHdrBrightnessValue();
+        float hdrBrightness =  mHbmController.getHdrBrightnessValue();
+        return Math.min(hdrBrightness, mHdrClamper.getMaxBrightness());
     }
 
     float getTransitionPoint() {
@@ -138,4 +151,8 @@
             hbmChangesFunc.run();
         }
     }
+
+    public float getHdrTransitionRate() {
+        return mHdrClamper.getTransitionRate();
+    }
 }
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 40dbabf..b7b46ea 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -677,7 +677,7 @@
         HighBrightnessModeController hbmController = createHbmControllerLocked(modeChangeCallback);
 
         mBrightnessRangeController = new BrightnessRangeController(hbmController,
-                modeChangeCallback, mDisplayDeviceConfig);
+                modeChangeCallback, mDisplayDeviceConfig, mHandler);
 
         mBrightnessThrottler = createBrightnessThrottlerLocked();
 
diff --git a/services/core/java/com/android/server/display/DisplayPowerController2.java b/services/core/java/com/android/server/display/DisplayPowerController2.java
index 460c351..7021eed 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController2.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController2.java
@@ -539,8 +539,8 @@
                 modeChangeCallback);
         mBrightnessThrottler = createBrightnessThrottlerLocked();
 
-        mBrightnessRangeController = new BrightnessRangeController(hbmController,
-                modeChangeCallback, mDisplayDeviceConfig);
+        mBrightnessRangeController = mInjector.getBrightnessRangeController(hbmController,
+                modeChangeCallback, mDisplayDeviceConfig, mHandler);
 
         mDisplayBrightnessController =
                 new DisplayBrightnessController(context, null,
@@ -1497,6 +1497,9 @@
             // allowed range.
             float animateValue = clampScreenBrightness(brightnessState);
 
+            // custom transition duration
+            float customTransitionRate = -1f;
+
             // If there are any HDR layers on the screen, we have a special brightness value that we
             // use instead. We still preserve the calculated brightness for Standard Dynamic Range
             // (SDR) layers, but the main brightness value will be the one for HDR.
@@ -1511,6 +1514,7 @@
                 // We want to scale HDR brightness level with the SDR level, we also need to restore
                 // SDR brightness immediately when entering dim or low power mode.
                 animateValue = mBrightnessRangeController.getHdrBrightnessValue();
+                customTransitionRate = mBrightnessRangeController.getHdrTransitionRate();
             }
 
             final float currentBrightness = mPowerState.getScreenBrightness();
@@ -1523,6 +1527,9 @@
                         || !isDisplayContentVisible || brightnessIsTemporary) {
                     animateScreenBrightness(animateValue, sdrAnimateValue,
                             SCREEN_ANIMATION_RATE_MINIMUM);
+                } else if (customTransitionRate > 0) {
+                    animateScreenBrightness(animateValue, sdrAnimateValue,
+                            customTransitionRate);
                 } else {
                     boolean isIncreasing = animateValue > currentBrightness;
                     final float rampSpeed;
@@ -2968,6 +2975,13 @@
                     hbmChangeCallback, hbmMetadata, context);
         }
 
+        BrightnessRangeController getBrightnessRangeController(
+                HighBrightnessModeController hbmController, Runnable modeChangeCallback,
+                DisplayDeviceConfig displayDeviceConfig, Handler handler) {
+            return new BrightnessRangeController(hbmController,
+                    modeChangeCallback, displayDeviceConfig, handler);
+        }
+
         DisplayWhiteBalanceController getDisplayWhiteBalanceController(Handler handler,
                 SensorManager sensorManager, Resources resources) {
             return DisplayWhiteBalanceFactory.create(handler,
diff --git a/services/core/java/com/android/server/display/brightness/clamper/HdrClamper.java b/services/core/java/com/android/server/display/brightness/clamper/HdrClamper.java
new file mode 100644
index 0000000..079a196
--- /dev/null
+++ b/services/core/java/com/android/server/display/brightness/clamper/HdrClamper.java
@@ -0,0 +1,132 @@
+/*
+ * 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.brightness.clamper;
+
+import android.os.Handler;
+import android.os.PowerManager;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class HdrClamper {
+
+    private final Configuration mConfiguration = new Configuration();
+
+    private final BrightnessClamperController.ClamperChangeListener mClamperChangeListener;
+
+    private final Handler mHandler;
+
+    private final Runnable mDebouncer;
+
+    private float mMaxBrightness = PowerManager.BRIGHTNESS_MAX;
+
+    // brightness change speed, in units per seconds,
+    private float mTransitionRate = -1f;
+
+    private float mDesiredMaxBrightness = PowerManager.BRIGHTNESS_MAX;
+
+    private float mDesiredTransitionDuration = -1; // in seconds
+
+    public HdrClamper(BrightnessClamperController.ClamperChangeListener clamperChangeListener,
+            Handler handler) {
+        mClamperChangeListener = clamperChangeListener;
+        mHandler = handler;
+        mDebouncer = () -> {
+            mTransitionRate = Math.abs((mMaxBrightness - mDesiredMaxBrightness)
+                    / mDesiredTransitionDuration);
+            mMaxBrightness = mDesiredMaxBrightness;
+            mClamperChangeListener.onChanged();
+        };
+    }
+
+    // Called in same looper: mHandler.getLooper()
+    public float getMaxBrightness() {
+        return mMaxBrightness;
+    }
+
+    // Called in same looper: mHandler.getLooper()
+    public float getTransitionRate() {
+        return mTransitionRate;
+    }
+
+
+    /**
+     * Updates brightness cap in response to ambient lux change.
+     * Called by ABC in same looper: mHandler.getLooper()
+     */
+    public void onAmbientLuxChange(float ambientLux) {
+        float expectedMaxBrightness = findBrightnessLimit(ambientLux);
+        if (mMaxBrightness == expectedMaxBrightness) {
+            mDesiredMaxBrightness = mMaxBrightness;
+            mDesiredTransitionDuration = -1;
+            mTransitionRate = -1f;
+            mHandler.removeCallbacks(mDebouncer);
+        } else if (mDesiredMaxBrightness != expectedMaxBrightness) {
+            mDesiredMaxBrightness = expectedMaxBrightness;
+            long debounceTime;
+            if (mDesiredMaxBrightness > mMaxBrightness) {
+                debounceTime = mConfiguration.mIncreaseConfig.mDebounceTimeMillis;
+                mDesiredTransitionDuration =
+                        (float) mConfiguration.mIncreaseConfig.mTransitionTimeMillis / 1000;
+            } else {
+                debounceTime = mConfiguration.mDecreaseConfig.mDebounceTimeMillis;
+                mDesiredTransitionDuration =
+                        (float) mConfiguration.mDecreaseConfig.mTransitionTimeMillis / 1000;
+            }
+
+            mHandler.removeCallbacks(mDebouncer);
+            mHandler.postDelayed(mDebouncer, debounceTime);
+        }
+    }
+
+    @VisibleForTesting
+    Configuration getConfiguration() {
+        return mConfiguration;
+    }
+
+    private float findBrightnessLimit(float ambientLux) {
+        float foundAmbientBoundary = Float.MAX_VALUE;
+        float foundMaxBrightness = PowerManager.BRIGHTNESS_MAX;
+        for (Map.Entry<Float, Float> brightnessPoint :
+                mConfiguration.mMaxBrightnessLimits.entrySet()) {
+            float ambientBoundary = brightnessPoint.getKey();
+            // find ambient lux upper boundary closest to current ambient lux
+            if (ambientBoundary > ambientLux && ambientBoundary < foundAmbientBoundary) {
+                foundMaxBrightness = brightnessPoint.getValue();
+                foundAmbientBoundary = ambientBoundary;
+            }
+        }
+        return foundMaxBrightness;
+    }
+
+    @VisibleForTesting
+    static class Configuration {
+        final Map<Float, Float> mMaxBrightnessLimits = new HashMap<>();
+        final TransitionConfiguration mIncreaseConfig = new TransitionConfiguration();
+
+        final TransitionConfiguration mDecreaseConfig = new TransitionConfiguration();
+    }
+
+    @VisibleForTesting
+    static class TransitionConfiguration {
+        long mDebounceTimeMillis;
+
+        long mTransitionTimeMillis;
+    }
+}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerController2Test.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerController2Test.java
index e7dc48e..11ff42b 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerController2Test.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerController2Test.java
@@ -43,6 +43,7 @@
 import android.hardware.Sensor;
 import android.hardware.SensorEventListener;
 import android.hardware.SensorManager;
+import android.hardware.display.BrightnessInfo;
 import android.hardware.display.DisplayManagerInternal.DisplayPowerCallbacks;
 import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
 import android.os.Handler;
@@ -67,7 +68,9 @@
 import com.android.server.am.BatteryStatsService;
 import com.android.server.display.RampAnimator.DualRampAnimator;
 import com.android.server.display.brightness.BrightnessEvent;
+import com.android.server.display.brightness.clamper.HdrClamper;
 import com.android.server.display.color.ColorDisplayService;
+import com.android.server.display.feature.DeviceConfigParameterProvider;
 import com.android.server.display.layout.Layout;
 import com.android.server.display.whitebalance.DisplayWhiteBalanceController;
 import com.android.server.policy.WindowManagerPolicy;
@@ -1175,6 +1178,26 @@
         verify(mHolder.displayPowerState, times(1)).stop();
     }
 
+    @Test
+    public void testRampRateForHdrContent() {
+        float clampedBrightness = 0.6f;
+        float transitionRate = 35.5f;
+
+        DisplayPowerRequest dpr = new DisplayPowerRequest();
+        when(mHolder.displayPowerState.getColorFadeLevel()).thenReturn(1.0f);
+        when(mHolder.hbmController.getHighBrightnessMode()).thenReturn(
+                BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR);
+        when(mHolder.hbmController.getHdrBrightnessValue()).thenReturn(PowerManager.BRIGHTNESS_MAX);
+        when(mHolder.hdrClamper.getMaxBrightness()).thenReturn(clampedBrightness);
+        when(mHolder.hdrClamper.getTransitionRate()).thenReturn(transitionRate);
+
+        mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+        advanceTime(1); // Run updatePowerState
+
+        verify(mHolder.animator, atLeastOnce()).animateTo(eq(clampedBrightness), anyFloat(),
+                eq(transitionRate));
+    }
+
     /**
      * Creates a mock and registers it to {@link LocalServices}.
      */
@@ -1270,12 +1293,16 @@
         final ScreenOffBrightnessSensorController screenOffBrightnessSensorController =
                 mock(ScreenOffBrightnessSensorController.class);
         final HighBrightnessModeController hbmController = mock(HighBrightnessModeController.class);
+        final HdrClamper hdrClamper = mock(HdrClamper.class);
+        final DeviceConfigParameterProvider deviceConfigParameterProvider =
+                mock(DeviceConfigParameterProvider.class);
 
         when(hbmController.getCurrentBrightnessMax()).thenReturn(PowerManager.BRIGHTNESS_MAX);
 
         TestInjector injector = spy(new TestInjector(displayPowerState, animator,
                 automaticBrightnessController, wakelockController, brightnessMappingStrategy,
-                hysteresisLevels, screenOffBrightnessSensorController, hbmController));
+                hysteresisLevels, screenOffBrightnessSensorController, hbmController, hdrClamper,
+                deviceConfigParameterProvider));
 
         final LogicalDisplay display = mock(LogicalDisplay.class);
         final DisplayDevice device = mock(DisplayDevice.class);
@@ -1293,7 +1320,7 @@
 
         return new DisplayPowerControllerHolder(dpc, display, displayPowerState, brightnessSetting,
                 animator, automaticBrightnessController, wakelockController,
-                screenOffBrightnessSensorController, hbmController, hbmMetadata,
+                screenOffBrightnessSensorController, hbmController, hdrClamper, hbmMetadata,
                 brightnessMappingStrategy, injector);
     }
 
@@ -1311,6 +1338,8 @@
         public final WakelockController wakelockController;
         public final ScreenOffBrightnessSensorController screenOffBrightnessSensorController;
         public final HighBrightnessModeController hbmController;
+
+        public final HdrClamper hdrClamper;
         public final HighBrightnessModeMetadata hbmMetadata;
         public final BrightnessMappingStrategy brightnessMappingStrategy;
         public final DisplayPowerController2.Injector injector;
@@ -1322,6 +1351,7 @@
                 WakelockController wakelockController,
                 ScreenOffBrightnessSensorController screenOffBrightnessSensorController,
                 HighBrightnessModeController hbmController,
+                HdrClamper hdrClamper,
                 HighBrightnessModeMetadata hbmMetadata,
                 BrightnessMappingStrategy brightnessMappingStrategy,
                 DisplayPowerController2.Injector injector) {
@@ -1334,6 +1364,7 @@
             this.wakelockController = wakelockController;
             this.screenOffBrightnessSensorController = screenOffBrightnessSensorController;
             this.hbmController = hbmController;
+            this.hdrClamper = hdrClamper;
             this.hbmMetadata = hbmMetadata;
             this.brightnessMappingStrategy = brightnessMappingStrategy;
             this.injector = injector;
@@ -1350,13 +1381,19 @@
         private final ScreenOffBrightnessSensorController mScreenOffBrightnessSensorController;
         private final HighBrightnessModeController mHighBrightnessModeController;
 
+        private final HdrClamper mHdrClamper;
+
+        private final DeviceConfigParameterProvider mDeviceConfigParameterProvider;
+
         TestInjector(DisplayPowerState dps, DualRampAnimator<DisplayPowerState> animator,
                 AutomaticBrightnessController automaticBrightnessController,
                 WakelockController wakelockController,
                 BrightnessMappingStrategy brightnessMappingStrategy,
                 HysteresisLevels hysteresisLevels,
                 ScreenOffBrightnessSensorController screenOffBrightnessSensorController,
-                HighBrightnessModeController highBrightnessModeController) {
+                HighBrightnessModeController highBrightnessModeController,
+                HdrClamper hdrClamper,
+                DeviceConfigParameterProvider deviceConfigParameterProvider) {
             mDisplayPowerState = dps;
             mAnimator = animator;
             mAutomaticBrightnessController = automaticBrightnessController;
@@ -1365,6 +1402,8 @@
             mHysteresisLevels = hysteresisLevels;
             mScreenOffBrightnessSensorController = screenOffBrightnessSensorController;
             mHighBrightnessModeController = highBrightnessModeController;
+            mHdrClamper = hdrClamper;
+            mDeviceConfigParameterProvider = deviceConfigParameterProvider;
         }
 
         @Override
@@ -1471,6 +1510,14 @@
         }
 
         @Override
+        BrightnessRangeController getBrightnessRangeController(
+                HighBrightnessModeController hbmController, Runnable modeChangeCallback,
+                DisplayDeviceConfig displayDeviceConfig, Handler handler) {
+            return new BrightnessRangeController(hbmController, modeChangeCallback,
+                    displayDeviceConfig, mHdrClamper, mDeviceConfigParameterProvider);
+        }
+
+        @Override
         DisplayWhiteBalanceController getDisplayWhiteBalanceController(Handler handler,
                 SensorManager sensorManager, Resources resources) {
             return mDisplayWhiteBalanceControllerMock;
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/HdrClamperTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/HdrClamperTest.java
new file mode 100644
index 0000000..0ebe46a
--- /dev/null
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/HdrClamperTest.java
@@ -0,0 +1,117 @@
+/*
+ * 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.brightness.clamper;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import android.os.PowerManager;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.server.testutils.OffsettableClock;
+import com.android.server.testutils.TestHandler;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+@SmallTest
+public class HdrClamperTest {
+
+    public static final float FLOAT_TOLERANCE = 0.0001f;
+
+    @Rule
+    public MockitoRule mRule = MockitoJUnit.rule();
+
+    @Mock
+    private BrightnessClamperController.ClamperChangeListener mMockListener;
+
+    OffsettableClock mClock = new OffsettableClock.Stopped();
+
+    private final TestHandler mTestHandler = new TestHandler(null, mClock);
+
+
+    private HdrClamper mHdrClamper;
+
+
+    @Before
+    public void setUp() {
+        mHdrClamper = new HdrClamper(mMockListener, mTestHandler);
+        configureClamper();
+    }
+
+    @Test
+    public void testClamper_AmbientLuxChangesAboveLimit() {
+        mHdrClamper.onAmbientLuxChange(500);
+
+        assertFalse(mTestHandler.hasMessagesOrCallbacks());
+        assertEquals(PowerManager.BRIGHTNESS_MAX, mHdrClamper.getMaxBrightness(), FLOAT_TOLERANCE);
+    }
+
+    @Test
+    public void testClamper_AmbientLuxChangesBelowLimit() {
+        mHdrClamper.onAmbientLuxChange(499);
+
+        assertTrue(mTestHandler.hasMessagesOrCallbacks());
+        TestHandler.MsgInfo msgInfo = mTestHandler.getPendingMessages().peek();
+        assertEquals(2000, msgInfo.sendTime);
+        assertEquals(PowerManager.BRIGHTNESS_MAX, mHdrClamper.getMaxBrightness(), FLOAT_TOLERANCE);
+
+        mClock.fastForward(2000);
+        mTestHandler.timeAdvance();
+        assertEquals(0.6f, mHdrClamper.getMaxBrightness(), FLOAT_TOLERANCE);
+    }
+
+    @Test
+    public void testClamper_AmbientLuxChangesBelowLimit_ThenFastAboveLimit() {
+        mHdrClamper.onAmbientLuxChange(499);
+        mHdrClamper.onAmbientLuxChange(500);
+
+        assertFalse(mTestHandler.hasMessagesOrCallbacks());
+        assertEquals(PowerManager.BRIGHTNESS_MAX, mHdrClamper.getMaxBrightness(), FLOAT_TOLERANCE);
+    }
+
+    @Test
+    public void testClamper_AmbientLuxChangesBelowLimit_ThenSlowlyAboveLimit() {
+        mHdrClamper.onAmbientLuxChange(499);
+        mClock.fastForward(2000);
+        mTestHandler.timeAdvance();
+
+        mHdrClamper.onAmbientLuxChange(500);
+
+        assertTrue(mTestHandler.hasMessagesOrCallbacks());
+        TestHandler.MsgInfo msgInfo = mTestHandler.getPendingMessages().peek();
+        assertEquals(3000, msgInfo.sendTime); // 2000 + 1000
+
+        mClock.fastForward(1000);
+        mTestHandler.timeAdvance();
+        assertEquals(PowerManager.BRIGHTNESS_MAX, mHdrClamper.getMaxBrightness(), FLOAT_TOLERANCE);
+    }
+
+    private void configureClamper() {
+        mHdrClamper.getConfiguration().mMaxBrightnessLimits.put(500f, 0.6f);
+        mHdrClamper.getConfiguration().mIncreaseConfig.mDebounceTimeMillis = 1000;
+        mHdrClamper.getConfiguration().mIncreaseConfig.mTransitionTimeMillis = 1500;
+        mHdrClamper.getConfiguration().mDecreaseConfig.mDebounceTimeMillis = 2000;
+        mHdrClamper.getConfiguration().mDecreaseConfig.mTransitionTimeMillis = 2500;
+    }
+}