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.controller.Controller; 27 import com.android.deskclock.data.DataModel; 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 DataModel.getDataModel().updateGlobalIntentId(); 62 63 // Updates stopwatch and timer data after a device reboot so they are as accurate as 64 // possible. 65 if (ACTION_BOOT_COMPLETED.equals(action)) { 66 DataModel.getDataModel().updateAfterReboot(); 67 // Stopwatch and timer data need to be updated on time change so the reboot 68 // functionality works as expected. 69 } else if (Intent.ACTION_TIME_CHANGED.equals(action)) { 70 DataModel.getDataModel().updateAfterTimeSet(); 71 } 72 73 // Update shortcuts so they exist for the user. 74 if (Intent.ACTION_BOOT_COMPLETED.equals(action) 75 || Intent.ACTION_LOCALE_CHANGED.equals(action)) { 76 Controller.getController().updateShortcuts(); 77 } 78 79 // Notifications are canceled by the system on application upgrade. This broadcast signals 80 // that the new app is free to rebuild the notifications using the existing data. 81 // Additionally on new app installs, make sure to enable shortcuts immediately as opposed 82 // to waiting for system reboot. 83 if (Intent.ACTION_MY_PACKAGE_REPLACED.equals(action)) { 84 DataModel.getDataModel().updateAllNotifications(); 85 Controller.getController().updateShortcuts(); 86 } 87 88 AsyncHandler.post(new Runnable() { 89 @Override 90 public void run() { 91 try { 92 // Process restored data if any exists 93 if (!DeskClockBackupAgent.processRestoredData(context)) { 94 // Update all the alarm instances on time change event 95 AlarmStateManager.fixAlarmInstances(context); 96 } 97 } finally { 98 result.finish(); 99 wl.release(); 100 LogUtils.v("AlarmInitReceiver finished"); 101 } 102 } 103 }); 104 } 105 } 106