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

Commit 97cba33f authored by Christine Franks's avatar Christine Franks Committed by Android (Google) Code Review
Browse files

Merge "Split global saturation into a dedicated helper"

parents a0cb13f7 7119e99d
Loading
Loading
Loading
Loading
+8 −137
Original line number Diff line number Diff line
@@ -26,7 +26,6 @@ import static android.hardware.display.ColorDisplayManager.COLOR_MODE_SATURATED;

import static com.android.server.display.color.DisplayTransformManager.LEVEL_COLOR_MATRIX_DISPLAY_WHITE_BALANCE;
import static com.android.server.display.color.DisplayTransformManager.LEVEL_COLOR_MATRIX_NIGHT_DISPLAY;
import static com.android.server.display.color.DisplayTransformManager.LEVEL_COLOR_MATRIX_SATURATION;

import android.Manifest;
import android.animation.Animator;
@@ -88,19 +87,13 @@ import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeParseException;
import java.util.Arrays;

/**
 * Controls the display's color transforms.
 */
public final class ColorDisplayService extends SystemService {

    private static final String TAG = "ColorDisplayService";

    /**
     * The transition time, in milliseconds, for Night Display to turn on/off.
     */
    private static final long TRANSITION_DURATION = 3000L;
    static final String TAG = "ColorDisplayService";

    /**
     * The identity matrix, used if one of the given matrices is {@code null}.
@@ -111,6 +104,11 @@ public final class ColorDisplayService extends SystemService {
        Matrix.setIdentityM(MATRIX_IDENTITY, 0);
    }

    /**
     * The transition time, in milliseconds, for Night Display to turn on/off.
     */
    private static final long TRANSITION_DURATION = 3000L;

    private static final int MSG_APPLY_NIGHT_DISPLAY_IMMEDIATE = 0;
    private static final int MSG_APPLY_NIGHT_DISPLAY_ANIMATED = 1;
    private static final int MSG_APPLY_GLOBAL_SATURATION = 2;
@@ -133,59 +131,8 @@ public final class ColorDisplayService extends SystemService {
    final DisplayWhiteBalanceTintController mDisplayWhiteBalanceTintController =
            new DisplayWhiteBalanceTintController();

    private final TintController mGlobalSaturationTintController = new TintController() {

        private float[] mMatrixGlobalSaturation = new float[16];

        @Override
        public void setUp(Context context, boolean needsLinear) {
        }

        @Override
        public float[] getMatrix() {
            return Arrays.copyOf(mMatrixGlobalSaturation, mMatrixGlobalSaturation.length);
        }

        @Override
        public void setMatrix(int saturationLevel) {
            if (saturationLevel < 0) {
                saturationLevel = 0;
            } else if (saturationLevel > 100) {
                saturationLevel = 100;
            }
            Slog.d(TAG, "Setting saturation level: " + saturationLevel);

            if (saturationLevel == 100) {
                setActivated(false);
                Matrix.setIdentityM(mMatrixGlobalSaturation, 0);
            } else {
                setActivated(true);
                float saturation = saturationLevel * 0.1f;
                float desaturation = 1.0f - saturation;
                float[] luminance = {0.231f * desaturation, 0.715f * desaturation,
                        0.072f * desaturation};
                mMatrixGlobalSaturation[0] = luminance[0] + saturation;
                mMatrixGlobalSaturation[1] = luminance[0];
                mMatrixGlobalSaturation[2] = luminance[0];
                mMatrixGlobalSaturation[4] = luminance[1];
                mMatrixGlobalSaturation[5] = luminance[1] + saturation;
                mMatrixGlobalSaturation[6] = luminance[1];
                mMatrixGlobalSaturation[8] = luminance[2];
                mMatrixGlobalSaturation[9] = luminance[2];
                mMatrixGlobalSaturation[10] = luminance[2] + saturation;
            }
        }

        @Override
        public int getLevel() {
            return LEVEL_COLOR_MATRIX_SATURATION;
        }

        @Override
        public boolean isAvailable(Context context) {
            return ColorDisplayManager.isColorTransformAccelerated(context);
        }
    };
    private final TintController mGlobalSaturationTintController =
            new GlobalSaturationTintController();

    /**
     * Matrix and offset used for converting color to grayscale.
@@ -1084,82 +1031,6 @@ public final class ColorDisplayService extends SystemService {
        }
    }

    private abstract static class TintController {

        private ValueAnimator mAnimator;
        private Boolean mIsActivated;

        public ValueAnimator getAnimator() {
            return mAnimator;
        }

        public void setAnimator(ValueAnimator animator) {
            mAnimator = animator;
        }

        /**
         * Cancel the animator if it's still running.
         */
        public void cancelAnimator() {
            if (mAnimator != null) {
                mAnimator.cancel();
            }
        }

        /**
         * End the animator if it's still running, jumping to the end state.
         */
        public void endAnimator() {
            if (mAnimator != null) {
                mAnimator.end();
                mAnimator = null;
            }
        }

        public void setActivated(Boolean isActivated) {
            mIsActivated = isActivated;
        }

        public boolean isActivated() {
            return mIsActivated != null && mIsActivated;
        }

        public boolean isActivatedStateNotSet() {
            return mIsActivated == null;
        }

        /**
         * Dump debug information.
         */
        public void dump(PrintWriter pw) {
        }

        /**
         * Set up any constants needed for computing the matrix.
         */
        public abstract void setUp(Context context, boolean needsLinear);

        /**
         * Sets the 4x4 matrix to apply.
         */
        public abstract void setMatrix(int value);

        /**
         * Get the 4x4 matrix to apply.
         */
        public abstract float[] getMatrix();

        /**
         * Get the color transform level to apply the matrix.
         */
        public abstract int getLevel();

        /**
         * Returns whether or not this transform type is available on this device.
         */
        public abstract boolean isAvailable(Context context);
    }

