15fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project/*
25fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
35fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project *
45fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
55fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * you may not use this file except in compliance with the License.
65fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * You may obtain a copy of the License at
75fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project *
85fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
95fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project *
105fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
115fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
125fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * See the License for the specific language governing permissions and
145fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * limitations under the License.
155fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */
165fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
17fa954248b41b567dfa2ddd7bd063d3936a51758eDaniel Sandlerpackage com.android.deskclock;
185fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
19db9dff0ab3d3295cffdde9b9364ddb413f14ed9eJeff Sharkeyimport android.annotation.SuppressLint;
20de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelsonimport android.content.BroadcastReceiver;
215fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.content.Context;
225fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.content.Intent;
23df77f79bbf931894d91cd0d8334f204ff67e903aPatrick Scottimport android.os.PowerManager.WakeLock;
24de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson
25ab0d28c68a77bea2a4a2ee50378da3670a1dd939Paul Sliwowskiimport com.android.deskclock.alarms.AlarmStateManager;
2624a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieuximport com.android.deskclock.data.DataModel;
276d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieuximport com.android.deskclock.events.Events;
285fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
295fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectpublic class AlarmInitReceiver extends BroadcastReceiver {
30079dc3af583995b1fcbd84534f73feaf10adb596Justin Klaassen
31079dc3af583995b1fcbd84534f73feaf10adb596Justin Klaassen    /**
32079dc3af583995b1fcbd84534f73feaf10adb596Justin Klaassen     * When running on N devices, we're interested in the boot completed event that is sent while
33079dc3af583995b1fcbd84534f73feaf10adb596Justin Klaassen     * the user is still locked, so that we can schedule alarms.
34079dc3af583995b1fcbd84534f73feaf10adb596Justin Klaassen     */
35079dc3af583995b1fcbd84534f73feaf10adb596Justin Klaassen    @SuppressLint("InlinedApi")
36079dc3af583995b1fcbd84534f73feaf10adb596Justin Klaassen    private static final String ACTION_BOOT_COMPLETED = Utils.isNOrLater()
37079dc3af583995b1fcbd84534f73feaf10adb596Justin Klaassen            ? Intent.ACTION_LOCKED_BOOT_COMPLETED : Intent.ACTION_BOOT_COMPLETED;
38079dc3af583995b1fcbd84534f73feaf10adb596Justin Klaassen
395fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
4032e2e0440cc4219dfe200bcf025508b740ec7cb1James Lemieux     * This receiver handles a variety of actions:
4132e2e0440cc4219dfe200bcf025508b740ec7cb1James Lemieux     *
4232e2e0440cc4219dfe200bcf025508b740ec7cb1James Lemieux     * <ul>
4332e2e0440cc4219dfe200bcf025508b740ec7cb1James Lemieux     *     <li>Clean up backup data that was recently restored to this device on
4432e2e0440cc4219dfe200bcf025508b740ec7cb1James Lemieux     *     ACTION_COMPLETE_RESTORE.</li>
456d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux     *     <li>Reset timers and stopwatch on ACTION_BOOT_COMPLETED</li>
4632e2e0440cc4219dfe200bcf025508b740ec7cb1James Lemieux     *     <li>Fix alarm states on ACTION_BOOT_COMPLETED, TIME_SET, TIMEZONE_CHANGED,
4732e2e0440cc4219dfe200bcf025508b740ec7cb1James Lemieux     *     and LOCALE_CHANGED</li>
48ac1506f175631e2b2f52ff9142cbdc6c725ef447James Lemieux     *     <li>Rebuild notifications on MY_PACKAGE_REPLACED</li>
4932e2e0440cc4219dfe200bcf025508b740ec7cb1James Lemieux     * </ul>
505fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
515fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    @Override
52df77f79bbf931894d91cd0d8334f204ff67e903aPatrick Scott    public void onReceive(final Context context, Intent intent) {
53df77f79bbf931894d91cd0d8334f204ff67e903aPatrick Scott        final String action = intent.getAction();
5419abdb148ee0716b10b04df8ab02b4c780fab3eaAnnie Chin        LogUtils.i("AlarmInitReceiver " + action);
555fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
56df77f79bbf931894d91cd0d8334f204ff67e903aPatrick Scott        final PendingResult result = goAsync();
57df77f79bbf931894d91cd0d8334f204ff67e903aPatrick Scott        final WakeLock wl = AlarmAlertWakeLock.createPartialWakeLock(context);
58df77f79bbf931894d91cd0d8334f204ff67e903aPatrick Scott        wl.acquire();
5925b9df53e993ee775c4733e61b8fef2aa358ef70Paul Sliwowski
6032e2e0440cc4219dfe200bcf025508b740ec7cb1James Lemieux        // We need to increment the global id out of the async task to prevent race conditions
61b4aacfb276d66f2bf02691e56d0d20fe6bab31a4Budi Kusmiantoro        AlarmStateManager.updateGlobalIntentId(context);
6232e2e0440cc4219dfe200bcf025508b740ec7cb1James Lemieux
636d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux        // Clear stopwatch data and reset timers because they rely on elapsed real-time values
646d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux        // which are meaningless after a device reboot.
65079dc3af583995b1fcbd84534f73feaf10adb596Justin Klaassen        if (ACTION_BOOT_COMPLETED.equals(action)) {
6624a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux            DataModel.getDataModel().clearLaps();
6724a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux            DataModel.getDataModel().resetStopwatch();
686d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux            Events.sendStopwatchEvent(R.string.action_reset, R.string.label_reboot);
696d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux            DataModel.getDataModel().resetTimers(R.string.label_reboot);
7024a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux        }
7124a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux
72ac1506f175631e2b2f52ff9142cbdc6c725ef447James Lemieux        // Notifications are canceled by the system on application upgrade. This broadcast signals
73ac1506f175631e2b2f52ff9142cbdc6c725ef447James Lemieux        // that the new app is free to rebuild the notifications using the existing data.
74ac1506f175631e2b2f52ff9142cbdc6c725ef447James Lemieux        if (Intent.ACTION_MY_PACKAGE_REPLACED.equals(action)) {
75ac1506f175631e2b2f52ff9142cbdc6c725ef447James Lemieux            DataModel.getDataModel().updateAllNotifications();
76ac1506f175631e2b2f52ff9142cbdc6c725ef447James Lemieux        }
77ac1506f175631e2b2f52ff9142cbdc6c725ef447James Lemieux
78df77f79bbf931894d91cd0d8334f204ff67e903aPatrick Scott        AsyncHandler.post(new Runnable() {
796d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux            @Override
806d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux            public void run() {
8132e2e0440cc4219dfe200bcf025508b740ec7cb1James Lemieux                try {
8232e2e0440cc4219dfe200bcf025508b740ec7cb1James Lemieux                    // Process restored data if any exists
8332e2e0440cc4219dfe200bcf025508b740ec7cb1James Lemieux                    if (!DeskClockBackupAgent.processRestoredData(context)) {
8432e2e0440cc4219dfe200bcf025508b740ec7cb1James Lemieux                        // Update all the alarm instances on time change event
8532e2e0440cc4219dfe200bcf025508b740ec7cb1James Lemieux                        AlarmStateManager.fixAlarmInstances(context);
8632e2e0440cc4219dfe200bcf025508b740ec7cb1James Lemieux                    }
8732e2e0440cc4219dfe200bcf025508b740ec7cb1James Lemieux                } finally {
8832e2e0440cc4219dfe200bcf025508b740ec7cb1James Lemieux                    result.finish();
8932e2e0440cc4219dfe200bcf025508b740ec7cb1James Lemieux                    wl.release();
9032e2e0440cc4219dfe200bcf025508b740ec7cb1James Lemieux                    LogUtils.v("AlarmInitReceiver finished");
9132e2e0440cc4219dfe200bcf025508b740ec7cb1James Lemieux                }
92df77f79bbf931894d91cd0d8334f204ff67e903aPatrick Scott            }
93df77f79bbf931894d91cd0d8334f204ff67e903aPatrick Scott        });
945fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
95db9dff0ab3d3295cffdde9b9364ddb413f14ed9eJeff Sharkey}
96