diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index ffed68ed7d38c..f4c36c6b6ec2a 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -74,13 +74,6 @@ class AutomaticBrightnessController {
private static final int MSG_UPDATE_FOREGROUND_APP_SYNC = 5;
private static final int MSG_RUN_UPDATE = 6;
- // Length of the ambient light horizon used to calculate the long term estimate of ambient
- // light.
- private static final int AMBIENT_LIGHT_LONG_HORIZON_MILLIS = 10000;
-
- // Length of the ambient light horizon used to calculate short-term estimate of ambient light.
- private static final int AMBIENT_LIGHT_SHORT_HORIZON_MILLIS = 2000;
-
// Callbacks for requesting updates to the display's power state
private final Callbacks mCallbacks;
@@ -125,8 +118,10 @@ class AutomaticBrightnessController {
// and only then decide whether to change brightness.
private final boolean mResetAmbientLuxAfterWarmUpConfig;
- // Period of time in which to consider light samples in milliseconds.
- private final int mAmbientLightHorizon;
+ // Period of time in which to consider light samples for a short/long-term estimate of ambient
+ // light in milliseconds.
+ private final int mAmbientLightHorizonLong;
+ private final int mAmbientLightHorizonShort;
// The intercept used for the weighting calculation. This is used in order to keep all possible
// weighting values positive.
@@ -220,6 +215,7 @@ class AutomaticBrightnessController {
private Context mContext;
private int mState = AUTO_BRIGHTNESS_DISABLED;
+ private Clock mClock;
private final Injector mInjector;
AutomaticBrightnessController(Callbacks callbacks, Looper looper,
@@ -231,14 +227,16 @@ class AutomaticBrightnessController {
boolean resetAmbientLuxAfterWarmUpConfig, HysteresisLevels ambientBrightnessThresholds,
HysteresisLevels screenBrightnessThresholds, Context context,
HighBrightnessModeController hbmController,
- BrightnessMappingStrategy idleModeBrightnessMapper) {
+ BrightnessMappingStrategy idleModeBrightnessMapper, int ambientLightHorizonShort,
+ int ambientLightHorizonLong) {
this(new Injector(), callbacks, looper, sensorManager, lightSensor,
interactiveModeBrightnessMapper,
lightSensorWarmUpTime, brightnessMin, brightnessMax, dozeScaleFactor,
lightSensorRate, initialLightSensorRate, brighteningLightDebounceConfig,
darkeningLightDebounceConfig, resetAmbientLuxAfterWarmUpConfig,
ambientBrightnessThresholds, screenBrightnessThresholds, context,
- hbmController, idleModeBrightnessMapper
+ hbmController, idleModeBrightnessMapper, ambientLightHorizonShort,
+ ambientLightHorizonLong
);
}
@@ -252,8 +250,10 @@ class AutomaticBrightnessController {
boolean resetAmbientLuxAfterWarmUpConfig, HysteresisLevels ambientBrightnessThresholds,
HysteresisLevels screenBrightnessThresholds, Context context,
HighBrightnessModeController hbmController,
- BrightnessMappingStrategy idleModeBrightnessMapper) {
+ BrightnessMappingStrategy idleModeBrightnessMapper, int ambientLightHorizonShort,
+ int ambientLightHorizonLong) {
mInjector = injector;
+ mClock = injector.createClock();
mContext = context;
mCallbacks = callbacks;
mSensorManager = sensorManager;
@@ -268,15 +268,16 @@ class AutomaticBrightnessController {
mBrighteningLightDebounceConfig = brighteningLightDebounceConfig;
mDarkeningLightDebounceConfig = darkeningLightDebounceConfig;
mResetAmbientLuxAfterWarmUpConfig = resetAmbientLuxAfterWarmUpConfig;
- mAmbientLightHorizon = AMBIENT_LIGHT_LONG_HORIZON_MILLIS;
- mWeightingIntercept = AMBIENT_LIGHT_LONG_HORIZON_MILLIS;
+ mAmbientLightHorizonLong = ambientLightHorizonLong;
+ mAmbientLightHorizonShort = ambientLightHorizonShort;
+ mWeightingIntercept = ambientLightHorizonLong;
mAmbientBrightnessThresholds = ambientBrightnessThresholds;
mScreenBrightnessThresholds = screenBrightnessThresholds;
mShortTermModelValid = true;
mShortTermModelAnchor = -1;
mHandler = new AutomaticBrightnessHandler(looper);
mAmbientLightRingBuffer =
- new AmbientLightRingBuffer(mNormalLightSensorRate, mAmbientLightHorizon);
+ new AmbientLightRingBuffer(mNormalLightSensorRate, mAmbientLightHorizonLong, mClock);
if (!DEBUG_PRETEND_LIGHT_SENSOR_ABSENT) {
mLightSensor = lightSensor;
@@ -397,6 +398,11 @@ class AutomaticBrightnessController {
mHandler.sendEmptyMessage(MSG_RUN_UPDATE);
}
+ @VisibleForTesting
+ float getAmbientLux() {
+ return mAmbientLux;
+ }
+
private boolean setDisplayPolicy(int policy) {
if (mDisplayPolicy == policy) {
return false;
@@ -476,7 +482,8 @@ class AutomaticBrightnessController {
pw.println(" mBrighteningLightDebounceConfig=" + mBrighteningLightDebounceConfig);
pw.println(" mDarkeningLightDebounceConfig=" + mDarkeningLightDebounceConfig);
pw.println(" mResetAmbientLuxAfterWarmUpConfig=" + mResetAmbientLuxAfterWarmUpConfig);
- pw.println(" mAmbientLightHorizon=" + mAmbientLightHorizon);
+ pw.println(" mAmbientLightHorizonLong=" + mAmbientLightHorizonLong);
+ pw.println(" mAmbientLightHorizonShort=" + mAmbientLightHorizonShort);
pw.println(" mWeightingIntercept=" + mWeightingIntercept);
pw.println();
@@ -545,7 +552,7 @@ class AutomaticBrightnessController {
if (enable) {
if (!mLightSensorEnabled) {
mLightSensorEnabled = true;
- mLightSensorEnableTime = SystemClock.uptimeMillis();
+ mLightSensorEnableTime = mClock.uptimeMillis();
mCurrentLightSensorRate = mInitialLightSensorRate;
registerForegroundAppUpdater();
mSensorManager.registerListener(mLightSensorListener, mLightSensor,
@@ -580,7 +587,7 @@ class AutomaticBrightnessController {
private void applyLightSensorMeasurement(long time, float lux) {
mRecentLightSamples++;
- mAmbientLightRingBuffer.prune(time - mAmbientLightHorizon);
+ mAmbientLightRingBuffer.prune(time - mAmbientLightHorizonLong);
mAmbientLightRingBuffer.push(time, lux);
// Remember this sample value.
@@ -721,8 +728,8 @@ class AutomaticBrightnessController {
}
private void updateAmbientLux() {
- long time = SystemClock.uptimeMillis();
- mAmbientLightRingBuffer.prune(time - mAmbientLightHorizon);
+ long time = mClock.uptimeMillis();
+ mAmbientLightRingBuffer.prune(time - mAmbientLightHorizonLong);
updateAmbientLux(time);
}
@@ -742,7 +749,7 @@ class AutomaticBrightnessController {
timeWhenSensorWarmedUp);
return;
}
- setAmbientLux(calculateAmbientLux(time, AMBIENT_LIGHT_SHORT_HORIZON_MILLIS));
+ setAmbientLux(calculateAmbientLux(time, mAmbientLightHorizonShort));
mAmbientLuxValid = true;
if (mLoggingEnabled) {
Slog.d(TAG, "updateAmbientLux: Initializing: " +
@@ -762,8 +769,8 @@ class AutomaticBrightnessController {
// proposed ambient light value since the slow value might be sufficiently far enough away
// from the fast value to cause a recalculation while its actually just converging on
// the fast value still.
- float slowAmbientLux = calculateAmbientLux(time, AMBIENT_LIGHT_LONG_HORIZON_MILLIS);
- float fastAmbientLux = calculateAmbientLux(time, AMBIENT_LIGHT_SHORT_HORIZON_MILLIS);
+ float slowAmbientLux = calculateAmbientLux(time, mAmbientLightHorizonLong);
+ float fastAmbientLux = calculateAmbientLux(time, mAmbientLightHorizonShort);
if ((slowAmbientLux >= mAmbientBrighteningThreshold
&& fastAmbientLux >= mAmbientBrighteningThreshold
@@ -1044,7 +1051,7 @@ class AutomaticBrightnessController {
@Override
public void onSensorChanged(SensorEvent event) {
if (mLightSensorEnabled) {
- final long time = SystemClock.uptimeMillis();
+ final long time = mClock.uptimeMillis();
final float lux = event.values[0];
handleLightSensorEvent(time, lux);
}
@@ -1070,6 +1077,15 @@ class AutomaticBrightnessController {
void updateBrightness();
}
+ /** Functional interface for providing time. */
+ @VisibleForTesting
+ interface Clock {
+ /**
+ * Returns current time in milliseconds since boot, not counting time spent in deep sleep.
+ */
+ long uptimeMillis();
+ }
+
/**
* A ring buffer of ambient light measurements sorted by time.
*
@@ -1089,14 +1105,16 @@ class AutomaticBrightnessController {
private int mStart;
private int mEnd;
private int mCount;
+ Clock mClock;
- public AmbientLightRingBuffer(long lightSensorRate, int ambientLightHorizon) {
+ public AmbientLightRingBuffer(long lightSensorRate, int ambientLightHorizon, Clock clock) {
if (lightSensorRate <= 0) {
throw new IllegalArgumentException("lightSensorRate must be above 0");
}
mCapacity = (int) Math.ceil(ambientLightHorizon * BUFFER_SLACK / lightSensorRate);
mRingLux = new float[mCapacity];
mRingTime = new long[mCapacity];
+ mClock = clock;
}
public float getLux(int index) {
@@ -1181,7 +1199,7 @@ class AutomaticBrightnessController {
StringBuilder buf = new StringBuilder();
buf.append('[');
for (int i = 0; i < mCount; i++) {
- final long next = i + 1 < mCount ? getTime(i + 1) : SystemClock.uptimeMillis();
+ final long next = i + 1 < mCount ? getTime(i + 1) : mClock.uptimeMillis();
if (i != 0) {
buf.append(", ");
}
@@ -1210,5 +1228,9 @@ class AutomaticBrightnessController {
public Handler getBackgroundThreadHandler() {
return BackgroundThread.getHandler();
}
+
+ Clock createClock() {
+ return SystemClock::uptimeMillis;
+ }
}
}
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index a9e1647446cb8..3df2422071b82 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -52,6 +52,7 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
+import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -86,6 +87,13 @@ public class DisplayDeviceConfig {
private static final float NITS_INVALID = -1;
+ // Length of the ambient light horizon used to calculate the long term estimate of ambient
+ // light.
+ private static final int AMBIENT_LIGHT_LONG_HORIZON_MILLIS = 10000;
+
+ // Length of the ambient light horizon used to calculate short-term estimate of ambient light.
+ private static final int AMBIENT_LIGHT_SHORT_HORIZON_MILLIS = 2000;
+
private final Context mContext;
// The details of the ambient light sensor associated with this display.
@@ -120,6 +128,8 @@ public class DisplayDeviceConfig {
private float mBrightnessRampFastIncrease = Float.NaN;
private float mBrightnessRampSlowDecrease = Float.NaN;
private float mBrightnessRampSlowIncrease = Float.NaN;
+ private int mAmbientHorizonLong = AMBIENT_LIGHT_LONG_HORIZON_MILLIS;
+ private int mAmbientHorizonShort = AMBIENT_LIGHT_SHORT_HORIZON_MILLIS;
private Spline mBrightnessToBacklightSpline;
private Spline mBacklightToBrightnessSpline;
private Spline mBacklightToNitsSpline;
@@ -346,6 +356,14 @@ public class DisplayDeviceConfig {
return mBrightnessRampSlowIncrease;
}
+ public int getAmbientHorizonLong() {
+ return mAmbientHorizonLong;
+ }
+
+ public int getAmbientHorizonShort() {
+ return mAmbientHorizonShort;
+ }
+
SensorData getAmbientLightSensor() {
return mAmbientLightSensor;
}
@@ -405,6 +423,8 @@ public class DisplayDeviceConfig {
+ ", mBrightnessRampFastIncrease=" + mBrightnessRampFastIncrease
+ ", mBrightnessRampSlowDecrease=" + mBrightnessRampSlowDecrease
+ ", mBrightnessRampSlowIncrease=" + mBrightnessRampSlowIncrease
+ + ", mAmbientHorizonLong=" + mAmbientHorizonLong
+ + ", mAmbientHorizonShort=" + mAmbientHorizonShort
+ ", mAmbientLightSensor=" + mAmbientLightSensor
+ ", mProximitySensor=" + mProximitySensor
+ ", mRefreshRateLimitations= " + Arrays.toString(mRefreshRateLimitations.toArray())
@@ -461,6 +481,7 @@ public class DisplayDeviceConfig {
loadBrightnessRamps(config);
loadAmbientLightSensorFromDdc(config);
loadProxSensorFromDdc(config);
+ loadAmbientHorizonFromDdc(config);
} else {
Slog.w(TAG, "DisplayDeviceConfig file is null");
}
@@ -869,6 +890,17 @@ public class DisplayDeviceConfig {
}
}
+ private void loadAmbientHorizonFromDdc(DisplayConfiguration config) {
+ final BigInteger configLongHorizon = config.getAmbientLightHorizonLong();
+ if (configLongHorizon != null) {
+ mAmbientHorizonLong = configLongHorizon.intValue();
+ }
+ final BigInteger configShortHorizon = config.getAmbientLightHorizonShort();
+ if (configShortHorizon != null) {
+ mAmbientHorizonShort = configShortHorizon.intValue();
+ }
+ }
+
static class SensorData {
public String type;
public String name;
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index faf0038b29c8d..34f915e41cd77 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -957,7 +957,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
lightSensorRate, initialLightSensorRate, brighteningLightDebounce,
darkeningLightDebounce, autoBrightnessResetAmbientLuxAfterWarmUp,
ambientBrightnessThresholds, screenBrightnessThresholds, mContext,
- mHbmController, mIdleModeBrightnessMapper);
+ mHbmController, mIdleModeBrightnessMapper,
+ mDisplayDeviceConfig.getAmbientHorizonShort(),
+ mDisplayDeviceConfig.getAmbientHorizonLong());
} else {
mUseSoftwareAutoBrightnessConfig = 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 2f4dd57ab15b0..baf2ede07fa30 100644
--- a/services/core/xsd/display-device-config/display-device-config.xsd
+++ b/services/core/xsd/display-device-config/display-device-config.xsd
@@ -58,6 +58,15 @@
+
+
+
+
+
+
+
+
diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt
index 5b2b87c3f14e4..6f97431b48739 100644
--- a/services/core/xsd/display-device-config/schema/current.txt
+++ b/services/core/xsd/display-device-config/schema/current.txt
@@ -18,6 +18,8 @@ package com.android.server.display.config {
public class DisplayConfiguration {
ctor public DisplayConfiguration();
+ method public final java.math.BigInteger getAmbientLightHorizonLong();
+ method public final java.math.BigInteger getAmbientLightHorizonShort();
method @Nullable public final com.android.server.display.config.DensityMap getDensityMap();
method public com.android.server.display.config.HighBrightnessMode getHighBrightnessMode();
method public final com.android.server.display.config.SensorDetails getLightSensor();
@@ -29,6 +31,8 @@ package com.android.server.display.config {
method public final java.math.BigDecimal getScreenBrightnessRampFastIncrease();
method public final java.math.BigDecimal getScreenBrightnessRampSlowDecrease();
method public final java.math.BigDecimal getScreenBrightnessRampSlowIncrease();
+ method public final void setAmbientLightHorizonLong(java.math.BigInteger);
+ method public final void setAmbientLightHorizonShort(java.math.BigInteger);
method public final void setDensityMap(@Nullable com.android.server.display.config.DensityMap);
method public void setHighBrightnessMode(com.android.server.display.config.HighBrightnessMode);
method public final void setLightSensor(com.android.server.display.config.SensorDetails);
diff --git a/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java b/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
index 176e5a9fdc512..54945e44fee58 100644
--- a/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
@@ -19,6 +19,7 @@ package com.android.server.display;
import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyFloat;
@@ -34,18 +35,22 @@ import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
import android.os.Handler;
+import android.os.test.TestLooper;
import android.platform.test.annotations.Presubmit;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.server.testutils.OffsettableClock;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
@SmallTest
@@ -61,7 +66,11 @@ public class AutomaticBrightnessControllerTest {
private static final float DOZE_SCALE_FACTOR = 0.0f;
private static final boolean RESET_AMBIENT_LUX_AFTER_WARMUP_CONFIG = false;
private static final int LIGHT_SENSOR_WARMUP_TIME = 0;
-
+ private static final int AMBIENT_LIGHT_HORIZON_SHORT = 1000;
+ private static final int AMBIENT_LIGHT_HORIZON_LONG = 2000;
+ private static final float EPSILON = 0.001f;
+ private OffsettableClock mClock = new OffsettableClock();
+ private TestLooper mTestLooper;
private Context mContext;
private AutomaticBrightnessController mController;
@@ -91,21 +100,36 @@ public class AutomaticBrightnessControllerTest {
}
}
+ private void advanceTime(long timeMs) {
+ mClock.fastForward(timeMs);
+ mTestLooper.dispatchAll();
+ }
+
private AutomaticBrightnessController setupController(Sensor lightSensor) {
+ mClock = new OffsettableClock.Stopped();
+ mTestLooper = new TestLooper(mClock::now);
+
AutomaticBrightnessController controller = new AutomaticBrightnessController(
new AutomaticBrightnessController.Injector() {
@Override
public Handler getBackgroundThreadHandler() {
return mNoOpHandler;
}
- },
- () -> { }, mContext.getMainLooper(), mSensorManager, lightSensor,
+
+ @Override
+ AutomaticBrightnessController.Clock createClock() {
+ return mClock::now;
+ }
+
+ }, // pass in test looper instead, pass in offsetable clock
+ () -> { }, mTestLooper.getLooper(), mSensorManager, lightSensor,
mBrightnessMappingStrategy, LIGHT_SENSOR_WARMUP_TIME, BRIGHTNESS_MIN_FLOAT,
BRIGHTNESS_MAX_FLOAT, DOZE_SCALE_FACTOR, LIGHT_SENSOR_RATE,
INITIAL_LIGHT_SENSOR_RATE, BRIGHTENING_LIGHT_DEBOUNCE_CONFIG,
DARKENING_LIGHT_DEBOUNCE_CONFIG, RESET_AMBIENT_LUX_AFTER_WARMUP_CONFIG,
mAmbientBrightnessThresholds, mScreenBrightnessThresholds,
- mContext, mHbmController, mIdleBrightnessMappingStrategy
+ mContext, mHbmController, mIdleBrightnessMappingStrategy,
+ AMBIENT_LIGHT_HORIZON_SHORT, AMBIENT_LIGHT_HORIZON_LONG
);
when(mHbmController.getCurrentBrightnessMax()).thenReturn(BRIGHTNESS_MAX_FLOAT);
@@ -276,4 +300,95 @@ public class AutomaticBrightnessControllerTest {
// Ensure we use the correct mapping strategy
verify(mIdleBrightnessMappingStrategy, times(1)).addUserDataPoint(1000f, 0.5f);
}
+
+ @Test
+ public void testAmbientLightHorizon() throws Exception {
+ // create abc
+ Sensor lightSensor = TestUtils.createSensor(Sensor.TYPE_LIGHT, "Light Sensor");
+ mController = setupController(lightSensor);
+ ArgumentCaptor listenerCaptor =
+ ArgumentCaptor.forClass(SensorEventListener.class);
+ verify(mSensorManager).registerListener(listenerCaptor.capture(), eq(lightSensor),
+ eq(INITIAL_LIGHT_SENSOR_RATE * 1000), any(Handler.class));
+ SensorEventListener listener = listenerCaptor.getValue();
+
+ long increment = 500;
+ // set autobrightness to low
+ // t = 0
+ listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 0));
+
+ // t = 500
+ mClock.fastForward(increment);
+ listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 0));
+
+ // t = 1000
+ mClock.fastForward(increment);
+ listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 0));
+ assertEquals(0.0f, mController.getAmbientLux(), EPSILON);
+
+ // t = 1500
+ mClock.fastForward(increment);
+ listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 0));
+ assertEquals(0.0f, mController.getAmbientLux(), EPSILON);
+
+ // t = 2000
+ // ensure that our reading is at 0.
+ mClock.fastForward(increment);
+ listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 0));
+ assertEquals(0.0f, mController.getAmbientLux(), EPSILON);
+
+ // t = 2500
+ // first 10000 lux sensor event reading
+ mClock.fastForward(increment);
+ listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 10000));
+ assertTrue(mController.getAmbientLux() > 0.0f);
+ assertTrue(mController.getAmbientLux() < 10000.0f);
+
+ // t = 3000
+ // lux reading should still not yet be 10000.
+ mClock.fastForward(increment);
+ listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 10000));
+ assertTrue(mController.getAmbientLux() > 0.0f);
+ assertTrue(mController.getAmbientLux() < 10000.0f);
+
+ // t = 3500
+ mClock.fastForward(increment);
+ // lux has been high (10000) for 1000ms.
+ // lux reading should be 10000
+ // short horizon (ambient lux) is high, long horizon is still not high
+ listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 10000));
+ assertEquals(10000.0f, mController.getAmbientLux(), EPSILON);
+
+ // t = 4000
+ // stay high
+ mClock.fastForward(increment);
+ listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 10000));
+ assertEquals(10000.0f, mController.getAmbientLux(), EPSILON);
+
+ // t = 4500
+ Mockito.clearInvocations(mBrightnessMappingStrategy);
+ mClock.fastForward(increment);
+ // short horizon is high, long horizon is high too
+ listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 10000));
+ verify(mBrightnessMappingStrategy, times(1)).getBrightness(10000, null, -1);
+ assertEquals(10000.0f, mController.getAmbientLux(), EPSILON);
+
+ // t = 5000
+ mClock.fastForward(increment);
+ listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 0));
+ assertTrue(mController.getAmbientLux() > 0.0f);
+ assertTrue(mController.getAmbientLux() < 10000.0f);
+
+ // t = 5500
+ mClock.fastForward(increment);
+ listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 0));
+ assertTrue(mController.getAmbientLux() > 0.0f);
+ assertTrue(mController.getAmbientLux() < 10000.0f);
+
+ // t = 6000
+ mClock.fastForward(increment);
+ // ambient lux goes to 0
+ listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 0));
+ assertEquals(0.0f, mController.getAmbientLux(), EPSILON);
+ }
}