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

Commit 1f3d43d7 authored by Anthony Han's avatar Anthony Han Committed by android-build-merger
Browse files

Merge "Interpolate high light white balance" into qt-r1-dev

am: e831c9fd

Change-Id: I7a481d408cd2ef783a2e661406ff674462d73569
parents 1b0d7694 e831c9fd
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
@@ -3750,6 +3750,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++) {