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

Commit 8f328f06 authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Make DWB CCT changes follow a step function" into udc-dev am: 0cdca7eb am: f1275221

parents 81c6ea4b f1275221
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -995,6 +995,25 @@
        <!-- Nominal White Z --> <item>1.089058</item>
    </string-array>

    <!-- The CCT closest to the white coordinates (primary) above and in SurfaceControl. -->
    <integer name="config_displayWhiteBalanceDisplayNominalWhiteCct">6500</integer>

    <!-- Range minimums corresponding to config_displayWhiteBalanceDisplaySteps. For example, if the
         range minimums are [0, 3000] and the steps are [10, 20] then between 0 and 3000, exclusive,
         the step between them will be 10 (i.e. 0, 10, 20, etc.) and the step between 3000 and the
         maximum value is 20 (i.e. 3000, 3020, 3040, etc.). -->
    <integer-array name="config_displayWhiteBalanceDisplayRangeMinimums">
        <item>0</item>
    </integer-array>

    <!-- Steps corresponding to config_displayWhiteBalanceDisplayRangeMinimums. For example, if the
         range minimums are [0, 3000] and the steps are [10, 20] then between 0 and 3000, exclusive,
         the step between them will be 10 (i.e. 0, 10, 20, etc.) and the step between 3000 and the
         maximum value is 20 (i.e. 3000, 3020, 3040, etc.). -->
    <integer-array name="config_displayWhiteBalanceDisplaySteps">
        <item>1</item>
    </integer-array>

    <!-- Boolean indicating whether light mode is allowed when DWB is turned on. -->
    <bool name="config_displayWhiteBalanceLightModeAllowed">true</bool>

+3 −0
Original line number Diff line number Diff line
@@ -3426,6 +3426,9 @@
  <java-symbol type="integer" name="config_displayWhiteBalanceColorTemperatureDefault" />
  <java-symbol type="array" name="config_displayWhiteBalanceDisplayPrimaries" />
  <java-symbol type="array" name="config_displayWhiteBalanceDisplayNominalWhite" />
  <java-symbol type="integer" name="config_displayWhiteBalanceDisplayNominalWhiteCct" />
  <java-symbol type="array" name="config_displayWhiteBalanceDisplayRangeMinimums" />
  <java-symbol type="array" name="config_displayWhiteBalanceDisplaySteps" />
  <java-symbol type="bool" name="config_displayWhiteBalanceLightModeAllowed" />
  <java-symbol type="integer" name="config_displayWhiteBalanceTransitionTime" />

+108 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.display.color;

import android.animation.TypeEvaluator;
import android.util.Slog;

import com.android.internal.annotations.VisibleForTesting;

import java.util.Arrays;

/**
 * Interpolates between CCT values by a given step.
 */
class CctEvaluator implements TypeEvaluator<Integer> {

    private static final String TAG = "CctEvaluator";

    /**
     * The minimum input value, which will represent index 0 in the mValues array. Each
     * subsequent input value is offset by this amount.
     */
    private final int mIndexOffset;
    /**
     * Cached step values at each CCT value (offset by the {@link #mIndexOffset} above). For
     * example, if the minimum CCT is 2000K (which is set to mIndexOffset), then the 0th index of
     * this array is equivalent to the step value at 2000K, 1st index corresponds to 2001K, and so
     * on.
     */
    @VisibleForTesting
    final int[] mStepsAtOffsetCcts;
    /**
     * Pre-computed stepped CCTs. These will be accessed frequently; the memory cost of caching them
     * is well-spent.
     */
    @VisibleForTesting
    final int[] mSteppedCctsAtOffsetCcts;

    CctEvaluator(int min, int max, int[] cctRangeMinimums, int[] steps) {
        final int delta = max - min + 1;
        mStepsAtOffsetCcts = new int[delta];
        mSteppedCctsAtOffsetCcts = new int[delta];
        mIndexOffset = min;

        final int parallelArraysLength = cctRangeMinimums.length;
        if (cctRangeMinimums.length != steps.length) {
            Slog.e(TAG,
                    "Parallel arrays cctRangeMinimums and steps are different lengths; setting "
                            + "step of 1");
            setStepOfOne();
        } else if (parallelArraysLength == 0) {
            Slog.e(TAG, "No cctRangeMinimums or steps are set; setting step of 1");
            setStepOfOne();
        } else {
            int parallelArraysIndex = 0;
            int index = 0;
            int lastSteppedCct = Integer.MIN_VALUE;
            while (index < delta) {
                final int cct = index + mIndexOffset;
                int nextParallelArraysIndex = parallelArraysIndex + 1;
                while (nextParallelArraysIndex < parallelArraysLength
                        && cct >= cctRangeMinimums[nextParallelArraysIndex]) {
                    parallelArraysIndex = nextParallelArraysIndex;
                    nextParallelArraysIndex++;
                }
                mStepsAtOffsetCcts[index] = steps[parallelArraysIndex];
                if (lastSteppedCct == Integer.MIN_VALUE
                        || Math.abs(lastSteppedCct - cct) >= steps[parallelArraysIndex]) {
                    lastSteppedCct = cct;
                }
                mSteppedCctsAtOffsetCcts[index] = lastSteppedCct;
                index++;
            }
        }
    }

