Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0c8297c4 authored by Anthony Han's avatar Anthony Han
Browse files

Interpolate high light white balance

In very high lux conditions, add an option to force a
cooler white balance cct to maximize display brightness.

Test: atest AmbientLuxTest
Bug: 134417265
Change-Id: I3db16eaf66c38955e2b11db11c766b85b8a0b5b8
parent 0aa57fe0
Loading
Loading
Loading
Loading
+29 −2
Original line number Diff line number Diff line
@@ -4045,10 +4045,37 @@
    </array>

    <!-- See DisplayWhiteBalanceController.
         The ambient color temperature (in cct) to which we fall back when the ambient brightness
         drops beneath a certain threshold. -->
         The ambient color temperature (in cct) to which we interpolate towards using the
         the look up table generated by config_displayWhiteBalanceLowLightAmbientBrightnesses
         and config_displayWhiteBalanceLowLightAmbientBiases. -->
    <item name="config_displayWhiteBalanceLowLightAmbientColorTemperature" format="float" type="dimen">6500.0</item>

    <!-- See DisplayWhiteBalanceController.
         A float array containing a list of ambient brightnesses, in Lux. This array,
         together with config_displayWhiteBalanceHighLightAmbientBiases, 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_displayWhiteBalanceHighLightAmbientColorTemperature.
         This table is optional. If used, this array must,
         1) Contain at least two entries
         2) Be the same length as config_displayWhiteBalanceHighLightAmbientBiases. -->
    <array name ="config_displayWhiteBalanceHighLightAmbientBrightnesses">
    </array>

    <!-- See DisplayWhiteBalanceController.
         An array containing a list of biases. See
         config_displayWhiteBalanceHighLightAmbientBrightnesses for additional details.
         This array must be in the range of [0.0, 1.0]. -->
    <array name ="config_displayWhiteBalanceHighLightAmbientBiases">
    </array>

    <!-- See DisplayWhiteBalanceController.
         The ambient color temperature (in cct) to which we interpolate towards using the
         the look up table generated by config_displayWhiteBalanceHighLightAmbientBrightnesses
         and config_displayWhiteBalanceHighLightAmbientBiases. -->
    <item name="config_displayWhiteBalanceHighLightAmbientColorTemperature" format="float" type="dimen">8000.0</item>

    <!-- See DisplayWhiteBalanceController.
         A float array containing a list of ambient color temperatures, in Kelvin. This array,
         together with config_displayWhiteBalanceDisplayColorTemperatures, is used to generate a
+3 −0
Original line number Diff line number Diff line
@@ -3749,6 +3749,9 @@
  <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_displayWhiteBalanceHighLightAmbientBrightnesses" />
  <java-symbol type="array" name="config_displayWhiteBalanceHighLightAmbientBiases" />
  <java-symbol type="dimen" name="config_displayWhiteBalanceHighLightAmbientColorTemperature" />
  <java-symbol type="array" name="config_displayWhiteBalanceAmbientColorTemperatures" />
  <java-symbol type="array" name="config_displayWhiteBalanceDisplayColorTemperatures" />
  <java-symbol type="drawable" name="ic_action_open" />
+65 −6
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ public class DisplayWhiteBalanceController implements
    private DisplayWhiteBalanceThrottler mThrottler;

    private final float mLowLightAmbientColorTemperature;
    private final float mHighLightAmbientColorTemperature;

    private float mAmbientColorTemperature;

