1 /* 2 * Copyright (C) 2007 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.deskclock; 18 19 import android.annotation.SuppressLint; 20 import android.content.BroadcastReceiver; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.os.PowerManager.WakeLock; 24 25 import com.android.deskclock.alarms.AlarmStateManager; 26 import com.android.deskclock.data.DataModel; 27 import com.android.deskclock.events.Events; 28 29 public class AlarmInitReceiver extends BroadcastReceiver { 30 31 /** 32 * When running on N devices, we're interested in the boot completed event that is sent while 33 * the user is still locked, so that we can schedule alarms. 34 */ 35 @SuppressLint("InlinedApi") 36 private static final String ACTION_BOOT_COMPLETED = Utils.isNOrLater() 37 ? Intent.ACTION_LOCKED_BOOT_COMPLETED : Intent.ACTION_BOOT_COMPLETED; 38 39 /** 40 * This receiver handles a variety of actions: 41 * 42 * <ul> 43 * <li>Clean up backup data that was recently restored to this device on 44 * ACTION_COMPLETE_RESTORE.</li> 45 * <li>Reset timers and stopwatch on ACTION_BOOT_COMPLETED</li> 46 * <li>Fix alarm states on ACTION_BOOT_COMPLETED, TIME_SET, TIMEZONE_CHANGED, 47 * and LOCALE_CHANGED</li> 48 * <li>Rebuild notifications on MY_PACKAGE_REPLACED</li> 49 * </ul> 50 */ 51 @Override onReceive(final Context context, Intent intent)52 public void onReceive(final Context context, Intent intent) { 53 final String action = intent.getAction(); 54 LogUtils.i("AlarmInitReceiver " + action); 55 56 final PendingResult result = goAsync(); 57 final WakeLock wl = AlarmAlertWakeLock.createPartialWakeLock(context); 58 wl.acquire(); 59 60 // We need to increment the global id out of the async task to prevent race conditions 61 AlarmStateManager.updateGlobalIntentId(context); 62 63 // Clear stopwatch data and reset timers because they rely on elapsed real-time values 64 // which are meaningless after a device reboot. 65 if (ACTION_BOOT_COMPLETED.equals(action)) { 66 DataModel.getDataModel().clearLaps(); 67 DataModel.getDataModel().resetStopwatch(); 68 Events.sendStopwatchEvent(R.string.action_reset, R.string.label_reboot); 69 DataModel.getDataModel().resetTimers(R.string.label_reboot); 70 } 71 72 // Notifications are canceled by the system on application upgrade. This broadcast signals 73 // that the new app is free to rebuild the notifications using the existing data. 74 if (Intent.ACTION_MY_PACKAGE_REPLACED.equals(action)) { 75 DataModel.getDataModel().updateAllNotifications(); 76 } 77 78 AsyncHandler.post(new Runnable() { 79 @Override 80 public void run() { 81 try { 82 // Process restored data if any exists 83 if (!DeskClockBackupAgent.processRestoredData(context)) { 84 // Update all the alarm instances on time change event 85 AlarmStateManager.fixAlarmInstances(context); 86 } 87 } finally { 88 result.finish(); 89 wl.release(); 90 LogUtils.v("AlarmInitReceiver finished"); 91 } 92 } 93 }); 94 } 95 } 96