/*
 * Copyright (C) 2018 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 android.hardware.display;

import android.Manifest;
import android.annotation.IntDef;
import android.annotation.IntRange;
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;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;

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

/**
 * Manages the display's color transforms and modes.
 *
 * @hide
 */
@SystemApi
@SystemService(Context.COLOR_DISPLAY_SERVICE)
public final class ColorDisplayManager {

    /**
     * @hide
     */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({CAPABILITY_NONE, CAPABILITY_PROTECTED_CONTENT, CAPABILITY_HARDWARE_ACCELERATION_GLOBAL,
            CAPABILITY_HARDWARE_ACCELERATION_PER_APP})
    public @interface CapabilityType {}

    /**
     * The device does not support color transforms.
     *
     * @hide
     */
    @SystemApi
    public static final int CAPABILITY_NONE = 0x0;
    /**
     * The device can use GPU composition on protected content (layers whose buffers are protected
     * in the trusted memory zone).
     *
     * @hide
     */
    @SystemApi
    public static final int CAPABILITY_PROTECTED_CONTENT = 0x1;
    /**
     * The device's hardware can efficiently apply transforms to the entire display.
     *
     * @hide
     */
    @SystemApi
    public static final int CAPABILITY_HARDWARE_ACCELERATION_GLOBAL = 0x2;
    /**
     * The device's hardware can efficiently apply transforms to a specific Surface (window) so
     * that apps can be transformed independently of one another.
     *
     * @hide
     */
    @SystemApi
    public static final int CAPABILITY_HARDWARE_ACCELERATION_PER_APP = 0x4;

    /**
     * @hide
     */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({ AUTO_MODE_DISABLED, AUTO_MODE_CUSTOM_TIME, AUTO_MODE_TWILIGHT })
    public @interface AutoMode {}

    /**
     * Auto mode value to prevent Night display from being automatically activated. It can still
     * be activated manually via {@link #setNightDisplayActivated(boolean)}.
     *
     * @see #setNightDisplayAutoMode(int)
     *
     * @hide
     */
    @SystemApi
    public static final int AUTO_MODE_DISABLED = 0;
    /**
     * Auto mode value to automatically activate Night display at a specific start and end time.
     *
     * @see #setNightDisplayAutoMode(int)
     * @see #setNightDisplayCustomStartTime(LocalTime)
     * @see #setNightDisplayCustomEndTime(LocalTime)
     *
     * @hide
     */
    @SystemApi
    public static final int AUTO_MODE_CUSTOM_TIME = 1;
    /**
     * Auto mode value to automatically activate Night display from sunset to sunrise.
     *
     * @see #setNightDisplayAutoMode(int)
     *
     * @hide
     */
    @SystemApi
    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;

    /**
     * Display color mode range reserved for vendor customizations by the RenderIntent definition in
     * hardware/interfaces/graphics/common/1.1/types.hal. These are NOT directly related to (but ARE
     * mutually exclusive with) the {@link ColorMode} constants, but ARE directly related (and ARE
     * mutually exclusive with) the DISPLAY_COLOR_* constants in DisplayTransformManager.
     *
     * @hide
     */
    public static final int VENDOR_COLOR_MODE_RANGE_MIN = 256; // 0x100
    /**
     * @hide
     */
    public static final int VENDOR_COLOR_MODE_RANGE_MAX = 511; // 0x1ff

    private final ColorDisplayManagerInternal mManager;
    private MetricsLogger mMetricsLogger;

    /**
     * @hide
     */
    public ColorDisplayManager() {
        mManager = ColorDisplayManagerInternal.getInstance();
    }

    /**
     * (De)activates the night display transform.
     *
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
    public boolean setNightDisplayActivated(boolean activated) {
        return mManager.setNightDisplayActivated(activated);
    }

    /**
     * Returns whether the night display transform is currently active.
     *
     * @hide
     */
    public boolean isNightDisplayActivated() {
        return mManager.isNightDisplayActivated();
    }

    /**
     * Sets the color temperature of the night display transform.
     *
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
    public boolean setNightDisplayColorTemperature(int temperature) {
        return mManager.setNightDisplayColorTemperature(temperature);
    }

    /**
     * Gets the color temperature of the night display transform.
     *
     * @hide
     */
    public int getNightDisplayColorTemperature() {
        return mManager.getNightDisplayColorTemperature();
    }

    /**
     * Returns the current auto mode value controlling when Night display will be automatically
     * activated. One of {@link #AUTO_MODE_DISABLED}, {@link #AUTO_MODE_CUSTOM_TIME}, or
     * {@link #AUTO_MODE_TWILIGHT}.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
    public @AutoMode int getNightDisplayAutoMode() {
        return mManager.getNightDisplayAutoMode();
    }

    /**
     * Returns the current auto mode value, without validation, or {@code 1} if the auto mode has
     * never been set.
     *
     * @hide
     */
    public int getNightDisplayAutoModeRaw() {
        return mManager.getNightDisplayAutoModeRaw();
    }

