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);
2476 mClockReceiver.scheduleTimeTickEvent();
2477 synchronized (mLock) {
2479 mLastTimeChangeClockTime = nowRTC;
2480 mLastTimeChangeRealtime = nowELAPSED;
2482 Intent intent = new Intent(Intent.ACTION_TIME_CHANGED);
2483 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
2484 | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
2485 getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
2487 // The world has changed on us, so we need to re-evaluate alarms
2488 // regardless of whether the kernel has told us one went off.
2489 result |= IS_WAKEUP_MASK;
2493 if (result != TIME_CHANGED_MASK) {
2494 // If this was anything besides just a time change, then figure what if
2495 // anything to do about alarms.
2496 synchronized (mLock) {
2497 if (localLOGV) Slog.v(
2498 TAG, "Checking for alarms... rtc=" + nowRTC
2499 + ", elapsed=" + nowELAPSED);
2502 if ((result & IS_WAKEUP_MASK) != 0) {
2503 long newEarliest = nowRTC - RECENT_WAKEUP_PERIOD;
2505 for (WakeupEvent event : mRecentWakeups) {
2506 if (event.when > newEarliest) break;
2507 n++; // number of now-stale entries at the list head
2509 for (int i = 0; i < n; i++) {
2510 mRecentWakeups.remove();
2513 recordWakeupAlarms(mAlarmBatches, nowELAPSED, nowRTC);
2517 boolean hasWakeup = triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC);
2518 if (!hasWakeup && checkAllowNonWakeupDelayLocked(nowELAPSED)) {
2519 // if there are no wakeup alarms and the screen is off, we can
2520 // delay what we have so far until the future.
2521 if (mPendingNonWakeupAlarms.size() == 0) {
2522 mStartCurrentDelayTime = nowELAPSED;
2523 mNextNonWakeupDeliveryTime = nowELAPSED
2524 + ((currentNonWakeupFuzzLocked(nowELAPSED)*3)/2);
2526 mPendingNonWakeupAlarms.addAll(triggerList);
2527 mNumDelayedAlarms += triggerList.size();
2528 rescheduleKernelAlarmsLocked();
2529 updateNextAlarmClockLocked();
2531 // now deliver the alarm intents; if there are pending non-wakeup
2532 // alarms, we need to merge them in to the list. note we don't
2533 // just deliver them first because we generally want non-wakeup
2534 // alarms delivered after wakeup alarms.
2535 rescheduleKernelAlarmsLocked();
2536 updateNextAlarmClockLocked();
2537 if (mPendingNonWakeupAlarms.size() > 0) {
2538 calculateDeliveryPriorities(mPendingNonWakeupAlarms);
2539 triggerList.addAll(mPendingNonWakeupAlarms);
2540 Collections.sort(triggerList, mAlarmDispatchComparator);
2541 final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
2542 mTotalDelayTime += thisDelayTime;
2543 if (mMaxDelayTime < thisDelayTime) {
2544 mMaxDelayTime = thisDelayTime;
2546 mPendingNonWakeupAlarms.clear();
2548 deliverAlarmsLocked(triggerList, nowELAPSED);
2553 // Just in case -- even though no wakeup flag was set, make sure
2554 // we have updated the kernel to the next alarm time.
2555 rescheduleKernelAlarmsLocked();
2562 * Attribute blame for a WakeLock.
2563 * @param pi PendingIntent to attribute blame to if ws is null.
2564 * @param ws WorkSource to attribute blame.
2565 * @param knownUid attribution uid; < 0 if we need to derive it from the PendingIntent sender
2567 void setWakelockWorkSource(PendingIntent pi, WorkSource ws, int type, String tag,
2568 int knownUid, boolean first) {
2570 final boolean unimportant = pi == mTimeTickSender;
2571 mWakeLock.setUnimportantForLogging(unimportant);
2572 if (first || mLastWakeLockUnimportantForLogging) {
2573 mWakeLock.setHistoryTag(tag);
2575 mWakeLock.setHistoryTag(null);
2577 mLastWakeLockUnimportantForLogging = unimportant;
2579 mWakeLock.setWorkSource(ws);
2583 final int uid = (knownUid >= 0)
2585 : ActivityManagerNative.getDefault().getUidForIntentSender(pi.getTarget());
2587 mWakeLock.setWorkSource(new WorkSource(uid));
2590 } catch (Exception e) {
2593 // Something went wrong; fall back to attributing the lock to the OS
2594 mWakeLock.setWorkSource(null);
2597 private class AlarmHandler extends Handler {
2598 public static final int ALARM_EVENT = 1;
2599 public static final int SEND_NEXT_ALARM_CLOCK_CHANGED = 2;
2600 public static final int LISTENER_TIMEOUT = 3;
2601 public static final int REPORT_ALARMS_ACTIVE = 4;
2603 public AlarmHandler() {
2606 public void handleMessage(Message msg) {
2609 ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
2610 synchronized (mLock) {
2611 final long nowRTC = System.currentTimeMillis();
2612 final long nowELAPSED = SystemClock.elapsedRealtime();
2613 triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC);
2614 updateNextAlarmClockLocked();
2617 // now trigger the alarms without the lock held
2618 for (int i=0; i<triggerList.size(); i++) {
2619 Alarm alarm = triggerList.get(i);
2621 alarm.operation.send();
2622 } catch (PendingIntent.CanceledException e) {
2623 if (alarm.repeatInterval > 0) {
2624 // This IntentSender is no longer valid, but this
2625 // is a repeating alarm, so toss the hoser.
2626 removeImpl(alarm.operation);
2633 case SEND_NEXT_ALARM_CLOCK_CHANGED:
2634 sendNextAlarmClockChanged();
2637 case LISTENER_TIMEOUT:
2638 mDeliveryTracker.alarmTimedOut((IBinder) msg.obj);
2641 case REPORT_ALARMS_ACTIVE:
2642 if (mLocalDeviceIdleController != null) {
2643 mLocalDeviceIdleController.setAlarmsActive(msg.arg1 != 0);
2648 // nope, just ignore it
2654 class ClockReceiver extends BroadcastReceiver {
2655 public ClockReceiver() {
2656 IntentFilter filter = new IntentFilter();
2657 filter.addAction(Intent.ACTION_TIME_TICK);
2658 filter.addAction(Intent.ACTION_DATE_CHANGED);
2659 getContext().registerReceiver(this, filter);
2663 public void onReceive(Context context, Intent intent) {
2664 if (intent.getAction().equals(Intent.ACTION_TIME_TICK)) {
2666 Slog.v(TAG, "Received TIME_TICK alarm; rescheduling");
2668 scheduleTimeTickEvent();
2669 } else if (intent.getAction().equals(Intent.ACTION_DATE_CHANGED)) {
2670 // Since the kernel does not keep track of DST, we need to
2671 // reset the TZ information at the beginning of each day
2672 // based off of the current Zone gmt offset + userspace tracked
2673 // daylight savings information.
2674 TimeZone zone = TimeZone.getTimeZone(SystemProperties.get(TIMEZONE_PROPERTY));
2675 int gmtOffset = zone.getOffset(System.currentTimeMillis());
2676 setKernelTimezone(mNativeData, -(gmtOffset / 60000));
2677 scheduleDateChangedEvent();
2681 public void scheduleTimeTickEvent() {
2682 final long currentTime = System.currentTimeMillis();
2683 final long nextTime = 60000 * ((currentTime / 60000) + 1);
2685 // Schedule this event for the amount of time that it would take to get to
2686 // the top of the next minute.
2687 final long tickEventDelay = nextTime - currentTime;
2689 final WorkSource workSource = null; // Let system take blame for time tick events.
2690 setImpl(ELAPSED_REALTIME, SystemClock.elapsedRealtime() + tickEventDelay, 0,
2691 0, mTimeTickSender, null, null, AlarmManager.FLAG_STANDALONE, workSource,
2692 null, Process.myUid(), "android");
2695 public void scheduleDateChangedEvent() {
2696 Calendar calendar = Calendar.getInstance();
2697 calendar.setTimeInMillis(System.currentTimeMillis());
2698 calendar.set(Calendar.HOUR, 0);
2699 calendar.set(Calendar.MINUTE, 0);
2700 calendar.set(Calendar.SECOND, 0);
2701 calendar.set(Calendar.MILLISECOND, 0);
2702 calendar.add(Calendar.DAY_OF_MONTH, 1);
2704 final WorkSource workSource = null; // Let system take blame for date change events.
2705 setImpl(RTC, calendar.getTimeInMillis(), 0, 0, mDateChangeSender, null, null,
2706 AlarmManager.FLAG_STANDALONE, workSource, null,
2707 Process.myUid(), "android");
2711 class InteractiveStateReceiver extends BroadcastReceiver {
2712 public InteractiveStateReceiver() {
2713 IntentFilter filter = new IntentFilter();
2714 filter.addAction(Intent.ACTION_SCREEN_OFF);
2715 filter.addAction(Intent.ACTION_SCREEN_ON);
2716 filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
2717 getContext().registerReceiver(this, filter);
2721 public void onReceive(Context context, Intent intent) {
2722 synchronized (mLock) {
2723 interactiveStateChangedLocked(Intent.ACTION_SCREEN_ON.equals(intent.getAction()));
2728 class UninstallReceiver extends BroadcastReceiver {
2729 public UninstallReceiver() {
2730 IntentFilter filter = new IntentFilter();
2731 filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
2732 filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
2733 filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
2734 filter.addDataScheme("package");
2735 getContext().registerReceiver(this, filter);
2736 // Register for events related to sdcard installation.
2737 IntentFilter sdFilter = new IntentFilter();
2738 sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
2739 sdFilter.addAction(Intent.ACTION_USER_STOPPED);
2740 sdFilter.addAction(Intent.ACTION_UID_REMOVED);
2741 getContext().registerReceiver(this, sdFilter);
2745 public void onReceive(Context context, Intent intent) {
2746 synchronized (mLock) {
2747 String action = intent.getAction();
2748 String pkgList[] = null;
2749 if (Intent.ACTION_QUERY_PACKAGE_RESTART.equals(action)) {
2750 pkgList = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
2751 for (String packageName : pkgList) {
2752 if (lookForPackageLocked(packageName)) {
2753 setResultCode(Activity.RESULT_OK);
2758 } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
2759 pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
2760 } else if (Intent.ACTION_USER_STOPPED.equals(action)) {
2761 int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
2762 if (userHandle >= 0) {
2763 removeUserLocked(userHandle);
2765 } else if (Intent.ACTION_UID_REMOVED.equals(action)) {
2766 int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
2768 mLastAllowWhileIdleDispatch.delete(uid);
2771 if (Intent.ACTION_PACKAGE_REMOVED.equals(action)
2772 && intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
2773 // This package is being updated; don't kill its alarms.
2776 Uri data = intent.getData();
2778 String pkg = data.getSchemeSpecificPart();
2780 pkgList = new String[]{pkg};
2784 if (pkgList != null && (pkgList.length > 0)) {
2785 for (String pkg : pkgList) {
2787 mPriorities.remove(pkg);
2788 for (int i=mBroadcastStats.size()-1; i>=0; i--) {
2789 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(i);
2790 if (uidStats.remove(pkg) != null) {
2791 if (uidStats.size() <= 0) {
2792 mBroadcastStats.removeAt(i);
2802 final class UidObserver extends IUidObserver.Stub {
2803 @Override public void onUidStateChanged(int uid, int procState) throws RemoteException {
2806 @Override public void onUidGone(int uid) throws RemoteException {
2809 @Override public void onUidActive(int uid) throws RemoteException {
2812 @Override public void onUidIdle(int uid) throws RemoteException {
2813 synchronized (mLock) {
2814 removeForStoppedLocked(uid);
2819 private final BroadcastStats getStatsLocked(PendingIntent pi) {
2820 String pkg = pi.getCreatorPackage();
2821 int uid = pi.getCreatorUid();
2822 return getStatsLocked(uid, pkg);
2825 private final BroadcastStats getStatsLocked(int uid, String pkgName) {
2826 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.get(uid);
2827 if (uidStats == null) {
2828 uidStats = new ArrayMap<String, BroadcastStats>();
2829 mBroadcastStats.put(uid, uidStats);
2831 BroadcastStats bs = uidStats.get(pkgName);
2833 bs = new BroadcastStats(uid, pkgName);
2834 uidStats.put(pkgName, bs);
2839 class DeliveryTracker extends IAlarmCompleteListener.Stub implements PendingIntent.OnFinished {
2840 private InFlight removeLocked(PendingIntent pi, Intent intent) {
2841 for (int i = 0; i < mInFlight.size(); i++) {
2842 if (mInFlight.get(i).mPendingIntent == pi) {
2843 return mInFlight.remove(i);
2846 mLog.w("No in-flight alarm for " + pi + " " + intent);
2850 private InFlight removeLocked(IBinder listener) {
2851 for (int i = 0; i < mInFlight.size(); i++) {
2852 if (mInFlight.get(i).mListener == listener) {
2853 return mInFlight.remove(i);
2856 mLog.w("No in-flight alarm for listener " + listener);
2860 private void updateStatsLocked(InFlight inflight) {
2861 final long nowELAPSED = SystemClock.elapsedRealtime();
2862 BroadcastStats bs = inflight.mBroadcastStats;
2864 if (bs.nesting <= 0) {
2866 bs.aggregateTime += nowELAPSED - bs.startTime;
2868 FilterStats fs = inflight.mFilterStats;
2870 if (fs.nesting <= 0) {
2872 fs.aggregateTime += nowELAPSED - fs.startTime;
2874 if (RECORD_ALARMS_IN_HISTORY) {
2875 if (inflight.mWorkSource != null && inflight.mWorkSource.size() > 0) {
2876 for (int wi=0; wi<inflight.mWorkSource.size(); wi++) {
2877 ActivityManagerNative.noteAlarmFinish(
2878 inflight.mPendingIntent, inflight.mWorkSource.get(wi), inflight.mTag);
2881 ActivityManagerNative.noteAlarmFinish(
2882 inflight.mPendingIntent, inflight.mUid, inflight.mTag);
2887 private void updateTrackingLocked(InFlight inflight) {
2888 if (inflight != null) {
2889 updateStatsLocked(inflight);
2891 mBroadcastRefCount--;
2892 if (mBroadcastRefCount == 0) {
2893 mHandler.obtainMessage(AlarmHandler.REPORT_ALARMS_ACTIVE, 0).sendToTarget();
2894 mWakeLock.release();
2895 if (mInFlight.size() > 0) {
2896 mLog.w("Finished all dispatches with " + mInFlight.size()
2897 + " remaining inflights");
2898 for (int i=0; i<mInFlight.size(); i++) {
2899 mLog.w(" Remaining #" + i + ": " + mInFlight.get(i));
2904 // the next of our alarms is now in flight. reattribute the wakelock.
2905 if (mInFlight.size() > 0) {
2906 InFlight inFlight = mInFlight.get(0);
2907 setWakelockWorkSource(inFlight.mPendingIntent, inFlight.mWorkSource,
2908 inFlight.mAlarmType, inFlight.mTag, -1, false);
2910 // should never happen
2911 mLog.w("Alarm wakelock still held but sent queue empty");
2912 mWakeLock.setWorkSource(null);
2918 * Callback that arrives when a direct-call alarm reports that delivery has finished
2921 public void alarmComplete(IBinder who) {
2923 Slog.w(TAG, "Invalid alarmComplete: uid=" + Binder.getCallingUid()
2924 + " pid=" + Binder.getCallingPid());
2928 final long ident = Binder.clearCallingIdentity();
2930 synchronized (mLock) {
2931 mHandler.removeMessages(AlarmHandler.LISTENER_TIMEOUT, who);
2932 InFlight inflight = removeLocked(who);
2933 if (inflight != null) {
2934 if (DEBUG_LISTENER_CALLBACK) {
2935 Slog.i(TAG, "alarmComplete() from " + who);
2937 updateTrackingLocked(inflight);
2939 // Delivery timed out, and the timeout handling already took care of
2940 // updating our tracking here, so we needn't do anything further.
2941 if (DEBUG_LISTENER_CALLBACK) {
2942 Slog.i(TAG, "Late alarmComplete() from " + who);
2947 Binder.restoreCallingIdentity(ident);
2952 * Callback that arrives when a PendingIntent alarm has finished delivery
2955 public void onSendFinished(PendingIntent pi, Intent intent, int resultCode,
2956 String resultData, Bundle resultExtras) {
2957 synchronized (mLock) {
2958 updateTrackingLocked(removeLocked(pi, intent));
2963 * Timeout of a direct-call alarm delivery
2965 public void alarmTimedOut(IBinder who) {
2966 synchronized (mLock) {
2967 InFlight inflight = removeLocked(who);
2968 if (inflight != null) {
2969 // TODO: implement ANR policy for the target
2970 if (DEBUG_LISTENER_CALLBACK) {
2971 Slog.i(TAG, "Alarm listener " + who + " timed out in delivery");
2973 updateTrackingLocked(inflight);
2975 if (DEBUG_LISTENER_CALLBACK) {
2976 Slog.i(TAG, "Spurious timeout of listener " + who);
2983 * Deliver an alarm and set up the post-delivery handling appropriately
2985 public void deliverLocked(Alarm alarm, long nowELAPSED, boolean allowWhileIdle) {
2986 if (alarm.operation != null) {
2987 // PendingIntent alarm
2989 alarm.operation.send(getContext(), 0,
2990 mBackgroundIntent.putExtra(
2991 Intent.EXTRA_ALARM_COUNT, alarm.count),
2992 mDeliveryTracker, mHandler, null,
2993 allowWhileIdle ? mIdleOptions : null);
2994 } catch (PendingIntent.CanceledException e) {
2995 if (alarm.repeatInterval > 0) {
2996 // This IntentSender is no longer valid, but this
2997 // is a repeating alarm, so toss it
2998 removeImpl(alarm.operation);
3000 // No actual delivery was possible, so the delivery tracker's
3001 // 'finished' callback won't be invoked. We also don't need
3002 // to do any wakelock or stats tracking, so we have nothing
3003 // left to do here but go on to the next thing.
3007 // Direct listener callback alarm
3009 if (DEBUG_LISTENER_CALLBACK) {
3010 Slog.v(TAG, "Alarm to uid=" + alarm.uid
3011 + " listener=" + alarm.listener.asBinder());
3013 alarm.listener.doAlarm(this);
3014 mHandler.sendMessageDelayed(
3015 mHandler.obtainMessage(AlarmHandler.LISTENER_TIMEOUT,
3016 alarm.listener.asBinder()),
3017 mConstants.LISTENER_TIMEOUT);
3018 } catch (Exception e) {
3019 if (DEBUG_LISTENER_CALLBACK) {
3020 Slog.i(TAG, "Alarm undeliverable to listener "
3021 + alarm.listener.asBinder(), e);
3023 // As in the PendingIntent.CanceledException case, delivery of the
3024 // alarm was not possible, so we have no wakelock or timeout or
3025 // stats management to do. It threw before we posted the delayed
3026 // timeout message, so we're done here.
3031 // The alarm is now in flight; now arrange wakelock and stats tracking
3032 if (mBroadcastRefCount == 0) {
3033 setWakelockWorkSource(alarm.operation, alarm.workSource,
3034 alarm.type, alarm.statsTag, (alarm.operation == null) ? alarm.uid : -1,
3036 mWakeLock.acquire();
3037 mHandler.obtainMessage(AlarmHandler.REPORT_ALARMS_ACTIVE, 1).sendToTarget();
3039 final InFlight inflight = new InFlight(AlarmManagerService.this,
3040 alarm.operation, alarm.listener, alarm.workSource, alarm.uid,
3041 alarm.packageName, alarm.type, alarm.statsTag, nowELAPSED);
3042 mInFlight.add(inflight);
3043 mBroadcastRefCount++;
3045 if (allowWhileIdle) {
3046 // Record the last time this uid handled an ALLOW_WHILE_IDLE alarm.
3047 mLastAllowWhileIdleDispatch.put(alarm.uid, nowELAPSED);
3048 if (RECORD_DEVICE_IDLE_ALARMS) {
3049 IdleDispatchEntry ent = new IdleDispatchEntry();
3050 ent.uid = alarm.uid;
3051 ent.pkg = alarm.packageName;
3052 ent.tag = alarm.statsTag;
3054 ent.elapsedRealtime = nowELAPSED;
3055 mAllowWhileIdleDispatches.add(ent);
3059 final BroadcastStats bs = inflight.mBroadcastStats;
3061 if (bs.nesting == 0) {
3063 bs.startTime = nowELAPSED;
3067 final FilterStats fs = inflight.mFilterStats;
3069 if (fs.nesting == 0) {
3071 fs.startTime = nowELAPSED;
3075 if (alarm.type == ELAPSED_REALTIME_WAKEUP
3076 || alarm.type == RTC_WAKEUP) {
3079 if (alarm.workSource != null && alarm.workSource.size() > 0) {
3080 for (int wi=0; wi<alarm.workSource.size(); wi++) {
3081 final String wsName = alarm.workSource.getName(wi);
3082 ActivityManagerNative.noteWakeupAlarm(
3083 alarm.operation, alarm.workSource.get(wi),
3084 (wsName != null) ? wsName : alarm.packageName,
3088 ActivityManagerNative.noteWakeupAlarm(
3089 alarm.operation, alarm.uid, alarm.packageName, alarm.statsTag);