@@ -83,9 +84,17 @@ public class DisplayWhiteBalanceController implements
    // A piecewise linear relationship between ambient and display color temperatures.
    private Spline.LinearSpline mAmbientToDisplayColorTemperatureSpline;

    // In very low or very high brightness conditions ambient EQ should to set to a default
    // instead of using mAmbientToDisplayColorTemperatureSpline. However, setting ambient EQ
    // based on thresholds can cause the display to rapidly change color temperature. To solve
    // this, mLowLightAmbientBrightnessToBiasSpline and mHighLightAmbientBrightnessToBiasSpline
    // are used to smoothly interpolate from ambient color temperature to the defaults.
    // A piecewise linear relationship between low light brightness and low light bias.
    private Spline.LinearSpline mLowLightAmbientBrightnessToBiasSpline;

    // A piecewise linear relationship between high light brightness and high light bias.
    private Spline.LinearSpline mHighLightAmbientBrightnessToBiasSpline;

    /**
     * @param brightnessSensor
     *      The sensor used to detect changes in the ambient brightness.
@@ -100,12 +109,22 @@ public class DisplayWhiteBalanceController implements
     * @param throttler
     *      The throttler used to determine whether the new display color temperature should be
     *      updated or not.
     * @param lowLightAmbientBrightnessThreshold
     *      The ambient brightness threshold beneath which we fall back to a fixed ambient color
     *      temperature.
     * @param lowLightAmbientBrightnesses
     *      The ambient brightness used to map the ambient brightnesses to the biases used to
     *      interpolate to lowLightAmbientColorTemperature.
     * @param lowLightAmbientBiases
     *      The biases used to map the ambient brightnesses to the biases used to interpolate to
     *      lowLightAmbientColorTemperature.
     * @param lowLightAmbientColorTemperature
     *      The ambient color temperature to which we fall back when the ambient brightness drops
     *      beneath a certain threshold.
     *      The ambient color temperature to which we interpolate to based on the low light curve.
     * @param highLightAmbientBrightnesses
     *      The ambient brightness used to map the ambient brightnesses to the biases used to
     *      interpolate to highLightAmbientColorTemperature.
     * @param highLightAmbientBiases
     *      The biases used to map the ambient brightnesses to the biases used to interpolate to
     *      highLightAmbientColorTemperature.
     * @param highLightAmbientColorTemperature
     *      The ambient color temperature to which we interpolate to based on the high light curve.
     * @param ambientColorTemperatures
     *      The ambient color tempeartures used to map the ambient color temperature to the display
     *      color temperature (or null if no mapping is necessary).
@@ -128,6 +147,8 @@ public class DisplayWhiteBalanceController implements
            @NonNull DisplayWhiteBalanceThrottler throttler,
            float[] lowLightAmbientBrightnesses, float[] lowLightAmbientBiases,
            float lowLightAmbientColorTemperature,
            float[] highLightAmbientBrightnesses, float[] highLightAmbientBiases,
            float highLightAmbientColorTemperature,
            float[] ambientColorTemperatures, float[] displayColorTemperatures) {
        validateArguments(brightnessSensor, brightnessFilter, colorTemperatureSensor,
                colorTemperatureFilter, throttler);
@@ -140,6 +161,7 @@ public class DisplayWhiteBalanceController implements
        mColorTemperatureFilter = colorTemperatureFilter;
        mThrottler = throttler;
        mLowLightAmbientColorTemperature = lowLightAmbientColorTemperature;
        mHighLightAmbientColorTemperature = highLightAmbientColorTemperature;
        mAmbientColorTemperature = -1.0f;
        mPendingAmbientColorTemperature = -1.0f;
        mLastAmbientColorTemperature = -1.0f;
@@ -158,8 +180,36 @@ public class DisplayWhiteBalanceController implements
                    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");
                        + "bias must begin at 0.0 and end at 1.0.");
                mLowLightAmbientBrightnessToBiasSpline = null;
            }
        }

        try {
            mHighLightAmbientBrightnessToBiasSpline = new Spline.LinearSpline(
                    highLightAmbientBrightnesses, highLightAmbientBiases);
        } catch (Exception e) {
            Slog.e(TAG, "failed to create high light ambient brightness to bias spline.", e);
            mHighLightAmbientBrightnessToBiasSpline = null;
        }
        if (mHighLightAmbientBrightnessToBiasSpline != null) {
            if (mHighLightAmbientBrightnessToBiasSpline.interpolate(0.0f) != 0.0f ||
                    mHighLightAmbientBrightnessToBiasSpline.interpolate(Float.POSITIVE_INFINITY)
                    != 1.0f) {
                Slog.d(TAG, "invalid high light ambient brightness to bias spline, "
                        + "bias must begin at 0.0 and end at 1.0.");
                mHighLightAmbientBrightnessToBiasSpline = null;
            }
        }

        if (mLowLightAmbientBrightnessToBiasSpline != null &&
                mHighLightAmbientBrightnessToBiasSpline != null) {
            if (lowLightAmbientBrightnesses[lowLightAmbientBrightnesses.length - 1] >
                    highLightAmbientBrightnesses[0]) {
                Slog.d(TAG, "invalid low light and high light ambient brightness to bias spline "
                        + "combination, defined domains must not intersect.");
                mLowLightAmbientBrightnessToBiasSpline = null;
                mHighLightAmbientBrightnessToBiasSpline = null;
            }
        }

@@ -264,6 +314,7 @@ public class DisplayWhiteBalanceController implements
        mColorTemperatureFilter.dump(writer);
        mThrottler.dump(writer);
        writer.println("  mLowLightAmbientColorTemperature=" + mLowLightAmbientColorTemperature);
        writer.println("  mHighLightAmbientColorTemperature=" + mHighLightAmbientColorTemperature);
        writer.println("  mAmbientColorTemperature=" + mAmbientColorTemperature);
        writer.println("  mPendingAmbientColorTemperature=" + mPendingAmbientColorTemperature);
        writer.println("  mLastAmbientColorTemperature=" + mLastAmbientColorTemperature);
@@ -273,6 +324,8 @@ public class DisplayWhiteBalanceController implements
                + mAmbientToDisplayColorTemperatureSpline);
        writer.println("  mLowLightAmbientBrightnessToBiasSpline="
                + mLowLightAmbientBrightnessToBiasSpline);
        writer.println("  mHighLightAmbientBrightnessToBiasSpline="
                + mHighLightAmbientBrightnessToBiasSpline);
    }

    @Override // AmbientSensor.AmbientBrightnessSensor.Callbacks
@@ -309,6 +362,12 @@ public class DisplayWhiteBalanceController implements
                    bias * ambientColorTemperature + (1.0f - bias)
                    * mLowLightAmbientColorTemperature;
        }
        if (mHighLightAmbientBrightnessToBiasSpline != null) {
            float bias = mHighLightAmbientBrightnessToBiasSpline.interpolate(ambientBrightness);
            ambientColorTemperature =
                    (1.0f - bias) * ambientColorTemperature + bias
                    * mHighLightAmbientColorTemperature;
        }

        if (mAmbientColorTemperatureOverride != -1.0f) {
            if (mLoggingEnabled) {
+11 −0
Original line number Diff line number Diff line
@@ -72,6 +72,15 @@ public class DisplayWhiteBalanceFactory {
        final float lowLightAmbientColorTemperature = getFloat(resources,
                com.android.internal.R.dimen
                .config_displayWhiteBalanceLowLightAmbientColorTemperature);
        final float[] displayWhiteBalanceHighLightAmbientBrightnesses = getFloatArray(resources,
                com.android.internal.R.array
                .config_displayWhiteBalanceHighLightAmbientBrightnesses);
        final float[] displayWhiteBalanceHighLightAmbientBiases = getFloatArray(resources,
                com.android.internal.R.array
                .config_displayWhiteBalanceHighLightAmbientBiases);
        final float highLightAmbientColorTemperature = getFloat(resources,
                com.android.internal.R.dimen
                .config_displayWhiteBalanceHighLightAmbientColorTemperature);
        final float[] ambientColorTemperatures = getFloatArray(resources,
                com.android.internal.R.array.config_displayWhiteBalanceAmbientColorTemperatures);
        final float[] displayColorTempeartures = getFloatArray(resources,
@@ -80,6 +89,8 @@ public class DisplayWhiteBalanceFactory {
                brightnessSensor, brightnessFilter, colorTemperatureSensor, colorTemperatureFilter,
                throttler, displayWhiteBalanceLowLightAmbientBrightnesses,
                displayWhiteBalanceLowLightAmbientBiases, lowLightAmbientColorTemperature,
                displayWhiteBalanceHighLightAmbientBrightnesses,
                displayWhiteBalanceHighLightAmbientBiases, highLightAmbientColorTemperature,
                ambientColorTemperatures, displayColorTempeartures);
        brightnessSensor.setCallbacks(controller);
        colorTemperatureSensor.setCallbacks(controller);
+179 −15
Original line number Diff line number Diff line
@@ -23,7 +23,12 @@ 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.Mockito.doAnswer;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.eq;
import org.mockito.stubbing.Answer;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
@@ -56,7 +61,8 @@ import java.util.List;
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 static final float LOW_LIGHT_AMBIENT_COLOR_TEMPERATURE = 5432.1f;
    private static final float HIGH_LIGHT_AMBIENT_COLOR_TEMPERATURE = 3456.7f;

    private Handler mHandler = new Handler(Looper.getMainLooper());
    private Sensor mLightSensor;
@@ -68,6 +74,8 @@ public final class AmbientLuxTest {

    @Mock private TypedArray mBrightnesses;
    @Mock private TypedArray mBiases;
    @Mock private TypedArray mHighLightBrightnesses;
    @Mock private TypedArray mHighLightBiases;

    @Before
    public void setUp() throws Exception {
@@ -89,9 +97,10 @@ public final class AmbientLuxTest {
        when(mResourcesSpy.getInteger(
                R.integer.config_displayWhiteBalanceIncreaseDebounce))
                .thenReturn(0);
        when(mResourcesSpy.getFloat(
                R.dimen.config_displayWhiteBalanceLowLightAmbientColorTemperature))
                .thenReturn(LOW_LIGHT_AMBIENT_COLOR_TEMPERATURE);
        mockResourcesFloat(R.dimen.config_displayWhiteBalanceLowLightAmbientColorTemperature,
                LOW_LIGHT_AMBIENT_COLOR_TEMPERATURE);
        mockResourcesFloat(R.dimen.config_displayWhiteBalanceHighLightAmbientColorTemperature,
                HIGH_LIGHT_AMBIENT_COLOR_TEMPERATURE);
        when(mResourcesSpy.obtainTypedArray(
                R.array.config_displayWhiteBalanceAmbientColorTemperatures))
                .thenReturn(createTypedArray());
@@ -105,6 +114,13 @@ public final class AmbientLuxTest {
        when(mResourcesSpy.obtainTypedArray(
                R.array.config_displayWhiteBalanceLowLightAmbientBiases))
                .thenReturn(mBiases);
        when(mResourcesSpy.obtainTypedArray(
                R.array.config_displayWhiteBalanceHighLightAmbientBrightnesses))
                .thenReturn(mHighLightBrightnesses);
        when(mResourcesSpy.obtainTypedArray(
                R.array.config_displayWhiteBalanceHighLightAmbientBiases))
                .thenReturn(mHighLightBiases);
        mockThrottler();
    }

    @Test
@@ -216,16 +232,27 @@ public final class AmbientLuxTest {
    }

    @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]);
    public void testSpline_InvalidEndBias() throws Exception {
        setBrightnesses(10.0f, 1000.0f);
        setBiases(0.0f, 2.0f);

        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_InvalidBeginBias() throws Exception {
        setBrightnesses(10.0f, 1000.0f);
        setBiases(0.1f, 1.0f);

        DisplayWhiteBalanceController controller =
                DisplayWhiteBalanceFactory.create(mHandler, mSensorManagerMock, mResourcesSpy);
@@ -239,6 +266,135 @@ public final class AmbientLuxTest {
                ambientColorTemperature, 0.001);
        }
    }

    @Test
    public void testSpline_OneSegmentHighLight() throws Exception {
        final float lowerBrightness = 10.0f;
        final float upperBrightness = 50.0f;
        setHighLightBrightnesses(lowerBrightness, upperBrightness);
        setHighLightBiases(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(HIGH_LIGHT_AMBIENT_COLOR_TEMPERATURE, ambientColorTemperature, 1.0f - t),
                    0.001);
        }

        setEstimatedBrightnessAndUpdate(controller, upperBrightness + 1.0f);
        assertEquals(controller.mPendingAmbientColorTemperature,
                HIGH_LIGHT_AMBIENT_COLOR_TEMPERATURE, 0.001);

        setEstimatedBrightnessAndUpdate(controller, 0.0f);
        assertEquals(controller.mPendingAmbientColorTemperature, ambientColorTemperature, 0.001);
    }

    @Test
    public void testSpline_TwoSegmentsHighLight() throws Exception {
        final float brightness0 = 10.0f;
        final float brightness1 = 50.0f;
        final float brightness2 = 60.0f;
        setHighLightBrightnesses(brightness0, brightness1, brightness2);
        final float bias0 = 0.0f;
        final float bias1 = 0.25f;
        final float bias2 = 1.0f;
        setHighLightBiases(bias0, bias1, bias2);

        DisplayWhiteBalanceController controller =
                DisplayWhiteBalanceFactory.create(mHandler, mSensorManagerMock, mResourcesSpy);
        final float ambientColorTemperature = 6000.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(HIGH_LIGHT_AMBIENT_COLOR_TEMPERATURE, ambientColorTemperature, 1.0f - bias),
                    0.01);
        }

        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(HIGH_LIGHT_AMBIENT_COLOR_TEMPERATURE, ambientColorTemperature, 1.0f - bias),
                    0.01);
        }

        setEstimatedBrightnessAndUpdate(controller, brightness2 + 1.0f);
        assertEquals(controller.mPendingAmbientColorTemperature,
                HIGH_LIGHT_AMBIENT_COLOR_TEMPERATURE, 0.001);

        setEstimatedBrightnessAndUpdate(controller, 0.0f);
        assertEquals(controller.mPendingAmbientColorTemperature, ambientColorTemperature, 0.001);
    }

    @Test
    public void testSpline_InvalidCombinations() throws Exception {
            setBrightnesses(100.0f, 200.0f);
            setBiases(0.0f, 1.0f);
            setHighLightBrightnesses(150.0f, 250.0f);
            setHighLightBiases(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 luxOverride = 0.1f; luxOverride <= 10000; luxOverride *= 10) {
                setEstimatedBrightnessAndUpdate(controller, luxOverride);
                assertEquals(controller.mPendingAmbientColorTemperature,
                        ambientColorTemperature, 0.001);
            }
    }

    void mockThrottler() {
        when(mResourcesSpy.getInteger(
                R.integer.config_displayWhiteBalanceDecreaseDebounce)).thenReturn(0);
        when(mResourcesSpy.getInteger(
                R.integer.config_displayWhiteBalanceIncreaseDebounce)).thenReturn(0);
        TypedArray base = mResourcesSpy.obtainTypedArray(
                R.array.config_displayWhiteBalanceBaseThresholds);
        TypedArray inc = mResourcesSpy.obtainTypedArray(
                R.array.config_displayWhiteBalanceIncreaseThresholds);
        TypedArray dec = mResourcesSpy.obtainTypedArray(
                R.array.config_displayWhiteBalanceDecreaseThresholds);
        base = spy(base);
        inc = spy(inc);
        dec = spy(dec);
        when(mResourcesSpy.obtainTypedArray(
                R.array.config_displayWhiteBalanceBaseThresholds)).thenReturn(base);
        when(mResourcesSpy.obtainTypedArray(
                R.array.config_displayWhiteBalanceIncreaseThresholds)).thenReturn(inc);
        when(mResourcesSpy.obtainTypedArray(
                R.array.config_displayWhiteBalanceDecreaseThresholds)).thenReturn(dec);
        setFloatArrayResource(base, new float[]{0.0f});
        setFloatArrayResource(inc, new float[]{0.0f});
        setFloatArrayResource(dec, new float[]{0.0f});
    }

    private void mockResourcesFloat(int id, float floatValue) {
        doAnswer(new Answer<Void>() {
            public Void answer(InvocationOnMock invocation) {
                TypedValue value = (TypedValue)invocation.getArgument(1);
                value.type = TypedValue.TYPE_FLOAT;
                value.data = Float.floatToIntBits(floatValue);
                return null;
            }
        }).when(mResourcesSpy).getValue(
                eq(id),
                any(TypedValue.class), eq(true));
    }

    private void setEstimatedColorTemperature(DisplayWhiteBalanceController controller,
@@ -262,6 +418,14 @@ public final class AmbientLuxTest {
        setFloatArrayResource(mBiases, vals);
    }

    private void setHighLightBrightnesses(float... vals) {
        setFloatArrayResource(mHighLightBrightnesses, vals);
    }

    private void setHighLightBiases(float... vals) {
        setFloatArrayResource(mHighLightBiases, vals);
    }

    private void setFloatArrayResource(TypedArray array, float[] vals) {
        when(array.length()).thenReturn(vals.length);
        for (int i = 0; i < vals.length; i++) {