    @Override
    public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
        final int cct = (int) (startValue + fraction * (endValue - startValue));
        final int index = cct - mIndexOffset;
        if (index < 0 || index >= mSteppedCctsAtOffsetCcts.length) {
            Slog.e(TAG, "steppedCctValueAt: returning same since invalid requested index=" + index);
            return cct;
        }
        return mSteppedCctsAtOffsetCcts[index];
    }

    private void setStepOfOne() {
        Arrays.fill(mStepsAtOffsetCcts, 1);
        for (int i = 0; i < mSteppedCctsAtOffsetCcts.length; i++) {
            mSteppedCctsAtOffsetCcts[i] = mIndexOffset + i;
        }
    }
}
+80 −5
Original line number Diff line number Diff line
@@ -180,6 +180,8 @@ public final class ColorDisplayService extends SystemService {
     */
    private SparseIntArray mColorModeCompositionColorSpaces = null;

    private final Object mCctTintApplierLock = new Object();

    public ColorDisplayService(Context context) {
        super(context);
        mHandler = new TintHandler(DisplayThread.get().getLooper());
@@ -698,6 +700,79 @@ public final class ColorDisplayService extends SystemService {
        }
    }

    private void applyTintByCct(ColorTemperatureTintController tintController, boolean immediate) {
        synchronized (mCctTintApplierLock) {
            tintController.cancelAnimator();

            final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class);
            final int from = tintController.getAppliedCct();
            final int to = tintController.isActivated() ? tintController.getTargetCct()
                    : tintController.getDisabledCct();

            if (immediate) {
                Slog.d(TAG, tintController.getClass().getSimpleName()
                        + " applied immediately: toCct=" + to + " fromCct=" + from);
                dtm.setColorMatrix(tintController.getLevel(),
                        tintController.computeMatrixForCct(to));
                tintController.setAppliedCct(to);
            } else {
                Slog.d(TAG, tintController.getClass().getSimpleName() + " animation started: toCct="
                        + to + " fromCct=" + from);
                ValueAnimator valueAnimator = ValueAnimator.ofInt(from, to);
                tintController.setAnimator(valueAnimator);
                final CctEvaluator evaluator = tintController.getEvaluator();
                if (evaluator != null) {
                    valueAnimator.setEvaluator(evaluator);
                }
                valueAnimator.setDuration(tintController.getTransitionDurationMilliseconds());
                valueAnimator.setInterpolator(AnimationUtils.loadInterpolator(
                        getContext(), android.R.interpolator.linear));
                valueAnimator.addUpdateListener((ValueAnimator animator) -> {
                    synchronized (mCctTintApplierLock) {
                        final int value = (int) animator.getAnimatedValue();
                        if (value != tintController.getAppliedCct()) {
                            dtm.setColorMatrix(tintController.getLevel(),
                                    tintController.computeMatrixForCct(value));
                            tintController.setAppliedCct(value);
                        }
                    }
                });
                valueAnimator.addListener(new AnimatorListenerAdapter() {

                    private boolean mIsCancelled;

                    @Override
                    public void onAnimationCancel(Animator animator) {
                        Slog.d(TAG, tintController.getClass().getSimpleName()
                                + " animation cancelled");
                        mIsCancelled = true;
                    }

                    @Override
                    public void onAnimationEnd(Animator animator) {
                        synchronized (mCctTintApplierLock) {
                            Slog.d(TAG, tintController.getClass().getSimpleName()
                                    + " animation ended: wasCancelled=" + mIsCancelled
                                    + " toCct=" + to
                                    + " fromCct=" + from);
                            if (!mIsCancelled) {
                                // Ensure final color matrix is set at the end of the animation.
                                // If the animation is cancelled then don't set the final color
                                // matrix so the new animator can pick up from where this one left
                                // off.
                                dtm.setColorMatrix(tintController.getLevel(),
                                        tintController.computeMatrixForCct(to));
                                tintController.setAppliedCct(to);
                            }
                            tintController.setAnimator(null);
                        }
                    }
                });
                valueAnimator.start();
            }
        }
    }

    /**
     * Returns the first date time corresponding to the local time that occurs before the provided
     * date time.
@@ -747,7 +822,7 @@ public final class ColorDisplayService extends SystemService {

        // If disabled, clear the tint. If enabled, do nothing more here and let the next
        // temperature update set the correct tint.
        if (!activated) {
        if (oldActivated && !activated) {
            mHandler.sendEmptyMessage(MSG_APPLY_DISPLAY_WHITE_BALANCE);
        }
    }
@@ -1464,8 +1539,8 @@ public final class ColorDisplayService extends SystemService {
         * @param cct the color temperature in Kelvin.
         */
        public boolean setDisplayWhiteBalanceColorTemperature(int cct) {
            // Update the transform matrix even if it can't be applied.
            mDisplayWhiteBalanceTintController.setMatrix(cct);
            // Update the transform target CCT even if it can't be applied.
            mDisplayWhiteBalanceTintController.setTargetCct(cct);

            if (mDisplayWhiteBalanceTintController.isActivated()) {
                mHandler.sendEmptyMessage(MSG_APPLY_DISPLAY_WHITE_BALANCE);
@@ -1601,7 +1676,7 @@ public final class ColorDisplayService extends SystemService {
                    applyTint(mNightDisplayTintController, false);
                    break;
                case MSG_APPLY_DISPLAY_WHITE_BALANCE:
                    applyTint(mDisplayWhiteBalanceTintController, false);
                    applyTintByCct(mDisplayWhiteBalanceTintController, false);
                    break;
            }
        }
+38 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.display.color;

abstract class ColorTemperatureTintController extends TintController {

    abstract int getAppliedCct();

    abstract void setAppliedCct(int cct);

    abstract int getTargetCct();

    abstract void setTargetCct(int cct);

    /**
     * Returns the CCT value most closely associated with the "disabled" (identity) matrix for
     * this device, to use as the target when deactivating this transform.
     */
    abstract int getDisabledCct();

    abstract float[] computeMatrixForCct(int cct);

    abstract CctEvaluator getEvaluator();
}
Loading