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