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

Commit 1276f357 authored by Christine Franks's avatar Christine Franks Committed by Android (Google) Code Review
Browse files

Merge "Handle night display state when timezone changes" into oc-mr1-dev

parents 5488a384 2ce862c3
Loading
Loading
Loading
Loading
+0 −1
Original line number Original line Diff line number Diff line
@@ -5243,7 +5243,6 @@ com.android.internal.app.IVoiceInteractor
com.android.internal.app.IVoiceInteractor$Stub
com.android.internal.app.IVoiceInteractor$Stub
com.android.internal.app.NightDisplayController
com.android.internal.app.NightDisplayController
com.android.internal.app.NightDisplayController$Callback
com.android.internal.app.NightDisplayController$Callback
com.android.internal.app.NightDisplayController$LocalTime
com.android.internal.app.ProcessMap
com.android.internal.app.ProcessMap
com.android.internal.app.ResolverActivity
com.android.internal.app.ResolverActivity
com.android.internal.app.ToolbarActionBar
com.android.internal.app.ToolbarActionBar
+0 −1
Original line number Original line Diff line number Diff line
@@ -2784,7 +2784,6 @@ com.android.internal.app.IVoiceInteractionManagerService$Stub
com.android.internal.app.IVoiceInteractor
com.android.internal.app.IVoiceInteractor
com.android.internal.app.IVoiceInteractor$Stub
com.android.internal.app.IVoiceInteractor$Stub
com.android.internal.app.NightDisplayController
com.android.internal.app.NightDisplayController
com.android.internal.app.NightDisplayController$1
com.android.internal.appwidget.IAppWidgetService
com.android.internal.appwidget.IAppWidgetService
com.android.internal.appwidget.IAppWidgetService$Stub
com.android.internal.appwidget.IAppWidgetService$Stub
com.android.internal.appwidget.IAppWidgetService$Stub$Proxy
com.android.internal.appwidget.IAppWidgetService$Stub$Proxy
+3 −2
Original line number Original line Diff line number Diff line
@@ -6931,8 +6931,9 @@ public final class Settings {
        public static final String NIGHT_DISPLAY_CUSTOM_END_TIME = "night_display_custom_end_time";
        public static final String NIGHT_DISPLAY_CUSTOM_END_TIME = "night_display_custom_end_time";


        /**
        /**
         * Time in milliseconds (since epoch) when Night display was last activated. Use to decide
         * A String representing the LocalDateTime when Night display was last activated. Use to
         * whether to apply the current activated state after a reboot or user change.
         * decide whether to apply the current activated state after a reboot or user change. In
         * legacy cases, this is represented by the time in milliseconds (since epoch).
         * @hide
         * @hide
         */
         */
        public static final String NIGHT_DISPLAY_LAST_ACTIVATED_TIME =
        public static final String NIGHT_DISPLAY_LAST_ACTIVATED_TIME =
+31 −119
Original line number Original line Diff line number Diff line
@@ -32,8 +32,12 @@ import com.android.internal.R;


import java.lang.annotation.Retention;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.RetentionPolicy;
import java.util.Calendar;
import java.time.DateTimeException;
import java.util.Locale;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeParseException;


/**
/**
 * Controller for managing Night display settings.
 * Controller for managing Night display settings.
@@ -116,8 +120,9 @@ public final class NightDisplayController {
     */
     */
    public boolean setActivated(boolean activated) {
    public boolean setActivated(boolean activated) {
        if (isActivated() != activated) {
        if (isActivated() != activated) {
            Secure.putLongForUser(mContext.getContentResolver(),
            Secure.putStringForUser(mContext.getContentResolver(),
                    Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, System.currentTimeMillis(),
                    Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME,
                    LocalDateTime.now().toString(),
                    mUserId);
                    mUserId);
        }
        }
        return Secure.putIntForUser(mContext.getContentResolver(),
        return Secure.putIntForUser(mContext.getContentResolver(),
@@ -128,17 +133,22 @@ public final class NightDisplayController {
     * Returns the time when Night display's activation state last changed, or {@code null} if it
     * Returns the time when Night display's activation state last changed, or {@code null} if it
     * has never been changed.
     * has never been changed.
     */
     */
    public Calendar getLastActivatedTime() {
    public LocalDateTime getLastActivatedTime() {
        final ContentResolver cr = mContext.getContentResolver();
        final ContentResolver cr = mContext.getContentResolver();
        final long lastActivatedTimeMillis = Secure.getLongForUser(
        final String lastActivatedTime = Secure.getStringForUser(
                cr, Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, -1, mUserId);
                cr, Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, mUserId);
        if (lastActivatedTimeMillis < 0) {
        if (lastActivatedTime != null) {
            return 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 null;
        final Calendar lastActivatedTime = Calendar.getInstance();
        lastActivatedTime.setTimeInMillis(lastActivatedTimeMillis);
        return lastActivatedTime;
    }
    }


    /**
    /**
@@ -183,8 +193,10 @@ public final class NightDisplayController {
        }
        }


        if (getAutoMode() != autoMode) {
        if (getAutoMode() != autoMode) {
            Secure.putLongForUser(mContext.getContentResolver(),
            Secure.putStringForUser(mContext.getContentResolver(),
                    Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, -1L, mUserId);
                    Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME,
                    null,
                    mUserId);
        }
        }
        return Secure.putIntForUser(mContext.getContentResolver(),
        return Secure.putIntForUser(mContext.getContentResolver(),
                Secure.NIGHT_DISPLAY_AUTO_MODE, autoMode, mUserId);
                Secure.NIGHT_DISPLAY_AUTO_MODE, autoMode, mUserId);
@@ -206,7 +218,7 @@ public final class NightDisplayController {
                    R.integer.config_defaultNightDisplayCustomStartTime);
                    R.integer.config_defaultNightDisplayCustomStartTime);
        }
        }


        return LocalTime.valueOf(startTimeValue);
        return LocalTime.ofSecondOfDay(startTimeValue / 1000);
    }
    }


    /**
    /**
@@ -221,7 +233,7 @@ public final class NightDisplayController {
            throw new IllegalArgumentException("startTime cannot be null");
            throw new IllegalArgumentException("startTime cannot be null");
        }
        }
        return Secure.putIntForUser(mContext.getContentResolver(),
        return Secure.putIntForUser(mContext.getContentResolver(),
                Secure.NIGHT_DISPLAY_CUSTOM_START_TIME, startTime.toMillis(), mUserId);
                Secure.NIGHT_DISPLAY_CUSTOM_START_TIME, startTime.toSecondOfDay() * 1000, mUserId);
    }
    }


    /**
    /**
@@ -240,7 +252,7 @@ public final class NightDisplayController {
                    R.integer.config_defaultNightDisplayCustomEndTime);
                    R.integer.config_defaultNightDisplayCustomEndTime);
        }
        }


        return LocalTime.valueOf(endTimeValue);
        return LocalTime.ofSecondOfDay(endTimeValue / 1000);
    }
    }


    /**
    /**
@@ -255,7 +267,7 @@ public final class NightDisplayController {
            throw new IllegalArgumentException("endTime cannot be null");
            throw new IllegalArgumentException("endTime cannot be null");
        }
        }
        return Secure.putIntForUser(mContext.getContentResolver(),
        return Secure.putIntForUser(mContext.getContentResolver(),
                Secure.NIGHT_DISPLAY_CUSTOM_END_TIME, endTime.toMillis(), mUserId);
                Secure.NIGHT_DISPLAY_CUSTOM_END_TIME, endTime.toSecondOfDay() * 1000, mUserId);
    }
    }


    /**
    /**
@@ -378,106 +390,6 @@ public final class NightDisplayController {
        return context.getResources().getBoolean(R.bool.config_nightDisplayAvailable);
        return context.getResources().getBoolean(R.bool.config_nightDisplayAvailable);
    }
    }


    /**
     * A time without a time-zone or date.
     */
    public static class LocalTime {

        /**
         * The hour of the day from 0 - 23.
         */
        public final int hourOfDay;
        /**
         * The minute within the hour from 0 - 59.
         */
        public final int minute;

        public LocalTime(int hourOfDay, int minute) {
            if (hourOfDay < 0 || hourOfDay > 23) {
                throw new IllegalArgumentException("Invalid hourOfDay: " + hourOfDay);
            } else if (minute < 0 || minute > 59) {
                throw new IllegalArgumentException("Invalid minute: " + minute);
            }

            this.hourOfDay = hourOfDay;
            this.minute = minute;
        }

        /**
         * Returns the first date time corresponding to this local time that occurs before the
         * provided date time.
         *
         * @param time the date time to compare against
         * @return the prior date time corresponding to this local time
         */
        public Calendar getDateTimeBefore(Calendar time) {
            final Calendar c = Calendar.getInstance();
            c.set(Calendar.YEAR, time.get(Calendar.YEAR));
            c.set(Calendar.DAY_OF_YEAR, time.get(Calendar.DAY_OF_YEAR));

            c.set(Calendar.HOUR_OF_DAY, hourOfDay);
            c.set(Calendar.MINUTE, minute);
            c.set(Calendar.SECOND, 0);
            c.set(Calendar.MILLISECOND, 0);

            // Check if the local time has past, if so return the same time tomorrow.
            if (c.after(time)) {
                c.add(Calendar.DATE, -1);
            }

            return c;
        }

        /**
         * Returns the first date time corresponding to this local time that occurs after the
         * provided date time.
         *
         * @param time the date time to compare against
         * @return the next date time corresponding to this local time
         */
        public Calendar getDateTimeAfter(Calendar time) {
            final Calendar c = Calendar.getInstance();
            c.set(Calendar.YEAR, time.get(Calendar.YEAR));
            c.set(Calendar.DAY_OF_YEAR, time.get(Calendar.DAY_OF_YEAR));

            c.set(Calendar.HOUR_OF_DAY, hourOfDay);
            c.set(Calendar.MINUTE, minute);
            c.set(Calendar.SECOND, 0);
            c.set(Calendar.MILLISECOND, 0);

            // Check if the local time has past, if so return the same time tomorrow.
            if (c.before(time)) {
                c.add(Calendar.DATE, 1);
            }

            return c;
        }

        /**
         * Returns a local time corresponding the given number of milliseconds from midnight.
         *
         * @param millis the number of milliseconds from midnight
         * @return the corresponding local time
         */
        private static LocalTime valueOf(int millis) {
            final int hourOfDay = (millis / 3600000) % 24;
            final int minutes = (millis / 60000) % 60;
            return new LocalTime(hourOfDay, minutes);
        }

        /**
         * Returns the local time represented as milliseconds from midnight.
         */
        private int toMillis() {
            return hourOfDay * 3600000 + minute * 60000;
        }

        @Override
        public String toString() {
            return String.format(Locale.US, "%02d:%02d", hourOfDay, minute);
        }
    }

    /**
    /**
     * Callback invoked whenever the Night display settings are changed.
     * Callback invoked whenever the Night display settings are changed.
     */
     */
+59 −42
Original line number Original line Diff line number Diff line
@@ -48,8 +48,10 @@ import com.android.server.twilight.TwilightListener;
import com.android.server.twilight.TwilightManager;
import com.android.server.twilight.TwilightManager;
import com.android.server.twilight.TwilightState;
import com.android.server.twilight.TwilightState;


import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.Calendar;
import java.util.TimeZone;
import java.util.TimeZone;


import com.android.internal.R;
import com.android.internal.R;
@@ -308,7 +310,7 @@ public final class NightDisplayService extends SystemService
    }
    }


    @Override
    @Override
    public void onCustomStartTimeChanged(NightDisplayController.LocalTime startTime) {
    public void onCustomStartTimeChanged(LocalTime startTime) {
        Slog.d(TAG, "onCustomStartTimeChanged: startTime=" + startTime);
        Slog.d(TAG, "onCustomStartTimeChanged: startTime=" + startTime);


        if (mAutoMode != null) {
        if (mAutoMode != null) {
@@ -317,7 +319,7 @@ public final class NightDisplayService extends SystemService
    }
    }


    @Override
    @Override
    public void onCustomEndTimeChanged(NightDisplayController.LocalTime endTime) {
    public void onCustomEndTimeChanged(LocalTime endTime) {
        Slog.d(TAG, "onCustomEndTimeChanged: endTime=" + endTime);
        Slog.d(TAG, "onCustomEndTimeChanged: endTime=" + endTime);


        if (mAutoMode != null) {
        if (mAutoMode != null) {
@@ -416,6 +418,36 @@ public final class NightDisplayService extends SystemService
        outTemp[10] = blue;
        outTemp[10] = blue;
    }
    }


    /**
     * 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
     */
    public 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
     */
    public 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;
    }

    private abstract class AutoMode implements NightDisplayController.Callback {
    private abstract class AutoMode implements NightDisplayController.Callback {
        public abstract void onStart();
        public abstract void onStart();


@@ -427,10 +459,10 @@ public final class NightDisplayService extends SystemService
        private final AlarmManager mAlarmManager;
        private final AlarmManager mAlarmManager;
        private final BroadcastReceiver mTimeChangedReceiver;
        private final BroadcastReceiver mTimeChangedReceiver;


        private NightDisplayController.LocalTime mStartTime;
        private LocalTime mStartTime;
        private NightDisplayController.LocalTime mEndTime;
        private LocalTime mEndTime;


        private Calendar mLastActivatedTime;
        private LocalDateTime mLastActivatedTime;


        CustomAutoMode() {
        CustomAutoMode() {
            mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
            mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
@@ -443,31 +475,15 @@ public final class NightDisplayService extends SystemService
        }
        }


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


            boolean activate = now.before(endTime);
            if (mLastActivatedTime != null) {
            if (mLastActivatedTime != null) {
                // Convert mLastActivatedTime to the current timezone if needed.
                final TimeZone currentTimeZone = now.getTimeZone();
                if (!currentTimeZone.equals(mLastActivatedTime.getTimeZone())) {
                    final int year = mLastActivatedTime.get(Calendar.YEAR);
                    final int dayOfYear = mLastActivatedTime.get(Calendar.DAY_OF_YEAR);
                    final int hourOfDay = mLastActivatedTime.get(Calendar.HOUR_OF_DAY);
                    final int minute = mLastActivatedTime.get(Calendar.MINUTE);

                    mLastActivatedTime.setTimeZone(currentTimeZone);
                    mLastActivatedTime.set(Calendar.YEAR, year);
                    mLastActivatedTime.set(Calendar.DAY_OF_YEAR, dayOfYear);
                    mLastActivatedTime.set(Calendar.HOUR_OF_DAY, hourOfDay);
                    mLastActivatedTime.set(Calendar.MINUTE, minute);
                }

                // Maintain the existing activated state if within the current period.
                // Maintain the existing activated state if within the current period.
                if (mLastActivatedTime.before(now)
                if (mLastActivatedTime.isBefore(now) && mLastActivatedTime.isAfter(start)
                        && mLastActivatedTime.after(startTime)
                        && (mLastActivatedTime.isAfter(end) || now.isBefore(end))) {
                        && (mLastActivatedTime.after(endTime) || now.before(endTime))) {
                    activate = mController.isActivated();
                    activate = mController.isActivated();
                }
                }
            }
            }
@@ -475,14 +491,16 @@ public final class NightDisplayService extends SystemService
            if (mIsActivated == null || mIsActivated != activate) {
            if (mIsActivated == null || mIsActivated != activate) {
                mController.setActivated(activate);
                mController.setActivated(activate);
            }
            }

            updateNextAlarm(mIsActivated, now);
            updateNextAlarm(mIsActivated, now);
        }
        }


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


@@ -512,18 +530,18 @@ public final class NightDisplayService extends SystemService
        @Override
        @Override
        public void onActivated(boolean activated) {
        public void onActivated(boolean activated) {
            mLastActivatedTime = mController.getLastActivatedTime();
            mLastActivatedTime = mController.getLastActivatedTime();
            updateNextAlarm(activated, Calendar.getInstance());
            updateNextAlarm(activated, LocalDateTime.now());
        }
        }


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


        @Override
        @Override
        public void onCustomEndTimeChanged(NightDisplayController.LocalTime endTime) {
        public void onCustomEndTimeChanged(LocalTime endTime) {
            mEndTime = endTime;
            mEndTime = endTime;
            mLastActivatedTime = null;
            mLastActivatedTime = null;
            updateActivated();
            updateActivated();
@@ -552,15 +570,14 @@ public final class NightDisplayService extends SystemService
            }
            }


            boolean activate = state.isNight();
            boolean activate = state.isNight();
            final Calendar lastActivatedTime = mController.getLastActivatedTime();
            final LocalDateTime lastActivatedTime = mController.getLastActivatedTime();
            if (lastActivatedTime != null) {
            if (lastActivatedTime != null) {
                final Calendar now = Calendar.getInstance();
                final LocalDateTime now = LocalDateTime.now();
                final Calendar sunrise = state.sunrise();
                final LocalDateTime sunrise = state.sunrise();
                final Calendar sunset = state.sunset();
                final LocalDateTime sunset = state.sunset();

                // Maintain the existing activated state if within the current period.
                // Maintain the existing activated state if within the current period.
                if (lastActivatedTime.before(now)
                if (lastActivatedTime.isBefore(now) && (lastActivatedTime.isBefore(sunrise)
                        && (lastActivatedTime.after(sunrise) ^ lastActivatedTime.after(sunset))) {
                        ^ lastActivatedTime.isBefore(sunset))) {
                    activate = mController.isActivated();
                    activate = mController.isActivated();
                }
                }
            }
            }
Loading