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

Commit d154fe5d authored by Christine Franks's avatar Christine Franks
Browse files

Move color modes to ColorDisplayService

Bug: 123352608
Test: atest FrameworksServicesTests:ColorDisplayServiceTest
Change-Id: Iee9034721366723a7b2faba0ea2adc9479c6fec5
parent a75a6ee0
Loading
Loading
Loading
Loading
+84 −0
Original line number Diff line number Diff line
@@ -23,12 +23,14 @@ import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.ContentResolver;
import android.content.Context;
import android.metrics.LogMaker;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
import android.provider.Settings.Secure;

import com.android.internal.R;
import com.android.internal.logging.MetricsLogger;
@@ -120,6 +122,42 @@ public final class ColorDisplayManager {
     */
    public static final int AUTO_MODE_TWILIGHT = 2;

    /**
     * @hide
     */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({COLOR_MODE_NATURAL, COLOR_MODE_BOOSTED, COLOR_MODE_SATURATED, COLOR_MODE_AUTOMATIC})
    public @interface ColorMode {}

    /**
     * Color mode with natural colors.
     *
     * @hide
     * @see #setColorMode(int)
     */
    public static final int COLOR_MODE_NATURAL = 0;
    /**
     * Color mode with boosted colors.
     *
     * @hide
     * @see #setColorMode(int)
     */
    public static final int COLOR_MODE_BOOSTED = 1;
    /**
     * Color mode with saturated colors.
     *
     * @hide
     * @see #setColorMode(int)
     */
    public static final int COLOR_MODE_SATURATED = 2;
    /**
     * Color mode with automatic colors.
     *
     * @hide
     * @see #setColorMode(int)
     */
    public static final int COLOR_MODE_AUTOMATIC = 3;

    private final ColorDisplayManagerInternal mManager;
    private MetricsLogger mMetricsLogger;

@@ -274,6 +312,24 @@ public final class ColorDisplayManager {
        return mManager.setNightDisplayCustomEndTime(new Time(endTime));
    }

    /**
     * Sets the current display color mode.
     *
     * @hide
     */
    public void setColorMode(int colorMode) {
        mManager.setColorMode(colorMode);
    }

    /**
     * Gets the current display color mode.
     *
     * @hide
     */
    public int getColorMode() {
        return mManager.getColorMode();
    }

    /**
     * Returns whether the device has a wide color gamut display.
     *
@@ -373,6 +429,18 @@ public final class ColorDisplayManager {
        return mManager.getTransformCapabilities();
    }

    /**
     * Returns whether accessibility transforms are currently enabled, which determines whether
     * color modes are currently configurable for this device.
     *
     * @hide
     */
    public static boolean areAccessibilityTransformsEnabled(Context context) {
        final ContentResolver cr = context.getContentResolver();
        return Secure.getInt(cr, Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0) == 1
                || Secure.getInt(cr, Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0) == 1;
    }

    private MetricsLogger getMetricsLogger() {
        if (mMetricsLogger == null) {
            mMetricsLogger = new MetricsLogger();
@@ -517,6 +585,22 @@ public final class ColorDisplayManager {
            }
        }

        int getColorMode() {
            try {
                return mCdm.getColorMode();
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }

        void setColorMode(int colorMode) {
            try {
                mCdm.setColorMode(colorMode);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }

        int getTransformCapabilities() {
            try {
                return mCdm.getTransformCapabilities();
+3 −0
Original line number Diff line number Diff line
@@ -38,4 +38,7 @@ interface IColorDisplayManager {
    boolean setNightDisplayCustomStartTime(in Time time);
    Time getNightDisplayCustomEndTime();
    boolean setNightDisplayCustomEndTime(in Time time);

    int getColorMode();
    void setColorMode(int colorMode);
}
 No newline at end of file
+3 −3
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.SQLException;
import android.hardware.display.ColorDisplayManager;
import android.location.LocationManager;
import android.media.AudioFormat;
import android.net.ConnectivityManager;
@@ -89,7 +90,6 @@ import android.util.MemoryIntArray;
import android.view.inputmethod.InputMethodSystemProperty;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.ColorDisplayController;
import com.android.internal.widget.ILockSettings;
import java.io.IOException;
@@ -3239,8 +3239,8 @@ public final class Settings {
        private static final Validator DISPLAY_COLOR_MODE_VALIDATOR =
                new SettingsValidators.InclusiveIntegerRangeValidator(
                        ColorDisplayController.COLOR_MODE_NATURAL,
                        ColorDisplayController.COLOR_MODE_AUTOMATIC);
                        ColorDisplayManager.COLOR_MODE_NATURAL,
                        ColorDisplayManager.COLOR_MODE_AUTOMATIC);
        /**
         * The amount of time in milliseconds before the device goes to sleep or begins
+3 −147
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

package com.android.internal.app;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.app.ActivityManager;
import android.content.ContentResolver;
@@ -24,18 +23,13 @@ import android.content.Context;
import android.database.ContentObserver;
import android.hardware.display.ColorDisplayManager;
import android.hardware.display.ColorDisplayManager.AutoMode;
import android.hardware.display.ColorDisplayManager.ColorMode;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.SystemProperties;
import android.provider.Settings.Secure;
import android.provider.Settings.System;
import android.util.Slog;

import com.android.internal.R;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.time.LocalTime;

/**
@@ -49,35 +43,6 @@ public final class ColorDisplayController {
    private static final String TAG = "ColorDisplayController";
    private static final boolean DEBUG = false;

    @Retention(RetentionPolicy.SOURCE)
    @IntDef({COLOR_MODE_NATURAL, COLOR_MODE_BOOSTED, COLOR_MODE_SATURATED, COLOR_MODE_AUTOMATIC})
    public @interface ColorMode {}

    /**
     * Color mode with natural colors.
     *
     * @see #setColorMode(int)
     */
    public static final int COLOR_MODE_NATURAL = 0;
    /**
     * Color mode with boosted colors.
     *
     * @see #setColorMode(int)
     */
    public static final int COLOR_MODE_BOOSTED = 1;
    /**
     * Color mode with saturated colors.
     *
     * @see #setColorMode(int)
     */
    public static final int COLOR_MODE_SATURATED = 2;
    /**
     * Color mode with automatic colors.
     *
     * @see #setColorMode(int)
     */
    public static final int COLOR_MODE_AUTOMATIC = 3;

    private final Context mContext;
    private final int mUserId;
    private final ColorDisplayManager mColorDisplayManager;
@@ -196,75 +161,11 @@ public final class ColorDisplayController {
        return mColorDisplayManager.setNightDisplayColorTemperature(colorTemperature);
    }

    /**
     * Get the current color mode from system properties, or return -1.
     *
     * See com.android.server.display.DisplayTransformManager.
     */
    private @ColorMode int getCurrentColorModeFromSystemProperties() {
        final int displayColorSetting = SystemProperties.getInt("persist.sys.sf.native_mode", 0);
        if (displayColorSetting == 0) {
            return "1.0".equals(SystemProperties.get("persist.sys.sf.color_saturation"))
                    ? COLOR_MODE_NATURAL : COLOR_MODE_BOOSTED;
        } else if (displayColorSetting == 1) {
            return COLOR_MODE_SATURATED;
        } else if (displayColorSetting == 2) {
            return COLOR_MODE_AUTOMATIC;
        } else {
            return -1;
        }
    }

    private boolean isColorModeAvailable(@ColorMode int colorMode) {
        final int[] availableColorModes = mContext.getResources().getIntArray(
                R.array.config_availableColorModes);
        if (availableColorModes != null) {
            for (int mode : availableColorModes) {
                if (mode == colorMode) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Get the current color mode.
     */
    public int getColorMode() {
        if (getAccessibilityTransformActivated()) {
            if (isColorModeAvailable(COLOR_MODE_SATURATED)) {
                return COLOR_MODE_SATURATED;
            } else if (isColorModeAvailable(COLOR_MODE_AUTOMATIC)) {
                return COLOR_MODE_AUTOMATIC;
            }
        }

        int colorMode = System.getIntForUser(mContext.getContentResolver(),
                System.DISPLAY_COLOR_MODE, -1, mUserId);
        if (colorMode == -1) {
            // There might be a system property controlling color mode that we need to respect; if
            // not, this will set a suitable default.
            colorMode = getCurrentColorModeFromSystemProperties();
        }

        // This happens when a color mode is no longer available (e.g., after system update or B&R)
        // or the device does not support any color mode.
        if (!isColorModeAvailable(colorMode)) {
            if (colorMode == COLOR_MODE_BOOSTED && isColorModeAvailable(COLOR_MODE_NATURAL)) {
                colorMode = COLOR_MODE_NATURAL;
            } else if (colorMode == COLOR_MODE_SATURATED
                    && isColorModeAvailable(COLOR_MODE_AUTOMATIC)) {
                colorMode = COLOR_MODE_AUTOMATIC;
            } else if (colorMode == COLOR_MODE_AUTOMATIC
                    && isColorModeAvailable(COLOR_MODE_SATURATED)) {
                colorMode = COLOR_MODE_SATURATED;
            } else {
                colorMode = -1;
            }
        }

        return colorMode;
        return mColorDisplayManager.getColorMode();
    }

    /**
@@ -273,11 +174,7 @@ public final class ColorDisplayController {
     * @param colorMode the color mode
     */
    public void setColorMode(@ColorMode int colorMode) {
        if (!isColorModeAvailable(colorMode)) {
            throw new IllegalArgumentException("Invalid colorMode: " + colorMode);
        }
        System.putIntForUser(mContext.getContentResolver(), System.DISPLAY_COLOR_MODE, colorMode,
                mUserId);
        mColorDisplayManager.setColorMode(colorMode);
    }

    /**
@@ -294,18 +191,6 @@ public final class ColorDisplayController {
        return ColorDisplayManager.getMaximumColorTemperature(mContext);
    }

    /**
     * Returns true if any Accessibility color transforms are enabled.
     */
    public boolean getAccessibilityTransformActivated() {
        final ContentResolver cr = mContext.getContentResolver();
        return
            Secure.getIntForUser(cr, Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED,
                    0, mUserId) == 1
            || Secure.getIntForUser(cr, Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED,
                    0, mUserId) == 1;
    }

    private void onSettingChanged(@NonNull String setting) {
        if (DEBUG) {
            Slog.d(TAG, "onSettingChanged: " + setting);
@@ -328,13 +213,6 @@ public final class ColorDisplayController {
                case Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE:
                    mCallback.onColorTemperatureChanged(getColorTemperature());
                    break;
                case System.DISPLAY_COLOR_MODE:
                    mCallback.onDisplayColorModeChanged(getColorMode());
                    break;
                case Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED:
                case Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED:
                    mCallback.onAccessibilityTransformChanged(getAccessibilityTransformActivated());
                    break;
            }
        }
    }
@@ -377,14 +255,6 @@ public final class ColorDisplayController {
                        false /* notifyForDescendants */, mContentObserver, mUserId);
                cr.registerContentObserver(Secure.getUriFor(Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE),
                        false /* notifyForDescendants */, mContentObserver, mUserId);
                cr.registerContentObserver(System.getUriFor(System.DISPLAY_COLOR_MODE),
                        false /* notifyForDecendants */, mContentObserver, mUserId);
                cr.registerContentObserver(
                        Secure.getUriFor(Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED),
                        false /* notifyForDecendants */, mContentObserver, mUserId);
                cr.registerContentObserver(
                        Secure.getUriFor(Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED),
                        false /* notifyForDecendants */, mContentObserver, mUserId);
            }
        }
    }
@@ -424,19 +294,5 @@ public final class ColorDisplayController {
         * @param colorTemperature the color temperature to tint the screen
         */
        default void onColorTemperatureChanged(int colorTemperature) {}

        /**
         * Callback invoked when the color mode changes.
         *
         * @param displayColorMode the color mode
         */
        default void onDisplayColorModeChanged(int displayColorMode) {}

        /**
         * Callback invoked when Accessibility color transforms change.
         *
         * @param state the state Accessibility color transforms (true of active)
         */
        default void onAccessibilityTransformChanged(boolean state) {}
    }
}
+126 −13
Original line number Diff line number Diff line
@@ -19,7 +19,10 @@ package com.android.server.display;
import static android.hardware.display.ColorDisplayManager.AUTO_MODE_CUSTOM_TIME;
import static android.hardware.display.ColorDisplayManager.AUTO_MODE_DISABLED;
import static android.hardware.display.ColorDisplayManager.AUTO_MODE_TWILIGHT;

import static android.hardware.display.ColorDisplayManager.COLOR_MODE_AUTOMATIC;
import static android.hardware.display.ColorDisplayManager.COLOR_MODE_BOOSTED;
import static android.hardware.display.ColorDisplayManager.COLOR_MODE_NATURAL;
import static android.hardware.display.ColorDisplayManager.COLOR_MODE_SATURATED;
import static com.android.server.display.DisplayTransformManager.LEVEL_COLOR_MATRIX_DISPLAY_WHITE_BALANCE;
import static com.android.server.display.DisplayTransformManager.LEVEL_COLOR_MATRIX_NIGHT_DISPLAY;
import static com.android.server.display.DisplayTransformManager.LEVEL_COLOR_MATRIX_SATURATION;
@@ -45,6 +48,7 @@ import android.database.ContentObserver;
import android.graphics.ColorSpace;
import android.hardware.display.ColorDisplayManager;
import android.hardware.display.ColorDisplayManager.AutoMode;
import android.hardware.display.ColorDisplayManager.ColorMode;
import android.hardware.display.IColorDisplayManager;
import android.hardware.display.Time;
import android.net.Uri;
@@ -53,6 +57,7 @@ import android.os.Binder;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.provider.Settings.Secure;
import android.provider.Settings.System;
@@ -61,7 +66,6 @@ import android.util.Slog;
import android.view.SurfaceControl;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.AnimationUtils;

import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.ColorDisplayController;
@@ -71,7 +75,6 @@ import com.android.server.SystemService;
import com.android.server.twilight.TwilightListener;
import com.android.server.twilight.TwilightManager;
import com.android.server.twilight.TwilightState;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
@@ -944,6 +947,89 @@ public final class ColorDisplayService extends SystemService {
                .setSaturationLevel(packageName, mCurrentUser, saturationLevel);
    }

    private void setColorModeInternal(@ColorMode int colorMode) {
        if (!isColorModeAvailable(colorMode)) {
            throw new IllegalArgumentException("Invalid colorMode: " + colorMode);
        }
        System.putIntForUser(getContext().getContentResolver(), System.DISPLAY_COLOR_MODE,
                colorMode,
                mCurrentUser);
    }

    private @ColorMode
    int getColorModeInternal() {
        final ContentResolver cr = getContext().getContentResolver();
        if (Secure.getIntForUser(cr, Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED,
                0, mCurrentUser) == 1
                || Secure.getIntForUser(cr, Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED,
                0, mCurrentUser) == 1) {
            // There are restrictions on the available color modes combined with a11y transforms.
            if (isColorModeAvailable(COLOR_MODE_SATURATED)) {
                return COLOR_MODE_SATURATED;
            } else if (isColorModeAvailable(COLOR_MODE_AUTOMATIC)) {
                return COLOR_MODE_AUTOMATIC;
            }
        }

        int colorMode = System.getIntForUser(cr, System.DISPLAY_COLOR_MODE, -1, mCurrentUser);
        if (colorMode == -1) {
            // There might be a system property controlling color mode that we need to respect; if
            // not, this will set a suitable default.
            colorMode = getCurrentColorModeFromSystemProperties();
        }

        // This happens when a color mode is no longer available (e.g., after system update or B&R)
        // or the device does not support any color mode.
        if (!isColorModeAvailable(colorMode)) {
            if (colorMode == COLOR_MODE_BOOSTED && isColorModeAvailable(COLOR_MODE_NATURAL)) {
                colorMode = COLOR_MODE_NATURAL;
            } else if (colorMode == COLOR_MODE_SATURATED
                    && isColorModeAvailable(COLOR_MODE_AUTOMATIC)) {
                colorMode = COLOR_MODE_AUTOMATIC;
            } else if (colorMode == COLOR_MODE_AUTOMATIC
                    && isColorModeAvailable(COLOR_MODE_SATURATED)) {
                colorMode = COLOR_MODE_SATURATED;
            } else {
                colorMode = -1;
            }
        }

        return colorMode;
    }

    /**
     * Get the current color mode from system properties, or return -1 if invalid.
     *
     * See {@link com.android.server.display.DisplayTransformManager}
     */
    private @ColorMode
    int getCurrentColorModeFromSystemProperties() {
        final int displayColorSetting = SystemProperties.getInt("persist.sys.sf.native_mode", 0);
        if (displayColorSetting == 0) {
            return "1.0".equals(SystemProperties.get("persist.sys.sf.color_saturation"))
                    ? COLOR_MODE_NATURAL : COLOR_MODE_BOOSTED;
        } else if (displayColorSetting == 1) {
            return COLOR_MODE_SATURATED;
        } else if (displayColorSetting == 2) {
            return COLOR_MODE_AUTOMATIC;
        } else {
            return -1;
        }
    }

    private boolean isColorModeAvailable(@ColorMode int colorMode) {
        final int[] availableColorModes = getContext().getResources().getIntArray(
                R.array.config_availableColorModes);
        if (availableColorModes != null) {
            for (int mode : availableColorModes) {
                if (mode == colorMode) {
                    return true;
                }
            }
        }
        return false;
    }

    private void dumpInternal(PrintWriter pw) {
        pw.println("COLOR DISPLAY MANAGER dumpsys (color_display)");
        pw.println("Night Display:");
@@ -1445,13 +1531,38 @@ public final class ColorDisplayService extends SystemService {
     */
    public interface ColorTransformController {

        /** Apply the given saturation (grayscale) matrix to the associated AppWindow. */
        /**
         * Apply the given saturation (grayscale) matrix to the associated AppWindow.
         */
        void applyAppSaturation(@Size(9) float[] matrix, @Size(3) float[] translation);
    }

    @VisibleForTesting
    final class BinderService extends IColorDisplayManager.Stub {

        @Override
        public void setColorMode(int colorMode) {
            getContext().enforceCallingOrSelfPermission(
                    Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
                    "Permission required to set display color mode");
            final long token = Binder.clearCallingIdentity();
            try {
                setColorModeInternal(colorMode);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override
        public int getColorMode() {
            final long token = Binder.clearCallingIdentity();
            try {
                return getColorModeInternal();
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override
        public boolean isDeviceColorManaged() {
            final long token = Binder.clearCallingIdentity();
@@ -1640,7 +1751,9 @@ public final class ColorDisplayService extends SystemService {

        @Override
        public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
            if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return;
            if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) {
                return;
            }

            final long token = Binder.clearCallingIdentity();
            try {
Loading