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

Commit a4ab5679 authored by Daniel Solomon's avatar Daniel Solomon
Browse files

Initialize Display White Balance using SurfaceControl

Currently, DWB reads display color characteristics from device overlays.
This limits DWB to a static source of data.

This change adds another, higher priority initialization option, using
SurfaceControl. SurfaceControl exposes device color characteristics from
the Configstore HAL, which may be dynamically populated based on
specific device characteristics. Consequently, this source of data
allows for more accurate color transforms in DWB.

Bug 123102849
Test: manually force initialization using both methods

Change-Id: I3bf889e98f2b52866c90513203c02adcff338ac7
parent 10e3b336
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -1022,7 +1022,8 @@
    <integer name="config_displayWhiteBalanceColorTemperatureDefault">6500</integer>

    <!-- The display primaries, in CIE1931 XYZ color space, for display
         white balance to use in its calculations. -->
         white balance to use in its calculations. The array must include a total of 12 float
         values: 3 values per color (X, Y, Z) and 4 colors (R, G, B, W) -->
    <string-array name="config_displayWhiteBalanceDisplayPrimaries">
        <!-- Red X -->   <item>0.412315</item>
        <!-- Red Y -->   <item>0.212600</item>
@@ -1040,7 +1041,7 @@

    <!-- The nominal white coordinates, in CIE1931 XYZ color space, for Display White Balance to
         use in its calculations. AWB will adapt this white point to the target ambient white
         point. -->
         point. The array must include a total of 3 float values (X, Y, Z) -->
    <string-array name="config_displayWhiteBalanceDisplayNominalWhite">
        <!-- Nominal White X --> <item>0.950456</item>
        <!-- Nominal White Y --> <item>1.000000</item>
+68 −36
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ import android.net.Uri;
import android.opengl.Matrix;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.SystemProperties;
@@ -66,6 +67,9 @@ import android.util.Slog;
import android.view.SurfaceControl;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.AnimationUtils;
import android.view.SurfaceControl;
import android.view.SurfaceControl.DisplayPrimaries;

