summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony Han <modan@google.com>2019-06-11 15:28:08 -0700
committerandroid-build-merger <android-build-merger@google.com>2019-06-11 15:28:08 -0700
commit77babbe3dc067872e5725de1a8031a73dfd8a61c (patch)
treeced3970a993ff1b65660f498a1c226cf3cd15a9f
parent1708b64eb957c108daa09cdbbf57121a13866f6d (diff)
parentd3d81a9f3f16c5561da2f29f773d64e23f01a03b (diff)
Merge "Interpolate low light white balance" into qt-r1-dev am: 5622e1bff7
am: d3d81a9f3f Change-Id: I58724b464016083d8c5d4935175c0720c52426b6
-rw-r--r--core/res/res/values/config.xml25
-rw-r--r--core/res/res/values/symbols.xml3
-rw-r--r--services/core/java/com/android/server/display/whitebalance/AmbientFilter.java4
-rw-r--r--services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java61
-rw-r--r--services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java12
-rw-r--r--services/tests/servicestests/src/com/android/server/display/whitebalance/AmbientLuxTest.java299
6 files changed, 376 insertions, 28 deletions
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index c3bca6f9bead..55d80ac065c3 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4034,9 +4034,28 @@
</array>
<!-- See DisplayWhiteBalanceController.
- The ambient brightness threshold (in lux) beneath which we fall back to a fixed ambient
- color temperature. -->
- <item name="config_displayWhiteBalanceLowLightAmbientBrightnessThreshold" format="float" type="dimen">10.0</item>
+ A float array containing a list of ambient brightnesses, in Lux. This array,
+ together with config_displayWhiteBalanceLowLightAmbientBiases, is used to generate a
+ lookup table used in DisplayWhiteBalanceController. This lookup table is used to map
+ ambient brightness readings to a bias, where the bias is used to linearly interpolate
+ between ambient color temperature and
+ config_displayWhiteBalanceLowLightAmbientColorTemperature.
+ This table is optional. If used, this array must,
+ 1) Contain at least two entries
+ 2) Be the same length as config_displayWhiteBalanceLowLightAmbientBiases. -->
+ <array name ="config_displayWhiteBalanceLowLightAmbientBrightnesses">
+ <item>10.0</item>
+ <item>10.0</item>
+ </array>
+
+ <!-- See DisplayWhiteBalanceController.
+ An array containing a list of biases. See
+ config_displayWhiteBalanceLowLightAmbientBrightnesses for additional details.
+ This array must be in the range of [0.0, 1.0]. -->
+ <array name ="config_displayWhiteBalanceLowLightAmbientBiases">
+ <item>0.0</item>
+ <item>1.0</item>
+ </array>
<!-- See DisplayWhiteBalanceController.
The ambient color temperature (in cct) to which we fall back when the ambient brightness
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index ff9e379d4c4d..63d9eba45b8a 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3750,7 +3750,8 @@
<java-symbol type="array" name="config_displayWhiteBalanceBaseThresholds" />
<java-symbol type="array" name="config_displayWhiteBalanceIncreaseThresholds" />
<java-symbol type="array" name="config_displayWhiteBalanceDecreaseThresholds" />
- <java-symbol type="dimen" name="config_displayWhiteBalanceLowLightAmbientBrightnessThreshold" />
+ <java-symbol type="array" name="config_displayWhiteBalanceLowLightAmbientBrightnesses" />
+ <java-symbol type="array" name="config_displayWhiteBalanceLowLightAmbientBiases" />
<java-symbol type="dimen" name="config_displayWhiteBalanceLowLightAmbientColorTemperature" />
<java-symbol type="array" name="config_displayWhiteBalanceAmbientColorTemperatures" />
<java-symbol type="array" name="config_displayWhiteBalanceDisplayColorTemperatures" />
diff --git a/services/core/java/com/android/server/display/whitebalance/AmbientFilter.java b/services/core/java/com/android/server/display/whitebalance/AmbientFilter.java
index 532bbed9588e..123cd73a3ff3 100644
--- a/services/core/java/com/android/server/display/whitebalance/AmbientFilter.java
+++ b/services/core/java/com/android/server/display/whitebalance/AmbientFilter.java
@@ -18,6 +18,7 @@ package com.android.server.display.whitebalance;
import android.util.Slog;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.server.display.utils.RollingBuffer;
import java.io.PrintWriter;
@@ -155,7 +156,8 @@ abstract class AmbientFilter {
/**
* A weighted average prioritising recent changes.
*/
- static class WeightedMovingAverageAmbientFilter extends AmbientFilter {
+ @VisibleForTesting
+ public static class WeightedMovingAverageAmbientFilter extends AmbientFilter {
// How long the latest ambient value change is predicted to last.
private static final int PREDICTION_TIME = 100; // Milliseconds
diff --git a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
index 0f86b478468f..395319d897ad 100644
--- a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
+++ b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
@@ -20,6 +20,7 @@ import android.annotation.NonNull;
import android.util.Slog;
import android.util.Spline;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
import com.android.server.LocalServices;
import com.android.server.display.color.ColorDisplayService.ColorDisplayServiceInternal;
@@ -53,18 +54,21 @@ public class DisplayWhiteBalanceController implements
private Callbacks mCallbacks;
private AmbientSensor.AmbientBrightnessSensor mBrightnessSensor;
- private AmbientFilter mBrightnessFilter;
+
+ @VisibleForTesting
+ AmbientFilter mBrightnessFilter;
private AmbientSensor.AmbientColorTemperatureSensor mColorTemperatureSensor;
- private AmbientFilter mColorTemperatureFilter;
+
+ @VisibleForTesting
+ AmbientFilter mColorTemperatureFilter;
private DisplayWhiteBalanceThrottler mThrottler;
- // When the brightness drops below a certain threshold, it affects the color temperature
- // accuracy, so we fall back to a fixed ambient color temperature.
- private final float mLowLightAmbientBrightnessThreshold;
private final float mLowLightAmbientColorTemperature;
private float mAmbientColorTemperature;
- private float mPendingAmbientColorTemperature;
+
+ @VisibleForTesting
+ float mPendingAmbientColorTemperature;
private float mLastAmbientColorTemperature;
private ColorDisplayServiceInternal mColorDisplayServiceInternal;
@@ -79,6 +83,9 @@ public class DisplayWhiteBalanceController implements
// A piecewise linear relationship between ambient and display color temperatures.
private Spline.LinearSpline mAmbientToDisplayColorTemperatureSpline;
+ // A piecewise linear relationship between low light brightness and low light bias.
+ private Spline.LinearSpline mLowLightAmbientBrightnessToBiasSpline;
+
/**
* @param brightnessSensor
* The sensor used to detect changes in the ambient brightness.
@@ -119,7 +126,8 @@ public class DisplayWhiteBalanceController implements
@NonNull AmbientSensor.AmbientColorTemperatureSensor colorTemperatureSensor,
@NonNull AmbientFilter colorTemperatureFilter,
@NonNull DisplayWhiteBalanceThrottler throttler,
- float lowLightAmbientBrightnessThreshold, float lowLightAmbientColorTemperature,
+ float[] lowLightAmbientBrightnesses, float[] lowLightAmbientBiases,
+ float lowLightAmbientColorTemperature,
float[] ambientColorTemperatures, float[] displayColorTemperatures) {
validateArguments(brightnessSensor, brightnessFilter, colorTemperatureSensor,
colorTemperatureFilter, throttler);
@@ -131,7 +139,6 @@ public class DisplayWhiteBalanceController implements
mColorTemperatureSensor = colorTemperatureSensor;
mColorTemperatureFilter = colorTemperatureFilter;
mThrottler = throttler;
- mLowLightAmbientBrightnessThreshold = lowLightAmbientBrightnessThreshold;
mLowLightAmbientColorTemperature = lowLightAmbientColorTemperature;
mAmbientColorTemperature = -1.0f;
mPendingAmbientColorTemperature = -1.0f;
@@ -140,9 +147,27 @@ public class DisplayWhiteBalanceController implements
mAmbientColorTemperatureOverride = -1.0f;
try {
+ mLowLightAmbientBrightnessToBiasSpline = new Spline.LinearSpline(
+ lowLightAmbientBrightnesses, lowLightAmbientBiases);
+ } catch (Exception e) {
+ Slog.e(TAG, "failed to create low light ambient brightness to bias spline.", e);
+ mLowLightAmbientBrightnessToBiasSpline = null;
+ }
+ if (mLowLightAmbientBrightnessToBiasSpline != null) {
+ if (mLowLightAmbientBrightnessToBiasSpline.interpolate(0.0f) != 0.0f ||
+ mLowLightAmbientBrightnessToBiasSpline.interpolate(Float.POSITIVE_INFINITY)
+ != 1.0f) {
+ Slog.d(TAG, "invalid low light ambient brightness to bias spline, "
+ + "bias must begin at 0.0 and end at 1.0");
+ mLowLightAmbientBrightnessToBiasSpline = null;
+ }
+ }
+
+ try {
mAmbientToDisplayColorTemperatureSpline = new Spline.LinearSpline(
ambientColorTemperatures, displayColorTemperatures);
} catch (Exception e) {
+ Slog.e(TAG, "failed to create ambient to display color temperature spline.", e);
mAmbientToDisplayColorTemperatureSpline = null;
}
@@ -238,8 +263,6 @@ public class DisplayWhiteBalanceController implements
mColorTemperatureSensor.dump(writer);
mColorTemperatureFilter.dump(writer);
mThrottler.dump(writer);
- writer.println(" mLowLightAmbientBrightnessThreshold="
- + mLowLightAmbientBrightnessThreshold);
writer.println(" mLowLightAmbientColorTemperature=" + mLowLightAmbientColorTemperature);
writer.println(" mAmbientColorTemperature=" + mAmbientColorTemperature);
writer.println(" mPendingAmbientColorTemperature=" + mPendingAmbientColorTemperature);
@@ -248,6 +271,8 @@ public class DisplayWhiteBalanceController implements
writer.println(" mAmbientColorTemperatureOverride=" + mAmbientColorTemperatureOverride);
writer.println(" mAmbientToDisplayColorTemperatureSpline="
+ mAmbientToDisplayColorTemperatureSpline);
+ writer.println(" mLowLightAmbientBrightnessToBiasSpline="
+ + mLowLightAmbientBrightnessToBiasSpline);
}
@Override // AmbientSensor.AmbientBrightnessSensor.Callbacks
@@ -276,15 +301,13 @@ public class DisplayWhiteBalanceController implements
mAmbientToDisplayColorTemperatureSpline.interpolate(ambientColorTemperature);
}
- final float ambientBrightness = mBrightnessFilter.getEstimate(time);
- if (ambientBrightness < mLowLightAmbientBrightnessThreshold) {
- if (mLoggingEnabled) {
- Slog.d(TAG, "low light ambient brightness: " + ambientBrightness + " < "
- + mLowLightAmbientBrightnessThreshold
- + ", falling back to fixed ambient color temperature: "
- + ambientColorTemperature + " => " + mLowLightAmbientColorTemperature);
- }
- ambientColorTemperature = mLowLightAmbientColorTemperature;
+ float ambientBrightness = mBrightnessFilter.getEstimate(time);
+
+ if (mLowLightAmbientBrightnessToBiasSpline != null) {
+ float bias = mLowLightAmbientBrightnessToBiasSpline.interpolate(ambientBrightness);
+ ambientColorTemperature =
+ bias * ambientColorTemperature + (1.0f - bias)
+ * mLowLightAmbientColorTemperature;
}
if (mAmbientColorTemperatureOverride != -1.0f) {
diff --git a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java
index 6ff2b09988e6..b1b465e3b359 100644
--- a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java
+++ b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java
@@ -63,9 +63,12 @@ public class DisplayWhiteBalanceFactory {
createColorTemperatureSensor(handler, sensorManager, resources);
final AmbientFilter colorTemperatureFilter = createColorTemperatureFilter(resources);
final DisplayWhiteBalanceThrottler throttler = createThrottler(resources);
- final float lowLightAmbientBrightnessThreshold = getFloat(resources,
- com.android.internal.R.dimen
- .config_displayWhiteBalanceLowLightAmbientBrightnessThreshold);
+ final float[] displayWhiteBalanceLowLightAmbientBrightnesses = getFloatArray(resources,
+ com.android.internal.R.array
+ .config_displayWhiteBalanceLowLightAmbientBrightnesses);
+ final float[] displayWhiteBalanceLowLightAmbientBiases = getFloatArray(resources,
+ com.android.internal.R.array
+ .config_displayWhiteBalanceLowLightAmbientBiases);
final float lowLightAmbientColorTemperature = getFloat(resources,
com.android.internal.R.dimen
.config_displayWhiteBalanceLowLightAmbientColorTemperature);
@@ -75,7 +78,8 @@ public class DisplayWhiteBalanceFactory {
com.android.internal.R.array.config_displayWhiteBalanceDisplayColorTemperatures);
final DisplayWhiteBalanceController controller = new DisplayWhiteBalanceController(
brightnessSensor, brightnessFilter, colorTemperatureSensor, colorTemperatureFilter,
- throttler, lowLightAmbientBrightnessThreshold, lowLightAmbientColorTemperature,
+ throttler, displayWhiteBalanceLowLightAmbientBrightnesses,
+ displayWhiteBalanceLowLightAmbientBiases, lowLightAmbientColorTemperature,
ambientColorTemperatures, displayColorTempeartures);
brightnessSensor.setCallbacks(controller);
colorTemperatureSensor.setCallbacks(controller);
diff --git a/services/tests/servicestests/src/com/android/server/display/whitebalance/AmbientLuxTest.java b/services/tests/servicestests/src/com/android/server/display/whitebalance/AmbientLuxTest.java
new file mode 100644
index 000000000000..de68036d2d4c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/display/whitebalance/AmbientLuxTest.java
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2019 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.whitebalance;
+
+import com.android.internal.R;
+import com.google.common.collect.ImmutableList;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+import static org.mockito.Matchers.anyLong;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
+
+import android.content.ContextWrapper;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.TypedValue;
+
+import androidx.test.InstrumentationRegistry;
+
+import org.junit.Before;
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.List;
+
+@RunWith(JUnit4.class)
+public final class AmbientLuxTest {
+ private static final int AMBIENT_COLOR_TYPE = 20705;
+ private static final String AMBIENT_COLOR_TYPE_STR = "colorSensoryDensoryDoc";
+ private static final float LOW_LIGHT_AMBIENT_COLOR_TEMPERATURE = 5700;
+
+ private Handler mHandler = new Handler(Looper.getMainLooper());
+ private Sensor mLightSensor;
+ private Sensor mAmbientColorSensor;
+ private ContextWrapper mContextSpy;
+ private Resources mResourcesSpy;
+
+ @Mock private SensorManager mSensorManagerMock;
+
+ @Mock private TypedArray mBrightnesses;
+ @Mock private TypedArray mBiases;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mLightSensor = createSensor(Sensor.TYPE_LIGHT, null);
+ mAmbientColorSensor = createSensor(AMBIENT_COLOR_TYPE, AMBIENT_COLOR_TYPE_STR);
+ mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getContext()));
+ mResourcesSpy = spy(mContextSpy.getResources());
+ when(mContextSpy.getResources()).thenReturn(mResourcesSpy);
+ when(mSensorManagerMock.getDefaultSensor(Sensor.TYPE_LIGHT)).thenReturn(mLightSensor);
+ final List<Sensor> sensorList = ImmutableList.of(mLightSensor, mAmbientColorSensor);
+ when(mSensorManagerMock.getSensorList(Sensor.TYPE_ALL)).thenReturn(sensorList);
+ when(mResourcesSpy.getString(
+ R.string.config_displayWhiteBalanceColorTemperatureSensorName))
+ .thenReturn(AMBIENT_COLOR_TYPE_STR);
+ when(mResourcesSpy.getInteger(
+ R.integer.config_displayWhiteBalanceDecreaseDebounce))
+ .thenReturn(0);
+ when(mResourcesSpy.getInteger(
+ R.integer.config_displayWhiteBalanceIncreaseDebounce))
+ .thenReturn(0);
+ when(mResourcesSpy.getFloat(
+ R.dimen.config_displayWhiteBalanceLowLightAmbientColorTemperature))
+ .thenReturn(LOW_LIGHT_AMBIENT_COLOR_TEMPERATURE);
+ when(mResourcesSpy.obtainTypedArray(
+ R.array.config_displayWhiteBalanceAmbientColorTemperatures))
+ .thenReturn(createTypedArray());
+ when(mResourcesSpy.obtainTypedArray(
+ R.array.config_displayWhiteBalanceDisplayColorTemperatures))
+ .thenReturn(createTypedArray());
+
+ when(mResourcesSpy.obtainTypedArray(
+ R.array.config_displayWhiteBalanceLowLightAmbientBrightnesses))
+ .thenReturn(mBrightnesses);
+ when(mResourcesSpy.obtainTypedArray(
+ R.array.config_displayWhiteBalanceLowLightAmbientBiases))
+ .thenReturn(mBiases);
+ }
+
+ @Test
+ public void testNoSpline() throws Exception {
+ setBrightnesses();
+ setBiases();
+
+ DisplayWhiteBalanceController controller =
+ DisplayWhiteBalanceFactory.create(mHandler, mSensorManagerMock, mResourcesSpy);
+ final float ambientColorTemperature = 8000.0f;
+ setEstimatedColorTemperature(controller, ambientColorTemperature);
+ controller.mBrightnessFilter = spy(controller.mBrightnessFilter);
+
+ for (float luxOverride = 0.1f; luxOverride <= 10000; luxOverride *= 10) {
+ setEstimatedBrightnessAndUpdate(controller, luxOverride);
+ assertEquals(controller.mPendingAmbientColorTemperature,
+ ambientColorTemperature, 0.001);
+ }
+ }
+
+ @Test
+ public void testSpline_OneSegment() throws Exception {
+ final float lowerBrightness = 10.0f;
+ final float upperBrightness = 50.0f;
+ setBrightnesses(lowerBrightness, upperBrightness);
+ setBiases(0.0f, 1.0f);
+
+ DisplayWhiteBalanceController controller =
+ DisplayWhiteBalanceFactory.create(mHandler, mSensorManagerMock, mResourcesSpy);
+ final float ambientColorTemperature = 8000.0f;
+ setEstimatedColorTemperature(controller, ambientColorTemperature);
+ controller.mBrightnessFilter = spy(controller.mBrightnessFilter);
+
+ for (float t = 0.0f; t <= 1.0f; t += 0.1f) {
+ setEstimatedBrightnessAndUpdate(controller,
+ mix(lowerBrightness, upperBrightness, t));
+ assertEquals(controller.mPendingAmbientColorTemperature,
+ mix(LOW_LIGHT_AMBIENT_COLOR_TEMPERATURE, ambientColorTemperature, t), 0.001);
+ }
+
+ setEstimatedBrightnessAndUpdate(controller, 0.0f);
+ assertEquals(controller.mPendingAmbientColorTemperature,
+ LOW_LIGHT_AMBIENT_COLOR_TEMPERATURE, 0.001);
+
+ setEstimatedBrightnessAndUpdate(controller, upperBrightness + 1.0f);
+ assertEquals(controller.mPendingAmbientColorTemperature, ambientColorTemperature, 0.001);
+ }
+
+ @Test
+ public void testSpline_TwoSegments() throws Exception {
+ final float brightness0 = 10.0f;
+ final float brightness1 = 50.0f;
+ final float brightness2 = 60.0f;
+ setBrightnesses(brightness0, brightness1, brightness2);
+ final float bias0 = 0.0f;
+ final float bias1 = 0.25f;
+ final float bias2 = 1.0f;
+ setBiases(bias0, bias1, bias2);
+
+ DisplayWhiteBalanceController controller =
+ DisplayWhiteBalanceFactory.create(mHandler, mSensorManagerMock, mResourcesSpy);
+ final float ambientColorTemperature = 8000.0f;
+ setEstimatedColorTemperature(controller, ambientColorTemperature);
+ controller.mBrightnessFilter = spy(controller.mBrightnessFilter);
+
+ for (float t = 0.0f; t <= 1.0f; t += 0.1f) {
+ float luxOverride = mix(brightness0, brightness1, t);
+ setEstimatedBrightnessAndUpdate(controller, luxOverride);
+ float bias = mix(bias0, bias1, t);
+ assertEquals(controller.mPendingAmbientColorTemperature,
+ mix(LOW_LIGHT_AMBIENT_COLOR_TEMPERATURE, ambientColorTemperature, bias), 0.001);
+ }
+
+ for (float t = 0.0f; t <= 1.0f; t += 0.1f) {
+ float luxOverride = mix(brightness1, brightness2, t);
+ setEstimatedBrightnessAndUpdate(controller, luxOverride);
+ float bias = mix(bias1, bias2, t);
+ assertEquals(controller.mPendingAmbientColorTemperature,
+ mix(LOW_LIGHT_AMBIENT_COLOR_TEMPERATURE, ambientColorTemperature, bias), 0.001);
+ }
+
+ setEstimatedBrightnessAndUpdate(controller, 0.0f);
+ assertEquals(controller.mPendingAmbientColorTemperature,
+ LOW_LIGHT_AMBIENT_COLOR_TEMPERATURE, 0.001);
+
+ setEstimatedBrightnessAndUpdate(controller, brightness2 + 1.0f);
+ assertEquals(controller.mPendingAmbientColorTemperature, ambientColorTemperature, 0.001);
+ }
+
+ @Test
+ public void testSpline_VerticalSegment() throws Exception {
+ final float lowerBrightness = 10.0f;
+ final float upperBrightness = 10.0f;
+ setBrightnesses(lowerBrightness, upperBrightness);
+ setBiases(0.0f, 1.0f);
+
+ DisplayWhiteBalanceController controller =
+ DisplayWhiteBalanceFactory.create(mHandler, mSensorManagerMock, mResourcesSpy);
+ final float ambientColorTemperature = 8000.0f;
+ setEstimatedColorTemperature(controller, ambientColorTemperature);
+ controller.mBrightnessFilter = spy(controller.mBrightnessFilter);
+
+ setEstimatedBrightnessAndUpdate(controller, 0.0f);
+ assertEquals(controller.mPendingAmbientColorTemperature,
+ LOW_LIGHT_AMBIENT_COLOR_TEMPERATURE, 0.001);
+
+ setEstimatedBrightnessAndUpdate(controller, upperBrightness + 1.0f);
+ assertEquals(controller.mPendingAmbientColorTemperature, ambientColorTemperature, 0.001);
+ }
+
+ @Test
+ public void testSpline_InvalidBiases() throws Exception {
+ float[][] invalidBrightnesses =
+ {{10.0f, 1000.0f}, {10.0f, 1000.0f}, {10.0f, 1000.0f}, {10.0f, 1000.0f},
+ {10.0f, 1000.0f}, {-1.0f, 1.0f}, {-1.0f, 1.0f}};
+ float[][] invalidBiases =
+ {{0.0f, 2.0f}, {0.0f, 0.9f}, {0.1f, 1.0f}, {-0.1f, 1.0f},
+ {0.1f, 1.1f}, {0.0f, 1.0f}, {-2.0f, 1.0f}};
+ for (int i = 0; i < invalidBrightnesses.length; ++i) {
+ setBrightnesses(invalidBrightnesses[i][0], invalidBrightnesses[i][1]);
+ setBiases(invalidBiases[i][0], invalidBiases[i][1]);
+
+ DisplayWhiteBalanceController controller =
+ DisplayWhiteBalanceFactory.create(mHandler, mSensorManagerMock, mResourcesSpy);
+ final float ambientColorTemperature = 8000.0f;
+ setEstimatedColorTemperature(controller, ambientColorTemperature);
+ controller.mBrightnessFilter = spy(controller.mBrightnessFilter);
+
+ for (float luxOverride = 0.1f; luxOverride <= 10000; luxOverride *= 10) {
+ setEstimatedBrightnessAndUpdate(controller, luxOverride);
+ assertEquals(controller.mPendingAmbientColorTemperature,
+ ambientColorTemperature, 0.001);
+ }
+ }
+ }
+
+ private void setEstimatedColorTemperature(DisplayWhiteBalanceController controller,
+ float ambientColorTemperature) {
+ AmbientFilter colorTemperatureFilter = spy(controller.mColorTemperatureFilter);
+ controller.mColorTemperatureFilter = colorTemperatureFilter;
+ when(colorTemperatureFilter.getEstimate(anyLong())).thenReturn(ambientColorTemperature);
+ }
+
+ private void setEstimatedBrightnessAndUpdate(DisplayWhiteBalanceController controller,
+ float brightness) {
+ when(controller.mBrightnessFilter.getEstimate(anyLong())).thenReturn(brightness);
+ controller.updateAmbientColorTemperature();
+ }
+
+ private void setBrightnesses(float... vals) {
+ setFloatArrayResource(mBrightnesses, vals);
+ }
+
+ private void setBiases(float... vals) {
+ setFloatArrayResource(mBiases, vals);
+ }
+
+ private void setFloatArrayResource(TypedArray array, float[] vals) {
+ when(array.length()).thenReturn(vals.length);
+ for (int i = 0; i < vals.length; i++) {
+ when(array.getFloat(i, Float.NaN)).thenReturn(vals[i]);
+ }
+ }
+
+ private void setSensorType(Sensor sensor, int type, String strType) throws Exception {
+ Method setter = Sensor.class.getDeclaredMethod("setType", Integer.TYPE);
+ setter.setAccessible(true);
+ setter.invoke(sensor, type);
+ if (strType != null) {
+ Field f = sensor.getClass().getDeclaredField("mStringType");
+ f.setAccessible(true);
+ f.set(sensor, strType);
+ }
+ }
+
+ private Sensor createSensor(int type, String strType) throws Exception {
+ Constructor<Sensor> constr = Sensor.class.getDeclaredConstructor();
+ constr.setAccessible(true);
+ Sensor sensor = constr.newInstance();
+ setSensorType(sensor, type, strType);
+ return sensor;
+ }
+
+ private TypedArray createTypedArray() throws Exception {
+ TypedArray mockArray = mock(TypedArray.class);
+ return mockArray;
+ }
+
+ private static float mix(float a, float b, float t) {
+ return (1.0f - t) * a + t * b;
+ }
+}