1 /*
2  * Copyright (C) 2017 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 package com.android.wallpaper.module;
17 
18 import static android.app.PendingIntent.FLAG_IMMUTABLE;
19 
20 import android.app.AlarmManager;
21 import android.app.PendingIntent;
22 import android.content.Context;
23 import android.content.Intent;
24 
25 import java.util.Calendar;
26 import java.util.concurrent.TimeUnit;
27 
28 /**
29  * Schedules and cancels alarms on Android's {@link AlarmManager} to occur every 24 hours to perform
30  * daily logging.
31  */
32 public class DailyLoggingAlarmScheduler {
33 
34     private static final int UNUSED_REQUEST_CODE = 0;
35 
36     /**
37      * Sets a new alarm to fire approximately 24 hours after the last one, or immediately if it has
38      * not fired in over 24 hours.
39      */
setAlarm(Context appContext)40     public static void setAlarm(Context appContext) {
41         Injector injector = InjectorProvider.getInjector();
42         AlarmManagerWrapper alarmManagerWrapper = injector.getAlarmManagerWrapper(appContext);
43         WallpaperPreferences preferences = injector.getPreferences(appContext);
44 
45         long lastTimestamp = preferences.getLastDailyLogTimestamp();
46 
47         Calendar oneDayAgo = Calendar.getInstance();
48         long currentTimeMillis = System.currentTimeMillis();
49         oneDayAgo.setTimeInMillis(currentTimeMillis);
50         oneDayAgo.add(Calendar.DAY_OF_YEAR, -1);
51 
52         long triggerAtMillis;
53         if (lastTimestamp == -1 || lastTimestamp < oneDayAgo.getTimeInMillis()) {
54             // Schedule for right now (a minute from now, to ensure the trigger time is in the future) and
55             // then every ~24 hours later.
56             Calendar oneMinuteFromNow = Calendar.getInstance();
57             oneMinuteFromNow.setTimeInMillis(currentTimeMillis);
58             oneMinuteFromNow.add(Calendar.MINUTE, 1);
59             triggerAtMillis = oneMinuteFromNow.getTimeInMillis();
60         } else {
61             // Schedule for 24 hours after the last daily log, and every ~24 hours after that.
62             Calendar oneDayFromNow = Calendar.getInstance();
63             oneDayFromNow.setTimeInMillis(lastTimestamp);
64             oneDayFromNow.add(Calendar.DAY_OF_YEAR, 1);
65             triggerAtMillis = oneDayFromNow.getTimeInMillis();
66         }
67 
68         // Cancel any existing daily logging alarms. Then do the actual scheduling of the new alarm.
69         PendingIntent pendingIntent = createAlarmReceiverPendingIntent(appContext);
70         alarmManagerWrapper.cancel(pendingIntent);
71 
72         pendingIntent = createAlarmReceiverPendingIntent(appContext);
73         alarmManagerWrapper.setInexactRepeating(
74                 AlarmManager.RTC /* type */,
75                 triggerAtMillis /* triggerAtMillis */,
76                 TimeUnit.MILLISECONDS.convert(24, TimeUnit.HOURS) /* intervalMillis */,
77                 pendingIntent /* operation */);
78     }
79 
createAlarmReceiverPendingIntent(Context appContext)80     private static PendingIntent createAlarmReceiverPendingIntent(Context appContext) {
81         Intent intent = new Intent(appContext, DailyLoggingAlarmReceiver.class);
82         return PendingIntent.getBroadcast(
83                 appContext, UNUSED_REQUEST_CODE, intent, FLAG_IMMUTABLE);
84     }
85 
86 }
87