/*
 * Copyright (C) 2016 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 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 android.hardware.display.ColorDisplayManager.VENDOR_COLOR_MODE_RANGE_MAX;
import static android.hardware.display.ColorDisplayManager.VENDOR_COLOR_MODE_RANGE_MIN;

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

import android.Manifest;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.TypeEvaluator;
import android.animation.ValueAnimator;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Size;
import android.annotation.UserIdInt;
import android.app.AlarmManager;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.database.ContentObserver;
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;
import android.opengl.Matrix;
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;
import android.util.MathUtils;
import android.util.Slog;
import android.util.SparseIntArray;
import android.view.Display;
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.util.DumpUtils;
import com.android.server.DisplayThread;
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;
import java.time.DateTimeException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeParseException;

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

    static final String TAG = "ColorDisplayService";

    /**
     * The identity matrix, used if one of the given matrices is {@code null}.
     */
    static final float[] MATRIX_IDENTITY = new float[16];

    static {
        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_USER_CHANGED = 0;
    private static final int MSG_SET_UP = 1;
    private static final int MSG_APPLY_NIGHT_DISPLAY_IMMEDIATE = 2;
    private static final int MSG_APPLY_NIGHT_DISPLAY_ANIMATED = 3;
    private static final int MSG_APPLY_GLOBAL_SATURATION = 4;
    private static final int MSG_APPLY_DISPLAY_WHITE_BALANCE = 5;

    /**
     * Return value if a setting has not been set.
     */
    private static final int NOT_SET = -1;

    /**
     * Evaluator used to animate color matrix transitions.
     */
    private static final ColorMatrixEvaluator COLOR_MATRIX_EVALUATOR = new ColorMatrixEvaluator();

    private final NightDisplayTintController mNightDisplayTintController =
            new NightDisplayTintController();

    @VisibleForTesting
    final DisplayWhiteBalanceTintController mDisplayWhiteBalanceTintController =
            new DisplayWhiteBalanceTintController();

    private final TintController mGlobalSaturationTintController =
            new GlobalSaturationTintController();

    /**
     * Matrix and offset used for converting color to grayscale.
     */
    private static final float[] MATRIX_GRAYSCALE = new float[]{
            .2126f, .2126f, .2126f, 0f,
            .7152f, .7152f, .7152f, 0f,
            .0722f, .0722f, .0722f, 0f,
            0f, 0f, 0f, 1f
    };

    /**
     * Matrix and offset used for luminance inversion. Represents a transform from RGB to YIQ color
     * space, rotation around the Y axis by 180 degrees, transform back to RGB color space, and
     * subtraction from 1. The last row represents a non-multiplied addition, see surfaceflinger's
     * ProgramCache for full implementation details.
     */
    private static final float[] MATRIX_INVERT_COLOR = new float[]{
            0.402f, -0.598f, -0.599f, 0f,
            -1.174f, -0.174f, -1.175f, 0f,
            -0.228f, -0.228f, 0.772f, 0f,
            1f, 1f, 1f, 1f
    };

    private final Handler mHandler;

    private final AppSaturationController mAppSaturationController = new AppSaturationController();

    private int mCurrentUser = UserHandle.USER_NULL;
    private ContentObserver mUserSetupObserver;
    private boolean mBootCompleted;

    private ContentObserver mContentObserver;

    private DisplayWhiteBalanceListener mDisplayWhiteBalanceListener;

    private NightDisplayAutoMode mNightDisplayAutoMode;

    /**
     * Map of color modes -> display composition colorspace
     */
    private SparseIntArray mColorModeCompositionColorSpaces = null;

    public ColorDisplayService(Context context) {
        super(context);
        mHandler = new TintHandler(DisplayThread.get().getLooper());
    }

    @Override
    public void onStart() {
        publishBinderService(Context.COLOR_DISPLAY_SERVICE, new BinderService());
        publishLocalService(ColorDisplayServiceInternal.class, new ColorDisplayServiceInternal());
        publishLocalService(DisplayTransformManager.class, new DisplayTransformManager());
    }

    @Override
    public void onBootPhase(int phase) {
        if (phase >= PHASE_BOOT_COMPLETED) {
            mBootCompleted = true;

            // Register listeners now that boot is complete.
            if (mCurrentUser != UserHandle.USER_NULL && mUserSetupObserver == null) {
                mHandler.sendEmptyMessage(MSG_SET_UP);
            }
        }
    }

    @Override
    public void onStartUser(int userHandle) {
        super.onStartUser(userHandle);

        if (mCurrentUser == UserHandle.USER_NULL) {
            final Message message = mHandler.obtainMessage(MSG_USER_CHANGED);
            message.arg1 = userHandle;
            mHandler.sendMessage(message);
        }
    }

    @Override
    public void onSwitchUser(int userHandle) {
        super.onSwitchUser(userHandle);

        final Message message = mHandler.obtainMessage(MSG_USER_CHANGED);
        message.arg1 = userHandle;
        mHandler.sendMessage(message);
    }

    @Override
    public void onStopUser(int userHandle) {
        super.onStopUser(userHandle);

        if (mCurrentUser == userHandle) {
            final Message message = mHandler.obtainMessage(MSG_USER_CHANGED);
            message.arg1 = UserHandle.USER_NULL;
            mHandler.sendMessage(message);
        }
    }

    @VisibleForTesting void onUserChanged(int userHandle) {
        final ContentResolver cr = getContext().getContentResolver();

        if (mCurrentUser != UserHandle.USER_NULL) {
            if (mUserSetupObserver != null) {
                cr.unregisterContentObserver(mUserSetupObserver);
                mUserSetupObserver = null;
            } else if (mBootCompleted) {
                tearDown();
            }
        }

        mCurrentUser = userHandle;

        if (mCurrentUser != UserHandle.USER_NULL) {
            if (!isUserSetupCompleted(cr, mCurrentUser)) {
                mUserSetupObserver = new ContentObserver(mHandler) {
                    @Override
                    public void onChange(boolean selfChange, Uri uri) {
                        if (isUserSetupCompleted(cr, mCurrentUser)) {
                            cr.unregisterContentObserver(this);
                            mUserSetupObserver = null;

                            if (mBootCompleted) {
                                setUp();
                            }
                        }
                    }
                };
                cr.registerContentObserver(Secure.getUriFor(Secure.USER_SETUP_COMPLETE),
                        false /* notifyForDescendants */, mUserSetupObserver, mCurrentUser);
            } else if (mBootCompleted) {
                setUp();
            }
        }
    }

    private static boolean isUserSetupCompleted(ContentResolver cr, int userHandle) {
        return Secure.getIntForUser(cr, Secure.USER_SETUP_COMPLETE, 0, userHandle) == 1;
    }

    private void setUpDisplayCompositionColorSpaces(Resources res) {
        mColorModeCompositionColorSpaces = null;

        final int[] colorModes = res.getIntArray(R.array.config_displayCompositionColorModes);
        if (colorModes == null) {
            return;
        }

        final int[] compSpaces = res.getIntArray(R.array.config_displayCompositionColorSpaces);
        if (compSpaces == null) {
            return;
        }

        if (colorModes.length != compSpaces.length) {
            Slog.e(TAG, "Number of composition color spaces doesn't match specified color modes");
            return;
        }

        mColorModeCompositionColorSpaces = new SparseIntArray(colorModes.length);
        for (int i = 0; i < colorModes.length; i++) {
            mColorModeCompositionColorSpaces.put(colorModes[i], compSpaces[i]);
        }
    }

    private void setUp() {
        Slog.d(TAG, "setUp: currentUser=" + mCurrentUser);

        // Listen for external changes to any of the settings.
        if (mContentObserver == null) {
            mContentObserver = new ContentObserver(mHandler) {
                @Override
                public void onChange(boolean selfChange, Uri uri) {
                    super.onChange(selfChange, uri);

                    final String setting = uri == null ? null : uri.getLastPathSegment();
                    if (setting != null) {
                        switch (setting) {
                            case Secure.NIGHT_DISPLAY_ACTIVATED:
                                final boolean activated = mNightDisplayTintController
                                        .isActivatedSetting();
                                if (mNightDisplayTintController.isActivatedStateNotSet()
                                        || mNightDisplayTintController.isActivated() != activated) {
                                    mNightDisplayTintController.setActivated(activated);
                                }
                                break;
                            case Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE:
                                final int temperature = mNightDisplayTintController
                                        .getColorTemperatureSetting();
                                if (mNightDisplayTintController.getColorTemperature()
                                        != temperature) {
                                    mNightDisplayTintController
                                            .onColorTemperatureChanged(temperature);
                                }
                                break;
                            case Secure.NIGHT_DISPLAY_AUTO_MODE:
                                onNightDisplayAutoModeChanged(getNightDisplayAutoModeInternal());
                                break;
                            case Secure.NIGHT_DISPLAY_CUSTOM_START_TIME:
                                onNightDisplayCustomStartTimeChanged(
                                        getNightDisplayCustomStartTimeInternal().getLocalTime());
                                break;
                            case Secure.NIGHT_DISPLAY_CUSTOM_END_TIME:
                                onNightDisplayCustomEndTimeChanged(
                                        getNightDisplayCustomEndTimeInternal().getLocalTime());
                                break;
                            case System.DISPLAY_COLOR_MODE:
                                onDisplayColorModeChanged(getColorModeInternal());
                                break;
                            case Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED:
                                onAccessibilityInversionChanged();
                                onAccessibilityActivated();
                                break;
                            case Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED:
                                onAccessibilityDaltonizerChanged();
                                onAccessibilityActivated();
                                break;
                            case Secure.ACCESSIBILITY_DISPLAY_DALTONIZER:
                                onAccessibilityDaltonizerChanged();
                                break;
                            case Secure.DISPLAY_WHITE_BALANCE_ENABLED:
                                updateDisplayWhiteBalanceStatus();
                                break;
                        }
                    }
                }
            };
        }
        final ContentResolver cr = getContext().getContentResolver();
        cr.registerContentObserver(Secure.getUriFor(Secure.NIGHT_DISPLAY_ACTIVATED),
                false /* notifyForDescendants */, mContentObserver, mCurrentUser);
        cr.registerContentObserver(Secure.getUriFor(Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE),
                false /* notifyForDescendants */, mContentObserver, mCurrentUser);
        cr.registerContentObserver(Secure.getUriFor(Secure.NIGHT_DISPLAY_AUTO_MODE),
                false /* notifyForDescendants */, mContentObserver, mCurrentUser);
        cr.registerContentObserver(Secure.getUriFor(Secure.NIGHT_DISPLAY_CUSTOM_START_TIME),
                false /* notifyForDescendants */, mContentObserver, mCurrentUser);
        cr.registerContentObserver(Secure.getUriFor(Secure.NIGHT_DISPLAY_CUSTOM_END_TIME),
                false /* notifyForDescendants */, mContentObserver, mCurrentUser);
        cr.registerContentObserver(System.getUriFor(System.DISPLAY_COLOR_MODE),
                false /* notifyForDescendants */, mContentObserver, mCurrentUser);
        cr.registerContentObserver(
                Secure.getUriFor(Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED),
                false /* notifyForDescendants */, mContentObserver, mCurrentUser);
        cr.registerContentObserver(
                Secure.getUriFor(Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED),
                false /* notifyForDescendants */, mContentObserver, mCurrentUser);
        cr.registerContentObserver(
                Secure.getUriFor(Secure.ACCESSIBILITY_DISPLAY_DALTONIZER),
                false /* notifyForDescendants */, mContentObserver, mCurrentUser);
        cr.registerContentObserver(Secure.getUriFor(Secure.DISPLAY_WHITE_BALANCE_ENABLED),
                false /* notifyForDescendants */, mContentObserver, mCurrentUser);

        // Apply the accessibility settings first, since they override most other settings.
        onAccessibilityInversionChanged();
        onAccessibilityDaltonizerChanged();

        setUpDisplayCompositionColorSpaces(getContext().getResources());

        // Set the color mode, if valid, and immediately apply the updated tint matrix based on the
        // existing activated state. This ensures consistency of tint across the color mode change.
        onDisplayColorModeChanged(getColorModeInternal());

        if (mNightDisplayTintController.isAvailable(getContext())) {
            // Reset the activated state.
            mNightDisplayTintController.setActivated(null);

            // Prepare the night display color transformation matrix.
            mNightDisplayTintController
                    .setUp(getContext(), DisplayTransformManager.needsLinearColorMatrix());
            mNightDisplayTintController
                    .setMatrix(mNightDisplayTintController.getColorTemperatureSetting());

            // Initialize the current auto mode.
            onNightDisplayAutoModeChanged(getNightDisplayAutoModeInternal());

            // Force the initialization of the current saved activation state.
            if (mNightDisplayTintController.isActivatedStateNotSet()) {
                mNightDisplayTintController
                        .setActivated(mNightDisplayTintController.isActivatedSetting());
            }
        }

        if (mDisplayWhiteBalanceTintController.isAvailable(getContext())) {
            // Prepare the display white balance transform matrix.
            mDisplayWhiteBalanceTintController.setUp(getContext(), true /* needsLinear */);

            updateDisplayWhiteBalanceStatus();
        }
    }

    private void tearDown() {
        Slog.d(TAG, "tearDown: currentUser=" + mCurrentUser);

        if (mContentObserver != null) {
            getContext().getContentResolver().unregisterContentObserver(mContentObserver);
        }

        if (mNightDisplayTintController.isAvailable(getContext())) {
            if (mNightDisplayAutoMode != null) {
                mNightDisplayAutoMode.onStop();
                mNightDisplayAutoMode = null;
            }
            mNightDisplayTintController.endAnimator();
        }

        if (mDisplayWhiteBalanceTintController.isAvailable(getContext())) {
            mDisplayWhiteBalanceTintController.endAnimator();
        }

        if (mGlobalSaturationTintController.isAvailable(getContext())) {
            mGlobalSaturationTintController.setActivated(null);
        }
    }

    private void onNightDisplayAutoModeChanged(int autoMode) {
        Slog.d(TAG, "onNightDisplayAutoModeChanged: autoMode=" + autoMode);

        if (mNightDisplayAutoMode != null) {
            mNightDisplayAutoMode.onStop();
            mNightDisplayAutoMode = null;
        }

        if (autoMode == AUTO_MODE_CUSTOM_TIME) {
            mNightDisplayAutoMode = new CustomNightDisplayAutoMode();
        } else if (autoMode == AUTO_MODE_TWILIGHT) {
            mNightDisplayAutoMode = new TwilightNightDisplayAutoMode();
        }

        if (mNightDisplayAutoMode != null) {
            mNightDisplayAutoMode.onStart();
        }
    }

    private void onNightDisplayCustomStartTimeChanged(LocalTime startTime) {
        Slog.d(TAG, "onNightDisplayCustomStartTimeChanged: startTime=" + startTime);

        if (mNightDisplayAutoMode != null) {
            mNightDisplayAutoMode.onCustomStartTimeChanged(startTime);
        }
    }

    private void onNightDisplayCustomEndTimeChanged(LocalTime endTime) {
        Slog.d(TAG, "onNightDisplayCustomEndTimeChanged: endTime=" + endTime);

        if (mNightDisplayAutoMode != null) {
            mNightDisplayAutoMode.onCustomEndTimeChanged(endTime);
        }
    }

    private int getCompositionColorSpace(int mode) {
        if (mColorModeCompositionColorSpaces == null) {
            return Display.COLOR_MODE_INVALID;
        }

        return mColorModeCompositionColorSpaces.get(mode, Display.COLOR_MODE_INVALID);
    }

    private void onDisplayColorModeChanged(int mode) {
        if (mode == NOT_SET) {
            return;
        }

        mNightDisplayTintController.cancelAnimator();
        mDisplayWhiteBalanceTintController.cancelAnimator();

        if (mNightDisplayTintController.isAvailable(getContext())) {
            mNightDisplayTintController
                    .setUp(getContext(), DisplayTransformManager.needsLinearColorMatrix(mode));
            mNightDisplayTintController
                    .setMatrix(mNightDisplayTintController.getColorTemperatureSetting());
        }

        // dtm.setColorMode() needs to be called before
        // updateDisplayWhiteBalanceStatus(), this is because the latter calls
        // DisplayTransformManager.needsLinearColorMatrix(), therefore it is dependent
        // on the state of DisplayTransformManager.
        final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class);
        dtm.setColorMode(mode, mNightDisplayTintController.getMatrix(),
                getCompositionColorSpace(mode));

        if (mDisplayWhiteBalanceTintController.isAvailable(getContext())) {
            updateDisplayWhiteBalanceStatus();
        }
    }

    private void onAccessibilityActivated() {
        onDisplayColorModeChanged(getColorModeInternal());
    }

    private boolean isAccessiblityDaltonizerEnabled() {
        return Secure.getIntForUser(getContext().getContentResolver(),
            Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0, mCurrentUser) != 0;
    }

    private boolean isAccessiblityInversionEnabled() {
        return Secure.getIntForUser(getContext().getContentResolver(),
            Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, mCurrentUser) != 0;
    }

    private boolean isAccessibilityEnabled() {
        return isAccessiblityDaltonizerEnabled() || isAccessiblityInversionEnabled();
    }

    /**
     * Apply the accessibility daltonizer transform based on the settings value.
     */
    private void onAccessibilityDaltonizerChanged() {
        if (mCurrentUser == UserHandle.USER_NULL) {
            return;
        }
        final int daltonizerMode = isAccessiblityDaltonizerEnabled()
                ? Secure.getIntForUser(getContext().getContentResolver(),
                    Secure.ACCESSIBILITY_DISPLAY_DALTONIZER,
                    AccessibilityManager.DALTONIZER_CORRECT_DEUTERANOMALY, mCurrentUser)
                : AccessibilityManager.DALTONIZER_DISABLED;

        final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class);
        if (daltonizerMode == AccessibilityManager.DALTONIZER_SIMULATE_MONOCHROMACY) {
            // Monochromacy isn't supported by the native Daltonizer implementation; use grayscale.
            dtm.setColorMatrix(DisplayTransformManager.LEVEL_COLOR_MATRIX_GRAYSCALE,
                    MATRIX_GRAYSCALE);
            dtm.setDaltonizerMode(AccessibilityManager.DALTONIZER_DISABLED);
        } else {
            dtm.setColorMatrix(DisplayTransformManager.LEVEL_COLOR_MATRIX_GRAYSCALE, null);
            dtm.setDaltonizerMode(daltonizerMode);
        }
    }

    /**
     * Apply the accessibility inversion transform based on the settings value.
     */
    private void onAccessibilityInversionChanged() {
        if (mCurrentUser == UserHandle.USER_NULL) {
            return;
        }
        final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class);
        dtm.setColorMatrix(DisplayTransformManager.LEVEL_COLOR_MATRIX_INVERT_COLOR,
                isAccessiblityInversionEnabled() ? MATRIX_INVERT_COLOR : null);
    }

    /**
     * Applies current color temperature matrix, or removes it if deactivated.
     *
     * @param immediate {@code true} skips transition animation
     */
    private void applyTint(TintController tintController, boolean immediate) {
        tintController.cancelAnimator();

        final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class);
        final float[] from = dtm.getColorMatrix(tintController.getLevel());
        final float[] to = tintController.getMatrix();

        if (immediate) {
            dtm.setColorMatrix(tintController.getLevel(), to);
        } else {
            tintController.setAnimator(ValueAnimator.ofObject(COLOR_MATRIX_EVALUATOR,
                    from == null ? MATRIX_IDENTITY : from, to));
            tintController.getAnimator().setDuration(TRANSITION_DURATION);
            tintController.getAnimator().setInterpolator(AnimationUtils.loadInterpolator(
                    getContext(), android.R.interpolator.fast_out_slow_in));
            tintController.getAnimator().addUpdateListener((ValueAnimator animator) -> {
                final float[] value = (float[]) animator.getAnimatedValue();
                dtm.setColorMatrix(tintController.getLevel(), value);
            });
            tintController.getAnimator().addListener(new AnimatorListenerAdapter() {

                private boolean mIsCancelled;

                @Override
                public void onAnimationCancel(Animator animator) {
                    mIsCancelled = true;
                }

                @Override
                public void onAnimationEnd(Animator animator) {
                    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(), to);
                    }
                    tintController.setAnimator(null);
                }
            });
            tintController.getAnimator().start();
        }
    }

    /**
     * Returns the first date time corresponding to the local time that occurs before the provided
     * date time.
     *
     * @param compareTime the LocalDateTime to compare against
     * @return the prior LocalDateTime corresponding to this local time
     */
    @VisibleForTesting
    static LocalDateTime getDateTimeBefore(LocalTime localTime, LocalDateTime compareTime) {
        final LocalDateTime ldt = LocalDateTime.of(compareTime.getYear(), compareTime.getMonth(),
                compareTime.getDayOfMonth(), localTime.getHour(), localTime.getMinute());

        // Check if the local time has passed, if so return the same time yesterday.
        return ldt.isAfter(compareTime) ? ldt.minusDays(1) : ldt;
    }

    /**
     * Returns the first date time corresponding to this local time that occurs after the provided
     * date time.
     *
     * @param compareTime the LocalDateTime to compare against
     * @return the next LocalDateTime corresponding to this local time
     */
    @VisibleForTesting
    static LocalDateTime getDateTimeAfter(LocalTime localTime, LocalDateTime compareTime) {
        final LocalDateTime ldt = LocalDateTime.of(compareTime.getYear(), compareTime.getMonth(),
                compareTime.getDayOfMonth(), localTime.getHour(), localTime.getMinute());

        // Check if the local time has passed, if so return the same time tomorrow.
        return ldt.isBefore(compareTime) ? ldt.plusDays(1) : ldt;
    }

    @VisibleForTesting
    void updateDisplayWhiteBalanceStatus() {
        boolean oldActivated = mDisplayWhiteBalanceTintController.isActivated();
        mDisplayWhiteBalanceTintController.setActivated(isDisplayWhiteBalanceSettingEnabled()
                && !mNightDisplayTintController.isActivated()
                && !isAccessibilityEnabled()
                && DisplayTransformManager.needsLinearColorMatrix());
        boolean activated = mDisplayWhiteBalanceTintController.isActivated();

        if (mDisplayWhiteBalanceListener != null && oldActivated != activated) {
            mDisplayWhiteBalanceListener.onDisplayWhiteBalanceStatusChanged(activated);
        }

        // If disabled, clear the tint. If enabled, do nothing more here and let the next
        // temperature update set the correct tint.
        if (!activated) {
            mHandler.sendEmptyMessage(MSG_APPLY_DISPLAY_WHITE_BALANCE);
        }
    }

    private boolean setDisplayWhiteBalanceSettingEnabled(boolean enabled) {
        if (mCurrentUser == UserHandle.USER_NULL) {
            return false;
        }
        return Secure.putIntForUser(getContext().getContentResolver(),
                Secure.DISPLAY_WHITE_BALANCE_ENABLED,
                enabled ? 1 : 0, mCurrentUser);
    }

    private boolean isDisplayWhiteBalanceSettingEnabled() {
        if (mCurrentUser == UserHandle.USER_NULL) {
            return false;
        }
        return Secure.getIntForUser(getContext().getContentResolver(),
                Secure.DISPLAY_WHITE_BALANCE_ENABLED,
                getContext().getResources()
                        .getBoolean(R.bool.config_displayWhiteBalanceEnabledDefault) ? 1
                        : 0,
                mCurrentUser) == 1;
    }

    private boolean isDeviceColorManagedInternal() {
        final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class);
        return dtm.isDeviceColorManaged();
    }

    private int getTransformCapabilitiesInternal() {
        int availabilityFlags = ColorDisplayManager.CAPABILITY_NONE;
        if (SurfaceControl.getProtectedContentSupport()) {
            availabilityFlags |= ColorDisplayManager.CAPABILITY_PROTECTED_CONTENT;
        }
        final Resources res = getContext().getResources();
        if (res.getBoolean(R.bool.config_setColorTransformAccelerated)) {
            availabilityFlags |= ColorDisplayManager.CAPABILITY_HARDWARE_ACCELERATION_GLOBAL;
        }
        if (res.getBoolean(R.bool.config_setColorTransformAcceleratedPerLayer)) {
            availabilityFlags |= ColorDisplayManager.CAPABILITY_HARDWARE_ACCELERATION_PER_APP;
        }
        return availabilityFlags;
    }

    private boolean setNightDisplayAutoModeInternal(@AutoMode int autoMode) {
        if (getNightDisplayAutoModeInternal() != autoMode) {
            Secure.putStringForUser(getContext().getContentResolver(),
                    Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME,
                    null,
                    mCurrentUser);
        }
        return Secure.putIntForUser(getContext().getContentResolver(),
                Secure.NIGHT_DISPLAY_AUTO_MODE, autoMode, mCurrentUser);
    }

    private int getNightDisplayAutoModeInternal() {
        int autoMode = getNightDisplayAutoModeRawInternal();
        if (autoMode == NOT_SET) {
            autoMode = getContext().getResources().getInteger(
                    R.integer.config_defaultNightDisplayAutoMode);
        }
        if (autoMode != AUTO_MODE_DISABLED
                && autoMode != AUTO_MODE_CUSTOM_TIME
                && autoMode != AUTO_MODE_TWILIGHT) {
            Slog.e(TAG, "Invalid autoMode: " + autoMode);
            autoMode = AUTO_MODE_DISABLED;
        }
        return autoMode;
    }

    private int getNightDisplayAutoModeRawInternal() {
        if (mCurrentUser == UserHandle.USER_NULL) {
            return NOT_SET;
        }
        return Secure
                .getIntForUser(getContext().getContentResolver(), Secure.NIGHT_DISPLAY_AUTO_MODE,
                        NOT_SET, mCurrentUser);
    }

    private Time getNightDisplayCustomStartTimeInternal() {
        int startTimeValue = Secure.getIntForUser(getContext().getContentResolver(),
                Secure.NIGHT_DISPLAY_CUSTOM_START_TIME, NOT_SET, mCurrentUser);
        if (startTimeValue == NOT_SET) {
            startTimeValue = getContext().getResources().getInteger(
                    R.integer.config_defaultNightDisplayCustomStartTime);
        }
        return new Time(LocalTime.ofSecondOfDay(startTimeValue / 1000));
    }

    private boolean setNightDisplayCustomStartTimeInternal(Time startTime) {
        return Secure.putIntForUser(getContext().getContentResolver(),
                Secure.NIGHT_DISPLAY_CUSTOM_START_TIME,
                startTime.getLocalTime().toSecondOfDay() * 1000,
                mCurrentUser);
    }

    private Time getNightDisplayCustomEndTimeInternal() {
        int endTimeValue = Secure.getIntForUser(getContext().getContentResolver(),
                Secure.NIGHT_DISPLAY_CUSTOM_END_TIME, NOT_SET, mCurrentUser);
        if (endTimeValue == NOT_SET) {
            endTimeValue = getContext().getResources().getInteger(
                    R.integer.config_defaultNightDisplayCustomEndTime);
        }
        return new Time(LocalTime.ofSecondOfDay(endTimeValue / 1000));
    }

    private boolean setNightDisplayCustomEndTimeInternal(Time endTime) {
        return Secure.putIntForUser(getContext().getContentResolver(),
                Secure.NIGHT_DISPLAY_CUSTOM_END_TIME, endTime.getLocalTime().toSecondOfDay() * 1000,
                mCurrentUser);
    }

    /**
     * Returns the last time the night display transform activation state was changed, or {@link
     * LocalDateTime#MIN} if night display has never been activated.
     */
    private LocalDateTime getNightDisplayLastActivatedTimeSetting() {
        final ContentResolver cr = getContext().getContentResolver();
        final String lastActivatedTime = Secure.getStringForUser(
                cr, Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, getContext().getUserId());
        if (lastActivatedTime != null) {
            try {
                return LocalDateTime.parse(lastActivatedTime);
            } catch (DateTimeParseException ignored) {
            }
            // Uses the old epoch time.
            try {
                return LocalDateTime.ofInstant(
                        Instant.ofEpochMilli(Long.parseLong(lastActivatedTime)),
                        ZoneId.systemDefault());
            } catch (DateTimeException | NumberFormatException ignored) {
            }
        }
        return LocalDateTime.MIN;
    }

    private boolean setAppSaturationLevelInternal(String packageName, int saturationLevel) {
        return mAppSaturationController
                .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 (isAccessibilityEnabled()) {
            // There are restrictions on the available color modes combined with a11y transforms.
            final int a11yColorMode = getContext().getResources().getInteger(
                    R.integer.config_accessibilityColorMode);
            if (a11yColorMode >= 0) {
                return a11yColorMode;
            }
        }

        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 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 if (displayColorSetting >= VENDOR_COLOR_MODE_RANGE_MIN
                && displayColorSetting <= VENDOR_COLOR_MODE_RANGE_MAX) {
            return displayColorSetting;
        } 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:");
        if (mNightDisplayTintController.isAvailable(getContext())) {
            pw.println("    Activated: " + mNightDisplayTintController.isActivated());
            pw.println("    Color temp: " + mNightDisplayTintController.getColorTemperature());
        } else {
            pw.println("    Not available");
        }

        pw.println("Global saturation:");
        if (mGlobalSaturationTintController.isAvailable(getContext())) {
            pw.println("    Activated: " + mGlobalSaturationTintController.isActivated());
        } else {
            pw.println("    Not available");
        }

        mAppSaturationController.dump(pw);

        pw.println("Display white balance:");
        if (mDisplayWhiteBalanceTintController.isAvailable(getContext())) {
            pw.println("    Activated: " + mDisplayWhiteBalanceTintController.isActivated());
            mDisplayWhiteBalanceTintController.dump(pw);
        } else {
            pw.println("    Not available");
        }

        pw.println("Color mode: " + getColorModeInternal());
    }

    private abstract class NightDisplayAutoMode {

        public abstract void onActivated(boolean activated);

        public abstract void onStart();

        public abstract void onStop();

        public void onCustomStartTimeChanged(LocalTime startTime) {
        }

        public void onCustomEndTimeChanged(LocalTime endTime) {
        }
    }

    private final class CustomNightDisplayAutoMode extends NightDisplayAutoMode implements
            AlarmManager.OnAlarmListener {

        private final AlarmManager mAlarmManager;
        private final BroadcastReceiver mTimeChangedReceiver;

        private LocalTime mStartTime;
        private LocalTime mEndTime;

        private LocalDateTime mLastActivatedTime;

        CustomNightDisplayAutoMode() {
            mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
            mTimeChangedReceiver = new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    updateActivated();
                }
            };
        }

        private void updateActivated() {
            final LocalDateTime now = LocalDateTime.now();
            final LocalDateTime start = getDateTimeBefore(mStartTime, now);
            final LocalDateTime end = getDateTimeAfter(mEndTime, start);
            boolean activate = now.isBefore(end);

            if (mLastActivatedTime != null) {
                // Maintain the existing activated state if within the current period.
                if (mLastActivatedTime.isBefore(now)
                        && mLastActivatedTime.isAfter(start)
                        && (mLastActivatedTime.isAfter(end) || now.isBefore(end))) {
                    activate = mNightDisplayTintController.isActivatedSetting();
                }
            }

            if (mNightDisplayTintController.isActivatedStateNotSet()
                    || (mNightDisplayTintController.isActivated() != activate)) {
                mNightDisplayTintController.setActivated(activate, activate ? start : end);
            }

            updateNextAlarm(mNightDisplayTintController.isActivated(), now);
        }

        private void updateNextAlarm(@Nullable Boolean activated, @NonNull LocalDateTime now) {
            if (activated != null) {
                final LocalDateTime next = activated ? getDateTimeAfter(mEndTime, now)
                        : getDateTimeAfter(mStartTime, now);
                final long millis = next.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
                mAlarmManager.setExact(AlarmManager.RTC, millis, TAG, this, null);
            }
        }

        @Override
        public void onStart() {
            final IntentFilter intentFilter = new IntentFilter(Intent.ACTION_TIME_CHANGED);
            intentFilter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
            getContext().registerReceiver(mTimeChangedReceiver, intentFilter);

            mStartTime = getNightDisplayCustomStartTimeInternal().getLocalTime();
            mEndTime = getNightDisplayCustomEndTimeInternal().getLocalTime();

            mLastActivatedTime = getNightDisplayLastActivatedTimeSetting();

            // Force an update to initialize state.
            updateActivated();
        }

        @Override
        public void onStop() {
            getContext().unregisterReceiver(mTimeChangedReceiver);

            mAlarmManager.cancel(this);
            mLastActivatedTime = null;
        }

        @Override
        public void onActivated(boolean activated) {
            mLastActivatedTime = getNightDisplayLastActivatedTimeSetting();
            updateNextAlarm(activated, LocalDateTime.now());
        }

        @Override
        public void onCustomStartTimeChanged(LocalTime startTime) {
            mStartTime = startTime;
            mLastActivatedTime = null;
            updateActivated();
        }

        @Override
        public void onCustomEndTimeChanged(LocalTime endTime) {
            mEndTime = endTime;
            mLastActivatedTime = null;
            updateActivated();
        }

        @Override
        public void onAlarm() {
            Slog.d(TAG, "onAlarm");
            updateActivated();
        }
    }

    private final class TwilightNightDisplayAutoMode extends NightDisplayAutoMode implements
            TwilightListener {

        private final TwilightManager mTwilightManager;
        private LocalDateTime mLastActivatedTime;

        TwilightNightDisplayAutoMode() {
            mTwilightManager = getLocalService(TwilightManager.class);
        }

        private void updateActivated(TwilightState state) {
            if (state == null) {
                // If there isn't a valid TwilightState then just keep the current activated
                // state.
                return;
            }

            boolean activate = state.isNight();
            if (mLastActivatedTime != null) {
                final LocalDateTime now = LocalDateTime.now();
                final LocalDateTime sunrise = state.sunrise();
                final LocalDateTime sunset = state.sunset();
                // Maintain the existing activated state if within the current period.
                if (mLastActivatedTime.isBefore(now) && (mLastActivatedTime.isBefore(sunrise)
                        ^ mLastActivatedTime.isBefore(sunset))) {
                    activate = mNightDisplayTintController.isActivatedSetting();
                }
            }

            if (mNightDisplayTintController.isActivatedStateNotSet() || (
                    mNightDisplayTintController.isActivated() != activate)) {
                mNightDisplayTintController.setActivated(activate);
            }
        }

        @Override
        public void onActivated(boolean activated) {
            mLastActivatedTime = getNightDisplayLastActivatedTimeSetting();
        }

        @Override
        public void onStart() {
            mTwilightManager.registerListener(this, mHandler);
            mLastActivatedTime = getNightDisplayLastActivatedTimeSetting();

            // Force an update to initialize state.
            updateActivated(mTwilightManager.getLastTwilightState());
        }

        @Override
        public void onStop() {
            mTwilightManager.unregisterListener(this);
            mLastActivatedTime = null;
        }

        @Override
        public void onTwilightStateChanged(@Nullable TwilightState state) {
            Slog.d(TAG, "onTwilightStateChanged: isNight="
                    + (state == null ? null : state.isNight()));
            updateActivated(state);
        }
    }

    /**
     * Interpolates between two 4x4 color transform matrices (in column-major order).
     */
    private static class ColorMatrixEvaluator implements TypeEvaluator<float[]> {

        /**
         * Result matrix returned by {@link #evaluate(float, float[], float[])}.
         */
        private final float[] mResultMatrix = new float[16];

        @Override
        public float[] evaluate(float fraction, float[] startValue, float[] endValue) {
            for (int i = 0; i < mResultMatrix.length; i++) {
                mResultMatrix[i] = MathUtils.lerp(startValue[i], endValue[i], fraction);
            }
            return mResultMatrix;
        }
    }

    private final class NightDisplayTintController extends TintController {

        private final float[] mMatrix = new float[16];
        private final float[] mColorTempCoefficients = new float[9];

        private Boolean mIsAvailable;
        private Integer mColorTemp;

        /**
         * Set coefficients based on whether the color matrix is linear or not.
         */
        @Override
        public void setUp(Context context, boolean needsLinear) {
            final String[] coefficients = context.getResources().getStringArray(needsLinear
                    ? R.array.config_nightDisplayColorTemperatureCoefficients
                    : R.array.config_nightDisplayColorTemperatureCoefficientsNative);
            for (int i = 0; i < 9 && i < coefficients.length; i++) {
                mColorTempCoefficients[i] = Float.parseFloat(coefficients[i]);
            }
        }

        @Override
        public void setMatrix(int cct) {
            if (mMatrix.length != 16) {
                Slog.d(TAG, "The display transformation matrix must be 4x4");
                return;
            }

            Matrix.setIdentityM(mMatrix, 0);

            final float squareTemperature = cct * cct;
            final float red = squareTemperature * mColorTempCoefficients[0]
                    + cct * mColorTempCoefficients[1] + mColorTempCoefficients[2];
            final float green = squareTemperature * mColorTempCoefficients[3]
                    + cct * mColorTempCoefficients[4] + mColorTempCoefficients[5];
            final float blue = squareTemperature * mColorTempCoefficients[6]
                    + cct * mColorTempCoefficients[7] + mColorTempCoefficients[8];
            mMatrix[0] = red;
            mMatrix[5] = green;
            mMatrix[10] = blue;
        }

        @Override
        public float[] getMatrix() {
            return isActivated() ? mMatrix : MATRIX_IDENTITY;
        }

        @Override
        public void setActivated(Boolean activated) {
            setActivated(activated, LocalDateTime.now());
        }

        /**
         * Use directly when it is important that the last activation time be exact (for example, an
         * automatic change). Otherwise use {@link #setActivated(Boolean)}.
         */
        public void setActivated(Boolean activated, @NonNull LocalDateTime lastActivationTime) {
            if (activated == null) {
                super.setActivated(null);
                return;
            }

            boolean activationStateChanged = activated != isActivated();

            if (!isActivatedStateNotSet() && activationStateChanged) {
                // This is a true state change, so set this as the last activation time.
                Secure.putStringForUser(getContext().getContentResolver(),
                        Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME,
                        lastActivationTime.toString(),
                        mCurrentUser);
            }

            if (isActivatedStateNotSet() || activationStateChanged) {
                super.setActivated(activated);
                if (isActivatedSetting() != activated) {
                    Secure.putIntForUser(getContext().getContentResolver(),
                            Secure.NIGHT_DISPLAY_ACTIVATED,
                            activated ? 1 : 0, mCurrentUser);
                }
                onActivated(activated);
            }
        }

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

        @Override
        public boolean isAvailable(Context context) {
            if (mIsAvailable == null) {
                mIsAvailable = ColorDisplayManager.isNightDisplayAvailable(context);
            }
            return mIsAvailable;
        }

        private void onActivated(boolean activated) {
            Slog.i(TAG, activated ? "Turning on night display" : "Turning off night display");
            if (mNightDisplayAutoMode != null) {
                mNightDisplayAutoMode.onActivated(activated);
            }

            if (mDisplayWhiteBalanceTintController.isAvailable(getContext())) {
                updateDisplayWhiteBalanceStatus();
            }

            mHandler.sendEmptyMessage(MSG_APPLY_NIGHT_DISPLAY_ANIMATED);
        }

        int getColorTemperature() {
            return mColorTemp != null ? clampNightDisplayColorTemperature(mColorTemp)
                    : getColorTemperatureSetting();
        }

        boolean setColorTemperature(int temperature) {
            mColorTemp = temperature;
            final boolean success = Secure.putIntForUser(getContext().getContentResolver(),
                    Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE, temperature, mCurrentUser);
            onColorTemperatureChanged(temperature);
            return success;
        }

        void onColorTemperatureChanged(int temperature) {
            setMatrix(temperature);
            mHandler.sendEmptyMessage(MSG_APPLY_NIGHT_DISPLAY_IMMEDIATE);
        }

        boolean isActivatedSetting() {
            if (mCurrentUser == UserHandle.USER_NULL) {
                return false;
            }
            return Secure.getIntForUser(getContext().getContentResolver(),
                    Secure.NIGHT_DISPLAY_ACTIVATED, 0, mCurrentUser) == 1;
        }

        int getColorTemperatureSetting() {
            if (mCurrentUser == UserHandle.USER_NULL) {
                return NOT_SET;
            }
            return clampNightDisplayColorTemperature(Secure.getIntForUser(
                    getContext().getContentResolver(), Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE,
                    NOT_SET,
                    mCurrentUser));
        }

        private int clampNightDisplayColorTemperature(int colorTemperature) {
            if (colorTemperature == NOT_SET) {
                colorTemperature = getContext().getResources().getInteger(
                        R.integer.config_nightDisplayColorTemperatureDefault);
            }
            final int minimumTemperature = ColorDisplayManager
                    .getMinimumColorTemperature(getContext());
            final int maximumTemperature = ColorDisplayManager
                    .getMaximumColorTemperature(getContext());
            if (colorTemperature < minimumTemperature) {
                colorTemperature = minimumTemperature;
            } else if (colorTemperature > maximumTemperature) {
                colorTemperature = maximumTemperature;
            }

            return colorTemperature;
        }
    }

    /**
     * Local service that allows color transforms to be enabled from other system services.
     */
    public final class ColorDisplayServiceInternal {

        /**
         * Set the current CCT value for the display white balance transform, and if the transform
         * is enabled, apply it.
         *
         * @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);

            if (mDisplayWhiteBalanceTintController.isActivated()) {
                mHandler.sendEmptyMessage(MSG_APPLY_DISPLAY_WHITE_BALANCE);
                return true;
            }
            return false;
        }

        /**
         * Reset the CCT value for the display white balance transform to its default value.
         */
        public boolean resetDisplayWhiteBalanceColorTemperature() {
            return setDisplayWhiteBalanceColorTemperature(getContext().getResources()
                    .getInteger(R.integer.config_displayWhiteBalanceColorTemperatureDefault));
        }

        /**
         * Sets the listener and returns whether display white balance is currently enabled.
         */
        public boolean setDisplayWhiteBalanceListener(DisplayWhiteBalanceListener listener) {
            mDisplayWhiteBalanceListener = listener;
            return mDisplayWhiteBalanceTintController.isActivated();
        }

        /**
         * Returns whether Display white balance is currently enabled.
         */
        public boolean isDisplayWhiteBalanceEnabled() {
            return isDisplayWhiteBalanceSettingEnabled();
        }

        /**
         * Adds a {@link WeakReference<ColorTransformController>} for a newly started activity, and
         * invokes {@link ColorTransformController#applyAppSaturation(float[], float[])} if needed.
         */
        public boolean attachColorTransformController(String packageName, @UserIdInt int userId,
                WeakReference<ColorTransformController> controller) {
            return mAppSaturationController
                    .addColorTransformController(packageName, userId, controller);
        }
    }

    /**
     * Listener for changes in display white balance status.
     */
    public interface DisplayWhiteBalanceListener {

        /**
         * Notify that the display white balance status has changed, either due to preemption by
         * another transform or the feature being turned off.
         */
        void onDisplayWhiteBalanceStatusChanged(boolean activated);
    }

    private final class TintHandler extends Handler {

        private TintHandler(Looper looper) {
            super(looper, null, true /* async */);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_USER_CHANGED:
                    onUserChanged(msg.arg1);
                    break;
                case MSG_SET_UP:
                    setUp();
                    break;
                case MSG_APPLY_GLOBAL_SATURATION:
                    mGlobalSaturationTintController.setMatrix(msg.arg1);
                    applyTint(mGlobalSaturationTintController, false);
                    break;
                case MSG_APPLY_NIGHT_DISPLAY_IMMEDIATE:
                    applyTint(mNightDisplayTintController, true);
                    break;
                case MSG_APPLY_NIGHT_DISPLAY_ANIMATED:
                    applyTint(mNightDisplayTintController, false);
                    break;
                case MSG_APPLY_DISPLAY_WHITE_BALANCE:
                    applyTint(mDisplayWhiteBalanceTintController, false);
                    break;
            }
        }
    }

    /**
     * Interface for applying transforms to a given AppWindow.
     */
    public interface ColorTransformController {

        /**
         * 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();
            try {
                return isDeviceColorManagedInternal();
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override
        public boolean setSaturationLevel(int level) {
            final boolean hasTransformsPermission = getContext()
                    .checkCallingPermission(Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
                    == PackageManager.PERMISSION_GRANTED;
            final boolean hasLegacyPermission = getContext()
                    .checkCallingPermission(Manifest.permission.CONTROL_DISPLAY_SATURATION)
                    == PackageManager.PERMISSION_GRANTED;
            if (!hasTransformsPermission && !hasLegacyPermission) {
                throw new SecurityException("Permission required to set display saturation level");
            }
            final long token = Binder.clearCallingIdentity();
            try {
                final Message message = mHandler.obtainMessage(MSG_APPLY_GLOBAL_SATURATION);
                message.arg1 = level;
                mHandler.sendMessage(message);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
            return true;
        }

        @Override
        public boolean isSaturationActivated() {
            getContext().enforceCallingPermission(
                    Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
                    "Permission required to get display saturation level");
            final long token = Binder.clearCallingIdentity();
            try {
                return !mGlobalSaturationTintController.isActivatedStateNotSet()
                        && mGlobalSaturationTintController.isActivated();
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override
        public boolean setAppSaturationLevel(String packageName, int level) {
            getContext().enforceCallingPermission(
                    Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
                    "Permission required to set display saturation level");
            final long token = Binder.clearCallingIdentity();
            try {
                return setAppSaturationLevelInternal(packageName, level);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        public int getTransformCapabilities() {
            getContext().enforceCallingPermission(
                    Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
                    "Permission required to query transform capabilities");
            final long token = Binder.clearCallingIdentity();
            try {
                return getTransformCapabilitiesInternal();
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override
        public boolean setNightDisplayActivated(boolean activated) {
            getContext().enforceCallingOrSelfPermission(
                    Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
                    "Permission required to set night display activated");
            final long token = Binder.clearCallingIdentity();
            try {
                mNightDisplayTintController.setActivated(activated);
                return true;
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override
        public boolean isNightDisplayActivated() {
            final long token = Binder.clearCallingIdentity();
            try {
                return mNightDisplayTintController.isActivated();
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override
        public boolean setNightDisplayColorTemperature(int temperature) {
            getContext().enforceCallingOrSelfPermission(
                    Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
                    "Permission required to set night display temperature");
            final long token = Binder.clearCallingIdentity();
            try {
                return mNightDisplayTintController.setColorTemperature(temperature);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

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

        @Override
        public boolean setNightDisplayAutoMode(int autoMode) {
            getContext().enforceCallingOrSelfPermission(
                    Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
                    "Permission required to set night display auto mode");
            final long token = Binder.clearCallingIdentity();
            try {
                return setNightDisplayAutoModeInternal(autoMode);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override
        public int getNightDisplayAutoMode() {
            getContext().enforceCallingOrSelfPermission(
                    Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
                    "Permission required to get night display auto mode");
            final long token = Binder.clearCallingIdentity();
            try {
                return getNightDisplayAutoModeInternal();
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

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

        @Override
        public boolean setNightDisplayCustomStartTime(Time startTime) {
            getContext().enforceCallingOrSelfPermission(
                    Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
                    "Permission required to set night display custom start time");
            final long token = Binder.clearCallingIdentity();
            try {
                return setNightDisplayCustomStartTimeInternal(startTime);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override
        public Time getNightDisplayCustomStartTime() {
            final long token = Binder.clearCallingIdentity();
            try {
                return getNightDisplayCustomStartTimeInternal();
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override
        public boolean setNightDisplayCustomEndTime(Time endTime) {
            getContext().enforceCallingOrSelfPermission(
                    Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
                    "Permission required to set night display custom end time");
            final long token = Binder.clearCallingIdentity();
            try {
                return setNightDisplayCustomEndTimeInternal(endTime);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override
        public Time getNightDisplayCustomEndTime() {
            final long token = Binder.clearCallingIdentity();
            try {
                return getNightDisplayCustomEndTimeInternal();
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override
        public boolean setDisplayWhiteBalanceEnabled(boolean enabled) {
            getContext().enforceCallingOrSelfPermission(
                    Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
                    "Permission required to set night display activated");
            final long token = Binder.clearCallingIdentity();
            try {
                return setDisplayWhiteBalanceSettingEnabled(enabled);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override
        public boolean isDisplayWhiteBalanceEnabled() {
            final long token = Binder.clearCallingIdentity();
            try {
                return isDisplayWhiteBalanceSettingEnabled();
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

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

            final long token = Binder.clearCallingIdentity();
            try {
                dumpInternal(pw);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }
    }
}