    private final class NightDisplayTintController extends TintController {

        private final float[] mMatrix = new float[16];
+81 −0
Original line number Diff line number Diff line
/*
 * 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.color;

import static com.android.server.display.color.DisplayTransformManager.LEVEL_COLOR_MATRIX_SATURATION;

import android.content.Context;
import android.hardware.display.ColorDisplayManager;
import android.opengl.Matrix;
import android.util.Slog;

import java.util.Arrays;

/** Control the color transform for global device saturation. */
public class GlobalSaturationTintController extends TintController {

    private final float[] mMatrixGlobalSaturation = new float[16];

    @Override
    public void setUp(Context context, boolean needsLinear) {
    }

    @Override
    public float[] getMatrix() {
        return Arrays.copyOf(mMatrixGlobalSaturation, mMatrixGlobalSaturation.length);
    }

    @Override
    public void setMatrix(int saturationLevel) {
        if (saturationLevel < 0) {
            saturationLevel = 0;
        } else if (saturationLevel > 100) {
            saturationLevel = 100;
        }
        Slog.d(ColorDisplayService.TAG, "Setting saturation level: " + saturationLevel);

        if (saturationLevel == 100) {
            setActivated(false);
            Matrix.setIdentityM(mMatrixGlobalSaturation, 0);
        } else {
            setActivated(true);
            float saturation = saturationLevel * 0.01f;
            float desaturation = 1.0f - saturation;
            float[] luminance = {0.231f * desaturation, 0.715f * desaturation,
                    0.072f * desaturation};
            mMatrixGlobalSaturation[0] = luminance[0] + saturation;
            mMatrixGlobalSaturation[1] = luminance[0];
            mMatrixGlobalSaturation[2] = luminance[0];
            mMatrixGlobalSaturation[4] = luminance[1];
            mMatrixGlobalSaturation[5] = luminance[1] + saturation;
            mMatrixGlobalSaturation[6] = luminance[1];
            mMatrixGlobalSaturation[8] = luminance[2];
            mMatrixGlobalSaturation[9] = luminance[2];
            mMatrixGlobalSaturation[10] = luminance[2] + saturation;
        }
    }

    @Override
    public int getLevel() {
        return LEVEL_COLOR_MATRIX_SATURATION;
    }

    @Override
    public boolean isAvailable(Context context) {
        return ColorDisplayManager.isColorTransformAccelerated(context);
    }
}
+98 −0
Original line number Diff line number Diff line
/*
 * 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.color;

import android.animation.ValueAnimator;
import android.content.Context;

import java.io.PrintWriter;

abstract class TintController {

    private ValueAnimator mAnimator;
    private Boolean mIsActivated;

    public ValueAnimator getAnimator() {
        return mAnimator;
    }

    public void setAnimator(ValueAnimator animator) {
        mAnimator = animator;
    }

    /**
     * Cancel the animator if it's still running.
     */
    public void cancelAnimator() {
        if (mAnimator != null) {
            mAnimator.cancel();
        }
    }

    /**
     * End the animator if it's still running, jumping to the end state.
     */
    public void endAnimator() {
        if (mAnimator != null) {
            mAnimator.end();
            mAnimator = null;
        }
    }

    public void setActivated(Boolean isActivated) {
        mIsActivated = isActivated;
    }

    public boolean isActivated() {
        return mIsActivated != null && mIsActivated;
    }

    public boolean isActivatedStateNotSet() {
        return mIsActivated == null;
    }

    /**
     * Dump debug information.
     */
    public void dump(PrintWriter pw) {
    }

    /**
     * Set up any constants needed for computing the matrix.
     */
    public abstract void setUp(Context context, boolean needsLinear);

    /**
     * Sets the 4x4 matrix to apply.
     */
    public abstract void setMatrix(int value);

    /**
     * Get the 4x4 matrix to apply.
     */
    public abstract float[] getMatrix();

    /**
     * Get the color transform level to apply the matrix.
     */
    public abstract int getLevel();

    /**
     * Returns whether or not this transform type is available on this device.
     */
    public abstract boolean isAvailable(Context context);
}
+48 −0
Original line number Diff line number Diff line
/*
 * 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.color;

import static com.google.common.truth.Truth.assertThat;

import android.opengl.Matrix;

import androidx.test.runner.AndroidJUnit4;

import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(AndroidJUnit4.class)
public class GlobalSaturationTintControllerTest {

    @Test
    public void setAndGetMatrix() {
        final GlobalSaturationTintController tintController = new GlobalSaturationTintController();
        tintController.setMatrix(50);
        assertThat(tintController.getMatrix()).hasValuesWithin(0.00001f)
                .of(new float[]{0.6155f, 0.1155f, 0.1155f, 0.0f, 0.3575f, 0.85749996f, 0.3575f,
                        0.0f, 0.036f, 0.036f, 0.536f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f});
    }

    @Test
    public void resetMatrix() {
        final GlobalSaturationTintController tintController = new GlobalSaturationTintController();
        tintController.setMatrix(100);
        final float[] matrix = new float[16];
        Matrix.setIdentityM(matrix, 0);
        assertThat(tintController.getMatrix()).hasValuesWithin(0.00001f).of(matrix);
    }
}