• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 ** Copyright 2006, 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 ** See the License for the specific language governing permissions and
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** limitations under the License.
15 */
16 
17 package com.android.providers.calendar;
18 
19 import android.app.AlarmManager;
20 import android.app.PendingIntent;
21 import android.content.BroadcastReceiver;
22 import android.content.ContentResolver;
23 import android.content.Context;
24 import android.content.Intent;
25 import android.os.PowerManager;
26 import android.os.SystemProperties;
27 import android.util.Log;
28 
29 import java.util.concurrent.TimeUnit;
30 
31 /**
32  * This IntentReceiver executes when the boot completes and ensures that
33  * the Calendar provider has started and then initializes the alarm
34  * scheduler for the Calendar provider.  This needs to be done after
35  * the boot completes because the alarm manager may not have been started
36  * yet.
37  */
38 public class CalendarReceiver extends BroadcastReceiver {
39     private static final String TAG = CalendarProvider2.TAG;
40 
41     private static final long NEXT_EVENT_CHECK_INTERVAL =
42             SystemProperties.getLong("debug.calendar.check_interval", TimeUnit.HOURS.toMillis(6));
43     private static final int NEXT_EVENT_CHECK_PENDING_CODE = 100;
44 
45     private PowerManager.WakeLock mWakeLock;
46 
47     @Override
onReceive(Context context, Intent intent)48     public void onReceive(Context context, Intent intent) {
49         final String action = intent.getAction();
50 
51         if (!Intent.ACTION_BOOT_COMPLETED.equals(action)) {
52             Log.w(TAG, "Unexpected broadcast: " + action);
53             return;
54         }
55         if (Log.isLoggable(TAG, Log.DEBUG)) {
56             Log.d(TAG, "BOOT_COMPLETED");
57         }
58 
59         if (mWakeLock == null) {
60             PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
61             mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "CalendarReceiver_Provider");
62             mWakeLock.setReferenceCounted(true);
63         }
64         mWakeLock.acquire();
65 
66         final ContentResolver cr = context.getContentResolver();
67         final PendingResult result = goAsync();
68 
69         new Thread(() -> {
70             setCalendarCheckAlarm(context);
71             removeScheduledAlarms(cr);
72             result.finish();
73             mWakeLock.release();
74         }).start();
75     }
76 
77     /*
78      * Remove alarms from the CalendarAlerts table that have been marked
79      * as "scheduled" but not fired yet.  We do this because the
80      * AlarmManagerService loses all information about alarms when the
81      * power turns off but we store the information in a database table
82      * that persists across reboots. See the documentation for
83      * scheduleNextAlarmLocked() for more information.
84      *
85      * We don't expect this to be called more than once.  If it were, we would have to
86      * worry about serializing the use of the service.
87      */
removeScheduledAlarms(ContentResolver resolver)88     private void removeScheduledAlarms(ContentResolver resolver) {
89         resolver.update(CalendarAlarmManager.SCHEDULE_ALARM_REMOVE_URI, null /* values */,
90                 null /* where */, null /* selectionArgs */);
91     }
92 
setCalendarCheckAlarm(Context context)93     private static void setCalendarCheckAlarm(Context context) {
94         final PendingIntent checkIntent = PendingIntent.getBroadcast(context,
95                 NEXT_EVENT_CHECK_PENDING_CODE,
96                 CalendarAlarmManager.getCheckNextAlarmIntentForBroadcast(context),
97                 PendingIntent.FLAG_UPDATE_CURRENT);
98 
99         final AlarmManager am = context.getSystemService(AlarmManager.class);
100 
101         am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
102                 NEXT_EVENT_CHECK_INTERVAL, NEXT_EVENT_CHECK_INTERVAL, checkIntent);
103     }
104 }
105