import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.ColorDisplayController;
@@ -145,43 +149,20 @@ public final class ColorDisplayService extends SystemService {
        @Override
        public void setUp(Context context, boolean needsLinear) {
            mSetUp = false;

            final Resources res = getContext().getResources();
            final String[] displayPrimariesValues = res.getStringArray(
                    R.array.config_displayWhiteBalanceDisplayPrimaries);
            final String[] nominalWhiteValues = res.getStringArray(
                    R.array.config_displayWhiteBalanceDisplayNominalWhite);

            if (displayPrimariesValues.length != NUM_DISPLAY_PRIMARIES_VALS) {
                Slog.e(TAG, "Unexpected display white balance primaries resource length " +
                        displayPrimariesValues.length);
            final Resources res = context.getResources();

            ColorSpace.Rgb displayColorSpaceRGB = getDisplayColorSpaceFromSurfaceControl();
            if (displayColorSpaceRGB == null) {
                Slog.w(TAG, "Failed to get display color space from SurfaceControl, trying res");
                displayColorSpaceRGB = getDisplayColorSpaceFromResources(res);
                if (displayColorSpaceRGB == null) {
                    Slog.e(TAG, "Failed to get display color space from resources");
                    return;
                }

            if (nominalWhiteValues.length != NUM_VALUES_PER_PRIMARY) {
                Slog.e(TAG, "Unexpected display white balance nominal white resource length " +
                        nominalWhiteValues.length);
                return;
            }

            float[] displayRedGreenBlueXYZ =
                    new float[NUM_DISPLAY_PRIMARIES_VALS - NUM_VALUES_PER_PRIMARY];
            float[] displayWhiteXYZ = new float[NUM_VALUES_PER_PRIMARY];
            for (int i = 0; i < displayRedGreenBlueXYZ.length; i++) {
                displayRedGreenBlueXYZ[i] = Float.parseFloat(displayPrimariesValues[i]);
            }
            for (int i = 0; i < displayWhiteXYZ.length; i++) {
                displayWhiteXYZ[i] = Float.parseFloat(
                        displayPrimariesValues[displayRedGreenBlueXYZ.length + i]);
            }

            final ColorSpace.Rgb displayColorSpaceRGB = new ColorSpace.Rgb(
                    "Display Color Space",
                    displayRedGreenBlueXYZ,
                    displayWhiteXYZ,
                    2.2f // gamma, unused for display white balance
            );

            final String[] nominalWhiteValues = res.getStringArray(
                    R.array.config_displayWhiteBalanceDisplayNominalWhite);
            float[] displayNominalWhiteXYZ = new float[NUM_VALUES_PER_PRIMARY];
            for (int i = 0; i < nominalWhiteValues.length; i++) {
                displayNominalWhiteXYZ[i] = Float.parseFloat(nominalWhiteValues[i]);
@@ -190,14 +171,14 @@ public final class ColorDisplayService extends SystemService {
            final int colorTemperatureMin = res.getInteger(
                    R.integer.config_displayWhiteBalanceColorTemperatureMin);
            if (colorTemperatureMin <= 0) {
                Slog.e(TAG, "display white balance minimum temperature must be greater than 0");
                Slog.e(TAG, "Display white balance minimum temperature must be greater than 0");
                return;
            }

            final int colorTemperatureMax = res.getInteger(
                    R.integer.config_displayWhiteBalanceColorTemperatureMax);
            if (colorTemperatureMax < colorTemperatureMin) {
                Slog.e(TAG, "display white balance max temp must be greater or equal to min");
                Slog.e(TAG, "Display white balance max temp must be greater or equal to min");
                return;
            }

@@ -323,6 +304,57 @@ public final class ColorDisplayService extends SystemService {
                        matrixToString(mMatrixDisplayWhiteBalance, 4));
            }
        }

        private ColorSpace.Rgb makeRgbColorSpaceFromXYZ(float[] redGreenBlueXYZ, float[] whiteXYZ) {
            return new ColorSpace.Rgb(
                "Display Color Space",
                redGreenBlueXYZ,
                whiteXYZ,
                2.2f // gamma, unused for display white balance
            );
        }

        private ColorSpace.Rgb getDisplayColorSpaceFromSurfaceControl() {
            IBinder displayToken = SurfaceControl.getBuiltInDisplay(
                    SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN);
            if (displayToken == null) {
                return null;
            }

            DisplayPrimaries primaries = SurfaceControl.getDisplayNativePrimaries(displayToken);
            if (primaries == null || primaries.red == null || primaries.green == null ||
                primaries.blue == null || primaries.white == null) {
                return null;
            }

            return makeRgbColorSpaceFromXYZ(
                    new float[] {
                        primaries.red.X, primaries.red.Y, primaries.red.Z,
                        primaries.green.X, primaries.green.Y, primaries.green.Z,
                        primaries.blue.X, primaries.blue.Y, primaries.blue.Z,
                    },
                    new float[] { primaries.white.X, primaries.white.Y, primaries.white.Z }
                    );
        }

        private ColorSpace.Rgb getDisplayColorSpaceFromResources(Resources res) {
            final String[] displayPrimariesValues = res.getStringArray(
                    R.array.config_displayWhiteBalanceDisplayPrimaries);
            float[] displayRedGreenBlueXYZ =
                    new float[NUM_DISPLAY_PRIMARIES_VALS - NUM_VALUES_PER_PRIMARY];
            float[] displayWhiteXYZ = new float[NUM_VALUES_PER_PRIMARY];

            for (int i = 0; i < displayRedGreenBlueXYZ.length; i++) {
                displayRedGreenBlueXYZ[i] = Float.parseFloat(displayPrimariesValues[i]);
            }

            for (int i = 0; i < displayWhiteXYZ.length; i++) {
                displayWhiteXYZ[i] = Float.parseFloat(
                        displayPrimariesValues[displayRedGreenBlueXYZ.length + i]);
            }

            return makeRgbColorSpaceFromXYZ(displayRedGreenBlueXYZ, displayWhiteXYZ);
        }
    };

    private final TintController mGlobalSaturationTintController = new TintController() {