    /**
     * Sets the current auto mode value controlling when Night display will be automatically
     * activated. One of {@link #AUTO_MODE_DISABLED}, {@link #AUTO_MODE_CUSTOM_TIME}, or
     * {@link #AUTO_MODE_TWILIGHT}.
     *
     * @param autoMode the new auto mode to use
     * @return {@code true} if new auto mode was set successfully
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
    public boolean setNightDisplayAutoMode(@AutoMode int autoMode) {
        if (autoMode != AUTO_MODE_DISABLED
                && autoMode != AUTO_MODE_CUSTOM_TIME
                && autoMode != AUTO_MODE_TWILIGHT) {
            throw new IllegalArgumentException("Invalid autoMode: " + autoMode);
        }
        if (mManager.getNightDisplayAutoMode() != autoMode) {
            getMetricsLogger().write(new LogMaker(
                    MetricsEvent.ACTION_NIGHT_DISPLAY_AUTO_MODE_CHANGED)
                    .setType(MetricsEvent.TYPE_ACTION)
                    .setSubtype(autoMode));
        }
        return mManager.setNightDisplayAutoMode(autoMode);
    }

    /**
     * Returns the local time when Night display will be automatically activated when using
     * {@link ColorDisplayManager#AUTO_MODE_CUSTOM_TIME}.
     *
     * @hide
     */
    public @NonNull LocalTime getNightDisplayCustomStartTime() {
        return mManager.getNightDisplayCustomStartTime().getLocalTime();
    }

    /**
     * Sets the local time when Night display will be automatically activated when using
     * {@link ColorDisplayManager#AUTO_MODE_CUSTOM_TIME}.
     *
     * @param startTime the local time to automatically activate Night display
     * @return {@code true} if the new custom start time was set successfully
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
    public boolean setNightDisplayCustomStartTime(@NonNull LocalTime startTime) {
        if (startTime == null) {
            throw new IllegalArgumentException("startTime cannot be null");
        }
        getMetricsLogger().write(new LogMaker(
                MetricsEvent.ACTION_NIGHT_DISPLAY_AUTO_MODE_CUSTOM_TIME_CHANGED)
                .setType(MetricsEvent.TYPE_ACTION)
                .setSubtype(0));
        return mManager.setNightDisplayCustomStartTime(new Time(startTime));
    }

    /**
     * Returns the local time when Night display will be automatically deactivated when using
     * {@link #AUTO_MODE_CUSTOM_TIME}.
     *
     * @hide
     */
    public @NonNull LocalTime getNightDisplayCustomEndTime() {
        return mManager.getNightDisplayCustomEndTime().getLocalTime();
    }

