AlarmManagerService.java revision 9066cfe9886ac131c34d59ed0e2d287b0e3c0087
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.server; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.ActivityManagerNative; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.AlarmManager; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.IAlarmManager; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.PendingIntent; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.BroadcastReceiver; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.IntentFilter; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.Uri; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.PowerManager; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemProperties; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.TextUtils; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.format.Time; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.EventLog; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintWriter; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Calendar; 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Collections; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Comparator; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Iterator; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Map; 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.TimeZone; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass AlarmManagerService extends IAlarmManager.Stub { 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The threshold for how long an alarm can be late before we print a 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // warning message. The time duration is in milliseconds. 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final long LATE_ALARM_THRESHOLD = 10 * 1000; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int RTC_WAKEUP_MASK = 1 << AlarmManager.RTC_WAKEUP; 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int RTC_MASK = 1 << AlarmManager.RTC; 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int ELAPSED_REALTIME_WAKEUP_MASK = 1 << AlarmManager.ELAPSED_REALTIME_WAKEUP; 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int ELAPSED_REALTIME_MASK = 1 << AlarmManager.ELAPSED_REALTIME; 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int TIME_CHANGED_MASK = 1 << 16; 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG = "AlarmManager"; 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String ClockReceiver_TAG = "ClockReceiver"; 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final boolean localLOGV = false; 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int ALARM_EVENT = 1; 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TIMEZONE_PROPERTY = "persist.sys.timezone"; 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final Intent mBackgroundIntent 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project = new Intent().addFlags(Intent.FLAG_FROM_BACKGROUND); 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Context mContext; 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Object mLock = new Object(); 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final ArrayList<Alarm> mRtcWakeupAlarms = new ArrayList<Alarm>(); 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final ArrayList<Alarm> mRtcAlarms = new ArrayList<Alarm>(); 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final ArrayList<Alarm> mElapsedRealtimeWakeupAlarms = new ArrayList<Alarm>(); 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final ArrayList<Alarm> mElapsedRealtimeAlarms = new ArrayList<Alarm>(); 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final IncreasingTimeOrder mIncreasingTimeOrder = new IncreasingTimeOrder(); 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // slots corresponding with the inexact-repeat interval buckets, 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // ordered from shortest to longest 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final long sInexactSlotIntervals[] = { 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AlarmManager.INTERVAL_FIFTEEN_MINUTES, 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AlarmManager.INTERVAL_HALF_HOUR, 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AlarmManager.INTERVAL_HOUR, 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AlarmManager.INTERVAL_HALF_DAY, 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AlarmManager.INTERVAL_DAY 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private long mInexactDeliveryTimes[] = { 0, 0, 0, 0, 0}; 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mDescriptor; 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mBroadcastRefCount = 0; 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private PowerManager.WakeLock mWakeLock; 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final AlarmThread mWaitThread = new AlarmThread(); 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final AlarmHandler mHandler = new AlarmHandler(); 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ClockReceiver mClockReceiver; 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private UninstallReceiver mUninstallReceiver; 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final ResultReceiver mResultReceiver = new ResultReceiver(); 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final PendingIntent mTimeTickSender; 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final PendingIntent mDateChangeSender; 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final class FilterStats { 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count; 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final class BroadcastStats { 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long aggregateTime; 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numWakeup; 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long startTime; 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int nesting; 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HashMap<Intent.FilterComparison, FilterStats> filterStats 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project = new HashMap<Intent.FilterComparison, FilterStats>(); 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final HashMap<String, BroadcastStats> mBroadcastStats 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project = new HashMap<String, BroadcastStats>(); 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public AlarmManagerService(Context context) { 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDescriptor = init(); 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTimeTickSender = PendingIntent.getBroadcast(context, 0, 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new Intent(Intent.ACTION_TIME_TICK).addFlags( 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Intent.FLAG_RECEIVER_REGISTERED_ONLY), 0); 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDateChangeSender = PendingIntent.getBroadcast(context, 0, 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new Intent(Intent.ACTION_DATE_CHANGED), 0); 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // now that we have initied the driver schedule the alarm 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mClockReceiver= new ClockReceiver(); 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mClockReceiver.scheduleTimeTickEvent(); 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mClockReceiver.scheduleDateChangedEvent(); 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUninstallReceiver = new UninstallReceiver(); 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDescriptor != -1) { 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWaitThread.start(); 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "Failed to open alarm driver. Falling back to a handler."); 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void finalize() throws Throwable { 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project close(mDescriptor); 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.finalize(); 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void set(int type, long triggerAtTime, PendingIntent operation) { 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setRepeating(type, triggerAtTime, 0, operation); 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setRepeating(int type, long triggerAtTime, long interval, 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PendingIntent operation) { 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (operation == null) { 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "set/setRepeating ignored because there is no intent"); 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mLock) { 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Alarm alarm = new Alarm(); 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project alarm.type = type; 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project alarm.when = triggerAtTime; 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project alarm.repeatInterval = interval; 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project alarm.operation = operation; 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Remove this alarm if already scheduled. 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeLocked(operation); 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (localLOGV) Log.v(TAG, "set: " + alarm); 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int index = addAlarmLocked(alarm); 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index == 0) { 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setLocked(alarm); 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setInexactRepeating(int type, long triggerAtTime, long interval, 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PendingIntent operation) { 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (operation == null) { 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "setInexactRepeating ignored because there is no intent"); 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // find the slot in the delivery-times array that we will use 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int intervalSlot; 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (intervalSlot = 0; intervalSlot < sInexactSlotIntervals.length; intervalSlot++) { 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sInexactSlotIntervals[intervalSlot] == interval) { 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Non-bucket intervals just fall back to the less-efficient 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // unbucketed recurring alarm implementation 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (intervalSlot >= sInexactSlotIntervals.length) { 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setRepeating(type, triggerAtTime, interval, operation); 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Align bucketed alarm deliveries by trying to match 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the shortest-interval bucket already scheduled 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long bucketTime = 0; 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int slot = 0; slot < mInexactDeliveryTimes.length; slot++) { 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mInexactDeliveryTimes[slot] > 0) { 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bucketTime = mInexactDeliveryTimes[slot]; 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (bucketTime == 0) { 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If nothing is scheduled yet, just start at the requested time 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bucketTime = triggerAtTime; 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Align the new alarm with the existing bucketed sequence. To achieve 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // alignment, we slide the start time around by min{interval, slot interval} 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long adjustment = (interval <= sInexactSlotIntervals[intervalSlot]) 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ? interval : sInexactSlotIntervals[intervalSlot]; 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The bucket may have started in the past; adjust 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (bucketTime < triggerAtTime) { 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bucketTime += adjustment; 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Or the bucket may be set to start more than an interval beyond 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // our requested trigger time; pull it back to meet our needs 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (bucketTime > triggerAtTime + adjustment) { 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bucketTime -= adjustment; 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Remember where this bucket started (reducing the amount of later 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // fixup required) and set the alarm with the new, bucketed start time. 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (localLOGV) Log.v(TAG, "setInexactRepeating: interval=" + interval 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " bucketTime=" + bucketTime); 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mInexactDeliveryTimes[intervalSlot] = bucketTime; 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setRepeating(type, bucketTime, interval, operation); 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setTimeZone(String tz) { 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission( 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "android.permission.SET_TIME_ZONE", 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "setTimeZone"); 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (TextUtils.isEmpty(tz)) return; 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TimeZone zone = TimeZone.getTimeZone(tz); 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Prevent reentrant calls from stepping on each other when writing 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the time zone property 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean timeZoneWasChanged = false; 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (this) { 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String current = SystemProperties.get(TIMEZONE_PROPERTY); 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (current == null || !current.equals(zone.getID())) { 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (localLOGV) Log.v(TAG, "timezone changed: " + current + ", new=" + zone.getID()); 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project timeZoneWasChanged = true; 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SystemProperties.set(TIMEZONE_PROPERTY, zone.getID()); 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Update the kernel timezone information 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Kernel tracks time offsets as 'minutes west of GMT' 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int gmtOffset = (zone.getRawOffset() + zone.getDSTSavings()) / 60000; 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setKernelTimezone(mDescriptor, -(gmtOffset)); 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TimeZone.setDefault(null); 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (timeZoneWasChanged) { 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Intent intent = new Intent(Intent.ACTION_TIMEZONE_CHANGED); 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project intent.putExtra("time-zone", zone.getID()); 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.sendBroadcast(intent); 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void remove(PendingIntent operation) { 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (operation == null) { 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mLock) { 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeLocked(operation); 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void removeLocked(PendingIntent operation) { 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeLocked(mRtcWakeupAlarms, operation); 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeLocked(mRtcAlarms, operation); 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeLocked(mElapsedRealtimeWakeupAlarms, operation); 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeLocked(mElapsedRealtimeAlarms, operation); 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void removeLocked(ArrayList<Alarm> alarmList, 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PendingIntent operation) { 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (alarmList.size() <= 0) { 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // iterator over the list removing any it where the intent match 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<Alarm> it = alarmList.iterator(); 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (it.hasNext()) { 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Alarm alarm = it.next(); 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (alarm.operation.equals(operation)) { 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project it.remove(); 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void removeLocked(String packageName) { 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeLocked(mRtcWakeupAlarms, packageName); 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeLocked(mRtcAlarms, packageName); 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeLocked(mElapsedRealtimeWakeupAlarms, packageName); 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeLocked(mElapsedRealtimeAlarms, packageName); 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void removeLocked(ArrayList<Alarm> alarmList, 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String packageName) { 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (alarmList.size() <= 0) { 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // iterator over the list removing any it where the intent match 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<Alarm> it = alarmList.iterator(); 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (it.hasNext()) { 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Alarm alarm = it.next(); 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (alarm.operation.getTargetPackage().equals(packageName)) { 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project it.remove(); 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ArrayList<Alarm> getAlarmList(int type) { 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (type) { 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case AlarmManager.RTC_WAKEUP: return mRtcWakeupAlarms; 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case AlarmManager.RTC: return mRtcAlarms; 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case AlarmManager.ELAPSED_REALTIME_WAKEUP: return mElapsedRealtimeWakeupAlarms; 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case AlarmManager.ELAPSED_REALTIME: return mElapsedRealtimeAlarms; 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int addAlarmLocked(Alarm alarm) { 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Alarm> alarmList = getAlarmList(alarm.type); 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int index = Collections.binarySearch(alarmList, alarm, mIncreasingTimeOrder); 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index < 0) { 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = 0 - index - 1; 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (localLOGV) Log.v(TAG, "Adding alarm " + alarm + " at " + index); 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project alarmList.add(index, alarm); 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (localLOGV) { 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Display the list of alarms for this alarm type 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v(TAG, "alarms: " + alarmList.size() + " type: " + alarm.type); 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int position = 0; 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (Alarm a : alarmList) { 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Time time = new Time(); 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project time.set(a.when); 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String timeStr = time.format("%b %d %I:%M:%S %p"); 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v(TAG, position + ": " + timeStr 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " " + a.operation.getTargetPackage()); 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project position += 1; 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return index; 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long timeToNextAlarm() { 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long nextAlarm = 0xfffffffffffffffl; 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mLock) { 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i=AlarmManager.RTC_WAKEUP; 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project i<=AlarmManager.ELAPSED_REALTIME; i++) { 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Alarm> alarmList = getAlarmList(i); 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (alarmList.size() > 0) { 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Alarm a = alarmList.get(0); 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (a.when < nextAlarm) { 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nextAlarm = a.when; 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return nextAlarm; 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void setLocked(Alarm alarm) 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDescriptor != -1) 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project set(mDescriptor, alarm.type, (alarm.when * 1000 * 1000)); 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Message msg = Message.obtain(); 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg.what = ALARM_EVENT; 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.removeMessages(ALARM_EVENT); 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.sendMessageAtTime(msg, alarm.when); 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project != PackageManager.PERMISSION_GRANTED) { 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println("Permission Denial: can't dump AlarmManager from from pid=" 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + Binder.getCallingPid() 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + ", uid=" + Binder.getCallingUid()); 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mLock) { 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println("Current Alarm Manager state:"); 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mRtcWakeupAlarms.size() > 0) { 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(" "); 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(" Realtime wakeup alarms that are scheduled:"); 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dumpAlarmList(pw, mRtcWakeupAlarms, " ", "RTC_WAKEUP"); 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mRtcAlarms.size() > 0) { 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(" "); 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(" Realtime alarms that are scheduled:"); 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dumpAlarmList(pw, mRtcAlarms, " ", "RTC"); 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mElapsedRealtimeWakeupAlarms.size() > 0) { 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(" "); 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(" Elapsed realtime wakeup alarms that are scheduled:"); 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dumpAlarmList(pw, mElapsedRealtimeWakeupAlarms, " ", "ELAPSED_REALTIME_WAKEUP"); 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mElapsedRealtimeAlarms.size() > 0) { 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(" "); 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(" Elapsed realtime alarms that are scheduled:"); 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dumpAlarmList(pw, mElapsedRealtimeAlarms, " ", "ELAPSED_REALTIME"); 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(" "); 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(" Broadcast ref count: " + mBroadcastRefCount); 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(" "); 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(" Alarm Stats:"); 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (Map.Entry<String, BroadcastStats> be : mBroadcastStats.entrySet()) { 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BroadcastStats bs = be.getValue(); 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(" " + be.getKey()); 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(" " + bs.aggregateTime + "ms running, " 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + bs.numWakeup + " wakeups"); 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (Map.Entry<Intent.FilterComparison, FilterStats> fe 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : bs.filterStats.entrySet()) { 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(" " + fe.getValue().count + " alarms: " 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + fe.getKey().getIntent()); 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list, String prefix, String label) { 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i=list.size()-1; i>=0; i--) { 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Alarm a = list.get(i); 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(prefix + label + " #" + i + ":"); 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a.dump(pw, prefix + " "); 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native int init(); 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native void close(int fd); 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native void set(int fd, int type, long nanoseconds); 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native int waitForAlarm(int fd); 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native int setKernelTimezone(int fd, int minuteswest); 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void triggerAlarmsLocked(ArrayList<Alarm> alarmList, 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Alarm> triggerList, 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long now) 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<Alarm> it = alarmList.iterator(); 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Alarm> repeats = new ArrayList<Alarm>(); 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (it.hasNext()) 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Alarm alarm = it.next(); 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (localLOGV) Log.v(TAG, "Checking active alarm when=" + alarm.when + " " + alarm); 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (alarm.when > now) { 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // don't fire alarms in the future 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If the alarm is late, then print a warning message. 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Note that this can happen if the user creates a new event on 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the Calendar app with a reminder that is in the past. In that 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // case, the reminder alarm will fire immediately. 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (localLOGV && now - alarm.when > LATE_ALARM_THRESHOLD) { 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v(TAG, "alarm is late! alarm time: " + alarm.when 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " now: " + now + " delay (in seconds): " 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + (now - alarm.when) / 1000); 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Recurring alarms may have passed several alarm intervals while the 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // phone was asleep or off, so pass a trigger count when sending them. 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (localLOGV) Log.v(TAG, "Alarm triggering: " + alarm); 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project alarm.count = 1; 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (alarm.repeatInterval > 0) { 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // this adjustment will be zero if we're late by 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // less than one full repeat interval 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project alarm.count += (now - alarm.when) / alarm.repeatInterval; 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project triggerList.add(alarm); 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // remove the alarm from the list 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project it.remove(); 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // if it repeats queue it up to be read-added to the list 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (alarm.repeatInterval > 0) { 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project repeats.add(alarm); 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // reset any repeating alarms. 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project it = repeats.iterator(); 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (it.hasNext()) { 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Alarm alarm = it.next(); 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project alarm.when += alarm.count * alarm.repeatInterval; 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project addAlarmLocked(alarm); 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (alarmList.size() > 0) { 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setLocked(alarmList.get(0)); 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This Comparator sorts Alarms into increasing time order. 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static class IncreasingTimeOrder implements Comparator<Alarm> { 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int compare(Alarm a1, Alarm a2) { 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long when1 = a1.when; 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long when2 = a2.when; 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (when1 - when2 > 0) { 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 1; 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (when1 - when2 < 0) { 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static class Alarm { 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int type; 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int count; 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long when; 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long repeatInterval; 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public PendingIntent operation; 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Alarm() { 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project when = 0; 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project repeatInterval = 0; 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project operation = null; 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String toString() 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "Alarm{" 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + Integer.toHexString(System.identityHashCode(this)) 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " type " + type + " " + operation.getTargetPackage() + "}"; 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void dump(PrintWriter pw, String prefix) 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(prefix + this); 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(prefix + "type=" + type + " when=" + when 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " repeatInterval=" + repeatInterval 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " count=" + count); 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(prefix + "operation=" + operation); 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class AlarmThread extends Thread 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public AlarmThread() 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super("AlarmManager"); 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (true) 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int result = waitForAlarm(mDescriptor); 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Alarm> triggerList = new ArrayList<Alarm>(); 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((result & TIME_CHANGED_MASK) != 0) { 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project remove(mTimeTickSender); 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mClockReceiver.scheduleTimeTickEvent(); 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.sendBroadcast(new Intent(Intent.ACTION_TIME_CHANGED)); 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mLock) { 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final long nowRTC = System.currentTimeMillis(); 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final long nowELAPSED = SystemClock.elapsedRealtime(); 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (localLOGV) Log.v( 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TAG, "Checking for alarms... rtc=" + nowRTC 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + ", elapsed=" + nowELAPSED); 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((result & RTC_WAKEUP_MASK) != 0) 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project triggerAlarmsLocked(mRtcWakeupAlarms, triggerList, nowRTC); 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((result & RTC_MASK) != 0) 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project triggerAlarmsLocked(mRtcAlarms, triggerList, nowRTC); 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((result & ELAPSED_REALTIME_WAKEUP_MASK) != 0) 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project triggerAlarmsLocked(mElapsedRealtimeWakeupAlarms, triggerList, nowELAPSED); 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((result & ELAPSED_REALTIME_MASK) != 0) 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project triggerAlarmsLocked(mElapsedRealtimeAlarms, triggerList, nowELAPSED); 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // now trigger the alarms 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<Alarm> it = triggerList.iterator(); 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (it.hasNext()) { 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Alarm alarm = it.next(); 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (localLOGV) Log.v(TAG, "sending alarm " + alarm); 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project alarm.operation.send(mContext, 0, 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBackgroundIntent.putExtra( 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Intent.EXTRA_ALARM_COUNT, alarm.count), 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mResultReceiver, mHandler); 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // we have an active broadcast so stay awake. 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mBroadcastRefCount == 0) { 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWakeLock.acquire(); 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBroadcastRefCount++; 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BroadcastStats bs = getStatsLocked(alarm.operation); 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (bs.nesting == 0) { 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bs.startTime = nowELAPSED; 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bs.nesting++; 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (alarm.type == AlarmManager.ELAPSED_REALTIME_WAKEUP 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || alarm.type == AlarmManager.RTC_WAKEUP) { 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bs.numWakeup++; 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ActivityManagerNative.noteWakeupAlarm( 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project alarm.operation); 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (PendingIntent.CanceledException e) { 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (alarm.repeatInterval > 0) { 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This IntentSender is no longer valid, but this 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // is a repeating alarm, so toss the hoser. 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project remove(alarm.operation); 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (RuntimeException e) { 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "Failure sending alarm.", e); 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class AlarmHandler extends Handler { 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int ALARM_EVENT = 1; 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int MINUTE_CHANGE_EVENT = 2; 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int DATE_CHANGE_EVENT = 3; 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public AlarmHandler() { 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void handleMessage(Message msg) { 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (msg.what == ALARM_EVENT) { 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Alarm> triggerList = new ArrayList<Alarm>(); 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mLock) { 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final long nowRTC = System.currentTimeMillis(); 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project triggerAlarmsLocked(mRtcWakeupAlarms, triggerList, nowRTC); 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project triggerAlarmsLocked(mRtcAlarms, triggerList, nowRTC); 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project triggerAlarmsLocked(mElapsedRealtimeWakeupAlarms, triggerList, nowRTC); 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project triggerAlarmsLocked(mElapsedRealtimeAlarms, triggerList, nowRTC); 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // now trigger the alarms without the lock held 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Iterator<Alarm> it = triggerList.iterator(); 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (it.hasNext()) 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Alarm alarm = it.next(); 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project alarm.operation.send(); 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (PendingIntent.CanceledException e) { 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (alarm.repeatInterval > 0) { 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This IntentSender is no longer valid, but this 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // is a repeating alarm, so toss the hoser. 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project remove(alarm.operation); 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project class ClockReceiver extends BroadcastReceiver { 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ClockReceiver() { 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IntentFilter filter = new IntentFilter(); 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project filter.addAction(Intent.ACTION_TIME_TICK); 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project filter.addAction(Intent.ACTION_DATE_CHANGED); 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.registerReceiver(this, filter); 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onReceive(Context context, Intent intent) { 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (intent.getAction().equals(Intent.ACTION_TIME_TICK)) { 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project scheduleTimeTickEvent(); 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (intent.getAction().equals(Intent.ACTION_DATE_CHANGED)) { 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Since the kernel does not keep track of DST, we need to 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // reset the TZ information at the beginning of each day 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // based off of the current Zone gmt offset + userspace tracked 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // daylight savings information. 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TimeZone zone = TimeZone.getTimeZone(SystemProperties.get(TIMEZONE_PROPERTY)); 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int gmtOffset = (zone.getRawOffset() + zone.getDSTSavings()) / 60000; 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setKernelTimezone(mDescriptor, -(gmtOffset)); 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project scheduleDateChangedEvent(); 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void scheduleTimeTickEvent() { 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Calendar calendar = Calendar.getInstance(); 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project calendar.setTimeInMillis(System.currentTimeMillis()); 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project calendar.add(Calendar.MINUTE, 1); 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project calendar.set(Calendar.SECOND, 0); 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project calendar.set(Calendar.MILLISECOND, 0); 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project set(AlarmManager.RTC, calendar.getTimeInMillis(), mTimeTickSender); 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void scheduleDateChangedEvent() { 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Calendar calendar = Calendar.getInstance(); 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project calendar.setTimeInMillis(System.currentTimeMillis()); 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project calendar.set(Calendar.HOUR, 0); 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project calendar.set(Calendar.MINUTE, 0); 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project calendar.set(Calendar.SECOND, 0); 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project calendar.set(Calendar.MILLISECOND, 0); 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project calendar.add(Calendar.DAY_OF_MONTH, 1); 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project set(AlarmManager.RTC, calendar.getTimeInMillis(), mDateChangeSender); 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project class UninstallReceiver extends BroadcastReceiver { 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public UninstallReceiver() { 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IntentFilter filter = new IntentFilter(); 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project filter.addAction(Intent.ACTION_PACKAGE_REMOVED); 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project filter.addAction(Intent.ACTION_PACKAGE_RESTARTED); 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project filter.addDataScheme("package"); 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.registerReceiver(this, filter); 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onReceive(Context context, Intent intent) { 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mLock) { 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Uri data = intent.getData(); 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (data != null) { 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String pkg = data.getSchemeSpecificPart(); 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeLocked(pkg); 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBroadcastStats.remove(pkg); 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final BroadcastStats getStatsLocked(PendingIntent pi) { 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String pkg = pi.getTargetPackage(); 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BroadcastStats bs = mBroadcastStats.get(pkg); 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (bs == null) { 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bs = new BroadcastStats(); 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBroadcastStats.put(pkg, bs); 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return bs; 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project class ResultReceiver implements PendingIntent.OnFinished { 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onSendFinished(PendingIntent pi, Intent intent, int resultCode, 7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String resultData, Bundle resultExtras) { 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mLock) { 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BroadcastStats bs = getStatsLocked(pi); 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (bs != null) { 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bs.nesting--; 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (bs.nesting <= 0) { 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bs.nesting = 0; 7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bs.aggregateTime += SystemClock.elapsedRealtime() 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project - bs.startTime; 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Intent.FilterComparison fc = new Intent.FilterComparison(intent); 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FilterStats fs = bs.filterStats.get(fc); 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fs == null) { 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fs = new FilterStats(); 7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bs.filterStats.put(fc, fs); 7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fs.count++; 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBroadcastRefCount--; 8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mBroadcastRefCount == 0) { 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWakeLock.release(); 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 809