Home | History | Annotate | Download | only in notification
      1 /**
      2  * Copyright (c) 2014, The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.server.notification;
     18 
     19 import android.service.notification.ZenModeConfig.ScheduleInfo;
     20 import android.util.ArraySet;
     21 
     22 import java.util.Calendar;
     23 import java.util.Objects;
     24 import java.util.TimeZone;
     25 
     26 public class ScheduleCalendar {
     27     private final ArraySet<Integer> mDays = new ArraySet<Integer>();
     28     private final Calendar mCalendar = Calendar.getInstance();
     29 
     30     private ScheduleInfo mSchedule;
     31 
     32     @Override
     33     public String toString() {
     34         return "ScheduleCalendar[mDays=" + mDays + ", mSchedule=" + mSchedule + "]";
     35     }
     36 
     37     public void setSchedule(ScheduleInfo schedule) {
     38         if (Objects.equals(mSchedule, schedule)) return;
     39         mSchedule = schedule;
     40         updateDays();
     41     }
     42 
     43     public void maybeSetNextAlarm(long now, long nextAlarm) {
     44         if (mSchedule != null) {
     45             if (mSchedule.exitAtAlarm
     46                     && (now > mSchedule.nextAlarm || nextAlarm < mSchedule.nextAlarm)) {
     47                 mSchedule.nextAlarm = nextAlarm;
     48             }
     49         }
     50     }
     51 
     52     public void setTimeZone(TimeZone tz) {
     53         mCalendar.setTimeZone(tz);
     54     }
     55 
     56     public long getNextChangeTime(long now) {
     57         if (mSchedule == null) return 0;
     58         final long nextStart = getNextTime(now, mSchedule.startHour, mSchedule.startMinute);
     59         final long nextEnd = getNextTime(now, mSchedule.endHour, mSchedule.endMinute);
     60         long nextScheduleTime = Math.min(nextStart, nextEnd);
     61 
     62         return nextScheduleTime;
     63     }
     64 
     65     private long getNextTime(long now, int hr, int min) {
     66         final long time = getTime(now, hr, min);
     67         return time <= now ? addDays(time, 1) : time;
     68     }
     69 
     70     private long getTime(long millis, int hour, int min) {
     71         mCalendar.setTimeInMillis(millis);
     72         mCalendar.set(Calendar.HOUR_OF_DAY, hour);
     73         mCalendar.set(Calendar.MINUTE, min);
     74         mCalendar.set(Calendar.SECOND, 0);
     75         mCalendar.set(Calendar.MILLISECOND, 0);
     76         return mCalendar.getTimeInMillis();
     77     }
     78 
     79     public boolean isInSchedule(long time) {
     80         if (mSchedule == null || mDays.size() == 0) return false;
     81         final long start = getTime(time, mSchedule.startHour, mSchedule.startMinute);
     82         long end = getTime(time, mSchedule.endHour, mSchedule.endMinute);
     83         if (end <= start) {
     84             end = addDays(end, 1);
     85         }
     86         return isInSchedule(-1, time, start, end) || isInSchedule(0, time, start, end);
     87     }
     88 
     89     public boolean shouldExitForAlarm(long time) {
     90         return mSchedule.exitAtAlarm
     91                 && mSchedule.nextAlarm != 0
     92                 && time >= mSchedule.nextAlarm;
     93     }
     94 
     95     private boolean isInSchedule(int daysOffset, long time, long start, long end) {
     96         final int n = Calendar.SATURDAY;
     97         final int day = ((getDayOfWeek(time) - 1) + (daysOffset % n) + n) % n + 1;
     98         start = addDays(start, daysOffset);
     99         end = addDays(end, daysOffset);
    100         return mDays.contains(day) && time >= start && time < end;
    101     }
    102 
    103     private int getDayOfWeek(long time) {
    104         mCalendar.setTimeInMillis(time);
    105         return mCalendar.get(Calendar.DAY_OF_WEEK);
    106     }
    107 
    108     private void updateDays() {
    109         mDays.clear();
    110         if (mSchedule != null && mSchedule.days != null) {
    111             for (int i = 0; i < mSchedule.days.length; i++) {
    112                 mDays.add(mSchedule.days[i]);
    113             }
    114         }
    115     }
    116 
    117     private long addDays(long time, int days) {
    118         mCalendar.setTimeInMillis(time);
    119         mCalendar.add(Calendar.DATE, days);
    120         return mCalendar.getTimeInMillis();
    121     }
    122 }
    123