    /**
     * Sets the local time when Night display will be automatically deactivated when using
     * {@link #AUTO_MODE_CUSTOM_TIME}.
     *
     * @param endTime the local time to automatically deactivate Night display
     * @return {@code true} if the new custom end time was set successfully
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
    public boolean setNightDisplayCustomEndTime(@NonNull LocalTime endTime) {
        if (endTime == null) {
            throw new IllegalArgumentException("endTime cannot be null");
        }
        getMetricsLogger().write(new LogMaker(
                MetricsEvent.ACTION_NIGHT_DISPLAY_AUTO_MODE_CUSTOM_TIME_CHANGED)
                .setType(MetricsEvent.TYPE_ACTION)
                .setSubtype(1));
        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.
     *
     * @hide
     */
    @RequiresPermission(Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
    public boolean isDeviceColorManaged() {
        return mManager.isDeviceColorManaged();
    }

    /**
     * Set the level of color saturation to apply to the display.
     *
     * @param saturationLevel 0-100 (inclusive), where 100 is full saturation
     * @return whether the saturation level change was applied successfully
     * @hide
     */
    @SystemApi
    @RequiresPermission(Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
    public boolean setSaturationLevel(@IntRange(from = 0, to = 100) int saturationLevel) {
        return mManager.setSaturationLevel(saturationLevel);
    }

    /**
     * Gets whether or not a non-default saturation level is currently applied to the display.
     *
     * @return {@code true} if the display is not at full saturation
     * @hide
     */
    @RequiresPermission(Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
    public boolean isSaturationActivated() {
        return mManager.isSaturationActivated();
    }

    /**
     * Set the level of color saturation to apply to a specific app.
     *
     * @param packageName the package name of the app whose windows should be desaturated
     * @param saturationLevel 0-100 (inclusive), where 100 is full saturation
     * @return whether the saturation level change was applied successfully
     * @hide
     */
    @SystemApi
    @RequiresPermission(Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
    public boolean setAppSaturationLevel(@NonNull String packageName,
            @IntRange(from = 0, to = 100) int saturationLevel) {
        return mManager.setAppSaturationLevel(packageName, saturationLevel);
    }

    /**
     * Enables or disables display white balance.
     *
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
    public boolean setDisplayWhiteBalanceEnabled(boolean enabled) {
        return mManager.setDisplayWhiteBalanceEnabled(enabled);
    }

    /**
     * Returns whether display white balance is currently enabled. Even if enabled, it may or may
     * not be active, if another transform with higher priority is active.
     *
     * @hide
     */
    public boolean isDisplayWhiteBalanceEnabled() {
        return mManager.isDisplayWhiteBalanceEnabled();
    }

    /**
     * Returns {@code true} if Night Display is supported by the device.
     *
     * @hide
     */
    public static boolean isNightDisplayAvailable(Context context) {
        return context.getResources().getBoolean(R.bool.config_nightDisplayAvailable);
    }

    /**
     * Returns the minimum allowed color temperature (in Kelvin) to tint the display when
     * activated.
     *
     * @hide
     */
    public static int getMinimumColorTemperature(Context context) {
        return context.getResources()
                .getInteger(R.integer.config_nightDisplayColorTemperatureMin);
    }

    /**
     * Returns the maximum allowed color temperature (in Kelvin) to tint the display when
     * activated.
     *
     * @hide
     */
    public static int getMaximumColorTemperature(Context context) {
        return context.getResources()
                .getInteger(R.integer.config_nightDisplayColorTemperatureMax);
    }

    /**
     * Returns {@code true} if display white balance is supported by the device.
     *
     * @hide
     */
    public static boolean isDisplayWhiteBalanceAvailable(Context context) {
        return context.getResources().getBoolean(R.bool.config_displayWhiteBalanceAvailable);
    }

    /**
     * Check if the color transforms are color accelerated. Some transforms are experimental only
     * on non-accelerated platforms due to the performance implications.
     *
     * @hide
     */
    public static boolean isColorTransformAccelerated(Context context) {
        return context.getResources().getBoolean(R.bool.config_setColorTransformAccelerated);
    }

    /**
     * Returns the available software and hardware color transform capabilities of this device.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
    public @CapabilityType int getTransformCapabilities() {
        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();
        }
        return mMetricsLogger;
    }

    private static class ColorDisplayManagerInternal {

        private static ColorDisplayManagerInternal sInstance;

        private final IColorDisplayManager mCdm;

        private ColorDisplayManagerInternal(IColorDisplayManager colorDisplayManager) {
            mCdm = colorDisplayManager;
        }

        public static ColorDisplayManagerInternal getInstance() {
            synchronized (ColorDisplayManagerInternal.class) {
                if (sInstance == null) {
                    try {
                        IBinder b = ServiceManager.getServiceOrThrow(Context.COLOR_DISPLAY_SERVICE);
                        sInstance = new ColorDisplayManagerInternal(
                                IColorDisplayManager.Stub.asInterface(b));
                    } catch (ServiceNotFoundException e) {
                        throw new IllegalStateException(e);
                    }
                }
                return sInstance;
            }
        }

        boolean isNightDisplayActivated() {
            try {
                return mCdm.isNightDisplayActivated();
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }

        boolean setNightDisplayActivated(boolean activated) {
            try {
                return mCdm.setNightDisplayActivated(activated);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }

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

        boolean setNightDisplayColorTemperature(int temperature) {
            try {
                return mCdm.setNightDisplayColorTemperature(temperature);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }

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

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

        boolean setNightDisplayAutoMode(int autoMode) {
            try {
                return mCdm.setNightDisplayAutoMode(autoMode);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }

        Time getNightDisplayCustomStartTime() {
            try {
                return mCdm.getNightDisplayCustomStartTime();
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }

        boolean setNightDisplayCustomStartTime(Time startTime) {
            try {
                return mCdm.setNightDisplayCustomStartTime(startTime);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }

        Time getNightDisplayCustomEndTime() {
            try {
                return mCdm.getNightDisplayCustomEndTime();
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }

        boolean setNightDisplayCustomEndTime(Time endTime) {
            try {
                return mCdm.setNightDisplayCustomEndTime(endTime);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }

        boolean isDeviceColorManaged() {
            try {
                return mCdm.isDeviceColorManaged();
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }

        boolean setSaturationLevel(int saturationLevel) {
            try {
                return mCdm.setSaturationLevel(saturationLevel);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }

        boolean isSaturationActivated() {
            try {
                return mCdm.isSaturationActivated();
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }

        boolean setAppSaturationLevel(String packageName, int saturationLevel) {
            try {
                return mCdm.setAppSaturationLevel(packageName, saturationLevel);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }

        boolean isDisplayWhiteBalanceEnabled() {
            try {
                return mCdm.isDisplayWhiteBalanceEnabled();
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }

        boolean setDisplayWhiteBalanceEnabled(boolean enabled) {
            try {
                return mCdm.setDisplayWhiteBalanceEnabled(enabled);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }

        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();
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    }
}
