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

Commit ab4c4606 authored by Steven Ng's avatar Steven Ng Committed by Android (Google) Code Review
Browse files

Merge "[Night] Add a new night theme trigger: bedtime"

parents 9e3690b1 4263ab66
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -919,15 +919,21 @@ package android.app {
    method @RequiresPermission(android.Manifest.permission.READ_PROJECTION_STATE) public void addOnProjectionStateChangedListener(int, @NonNull java.util.concurrent.Executor, @NonNull android.app.UiModeManager.OnProjectionStateChangedListener);
    method @RequiresPermission(android.Manifest.permission.ENTER_CAR_MODE_PRIORITIZED) public void enableCarMode(@IntRange(from=0) int, int);
    method @RequiresPermission(android.Manifest.permission.READ_PROJECTION_STATE) public int getActiveProjectionTypes();
    method @RequiresPermission(android.Manifest.permission.MODIFY_DAY_NIGHT_MODE) public int getNightModeCustomType();
    method @NonNull @RequiresPermission(android.Manifest.permission.READ_PROJECTION_STATE) public java.util.Set<java.lang.String> getProjectingPackages(int);
    method @RequiresPermission(value=android.Manifest.permission.TOGGLE_AUTOMOTIVE_PROJECTION, conditional=true) public boolean releaseProjection(int);
    method @RequiresPermission(android.Manifest.permission.READ_PROJECTION_STATE) public void removeOnProjectionStateChangedListener(@NonNull android.app.UiModeManager.OnProjectionStateChangedListener);
    method @RequiresPermission(value=android.Manifest.permission.TOGGLE_AUTOMOTIVE_PROJECTION, conditional=true) public boolean requestProjection(int);
    method @RequiresPermission(android.Manifest.permission.MODIFY_DAY_NIGHT_MODE) public boolean setNightModeActivatedForCustomMode(int, boolean);
    method @RequiresPermission(android.Manifest.permission.MODIFY_DAY_NIGHT_MODE) public void setNightModeCustomType(int);
    field public static final String ACTION_ENTER_CAR_MODE_PRIORITIZED = "android.app.action.ENTER_CAR_MODE_PRIORITIZED";
    field public static final String ACTION_EXIT_CAR_MODE_PRIORITIZED = "android.app.action.EXIT_CAR_MODE_PRIORITIZED";
    field public static final int DEFAULT_PRIORITY = 0; // 0x0
    field public static final String EXTRA_CALLING_PACKAGE = "android.app.extra.CALLING_PACKAGE";
    field public static final String EXTRA_PRIORITY = "android.app.extra.PRIORITY";
    field public static final int MODE_NIGHT_CUSTOM_TYPE_BEDTIME = 1; // 0x1
    field public static final int MODE_NIGHT_CUSTOM_TYPE_SCHEDULE = 0; // 0x0
    field public static final int MODE_NIGHT_CUSTOM_TYPE_UNKNOWN = -1; // 0xffffffff
    field public static final int PROJECTION_TYPE_ALL = -1; // 0xffffffff
    field public static final int PROJECTION_TYPE_AUTOMOTIVE = 1; // 0x1
    field public static final int PROJECTION_TYPE_NONE = 0; // 0x0
+43 −7
Original line number Diff line number Diff line
@@ -48,19 +48,42 @@ interface IUiModeManager {
    
    /**
     * Sets the night mode.
     * <p>
     * The mode can be one of:
     *   1 - notnight mode
     *   2 - night mode
     *   3 - automatic mode switching
     * <ol>notnight mode</ol>
     * <ol>night mode</ol>
     * <ol>custom schedule mode switching</ol>
     */
    void setNightMode(int mode);

    /**
     * Gets the currently configured night mode.  Return 1 for notnight,
     * 2 for night, and 3 for automatic mode switching.
     * Gets the currently configured night mode.
     * <p>
     * Returns
     * <ol>notnight mode</ol>
     * <ol>night mode</ol>
     * <ol>custom schedule mode switching</ol>
     */
    int getNightMode();

    /**
     * Sets the current night mode to {@link #MODE_NIGHT_CUSTOM} with the custom night mode type
     * {@code nightModeCustomType}.
     *
     * @param nightModeCustomType
     * @hide
     */
    void setNightModeCustomType(int nightModeCustomType);

    /**
     * Returns the custom night mode type.
     * <p>
     * If the current night mode is not {@link #MODE_NIGHT_CUSTOM}, returns
     * {@link #MODE_NIGHT_CUSTOM_TYPE_UNKNOWN}.
     * @hide
     */
    int getNightModeCustomType();

    /**
     * Sets the dark mode for the given application. This setting is persisted and will override the
     * system configuration for this application.
@@ -81,7 +104,20 @@ interface IUiModeManager {
    boolean isNightModeLocked();

    /**
    * [De]Activates night mode
     * [De]activating night mode for the current user if the current night mode is custom and the
     * custom type matches {@code nightModeCustomType}.
     *
     * @param nightModeCustomType the specify type of custom mode
     * @param active {@code true} to activate night mode. Otherwise, deactivate night mode
     * @return {@code true} if night mode has successfully activated for the requested
     *         {@code nightModeCustomType}.
     * @hide
     */
    boolean setNightModeActivatedForCustomMode(int nightModeCustom, boolean active);

    /**
     * [De]Activates night mode.
     * @hide
     */
    boolean setNightModeActivated(boolean active);

+103 −0
Original line number Diff line number Diff line
@@ -243,6 +243,45 @@ public class UiModeManager {
     */
    public static final int MODE_NIGHT_YES = 2;

    /**
     * Granular types for {@link MODE_NIGHT_CUSTOM_TYPE_BEDTIME}
     * @hide
     */
    @IntDef(prefix = { "MODE_NIGHT_CUSTOM_TYPE_" }, value = {
            MODE_NIGHT_CUSTOM_TYPE_UNKNOWN,
            MODE_NIGHT_CUSTOM_TYPE_SCHEDULE,
            MODE_NIGHT_CUSTOM_TYPE_BEDTIME,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface NightModeCustomType {}

    /**
     * A granular type for {@link #MODE_NIGHT_CUSTOM} which is unknown.
     * <p>
     * This is the default value when the night mode is set to value other than
     * {@link #MODE_NIGHT_CUSTOM}.
     * @hide
     */
    @SystemApi
    public static final int MODE_NIGHT_CUSTOM_TYPE_UNKNOWN = -1;

    /**
     * A granular type for {@link #MODE_NIGHT_CUSTOM} which is based on a custom schedule.
     * <p>
     * This is the default value when night mode is set to {@link #MODE_NIGHT_CUSTOM} unless the
     * the night mode custom type is specified by calling {@link #setNightModeCustomType(int)}.
     * @hide
     */
    @SystemApi
    public static final int MODE_NIGHT_CUSTOM_TYPE_SCHEDULE = 0;

    /**
     * A granular type for {@link #MODE_NIGHT_CUSTOM} which is based on the bedtime schedule.
     * @hide
     */
    @SystemApi
    public static final int MODE_NIGHT_CUSTOM_TYPE_BEDTIME = 1;

    private IUiModeManager mService;

    /**
@@ -495,6 +534,45 @@ public class UiModeManager {
        }
    }

    /**
     * Sets the current night mode to {@link #MODE_NIGHT_CUSTOM} with the custom night mode type
     * {@code nightModeCustomType}.
     *
     * @param nightModeCustomType
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.MODIFY_DAY_NIGHT_MODE)
    public void setNightModeCustomType(@NightModeCustomType int nightModeCustomType) {
        if (mService != null) {
            try {
                mService.setNightModeCustomType(nightModeCustomType);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    }

    /**
     * Returns the custom night mode type.
     * <p>
     * If the current night mode is not {@link #MODE_NIGHT_CUSTOM}, returns
     * {@link #MODE_NIGHT_CUSTOM_TYPE_UNKNOWN}.
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.MODIFY_DAY_NIGHT_MODE)
    public int getNightModeCustomType() {
        if (mService != null) {
            try {
                return mService.getNightModeCustomType();
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
        return MODE_NIGHT_CUSTOM_TYPE_UNKNOWN;
    }

    /**
     * Sets and persist the night mode for this application.
     * <p>
@@ -598,12 +676,37 @@ public class UiModeManager {
        return true;
    }

    /**
     * [De]activating night mode for the current user if the current night mode is custom and the
     * custom type matches {@code nightModeCustomType}.
     *
     * @param nightModeCustomType the specify type of custom mode
     * @param active {@code true} to activate night mode. Otherwise, deactivate night mode
     * @return {@code true} if night mode has successfully activated for the requested
     *         {@code nightModeCustomType}.
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.MODIFY_DAY_NIGHT_MODE)
    public boolean setNightModeActivatedForCustomMode(@NightModeCustomType int nightModeCustomType,
            boolean active) {
        if (mService != null) {
            try {
                return mService.setNightModeActivatedForCustomMode(nightModeCustomType, active);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
        return false;
    }

    /**
     * Activating night mode for the current user
     *
     * @return {@code true} if the change is successful
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.MODIFY_DAY_NIGHT_MODE)
    public boolean setNightModeActivated(boolean active) {
        if (mService != null) {
            try {
+9 −0
Original line number Diff line number Diff line
@@ -8983,6 +8983,15 @@ public final class Settings {
        @Readable
        public static final String UI_NIGHT_MODE = "ui_night_mode";
        /**
         * The current night mode custom type that has been selected by the user.  Owned
         * and controlled by UiModeManagerService. Constants are as per UiModeManager.
         * @hide
         */
        @Readable
        @SuppressLint("NoSettingsProvider")
        public static final String UI_NIGHT_MODE_CUSTOM_TYPE = "ui_night_mode_custom_type";
        /**
         * The current night mode that has been overridden to turn on by the system.  Owned
         * and controlled by UiModeManagerService.  Constants are as per
+77 −10
Original line number Diff line number Diff line
@@ -19,6 +19,9 @@ package com.android.server;
import static android.app.UiModeManager.DEFAULT_PRIORITY;
import static android.app.UiModeManager.MODE_NIGHT_AUTO;
import static android.app.UiModeManager.MODE_NIGHT_CUSTOM;
import static android.app.UiModeManager.MODE_NIGHT_CUSTOM_TYPE_BEDTIME;
import static android.app.UiModeManager.MODE_NIGHT_CUSTOM_TYPE_SCHEDULE;
import static android.app.UiModeManager.MODE_NIGHT_CUSTOM_TYPE_UNKNOWN;
import static android.app.UiModeManager.MODE_NIGHT_NO;
import static android.app.UiModeManager.MODE_NIGHT_YES;
import static android.app.UiModeManager.PROJECTION_TYPE_AUTOMOTIVE;
@@ -40,6 +43,7 @@ import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.StatusBarManager;
import android.app.UiModeManager;
import android.app.UiModeManager.NightModeCustomType;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -115,6 +119,7 @@ final class UiModeManagerService extends SystemService {

    private int mLastBroadcastState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
    private int mNightMode = UiModeManager.MODE_NIGHT_NO;
    private int mNightModeCustomType = UiModeManager.MODE_NIGHT_CUSTOM_TYPE_UNKNOWN;
    private final LocalTime DEFAULT_CUSTOM_NIGHT_START_TIME = LocalTime.of(22, 0);
    private final LocalTime DEFAULT_CUSTOM_NIGHT_END_TIME = LocalTime.of(6, 0);
    private LocalTime mCustomAutoNightModeStartMilliseconds = DEFAULT_CUSTOM_NIGHT_START_TIME;
@@ -136,6 +141,7 @@ final class UiModeManagerService extends SystemService {
    private boolean mWatch;
    private boolean mVrHeadset;
    private boolean mComputedNightMode;
    private boolean mLastBedtimeRequestedNightMode = false;
    private int mCarModeEnableFlags;
    private boolean mSetupWizardComplete;

@@ -541,6 +547,8 @@ final class UiModeManagerService extends SystemService {
            mNightMode = Secure.getIntForUser(context.getContentResolver(),
                    Secure.UI_NIGHT_MODE, res.getInteger(
                            com.android.internal.R.integer.config_defaultNightMode), userId);
            mNightModeCustomType = Secure.getIntForUser(context.getContentResolver(),
                    Secure.UI_NIGHT_MODE_CUSTOM_TYPE, MODE_NIGHT_CUSTOM_TYPE_UNKNOWN, userId);
                    mOverrideNightModeOn = Secure.getIntForUser(context.getContentResolver(),
                    Secure.UI_NIGHT_MODE_OVERRIDE_ON, 0, userId) != 0;
            mOverrideNightModeOff = Secure.getIntForUser(context.getContentResolver(),
@@ -702,6 +710,14 @@ final class UiModeManagerService extends SystemService {

        @Override
        public void setNightMode(int mode) {
            // MODE_NIGHT_CUSTOM_TYPE_SCHEDULE is the default for MODE_NIGHT_CUSTOM.
            int customModeType = mode == MODE_NIGHT_CUSTOM
                    ? MODE_NIGHT_CUSTOM_TYPE_SCHEDULE
                    : MODE_NIGHT_CUSTOM_TYPE_UNKNOWN;
            setNightModeInternal(mode, customModeType);
        }

        private void setNightModeInternal(int mode, int customModeType) {
            if (isNightModeLocked() && (getContext().checkCallingOrSelfPermission(
                    android.Manifest.permission.MODIFY_DAY_NIGHT_MODE)
                    != PackageManager.PERMISSION_GRANTED)) {
@@ -722,12 +738,14 @@ final class UiModeManagerService extends SystemService {
            final long ident = Binder.clearCallingIdentity();
            try {
                synchronized (mLock) {
                    if (mNightMode != mode) {
                    if (mNightMode != mode || mNightModeCustomType != customModeType) {
                        if (mNightMode == MODE_NIGHT_AUTO || mNightMode == MODE_NIGHT_CUSTOM) {
                            unregisterScreenOffEventLocked();
                            cancelCustomAlarm();
                        }

                        mNightModeCustomType = mode == MODE_NIGHT_CUSTOM
                                ? customModeType
                                : MODE_NIGHT_CUSTOM_TYPE_UNKNOWN;
                        mNightMode = mode;
                        resetNightModeOverrideLocked();
                        persistNightMode(user);
@@ -753,6 +771,30 @@ final class UiModeManagerService extends SystemService {
            }
        }

        @Override
        public void setNightModeCustomType(@NightModeCustomType int nightModeCustomType) {
            if (getContext().checkCallingOrSelfPermission(
                    android.Manifest.permission.MODIFY_DAY_NIGHT_MODE)
                    != PackageManager.PERMISSION_GRANTED) {
                throw new SecurityException(
                        "setNightModeCustomType requires MODIFY_DAY_NIGHT_MODE permission");
            }
            setNightModeInternal(MODE_NIGHT_CUSTOM, nightModeCustomType);
        }

        @Override
        public int getNightModeCustomType() {
            if (getContext().checkCallingOrSelfPermission(
                    android.Manifest.permission.MODIFY_DAY_NIGHT_MODE)
                    != PackageManager.PERMISSION_GRANTED) {
                throw new SecurityException(
                        "getNightModeCustomType requires MODIFY_DAY_NIGHT_MODE permission");
            }
            synchronized (mLock) {
                return mNightModeCustomType;
            }
        }

        @Override
        public void setApplicationNightMode(@UiModeManager.NightMode int mode) {
            switch (mode) {
@@ -807,11 +849,20 @@ final class UiModeManagerService extends SystemService {
            dumpImpl(pw);
        }

        @Override
        public boolean setNightModeActivatedForCustomMode(int modeNightCustomType, boolean active) {
            return setNightModeActivatedForModeInternal(modeNightCustomType, active);
        }

        @Override
        public boolean setNightModeActivated(boolean active) {
            if (isNightModeLocked() && (getContext().checkCallingOrSelfPermission(
            return setNightModeActivatedForModeInternal(mNightModeCustomType, active);
        }

        private boolean setNightModeActivatedForModeInternal(int modeCustomType, boolean active) {
            if (getContext().checkCallingOrSelfPermission(
                    android.Manifest.permission.MODIFY_DAY_NIGHT_MODE)
                    != PackageManager.PERMISSION_GRANTED)) {
                    != PackageManager.PERMISSION_GRANTED) {
                Slog.e(TAG, "Night mode locked, requires MODIFY_DAY_NIGHT_MODE permission");
                return false;
            }
@@ -824,6 +875,14 @@ final class UiModeManagerService extends SystemService {
                return false;

            }
            // Store the last requested bedtime night mode state so that we don't need to notify
            // anyone if the user decides to switch to the night mode to bedtime.
            if (modeCustomType == MODE_NIGHT_CUSTOM_TYPE_BEDTIME) {
                mLastBedtimeRequestedNightMode = active;
            }
            if (modeCustomType != mNightModeCustomType) {
                return false;
            }
            synchronized (mLock) {
                final long ident = Binder.clearCallingIdentity();
                try {
@@ -1421,6 +1480,8 @@ final class UiModeManagerService extends SystemService {
        if (mCarModeEnabled || mCar) return;
        Secure.putIntForUser(getContext().getContentResolver(),
                Secure.UI_NIGHT_MODE, mNightMode, user);
        Secure.putLongForUser(getContext().getContentResolver(),
                Secure.UI_NIGHT_MODE_CUSTOM_TYPE, mNightModeCustomType, user);
        Secure.putLongForUser(getContext().getContentResolver(),
                Secure.DARK_THEME_CUSTOM_START_TIME,
                mCustomAutoNightModeStartMilliseconds.toNanoOfDay() / 1000, user);
@@ -1473,10 +1534,14 @@ final class UiModeManagerService extends SystemService {
        }

        if (mNightMode == MODE_NIGHT_CUSTOM) {
            if (mNightModeCustomType == MODE_NIGHT_CUSTOM_TYPE_BEDTIME) {
                updateComputedNightModeLocked(mLastBedtimeRequestedNightMode);
            } else {
                registerTimeChangeEvent();
                final boolean activate = computeCustomNightMode();
                updateComputedNightModeLocked(activate);
                scheduleNextCustomTimeListener();
            }
        } else {
            unregisterTimeChangeEvent();
        }
@@ -1494,6 +1559,7 @@ final class UiModeManagerService extends SystemService {
                    "updateConfigurationLocked: mDockState=" + mDockState
                    + "; mCarMode=" + mCarModeEnabled
                    + "; mNightMode=" + mNightMode
                    + "; mNightModeCustomType=" + mNightModeCustomType
                    + "; uiMode=" + uiMode);
        }

@@ -1534,7 +1600,8 @@ final class UiModeManagerService extends SystemService {
    }

    private boolean shouldApplyAutomaticChangesImmediately() {
        return mCar || !mPowerManager.isInteractive();
        return mCar || !mPowerManager.isInteractive()
                || mNightModeCustomType == MODE_NIGHT_CUSTOM_TYPE_BEDTIME;
    }

    private void scheduleNextCustomTimeListener() {
Loading