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 17package com.android.providers.calendar; 18 19import android.app.Service; 20import android.content.BroadcastReceiver; 21import android.content.ContentResolver; 22import android.content.Context; 23import android.content.Intent; 24import android.os.IBinder; 25import android.util.Log; 26 27/** 28 * This IntentReceiver executes when the boot completes and ensures that 29 * the Calendar provider has started and then initializes the alarm 30 * scheduler for the Calendar provider. This needs to be done after 31 * the boot completes because the alarm manager may not have been started 32 * yet. 33 */ 34public class CalendarReceiver extends BroadcastReceiver { 35 private static final String TAG = "CalendarReceiver"; 36 37 static final String SCHEDULE = "com.android.providers.calendar.SCHEDULE_ALARM"; 38 39 @Override 40 public void onReceive(Context context, Intent intent) { 41 String action = intent.getAction(); 42 ContentResolver cr = context.getContentResolver(); 43 if (action.equals(SCHEDULE)) { 44 cr.update(CalendarAlarmManager.SCHEDULE_ALARM_URI, null /* values */, null /* where */, 45 null /* selectionArgs */); 46 } else if (action.equals(Intent.ACTION_BOOT_COMPLETED)) { 47 removeScheduledAlarms(context, cr); 48 } 49 } 50 51 /* 52 * Remove alarms from the CalendarAlerts table that have been marked 53 * as "scheduled" but not fired yet. We do this because the 54 * AlarmManagerService loses all information about alarms when the 55 * power turns off but we store the information in a database table 56 * that persists across reboots. See the documentation for 57 * scheduleNextAlarmLocked() for more information. 58 * 59 * Running this on the main thread has caused ANRs, so we run it on a background 60 * thread and start an "empty service" to encourage the system to keep us alive. 61 * 62 * We don't expect this to be called more than once. If it were, we would have to 63 * worry about serializing the use of the service. 64 */ 65 private void removeScheduledAlarms(Context context, ContentResolver resolver) { 66 context.startService(new Intent(context, RemoveScheduledAlarmsEmptyService.class)); 67 68 RemoveScheduledAlarmsThread thread = new RemoveScheduledAlarmsThread(context, resolver); 69 thread.start(); 70 } 71 72 /** 73 * Background thread that handles cleanup of scheduled alarms. 74 */ 75 private static class RemoveScheduledAlarmsThread extends Thread { 76 private Context mContext; 77 private ContentResolver mResolver; 78 79 RemoveScheduledAlarmsThread(Context context, ContentResolver resolver) { 80 mContext = context; 81 mResolver = resolver; 82 } 83 84 @Override 85 public void run() { 86 if (Log.isLoggable(TAG, Log.DEBUG)) { 87 Log.d(TAG, "Removing scheduled alarms"); 88 } 89 mResolver.update(CalendarAlarmManager.SCHEDULE_ALARM_REMOVE_URI, null /* values */, 90 null /* where */, null /* selectionArgs */); 91 mContext.stopService(new Intent(mContext, RemoveScheduledAlarmsEmptyService.class)); 92 } 93 } 94 95 /** 96 * Background {@link Service} that is used to keep our process alive long enough 97 * for background threads to finish. Used for cleanup of scheduled alarms. 98 */ 99 public static class RemoveScheduledAlarmsEmptyService extends Service { 100 @Override 101 public IBinder onBind(Intent intent) { 102 return null; 103 } 104 } 105} 106