2 * Copyright (C) 2006 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.android.server;
19 import android.app.Activity;
20 import android.app.ActivityManager;
21 import android.app.ActivityManagerNative;
22 import android.app.AlarmManager;
23 import android.app.AppOpsManager;
24 import android.app.BroadcastOptions;
25 import android.app.IAlarmCompleteListener;
26 import android.app.IAlarmListener;
27 import android.app.IAlarmManager;
28 import android.app.IUidObserver;
29 import android.app.PendingIntent;
30 import android.content.BroadcastReceiver;
31 import android.content.ContentResolver;
32 import android.content.Context;
33 import android.content.Intent;
34 import android.content.IntentFilter;
35 import android.content.pm.PackageManager;
36 import android.database.ContentObserver;
37 import android.net.Uri;
38 import android.os.Binder;
39 import android.os.Bundle;
40 import android.os.Handler;
41 import android.os.IBinder;
42 import android.os.Message;
43 import android.os.PowerManager;
44 import android.os.Process;
45 import android.os.RemoteException;
46 import android.os.SystemClock;
47 import android.os.SystemProperties;
48 import android.os.UserHandle;
49 import android.os.WorkSource;
50 import android.provider.Settings;
51 import android.text.TextUtils;
52 import android.text.format.DateFormat;
53 import android.util.ArrayMap;
54 import android.util.KeyValueListParser;
55 import android.util.Log;
56 import android.util.Slog;
57 import android.util.SparseArray;
58 import android.util.SparseBooleanArray;
59 import android.util.SparseLongArray;
60 import android.util.TimeUtils;
62 import java.io.ByteArrayOutputStream;
63 import java.io.FileDescriptor;
64 import java.io.PrintWriter;
65 import java.text.SimpleDateFormat;
66 import java.util.ArrayList;
67 import java.util.Arrays;
68 import java.util.Calendar;
69 import java.util.Collections;
70 import java.util.Comparator;
71 import java.util.Date;
72 import java.util.HashMap;
73 import java.util.LinkedList;
74 import java.util.Locale;
75 import java.util.Random;
76 import java.util.TimeZone;
77 import java.util.TreeSet;
79 import static android.app.AlarmManager.RTC_WAKEUP;
80 import static android.app.AlarmManager.RTC;
81 import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP;
82 import static android.app.AlarmManager.ELAPSED_REALTIME;
84 import com.android.internal.util.LocalLog;
86 class AlarmManagerService extends SystemService {
87 private static final int RTC_WAKEUP_MASK = 1 << RTC_WAKEUP;
88 private static final int RTC_MASK = 1 << RTC;
89 private static final int ELAPSED_REALTIME_WAKEUP_MASK = 1 << ELAPSED_REALTIME_WAKEUP;
90 private static final int ELAPSED_REALTIME_MASK = 1 << ELAPSED_REALTIME;
91 static final int TIME_CHANGED_MASK = 1 << 16;
92 static final int IS_WAKEUP_MASK = RTC_WAKEUP_MASK|ELAPSED_REALTIME_WAKEUP_MASK;
94 // Mask for testing whether a given alarm type is wakeup vs non-wakeup
95 static final int TYPE_NONWAKEUP_MASK = 0x1; // low bit => non-wakeup
97 static final String TAG = "AlarmManager";
98 static final boolean localLOGV = false;
99 static final boolean DEBUG_BATCH = localLOGV || false;
100 static final boolean DEBUG_VALIDATE = localLOGV || false;
101 static final boolean DEBUG_ALARM_CLOCK = localLOGV || false;
102 static final boolean DEBUG_LISTENER_CALLBACK = localLOGV || false;
103 static final boolean RECORD_ALARMS_IN_HISTORY = true;
104 static final boolean RECORD_DEVICE_IDLE_ALARMS = false;
105 static final int ALARM_EVENT = 1;
106 static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
108 private final Intent mBackgroundIntent
109 = new Intent().addFlags(Intent.FLAG_FROM_BACKGROUND);
110 static final IncreasingTimeOrder sIncreasingTimeOrder = new IncreasingTimeOrder();
112 static final boolean WAKEUP_STATS = false;
114 private static final Intent NEXT_ALARM_CLOCK_CHANGED_INTENT =
115 new Intent(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED)
116 .addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
118 final LocalLog mLog = new LocalLog(TAG);
120 AppOpsManager mAppOps;
121 DeviceIdleController.LocalService mLocalDeviceIdleController;
123 final Object mLock = new Object();
126 private long mNextWakeup;
127 private long mNextNonWakeup;
128 private long mLastWakeupSet;
129 private long mLastWakeup;
130 int mBroadcastRefCount = 0;
131 PowerManager.WakeLock mWakeLock;
132 boolean mLastWakeLockUnimportantForLogging;
133 ArrayList<Alarm> mPendingNonWakeupAlarms = new ArrayList<>();
134 ArrayList<InFlight> mInFlight = new ArrayList<>();
135 final AlarmHandler mHandler = new AlarmHandler();
136 ClockReceiver mClockReceiver;
137 InteractiveStateReceiver mInteractiveStateReceiver;
138 private UninstallReceiver mUninstallReceiver;
139 final DeliveryTracker mDeliveryTracker = new DeliveryTracker();
140 PendingIntent mTimeTickSender;
141 PendingIntent mDateChangeSender;
143 boolean mInteractive = true;
144 long mNonInteractiveStartTime;
145 long mNonInteractiveTime;
146 long mLastAlarmDeliveryTime;
147 long mStartCurrentDelayTime;
148 long mNextNonWakeupDeliveryTime;
149 long mLastTimeChangeClockTime;
150 long mLastTimeChangeRealtime;
151 long mAllowWhileIdleMinTime;
155 * The current set of user whitelisted apps for device idle mode, meaning these are allowed
156 * to freely schedule alarms.
158 int[] mDeviceIdleUserWhitelist = new int[0];
161 * For each uid, this is the last time we dispatched an "allow while idle" alarm,
162 * used to determine the earliest we can dispatch the next such alarm.
164 final SparseLongArray mLastAllowWhileIdleDispatch = new SparseLongArray();
166 final static class IdleDispatchEntry {
171 long elapsedRealtime;
174 final ArrayList<IdleDispatchEntry> mAllowWhileIdleDispatches = new ArrayList();
177 * Broadcast options to use for FLAG_ALLOW_WHILE_IDLE.
181 private final SparseArray<AlarmManager.AlarmClockInfo> mNextAlarmClockForUser =
183 private final SparseArray<AlarmManager.AlarmClockInfo> mTmpSparseAlarmClockArray =
185 private final SparseBooleanArray mPendingSendNextAlarmClockChangedForUser =
186 new SparseBooleanArray();
187 private boolean mNextAlarmClockMayChange;
189 // May only use on mHandler's thread, locking not required.
190 private final SparseArray<AlarmManager.AlarmClockInfo> mHandlerSparseAlarmClockArray =
194 * All times are in milliseconds. These constants are kept synchronized with the system
195 * global Settings. Any access to this class or its fields should be done while
196 * holding the AlarmManagerService.mLock lock.
198 private final class Constants extends ContentObserver {
199 // Key names stored in the settings value.
200 private static final String KEY_MIN_FUTURITY = "min_futurity";
201 private static final String KEY_MIN_INTERVAL = "min_interval";
202 private static final String KEY_ALLOW_WHILE_IDLE_SHORT_TIME = "allow_while_idle_short_time";
203 private static final String KEY_ALLOW_WHILE_IDLE_LONG_TIME = "allow_while_idle_long_time";
204 private static final String KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION
205 = "allow_while_idle_whitelist_duration";
206 private static final String KEY_LISTENER_TIMEOUT = "listener_timeout";
208 private static final long DEFAULT_MIN_FUTURITY = 5 * 1000;
209 private static final long DEFAULT_MIN_INTERVAL = 60 * 1000;
210 private static final long DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME = DEFAULT_MIN_FUTURITY;
211 private static final long DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME = 9*60*1000;
212 private static final long DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION = 10*1000;
214 private static final long DEFAULT_LISTENER_TIMEOUT = 5 * 1000;
216 // Minimum futurity of a new alarm
217 public long MIN_FUTURITY = DEFAULT_MIN_FUTURITY;
219 // Minimum alarm recurrence interval
220 public long MIN_INTERVAL = DEFAULT_MIN_INTERVAL;
222 // Minimum time between ALLOW_WHILE_IDLE alarms when system is not idle.
223 public long ALLOW_WHILE_IDLE_SHORT_TIME = DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME;
225 // Minimum time between ALLOW_WHILE_IDLE alarms when system is idling.
226 public long ALLOW_WHILE_IDLE_LONG_TIME = DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME;
228 // BroadcastOptions.setTemporaryAppWhitelistDuration() to use for FLAG_ALLOW_WHILE_IDLE.
229 public long ALLOW_WHILE_IDLE_WHITELIST_DURATION
230 = DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION;
232 // Direct alarm listener callback timeout
233 public long LISTENER_TIMEOUT = DEFAULT_LISTENER_TIMEOUT;
235 private ContentResolver mResolver;
236 private final KeyValueListParser mParser = new KeyValueListParser(',');
237 private long mLastAllowWhileIdleWhitelistDuration = -1;
239 public Constants(Handler handler) {
241 updateAllowWhileIdleMinTimeLocked();
242 updateAllowWhileIdleWhitelistDurationLocked();
245 public void start(ContentResolver resolver) {
246 mResolver = resolver;
247 mResolver.registerContentObserver(Settings.Global.getUriFor(
248 Settings.Global.ALARM_MANAGER_CONSTANTS), false, this);
252 public void updateAllowWhileIdleMinTimeLocked() {
253 mAllowWhileIdleMinTime = mPendingIdleUntil != null
254 ? ALLOW_WHILE_IDLE_LONG_TIME : ALLOW_WHILE_IDLE_SHORT_TIME;
257 public void updateAllowWhileIdleWhitelistDurationLocked() {
258 if (mLastAllowWhileIdleWhitelistDuration != ALLOW_WHILE_IDLE_WHITELIST_DURATION) {
259 mLastAllowWhileIdleWhitelistDuration = ALLOW_WHILE_IDLE_WHITELIST_DURATION;
260 BroadcastOptions opts = BroadcastOptions.makeBasic();
261 opts.setTemporaryAppWhitelistDuration(ALLOW_WHILE_IDLE_WHITELIST_DURATION);
262 mIdleOptions = opts.toBundle();
267 public void onChange(boolean selfChange, Uri uri) {
271 private void updateConstants() {
272 synchronized (mLock) {
274 mParser.setString(Settings.Global.getString(mResolver,
275 Settings.Global.ALARM_MANAGER_CONSTANTS));
276 } catch (IllegalArgumentException e) {
277 // Failed to parse the settings string, log this and move on
279 Slog.e(TAG, "Bad device idle settings", e);
282 MIN_FUTURITY = mParser.getLong(KEY_MIN_FUTURITY, DEFAULT_MIN_FUTURITY);
283 MIN_INTERVAL = mParser.getLong(KEY_MIN_INTERVAL, DEFAULT_MIN_INTERVAL);
284 ALLOW_WHILE_IDLE_SHORT_TIME = mParser.getLong(KEY_ALLOW_WHILE_IDLE_SHORT_TIME,
285 DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME);
286 ALLOW_WHILE_IDLE_LONG_TIME = mParser.getLong(KEY_ALLOW_WHILE_IDLE_LONG_TIME,
287 DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME);
288 ALLOW_WHILE_IDLE_WHITELIST_DURATION = mParser.getLong(
289 KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION,
290 DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION);
291 LISTENER_TIMEOUT = mParser.getLong(KEY_LISTENER_TIMEOUT,
292 DEFAULT_LISTENER_TIMEOUT);
294 updateAllowWhileIdleMinTimeLocked();
295 updateAllowWhileIdleWhitelistDurationLocked();
299 void dump(PrintWriter pw) {
300 pw.println(" Settings:");
302 pw.print(" "); pw.print(KEY_MIN_FUTURITY); pw.print("=");
303 TimeUtils.formatDuration(MIN_FUTURITY, pw);
306 pw.print(" "); pw.print(KEY_MIN_INTERVAL); pw.print("=");
307 TimeUtils.formatDuration(MIN_INTERVAL, pw);
310 pw.print(" "); pw.print(KEY_LISTENER_TIMEOUT); pw.print("=");
311 TimeUtils.formatDuration(LISTENER_TIMEOUT, pw);
314 pw.print(" "); pw.print(KEY_ALLOW_WHILE_IDLE_SHORT_TIME); pw.print("=");
315 TimeUtils.formatDuration(ALLOW_WHILE_IDLE_SHORT_TIME, pw);
318 pw.print(" "); pw.print(KEY_ALLOW_WHILE_IDLE_LONG_TIME); pw.print("=");
319 TimeUtils.formatDuration(ALLOW_WHILE_IDLE_LONG_TIME, pw);
322 pw.print(" "); pw.print(KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION); pw.print("=");
323 TimeUtils.formatDuration(ALLOW_WHILE_IDLE_WHITELIST_DURATION, pw);
328 final Constants mConstants;
330 // Alarm delivery ordering bookkeeping
331 static final int PRIO_TICK = 0;
332 static final int PRIO_WAKEUP = 1;
333 static final int PRIO_NORMAL = 2;
335 final class PriorityClass {
340 seq = mCurrentSeq - 1;
341 priority = PRIO_NORMAL;
345 final HashMap<String, PriorityClass> mPriorities = new HashMap<>();
348 static final class WakeupEvent {
351 public String action;
353 public WakeupEvent(long theTime, int theUid, String theAction) {
360 final LinkedList<WakeupEvent> mRecentWakeups = new LinkedList<WakeupEvent>();
361 final long RECENT_WAKEUP_PERIOD = 1000L * 60 * 60 * 24; // one day
364 long start; // These endpoints are always in ELAPSED
366 int flags; // Flags for alarms, such as FLAG_STANDALONE.
368 final ArrayList<Alarm> alarms = new ArrayList<Alarm>();
372 end = Long.MAX_VALUE;
377 start = seed.whenElapsed;
378 end = seed.maxWhenElapsed;
384 return alarms.size();
387 Alarm get(int index) {
388 return alarms.get(index);
391 boolean canHold(long whenElapsed, long maxWhen) {
392 return (end >= whenElapsed) && (start <= maxWhen);
395 boolean add(Alarm alarm) {
396 boolean newStart = false;
397 // narrows the batch if necessary; presumes that canHold(alarm) is true
398 int index = Collections.binarySearch(alarms, alarm, sIncreasingTimeOrder);
400 index = 0 - index - 1;
402 alarms.add(index, alarm);
404 Slog.v(TAG, "Adding " + alarm + " to " + this);
406 if (alarm.whenElapsed > start) {
407 start = alarm.whenElapsed;
410 if (alarm.maxWhenElapsed < end) {
411 end = alarm.maxWhenElapsed;
413 flags |= alarm.flags;
416 Slog.v(TAG, " => now " + this);
421 boolean remove(final PendingIntent operation, final IAlarmListener listener) {
422 if (operation == null && listener == null) {
424 Slog.w(TAG, "requested remove() of null operation",
425 new RuntimeException("here"));
429 boolean didRemove = false;
430 long newStart = 0; // recalculate endpoints as we go
431 long newEnd = Long.MAX_VALUE;
433 for (int i = 0; i < alarms.size(); ) {
434 Alarm alarm = alarms.get(i);
435 if (alarm.matches(operation, listener)) {
438 if (alarm.alarmClock != null) {
439 mNextAlarmClockMayChange = true;
442 if (alarm.whenElapsed > newStart) {
443 newStart = alarm.whenElapsed;
445 if (alarm.maxWhenElapsed < newEnd) {
446 newEnd = alarm.maxWhenElapsed;
448 newFlags |= alarm.flags;
453 // commit the new batch bounds
461 boolean remove(final String packageName) {
462 if (packageName == null) {
464 Slog.w(TAG, "requested remove() of null packageName",
465 new RuntimeException("here"));
469 boolean didRemove = false;
470 long newStart = 0; // recalculate endpoints as we go
471 long newEnd = Long.MAX_VALUE;
473 for (int i = alarms.size()-1; i >= 0; i--) {
474 Alarm alarm = alarms.get(i);
475 if (alarm.matches(packageName)) {
478 if (alarm.alarmClock != null) {
479 mNextAlarmClockMayChange = true;
482 if (alarm.whenElapsed > newStart) {
483 newStart = alarm.whenElapsed;
485 if (alarm.maxWhenElapsed < newEnd) {
486 newEnd = alarm.maxWhenElapsed;
488 newFlags |= alarm.flags;
492 // commit the new batch bounds
500 boolean removeForStopped(final int uid) {
501 boolean didRemove = false;
502 long newStart = 0; // recalculate endpoints as we go
503 long newEnd = Long.MAX_VALUE;
505 for (int i = alarms.size()-1; i >= 0; i--) {
506 Alarm alarm = alarms.get(i);
508 if (alarm.uid == uid && ActivityManagerNative.getDefault().getAppStartMode(
509 uid, alarm.packageName) == ActivityManager.APP_START_MODE_DISABLED) {
512 if (alarm.alarmClock != null) {
513 mNextAlarmClockMayChange = true;
516 if (alarm.whenElapsed > newStart) {
517 newStart = alarm.whenElapsed;
519 if (alarm.maxWhenElapsed < newEnd) {
520 newEnd = alarm.maxWhenElapsed;
522 newFlags |= alarm.flags;
524 } catch (RemoteException e) {
528 // commit the new batch bounds
536 boolean remove(final int userHandle) {
537 boolean didRemove = false;
538 long newStart = 0; // recalculate endpoints as we go
539 long newEnd = Long.MAX_VALUE;
540 for (int i = 0; i < alarms.size(); ) {
541 Alarm alarm = alarms.get(i);
542 if (UserHandle.getUserId(alarm.creatorUid) == userHandle) {
545 if (alarm.alarmClock != null) {
546 mNextAlarmClockMayChange = true;
549 if (alarm.whenElapsed > newStart) {
550 newStart = alarm.whenElapsed;
552 if (alarm.maxWhenElapsed < newEnd) {
553 newEnd = alarm.maxWhenElapsed;
559 // commit the new batch bounds
566 boolean hasPackage(final String packageName) {
567 final int N = alarms.size();
568 for (int i = 0; i < N; i++) {
569 Alarm a = alarms.get(i);
570 if (a.matches(packageName)) {
577 boolean hasWakeups() {
578 final int N = alarms.size();
579 for (int i = 0; i < N; i++) {
580 Alarm a = alarms.get(i);
581 // non-wakeup alarms are types 1 and 3, i.e. have the low bit set
582 if ((a.type & TYPE_NONWAKEUP_MASK) == 0) {
590 public String toString() {
591 StringBuilder b = new StringBuilder(40);
592 b.append("Batch{"); b.append(Integer.toHexString(this.hashCode()));
593 b.append(" num="); b.append(size());
594 b.append(" start="); b.append(start);
595 b.append(" end="); b.append(end);
597 b.append(" flgs=0x");
598 b.append(Integer.toHexString(flags));
605 static class BatchTimeOrder implements Comparator<Batch> {
606 public int compare(Batch b1, Batch b2) {
607 long when1 = b1.start;
608 long when2 = b2.start;
619 final Comparator<Alarm> mAlarmDispatchComparator = new Comparator<Alarm>() {
621 public int compare(Alarm lhs, Alarm rhs) {
622 // priority class trumps everything. TICK < WAKEUP < NORMAL
623 if (lhs.priorityClass.priority < rhs.priorityClass.priority) {
625 } else if (lhs.priorityClass.priority > rhs.priorityClass.priority) {
629 // within each class, sort by nominal delivery time
630 if (lhs.whenElapsed < rhs.whenElapsed) {
632 } else if (lhs.whenElapsed > rhs.whenElapsed) {
636 // same priority class + same target delivery time
641 void calculateDeliveryPriorities(ArrayList<Alarm> alarms) {
642 final int N = alarms.size();
643 for (int i = 0; i < N; i++) {
644 Alarm a = alarms.get(i);
647 if (a.operation != null
648 && Intent.ACTION_TIME_TICK.equals(a.operation.getIntent().getAction())) {
649 alarmPrio = PRIO_TICK;
650 } else if (a.wakeup) {
651 alarmPrio = PRIO_WAKEUP;
653 alarmPrio = PRIO_NORMAL;
656 PriorityClass packagePrio = a.priorityClass;
657 String alarmPackage = (a.operation != null)
658 ? a.operation.getCreatorPackage()
660 if (packagePrio == null) packagePrio = mPriorities.get(alarmPackage);
661 if (packagePrio == null) {
662 packagePrio = a.priorityClass = new PriorityClass(); // lowest prio & stale sequence
663 mPriorities.put(alarmPackage, packagePrio);
665 a.priorityClass = packagePrio;
667 if (packagePrio.seq != mCurrentSeq) {
668 // first alarm we've seen in the current delivery generation from this package
669 packagePrio.priority = alarmPrio;
670 packagePrio.seq = mCurrentSeq;
672 // Multiple alarms from this package being delivered in this generation;
673 // bump the package's delivery class if it's warranted.
674 // TICK < WAKEUP < NORMAL
675 if (alarmPrio < packagePrio.priority) {
676 packagePrio.priority = alarmPrio;
682 // minimum recurrence period or alarm futurity for us to be able to fuzz it
683 static final long MIN_FUZZABLE_INTERVAL = 10000;
684 static final BatchTimeOrder sBatchOrder = new BatchTimeOrder();
685 final ArrayList<Batch> mAlarmBatches = new ArrayList<>();
687 // set to null if in idle mode; while in this mode, any alarms we don't want
688 // to run during this time are placed in mPendingWhileIdleAlarms
689 Alarm mPendingIdleUntil = null;
690 Alarm mNextWakeFromIdle = null;
691 ArrayList<Alarm> mPendingWhileIdleAlarms = new ArrayList<>();
693 public AlarmManagerService(Context context) {
695 mConstants = new Constants(mHandler);
698 static long convertToElapsed(long when, int type) {
699 final boolean isRtc = (type == RTC || type == RTC_WAKEUP);
701 when -= System.currentTimeMillis() - SystemClock.elapsedRealtime();
706 // Apply a heuristic to { recurrence interval, futurity of the trigger time } to
707 // calculate the end of our nominal delivery window for the alarm.
708 static long maxTriggerTime(long now, long triggerAtTime, long interval) {
709 // Current heuristic: batchable window is 75% of either the recurrence interval
710 // [for a periodic alarm] or of the time from now to the desired delivery time,
711 // with a minimum delay/interval of 10 seconds, under which we will simply not
713 long futurity = (interval == 0)
714 ? (triggerAtTime - now)
716 if (futurity < MIN_FUZZABLE_INTERVAL) {
719 return triggerAtTime + (long)(.75 * futurity);
722 // returns true if the batch was added at the head
723 static boolean addBatchLocked(ArrayList<Batch> list, Batch newBatch) {
724 int index = Collections.binarySearch(list, newBatch, sBatchOrder);
726 index = 0 - index - 1;
728 list.add(index, newBatch);
732 // Return the index of the matching batch, or -1 if none found.
733 int attemptCoalesceLocked(long whenElapsed, long maxWhen) {
734 final int N = mAlarmBatches.size();
735 for (int i = 0; i < N; i++) {
736 Batch b = mAlarmBatches.get(i);
737 if ((b.flags&AlarmManager.FLAG_STANDALONE) == 0 && b.canHold(whenElapsed, maxWhen)) {
744 // The RTC clock has moved arbitrarily, so we need to recalculate all the batching
745 void rebatchAllAlarms() {
746 synchronized (mLock) {
747 rebatchAllAlarmsLocked(true);
751 void rebatchAllAlarmsLocked(boolean doValidate) {
752 ArrayList<Batch> oldSet = (ArrayList<Batch>) mAlarmBatches.clone();
753 mAlarmBatches.clear();
754 Alarm oldPendingIdleUntil = mPendingIdleUntil;
755 final long nowElapsed = SystemClock.elapsedRealtime();
756 final int oldBatches = oldSet.size();
757 for (int batchNum = 0; batchNum < oldBatches; batchNum++) {
758 Batch batch = oldSet.get(batchNum);
759 final int N = batch.size();
760 for (int i = 0; i < N; i++) {
761 reAddAlarmLocked(batch.get(i), nowElapsed, doValidate);
764 if (oldPendingIdleUntil != null && oldPendingIdleUntil != mPendingIdleUntil) {
765 Slog.wtf(TAG, "Rebatching: idle until changed from " + oldPendingIdleUntil
766 + " to " + mPendingIdleUntil);
767 if (mPendingIdleUntil == null) {
768 // Somehow we lost this... we need to restore all of the pending alarms.
769 restorePendingWhileIdleAlarmsLocked();
772 rescheduleKernelAlarmsLocked();
773 updateNextAlarmClockLocked();
776 void reAddAlarmLocked(Alarm a, long nowElapsed, boolean doValidate) {
778 long whenElapsed = convertToElapsed(a.when, a.type);
779 final long maxElapsed;
780 if (a.windowLength == AlarmManager.WINDOW_EXACT) {
782 maxElapsed = whenElapsed;
784 // Not exact. Preserve any explicit window, otherwise recalculate
785 // the window based on the alarm's new futurity. Note that this
786 // reflects a policy of preferring timely to deferred delivery.
787 maxElapsed = (a.windowLength > 0)
788 ? (whenElapsed + a.windowLength)
789 : maxTriggerTime(nowElapsed, whenElapsed, a.repeatInterval);
791 a.whenElapsed = whenElapsed;
792 a.maxWhenElapsed = maxElapsed;
793 setImplLocked(a, true, doValidate);
796 void restorePendingWhileIdleAlarmsLocked() {
797 if (RECORD_DEVICE_IDLE_ALARMS) {
798 IdleDispatchEntry ent = new IdleDispatchEntry();
800 ent.pkg = "FINISH IDLE";
801 ent.elapsedRealtime = SystemClock.elapsedRealtime();
802 mAllowWhileIdleDispatches.add(ent);
805 // Bring pending alarms back into the main list.
806 if (mPendingWhileIdleAlarms.size() > 0) {
807 ArrayList<Alarm> alarms = mPendingWhileIdleAlarms;
808 mPendingWhileIdleAlarms = new ArrayList<>();
809 final long nowElapsed = SystemClock.elapsedRealtime();
810 for (int i=alarms.size() - 1; i >= 0; i--) {
811 Alarm a = alarms.get(i);
812 reAddAlarmLocked(a, nowElapsed, false);
816 // Make sure we are using the correct ALLOW_WHILE_IDLE min time.
817 mConstants.updateAllowWhileIdleMinTimeLocked();
819 // Reschedule everything.
820 rescheduleKernelAlarmsLocked();
821 updateNextAlarmClockLocked();
823 // And send a TIME_TICK right now, since it is important to get the UI updated.
825 mTimeTickSender.send();
826 } catch (PendingIntent.CanceledException e) {
830 static final class InFlight {
831 final PendingIntent mPendingIntent;
832 final IBinder mListener;
833 final WorkSource mWorkSource;
836 final BroadcastStats mBroadcastStats;
837 final FilterStats mFilterStats;
838 final int mAlarmType;
840 InFlight(AlarmManagerService service, PendingIntent pendingIntent, IAlarmListener listener,
841 WorkSource workSource, int uid, String alarmPkg, int alarmType, String tag,
843 mPendingIntent = pendingIntent;
844 mListener = listener != null ? listener.asBinder() : null;
845 mWorkSource = workSource;
848 mBroadcastStats = (pendingIntent != null)
849 ? service.getStatsLocked(pendingIntent)
850 : service.getStatsLocked(uid, alarmPkg);
851 FilterStats fs = mBroadcastStats.filterStats.get(mTag);
853 fs = new FilterStats(mBroadcastStats, mTag);
854 mBroadcastStats.filterStats.put(mTag, fs);
856 fs.lastTime = nowELAPSED;
858 mAlarmType = alarmType;
862 static final class FilterStats {
863 final BroadcastStats mBroadcastStats;
873 FilterStats(BroadcastStats broadcastStats, String tag) {
874 mBroadcastStats = broadcastStats;
879 static final class BroadcastStats {
881 final String mPackageName;
888 final ArrayMap<String, FilterStats> filterStats = new ArrayMap<String, FilterStats>();
890 BroadcastStats(int uid, String packageName) {
892 mPackageName = packageName;
896 final SparseArray<ArrayMap<String, BroadcastStats>> mBroadcastStats
897 = new SparseArray<ArrayMap<String, BroadcastStats>>();
899 int mNumDelayedAlarms = 0;
900 long mTotalDelayTime = 0;
901 long mMaxDelayTime = 0;
904 public void onStart() {
905 mNativeData = init();
906 mNextWakeup = mNextNonWakeup = 0;
908 // We have to set current TimeZone info to kernel
909 // because kernel doesn't keep this after reboot
910 setTimeZoneImpl(SystemProperties.get(TIMEZONE_PROPERTY));
912 PowerManager pm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE);
913 mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*alarm*");
915 mTimeTickSender = PendingIntent.getBroadcastAsUser(getContext(), 0,
916 new Intent(Intent.ACTION_TIME_TICK).addFlags(
917 Intent.FLAG_RECEIVER_REGISTERED_ONLY
918 | Intent.FLAG_RECEIVER_FOREGROUND), 0,
920 Intent intent = new Intent(Intent.ACTION_DATE_CHANGED);
921 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
922 mDateChangeSender = PendingIntent.getBroadcastAsUser(getContext(), 0, intent,
923 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT, UserHandle.ALL);
925 // now that we have initied the driver schedule the alarm
926 mClockReceiver = new ClockReceiver();
927 mClockReceiver.scheduleTimeTickEvent();
928 mClockReceiver.scheduleDateChangedEvent();
929 mInteractiveStateReceiver = new InteractiveStateReceiver();
930 mUninstallReceiver = new UninstallReceiver();
932 if (mNativeData != 0) {
933 AlarmThread waitThread = new AlarmThread();
936 Slog.w(TAG, "Failed to open alarm driver. Falling back to a handler.");
940 ActivityManagerNative.getDefault().registerUidObserver(new UidObserver(),
941 ActivityManager.UID_OBSERVER_IDLE);
942 } catch (RemoteException e) {
943 // ignored; both services live in system_server
946 publishBinderService(Context.ALARM_SERVICE, mService);
947 publishLocalService(LocalService.class, new LocalService());
951 public void onBootPhase(int phase) {
952 if (phase == PHASE_SYSTEM_SERVICES_READY) {
953 mConstants.start(getContext().getContentResolver());
954 mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
955 mLocalDeviceIdleController
956 = LocalServices.getService(DeviceIdleController.LocalService.class);
961 protected void finalize() throws Throwable {
969 void setTimeZoneImpl(String tz) {
970 if (TextUtils.isEmpty(tz)) {
974 TimeZone zone = TimeZone.getTimeZone(tz);
975 // Prevent reentrant calls from stepping on each other when writing
976 // the time zone property
977 boolean timeZoneWasChanged = false;
978 synchronized (this) {
979 String current = SystemProperties.get(TIMEZONE_PROPERTY);
980 if (current == null || !current.equals(zone.getID())) {
982 Slog.v(TAG, "timezone changed: " + current + ", new=" + zone.getID());
984 timeZoneWasChanged = true;
985 SystemProperties.set(TIMEZONE_PROPERTY, zone.getID());
988 // Update the kernel timezone information
989 // Kernel tracks time offsets as 'minutes west of GMT'
990 int gmtOffset = zone.getOffset(System.currentTimeMillis());
991 setKernelTimezone(mNativeData, -(gmtOffset / 60000));
994 TimeZone.setDefault(null);
996 if (timeZoneWasChanged) {
997 Intent intent = new Intent(Intent.ACTION_TIMEZONE_CHANGED);
998 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
999 intent.putExtra("time-zone", zone.getID());
1000 getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
1004 void removeImpl(PendingIntent operation) {
1005 if (operation == null) {
1008 synchronized (mLock) {
1009 removeLocked(operation, null);
1013 void setImpl(int type, long triggerAtTime, long windowLength, long interval,
1014 PendingIntent operation, IAlarmListener directReceiver, String listenerTag,
1015 int flags, WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock,
1016 int callingUid, String callingPackage) {
1017 // must be *either* PendingIntent or AlarmReceiver, but not both
1018 if ((operation == null && directReceiver == null)
1019 || (operation != null && directReceiver != null)) {
1020 Slog.w(TAG, "Alarms must either supply a PendingIntent or an AlarmReceiver");
1021 // NB: previous releases failed silently here, so we are continuing to do the same
1022 // rather than throw an IllegalArgumentException.
1026 // Sanity check the window length. This will catch people mistakenly
1027 // trying to pass an end-of-window timestamp rather than a duration.
1028 if (windowLength > AlarmManager.INTERVAL_HALF_DAY) {
1029 Slog.w(TAG, "Window length " + windowLength
1030 + "ms suspiciously long; limiting to 1 hour");
1031 windowLength = AlarmManager.INTERVAL_HOUR;
1034 // Sanity check the recurrence interval. This will catch people who supply
1035 // seconds when the API expects milliseconds.
1036 final long minInterval = mConstants.MIN_INTERVAL;
1037 if (interval > 0 && interval < minInterval) {
1038 Slog.w(TAG, "Suspiciously short interval " + interval
1039 + " millis; expanding to " + (minInterval/1000)
1041 interval = minInterval;
1044 if (type < RTC_WAKEUP || type > ELAPSED_REALTIME) {
1045 throw new IllegalArgumentException("Invalid alarm type " + type);
1048 if (triggerAtTime < 0) {
1049 final long what = Binder.getCallingPid();
1050 Slog.w(TAG, "Invalid alarm trigger time! " + triggerAtTime + " from uid=" + callingUid
1055 final long nowElapsed = SystemClock.elapsedRealtime();
1056 final long nominalTrigger = convertToElapsed(triggerAtTime, type);
1057 // Try to prevent spamming by making sure we aren't firing alarms in the immediate future
1058 final long minTrigger = nowElapsed + mConstants.MIN_FUTURITY;
1059 final long triggerElapsed = (nominalTrigger > minTrigger) ? nominalTrigger : minTrigger;
1061 final long maxElapsed;
1062 if (windowLength == AlarmManager.WINDOW_EXACT) {
1063 maxElapsed = triggerElapsed;
1064 } else if (windowLength < 0) {
1065 maxElapsed = maxTriggerTime(nowElapsed, triggerElapsed, interval);
1066 // Fix this window in place, so that as time approaches we don't collapse it.
1067 windowLength = maxElapsed - triggerElapsed;
1069 maxElapsed = triggerElapsed + windowLength;
1072 synchronized (mLock) {
1074 Slog.v(TAG, "set(" + operation + ") : type=" + type
1075 + " triggerAtTime=" + triggerAtTime + " win=" + windowLength
1076 + " tElapsed=" + triggerElapsed + " maxElapsed=" + maxElapsed
1077 + " interval=" + interval + " flags=0x" + Integer.toHexString(flags));
1079 setImplLocked(type, triggerAtTime, triggerElapsed, windowLength, maxElapsed,
1080 interval, operation, directReceiver, listenerTag, flags, true, workSource,
1081 alarmClock, callingUid, callingPackage);
1085 private void setImplLocked(int type, long when, long whenElapsed, long windowLength,
1086 long maxWhen, long interval, PendingIntent operation, IAlarmListener directReceiver,
1087 String listenerTag, int flags, boolean doValidate, WorkSource workSource,
1088 AlarmManager.AlarmClockInfo alarmClock, int callingUid, String callingPackage) {
1089 Alarm a = new Alarm(type, when, whenElapsed, windowLength, maxWhen, interval,
1090 operation, directReceiver, listenerTag, workSource, flags, alarmClock,
1091 callingUid, callingPackage);
1093 if (ActivityManagerNative.getDefault().getAppStartMode(callingUid, callingPackage)
1094 == ActivityManager.APP_START_MODE_DISABLED) {
1095 Slog.w(TAG, "Not setting alarm from " + callingUid + ":" + a
1096 + " -- package not allowed to start");
1099 } catch (RemoteException e) {
1101 removeLocked(operation, directReceiver);
1102 setImplLocked(a, false, doValidate);
1105 private void setImplLocked(Alarm a, boolean rebatching, boolean doValidate) {
1106 if ((a.flags&AlarmManager.FLAG_IDLE_UNTIL) != 0) {
1107 // This is a special alarm that will put the system into idle until it goes off.
1108 // The caller has given the time they want this to happen at, however we need
1109 // to pull that earlier if there are existing alarms that have requested to
1110 // bring us out of idle at an earlier time.
1111 if (mNextWakeFromIdle != null && a.whenElapsed > mNextWakeFromIdle.whenElapsed) {
1112 a.when = a.whenElapsed = a.maxWhenElapsed = mNextWakeFromIdle.whenElapsed;
1114 // Add fuzz to make the alarm go off some time before the actual desired time.
1115 final long nowElapsed = SystemClock.elapsedRealtime();
1116 final int fuzz = fuzzForDuration(a.whenElapsed-nowElapsed);
1118 if (mRandom == null) {
1119 mRandom = new Random();
1121 final int delta = mRandom.nextInt(fuzz);
1122 a.whenElapsed -= delta;
1124 Slog.d(TAG, "Alarm when: " + a.whenElapsed);
1125 Slog.d(TAG, "Delta until alarm: " + (a.whenElapsed-nowElapsed));
1126 Slog.d(TAG, "Applied fuzz: " + fuzz);
1127 Slog.d(TAG, "Final delta: " + delta);
1128 Slog.d(TAG, "Final when: " + a.whenElapsed);
1130 a.when = a.maxWhenElapsed = a.whenElapsed;
1133 } else if (mPendingIdleUntil != null) {
1134 // We currently have an idle until alarm scheduled; if the new alarm has
1135 // not explicitly stated it wants to run while idle, then put it on hold.
1136 if ((a.flags&(AlarmManager.FLAG_ALLOW_WHILE_IDLE
1137 | AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED
1138 | AlarmManager.FLAG_WAKE_FROM_IDLE))
1140 mPendingWhileIdleAlarms.add(a);
1145 if (RECORD_DEVICE_IDLE_ALARMS) {
1146 if ((a.flags & AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) {
1147 IdleDispatchEntry ent = new IdleDispatchEntry();
1149 ent.pkg = a.operation.getCreatorPackage();
1150 ent.tag = a.operation.getTag("");
1152 ent.elapsedRealtime = SystemClock.elapsedRealtime();
1153 ent.argRealtime = a.whenElapsed;
1154 mAllowWhileIdleDispatches.add(ent);
1158 int whichBatch = ((a.flags&AlarmManager.FLAG_STANDALONE) != 0)
1159 ? -1 : attemptCoalesceLocked(a.whenElapsed, a.maxWhenElapsed);
1160 if (whichBatch < 0) {
1161 Batch batch = new Batch(a);
1162 addBatchLocked(mAlarmBatches, batch);
1164 Batch batch = mAlarmBatches.get(whichBatch);
1166 // The start time of this batch advanced, so batch ordering may
1167 // have just been broken. Move it to where it now belongs.
1168 mAlarmBatches.remove(whichBatch);
1169 addBatchLocked(mAlarmBatches, batch);
1173 if (a.alarmClock != null) {
1174 mNextAlarmClockMayChange = true;
1177 boolean needRebatch = false;
1179 if ((a.flags&AlarmManager.FLAG_IDLE_UNTIL) != 0) {
1180 if (RECORD_DEVICE_IDLE_ALARMS) {
1181 if (mPendingIdleUntil == null) {
1182 IdleDispatchEntry ent = new IdleDispatchEntry();
1184 ent.pkg = "START IDLE";
1185 ent.elapsedRealtime = SystemClock.elapsedRealtime();
1186 mAllowWhileIdleDispatches.add(ent);
1189 mPendingIdleUntil = a;
1190 mConstants.updateAllowWhileIdleMinTimeLocked();
1192 } else if ((a.flags&AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) {
1193 if (mNextWakeFromIdle == null || mNextWakeFromIdle.whenElapsed > a.whenElapsed) {
1194 mNextWakeFromIdle = a;
1195 // If this wake from idle is earlier than whatever was previously scheduled,
1196 // and we are currently idling, then we need to rebatch alarms in case the idle
1197 // until time needs to be updated.
1198 if (mPendingIdleUntil != null) {
1205 if (DEBUG_VALIDATE) {
1206 if (doValidate && !validateConsistencyLocked()) {
1207 Slog.v(TAG, "Tipping-point operation: type=" + a.type + " when=" + a.when
1208 + " when(hex)=" + Long.toHexString(a.when)
1209 + " whenElapsed=" + a.whenElapsed
1210 + " maxWhenElapsed=" + a.maxWhenElapsed
1211 + " interval=" + a.repeatInterval + " op=" + a.operation
1212 + " flags=0x" + Integer.toHexString(a.flags));
1213 rebatchAllAlarmsLocked(false);
1214 needRebatch = false;
1219 rebatchAllAlarmsLocked(false);
1222 rescheduleKernelAlarmsLocked();
1223 updateNextAlarmClockLocked();
1227 private final IBinder mService = new IAlarmManager.Stub() {
1229 public void set(String callingPackage,
1230 int type, long triggerAtTime, long windowLength, long interval, int flags,
1231 PendingIntent operation, IAlarmListener directReceiver, String listenerTag,
1232 WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock) {
1233 final int callingUid = Binder.getCallingUid();
1235 // make sure the caller is not lying about which package should be blamed for
1236 // wakelock time spent in alarm delivery
1237 mAppOps.checkPackage(callingUid, callingPackage);
1239 // Repeating alarms must use PendingIntent, not direct listener
1240 if (interval != 0) {
1241 if (directReceiver != null) {
1242 throw new IllegalArgumentException("Repeating alarms cannot use AlarmReceivers");
1246 if (workSource != null) {
1247 getContext().enforcePermission(
1248 android.Manifest.permission.UPDATE_DEVICE_STATS,
1249 Binder.getCallingPid(), callingUid, "AlarmManager.set");
1252 // No incoming callers can request either WAKE_FROM_IDLE or
1253 // ALLOW_WHILE_IDLE_UNRESTRICTED -- we will apply those later as appropriate.
1254 flags &= ~(AlarmManager.FLAG_WAKE_FROM_IDLE
1255 | AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED);
1257 // Only the system can use FLAG_IDLE_UNTIL -- this is used to tell the alarm
1258 // manager when to come out of idle mode, which is only for DeviceIdleController.
1259 if (callingUid != Process.SYSTEM_UID) {
1260 flags &= ~AlarmManager.FLAG_IDLE_UNTIL;
1263 // If this is an exact time alarm, then it can't be batched with other alarms.
1264 if (windowLength == AlarmManager.WINDOW_EXACT) {
1265 flags |= AlarmManager.FLAG_STANDALONE;
1268 // If this alarm is for an alarm clock, then it must be standalone and we will
1269 // use it to wake early from idle if needed.
1270 if (alarmClock != null) {
1271 flags |= AlarmManager.FLAG_WAKE_FROM_IDLE | AlarmManager.FLAG_STANDALONE;
1273 // If the caller is a core system component or on the user's whitelist, and not calling
1274 // to do work on behalf of someone else, then always set ALLOW_WHILE_IDLE_UNRESTRICTED.
1275 // This means we will allow these alarms to go off as normal even while idle, with no
1276 // timing restrictions.
1277 } else if (workSource == null && (callingUid < Process.FIRST_APPLICATION_UID
1278 || Arrays.binarySearch(mDeviceIdleUserWhitelist,
1279 UserHandle.getAppId(callingUid)) >= 0)) {
1280 flags |= AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
1281 flags &= ~AlarmManager.FLAG_ALLOW_WHILE_IDLE;
1284 setImpl(type, triggerAtTime, windowLength, interval, operation, directReceiver,
1285 listenerTag, flags, workSource, alarmClock, callingUid, callingPackage);
1289 public boolean setTime(long millis) {
1290 getContext().enforceCallingOrSelfPermission(
1291 "android.permission.SET_TIME",
1294 if (mNativeData == 0) {
1295 Slog.w(TAG, "Not setting time since no alarm driver is available.");
1299 synchronized (mLock) {
1300 return setKernelTime(mNativeData, millis) == 0;
1305 public void setTimeZone(String tz) {
1306 getContext().enforceCallingOrSelfPermission(
1307 "android.permission.SET_TIME_ZONE",
1310 final long oldId = Binder.clearCallingIdentity();
1312 setTimeZoneImpl(tz);
1314 Binder.restoreCallingIdentity(oldId);
1319 public void remove(PendingIntent operation, IAlarmListener listener) {
1320 if (operation == null && listener == null) {
1321 Slog.w(TAG, "remove() with no intent or listener");
1325 synchronized (mLock) {
1326 removeLocked(operation, listener);
1331 public long getNextWakeFromIdleTime() {
1332 return getNextWakeFromIdleTimeImpl();
1336 public AlarmManager.AlarmClockInfo getNextAlarmClock(int userId) {
1337 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
1338 Binder.getCallingUid(), userId, false /* allowAll */, false /* requireFull */,
1339 "getNextAlarmClock", null);
1341 return getNextAlarmClockImpl(userId);
1345 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1346 if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
1347 != PackageManager.PERMISSION_GRANTED) {
1348 pw.println("Permission Denial: can't dump AlarmManager from from pid="
1349 + Binder.getCallingPid()
1350 + ", uid=" + Binder.getCallingUid());
1358 public final class LocalService {
1359 public void setDeviceIdleUserWhitelist(int[] appids) {
1360 setDeviceIdleUserWhitelistImpl(appids);
1364 void dumpImpl(PrintWriter pw) {
1365 synchronized (mLock) {
1366 pw.println("Current Alarm Manager state:");
1367 mConstants.dump(pw);
1370 final long nowRTC = System.currentTimeMillis();
1371 final long nowELAPSED = SystemClock.elapsedRealtime();
1372 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
1374 pw.print(" nowRTC="); pw.print(nowRTC);
1375 pw.print("="); pw.print(sdf.format(new Date(nowRTC)));
1376 pw.print(" nowELAPSED="); pw.print(nowELAPSED);
1378 pw.print(" mLastTimeChangeClockTime="); pw.print(mLastTimeChangeClockTime);
1379 pw.print("="); pw.println(sdf.format(new Date(mLastTimeChangeClockTime)));
1380 pw.print(" mLastTimeChangeRealtime=");
1381 TimeUtils.formatDuration(mLastTimeChangeRealtime, pw);
1383 if (!mInteractive) {
1384 pw.print(" Time since non-interactive: ");
1385 TimeUtils.formatDuration(nowELAPSED - mNonInteractiveStartTime, pw);
1387 pw.print(" Max wakeup delay: ");
1388 TimeUtils.formatDuration(currentNonWakeupFuzzLocked(nowELAPSED), pw);
1390 pw.print(" Time since last dispatch: ");
1391 TimeUtils.formatDuration(nowELAPSED - mLastAlarmDeliveryTime, pw);
1393 pw.print(" Next non-wakeup delivery time: ");
1394 TimeUtils.formatDuration(nowELAPSED - mNextNonWakeupDeliveryTime, pw);
1398 long nextWakeupRTC = mNextWakeup + (nowRTC - nowELAPSED);
1399 long nextNonWakeupRTC = mNextNonWakeup + (nowRTC - nowELAPSED);
1400 pw.print(" Next non-wakeup alarm: ");
1401 TimeUtils.formatDuration(mNextNonWakeup, nowELAPSED, pw);
1402 pw.print(" = "); pw.println(sdf.format(new Date(nextNonWakeupRTC)));
1403 pw.print(" Next wakeup: "); TimeUtils.formatDuration(mNextWakeup, nowELAPSED, pw);
1404 pw.print(" = "); pw.println(sdf.format(new Date(nextWakeupRTC)));
1405 pw.print(" Last wakeup: "); TimeUtils.formatDuration(mLastWakeup, nowELAPSED, pw);
1406 pw.print(" set at "); TimeUtils.formatDuration(mLastWakeupSet, nowELAPSED, pw);
1408 pw.print(" Num time change events: "); pw.println(mNumTimeChanged);
1409 pw.println(" mDeviceIdleUserWhitelist=" + Arrays.toString(mDeviceIdleUserWhitelist));
1412 pw.println(" Next alarm clock information: ");
1413 final TreeSet<Integer> users = new TreeSet<>();
1414 for (int i = 0; i < mNextAlarmClockForUser.size(); i++) {
1415 users.add(mNextAlarmClockForUser.keyAt(i));
1417 for (int i = 0; i < mPendingSendNextAlarmClockChangedForUser.size(); i++) {
1418 users.add(mPendingSendNextAlarmClockChangedForUser.keyAt(i));
1420 for (int user : users) {
1421 final AlarmManager.AlarmClockInfo next = mNextAlarmClockForUser.get(user);
1422 final long time = next != null ? next.getTriggerTime() : 0;
1423 final boolean pendingSend = mPendingSendNextAlarmClockChangedForUser.get(user);
1424 pw.print(" user:"); pw.print(user);
1425 pw.print(" pendingSend:"); pw.print(pendingSend);
1426 pw.print(" time:"); pw.print(time);
1428 pw.print(" = "); pw.print(sdf.format(new Date(time)));
1429 pw.print(" = "); TimeUtils.formatDuration(time, nowRTC, pw);
1433 if (mAlarmBatches.size() > 0) {
1435 pw.print(" Pending alarm batches: ");
1436 pw.println(mAlarmBatches.size());
1437 for (Batch b : mAlarmBatches) {
1438 pw.print(b); pw.println(':');
1439 dumpAlarmList(pw, b.alarms, " ", nowELAPSED, nowRTC, sdf);
1442 if (mPendingIdleUntil != null || mPendingWhileIdleAlarms.size() > 0) {
1444 pw.println(" Idle mode state:");
1445 pw.print(" Idling until: ");
1446 if (mPendingIdleUntil != null) {
1447 pw.println(mPendingIdleUntil);
1448 mPendingIdleUntil.dump(pw, " ", nowRTC, nowELAPSED, sdf);
1452 pw.println(" Pending alarms:");
1453 dumpAlarmList(pw, mPendingWhileIdleAlarms, " ", nowELAPSED, nowRTC, sdf);
1455 if (mNextWakeFromIdle != null) {
1457 pw.print(" Next wake from idle: "); pw.println(mNextWakeFromIdle);
1458 mNextWakeFromIdle.dump(pw, " ", nowRTC, nowELAPSED, sdf);
1462 pw.print(" Past-due non-wakeup alarms: ");
1463 if (mPendingNonWakeupAlarms.size() > 0) {
1464 pw.println(mPendingNonWakeupAlarms.size());
1465 dumpAlarmList(pw, mPendingNonWakeupAlarms, " ", nowELAPSED, nowRTC, sdf);
1467 pw.println("(none)");
1469 pw.print(" Number of delayed alarms: "); pw.print(mNumDelayedAlarms);
1470 pw.print(", total delay time: "); TimeUtils.formatDuration(mTotalDelayTime, pw);
1472 pw.print(" Max delay time: "); TimeUtils.formatDuration(mMaxDelayTime, pw);
1473 pw.print(", max non-interactive time: ");
1474 TimeUtils.formatDuration(mNonInteractiveTime, pw);
1478 pw.print(" Broadcast ref count: "); pw.println(mBroadcastRefCount);
1481 if (mInFlight.size() > 0) {
1482 pw.println("Outstanding deliveries:");
1483 for (int i = 0; i < mInFlight.size(); i++) {
1484 pw.print(" #"); pw.print(i); pw.print(": ");
1485 pw.println(mInFlight.get(i));
1490 pw.print(" mAllowWhileIdleMinTime=");
1491 TimeUtils.formatDuration(mAllowWhileIdleMinTime, pw);
1493 if (mLastAllowWhileIdleDispatch.size() > 0) {
1494 pw.println(" Last allow while idle dispatch times:");
1495 for (int i=0; i<mLastAllowWhileIdleDispatch.size(); i++) {
1497 UserHandle.formatUid(pw, mLastAllowWhileIdleDispatch.keyAt(i));
1499 TimeUtils.formatDuration(mLastAllowWhileIdleDispatch.valueAt(i),
1506 if (mLog.dump(pw, " Recent problems", " ")) {
1510 final FilterStats[] topFilters = new FilterStats[10];
1511 final Comparator<FilterStats> comparator = new Comparator<FilterStats>() {
1513 public int compare(FilterStats lhs, FilterStats rhs) {
1514 if (lhs.aggregateTime < rhs.aggregateTime) {
1516 } else if (lhs.aggregateTime > rhs.aggregateTime) {
1523 for (int iu=0; iu<mBroadcastStats.size(); iu++) {
1524 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(iu);
1525 for (int ip=0; ip<uidStats.size(); ip++) {
1526 BroadcastStats bs = uidStats.valueAt(ip);
1527 for (int is=0; is<bs.filterStats.size(); is++) {
1528 FilterStats fs = bs.filterStats.valueAt(is);
1530 ? Arrays.binarySearch(topFilters, 0, len, fs, comparator) : 0;
1534 if (pos < topFilters.length) {
1535 int copylen = topFilters.length - pos - 1;
1537 System.arraycopy(topFilters, pos, topFilters, pos+1, copylen);
1539 topFilters[pos] = fs;
1540 if (len < topFilters.length) {
1548 pw.println(" Top Alarms:");
1549 for (int i=0; i<len; i++) {
1550 FilterStats fs = topFilters[i];
1552 if (fs.nesting > 0) pw.print("*ACTIVE* ");
1553 TimeUtils.formatDuration(fs.aggregateTime, pw);
1554 pw.print(" running, "); pw.print(fs.numWakeup);
1555 pw.print(" wakeups, "); pw.print(fs.count);
1556 pw.print(" alarms: "); UserHandle.formatUid(pw, fs.mBroadcastStats.mUid);
1557 pw.print(":"); pw.print(fs.mBroadcastStats.mPackageName);
1559 pw.print(" "); pw.print(fs.mTag);
1565 pw.println(" Alarm Stats:");
1566 final ArrayList<FilterStats> tmpFilters = new ArrayList<FilterStats>();
1567 for (int iu=0; iu<mBroadcastStats.size(); iu++) {
1568 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(iu);
1569 for (int ip=0; ip<uidStats.size(); ip++) {
1570 BroadcastStats bs = uidStats.valueAt(ip);
1572 if (bs.nesting > 0) pw.print("*ACTIVE* ");
1573 UserHandle.formatUid(pw, bs.mUid);
1575 pw.print(bs.mPackageName);
1576 pw.print(" "); TimeUtils.formatDuration(bs.aggregateTime, pw);
1577 pw.print(" running, "); pw.print(bs.numWakeup);
1578 pw.println(" wakeups:");
1580 for (int is=0; is<bs.filterStats.size(); is++) {
1581 tmpFilters.add(bs.filterStats.valueAt(is));
1583 Collections.sort(tmpFilters, comparator);
1584 for (int i=0; i<tmpFilters.size(); i++) {
1585 FilterStats fs = tmpFilters.get(i);
1587 if (fs.nesting > 0) pw.print("*ACTIVE* ");
1588 TimeUtils.formatDuration(fs.aggregateTime, pw);
1589 pw.print(" "); pw.print(fs.numWakeup);
1590 pw.print(" wakes " ); pw.print(fs.count);
1591 pw.print(" alarms, last ");
1592 TimeUtils.formatDuration(fs.lastTime, nowELAPSED, pw);
1601 if (RECORD_DEVICE_IDLE_ALARMS) {
1603 pw.println(" Allow while idle dispatches:");
1604 for (int i = 0; i < mAllowWhileIdleDispatches.size(); i++) {
1605 IdleDispatchEntry ent = mAllowWhileIdleDispatches.get(i);
1607 TimeUtils.formatDuration(ent.elapsedRealtime, nowELAPSED, pw);
1609 UserHandle.formatUid(pw, ent.uid);
1611 pw.println(ent.pkg);
1612 if (ent.op != null) {
1617 if (ent.argRealtime != 0) {
1619 TimeUtils.formatDuration(ent.argRealtime, nowELAPSED, pw);
1629 pw.println(" Recent Wakeup History:");
1631 for (WakeupEvent event : mRecentWakeups) {
1632 pw.print(" "); pw.print(sdf.format(new Date(event.when)));
1637 pw.print(event.when - last);
1640 pw.print('|'); pw.print(event.uid);
1641 pw.print('|'); pw.print(event.action);
1649 private void logBatchesLocked(SimpleDateFormat sdf) {
1650 ByteArrayOutputStream bs = new ByteArrayOutputStream(2048);
1651 PrintWriter pw = new PrintWriter(bs);
1652 final long nowRTC = System.currentTimeMillis();
1653 final long nowELAPSED = SystemClock.elapsedRealtime();
1654 final int NZ = mAlarmBatches.size();
1655 for (int iz = 0; iz < NZ; iz++) {
1656 Batch bz = mAlarmBatches.get(iz);
1657 pw.append("Batch "); pw.print(iz); pw.append(": "); pw.println(bz);
1658 dumpAlarmList(pw, bz.alarms, " ", nowELAPSED, nowRTC, sdf);
1660 Slog.v(TAG, bs.toString());
1665 private boolean validateConsistencyLocked() {
1666 if (DEBUG_VALIDATE) {
1667 long lastTime = Long.MIN_VALUE;
1668 final int N = mAlarmBatches.size();
1669 for (int i = 0; i < N; i++) {
1670 Batch b = mAlarmBatches.get(i);
1671 if (b.start >= lastTime) {
1672 // duplicate start times are okay because of standalone batches
1675 Slog.e(TAG, "CONSISTENCY FAILURE: Batch " + i + " is out of order");
1676 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
1677 logBatchesLocked(sdf);
1685 private Batch findFirstWakeupBatchLocked() {
1686 final int N = mAlarmBatches.size();
1687 for (int i = 0; i < N; i++) {
1688 Batch b = mAlarmBatches.get(i);
1689 if (b.hasWakeups()) {
1696 long getNextWakeFromIdleTimeImpl() {
1697 synchronized (mLock) {
1698 return mNextWakeFromIdle != null ? mNextWakeFromIdle.whenElapsed : Long.MAX_VALUE;
1702 void setDeviceIdleUserWhitelistImpl(int[] appids) {
1703 synchronized (mLock) {
1704 mDeviceIdleUserWhitelist = appids;
1708 AlarmManager.AlarmClockInfo getNextAlarmClockImpl(int userId) {
1709 synchronized (mLock) {
1710 return mNextAlarmClockForUser.get(userId);
1715 * Recomputes the next alarm clock for all users.
1717 private void updateNextAlarmClockLocked() {
1718 if (!mNextAlarmClockMayChange) {
1721 mNextAlarmClockMayChange = false;
1723 SparseArray<AlarmManager.AlarmClockInfo> nextForUser = mTmpSparseAlarmClockArray;
1724 nextForUser.clear();
1726 final int N = mAlarmBatches.size();
1727 for (int i = 0; i < N; i++) {
1728 ArrayList<Alarm> alarms = mAlarmBatches.get(i).alarms;
1729 final int M = alarms.size();
1731 for (int j = 0; j < M; j++) {
1732 Alarm a = alarms.get(j);
1733 if (a.alarmClock != null) {
1734 final int userId = UserHandle.getUserId(a.uid);
1735 AlarmManager.AlarmClockInfo current = mNextAlarmClockForUser.get(userId);
1737 if (DEBUG_ALARM_CLOCK) {
1738 Log.v(TAG, "Found AlarmClockInfo " + a.alarmClock + " at " +
1739 formatNextAlarm(getContext(), a.alarmClock, userId) +
1740 " for user " + userId);
1743 // Alarms and batches are sorted by time, no need to compare times here.
1744 if (nextForUser.get(userId) == null) {
1745 nextForUser.put(userId, a.alarmClock);
1746 } else if (a.alarmClock.equals(current)
1747 && current.getTriggerTime() <= nextForUser.get(userId).getTriggerTime()) {
1748 // same/earlier time and it's the one we cited before, so stick with it
1749 nextForUser.put(userId, current);
1755 // Update mNextAlarmForUser with new values.
1756 final int NN = nextForUser.size();
1757 for (int i = 0; i < NN; i++) {
1758 AlarmManager.AlarmClockInfo newAlarm = nextForUser.valueAt(i);
1759 int userId = nextForUser.keyAt(i);
1760 AlarmManager.AlarmClockInfo currentAlarm = mNextAlarmClockForUser.get(userId);
1761 if (!newAlarm.equals(currentAlarm)) {
1762 updateNextAlarmInfoForUserLocked(userId, newAlarm);
1766 // Remove users without any alarm clocks scheduled.
1767 final int NNN = mNextAlarmClockForUser.size();
1768 for (int i = NNN - 1; i >= 0; i--) {
1769 int userId = mNextAlarmClockForUser.keyAt(i);
1770 if (nextForUser.get(userId) == null) {
1771 updateNextAlarmInfoForUserLocked(userId, null);
1776 private void updateNextAlarmInfoForUserLocked(int userId,
1777 AlarmManager.AlarmClockInfo alarmClock) {
1778 if (alarmClock != null) {
1779 if (DEBUG_ALARM_CLOCK) {
1780 Log.v(TAG, "Next AlarmClockInfoForUser(" + userId + "): " +
1781 formatNextAlarm(getContext(), alarmClock, userId));
1783 mNextAlarmClockForUser.put(userId, alarmClock);
1785 if (DEBUG_ALARM_CLOCK) {
1786 Log.v(TAG, "Next AlarmClockInfoForUser(" + userId + "): None");
1788 mNextAlarmClockForUser.remove(userId);
1791 mPendingSendNextAlarmClockChangedForUser.put(userId, true);
1792 mHandler.removeMessages(AlarmHandler.SEND_NEXT_ALARM_CLOCK_CHANGED);
1793 mHandler.sendEmptyMessage(AlarmHandler.SEND_NEXT_ALARM_CLOCK_CHANGED);
1797 * Updates NEXT_ALARM_FORMATTED and sends NEXT_ALARM_CLOCK_CHANGED_INTENT for all users
1798 * for which alarm clocks have changed since the last call to this.
1800 * Do not call with a lock held. Only call from mHandler's thread.
1802 * @see AlarmHandler#SEND_NEXT_ALARM_CLOCK_CHANGED
1804 private void sendNextAlarmClockChanged() {
1805 SparseArray<AlarmManager.AlarmClockInfo> pendingUsers = mHandlerSparseAlarmClockArray;
1806 pendingUsers.clear();
1808 synchronized (mLock) {
1809 final int N = mPendingSendNextAlarmClockChangedForUser.size();
1810 for (int i = 0; i < N; i++) {
1811 int userId = mPendingSendNextAlarmClockChangedForUser.keyAt(i);
1812 pendingUsers.append(userId, mNextAlarmClockForUser.get(userId));
1814 mPendingSendNextAlarmClockChangedForUser.clear();
1817 final int N = pendingUsers.size();
1818 for (int i = 0; i < N; i++) {
1819 int userId = pendingUsers.keyAt(i);
1820 AlarmManager.AlarmClockInfo alarmClock = pendingUsers.valueAt(i);
1821 Settings.System.putStringForUser(getContext().getContentResolver(),
1822 Settings.System.NEXT_ALARM_FORMATTED,
1823 formatNextAlarm(getContext(), alarmClock, userId),
1826 getContext().sendBroadcastAsUser(NEXT_ALARM_CLOCK_CHANGED_INTENT,
1827 new UserHandle(userId));
1832 * Formats an alarm like platform/packages/apps/DeskClock used to.
1834 private static String formatNextAlarm(final Context context, AlarmManager.AlarmClockInfo info,
1836 String skeleton = DateFormat.is24HourFormat(context, userId) ? "EHm" : "Ehma";
1837 String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton);
1838 return (info == null) ? "" :
1839 DateFormat.format(pattern, info.getTriggerTime()).toString();
1842 void rescheduleKernelAlarmsLocked() {
1843 // Schedule the next upcoming wakeup alarm. If there is a deliverable batch
1844 // prior to that which contains no wakeups, we schedule that as well.
1845 long nextNonWakeup = 0;
1846 if (mAlarmBatches.size() > 0) {
1847 final Batch firstWakeup = findFirstWakeupBatchLocked();
1848 final Batch firstBatch = mAlarmBatches.get(0);
1849 if (firstWakeup != null && mNextWakeup != firstWakeup.start) {
1850 mNextWakeup = firstWakeup.start;
1851 mLastWakeupSet = SystemClock.elapsedRealtime();
1852 setLocked(ELAPSED_REALTIME_WAKEUP, firstWakeup.start);
1854 if (firstBatch != firstWakeup) {
1855 nextNonWakeup = firstBatch.start;
1858 if (mPendingNonWakeupAlarms.size() > 0) {
1859 if (nextNonWakeup == 0 || mNextNonWakeupDeliveryTime < nextNonWakeup) {
1860 nextNonWakeup = mNextNonWakeupDeliveryTime;
1863 if (nextNonWakeup != 0 && mNextNonWakeup != nextNonWakeup) {
1864 mNextNonWakeup = nextNonWakeup;
1865 setLocked(ELAPSED_REALTIME, nextNonWakeup);
1869 private void removeLocked(PendingIntent operation, IAlarmListener directReceiver) {
1870 boolean didRemove = false;
1871 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
1872 Batch b = mAlarmBatches.get(i);
1873 didRemove |= b.remove(operation, directReceiver);
1874 if (b.size() == 0) {
1875 mAlarmBatches.remove(i);
1878 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
1879 if (mPendingWhileIdleAlarms.get(i).matches(operation, directReceiver)) {
1880 // Don't set didRemove, since this doesn't impact the scheduled alarms.
1881 mPendingWhileIdleAlarms.remove(i);
1887 Slog.v(TAG, "remove(operation) changed bounds; rebatching");
1889 boolean restorePending = false;
1890 if (mPendingIdleUntil != null && mPendingIdleUntil.matches(operation, directReceiver)) {
1891 mPendingIdleUntil = null;
1892 restorePending = true;
1894 if (mNextWakeFromIdle != null && mNextWakeFromIdle.matches(operation, directReceiver)) {
1895 mNextWakeFromIdle = null;
1897 rebatchAllAlarmsLocked(true);
1898 if (restorePending) {
1899 restorePendingWhileIdleAlarmsLocked();
1901 updateNextAlarmClockLocked();
1905 void removeLocked(String packageName) {
1906 boolean didRemove = false;
1907 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
1908 Batch b = mAlarmBatches.get(i);
1909 didRemove |= b.remove(packageName);
1910 if (b.size() == 0) {
1911 mAlarmBatches.remove(i);
1914 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
1915 final Alarm a = mPendingWhileIdleAlarms.get(i);
1916 if (a.matches(packageName)) {
1917 // Don't set didRemove, since this doesn't impact the scheduled alarms.
1918 mPendingWhileIdleAlarms.remove(i);
1924 Slog.v(TAG, "remove(package) changed bounds; rebatching");
1926 rebatchAllAlarmsLocked(true);
1927 rescheduleKernelAlarmsLocked();
1928 updateNextAlarmClockLocked();
1932 void removeForStoppedLocked(int uid) {
1933 boolean didRemove = false;
1934 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
1935 Batch b = mAlarmBatches.get(i);
1936 didRemove |= b.removeForStopped(uid);
1937 if (b.size() == 0) {
1938 mAlarmBatches.remove(i);
1941 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
1942 final Alarm a = mPendingWhileIdleAlarms.get(i);
1944 if (a.uid == uid && ActivityManagerNative.getDefault().getAppStartMode(
1945 uid, a.packageName) == ActivityManager.APP_START_MODE_DISABLED) {
1946 // Don't set didRemove, since this doesn't impact the scheduled alarms.
1947 mPendingWhileIdleAlarms.remove(i);
1949 } catch (RemoteException e) {
1955 Slog.v(TAG, "remove(package) changed bounds; rebatching");
1957 rebatchAllAlarmsLocked(true);
1958 rescheduleKernelAlarmsLocked();
1959 updateNextAlarmClockLocked();
1963 void removeUserLocked(int userHandle) {
1964 boolean didRemove = false;
1965 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
1966 Batch b = mAlarmBatches.get(i);
1967 didRemove |= b.remove(userHandle);
1968 if (b.size() == 0) {
1969 mAlarmBatches.remove(i);
1972 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
1973 if (UserHandle.getUserId(mPendingWhileIdleAlarms.get(i).creatorUid)
1975 // Don't set didRemove, since this doesn't impact the scheduled alarms.
1976 mPendingWhileIdleAlarms.remove(i);
1979 for (int i = mLastAllowWhileIdleDispatch.size() - 1; i >= 0; i--) {
1980 if (UserHandle.getUserId(mLastAllowWhileIdleDispatch.keyAt(i)) == userHandle) {
1981 mLastAllowWhileIdleDispatch.removeAt(i);
1987 Slog.v(TAG, "remove(user) changed bounds; rebatching");
1989 rebatchAllAlarmsLocked(true);
1990 rescheduleKernelAlarmsLocked();
1991 updateNextAlarmClockLocked();
1995 void interactiveStateChangedLocked(boolean interactive) {
1996 if (mInteractive != interactive) {
1997 mInteractive = interactive;
1998 final long nowELAPSED = SystemClock.elapsedRealtime();
2000 if (mPendingNonWakeupAlarms.size() > 0) {
2001 final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
2002 mTotalDelayTime += thisDelayTime;
2003 if (mMaxDelayTime < thisDelayTime) {
2004 mMaxDelayTime = thisDelayTime;
2006 deliverAlarmsLocked(mPendingNonWakeupAlarms, nowELAPSED);
2007 mPendingNonWakeupAlarms.clear();
2009 if (mNonInteractiveStartTime > 0) {
2010 long dur = nowELAPSED - mNonInteractiveStartTime;
2011 if (dur > mNonInteractiveTime) {
2012 mNonInteractiveTime = dur;
2016 mNonInteractiveStartTime = nowELAPSED;
2021 boolean lookForPackageLocked(String packageName) {
2022 for (int i = 0; i < mAlarmBatches.size(); i++) {
2023 Batch b = mAlarmBatches.get(i);
2024 if (b.hasPackage(packageName)) {
2028 for (int i = 0; i < mPendingWhileIdleAlarms.size(); i++) {
2029 final Alarm a = mPendingWhileIdleAlarms.get(i);
2030 if (a.matches(packageName)) {
2037 private void setLocked(int type, long when) {
2038 if (mNativeData != 0) {
2039 // The kernel never triggers alarms with negative wakeup times
2040 // so we ensure they are positive.
2041 long alarmSeconds, alarmNanoseconds;
2044 alarmNanoseconds = 0;
2046 alarmSeconds = when / 1000;
2047 alarmNanoseconds = (when % 1000) * 1000 * 1000;
2050 set(mNativeData, type, alarmSeconds, alarmNanoseconds);
2052 Message msg = Message.obtain();
2053 msg.what = ALARM_EVENT;
2055 mHandler.removeMessages(ALARM_EVENT);
2056 mHandler.sendMessageAtTime(msg, when);
2060 private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list,
2061 String prefix, String label, long nowRTC, long nowELAPSED, SimpleDateFormat sdf) {
2062 for (int i=list.size()-1; i>=0; i--) {
2063 Alarm a = list.get(i);
2064 pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i);
2065 pw.print(": "); pw.println(a);
2066 a.dump(pw, prefix + " ", nowRTC, nowELAPSED, sdf);
2070 private static final String labelForType(int type) {
2072 case RTC: return "RTC";
2073 case RTC_WAKEUP : return "RTC_WAKEUP";
2074 case ELAPSED_REALTIME : return "ELAPSED";
2075 case ELAPSED_REALTIME_WAKEUP: return "ELAPSED_WAKEUP";
2079 return "--unknown--";
2082 private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list,
2083 String prefix, long nowELAPSED, long nowRTC, SimpleDateFormat sdf) {
2084 for (int i=list.size()-1; i>=0; i--) {
2085 Alarm a = list.get(i);
2086 final String label = labelForType(a.type);
2087 pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i);
2088 pw.print(": "); pw.println(a);
2089 a.dump(pw, prefix + " ", nowRTC, nowELAPSED, sdf);
2093 private native long init();
2094 private native void close(long nativeData);
2095 private native void set(long nativeData, int type, long seconds, long nanoseconds);
2096 private native int waitForAlarm(long nativeData);
2097 private native int setKernelTime(long nativeData, long millis);
2098 private native int setKernelTimezone(long nativeData, int minuteswest);
2100 boolean triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED,
2101 final long nowRTC) {
2102 boolean hasWakeup = false;
2103 // batches are temporally sorted, so we need only pull from the
2104 // start of the list until we either empty it or hit a batch
2105 // that is not yet deliverable
2106 while (mAlarmBatches.size() > 0) {
2107 Batch batch = mAlarmBatches.get(0);
2108 if (batch.start > nowELAPSED) {
2109 // Everything else is scheduled for the future
2113 // We will (re)schedule some alarms now; don't let that interfere
2114 // with delivery of this current batch
2115 mAlarmBatches.remove(0);
2117 final int N = batch.size();
2118 for (int i = 0; i < N; i++) {
2119 Alarm alarm = batch.get(i);
2121 if ((alarm.flags&AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) {
2122 // If this is an ALLOW_WHILE_IDLE alarm, we constrain how frequently the app can
2123 // schedule such alarms.
2124 long lastTime = mLastAllowWhileIdleDispatch.get(alarm.uid, 0);
2125 long minTime = lastTime + mAllowWhileIdleMinTime;
2126 if (nowELAPSED < minTime) {
2127 // Whoops, it hasn't been long enough since the last ALLOW_WHILE_IDLE
2128 // alarm went off for this app. Reschedule the alarm to be in the
2129 // correct time period.
2130 alarm.whenElapsed = minTime;
2131 if (alarm.maxWhenElapsed < minTime) {
2132 alarm.maxWhenElapsed = minTime;
2134 if (RECORD_DEVICE_IDLE_ALARMS) {
2135 IdleDispatchEntry ent = new IdleDispatchEntry();
2136 ent.uid = alarm.uid;
2137 ent.pkg = alarm.operation.getCreatorPackage();
2138 ent.tag = alarm.operation.getTag("");
2139 ent.op = "RESCHEDULE";
2140 ent.elapsedRealtime = nowELAPSED;
2141 ent.argRealtime = lastTime;
2142 mAllowWhileIdleDispatches.add(ent);
2144 setImplLocked(alarm, true, false);
2150 triggerList.add(alarm);
2151 if ((alarm.flags&AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) {
2152 EventLogTags.writeDeviceIdleWakeFromIdle(mPendingIdleUntil != null ? 1 : 0,
2155 if (mPendingIdleUntil == alarm) {
2156 mPendingIdleUntil = null;
2157 rebatchAllAlarmsLocked(false);
2158 restorePendingWhileIdleAlarmsLocked();
2160 if (mNextWakeFromIdle == alarm) {
2161 mNextWakeFromIdle = null;
2162 rebatchAllAlarmsLocked(false);
2165 // Recurring alarms may have passed several alarm intervals while the
2166 // phone was asleep or off, so pass a trigger count when sending them.
2167 if (alarm.repeatInterval > 0) {
2168 // this adjustment will be zero if we're late by
2169 // less than one full repeat interval
2170 alarm.count += (nowELAPSED - alarm.whenElapsed) / alarm.repeatInterval;
2172 // Also schedule its next recurrence
2173 final long delta = alarm.count * alarm.repeatInterval;
2174 final long nextElapsed = alarm.whenElapsed + delta;
2175 setImplLocked(alarm.type, alarm.when + delta, nextElapsed, alarm.windowLength,
2176 maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval),
2177 alarm.repeatInterval, alarm.operation, null, null, alarm.flags, true,
2178 alarm.workSource, alarm.alarmClock, alarm.uid, alarm.packageName);
2185 // We removed an alarm clock. Let the caller recompute the next alarm clock.
2186 if (alarm.alarmClock != null) {
2187 mNextAlarmClockMayChange = true;
2192 // This is a new alarm delivery set; bump the sequence number to indicate that
2193 // all apps' alarm delivery classes should be recalculated.
2195 calculateDeliveryPriorities(triggerList);
2196 Collections.sort(triggerList, mAlarmDispatchComparator);
2199 for (int i=0; i<triggerList.size(); i++) {
2200 Slog.v(TAG, "Triggering alarm #" + i + ": " + triggerList.get(i));
2208 * This Comparator sorts Alarms into increasing time order.
2210 public static class IncreasingTimeOrder implements Comparator<Alarm> {
2211 public int compare(Alarm a1, Alarm a2) {
2212 long when1 = a1.whenElapsed;
2213 long when2 = a2.whenElapsed;
2214 if (when1 > when2) {
2217 if (when1 < when2) {
2224 private static class Alarm {
2225 public final int type;
2226 public final long origWhen;
2227 public final boolean wakeup;
2228 public final PendingIntent operation;
2229 public final IAlarmListener listener;
2230 public final String listenerTag;
2231 public final String statsTag;
2232 public final WorkSource workSource;
2233 public final int flags;
2234 public final AlarmManager.AlarmClockInfo alarmClock;
2235 public final int uid;
2236 public final int creatorUid;
2237 public final String packageName;
2240 public long windowLength;
2241 public long whenElapsed; // 'when' in the elapsed time base
2242 public long maxWhenElapsed; // also in the elapsed time base
2243 public long repeatInterval;
2244 public PriorityClass priorityClass;
2246 public Alarm(int _type, long _when, long _whenElapsed, long _windowLength, long _maxWhen,
2247 long _interval, PendingIntent _op, IAlarmListener _rec, String _listenerTag,
2248 WorkSource _ws, int _flags, AlarmManager.AlarmClockInfo _info,
2249 int _uid, String _pkgName) {
2252 wakeup = _type == AlarmManager.ELAPSED_REALTIME_WAKEUP
2253 || _type == AlarmManager.RTC_WAKEUP;
2255 whenElapsed = _whenElapsed;
2256 windowLength = _windowLength;
2257 maxWhenElapsed = _maxWhen;
2258 repeatInterval = _interval;
2261 listenerTag = _listenerTag;
2262 statsTag = makeTag(_op, _listenerTag, _type);
2267 packageName = _pkgName;
2269 creatorUid = (operation != null) ? operation.getCreatorUid() : uid;
2272 public static String makeTag(PendingIntent pi, String tag, int type) {
2273 final String alarmString = type == ELAPSED_REALTIME_WAKEUP || type == RTC_WAKEUP
2274 ? "*walarm*:" : "*alarm*:";
2275 return (pi != null) ? pi.getTag(alarmString) : (alarmString + tag);
2278 public WakeupEvent makeWakeupEvent(long nowRTC) {
2279 return new WakeupEvent(nowRTC, creatorUid,
2281 ? operation.getIntent().getAction()
2282 : ("<listener>:" + listenerTag));
2285 // Returns true if either matches
2286 public boolean matches(PendingIntent pi, IAlarmListener rec) {
2287 return (operation != null)
2288 ? operation.equals(pi)
2289 : rec != null && listener.asBinder().equals(rec.asBinder());
2292 public boolean matches(String packageName) {
2293 return (operation != null)
2294 ? packageName.equals(operation.getTargetPackage())
2295 : packageName.equals(this.packageName);
2299 public String toString() {
2300 StringBuilder sb = new StringBuilder(128);
2301 sb.append("Alarm{");
2302 sb.append(Integer.toHexString(System.identityHashCode(this)));
2303 sb.append(" type ");
2305 sb.append(" when ");
2308 if (operation != null) {
2309 sb.append(operation.getTargetPackage());
2311 sb.append(packageName);
2314 return sb.toString();
2317 public void dump(PrintWriter pw, String prefix, long nowRTC, long nowELAPSED,
2318 SimpleDateFormat sdf) {
2319 final boolean isRtc = (type == RTC || type == RTC_WAKEUP);
2320 pw.print(prefix); pw.print("tag="); pw.println(statsTag);
2321 pw.print(prefix); pw.print("type="); pw.print(type);
2322 pw.print(" whenElapsed="); TimeUtils.formatDuration(whenElapsed,
2326 pw.print(sdf.format(new Date(when)));
2328 TimeUtils.formatDuration(when, nowELAPSED, pw);
2331 pw.print(prefix); pw.print("window="); TimeUtils.formatDuration(windowLength, pw);
2332 pw.print(" repeatInterval="); pw.print(repeatInterval);
2333 pw.print(" count="); pw.print(count);
2334 pw.print(" flags=0x"); pw.println(Integer.toHexString(flags));
2335 if (alarmClock != null) {
2336 pw.print(prefix); pw.println("Alarm clock:");
2337 pw.print(prefix); pw.print(" triggerTime=");
2338 pw.println(sdf.format(new Date(alarmClock.getTriggerTime())));
2339 pw.print(prefix); pw.print(" showIntent="); pw.println(alarmClock.getShowIntent());
2341 pw.print(prefix); pw.print("operation="); pw.println(operation);
2342 if (listener != null) {
2343 pw.print(prefix); pw.print("listener="); pw.println(listener.asBinder());
2348 void recordWakeupAlarms(ArrayList<Batch> batches, long nowELAPSED, long nowRTC) {
2349 final int numBatches = batches.size();
2350 for (int nextBatch = 0; nextBatch < numBatches; nextBatch++) {
2351 Batch b = batches.get(nextBatch);
2352 if (b.start > nowELAPSED) {
2356 final int numAlarms = b.alarms.size();
2357 for (int nextAlarm = 0; nextAlarm < numAlarms; nextAlarm++) {
2358 Alarm a = b.alarms.get(nextAlarm);
2359 mRecentWakeups.add(a.makeWakeupEvent(nowRTC));
2364 long currentNonWakeupFuzzLocked(long nowELAPSED) {
2365 long timeSinceOn = nowELAPSED - mNonInteractiveStartTime;
2366 if (timeSinceOn < 5*60*1000) {
2367 // If the screen has been off for 5 minutes, only delay by at most two minutes.
2369 } else if (timeSinceOn < 30*60*1000) {
2370 // If the screen has been off for 30 minutes, only delay by at most 15 minutes.
2373 // Otherwise, we will delay by at most an hour.
2378 static int fuzzForDuration(long duration) {
2379 if (duration < 15*60*1000) {
2380 // If the duration until the time is less than 15 minutes, the maximum fuzz
2382 return (int)duration;
2383 } else if (duration < 90*60*1000) {
2384 // If duration is less than 1 1/2 hours, the maximum fuzz is 15 minutes,
2387 // Otherwise, we will fuzz by at most half an hour.
2392 boolean checkAllowNonWakeupDelayLocked(long nowELAPSED) {
2396 if (mLastAlarmDeliveryTime <= 0) {
2399 if (mPendingNonWakeupAlarms.size() > 0 && mNextNonWakeupDeliveryTime < nowELAPSED) {
2400 // This is just a little paranoia, if somehow we have pending non-wakeup alarms
2401 // and the next delivery time is in the past, then just deliver them all. This
2402 // avoids bugs where we get stuck in a loop trying to poll for alarms.
2405 long timeSinceLast = nowELAPSED - mLastAlarmDeliveryTime;
2406 return timeSinceLast <= currentNonWakeupFuzzLocked(nowELAPSED);
2409 void deliverAlarmsLocked(ArrayList<Alarm> triggerList, long nowELAPSED) {
2410 mLastAlarmDeliveryTime = nowELAPSED;
2411 for (int i=0; i<triggerList.size(); i++) {
2412 Alarm alarm = triggerList.get(i);
2413 final boolean allowWhileIdle = (alarm.flags&AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0;
2416 Slog.v(TAG, "sending alarm " + alarm);
2418 if (RECORD_ALARMS_IN_HISTORY) {
2419 if (alarm.workSource != null && alarm.workSource.size() > 0) {
2420 for (int wi=0; wi<alarm.workSource.size(); wi++) {
2421 ActivityManagerNative.noteAlarmStart(
2422 alarm.operation, alarm.workSource.get(wi), alarm.statsTag);
2425 ActivityManagerNative.noteAlarmStart(
2426 alarm.operation, alarm.uid, alarm.statsTag);
2429 mDeliveryTracker.deliverLocked(alarm, nowELAPSED, allowWhileIdle);
2430 } catch (RuntimeException e) {
2431 Slog.w(TAG, "Failure sending alarm.", e);
2436 private class AlarmThread extends Thread
2438 public AlarmThread()
2440 super("AlarmManager");
2445 ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
2449 int result = waitForAlarm(mNativeData);
2450 mLastWakeup = SystemClock.elapsedRealtime();
2452 triggerList.clear();
2454 final long nowRTC = System.currentTimeMillis();
2455 final long nowELAPSED = SystemClock.elapsedRealtime();
2457 if ((result & TIME_CHANGED_MASK) != 0) {
2458 // The kernel can give us spurious time change notifications due to
2459 // small adjustments it makes internally; we want to filter those out.
2460 final long lastTimeChangeClockTime;
2461 final long expectedClockTime;
2462 synchronized (mLock) {
2463 lastTimeChangeClockTime = mLastTimeChangeClockTime;
2464 expectedClockTime = lastTimeChangeClockTime
2465 + (nowELAPSED - mLastTimeChangeRealtime);
2467 if (lastTimeChangeClockTime == 0 || nowRTC < (expectedClockTime-500)
2468 || nowRTC > (expectedClockTime+500)) {
2469 // The change is by at least +/- 500 ms (or this is the first change),
2472 Slog.v(TAG, "Time changed notification from kernel; rebatching");
2474 removeImpl(mTimeTickSender);
2475 removeImpl(mDateChangeSender);
2477 mClockReceiver.scheduleTimeTickEvent();
2478 mClockReceiver.scheduleDateChangedEvent();
2479 synchronized (mLock) {
2481 mLastTimeChangeClockTime = nowRTC;
2482 mLastTimeChangeRealtime = nowELAPSED;
2484 Intent intent = new Intent(Intent.ACTION_TIME_CHANGED);
2485 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
2486 | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
2487 getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
2489 // The world has changed on us, so we need to re-evaluate alarms
2490 // regardless of whether the kernel has told us one went off.
2491 result |= IS_WAKEUP_MASK;
2495 if (result != TIME_CHANGED_MASK) {
2496 // If this was anything besides just a time change, then figure what if
2497 // anything to do about alarms.
2498 synchronized (mLock) {
2499 if (localLOGV) Slog.v(
2500 TAG, "Checking for alarms... rtc=" + nowRTC
2501 + ", elapsed=" + nowELAPSED);
2504 if ((result & IS_WAKEUP_MASK) != 0) {
2505 long newEarliest = nowRTC - RECENT_WAKEUP_PERIOD;
2507 for (WakeupEvent event : mRecentWakeups) {
2508 if (event.when > newEarliest) break;
2509 n++; // number of now-stale entries at the list head
2511 for (int i = 0; i < n; i++) {
2512 mRecentWakeups.remove();
2515 recordWakeupAlarms(mAlarmBatches, nowELAPSED, nowRTC);
2519 boolean hasWakeup = triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC);
2520 if (!hasWakeup && checkAllowNonWakeupDelayLocked(nowELAPSED)) {
2521 // if there are no wakeup alarms and the screen is off, we can
2522 // delay what we have so far until the future.
2523 if (mPendingNonWakeupAlarms.size() == 0) {
2524 mStartCurrentDelayTime = nowELAPSED;
2525 mNextNonWakeupDeliveryTime = nowELAPSED
2526 + ((currentNonWakeupFuzzLocked(nowELAPSED)*3)/2);
2528 mPendingNonWakeupAlarms.addAll(triggerList);
2529 mNumDelayedAlarms += triggerList.size();
2530 rescheduleKernelAlarmsLocked();
2531 updateNextAlarmClockLocked();
2533 // now deliver the alarm intents; if there are pending non-wakeup
2534 // alarms, we need to merge them in to the list. note we don't
2535 // just deliver them first because we generally want non-wakeup
2536 // alarms delivered after wakeup alarms.
2537 rescheduleKernelAlarmsLocked();
2538 updateNextAlarmClockLocked();
2539 if (mPendingNonWakeupAlarms.size() > 0) {
2540 calculateDeliveryPriorities(mPendingNonWakeupAlarms);
2541 triggerList.addAll(mPendingNonWakeupAlarms);
2542 Collections.sort(triggerList, mAlarmDispatchComparator);
2543 final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
2544 mTotalDelayTime += thisDelayTime;
2545 if (mMaxDelayTime < thisDelayTime) {
2546 mMaxDelayTime = thisDelayTime;
2548 mPendingNonWakeupAlarms.clear();
2550 deliverAlarmsLocked(triggerList, nowELAPSED);
2555 // Just in case -- even though no wakeup flag was set, make sure
2556 // we have updated the kernel to the next alarm time.
2557 synchronized (mLock) {
2558 rescheduleKernelAlarmsLocked();
2566 * Attribute blame for a WakeLock.
2567 * @param pi PendingIntent to attribute blame to if ws is null.
2568 * @param ws WorkSource to attribute blame.
2569 * @param knownUid attribution uid; < 0 if we need to derive it from the PendingIntent sender
2571 void setWakelockWorkSource(PendingIntent pi, WorkSource ws, int type, String tag,
2572 int knownUid, boolean first) {
2574 final boolean unimportant = pi == mTimeTickSender;
2575 mWakeLock.setUnimportantForLogging(unimportant);
2576 if (first || mLastWakeLockUnimportantForLogging) {
2577 mWakeLock.setHistoryTag(tag);
2579 mWakeLock.setHistoryTag(null);
2581 mLastWakeLockUnimportantForLogging = unimportant;
2583 mWakeLock.setWorkSource(ws);
2587 final int uid = (knownUid >= 0)
2589 : ActivityManagerNative.getDefault().getUidForIntentSender(pi.getTarget());
2591 mWakeLock.setWorkSource(new WorkSource(uid));
2594 } catch (Exception e) {
2597 // Something went wrong; fall back to attributing the lock to the OS
2598 mWakeLock.setWorkSource(null);
2601 private class AlarmHandler extends Handler {
2602 public static final int ALARM_EVENT = 1;
2603 public static final int SEND_NEXT_ALARM_CLOCK_CHANGED = 2;
2604 public static final int LISTENER_TIMEOUT = 3;
2605 public static final int REPORT_ALARMS_ACTIVE = 4;
2607 public AlarmHandler() {
2610 public void handleMessage(Message msg) {
2613 ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
2614 synchronized (mLock) {
2615 final long nowRTC = System.currentTimeMillis();
2616 final long nowELAPSED = SystemClock.elapsedRealtime();
2617 triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC);
2618 updateNextAlarmClockLocked();
2621 // now trigger the alarms without the lock held
2622 for (int i=0; i<triggerList.size(); i++) {
2623 Alarm alarm = triggerList.get(i);
2625 alarm.operation.send();
2626 } catch (PendingIntent.CanceledException e) {
2627 if (alarm.repeatInterval > 0) {
2628 // This IntentSender is no longer valid, but this
2629 // is a repeating alarm, so toss the hoser.
2630 removeImpl(alarm.operation);
2637 case SEND_NEXT_ALARM_CLOCK_CHANGED:
2638 sendNextAlarmClockChanged();
2641 case LISTENER_TIMEOUT:
2642 mDeliveryTracker.alarmTimedOut((IBinder) msg.obj);
2645 case REPORT_ALARMS_ACTIVE:
2646 if (mLocalDeviceIdleController != null) {
2647 mLocalDeviceIdleController.setAlarmsActive(msg.arg1 != 0);
2652 // nope, just ignore it
2658 class ClockReceiver extends BroadcastReceiver {
2659 public ClockReceiver() {
2660 IntentFilter filter = new IntentFilter();
2661 filter.addAction(Intent.ACTION_TIME_TICK);
2662 filter.addAction(Intent.ACTION_DATE_CHANGED);
2663 getContext().registerReceiver(this, filter);
2667 public void onReceive(Context context, Intent intent) {
2668 if (intent.getAction().equals(Intent.ACTION_TIME_TICK)) {
2670 Slog.v(TAG, "Received TIME_TICK alarm; rescheduling");
2672 scheduleTimeTickEvent();
2673 } else if (intent.getAction().equals(Intent.ACTION_DATE_CHANGED)) {
2674 // Since the kernel does not keep track of DST, we need to
2675 // reset the TZ information at the beginning of each day
2676 // based off of the current Zone gmt offset + userspace tracked
2677 // daylight savings information.
2678 TimeZone zone = TimeZone.getTimeZone(SystemProperties.get(TIMEZONE_PROPERTY));
2679 int gmtOffset = zone.getOffset(System.currentTimeMillis());
2680 setKernelTimezone(mNativeData, -(gmtOffset / 60000));
2681 scheduleDateChangedEvent();
2685 public void scheduleTimeTickEvent() {
2686 final long currentTime = System.currentTimeMillis();
2687 final long nextTime = 60000 * ((currentTime / 60000) + 1);
2689 // Schedule this event for the amount of time that it would take to get to
2690 // the top of the next minute.
2691 final long tickEventDelay = nextTime - currentTime;
2693 final WorkSource workSource = null; // Let system take blame for time tick events.
2694 setImpl(ELAPSED_REALTIME, SystemClock.elapsedRealtime() + tickEventDelay, 0,
2695 0, mTimeTickSender, null, null, AlarmManager.FLAG_STANDALONE, workSource,
2696 null, Process.myUid(), "android");
2699 public void scheduleDateChangedEvent() {
2700 Calendar calendar = Calendar.getInstance();
2701 calendar.setTimeInMillis(System.currentTimeMillis());
2702 calendar.set(Calendar.HOUR_OF_DAY, 0);
2703 calendar.set(Calendar.MINUTE, 0);
2704 calendar.set(Calendar.SECOND, 0);
2705 calendar.set(Calendar.MILLISECOND, 0);
2706 calendar.add(Calendar.DAY_OF_MONTH, 1);
2708 final WorkSource workSource = null; // Let system take blame for date change events.
2709 setImpl(RTC, calendar.getTimeInMillis(), 0, 0, mDateChangeSender, null, null,
2710 AlarmManager.FLAG_STANDALONE, workSource, null,
2711 Process.myUid(), "android");
2715 class InteractiveStateReceiver extends BroadcastReceiver {
2716 public InteractiveStateReceiver() {
2717 IntentFilter filter = new IntentFilter();
2718 filter.addAction(Intent.ACTION_SCREEN_OFF);
2719 filter.addAction(Intent.ACTION_SCREEN_ON);
2720 filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
2721 getContext().registerReceiver(this, filter);
2725 public void onReceive(Context context, Intent intent) {
2726 synchronized (mLock) {
2727 interactiveStateChangedLocked(Intent.ACTION_SCREEN_ON.equals(intent.getAction()));
2732 class UninstallReceiver extends BroadcastReceiver {
2733 public UninstallReceiver() {
2734 IntentFilter filter = new IntentFilter();
2735 filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
2736 filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
2737 filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
2738 filter.addDataScheme("package");
2739 getContext().registerReceiver(this, filter);
2740 // Register for events related to sdcard installation.
2741 IntentFilter sdFilter = new IntentFilter();
2742 sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
2743 sdFilter.addAction(Intent.ACTION_USER_STOPPED);
2744 sdFilter.addAction(Intent.ACTION_UID_REMOVED);
2745 getContext().registerReceiver(this, sdFilter);
2749 public void onReceive(Context context, Intent intent) {
2750 synchronized (mLock) {
2751 String action = intent.getAction();
2752 String pkgList[] = null;
2753 if (Intent.ACTION_QUERY_PACKAGE_RESTART.equals(action)) {
2754 pkgList = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
2755 for (String packageName : pkgList) {
2756 if (lookForPackageLocked(packageName)) {
2757 setResultCode(Activity.RESULT_OK);
2762 } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
2763 pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
2764 } else if (Intent.ACTION_USER_STOPPED.equals(action)) {
2765 int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
2766 if (userHandle >= 0) {
2767 removeUserLocked(userHandle);
2769 } else if (Intent.ACTION_UID_REMOVED.equals(action)) {
2770 int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
2772 mLastAllowWhileIdleDispatch.delete(uid);
2775 if (Intent.ACTION_PACKAGE_REMOVED.equals(action)
2776 && intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
2777 // This package is being updated; don't kill its alarms.
2780 Uri data = intent.getData();
2782 String pkg = data.getSchemeSpecificPart();
2784 pkgList = new String[]{pkg};
2788 if (pkgList != null && (pkgList.length > 0)) {
2789 for (String pkg : pkgList) {
2791 mPriorities.remove(pkg);
2792 for (int i=mBroadcastStats.size()-1; i>=0; i--) {
2793 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(i);
2794 if (uidStats.remove(pkg) != null) {
2795 if (uidStats.size() <= 0) {
2796 mBroadcastStats.removeAt(i);
2806 final class UidObserver extends IUidObserver.Stub {
2807 @Override public void onUidStateChanged(int uid, int procState) throws RemoteException {
2810 @Override public void onUidGone(int uid) throws RemoteException {
2813 @Override public void onUidActive(int uid) throws RemoteException {
2816 @Override public void onUidIdle(int uid) throws RemoteException {
2817 synchronized (mLock) {
2818 removeForStoppedLocked(uid);
2823 private final BroadcastStats getStatsLocked(PendingIntent pi) {
2824 String pkg = pi.getCreatorPackage();
2825 int uid = pi.getCreatorUid();
2826 return getStatsLocked(uid, pkg);
2829 private final BroadcastStats getStatsLocked(int uid, String pkgName) {
2830 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.get(uid);
2831 if (uidStats == null) {
2832 uidStats = new ArrayMap<String, BroadcastStats>();
2833 mBroadcastStats.put(uid, uidStats);
2835 BroadcastStats bs = uidStats.get(pkgName);
2837 bs = new BroadcastStats(uid, pkgName);
2838 uidStats.put(pkgName, bs);
2843 class DeliveryTracker extends IAlarmCompleteListener.Stub implements PendingIntent.OnFinished {
2844 private InFlight removeLocked(PendingIntent pi, Intent intent) {
2845 for (int i = 0; i < mInFlight.size(); i++) {
2846 if (mInFlight.get(i).mPendingIntent == pi) {
2847 return mInFlight.remove(i);
2850 mLog.w("No in-flight alarm for " + pi + " " + intent);
2854 private InFlight removeLocked(IBinder listener) {
2855 for (int i = 0; i < mInFlight.size(); i++) {
2856 if (mInFlight.get(i).mListener == listener) {
2857 return mInFlight.remove(i);
2860 mLog.w("No in-flight alarm for listener " + listener);
2864 private void updateStatsLocked(InFlight inflight) {
2865 final long nowELAPSED = SystemClock.elapsedRealtime();
2866 BroadcastStats bs = inflight.mBroadcastStats;
2868 if (bs.nesting <= 0) {
2870 bs.aggregateTime += nowELAPSED - bs.startTime;
2872 FilterStats fs = inflight.mFilterStats;
2874 if (fs.nesting <= 0) {
2876 fs.aggregateTime += nowELAPSED - fs.startTime;
2878 if (RECORD_ALARMS_IN_HISTORY) {
2879 if (inflight.mWorkSource != null && inflight.mWorkSource.size() > 0) {
2880 for (int wi=0; wi<inflight.mWorkSource.size(); wi++) {
2881 ActivityManagerNative.noteAlarmFinish(
2882 inflight.mPendingIntent, inflight.mWorkSource.get(wi), inflight.mTag);
2885 ActivityManagerNative.noteAlarmFinish(
2886 inflight.mPendingIntent, inflight.mUid, inflight.mTag);
2891 private void updateTrackingLocked(InFlight inflight) {
2892 if (inflight != null) {
2893 updateStatsLocked(inflight);
2895 mBroadcastRefCount--;
2896 if (mBroadcastRefCount == 0) {
2897 mHandler.obtainMessage(AlarmHandler.REPORT_ALARMS_ACTIVE, 0).sendToTarget();
2898 mWakeLock.release();
2899 if (mInFlight.size() > 0) {
2900 mLog.w("Finished all dispatches with " + mInFlight.size()
2901 + " remaining inflights");
2902 for (int i=0; i<mInFlight.size(); i++) {
2903 mLog.w(" Remaining #" + i + ": " + mInFlight.get(i));
2908 // the next of our alarms is now in flight. reattribute the wakelock.
2909 if (mInFlight.size() > 0) {
2910 InFlight inFlight = mInFlight.get(0);
2911 setWakelockWorkSource(inFlight.mPendingIntent, inFlight.mWorkSource,
2912 inFlight.mAlarmType, inFlight.mTag, -1, false);
2914 // should never happen
2915 mLog.w("Alarm wakelock still held but sent queue empty");
2916 mWakeLock.setWorkSource(null);
2922 * Callback that arrives when a direct-call alarm reports that delivery has finished
2925 public void alarmComplete(IBinder who) {
2927 Slog.w(TAG, "Invalid alarmComplete: uid=" + Binder.getCallingUid()
2928 + " pid=" + Binder.getCallingPid());
2932 final long ident = Binder.clearCallingIdentity();
2934 synchronized (mLock) {
2935 mHandler.removeMessages(AlarmHandler.LISTENER_TIMEOUT, who);
2936 InFlight inflight = removeLocked(who);
2937 if (inflight != null) {
2938 if (DEBUG_LISTENER_CALLBACK) {
2939 Slog.i(TAG, "alarmComplete() from " + who);
2941 updateTrackingLocked(inflight);
2943 // Delivery timed out, and the timeout handling already took care of
2944 // updating our tracking here, so we needn't do anything further.
2945 if (DEBUG_LISTENER_CALLBACK) {
2946 Slog.i(TAG, "Late alarmComplete() from " + who);
2951 Binder.restoreCallingIdentity(ident);
2956 * Callback that arrives when a PendingIntent alarm has finished delivery
2959 public void onSendFinished(PendingIntent pi, Intent intent, int resultCode,
2960 String resultData, Bundle resultExtras) {
2961 synchronized (mLock) {
2962 updateTrackingLocked(removeLocked(pi, intent));
2967 * Timeout of a direct-call alarm delivery
2969 public void alarmTimedOut(IBinder who) {
2970 synchronized (mLock) {
2971 InFlight inflight = removeLocked(who);
2972 if (inflight != null) {
2973 // TODO: implement ANR policy for the target
2974 if (DEBUG_LISTENER_CALLBACK) {
2975 Slog.i(TAG, "Alarm listener " + who + " timed out in delivery");
2977 updateTrackingLocked(inflight);
2979 if (DEBUG_LISTENER_CALLBACK) {
2980 Slog.i(TAG, "Spurious timeout of listener " + who);
2987 * Deliver an alarm and set up the post-delivery handling appropriately
2989 public void deliverLocked(Alarm alarm, long nowELAPSED, boolean allowWhileIdle) {
2990 if (alarm.operation != null) {
2991 // PendingIntent alarm
2993 alarm.operation.send(getContext(), 0,
2994 mBackgroundIntent.putExtra(
2995 Intent.EXTRA_ALARM_COUNT, alarm.count),
2996 mDeliveryTracker, mHandler, null,
2997 allowWhileIdle ? mIdleOptions : null);
2998 } catch (PendingIntent.CanceledException e) {
2999 if (alarm.repeatInterval > 0) {
3000 // This IntentSender is no longer valid, but this
3001 // is a repeating alarm, so toss it
3002 removeImpl(alarm.operation);
3004 // No actual delivery was possible, so the delivery tracker's
3005 // 'finished' callback won't be invoked. We also don't need
3006 // to do any wakelock or stats tracking, so we have nothing
3007 // left to do here but go on to the next thing.
3011 // Direct listener callback alarm
3013 if (DEBUG_LISTENER_CALLBACK) {
3014 Slog.v(TAG, "Alarm to uid=" + alarm.uid
3015 + " listener=" + alarm.listener.asBinder());
3017 alarm.listener.doAlarm(this);
3018 mHandler.sendMessageDelayed(
3019 mHandler.obtainMessage(AlarmHandler.LISTENER_TIMEOUT,
3020 alarm.listener.asBinder()),
3021 mConstants.LISTENER_TIMEOUT);
3022 } catch (Exception e) {
3023 if (DEBUG_LISTENER_CALLBACK) {
3024 Slog.i(TAG, "Alarm undeliverable to listener "
3025 + alarm.listener.asBinder(), e);
3027 // As in the PendingIntent.CanceledException case, delivery of the
3028 // alarm was not possible, so we have no wakelock or timeout or
3029 // stats management to do. It threw before we posted the delayed
3030 // timeout message, so we're done here.
3035 // The alarm is now in flight; now arrange wakelock and stats tracking
3036 if (mBroadcastRefCount == 0) {
3037 setWakelockWorkSource(alarm.operation, alarm.workSource,
3038 alarm.type, alarm.statsTag, (alarm.operation == null) ? alarm.uid : -1,
3040 mWakeLock.acquire();
3041 mHandler.obtainMessage(AlarmHandler.REPORT_ALARMS_ACTIVE, 1).sendToTarget();
3043 final InFlight inflight = new InFlight(AlarmManagerService.this,
3044 alarm.operation, alarm.listener, alarm.workSource, alarm.uid,
3045 alarm.packageName, alarm.type, alarm.statsTag, nowELAPSED);
3046 mInFlight.add(inflight);
3047 mBroadcastRefCount++;
3049 if (allowWhileIdle) {
3050 // Record the last time this uid handled an ALLOW_WHILE_IDLE alarm.
3051 mLastAllowWhileIdleDispatch.put(alarm.uid, nowELAPSED);
3052 if (RECORD_DEVICE_IDLE_ALARMS) {
3053 IdleDispatchEntry ent = new IdleDispatchEntry();
3054 ent.uid = alarm.uid;
3055 ent.pkg = alarm.packageName;
3056 ent.tag = alarm.statsTag;
3058 ent.elapsedRealtime = nowELAPSED;
3059 mAllowWhileIdleDispatches.add(ent);
3063 final BroadcastStats bs = inflight.mBroadcastStats;
3065 if (bs.nesting == 0) {
3067 bs.startTime = nowELAPSED;
3071 final FilterStats fs = inflight.mFilterStats;
3073 if (fs.nesting == 0) {
3075 fs.startTime = nowELAPSED;
3079 if (alarm.type == ELAPSED_REALTIME_WAKEUP
3080 || alarm.type == RTC_WAKEUP) {
3083 if (alarm.workSource != null && alarm.workSource.size() > 0) {
3084 for (int wi=0; wi<alarm.workSource.size(); wi++) {
3085 final String wsName = alarm.workSource.getName(wi);
3086 ActivityManagerNative.noteWakeupAlarm(
3087 alarm.operation, alarm.workSource.get(wi),
3088 (wsName != null) ? wsName : alarm.packageName,
3092 ActivityManagerNative.noteWakeupAlarm(
3093 alarm.operation, alarm.uid, alarm.packageName, alarm.statsTag);