AlarmManagerService.java revision 14a7bb0d370fffdf902a4e2345f46754ed2d7684
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
19import android.app.Activity;
20import android.app.ActivityManager;
21import android.app.ActivityManagerNative;
22import android.app.AlarmManager;
23import android.app.AppOpsManager;
24import android.app.BroadcastOptions;
25import android.app.IAlarmCompleteListener;
26import android.app.IAlarmListener;
27import android.app.IAlarmManager;
28import android.app.PendingIntent;
29import android.content.BroadcastReceiver;
30import android.content.ContentResolver;
31import android.content.Context;
32import android.content.Intent;
33import android.content.IntentFilter;
34import android.content.pm.PackageManager;
35import android.database.ContentObserver;
36import android.net.Uri;
37import android.os.Binder;
38import android.os.Bundle;
39import android.os.Handler;
40import android.os.IBinder;
41import android.os.Message;
42import android.os.PowerManager;
43import android.os.Process;
44import android.os.SystemClock;
45import android.os.SystemProperties;
46import android.os.UserHandle;
47import android.os.WorkSource;
48import android.provider.Settings;
49import android.text.TextUtils;
50import android.text.format.DateFormat;
51import android.util.ArrayMap;
52import android.util.KeyValueListParser;
53import android.util.Log;
54import android.util.Slog;
55import android.util.SparseArray;
56import android.util.SparseBooleanArray;
57import android.util.SparseLongArray;
58import android.util.TimeUtils;
59
60import java.io.ByteArrayOutputStream;
61import java.io.FileDescriptor;
62import java.io.PrintWriter;
63import java.text.SimpleDateFormat;
64import java.util.ArrayList;
65import java.util.Arrays;
66import java.util.Calendar;
67import java.util.Collections;
68import java.util.Comparator;
69import java.util.Date;
70import java.util.HashMap;
71import java.util.LinkedList;
72import java.util.Locale;
73import java.util.Random;
74import java.util.TimeZone;
75import java.util.TreeSet;
76
77import static android.app.AlarmManager.RTC_WAKEUP;
78import static android.app.AlarmManager.RTC;
79import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP;
80import static android.app.AlarmManager.ELAPSED_REALTIME;
81
82import com.android.internal.util.LocalLog;
83
84class AlarmManagerService extends SystemService {
85    private static final int RTC_WAKEUP_MASK = 1 << RTC_WAKEUP;
86    private static final int RTC_MASK = 1 << RTC;
87    private static final int ELAPSED_REALTIME_WAKEUP_MASK = 1 << ELAPSED_REALTIME_WAKEUP;
88    private static final int ELAPSED_REALTIME_MASK = 1 << ELAPSED_REALTIME;
89    static final int TIME_CHANGED_MASK = 1 << 16;
90    static final int IS_WAKEUP_MASK = RTC_WAKEUP_MASK|ELAPSED_REALTIME_WAKEUP_MASK;
91
92    // Mask for testing whether a given alarm type is wakeup vs non-wakeup
93    static final int TYPE_NONWAKEUP_MASK = 0x1; // low bit => non-wakeup
94
95    static final String TAG = "AlarmManager";
96    static final boolean localLOGV = false;
97    static final boolean DEBUG_BATCH = localLOGV || false;
98    static final boolean DEBUG_VALIDATE = localLOGV || false;
99    static final boolean DEBUG_ALARM_CLOCK = localLOGV || false;
100    static final boolean DEBUG_LISTENER_CALLBACK = localLOGV || false;
101    static final boolean RECORD_ALARMS_IN_HISTORY = true;
102    static final boolean RECORD_DEVICE_IDLE_ALARMS = false;
103    static final int ALARM_EVENT = 1;
104    static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
105
106    private final Intent mBackgroundIntent
107            = new Intent().addFlags(Intent.FLAG_FROM_BACKGROUND);
108    static final IncreasingTimeOrder sIncreasingTimeOrder = new IncreasingTimeOrder();
109
110    static final boolean WAKEUP_STATS = false;
111
112    private static final Intent NEXT_ALARM_CLOCK_CHANGED_INTENT = new Intent(
113            AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED);
114
115    final LocalLog mLog = new LocalLog(TAG);
116
117    AppOpsManager mAppOps;
118
119    final Object mLock = new Object();
120
121    long mNativeData;
122    private long mNextWakeup;
123    private long mNextNonWakeup;
124    int mBroadcastRefCount = 0;
125    PowerManager.WakeLock mWakeLock;
126    boolean mLastWakeLockUnimportantForLogging;
127    ArrayList<Alarm> mPendingNonWakeupAlarms = new ArrayList<>();
128    ArrayList<InFlight> mInFlight = new ArrayList<>();
129    final AlarmHandler mHandler = new AlarmHandler();
130    ClockReceiver mClockReceiver;
131    InteractiveStateReceiver mInteractiveStateReceiver;
132    private UninstallReceiver mUninstallReceiver;
133    final DeliveryTracker mDeliveryTracker = new DeliveryTracker();
134    PendingIntent mTimeTickSender;
135    PendingIntent mDateChangeSender;
136    Random mRandom;
137    boolean mInteractive = true;
138    long mNonInteractiveStartTime;
139    long mNonInteractiveTime;
140    long mLastAlarmDeliveryTime;
141    long mStartCurrentDelayTime;
142    long mNextNonWakeupDeliveryTime;
143    long mLastTimeChangeClockTime;
144    long mLastTimeChangeRealtime;
145    long mAllowWhileIdleMinTime;
146    int mNumTimeChanged;
147
148    /**
149     * For each uid, this is the last time we dispatched an "allow while idle" alarm,
150     * used to determine the earliest we can dispatch the next such alarm.
151     */
152    final SparseLongArray mLastAllowWhileIdleDispatch = new SparseLongArray();
153
154    final static class IdleDispatchEntry {
155        int uid;
156        String pkg;
157        String tag;
158        String op;
159        long elapsedRealtime;
160        long argRealtime;
161    }
162    final ArrayList<IdleDispatchEntry> mAllowWhileIdleDispatches = new ArrayList();
163
164    /**
165     * Broadcast options to use for FLAG_ALLOW_WHILE_IDLE.
166     */
167    Bundle mIdleOptions;
168
169    private final SparseArray<AlarmManager.AlarmClockInfo> mNextAlarmClockForUser =
170            new SparseArray<>();
171    private final SparseArray<AlarmManager.AlarmClockInfo> mTmpSparseAlarmClockArray =
172            new SparseArray<>();
173    private final SparseBooleanArray mPendingSendNextAlarmClockChangedForUser =
174            new SparseBooleanArray();
175    private boolean mNextAlarmClockMayChange;
176
177    // May only use on mHandler's thread, locking not required.
178    private final SparseArray<AlarmManager.AlarmClockInfo> mHandlerSparseAlarmClockArray =
179            new SparseArray<>();
180
181    /**
182     * All times are in milliseconds. These constants are kept synchronized with the system
183     * global Settings. Any access to this class or its fields should be done while
184     * holding the AlarmManagerService.mLock lock.
185     */
186    private final class Constants extends ContentObserver {
187        // Key names stored in the settings value.
188        private static final String KEY_MIN_FUTURITY = "min_futurity";
189        private static final String KEY_MIN_INTERVAL = "min_interval";
190        private static final String KEY_ALLOW_WHILE_IDLE_SHORT_TIME = "allow_while_idle_short_time";
191        private static final String KEY_ALLOW_WHILE_IDLE_LONG_TIME = "allow_while_idle_long_time";
192        private static final String KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION
193                = "allow_while_idle_whitelist_duration";
194        private static final String KEY_LISTENER_TIMEOUT = "listener_timeout";
195
196        private static final long DEFAULT_MIN_FUTURITY = 5 * 1000;
197        private static final long DEFAULT_MIN_INTERVAL = 60 * 1000;
198        private static final long DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME = DEFAULT_MIN_FUTURITY;
199        private static final long DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME = 9*60*1000;
200        private static final long DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION = 10*1000;
201
202        private static final long DEFAULT_LISTENER_TIMEOUT = 5 * 1000;
203
204        // Minimum futurity of a new alarm
205        public long MIN_FUTURITY = DEFAULT_MIN_FUTURITY;
206
207        // Minimum alarm recurrence interval
208        public long MIN_INTERVAL = DEFAULT_MIN_INTERVAL;
209
210        // Minimum time between ALLOW_WHILE_IDLE alarms when system is not idle.
211        public long ALLOW_WHILE_IDLE_SHORT_TIME = DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME;
212
213        // Minimum time between ALLOW_WHILE_IDLE alarms when system is idling.
214        public long ALLOW_WHILE_IDLE_LONG_TIME = DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME;
215
216        // BroadcastOptions.setTemporaryAppWhitelistDuration() to use for FLAG_ALLOW_WHILE_IDLE.
217        public long ALLOW_WHILE_IDLE_WHITELIST_DURATION
218                = DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION;
219
220        // Direct alarm listener callback timeout
221        public long LISTENER_TIMEOUT = DEFAULT_LISTENER_TIMEOUT;
222
223        private ContentResolver mResolver;
224        private final KeyValueListParser mParser = new KeyValueListParser(',');
225        private long mLastAllowWhileIdleWhitelistDuration = -1;
226
227        public Constants(Handler handler) {
228            super(handler);
229            updateAllowWhileIdleMinTimeLocked();
230            updateAllowWhileIdleWhitelistDurationLocked();
231        }
232
233        public void start(ContentResolver resolver) {
234            mResolver = resolver;
235            mResolver.registerContentObserver(Settings.Global.getUriFor(
236                    Settings.Global.ALARM_MANAGER_CONSTANTS), false, this);
237            updateConstants();
238        }
239
240        public void updateAllowWhileIdleMinTimeLocked() {
241            mAllowWhileIdleMinTime = mPendingIdleUntil != null
242                    ? ALLOW_WHILE_IDLE_LONG_TIME : ALLOW_WHILE_IDLE_SHORT_TIME;
243        }
244
245        public void updateAllowWhileIdleWhitelistDurationLocked() {
246            if (mLastAllowWhileIdleWhitelistDuration != ALLOW_WHILE_IDLE_WHITELIST_DURATION) {
247                mLastAllowWhileIdleWhitelistDuration = ALLOW_WHILE_IDLE_WHITELIST_DURATION;
248                BroadcastOptions opts = BroadcastOptions.makeBasic();
249                opts.setTemporaryAppWhitelistDuration(ALLOW_WHILE_IDLE_WHITELIST_DURATION);
250                mIdleOptions = opts.toBundle();
251            }
252        }
253
254        @Override
255        public void onChange(boolean selfChange, Uri uri) {
256            updateConstants();
257        }
258
259        private void updateConstants() {
260            synchronized (mLock) {
261                try {
262                    mParser.setString(Settings.Global.getString(mResolver,
263                            Settings.Global.ALARM_MANAGER_CONSTANTS));
264                } catch (IllegalArgumentException e) {
265                    // Failed to parse the settings string, log this and move on
266                    // with defaults.
267                    Slog.e(TAG, "Bad device idle settings", e);
268                }
269
270                MIN_FUTURITY = mParser.getLong(KEY_MIN_FUTURITY, DEFAULT_MIN_FUTURITY);
271                MIN_INTERVAL = mParser.getLong(KEY_MIN_INTERVAL, DEFAULT_MIN_INTERVAL);
272                ALLOW_WHILE_IDLE_SHORT_TIME = mParser.getLong(KEY_ALLOW_WHILE_IDLE_SHORT_TIME,
273                        DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME);
274                ALLOW_WHILE_IDLE_LONG_TIME = mParser.getLong(KEY_ALLOW_WHILE_IDLE_LONG_TIME,
275                        DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME);
276                ALLOW_WHILE_IDLE_WHITELIST_DURATION = mParser.getLong(
277                        KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION,
278                        DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION);
279                LISTENER_TIMEOUT = mParser.getLong(KEY_LISTENER_TIMEOUT,
280                        DEFAULT_LISTENER_TIMEOUT);
281
282                updateAllowWhileIdleMinTimeLocked();
283                updateAllowWhileIdleWhitelistDurationLocked();
284            }
285        }
286
287        void dump(PrintWriter pw) {
288            pw.println("  Settings:");
289
290            pw.print("    "); pw.print(KEY_MIN_FUTURITY); pw.print("=");
291            TimeUtils.formatDuration(MIN_FUTURITY, pw);
292            pw.println();
293
294            pw.print("    "); pw.print(KEY_MIN_INTERVAL); pw.print("=");
295            TimeUtils.formatDuration(MIN_INTERVAL, pw);
296            pw.println();
297
298            pw.print("    "); pw.print(KEY_LISTENER_TIMEOUT); pw.print("=");
299            TimeUtils.formatDuration(LISTENER_TIMEOUT, pw);
300            pw.println();
301
302            pw.print("    "); pw.print(KEY_ALLOW_WHILE_IDLE_SHORT_TIME); pw.print("=");
303            TimeUtils.formatDuration(ALLOW_WHILE_IDLE_SHORT_TIME, pw);
304            pw.println();
305
306            pw.print("    "); pw.print(KEY_ALLOW_WHILE_IDLE_LONG_TIME); pw.print("=");
307            TimeUtils.formatDuration(ALLOW_WHILE_IDLE_LONG_TIME, pw);
308            pw.println();
309
310            pw.print("    "); pw.print(KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION); pw.print("=");
311            TimeUtils.formatDuration(ALLOW_WHILE_IDLE_WHITELIST_DURATION, pw);
312            pw.println();
313        }
314    }
315
316    final Constants mConstants;
317
318    // Alarm delivery ordering bookkeeping
319    static final int PRIO_TICK = 0;
320    static final int PRIO_WAKEUP = 1;
321    static final int PRIO_NORMAL = 2;
322
323    final class PriorityClass {
324        int seq;
325        int priority;
326
327        PriorityClass() {
328            seq = mCurrentSeq - 1;
329            priority = PRIO_NORMAL;
330        }
331    }
332
333    final HashMap<String, PriorityClass> mPriorities = new HashMap<>();
334    int mCurrentSeq = 0;
335
336    static final class WakeupEvent {
337        public long when;
338        public int uid;
339        public String action;
340
341        public WakeupEvent(long theTime, int theUid, String theAction) {
342            when = theTime;
343            uid = theUid;
344            action = theAction;
345        }
346    }
347
348    final LinkedList<WakeupEvent> mRecentWakeups = new LinkedList<WakeupEvent>();
349    final long RECENT_WAKEUP_PERIOD = 1000L * 60 * 60 * 24; // one day
350
351    final class Batch {
352        long start;     // These endpoints are always in ELAPSED
353        long end;
354        int flags;      // Flags for alarms, such as FLAG_STANDALONE.
355
356        final ArrayList<Alarm> alarms = new ArrayList<Alarm>();
357
358        Batch() {
359            start = 0;
360            end = Long.MAX_VALUE;
361            flags = 0;
362        }
363
364        Batch(Alarm seed) {
365            start = seed.whenElapsed;
366            end = seed.maxWhenElapsed;
367            flags = seed.flags;
368            alarms.add(seed);
369        }
370
371        int size() {
372            return alarms.size();
373        }
374
375        Alarm get(int index) {
376            return alarms.get(index);
377        }
378
379        boolean canHold(long whenElapsed, long maxWhen) {
380            return (end >= whenElapsed) && (start <= maxWhen);
381        }
382
383        boolean add(Alarm alarm) {
384            boolean newStart = false;
385            // narrows the batch if necessary; presumes that canHold(alarm) is true
386            int index = Collections.binarySearch(alarms, alarm, sIncreasingTimeOrder);
387            if (index < 0) {
388                index = 0 - index - 1;
389            }
390            alarms.add(index, alarm);
391            if (DEBUG_BATCH) {
392                Slog.v(TAG, "Adding " + alarm + " to " + this);
393            }
394            if (alarm.whenElapsed > start) {
395                start = alarm.whenElapsed;
396                newStart = true;
397            }
398            if (alarm.maxWhenElapsed < end) {
399                end = alarm.maxWhenElapsed;
400            }
401            flags |= alarm.flags;
402
403            if (DEBUG_BATCH) {
404                Slog.v(TAG, "    => now " + this);
405            }
406            return newStart;
407        }
408
409        boolean remove(final PendingIntent operation, final IAlarmListener listener) {
410            if (operation == null && listener == null) {
411                if (localLOGV) {
412                    Slog.w(TAG, "requested remove() of null operation",
413                            new RuntimeException("here"));
414                }
415                return false;
416            }
417            boolean didRemove = false;
418            long newStart = 0;  // recalculate endpoints as we go
419            long newEnd = Long.MAX_VALUE;
420            int newFlags = 0;
421            for (int i = 0; i < alarms.size(); ) {
422                Alarm alarm = alarms.get(i);
423                if (alarm.matches(operation, listener)) {
424                    alarms.remove(i);
425                    didRemove = true;
426                    if (alarm.alarmClock != null) {
427                        mNextAlarmClockMayChange = true;
428                    }
429                } else {
430                    if (alarm.whenElapsed > newStart) {
431                        newStart = alarm.whenElapsed;
432                    }
433                    if (alarm.maxWhenElapsed < newEnd) {
434                        newEnd = alarm.maxWhenElapsed;
435                    }
436                    newFlags |= alarm.flags;
437                    i++;
438                }
439            }
440            if (didRemove) {
441                // commit the new batch bounds
442                start = newStart;
443                end = newEnd;
444                flags = newFlags;
445            }
446            return didRemove;
447        }
448
449        boolean remove(final String packageName) {
450            if (packageName == null) {
451                if (localLOGV) {
452                    Slog.w(TAG, "requested remove() of null packageName",
453                            new RuntimeException("here"));
454                }
455                return false;
456            }
457            boolean didRemove = false;
458            long newStart = 0;  // recalculate endpoints as we go
459            long newEnd = Long.MAX_VALUE;
460            int newFlags = 0;
461            for (int i = 0; i < alarms.size(); ) {
462                Alarm alarm = alarms.get(i);
463                if (alarm.matches(packageName)) {
464                    alarms.remove(i);
465                    didRemove = true;
466                    if (alarm.alarmClock != null) {
467                        mNextAlarmClockMayChange = true;
468                    }
469                } else {
470                    if (alarm.whenElapsed > newStart) {
471                        newStart = alarm.whenElapsed;
472                    }
473                    if (alarm.maxWhenElapsed < newEnd) {
474                        newEnd = alarm.maxWhenElapsed;
475                    }
476                    newFlags |= alarm.flags;
477                    i++;
478                }
479            }
480            if (didRemove) {
481                // commit the new batch bounds
482                start = newStart;
483                end = newEnd;
484                flags = newFlags;
485            }
486            return didRemove;
487        }
488
489        boolean remove(final int userHandle) {
490            boolean didRemove = false;
491            long newStart = 0;  // recalculate endpoints as we go
492            long newEnd = Long.MAX_VALUE;
493            for (int i = 0; i < alarms.size(); ) {
494                Alarm alarm = alarms.get(i);
495                if (UserHandle.getUserId(alarm.creatorUid) == userHandle) {
496                    alarms.remove(i);
497                    didRemove = true;
498                    if (alarm.alarmClock != null) {
499                        mNextAlarmClockMayChange = true;
500                    }
501                } else {
502                    if (alarm.whenElapsed > newStart) {
503                        newStart = alarm.whenElapsed;
504                    }
505                    if (alarm.maxWhenElapsed < newEnd) {
506                        newEnd = alarm.maxWhenElapsed;
507                    }
508                    i++;
509                }
510            }
511            if (didRemove) {
512                // commit the new batch bounds
513                start = newStart;
514                end = newEnd;
515            }
516            return didRemove;
517        }
518
519        boolean hasPackage(final String packageName) {
520            final int N = alarms.size();
521            for (int i = 0; i < N; i++) {
522                Alarm a = alarms.get(i);
523                if (a.matches(packageName)) {
524                    return true;
525                }
526            }
527            return false;
528        }
529
530        boolean hasWakeups() {
531            final int N = alarms.size();
532            for (int i = 0; i < N; i++) {
533                Alarm a = alarms.get(i);
534                // non-wakeup alarms are types 1 and 3, i.e. have the low bit set
535                if ((a.type & TYPE_NONWAKEUP_MASK) == 0) {
536                    return true;
537                }
538            }
539            return false;
540        }
541
542        @Override
543        public String toString() {
544            StringBuilder b = new StringBuilder(40);
545            b.append("Batch{"); b.append(Integer.toHexString(this.hashCode()));
546            b.append(" num="); b.append(size());
547            b.append(" start="); b.append(start);
548            b.append(" end="); b.append(end);
549            if (flags != 0) {
550                b.append(" flgs=0x");
551                b.append(Integer.toHexString(flags));
552            }
553            b.append('}');
554            return b.toString();
555        }
556    }
557
558    static class BatchTimeOrder implements Comparator<Batch> {
559        public int compare(Batch b1, Batch b2) {
560            long when1 = b1.start;
561            long when2 = b2.start;
562            if (when1 > when2) {
563                return 1;
564            }
565            if (when1 < when2) {
566                return -1;
567            }
568            return 0;
569        }
570    }
571
572    final Comparator<Alarm> mAlarmDispatchComparator = new Comparator<Alarm>() {
573        @Override
574        public int compare(Alarm lhs, Alarm rhs) {
575            // priority class trumps everything.  TICK < WAKEUP < NORMAL
576            if (lhs.priorityClass.priority < rhs.priorityClass.priority) {
577                return -1;
578            } else if (lhs.priorityClass.priority > rhs.priorityClass.priority) {
579                return 1;
580            }
581
582            // within each class, sort by nominal delivery time
583            if (lhs.whenElapsed < rhs.whenElapsed) {
584                return -1;
585            } else if (lhs.whenElapsed > rhs.whenElapsed) {
586                return 1;
587            }
588
589            // same priority class + same target delivery time
590            return 0;
591        }
592    };
593
594    void calculateDeliveryPriorities(ArrayList<Alarm> alarms) {
595        final int N = alarms.size();
596        for (int i = 0; i < N; i++) {
597            Alarm a = alarms.get(i);
598
599            final int alarmPrio;
600            if (a.operation != null
601                    && Intent.ACTION_TIME_TICK.equals(a.operation.getIntent().getAction())) {
602                alarmPrio = PRIO_TICK;
603            } else if (a.wakeup) {
604                alarmPrio = PRIO_WAKEUP;
605            } else {
606                alarmPrio = PRIO_NORMAL;
607            }
608
609            PriorityClass packagePrio = a.priorityClass;
610            String alarmPackage = (a.operation != null)
611                    ? a.operation.getCreatorPackage()
612                    : a.packageName;
613            if (packagePrio == null) packagePrio = mPriorities.get(alarmPackage);
614            if (packagePrio == null) {
615                packagePrio = a.priorityClass = new PriorityClass(); // lowest prio & stale sequence
616                mPriorities.put(alarmPackage, packagePrio);
617            }
618            a.priorityClass = packagePrio;
619
620            if (packagePrio.seq != mCurrentSeq) {
621                // first alarm we've seen in the current delivery generation from this package
622                packagePrio.priority = alarmPrio;
623                packagePrio.seq = mCurrentSeq;
624            } else {
625                // Multiple alarms from this package being delivered in this generation;
626                // bump the package's delivery class if it's warranted.
627                // TICK < WAKEUP < NORMAL
628                if (alarmPrio < packagePrio.priority) {
629                    packagePrio.priority = alarmPrio;
630                }
631            }
632        }
633    }
634
635    // minimum recurrence period or alarm futurity for us to be able to fuzz it
636    static final long MIN_FUZZABLE_INTERVAL = 10000;
637    static final BatchTimeOrder sBatchOrder = new BatchTimeOrder();
638    final ArrayList<Batch> mAlarmBatches = new ArrayList<>();
639
640    // set to null if in idle mode; while in this mode, any alarms we don't want
641    // to run during this time are placed in mPendingWhileIdleAlarms
642    Alarm mPendingIdleUntil = null;
643    Alarm mNextWakeFromIdle = null;
644    ArrayList<Alarm> mPendingWhileIdleAlarms = new ArrayList<>();
645
646    public AlarmManagerService(Context context) {
647        super(context);
648        mConstants = new Constants(mHandler);
649    }
650
651    static long convertToElapsed(long when, int type) {
652        final boolean isRtc = (type == RTC || type == RTC_WAKEUP);
653        if (isRtc) {
654            when -= System.currentTimeMillis() - SystemClock.elapsedRealtime();
655        }
656        return when;
657    }
658
659    // Apply a heuristic to { recurrence interval, futurity of the trigger time } to
660    // calculate the end of our nominal delivery window for the alarm.
661    static long maxTriggerTime(long now, long triggerAtTime, long interval) {
662        // Current heuristic: batchable window is 75% of either the recurrence interval
663        // [for a periodic alarm] or of the time from now to the desired delivery time,
664        // with a minimum delay/interval of 10 seconds, under which we will simply not
665        // defer the alarm.
666        long futurity = (interval == 0)
667                ? (triggerAtTime - now)
668                : interval;
669        if (futurity < MIN_FUZZABLE_INTERVAL) {
670            futurity = 0;
671        }
672        return triggerAtTime + (long)(.75 * futurity);
673    }
674
675    // returns true if the batch was added at the head
676    static boolean addBatchLocked(ArrayList<Batch> list, Batch newBatch) {
677        int index = Collections.binarySearch(list, newBatch, sBatchOrder);
678        if (index < 0) {
679            index = 0 - index - 1;
680        }
681        list.add(index, newBatch);
682        return (index == 0);
683    }
684
685    // Return the index of the matching batch, or -1 if none found.
686    int attemptCoalesceLocked(long whenElapsed, long maxWhen) {
687        final int N = mAlarmBatches.size();
688        for (int i = 0; i < N; i++) {
689            Batch b = mAlarmBatches.get(i);
690            if ((b.flags&AlarmManager.FLAG_STANDALONE) == 0 && b.canHold(whenElapsed, maxWhen)) {
691                return i;
692            }
693        }
694        return -1;
695    }
696
697    // The RTC clock has moved arbitrarily, so we need to recalculate all the batching
698    void rebatchAllAlarms() {
699        synchronized (mLock) {
700            rebatchAllAlarmsLocked(true);
701        }
702    }
703
704    void rebatchAllAlarmsLocked(boolean doValidate) {
705        ArrayList<Batch> oldSet = (ArrayList<Batch>) mAlarmBatches.clone();
706        mAlarmBatches.clear();
707        Alarm oldPendingIdleUntil = mPendingIdleUntil;
708        final long nowElapsed = SystemClock.elapsedRealtime();
709        final int oldBatches = oldSet.size();
710        for (int batchNum = 0; batchNum < oldBatches; batchNum++) {
711            Batch batch = oldSet.get(batchNum);
712            final int N = batch.size();
713            for (int i = 0; i < N; i++) {
714                reAddAlarmLocked(batch.get(i), nowElapsed, doValidate);
715            }
716        }
717        if (oldPendingIdleUntil != null && oldPendingIdleUntil != mPendingIdleUntil) {
718            Slog.wtf(TAG, "Rebatching: idle until changed from " + oldPendingIdleUntil
719                    + " to " + mPendingIdleUntil);
720            if (mPendingIdleUntil == null) {
721                // Somehow we lost this...  we need to restore all of the pending alarms.
722                restorePendingWhileIdleAlarmsLocked();
723            }
724        }
725        rescheduleKernelAlarmsLocked();
726        updateNextAlarmClockLocked();
727    }
728
729    void reAddAlarmLocked(Alarm a, long nowElapsed, boolean doValidate) {
730        a.when = a.origWhen;
731        long whenElapsed = convertToElapsed(a.when, a.type);
732        final long maxElapsed;
733        if (a.windowLength == AlarmManager.WINDOW_EXACT) {
734            // Exact
735            maxElapsed = whenElapsed;
736        } else {
737            // Not exact.  Preserve any explicit window, otherwise recalculate
738            // the window based on the alarm's new futurity.  Note that this
739            // reflects a policy of preferring timely to deferred delivery.
740            maxElapsed = (a.windowLength > 0)
741                    ? (whenElapsed + a.windowLength)
742                    : maxTriggerTime(nowElapsed, whenElapsed, a.repeatInterval);
743        }
744        a.whenElapsed = whenElapsed;
745        a.maxWhenElapsed = maxElapsed;
746        setImplLocked(a, true, doValidate);
747    }
748
749    void restorePendingWhileIdleAlarmsLocked() {
750        if (RECORD_DEVICE_IDLE_ALARMS) {
751            IdleDispatchEntry ent = new IdleDispatchEntry();
752            ent.uid = 0;
753            ent.pkg = "FINISH IDLE";
754            ent.elapsedRealtime = SystemClock.elapsedRealtime();
755            mAllowWhileIdleDispatches.add(ent);
756        }
757
758        // Bring pending alarms back into the main list.
759        if (mPendingWhileIdleAlarms.size() > 0) {
760            ArrayList<Alarm> alarms = mPendingWhileIdleAlarms;
761            mPendingWhileIdleAlarms = new ArrayList<>();
762            final long nowElapsed = SystemClock.elapsedRealtime();
763            for (int i=alarms.size() - 1; i >= 0; i--) {
764                Alarm a = alarms.get(i);
765                reAddAlarmLocked(a, nowElapsed, false);
766            }
767        }
768
769        // Make sure we are using the correct ALLOW_WHILE_IDLE min time.
770        mConstants.updateAllowWhileIdleMinTimeLocked();
771
772        // Reschedule everything.
773        rescheduleKernelAlarmsLocked();
774        updateNextAlarmClockLocked();
775
776        // And send a TIME_TICK right now, since it is important to get the UI updated.
777        try {
778            mTimeTickSender.send();
779        } catch (PendingIntent.CanceledException e) {
780        }
781    }
782
783    static final class InFlight {
784        final PendingIntent mPendingIntent;
785        final IBinder mListener;
786        final WorkSource mWorkSource;
787        final int mUid;
788        final String mTag;
789        final BroadcastStats mBroadcastStats;
790        final FilterStats mFilterStats;
791        final int mAlarmType;
792
793        InFlight(AlarmManagerService service, PendingIntent pendingIntent, IAlarmListener listener,
794                WorkSource workSource, int uid, String alarmPkg, int alarmType, String tag,
795                long nowELAPSED) {
796            mPendingIntent = pendingIntent;
797            mListener = listener != null ? listener.asBinder() : null;
798            mWorkSource = workSource;
799            mUid = uid;
800            mTag = tag;
801            mBroadcastStats = (pendingIntent != null)
802                    ? service.getStatsLocked(pendingIntent)
803                    : service.getStatsLocked(uid, alarmPkg);
804            FilterStats fs = mBroadcastStats.filterStats.get(mTag);
805            if (fs == null) {
806                fs = new FilterStats(mBroadcastStats, mTag);
807                mBroadcastStats.filterStats.put(mTag, fs);
808            }
809            fs.lastTime = nowELAPSED;
810            mFilterStats = fs;
811            mAlarmType = alarmType;
812        }
813    }
814
815    static final class FilterStats {
816        final BroadcastStats mBroadcastStats;
817        final String mTag;
818
819        long lastTime;
820        long aggregateTime;
821        int count;
822        int numWakeup;
823        long startTime;
824        int nesting;
825
826        FilterStats(BroadcastStats broadcastStats, String tag) {
827            mBroadcastStats = broadcastStats;
828            mTag = tag;
829        }
830    }
831
832    static final class BroadcastStats {
833        final int mUid;
834        final String mPackageName;
835
836        long aggregateTime;
837        int count;
838        int numWakeup;
839        long startTime;
840        int nesting;
841        final ArrayMap<String, FilterStats> filterStats = new ArrayMap<String, FilterStats>();
842
843        BroadcastStats(int uid, String packageName) {
844            mUid = uid;
845            mPackageName = packageName;
846        }
847    }
848
849    final SparseArray<ArrayMap<String, BroadcastStats>> mBroadcastStats
850            = new SparseArray<ArrayMap<String, BroadcastStats>>();
851
852    int mNumDelayedAlarms = 0;
853    long mTotalDelayTime = 0;
854    long mMaxDelayTime = 0;
855
856    @Override
857    public void onStart() {
858        mNativeData = init();
859        mNextWakeup = mNextNonWakeup = 0;
860
861        // We have to set current TimeZone info to kernel
862        // because kernel doesn't keep this after reboot
863        setTimeZoneImpl(SystemProperties.get(TIMEZONE_PROPERTY));
864
865        PowerManager pm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE);
866        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*alarm*");
867
868        mTimeTickSender = PendingIntent.getBroadcastAsUser(getContext(), 0,
869                new Intent(Intent.ACTION_TIME_TICK).addFlags(
870                        Intent.FLAG_RECEIVER_REGISTERED_ONLY
871                        | Intent.FLAG_RECEIVER_FOREGROUND), 0,
872                        UserHandle.ALL);
873        Intent intent = new Intent(Intent.ACTION_DATE_CHANGED);
874        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
875        mDateChangeSender = PendingIntent.getBroadcastAsUser(getContext(), 0, intent,
876                Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT, UserHandle.ALL);
877
878        // now that we have initied the driver schedule the alarm
879        mClockReceiver = new ClockReceiver();
880        mClockReceiver.scheduleTimeTickEvent();
881        mClockReceiver.scheduleDateChangedEvent();
882        mInteractiveStateReceiver = new InteractiveStateReceiver();
883        mUninstallReceiver = new UninstallReceiver();
884
885        if (mNativeData != 0) {
886            AlarmThread waitThread = new AlarmThread();
887            waitThread.start();
888        } else {
889            Slog.w(TAG, "Failed to open alarm driver. Falling back to a handler.");
890        }
891
892        publishBinderService(Context.ALARM_SERVICE, mService);
893    }
894
895    @Override
896    public void onBootPhase(int phase) {
897        if (phase == PHASE_SYSTEM_SERVICES_READY) {
898            mConstants.start(getContext().getContentResolver());
899            mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
900        }
901    }
902
903    @Override
904    protected void finalize() throws Throwable {
905        try {
906            close(mNativeData);
907        } finally {
908            super.finalize();
909        }
910    }
911
912    void setTimeZoneImpl(String tz) {
913        if (TextUtils.isEmpty(tz)) {
914            return;
915        }
916
917        TimeZone zone = TimeZone.getTimeZone(tz);
918        // Prevent reentrant calls from stepping on each other when writing
919        // the time zone property
920        boolean timeZoneWasChanged = false;
921        synchronized (this) {
922            String current = SystemProperties.get(TIMEZONE_PROPERTY);
923            if (current == null || !current.equals(zone.getID())) {
924                if (localLOGV) {
925                    Slog.v(TAG, "timezone changed: " + current + ", new=" + zone.getID());
926                }
927                timeZoneWasChanged = true;
928                SystemProperties.set(TIMEZONE_PROPERTY, zone.getID());
929            }
930
931            // Update the kernel timezone information
932            // Kernel tracks time offsets as 'minutes west of GMT'
933            int gmtOffset = zone.getOffset(System.currentTimeMillis());
934            setKernelTimezone(mNativeData, -(gmtOffset / 60000));
935        }
936
937        TimeZone.setDefault(null);
938
939        if (timeZoneWasChanged) {
940            Intent intent = new Intent(Intent.ACTION_TIMEZONE_CHANGED);
941            intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
942            intent.putExtra("time-zone", zone.getID());
943            getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
944        }
945    }
946
947    void removeImpl(PendingIntent operation) {
948        if (operation == null) {
949            return;
950        }
951        synchronized (mLock) {
952            removeLocked(operation, null);
953        }
954    }
955
956    void setImpl(int type, long triggerAtTime, long windowLength, long interval,
957            PendingIntent operation, IAlarmListener directReceiver, String listenerTag,
958            int flags, WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock,
959            int callingUid, String callingPackage) {
960        // must be *either* PendingIntent or AlarmReceiver, but not both
961        if ((operation == null && directReceiver == null)
962                || (operation != null && directReceiver != null)) {
963            Slog.w(TAG, "Alarms must either supply a PendingIntent or an AlarmReceiver");
964            // NB: previous releases failed silently here, so we are continuing to do the same
965            // rather than throw an IllegalArgumentException.
966            return;
967        }
968
969        // Sanity check the window length.  This will catch people mistakenly
970        // trying to pass an end-of-window timestamp rather than a duration.
971        if (windowLength > AlarmManager.INTERVAL_HALF_DAY) {
972            Slog.w(TAG, "Window length " + windowLength
973                    + "ms suspiciously long; limiting to 1 hour");
974            windowLength = AlarmManager.INTERVAL_HOUR;
975        }
976
977        // Sanity check the recurrence interval.  This will catch people who supply
978        // seconds when the API expects milliseconds.
979        final long minInterval = mConstants.MIN_INTERVAL;
980        if (interval > 0 && interval < minInterval) {
981            Slog.w(TAG, "Suspiciously short interval " + interval
982                    + " millis; expanding to " + (minInterval/1000)
983                    + " seconds");
984            interval = minInterval;
985        }
986
987        if (type < RTC_WAKEUP || type > ELAPSED_REALTIME) {
988            throw new IllegalArgumentException("Invalid alarm type " + type);
989        }
990
991        if (triggerAtTime < 0) {
992            final long what = Binder.getCallingPid();
993            Slog.w(TAG, "Invalid alarm trigger time! " + triggerAtTime + " from uid=" + callingUid
994                    + " pid=" + what);
995            triggerAtTime = 0;
996        }
997
998        final long nowElapsed = SystemClock.elapsedRealtime();
999        final long nominalTrigger = convertToElapsed(triggerAtTime, type);
1000        // Try to prevent spamming by making sure we aren't firing alarms in the immediate future
1001        final long minTrigger = nowElapsed + mConstants.MIN_FUTURITY;
1002        final long triggerElapsed = (nominalTrigger > minTrigger) ? nominalTrigger : minTrigger;
1003
1004        final long maxElapsed;
1005        if (windowLength == AlarmManager.WINDOW_EXACT) {
1006            maxElapsed = triggerElapsed;
1007        } else if (windowLength < 0) {
1008            maxElapsed = maxTriggerTime(nowElapsed, triggerElapsed, interval);
1009            // Fix this window in place, so that as time approaches we don't collapse it.
1010            windowLength = maxElapsed - triggerElapsed;
1011        } else {
1012            maxElapsed = triggerElapsed + windowLength;
1013        }
1014
1015        synchronized (mLock) {
1016            if (DEBUG_BATCH) {
1017                Slog.v(TAG, "set(" + operation + ") : type=" + type
1018                        + " triggerAtTime=" + triggerAtTime + " win=" + windowLength
1019                        + " tElapsed=" + triggerElapsed + " maxElapsed=" + maxElapsed
1020                        + " interval=" + interval + " flags=0x" + Integer.toHexString(flags));
1021            }
1022            setImplLocked(type, triggerAtTime, triggerElapsed, windowLength, maxElapsed,
1023                    interval, operation, directReceiver, listenerTag, flags, true, workSource,
1024                    alarmClock, callingUid, callingPackage);
1025        }
1026    }
1027
1028    private void setImplLocked(int type, long when, long whenElapsed, long windowLength,
1029            long maxWhen, long interval, PendingIntent operation, IAlarmListener directReceiver,
1030            String listenerTag, int flags, boolean doValidate, WorkSource workSource,
1031            AlarmManager.AlarmClockInfo alarmClock, int callingUid, String callingPackage) {
1032        Alarm a = new Alarm(type, when, whenElapsed, windowLength, maxWhen, interval,
1033                operation, directReceiver, listenerTag, workSource, flags, alarmClock,
1034                callingUid, callingPackage);
1035        removeLocked(operation, directReceiver);
1036        setImplLocked(a, false, doValidate);
1037    }
1038
1039    private void setImplLocked(Alarm a, boolean rebatching, boolean doValidate) {
1040        if ((a.flags&AlarmManager.FLAG_IDLE_UNTIL) != 0) {
1041            // This is a special alarm that will put the system into idle until it goes off.
1042            // The caller has given the time they want this to happen at, however we need
1043            // to pull that earlier if there are existing alarms that have requested to
1044            // bring us out of idle at an earlier time.
1045            if (mNextWakeFromIdle != null && a.whenElapsed > mNextWakeFromIdle.whenElapsed) {
1046                a.when = a.whenElapsed = a.maxWhenElapsed = mNextWakeFromIdle.whenElapsed;
1047            }
1048            // Add fuzz to make the alarm go off some time before the actual desired time.
1049            final long nowElapsed = SystemClock.elapsedRealtime();
1050            final int fuzz = fuzzForDuration(a.whenElapsed-nowElapsed);
1051            if (fuzz > 0) {
1052                if (mRandom == null) {
1053                    mRandom = new Random();
1054                }
1055                final int delta = mRandom.nextInt(fuzz);
1056                a.whenElapsed -= delta;
1057                if (false) {
1058                    Slog.d(TAG, "Alarm when: " + a.whenElapsed);
1059                    Slog.d(TAG, "Delta until alarm: " + (a.whenElapsed-nowElapsed));
1060                    Slog.d(TAG, "Applied fuzz: " + fuzz);
1061                    Slog.d(TAG, "Final delta: " + delta);
1062                    Slog.d(TAG, "Final when: " + a.whenElapsed);
1063                }
1064                a.when = a.maxWhenElapsed = a.whenElapsed;
1065            }
1066
1067        } else if (mPendingIdleUntil != null) {
1068            // We currently have an idle until alarm scheduled; if the new alarm has
1069            // not explicitly stated it wants to run while idle, then put it on hold.
1070            if ((a.flags&(AlarmManager.FLAG_ALLOW_WHILE_IDLE
1071                    | AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED
1072                    | AlarmManager.FLAG_WAKE_FROM_IDLE))
1073                    == 0) {
1074                mPendingWhileIdleAlarms.add(a);
1075                return;
1076            }
1077        }
1078
1079        if (RECORD_DEVICE_IDLE_ALARMS) {
1080            if ((a.flags & AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) {
1081                IdleDispatchEntry ent = new IdleDispatchEntry();
1082                ent.uid = a.uid;
1083                ent.pkg = a.operation.getCreatorPackage();
1084                ent.tag = a.operation.getTag("");
1085                ent.op = "SET";
1086                ent.elapsedRealtime = SystemClock.elapsedRealtime();
1087                ent.argRealtime = a.whenElapsed;
1088                mAllowWhileIdleDispatches.add(ent);
1089            }
1090        }
1091
1092        int whichBatch = ((a.flags&AlarmManager.FLAG_STANDALONE) != 0)
1093                ? -1 : attemptCoalesceLocked(a.whenElapsed, a.maxWhenElapsed);
1094        if (whichBatch < 0) {
1095            Batch batch = new Batch(a);
1096            addBatchLocked(mAlarmBatches, batch);
1097        } else {
1098            Batch batch = mAlarmBatches.get(whichBatch);
1099            if (batch.add(a)) {
1100                // The start time of this batch advanced, so batch ordering may
1101                // have just been broken.  Move it to where it now belongs.
1102                mAlarmBatches.remove(whichBatch);
1103                addBatchLocked(mAlarmBatches, batch);
1104            }
1105        }
1106
1107        if (a.alarmClock != null) {
1108            mNextAlarmClockMayChange = true;
1109        }
1110
1111        boolean needRebatch = false;
1112
1113        if ((a.flags&AlarmManager.FLAG_IDLE_UNTIL) != 0) {
1114            if (RECORD_DEVICE_IDLE_ALARMS) {
1115                if (mPendingIdleUntil == null) {
1116                    IdleDispatchEntry ent = new IdleDispatchEntry();
1117                    ent.uid = 0;
1118                    ent.pkg = "START IDLE";
1119                    ent.elapsedRealtime = SystemClock.elapsedRealtime();
1120                    mAllowWhileIdleDispatches.add(ent);
1121                }
1122            }
1123            mPendingIdleUntil = a;
1124            mConstants.updateAllowWhileIdleMinTimeLocked();
1125            needRebatch = true;
1126        } else if ((a.flags&AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) {
1127            if (mNextWakeFromIdle == null || mNextWakeFromIdle.whenElapsed > a.whenElapsed) {
1128                mNextWakeFromIdle = a;
1129                // If this wake from idle is earlier than whatever was previously scheduled,
1130                // and we are currently idling, then we need to rebatch alarms in case the idle
1131                // until time needs to be updated.
1132                if (mPendingIdleUntil != null) {
1133                    needRebatch = true;
1134                }
1135            }
1136        }
1137
1138        if (!rebatching) {
1139            if (DEBUG_VALIDATE) {
1140                if (doValidate && !validateConsistencyLocked()) {
1141                    Slog.v(TAG, "Tipping-point operation: type=" + a.type + " when=" + a.when
1142                            + " when(hex)=" + Long.toHexString(a.when)
1143                            + " whenElapsed=" + a.whenElapsed
1144                            + " maxWhenElapsed=" + a.maxWhenElapsed
1145                            + " interval=" + a.repeatInterval + " op=" + a.operation
1146                            + " flags=0x" + Integer.toHexString(a.flags));
1147                    rebatchAllAlarmsLocked(false);
1148                    needRebatch = false;
1149                }
1150            }
1151
1152            if (needRebatch) {
1153                rebatchAllAlarmsLocked(false);
1154            }
1155
1156            rescheduleKernelAlarmsLocked();
1157            updateNextAlarmClockLocked();
1158        }
1159    }
1160
1161    private final IBinder mService = new IAlarmManager.Stub() {
1162        @Override
1163        public void set(String callingPackage,
1164                int type, long triggerAtTime, long windowLength, long interval, int flags,
1165                PendingIntent operation, IAlarmListener directReceiver, String listenerTag,
1166                WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock) {
1167            final int callingUid = Binder.getCallingUid();
1168
1169            // make sure the caller is not lying about which package should be blamed for
1170            // wakelock time spent in alarm delivery
1171            mAppOps.checkPackage(callingUid, callingPackage);
1172
1173            // Repeating alarms must use PendingIntent, not direct listener
1174            if (interval != 0) {
1175                if (directReceiver != null) {
1176                    throw new IllegalArgumentException("Repeating alarms cannot use AlarmReceivers");
1177                }
1178            }
1179
1180            // direct-callback alarms must be wakeup alarms (otherwise they should just be
1181            // posting work to a Handler)
1182            if (directReceiver != null) {
1183                if (type != RTC_WAKEUP && type != ELAPSED_REALTIME_WAKEUP) {
1184                    throw new IllegalArgumentException("Only wakeup alarms can use AlarmReceivers");
1185                }
1186            }
1187
1188            if (workSource != null) {
1189                getContext().enforcePermission(
1190                        android.Manifest.permission.UPDATE_DEVICE_STATS,
1191                        Binder.getCallingPid(), callingUid, "AlarmManager.set");
1192            }
1193
1194            // No incoming callers can request either WAKE_FROM_IDLE or
1195            // ALLOW_WHILE_IDLE_UNRESTRICTED -- we will apply those later as appropriate.
1196            flags &= ~(AlarmManager.FLAG_WAKE_FROM_IDLE
1197                    | AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED);
1198
1199            // Only the system can use FLAG_IDLE_UNTIL -- this is used to tell the alarm
1200            // manager when to come out of idle mode, which is only for DeviceIdleController.
1201            if (callingUid != Process.SYSTEM_UID) {
1202                flags &= ~AlarmManager.FLAG_IDLE_UNTIL;
1203            }
1204
1205            // If the caller is a core system component, and not calling to do work on behalf
1206            // of someone else, then always set ALLOW_WHILE_IDLE_UNRESTRICTED.  This means we
1207            // will allow these alarms to go off as normal even while idle, with no timing
1208            // restrictions.
1209            if (callingUid < Process.FIRST_APPLICATION_UID && workSource == null) {
1210                flags |= AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
1211            }
1212
1213            // If this is an exact time alarm, then it can't be batched with other alarms.
1214            if (windowLength == AlarmManager.WINDOW_EXACT) {
1215                flags |= AlarmManager.FLAG_STANDALONE;
1216            }
1217
1218            // If this alarm is for an alarm clock, then it must be standalone and we will
1219            // use it to wake early from idle if needed.
1220            if (alarmClock != null) {
1221                flags |= AlarmManager.FLAG_WAKE_FROM_IDLE | AlarmManager.FLAG_STANDALONE;
1222            }
1223
1224            setImpl(type, triggerAtTime, windowLength, interval, operation, directReceiver,
1225                    listenerTag, flags, workSource, alarmClock, callingUid, callingPackage);
1226        }
1227
1228        @Override
1229        public boolean setTime(long millis) {
1230            getContext().enforceCallingOrSelfPermission(
1231                    "android.permission.SET_TIME",
1232                    "setTime");
1233
1234            if (mNativeData == 0) {
1235                Slog.w(TAG, "Not setting time since no alarm driver is available.");
1236                return false;
1237            }
1238
1239            synchronized (mLock) {
1240                return setKernelTime(mNativeData, millis) == 0;
1241            }
1242        }
1243
1244        @Override
1245        public void setTimeZone(String tz) {
1246            getContext().enforceCallingOrSelfPermission(
1247                    "android.permission.SET_TIME_ZONE",
1248                    "setTimeZone");
1249
1250            final long oldId = Binder.clearCallingIdentity();
1251            try {
1252                setTimeZoneImpl(tz);
1253            } finally {
1254                Binder.restoreCallingIdentity(oldId);
1255            }
1256        }
1257
1258        @Override
1259        public void remove(PendingIntent operation, IAlarmListener listener) {
1260            if (operation == null && listener == null) {
1261                Slog.w(TAG, "remove() with no intent or listener");
1262                return;
1263            }
1264
1265            synchronized (mLock) {
1266                removeLocked(operation, listener);
1267            }
1268        }
1269
1270        @Override
1271        public long getNextWakeFromIdleTime() {
1272            return getNextWakeFromIdleTimeImpl();
1273        }
1274
1275        @Override
1276        public AlarmManager.AlarmClockInfo getNextAlarmClock(int userId) {
1277            userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
1278                    Binder.getCallingUid(), userId, false /* allowAll */, false /* requireFull */,
1279                    "getNextAlarmClock", null);
1280
1281            return getNextAlarmClockImpl(userId);
1282        }
1283
1284        @Override
1285        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1286            if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
1287                    != PackageManager.PERMISSION_GRANTED) {
1288                pw.println("Permission Denial: can't dump AlarmManager from from pid="
1289                        + Binder.getCallingPid()
1290                        + ", uid=" + Binder.getCallingUid());
1291                return;
1292            }
1293
1294            dumpImpl(pw);
1295        }
1296    };
1297
1298    void dumpImpl(PrintWriter pw) {
1299        synchronized (mLock) {
1300            pw.println("Current Alarm Manager state:");
1301            mConstants.dump(pw);
1302            pw.println();
1303
1304            final long nowRTC = System.currentTimeMillis();
1305            final long nowELAPSED = SystemClock.elapsedRealtime();
1306            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
1307
1308            pw.print("  nowRTC="); pw.print(nowRTC);
1309            pw.print("="); pw.print(sdf.format(new Date(nowRTC)));
1310            pw.print(" nowELAPSED="); TimeUtils.formatDuration(nowELAPSED, pw);
1311            pw.println();
1312            pw.print("  mLastTimeChangeClockTime="); pw.print(mLastTimeChangeClockTime);
1313            pw.print("="); pw.println(sdf.format(new Date(mLastTimeChangeClockTime)));
1314            pw.print("  mLastTimeChangeRealtime=");
1315            TimeUtils.formatDuration(mLastTimeChangeRealtime, pw);
1316            pw.println();
1317            if (!mInteractive) {
1318                pw.print("  Time since non-interactive: ");
1319                TimeUtils.formatDuration(nowELAPSED - mNonInteractiveStartTime, pw);
1320                pw.println();
1321                pw.print("  Max wakeup delay: ");
1322                TimeUtils.formatDuration(currentNonWakeupFuzzLocked(nowELAPSED), pw);
1323                pw.println();
1324                pw.print("  Time since last dispatch: ");
1325                TimeUtils.formatDuration(nowELAPSED - mLastAlarmDeliveryTime, pw);
1326                pw.println();
1327                pw.print("  Next non-wakeup delivery time: ");
1328                TimeUtils.formatDuration(nowELAPSED - mNextNonWakeupDeliveryTime, pw);
1329                pw.println();
1330            }
1331
1332            long nextWakeupRTC = mNextWakeup + (nowRTC - nowELAPSED);
1333            long nextNonWakeupRTC = mNextNonWakeup + (nowRTC - nowELAPSED);
1334            pw.print("  Next non-wakeup alarm: ");
1335                    TimeUtils.formatDuration(mNextNonWakeup, nowELAPSED, pw);
1336                    pw.print(" = "); pw.println(sdf.format(new Date(nextNonWakeupRTC)));
1337            pw.print("  Next wakeup: "); TimeUtils.formatDuration(mNextWakeup, nowELAPSED, pw);
1338                    pw.print(" = "); pw.println(sdf.format(new Date(nextWakeupRTC)));
1339            pw.print("  Num time change events: "); pw.println(mNumTimeChanged);
1340
1341            pw.println();
1342            pw.println("  Next alarm clock information: ");
1343            final TreeSet<Integer> users = new TreeSet<>();
1344            for (int i = 0; i < mNextAlarmClockForUser.size(); i++) {
1345                users.add(mNextAlarmClockForUser.keyAt(i));
1346            }
1347            for (int i = 0; i < mPendingSendNextAlarmClockChangedForUser.size(); i++) {
1348                users.add(mPendingSendNextAlarmClockChangedForUser.keyAt(i));
1349            }
1350            for (int user : users) {
1351                final AlarmManager.AlarmClockInfo next = mNextAlarmClockForUser.get(user);
1352                final long time = next != null ? next.getTriggerTime() : 0;
1353                final boolean pendingSend = mPendingSendNextAlarmClockChangedForUser.get(user);
1354                pw.print("    user:"); pw.print(user);
1355                pw.print(" pendingSend:"); pw.print(pendingSend);
1356                pw.print(" time:"); pw.print(time);
1357                if (time > 0) {
1358                    pw.print(" = "); pw.print(sdf.format(new Date(time)));
1359                    pw.print(" = "); TimeUtils.formatDuration(time, nowRTC, pw);
1360                }
1361                pw.println();
1362            }
1363            if (mAlarmBatches.size() > 0) {
1364                pw.println();
1365                pw.print("  Pending alarm batches: ");
1366                pw.println(mAlarmBatches.size());
1367                for (Batch b : mAlarmBatches) {
1368                    pw.print(b); pw.println(':');
1369                    dumpAlarmList(pw, b.alarms, "    ", nowELAPSED, nowRTC, sdf);
1370                }
1371            }
1372            if (mPendingIdleUntil != null || mPendingWhileIdleAlarms.size() > 0) {
1373                pw.println();
1374                pw.println("    Idle mode state:");
1375                pw.print("      Idling until: ");
1376                if (mPendingIdleUntil != null) {
1377                    pw.println(mPendingIdleUntil);
1378                    mPendingIdleUntil.dump(pw, "        ", nowRTC, nowELAPSED, sdf);
1379                } else {
1380                    pw.println("null");
1381                }
1382                pw.println("      Pending alarms:");
1383                dumpAlarmList(pw, mPendingWhileIdleAlarms, "      ", nowELAPSED, nowRTC, sdf);
1384            }
1385            if (mNextWakeFromIdle != null) {
1386                pw.println();
1387                pw.print("  Next wake from idle: "); pw.println(mNextWakeFromIdle);
1388                mNextWakeFromIdle.dump(pw, "    ", nowRTC, nowELAPSED, sdf);
1389            }
1390
1391            pw.println();
1392            pw.print("  Past-due non-wakeup alarms: ");
1393            if (mPendingNonWakeupAlarms.size() > 0) {
1394                pw.println(mPendingNonWakeupAlarms.size());
1395                dumpAlarmList(pw, mPendingNonWakeupAlarms, "    ", nowELAPSED, nowRTC, sdf);
1396            } else {
1397                pw.println("(none)");
1398            }
1399            pw.print("    Number of delayed alarms: "); pw.print(mNumDelayedAlarms);
1400            pw.print(", total delay time: "); TimeUtils.formatDuration(mTotalDelayTime, pw);
1401            pw.println();
1402            pw.print("    Max delay time: "); TimeUtils.formatDuration(mMaxDelayTime, pw);
1403            pw.print(", max non-interactive time: ");
1404            TimeUtils.formatDuration(mNonInteractiveTime, pw);
1405            pw.println();
1406
1407            pw.println();
1408            pw.print("  Broadcast ref count: "); pw.println(mBroadcastRefCount);
1409            pw.println();
1410
1411            pw.print("  mAllowWhileIdleMinTime=");
1412            TimeUtils.formatDuration(mAllowWhileIdleMinTime, pw);
1413            pw.println();
1414            if (mLastAllowWhileIdleDispatch.size() > 0) {
1415                pw.println("  Last allow while idle dispatch times:");
1416                for (int i=0; i<mLastAllowWhileIdleDispatch.size(); i++) {
1417                    pw.print("  UID ");
1418                    UserHandle.formatUid(pw, mLastAllowWhileIdleDispatch.keyAt(i));
1419                    pw.print(": ");
1420                    TimeUtils.formatDuration(mLastAllowWhileIdleDispatch.valueAt(i),
1421                            nowELAPSED, pw);
1422                    pw.println();
1423                }
1424            }
1425            pw.println();
1426
1427            if (mLog.dump(pw, "  Recent problems", "    ")) {
1428                pw.println();
1429            }
1430
1431            final FilterStats[] topFilters = new FilterStats[10];
1432            final Comparator<FilterStats> comparator = new Comparator<FilterStats>() {
1433                @Override
1434                public int compare(FilterStats lhs, FilterStats rhs) {
1435                    if (lhs.aggregateTime < rhs.aggregateTime) {
1436                        return 1;
1437                    } else if (lhs.aggregateTime > rhs.aggregateTime) {
1438                        return -1;
1439                    }
1440                    return 0;
1441                }
1442            };
1443            int len = 0;
1444            for (int iu=0; iu<mBroadcastStats.size(); iu++) {
1445                ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(iu);
1446                for (int ip=0; ip<uidStats.size(); ip++) {
1447                    BroadcastStats bs = uidStats.valueAt(ip);
1448                    for (int is=0; is<bs.filterStats.size(); is++) {
1449                        FilterStats fs = bs.filterStats.valueAt(is);
1450                        int pos = len > 0
1451                                ? Arrays.binarySearch(topFilters, 0, len, fs, comparator) : 0;
1452                        if (pos < 0) {
1453                            pos = -pos - 1;
1454                        }
1455                        if (pos < topFilters.length) {
1456                            int copylen = topFilters.length - pos - 1;
1457                            if (copylen > 0) {
1458                                System.arraycopy(topFilters, pos, topFilters, pos+1, copylen);
1459                            }
1460                            topFilters[pos] = fs;
1461                            if (len < topFilters.length) {
1462                                len++;
1463                            }
1464                        }
1465                    }
1466                }
1467            }
1468            if (len > 0) {
1469                pw.println("  Top Alarms:");
1470                for (int i=0; i<len; i++) {
1471                    FilterStats fs = topFilters[i];
1472                    pw.print("    ");
1473                    if (fs.nesting > 0) pw.print("*ACTIVE* ");
1474                    TimeUtils.formatDuration(fs.aggregateTime, pw);
1475                    pw.print(" running, "); pw.print(fs.numWakeup);
1476                    pw.print(" wakeups, "); pw.print(fs.count);
1477                    pw.print(" alarms: "); UserHandle.formatUid(pw, fs.mBroadcastStats.mUid);
1478                    pw.print(":"); pw.print(fs.mBroadcastStats.mPackageName);
1479                    pw.println();
1480                    pw.print("      "); pw.print(fs.mTag);
1481                    pw.println();
1482                }
1483            }
1484
1485            pw.println(" ");
1486            pw.println("  Alarm Stats:");
1487            final ArrayList<FilterStats> tmpFilters = new ArrayList<FilterStats>();
1488            for (int iu=0; iu<mBroadcastStats.size(); iu++) {
1489                ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(iu);
1490                for (int ip=0; ip<uidStats.size(); ip++) {
1491                    BroadcastStats bs = uidStats.valueAt(ip);
1492                    pw.print("  ");
1493                    if (bs.nesting > 0) pw.print("*ACTIVE* ");
1494                    UserHandle.formatUid(pw, bs.mUid);
1495                    pw.print(":");
1496                    pw.print(bs.mPackageName);
1497                    pw.print(" "); TimeUtils.formatDuration(bs.aggregateTime, pw);
1498                            pw.print(" running, "); pw.print(bs.numWakeup);
1499                            pw.println(" wakeups:");
1500                    tmpFilters.clear();
1501                    for (int is=0; is<bs.filterStats.size(); is++) {
1502                        tmpFilters.add(bs.filterStats.valueAt(is));
1503                    }
1504                    Collections.sort(tmpFilters, comparator);
1505                    for (int i=0; i<tmpFilters.size(); i++) {
1506                        FilterStats fs = tmpFilters.get(i);
1507                        pw.print("    ");
1508                                if (fs.nesting > 0) pw.print("*ACTIVE* ");
1509                                TimeUtils.formatDuration(fs.aggregateTime, pw);
1510                                pw.print(" "); pw.print(fs.numWakeup);
1511                                pw.print(" wakes " ); pw.print(fs.count);
1512                                pw.print(" alarms, last ");
1513                                TimeUtils.formatDuration(fs.lastTime, nowELAPSED, pw);
1514                                pw.println(":");
1515                        pw.print("      ");
1516                                pw.print(fs.mTag);
1517                                pw.println();
1518                    }
1519                }
1520            }
1521
1522            if (RECORD_DEVICE_IDLE_ALARMS) {
1523                pw.println();
1524                pw.println("  Allow while idle dispatches:");
1525                for (int i = 0; i < mAllowWhileIdleDispatches.size(); i++) {
1526                    IdleDispatchEntry ent = mAllowWhileIdleDispatches.get(i);
1527                    pw.print("    ");
1528                    TimeUtils.formatDuration(ent.elapsedRealtime, nowELAPSED, pw);
1529                    pw.print(": ");
1530                    UserHandle.formatUid(pw, ent.uid);
1531                    pw.print(":");
1532                    pw.println(ent.pkg);
1533                    if (ent.op != null) {
1534                        pw.print("      ");
1535                        pw.print(ent.op);
1536                        pw.print(" / ");
1537                        pw.print(ent.tag);
1538                        if (ent.argRealtime != 0) {
1539                            pw.print(" (");
1540                            TimeUtils.formatDuration(ent.argRealtime, nowELAPSED, pw);
1541                            pw.print(")");
1542                        }
1543                        pw.println();
1544                    }
1545                }
1546            }
1547
1548            if (WAKEUP_STATS) {
1549                pw.println();
1550                pw.println("  Recent Wakeup History:");
1551                long last = -1;
1552                for (WakeupEvent event : mRecentWakeups) {
1553                    pw.print("    "); pw.print(sdf.format(new Date(event.when)));
1554                    pw.print('|');
1555                    if (last < 0) {
1556                        pw.print('0');
1557                    } else {
1558                        pw.print(event.when - last);
1559                    }
1560                    last = event.when;
1561                    pw.print('|'); pw.print(event.uid);
1562                    pw.print('|'); pw.print(event.action);
1563                    pw.println();
1564                }
1565                pw.println();
1566            }
1567        }
1568    }
1569
1570    private void logBatchesLocked(SimpleDateFormat sdf) {
1571        ByteArrayOutputStream bs = new ByteArrayOutputStream(2048);
1572        PrintWriter pw = new PrintWriter(bs);
1573        final long nowRTC = System.currentTimeMillis();
1574        final long nowELAPSED = SystemClock.elapsedRealtime();
1575        final int NZ = mAlarmBatches.size();
1576        for (int iz = 0; iz < NZ; iz++) {
1577            Batch bz = mAlarmBatches.get(iz);
1578            pw.append("Batch "); pw.print(iz); pw.append(": "); pw.println(bz);
1579            dumpAlarmList(pw, bz.alarms, "  ", nowELAPSED, nowRTC, sdf);
1580            pw.flush();
1581            Slog.v(TAG, bs.toString());
1582            bs.reset();
1583        }
1584    }
1585
1586    private boolean validateConsistencyLocked() {
1587        if (DEBUG_VALIDATE) {
1588            long lastTime = Long.MIN_VALUE;
1589            final int N = mAlarmBatches.size();
1590            for (int i = 0; i < N; i++) {
1591                Batch b = mAlarmBatches.get(i);
1592                if (b.start >= lastTime) {
1593                    // duplicate start times are okay because of standalone batches
1594                    lastTime = b.start;
1595                } else {
1596                    Slog.e(TAG, "CONSISTENCY FAILURE: Batch " + i + " is out of order");
1597                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
1598                    logBatchesLocked(sdf);
1599                    return false;
1600                }
1601            }
1602        }
1603        return true;
1604    }
1605
1606    private Batch findFirstWakeupBatchLocked() {
1607        final int N = mAlarmBatches.size();
1608        for (int i = 0; i < N; i++) {
1609            Batch b = mAlarmBatches.get(i);
1610            if (b.hasWakeups()) {
1611                return b;
1612            }
1613        }
1614        return null;
1615    }
1616
1617    long getNextWakeFromIdleTimeImpl() {
1618        synchronized (mLock) {
1619            return mNextWakeFromIdle != null ? mNextWakeFromIdle.whenElapsed : Long.MAX_VALUE;
1620        }
1621    }
1622
1623    AlarmManager.AlarmClockInfo getNextAlarmClockImpl(int userId) {
1624        synchronized (mLock) {
1625            return mNextAlarmClockForUser.get(userId);
1626        }
1627    }
1628
1629    /**
1630     * Recomputes the next alarm clock for all users.
1631     */
1632    private void updateNextAlarmClockLocked() {
1633        if (!mNextAlarmClockMayChange) {
1634            return;
1635        }
1636        mNextAlarmClockMayChange = false;
1637
1638        SparseArray<AlarmManager.AlarmClockInfo> nextForUser = mTmpSparseAlarmClockArray;
1639        nextForUser.clear();
1640
1641        final int N = mAlarmBatches.size();
1642        for (int i = 0; i < N; i++) {
1643            ArrayList<Alarm> alarms = mAlarmBatches.get(i).alarms;
1644            final int M = alarms.size();
1645
1646            for (int j = 0; j < M; j++) {
1647                Alarm a = alarms.get(j);
1648                if (a.alarmClock != null) {
1649                    final int userId = UserHandle.getUserId(a.uid);
1650
1651                    if (DEBUG_ALARM_CLOCK) {
1652                        Log.v(TAG, "Found AlarmClockInfo at " +
1653                                formatNextAlarm(getContext(), a.alarmClock, userId) +
1654                                " for user " + userId);
1655                    }
1656
1657                    // Alarms and batches are sorted by time, no need to compare times here.
1658                    if (nextForUser.get(userId) == null) {
1659                        nextForUser.put(userId, a.alarmClock);
1660                    }
1661                }
1662            }
1663        }
1664
1665        // Update mNextAlarmForUser with new values.
1666        final int NN = nextForUser.size();
1667        for (int i = 0; i < NN; i++) {
1668            AlarmManager.AlarmClockInfo newAlarm = nextForUser.valueAt(i);
1669            int userId = nextForUser.keyAt(i);
1670            AlarmManager.AlarmClockInfo currentAlarm = mNextAlarmClockForUser.get(userId);
1671            if (!newAlarm.equals(currentAlarm)) {
1672                updateNextAlarmInfoForUserLocked(userId, newAlarm);
1673            }
1674        }
1675
1676        // Remove users without any alarm clocks scheduled.
1677        final int NNN = mNextAlarmClockForUser.size();
1678        for (int i = NNN - 1; i >= 0; i--) {
1679            int userId = mNextAlarmClockForUser.keyAt(i);
1680            if (nextForUser.get(userId) == null) {
1681                updateNextAlarmInfoForUserLocked(userId, null);
1682            }
1683        }
1684    }
1685
1686    private void updateNextAlarmInfoForUserLocked(int userId,
1687            AlarmManager.AlarmClockInfo alarmClock) {
1688        if (alarmClock != null) {
1689            if (DEBUG_ALARM_CLOCK) {
1690                Log.v(TAG, "Next AlarmClockInfoForUser(" + userId + "): " +
1691                        formatNextAlarm(getContext(), alarmClock, userId));
1692            }
1693            mNextAlarmClockForUser.put(userId, alarmClock);
1694        } else {
1695            if (DEBUG_ALARM_CLOCK) {
1696                Log.v(TAG, "Next AlarmClockInfoForUser(" + userId + "): None");
1697            }
1698            mNextAlarmClockForUser.remove(userId);
1699        }
1700
1701        mPendingSendNextAlarmClockChangedForUser.put(userId, true);
1702        mHandler.removeMessages(AlarmHandler.SEND_NEXT_ALARM_CLOCK_CHANGED);
1703        mHandler.sendEmptyMessage(AlarmHandler.SEND_NEXT_ALARM_CLOCK_CHANGED);
1704    }
1705
1706    /**
1707     * Updates NEXT_ALARM_FORMATTED and sends NEXT_ALARM_CLOCK_CHANGED_INTENT for all users
1708     * for which alarm clocks have changed since the last call to this.
1709     *
1710     * Do not call with a lock held. Only call from mHandler's thread.
1711     *
1712     * @see AlarmHandler#SEND_NEXT_ALARM_CLOCK_CHANGED
1713     */
1714    private void sendNextAlarmClockChanged() {
1715        SparseArray<AlarmManager.AlarmClockInfo> pendingUsers = mHandlerSparseAlarmClockArray;
1716        pendingUsers.clear();
1717
1718        synchronized (mLock) {
1719            final int N  = mPendingSendNextAlarmClockChangedForUser.size();
1720            for (int i = 0; i < N; i++) {
1721                int userId = mPendingSendNextAlarmClockChangedForUser.keyAt(i);
1722                pendingUsers.append(userId, mNextAlarmClockForUser.get(userId));
1723            }
1724            mPendingSendNextAlarmClockChangedForUser.clear();
1725        }
1726
1727        final int N = pendingUsers.size();
1728        for (int i = 0; i < N; i++) {
1729            int userId = pendingUsers.keyAt(i);
1730            AlarmManager.AlarmClockInfo alarmClock = pendingUsers.valueAt(i);
1731            Settings.System.putStringForUser(getContext().getContentResolver(),
1732                    Settings.System.NEXT_ALARM_FORMATTED,
1733                    formatNextAlarm(getContext(), alarmClock, userId),
1734                    userId);
1735
1736            getContext().sendBroadcastAsUser(NEXT_ALARM_CLOCK_CHANGED_INTENT,
1737                    new UserHandle(userId));
1738        }
1739    }
1740
1741    /**
1742     * Formats an alarm like platform/packages/apps/DeskClock used to.
1743     */
1744    private static String formatNextAlarm(final Context context, AlarmManager.AlarmClockInfo info,
1745            int userId) {
1746        String skeleton = DateFormat.is24HourFormat(context, userId) ? "EHm" : "Ehma";
1747        String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton);
1748        return (info == null) ? "" :
1749                DateFormat.format(pattern, info.getTriggerTime()).toString();
1750    }
1751
1752    void rescheduleKernelAlarmsLocked() {
1753        // Schedule the next upcoming wakeup alarm.  If there is a deliverable batch
1754        // prior to that which contains no wakeups, we schedule that as well.
1755        long nextNonWakeup = 0;
1756        if (mAlarmBatches.size() > 0) {
1757            final Batch firstWakeup = findFirstWakeupBatchLocked();
1758            final Batch firstBatch = mAlarmBatches.get(0);
1759            if (firstWakeup != null && mNextWakeup != firstWakeup.start) {
1760                mNextWakeup = firstWakeup.start;
1761                setLocked(ELAPSED_REALTIME_WAKEUP, firstWakeup.start);
1762            }
1763            if (firstBatch != firstWakeup) {
1764                nextNonWakeup = firstBatch.start;
1765            }
1766        }
1767        if (mPendingNonWakeupAlarms.size() > 0) {
1768            if (nextNonWakeup == 0 || mNextNonWakeupDeliveryTime < nextNonWakeup) {
1769                nextNonWakeup = mNextNonWakeupDeliveryTime;
1770            }
1771        }
1772        if (nextNonWakeup != 0 && mNextNonWakeup != nextNonWakeup) {
1773            mNextNonWakeup = nextNonWakeup;
1774            setLocked(ELAPSED_REALTIME, nextNonWakeup);
1775        }
1776    }
1777
1778    private void removeLocked(PendingIntent operation, IAlarmListener directReceiver) {
1779        boolean didRemove = false;
1780        for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
1781            Batch b = mAlarmBatches.get(i);
1782            didRemove |= b.remove(operation, directReceiver);
1783            if (b.size() == 0) {
1784                mAlarmBatches.remove(i);
1785            }
1786        }
1787        for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
1788            if (mPendingWhileIdleAlarms.get(i).matches(operation, directReceiver)) {
1789                // Don't set didRemove, since this doesn't impact the scheduled alarms.
1790                mPendingWhileIdleAlarms.remove(i);
1791            }
1792        }
1793
1794        if (didRemove) {
1795            if (DEBUG_BATCH) {
1796                Slog.v(TAG, "remove(operation) changed bounds; rebatching");
1797            }
1798            boolean restorePending = false;
1799            if (mPendingIdleUntil != null && mPendingIdleUntil.matches(operation, directReceiver)) {
1800                mPendingIdleUntil = null;
1801                restorePending = true;
1802            }
1803            if (mNextWakeFromIdle != null && mNextWakeFromIdle.matches(operation, directReceiver)) {
1804                mNextWakeFromIdle = null;
1805            }
1806            rebatchAllAlarmsLocked(true);
1807            if (restorePending) {
1808                restorePendingWhileIdleAlarmsLocked();
1809            }
1810            updateNextAlarmClockLocked();
1811        }
1812    }
1813
1814    void removeLocked(String packageName) {
1815        boolean didRemove = false;
1816        for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
1817            Batch b = mAlarmBatches.get(i);
1818            didRemove |= b.remove(packageName);
1819            if (b.size() == 0) {
1820                mAlarmBatches.remove(i);
1821            }
1822        }
1823        for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
1824            final Alarm a = mPendingWhileIdleAlarms.get(i);
1825            if (a.matches(packageName)) {
1826                // Don't set didRemove, since this doesn't impact the scheduled alarms.
1827                mPendingWhileIdleAlarms.remove(i);
1828            }
1829        }
1830
1831        if (didRemove) {
1832            if (DEBUG_BATCH) {
1833                Slog.v(TAG, "remove(package) changed bounds; rebatching");
1834            }
1835            rebatchAllAlarmsLocked(true);
1836            rescheduleKernelAlarmsLocked();
1837            updateNextAlarmClockLocked();
1838        }
1839    }
1840
1841    void removeUserLocked(int userHandle) {
1842        boolean didRemove = false;
1843        for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
1844            Batch b = mAlarmBatches.get(i);
1845            didRemove |= b.remove(userHandle);
1846            if (b.size() == 0) {
1847                mAlarmBatches.remove(i);
1848            }
1849        }
1850        for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
1851            if (UserHandle.getUserId(mPendingWhileIdleAlarms.get(i).creatorUid)
1852                    == userHandle) {
1853                // Don't set didRemove, since this doesn't impact the scheduled alarms.
1854                mPendingWhileIdleAlarms.remove(i);
1855            }
1856        }
1857        for (int i = mLastAllowWhileIdleDispatch.size() - 1; i >= 0; i--) {
1858            if (UserHandle.getUserId(mLastAllowWhileIdleDispatch.keyAt(i)) == userHandle) {
1859                mLastAllowWhileIdleDispatch.removeAt(i);
1860            }
1861        }
1862
1863        if (didRemove) {
1864            if (DEBUG_BATCH) {
1865                Slog.v(TAG, "remove(user) changed bounds; rebatching");
1866            }
1867            rebatchAllAlarmsLocked(true);
1868            rescheduleKernelAlarmsLocked();
1869            updateNextAlarmClockLocked();
1870        }
1871    }
1872
1873    void interactiveStateChangedLocked(boolean interactive) {
1874        if (mInteractive != interactive) {
1875            mInteractive = interactive;
1876            final long nowELAPSED = SystemClock.elapsedRealtime();
1877            if (interactive) {
1878                if (mPendingNonWakeupAlarms.size() > 0) {
1879                    final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
1880                    mTotalDelayTime += thisDelayTime;
1881                    if (mMaxDelayTime < thisDelayTime) {
1882                        mMaxDelayTime = thisDelayTime;
1883                    }
1884                    deliverAlarmsLocked(mPendingNonWakeupAlarms, nowELAPSED);
1885                    mPendingNonWakeupAlarms.clear();
1886                }
1887                if (mNonInteractiveStartTime > 0) {
1888                    long dur = nowELAPSED - mNonInteractiveStartTime;
1889                    if (dur > mNonInteractiveTime) {
1890                        mNonInteractiveTime = dur;
1891                    }
1892                }
1893            } else {
1894                mNonInteractiveStartTime = nowELAPSED;
1895            }
1896        }
1897    }
1898
1899    boolean lookForPackageLocked(String packageName) {
1900        for (int i = 0; i < mAlarmBatches.size(); i++) {
1901            Batch b = mAlarmBatches.get(i);
1902            if (b.hasPackage(packageName)) {
1903                return true;
1904            }
1905        }
1906        for (int i = 0; i < mPendingWhileIdleAlarms.size(); i++) {
1907            final Alarm a = mPendingWhileIdleAlarms.get(i);
1908            if (a.matches(packageName)) {
1909                return true;
1910            }
1911        }
1912        return false;
1913    }
1914
1915    private void setLocked(int type, long when) {
1916        if (mNativeData != 0) {
1917            // The kernel never triggers alarms with negative wakeup times
1918            // so we ensure they are positive.
1919            long alarmSeconds, alarmNanoseconds;
1920            if (when < 0) {
1921                alarmSeconds = 0;
1922                alarmNanoseconds = 0;
1923            } else {
1924                alarmSeconds = when / 1000;
1925                alarmNanoseconds = (when % 1000) * 1000 * 1000;
1926            }
1927
1928            set(mNativeData, type, alarmSeconds, alarmNanoseconds);
1929        } else {
1930            Message msg = Message.obtain();
1931            msg.what = ALARM_EVENT;
1932
1933            mHandler.removeMessages(ALARM_EVENT);
1934            mHandler.sendMessageAtTime(msg, when);
1935        }
1936    }
1937
1938    private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list,
1939            String prefix, String label, long nowRTC, long nowELAPSED, SimpleDateFormat sdf) {
1940        for (int i=list.size()-1; i>=0; i--) {
1941            Alarm a = list.get(i);
1942            pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i);
1943                    pw.print(": "); pw.println(a);
1944            a.dump(pw, prefix + "  ", nowRTC, nowELAPSED, sdf);
1945        }
1946    }
1947
1948    private static final String labelForType(int type) {
1949        switch (type) {
1950        case RTC: return "RTC";
1951        case RTC_WAKEUP : return "RTC_WAKEUP";
1952        case ELAPSED_REALTIME : return "ELAPSED";
1953        case ELAPSED_REALTIME_WAKEUP: return "ELAPSED_WAKEUP";
1954        default:
1955            break;
1956        }
1957        return "--unknown--";
1958    }
1959
1960    private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list,
1961            String prefix, long nowELAPSED, long nowRTC, SimpleDateFormat sdf) {
1962        for (int i=list.size()-1; i>=0; i--) {
1963            Alarm a = list.get(i);
1964            final String label = labelForType(a.type);
1965            pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i);
1966                    pw.print(": "); pw.println(a);
1967            a.dump(pw, prefix + "  ", nowRTC, nowELAPSED, sdf);
1968        }
1969    }
1970
1971    private native long init();
1972    private native void close(long nativeData);
1973    private native void set(long nativeData, int type, long seconds, long nanoseconds);
1974    private native int waitForAlarm(long nativeData);
1975    private native int setKernelTime(long nativeData, long millis);
1976    private native int setKernelTimezone(long nativeData, int minuteswest);
1977
1978    boolean triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED,
1979            final long nowRTC) {
1980        boolean hasWakeup = false;
1981        // batches are temporally sorted, so we need only pull from the
1982        // start of the list until we either empty it or hit a batch
1983        // that is not yet deliverable
1984        while (mAlarmBatches.size() > 0) {
1985            Batch batch = mAlarmBatches.get(0);
1986            if (batch.start > nowELAPSED) {
1987                // Everything else is scheduled for the future
1988                break;
1989            }
1990
1991            // We will (re)schedule some alarms now; don't let that interfere
1992            // with delivery of this current batch
1993            mAlarmBatches.remove(0);
1994
1995            final int N = batch.size();
1996            for (int i = 0; i < N; i++) {
1997                Alarm alarm = batch.get(i);
1998
1999                if ((alarm.flags&AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) {
2000                    // If this is an ALLOW_WHILE_IDLE alarm, we constrain how frequently the app can
2001                    // schedule such alarms.
2002                    long lastTime = mLastAllowWhileIdleDispatch.get(alarm.uid, 0);
2003                    long minTime = lastTime + mAllowWhileIdleMinTime;
2004                    if (nowELAPSED < minTime) {
2005                        // Whoops, it hasn't been long enough since the last ALLOW_WHILE_IDLE
2006                        // alarm went off for this app.  Reschedule the alarm to be in the
2007                        // correct time period.
2008                        alarm.whenElapsed = minTime;
2009                        if (alarm.maxWhenElapsed < minTime) {
2010                            alarm.maxWhenElapsed = minTime;
2011                        }
2012                        if (RECORD_DEVICE_IDLE_ALARMS) {
2013                            IdleDispatchEntry ent = new IdleDispatchEntry();
2014                            ent.uid = alarm.uid;
2015                            ent.pkg = alarm.operation.getCreatorPackage();
2016                            ent.tag = alarm.operation.getTag("");
2017                            ent.op = "RESCHEDULE";
2018                            ent.elapsedRealtime = nowELAPSED;
2019                            ent.argRealtime = lastTime;
2020                            mAllowWhileIdleDispatches.add(ent);
2021                        }
2022                        setImplLocked(alarm, true, false);
2023                        continue;
2024                    }
2025                }
2026
2027                alarm.count = 1;
2028                triggerList.add(alarm);
2029                if ((alarm.flags&AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) {
2030                    EventLogTags.writeDeviceIdleWakeFromIdle(mPendingIdleUntil != null ? 1 : 0,
2031                            alarm.statsTag);
2032                }
2033                if (mPendingIdleUntil == alarm) {
2034                    mPendingIdleUntil = null;
2035                    rebatchAllAlarmsLocked(false);
2036                    restorePendingWhileIdleAlarmsLocked();
2037                }
2038                if (mNextWakeFromIdle == alarm) {
2039                    mNextWakeFromIdle = null;
2040                    rebatchAllAlarmsLocked(false);
2041                }
2042
2043                // Recurring alarms may have passed several alarm intervals while the
2044                // phone was asleep or off, so pass a trigger count when sending them.
2045                if (alarm.repeatInterval > 0) {
2046                    // this adjustment will be zero if we're late by
2047                    // less than one full repeat interval
2048                    alarm.count += (nowELAPSED - alarm.whenElapsed) / alarm.repeatInterval;
2049
2050                    // Also schedule its next recurrence
2051                    final long delta = alarm.count * alarm.repeatInterval;
2052                    final long nextElapsed = alarm.whenElapsed + delta;
2053                    setImplLocked(alarm.type, alarm.when + delta, nextElapsed, alarm.windowLength,
2054                            maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval),
2055                            alarm.repeatInterval, alarm.operation, null, null, alarm.flags, true,
2056                            alarm.workSource, alarm.alarmClock, alarm.uid, alarm.packageName);
2057                }
2058
2059                if (alarm.wakeup) {
2060                    hasWakeup = true;
2061                }
2062
2063                // We removed an alarm clock. Let the caller recompute the next alarm clock.
2064                if (alarm.alarmClock != null) {
2065                    mNextAlarmClockMayChange = true;
2066                }
2067            }
2068        }
2069
2070        // This is a new alarm delivery set; bump the sequence number to indicate that
2071        // all apps' alarm delivery classes should be recalculated.
2072        mCurrentSeq++;
2073        calculateDeliveryPriorities(triggerList);
2074        Collections.sort(triggerList, mAlarmDispatchComparator);
2075
2076        if (localLOGV) {
2077            for (int i=0; i<triggerList.size(); i++) {
2078                Slog.v(TAG, "Triggering alarm #" + i + ": " + triggerList.get(i));
2079            }
2080        }
2081
2082        return hasWakeup;
2083    }
2084
2085    /**
2086     * This Comparator sorts Alarms into increasing time order.
2087     */
2088    public static class IncreasingTimeOrder implements Comparator<Alarm> {
2089        public int compare(Alarm a1, Alarm a2) {
2090            long when1 = a1.whenElapsed;
2091            long when2 = a2.whenElapsed;
2092            if (when1 > when2) {
2093                return 1;
2094            }
2095            if (when1 < when2) {
2096                return -1;
2097            }
2098            return 0;
2099        }
2100    }
2101
2102    private static class Alarm {
2103        public final int type;
2104        public final long origWhen;
2105        public final boolean wakeup;
2106        public final PendingIntent operation;
2107        public final IAlarmListener listener;
2108        public final String listenerTag;
2109        public final String statsTag;
2110        public final WorkSource workSource;
2111        public final int flags;
2112        public final AlarmManager.AlarmClockInfo alarmClock;
2113        public final int uid;
2114        public final int creatorUid;
2115        public final String packageName;
2116        public int count;
2117        public long when;
2118        public long windowLength;
2119        public long whenElapsed;    // 'when' in the elapsed time base
2120        public long maxWhenElapsed; // also in the elapsed time base
2121        public long repeatInterval;
2122        public PriorityClass priorityClass;
2123
2124        public Alarm(int _type, long _when, long _whenElapsed, long _windowLength, long _maxWhen,
2125                long _interval, PendingIntent _op, IAlarmListener _rec, String _listenerTag,
2126                WorkSource _ws, int _flags, AlarmManager.AlarmClockInfo _info,
2127                int _uid, String _pkgName) {
2128            type = _type;
2129            origWhen = _when;
2130            wakeup = _type == AlarmManager.ELAPSED_REALTIME_WAKEUP
2131                    || _type == AlarmManager.RTC_WAKEUP;
2132            when = _when;
2133            whenElapsed = _whenElapsed;
2134            windowLength = _windowLength;
2135            maxWhenElapsed = _maxWhen;
2136            repeatInterval = _interval;
2137            operation = _op;
2138            listener = _rec;
2139            listenerTag = _listenerTag;
2140            statsTag = makeTag(_op, _listenerTag, _type);
2141            workSource = _ws;
2142            flags = _flags;
2143            alarmClock = _info;
2144            uid = _uid;
2145            packageName = _pkgName;
2146
2147            creatorUid = (operation != null) ? operation.getCreatorUid() : uid;
2148        }
2149
2150        public static String makeTag(PendingIntent pi, String tag, int type) {
2151            final String alarmString = type == ELAPSED_REALTIME_WAKEUP || type == RTC_WAKEUP
2152                    ? "*walarm*:" : "*alarm*:";
2153            return (pi != null) ? pi.getTag(alarmString) : (alarmString + tag);
2154        }
2155
2156        public WakeupEvent makeWakeupEvent(long nowRTC) {
2157            return new WakeupEvent(nowRTC, creatorUid,
2158                    (operation != null)
2159                        ? operation.getIntent().getAction()
2160                        : ("<listener>:" + listenerTag));
2161        }
2162
2163        // Returns true if either matches
2164        public boolean matches(PendingIntent pi, IAlarmListener rec) {
2165            return (operation != null)
2166                    ? operation.equals(pi)
2167                    : listener.asBinder().equals(rec.asBinder());
2168        }
2169
2170        public boolean matches(String packageName) {
2171            return (operation != null)
2172                    ? packageName.equals(operation.getTargetPackage())
2173                    : packageName.equals(this.packageName);
2174        }
2175
2176        @Override
2177        public String toString() {
2178            StringBuilder sb = new StringBuilder(128);
2179            sb.append("Alarm{");
2180            sb.append(Integer.toHexString(System.identityHashCode(this)));
2181            sb.append(" type ");
2182            sb.append(type);
2183            sb.append(" when ");
2184            sb.append(when);
2185            sb.append(" ");
2186            if (operation != null) {
2187                sb.append(operation.getTargetPackage());
2188            } else {
2189                sb.append(listener.asBinder().toString());
2190            }
2191            sb.append('}');
2192            return sb.toString();
2193        }
2194
2195        public void dump(PrintWriter pw, String prefix, long nowRTC, long nowELAPSED,
2196                SimpleDateFormat sdf) {
2197            final boolean isRtc = (type == RTC || type == RTC_WAKEUP);
2198            pw.print(prefix); pw.print("tag="); pw.println(statsTag);
2199            pw.print(prefix); pw.print("type="); pw.print(type);
2200                    pw.print(" whenElapsed="); TimeUtils.formatDuration(whenElapsed,
2201                            nowELAPSED, pw);
2202                    pw.print(" when=");
2203                    if (isRtc) {
2204                        pw.print(sdf.format(new Date(when)));
2205                    } else {
2206                        TimeUtils.formatDuration(when, nowELAPSED, pw);
2207                    }
2208                    pw.println();
2209            pw.print(prefix); pw.print("window="); TimeUtils.formatDuration(windowLength, pw);
2210                    pw.print(" repeatInterval="); pw.print(repeatInterval);
2211                    pw.print(" count="); pw.print(count);
2212                    pw.print(" flags=0x"); pw.println(Integer.toHexString(flags));
2213            if (alarmClock != null) {
2214                pw.print(prefix); pw.println("Alarm clock:");
2215                pw.print(prefix); pw.print("  triggerTime=");
2216                pw.println(sdf.format(new Date(alarmClock.getTriggerTime())));
2217                pw.print(prefix); pw.print("  showIntent="); pw.println(alarmClock.getShowIntent());
2218            }
2219            pw.print(prefix); pw.print("operation="); pw.println(operation);
2220            if (listener != null) {
2221                pw.print(prefix); pw.print("listener="); pw.println(listener.asBinder());
2222            }
2223        }
2224    }
2225
2226    void recordWakeupAlarms(ArrayList<Batch> batches, long nowELAPSED, long nowRTC) {
2227        final int numBatches = batches.size();
2228        for (int nextBatch = 0; nextBatch < numBatches; nextBatch++) {
2229            Batch b = batches.get(nextBatch);
2230            if (b.start > nowELAPSED) {
2231                break;
2232            }
2233
2234            final int numAlarms = b.alarms.size();
2235            for (int nextAlarm = 0; nextAlarm < numAlarms; nextAlarm++) {
2236                Alarm a = b.alarms.get(nextAlarm);
2237                mRecentWakeups.add(a.makeWakeupEvent(nowRTC));
2238            }
2239        }
2240    }
2241
2242    long currentNonWakeupFuzzLocked(long nowELAPSED) {
2243        long timeSinceOn = nowELAPSED - mNonInteractiveStartTime;
2244        if (timeSinceOn < 5*60*1000) {
2245            // If the screen has been off for 5 minutes, only delay by at most two minutes.
2246            return 2*60*1000;
2247        } else if (timeSinceOn < 30*60*1000) {
2248            // If the screen has been off for 30 minutes, only delay by at most 15 minutes.
2249            return 15*60*1000;
2250        } else {
2251            // Otherwise, we will delay by at most an hour.
2252            return 60*60*1000;
2253        }
2254    }
2255
2256    static int fuzzForDuration(long duration) {
2257        if (duration < 15*60*1000) {
2258            // If the duration until the time is less than 15 minutes, the maximum fuzz
2259            // is the duration.
2260            return (int)duration;
2261        } else if (duration < 90*60*1000) {
2262            // If duration is less than 1 1/2 hours, the maximum fuzz is 15 minutes,
2263            return 15*60*1000;
2264        } else {
2265            // Otherwise, we will fuzz by at most half an hour.
2266            return 30*60*1000;
2267        }
2268    }
2269
2270    boolean checkAllowNonWakeupDelayLocked(long nowELAPSED) {
2271        if (mInteractive) {
2272            return false;
2273        }
2274        if (mLastAlarmDeliveryTime <= 0) {
2275            return false;
2276        }
2277        if (mPendingNonWakeupAlarms.size() > 0 && mNextNonWakeupDeliveryTime < nowELAPSED) {
2278            // This is just a little paranoia, if somehow we have pending non-wakeup alarms
2279            // and the next delivery time is in the past, then just deliver them all.  This
2280            // avoids bugs where we get stuck in a loop trying to poll for alarms.
2281            return false;
2282        }
2283        long timeSinceLast = nowELAPSED - mLastAlarmDeliveryTime;
2284        return timeSinceLast <= currentNonWakeupFuzzLocked(nowELAPSED);
2285    }
2286
2287    void deliverAlarmsLocked(ArrayList<Alarm> triggerList, long nowELAPSED) {
2288        mLastAlarmDeliveryTime = nowELAPSED;
2289        for (int i=0; i<triggerList.size(); i++) {
2290            Alarm alarm = triggerList.get(i);
2291            final boolean allowWhileIdle = (alarm.flags&AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0;
2292            try {
2293                if (localLOGV) {
2294                    Slog.v(TAG, "sending alarm " + alarm);
2295                }
2296                if (RECORD_ALARMS_IN_HISTORY) {
2297                    if (alarm.workSource != null && alarm.workSource.size() > 0) {
2298                        for (int wi=0; wi<alarm.workSource.size(); wi++) {
2299                            ActivityManagerNative.noteAlarmStart(
2300                                    alarm.operation, alarm.workSource.get(wi), alarm.statsTag);
2301                        }
2302                    } else {
2303                        ActivityManagerNative.noteAlarmStart(
2304                                alarm.operation, alarm.uid, alarm.statsTag);
2305                    }
2306                }
2307                mDeliveryTracker.deliverLocked(alarm, nowELAPSED, allowWhileIdle);
2308            } catch (RuntimeException e) {
2309                Slog.w(TAG, "Failure sending alarm.", e);
2310            }
2311        }
2312    }
2313
2314    private class AlarmThread extends Thread
2315    {
2316        public AlarmThread()
2317        {
2318            super("AlarmManager");
2319        }
2320
2321        public void run()
2322        {
2323            ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
2324
2325            while (true)
2326            {
2327                int result = waitForAlarm(mNativeData);
2328
2329                triggerList.clear();
2330
2331                final long nowRTC = System.currentTimeMillis();
2332                final long nowELAPSED = SystemClock.elapsedRealtime();
2333
2334                if ((result & TIME_CHANGED_MASK) != 0) {
2335                    // The kernel can give us spurious time change notifications due to
2336                    // small adjustments it makes internally; we want to filter those out.
2337                    final long lastTimeChangeClockTime;
2338                    final long expectedClockTime;
2339                    synchronized (mLock) {
2340                        lastTimeChangeClockTime = mLastTimeChangeClockTime;
2341                        expectedClockTime = lastTimeChangeClockTime
2342                                + (nowELAPSED - mLastTimeChangeRealtime);
2343                    }
2344                    if (lastTimeChangeClockTime == 0 || nowRTC < (expectedClockTime-500)
2345                            || nowRTC > (expectedClockTime+500)) {
2346                        // The change is by at least +/- 500 ms (or this is the first change),
2347                        // let's do it!
2348                        if (DEBUG_BATCH) {
2349                            Slog.v(TAG, "Time changed notification from kernel; rebatching");
2350                        }
2351                        removeImpl(mTimeTickSender);
2352                        rebatchAllAlarms();
2353                        mClockReceiver.scheduleTimeTickEvent();
2354                        synchronized (mLock) {
2355                            mNumTimeChanged++;
2356                            mLastTimeChangeClockTime = nowRTC;
2357                            mLastTimeChangeRealtime = nowELAPSED;
2358                        }
2359                        Intent intent = new Intent(Intent.ACTION_TIME_CHANGED);
2360                        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
2361                                | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
2362                        getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
2363
2364                        // The world has changed on us, so we need to re-evaluate alarms
2365                        // regardless of whether the kernel has told us one went off.
2366                        result |= IS_WAKEUP_MASK;
2367                    }
2368                }
2369
2370                if (result != TIME_CHANGED_MASK) {
2371                    // If this was anything besides just a time change, then figure what if
2372                    // anything to do about alarms.
2373                    synchronized (mLock) {
2374                        if (localLOGV) Slog.v(
2375                            TAG, "Checking for alarms... rtc=" + nowRTC
2376                            + ", elapsed=" + nowELAPSED);
2377
2378                        if (WAKEUP_STATS) {
2379                            if ((result & IS_WAKEUP_MASK) != 0) {
2380                                long newEarliest = nowRTC - RECENT_WAKEUP_PERIOD;
2381                                int n = 0;
2382                                for (WakeupEvent event : mRecentWakeups) {
2383                                    if (event.when > newEarliest) break;
2384                                    n++; // number of now-stale entries at the list head
2385                                }
2386                                for (int i = 0; i < n; i++) {
2387                                    mRecentWakeups.remove();
2388                                }
2389
2390                                recordWakeupAlarms(mAlarmBatches, nowELAPSED, nowRTC);
2391                            }
2392                        }
2393
2394                        boolean hasWakeup = triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC);
2395                        if (!hasWakeup && checkAllowNonWakeupDelayLocked(nowELAPSED)) {
2396                            // if there are no wakeup alarms and the screen is off, we can
2397                            // delay what we have so far until the future.
2398                            if (mPendingNonWakeupAlarms.size() == 0) {
2399                                mStartCurrentDelayTime = nowELAPSED;
2400                                mNextNonWakeupDeliveryTime = nowELAPSED
2401                                        + ((currentNonWakeupFuzzLocked(nowELAPSED)*3)/2);
2402                            }
2403                            mPendingNonWakeupAlarms.addAll(triggerList);
2404                            mNumDelayedAlarms += triggerList.size();
2405                            rescheduleKernelAlarmsLocked();
2406                            updateNextAlarmClockLocked();
2407                        } else {
2408                            // now deliver the alarm intents; if there are pending non-wakeup
2409                            // alarms, we need to merge them in to the list.  note we don't
2410                            // just deliver them first because we generally want non-wakeup
2411                            // alarms delivered after wakeup alarms.
2412                            rescheduleKernelAlarmsLocked();
2413                            updateNextAlarmClockLocked();
2414                            if (mPendingNonWakeupAlarms.size() > 0) {
2415                                calculateDeliveryPriorities(mPendingNonWakeupAlarms);
2416                                triggerList.addAll(mPendingNonWakeupAlarms);
2417                                Collections.sort(triggerList, mAlarmDispatchComparator);
2418                                final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
2419                                mTotalDelayTime += thisDelayTime;
2420                                if (mMaxDelayTime < thisDelayTime) {
2421                                    mMaxDelayTime = thisDelayTime;
2422                                }
2423                                mPendingNonWakeupAlarms.clear();
2424                            }
2425                            deliverAlarmsLocked(triggerList, nowELAPSED);
2426                        }
2427                    }
2428                }
2429            }
2430        }
2431    }
2432
2433    /**
2434     * Attribute blame for a WakeLock.
2435     * @param pi PendingIntent to attribute blame to if ws is null.
2436     * @param ws WorkSource to attribute blame.
2437     * @param knownUid attribution uid; < 0 if we need to derive it from the PendingIntent sender
2438     */
2439    void setWakelockWorkSource(PendingIntent pi, WorkSource ws, int type, String tag,
2440            int knownUid, boolean first) {
2441        try {
2442            final boolean unimportant = pi == mTimeTickSender;
2443            mWakeLock.setUnimportantForLogging(unimportant);
2444            if (first || mLastWakeLockUnimportantForLogging) {
2445                mWakeLock.setHistoryTag(tag);
2446            } else {
2447                mWakeLock.setHistoryTag(null);
2448            }
2449            mLastWakeLockUnimportantForLogging = unimportant;
2450            if (ws != null) {
2451                mWakeLock.setWorkSource(ws);
2452                return;
2453            }
2454
2455            final int uid = (knownUid >= 0)
2456                    ? knownUid
2457                    : ActivityManagerNative.getDefault().getUidForIntentSender(pi.getTarget());
2458            if (uid >= 0) {
2459                mWakeLock.setWorkSource(new WorkSource(uid));
2460                return;
2461            }
2462        } catch (Exception e) {
2463        }
2464
2465        // Something went wrong; fall back to attributing the lock to the OS
2466        mWakeLock.setWorkSource(null);
2467    }
2468
2469    private class AlarmHandler extends Handler {
2470        public static final int ALARM_EVENT = 1;
2471        public static final int MINUTE_CHANGE_EVENT = 2;
2472        public static final int DATE_CHANGE_EVENT = 3;
2473        public static final int SEND_NEXT_ALARM_CLOCK_CHANGED = 4;
2474        public static final int LISTENER_TIMEOUT = 5;
2475
2476        public AlarmHandler() {
2477        }
2478
2479        public void handleMessage(Message msg) {
2480            switch (msg.what) {
2481                case ALARM_EVENT: {
2482                    ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
2483                    synchronized (mLock) {
2484                        final long nowRTC = System.currentTimeMillis();
2485                        final long nowELAPSED = SystemClock.elapsedRealtime();
2486                        triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC);
2487                        updateNextAlarmClockLocked();
2488                    }
2489
2490                    // now trigger the alarms without the lock held
2491                    for (int i=0; i<triggerList.size(); i++) {
2492                        Alarm alarm = triggerList.get(i);
2493                        try {
2494                            alarm.operation.send();
2495                        } catch (PendingIntent.CanceledException e) {
2496                            if (alarm.repeatInterval > 0) {
2497                                // This IntentSender is no longer valid, but this
2498                                // is a repeating alarm, so toss the hoser.
2499                                removeImpl(alarm.operation);
2500                            }
2501                        }
2502                    }
2503                    break;
2504                }
2505
2506                case SEND_NEXT_ALARM_CLOCK_CHANGED:
2507                    sendNextAlarmClockChanged();
2508                    break;
2509
2510                case LISTENER_TIMEOUT:
2511                    mDeliveryTracker.alarmTimedOut((IBinder) msg.obj);
2512                    break;
2513
2514                default:
2515                    // nope, just ignore it
2516                    break;
2517            }
2518        }
2519    }
2520
2521    class ClockReceiver extends BroadcastReceiver {
2522        public ClockReceiver() {
2523            IntentFilter filter = new IntentFilter();
2524            filter.addAction(Intent.ACTION_TIME_TICK);
2525            filter.addAction(Intent.ACTION_DATE_CHANGED);
2526            getContext().registerReceiver(this, filter);
2527        }
2528
2529        @Override
2530        public void onReceive(Context context, Intent intent) {
2531            if (intent.getAction().equals(Intent.ACTION_TIME_TICK)) {
2532                if (DEBUG_BATCH) {
2533                    Slog.v(TAG, "Received TIME_TICK alarm; rescheduling");
2534                }
2535                scheduleTimeTickEvent();
2536            } else if (intent.getAction().equals(Intent.ACTION_DATE_CHANGED)) {
2537                // Since the kernel does not keep track of DST, we need to
2538                // reset the TZ information at the beginning of each day
2539                // based off of the current Zone gmt offset + userspace tracked
2540                // daylight savings information.
2541                TimeZone zone = TimeZone.getTimeZone(SystemProperties.get(TIMEZONE_PROPERTY));
2542                int gmtOffset = zone.getOffset(System.currentTimeMillis());
2543                setKernelTimezone(mNativeData, -(gmtOffset / 60000));
2544                scheduleDateChangedEvent();
2545            }
2546        }
2547
2548        public void scheduleTimeTickEvent() {
2549            final long currentTime = System.currentTimeMillis();
2550            final long nextTime = 60000 * ((currentTime / 60000) + 1);
2551
2552            // Schedule this event for the amount of time that it would take to get to
2553            // the top of the next minute.
2554            final long tickEventDelay = nextTime - currentTime;
2555
2556            final WorkSource workSource = null; // Let system take blame for time tick events.
2557            setImpl(ELAPSED_REALTIME, SystemClock.elapsedRealtime() + tickEventDelay, 0,
2558                    0, mTimeTickSender, null, null, AlarmManager.FLAG_STANDALONE, workSource,
2559                    null, Process.myUid(), "android");
2560        }
2561
2562        public void scheduleDateChangedEvent() {
2563            Calendar calendar = Calendar.getInstance();
2564            calendar.setTimeInMillis(System.currentTimeMillis());
2565            calendar.set(Calendar.HOUR, 0);
2566            calendar.set(Calendar.MINUTE, 0);
2567            calendar.set(Calendar.SECOND, 0);
2568            calendar.set(Calendar.MILLISECOND, 0);
2569            calendar.add(Calendar.DAY_OF_MONTH, 1);
2570
2571            final WorkSource workSource = null; // Let system take blame for date change events.
2572            setImpl(RTC, calendar.getTimeInMillis(), 0, 0, mDateChangeSender, null, null,
2573                    AlarmManager.FLAG_STANDALONE, workSource, null,
2574                    Process.myUid(), "android");
2575        }
2576    }
2577
2578    class InteractiveStateReceiver extends BroadcastReceiver {
2579        public InteractiveStateReceiver() {
2580            IntentFilter filter = new IntentFilter();
2581            filter.addAction(Intent.ACTION_SCREEN_OFF);
2582            filter.addAction(Intent.ACTION_SCREEN_ON);
2583            filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
2584            getContext().registerReceiver(this, filter);
2585        }
2586
2587        @Override
2588        public void onReceive(Context context, Intent intent) {
2589            synchronized (mLock) {
2590                interactiveStateChangedLocked(Intent.ACTION_SCREEN_ON.equals(intent.getAction()));
2591            }
2592        }
2593    }
2594
2595    class UninstallReceiver extends BroadcastReceiver {
2596        public UninstallReceiver() {
2597            IntentFilter filter = new IntentFilter();
2598            filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
2599            filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
2600            filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
2601            filter.addDataScheme("package");
2602            getContext().registerReceiver(this, filter);
2603             // Register for events related to sdcard installation.
2604            IntentFilter sdFilter = new IntentFilter();
2605            sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
2606            sdFilter.addAction(Intent.ACTION_USER_STOPPED);
2607            sdFilter.addAction(Intent.ACTION_UID_REMOVED);
2608            getContext().registerReceiver(this, sdFilter);
2609        }
2610
2611        @Override
2612        public void onReceive(Context context, Intent intent) {
2613            synchronized (mLock) {
2614                String action = intent.getAction();
2615                String pkgList[] = null;
2616                if (Intent.ACTION_QUERY_PACKAGE_RESTART.equals(action)) {
2617                    pkgList = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
2618                    for (String packageName : pkgList) {
2619                        if (lookForPackageLocked(packageName)) {
2620                            setResultCode(Activity.RESULT_OK);
2621                            return;
2622                        }
2623                    }
2624                    return;
2625                } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
2626                    pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
2627                } else if (Intent.ACTION_USER_STOPPED.equals(action)) {
2628                    int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
2629                    if (userHandle >= 0) {
2630                        removeUserLocked(userHandle);
2631                    }
2632                } else if (Intent.ACTION_UID_REMOVED.equals(action)) {
2633                    int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
2634                    if (uid >= 0) {
2635                        mLastAllowWhileIdleDispatch.delete(uid);
2636                    }
2637                } else {
2638                    if (Intent.ACTION_PACKAGE_REMOVED.equals(action)
2639                            && intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
2640                        // This package is being updated; don't kill its alarms.
2641                        return;
2642                    }
2643                    Uri data = intent.getData();
2644                    if (data != null) {
2645                        String pkg = data.getSchemeSpecificPart();
2646                        if (pkg != null) {
2647                            pkgList = new String[]{pkg};
2648                        }
2649                    }
2650                }
2651                if (pkgList != null && (pkgList.length > 0)) {
2652                    for (String pkg : pkgList) {
2653                        removeLocked(pkg);
2654                        mPriorities.remove(pkg);
2655                        for (int i=mBroadcastStats.size()-1; i>=0; i--) {
2656                            ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(i);
2657                            if (uidStats.remove(pkg) != null) {
2658                                if (uidStats.size() <= 0) {
2659                                    mBroadcastStats.removeAt(i);
2660                                }
2661                            }
2662                        }
2663                    }
2664                }
2665            }
2666        }
2667    }
2668
2669    private final BroadcastStats getStatsLocked(PendingIntent pi) {
2670        String pkg = pi.getCreatorPackage();
2671        int uid = pi.getCreatorUid();
2672        return getStatsLocked(uid, pkg);
2673    }
2674
2675    private final BroadcastStats getStatsLocked(int uid, String pkgName) {
2676        ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.get(uid);
2677        if (uidStats == null) {
2678            uidStats = new ArrayMap<String, BroadcastStats>();
2679            mBroadcastStats.put(uid, uidStats);
2680        }
2681        BroadcastStats bs = uidStats.get(pkgName);
2682        if (bs == null) {
2683            bs = new BroadcastStats(uid, pkgName);
2684            uidStats.put(pkgName, bs);
2685        }
2686        return bs;
2687    }
2688
2689    class DeliveryTracker extends IAlarmCompleteListener.Stub implements PendingIntent.OnFinished {
2690        private InFlight removeLocked(PendingIntent pi, Intent intent) {
2691            for (int i = 0; i < mInFlight.size(); i++) {
2692                if (mInFlight.get(i).mPendingIntent == pi) {
2693                    return mInFlight.remove(i);
2694                }
2695            }
2696            mLog.w("No in-flight alarm for " + pi + " " + intent);
2697            return null;
2698        }
2699
2700        private InFlight removeLocked(IBinder listener) {
2701            for (int i = 0; i < mInFlight.size(); i++) {
2702                if (mInFlight.get(i).mListener == listener) {
2703                    return mInFlight.remove(i);
2704                }
2705            }
2706            mLog.w("No in-flight alarm for listener " + listener);
2707            return null;
2708        }
2709
2710        private void updateStatsLocked(InFlight inflight) {
2711            final long nowELAPSED = SystemClock.elapsedRealtime();
2712            BroadcastStats bs = inflight.mBroadcastStats;
2713            bs.nesting--;
2714            if (bs.nesting <= 0) {
2715                bs.nesting = 0;
2716                bs.aggregateTime += nowELAPSED - bs.startTime;
2717            }
2718            FilterStats fs = inflight.mFilterStats;
2719            fs.nesting--;
2720            if (fs.nesting <= 0) {
2721                fs.nesting = 0;
2722                fs.aggregateTime += nowELAPSED - fs.startTime;
2723            }
2724            if (RECORD_ALARMS_IN_HISTORY) {
2725                if (inflight.mWorkSource != null && inflight.mWorkSource.size() > 0) {
2726                    for (int wi=0; wi<inflight.mWorkSource.size(); wi++) {
2727                        ActivityManagerNative.noteAlarmFinish(
2728                                inflight.mPendingIntent, inflight.mWorkSource.get(wi), inflight.mTag);
2729                    }
2730                } else {
2731                    ActivityManagerNative.noteAlarmFinish(
2732                            inflight.mPendingIntent, inflight.mUid, inflight.mTag);
2733                }
2734            }
2735        }
2736
2737        private void updateTrackingLocked(InFlight inflight) {
2738            if (inflight != null) {
2739                updateStatsLocked(inflight);
2740            }
2741            mBroadcastRefCount--;
2742            if (mBroadcastRefCount == 0) {
2743                mWakeLock.release();
2744                if (mInFlight.size() > 0) {
2745                    mLog.w("Finished all dispatches with " + mInFlight.size()
2746                            + " remaining inflights");
2747                    for (int i=0; i<mInFlight.size(); i++) {
2748                        mLog.w("  Remaining #" + i + ": " + mInFlight.get(i));
2749                    }
2750                    mInFlight.clear();
2751                }
2752            } else {
2753                // the next of our alarms is now in flight.  reattribute the wakelock.
2754                if (mInFlight.size() > 0) {
2755                    InFlight inFlight = mInFlight.get(0);
2756                    setWakelockWorkSource(inFlight.mPendingIntent, inFlight.mWorkSource,
2757                            inFlight.mAlarmType, inFlight.mTag, -1, false);
2758                } else {
2759                    // should never happen
2760                    mLog.w("Alarm wakelock still held but sent queue empty");
2761                    mWakeLock.setWorkSource(null);
2762                }
2763            }
2764        }
2765
2766        /**
2767         * Callback that arrives when a direct-call alarm reports that delivery has finished
2768         */
2769        @Override
2770        public void alarmComplete(IBinder who) {
2771            if (who == null) {
2772                Slog.w(TAG, "Invalid alarmComplete: uid=" + Binder.getCallingUid()
2773                        + " pid=" + Binder.getCallingPid());
2774                return;
2775            }
2776
2777            final long ident = Binder.clearCallingIdentity();
2778            try {
2779                synchronized (mLock) {
2780                    mHandler.removeMessages(AlarmHandler.LISTENER_TIMEOUT, who);
2781                    InFlight inflight = removeLocked(who);
2782                    if (inflight != null) {
2783                        if (DEBUG_LISTENER_CALLBACK) {
2784                            Slog.i(TAG, "alarmComplete() from " + who);
2785                        }
2786                        updateTrackingLocked(inflight);
2787                    } else {
2788                        // Delivery timed out, and the timeout handling already took care of
2789                        // updating our tracking here, so we needn't do anything further.
2790                        if (DEBUG_LISTENER_CALLBACK) {
2791                            Slog.i(TAG, "Late alarmComplete() from " + who);
2792                        }
2793                    }
2794                }
2795            } finally {
2796                Binder.restoreCallingIdentity(ident);
2797            }
2798        }
2799
2800        /**
2801         * Callback that arrives when a PendingIntent alarm has finished delivery
2802         */
2803        @Override
2804        public void onSendFinished(PendingIntent pi, Intent intent, int resultCode,
2805                String resultData, Bundle resultExtras) {
2806            synchronized (mLock) {
2807                updateTrackingLocked(removeLocked(pi, intent));
2808            }
2809        }
2810
2811        /**
2812         * Timeout of a direct-call alarm delivery
2813         */
2814        public void alarmTimedOut(IBinder who) {
2815            synchronized (mLock) {
2816                InFlight inflight = removeLocked(who);
2817                if (inflight != null) {
2818                    // TODO: implement ANR policy for the target
2819                    if (DEBUG_LISTENER_CALLBACK) {
2820                        Slog.i(TAG, "Alarm listener " + who + " timed out in delivery");
2821                    }
2822                    updateTrackingLocked(inflight);
2823                } else {
2824                    if (DEBUG_LISTENER_CALLBACK) {
2825                        Slog.i(TAG, "Spurious timeout of listener " + who);
2826                    }
2827                }
2828            }
2829        }
2830
2831        /**
2832         * Deliver an alarm and set up the post-delivery handling appropriately
2833         */
2834        public void deliverLocked(Alarm alarm, long nowELAPSED, boolean allowWhileIdle) {
2835            if (alarm.operation != null) {
2836                // PendingIntent alarm
2837                try {
2838                    alarm.operation.send(getContext(), 0,
2839                            mBackgroundIntent.putExtra(
2840                                    Intent.EXTRA_ALARM_COUNT, alarm.count),
2841                                    mDeliveryTracker, mHandler, null,
2842                                    allowWhileIdle ? mIdleOptions : null);
2843                } catch (PendingIntent.CanceledException e) {
2844                    if (alarm.repeatInterval > 0) {
2845                        // This IntentSender is no longer valid, but this
2846                        // is a repeating alarm, so toss it
2847                        removeImpl(alarm.operation);
2848                    }
2849                }
2850            } else {
2851                // Direct listener callback alarm
2852                try {
2853                    if (DEBUG_LISTENER_CALLBACK) {
2854                        Slog.v(TAG, "Alarm to uid=" + alarm.uid
2855                                + " listener=" + alarm.listener.asBinder());
2856                    }
2857                    alarm.listener.doAlarm(this);
2858                    mHandler.sendMessageDelayed(
2859                            mHandler.obtainMessage(AlarmHandler.LISTENER_TIMEOUT,
2860                                    alarm.listener.asBinder()),
2861                            mConstants.LISTENER_TIMEOUT);
2862                } catch (Exception e) {
2863                    if (DEBUG_LISTENER_CALLBACK) {
2864                        Slog.i(TAG, "Alarm undeliverable to listener "
2865                                + alarm.listener.asBinder(), e);
2866                    }
2867                }
2868            }
2869
2870            // The alarm is now in flight; now arrange wakelock and stats tracking
2871            if (mBroadcastRefCount == 0) {
2872                setWakelockWorkSource(alarm.operation, alarm.workSource,
2873                        alarm.type, alarm.statsTag, (alarm.operation == null) ? alarm.uid : -1,
2874                        true);
2875                mWakeLock.acquire();
2876            }
2877            final InFlight inflight = new InFlight(AlarmManagerService.this,
2878                    alarm.operation, alarm.listener, alarm.workSource, alarm.uid,
2879                    alarm.packageName, alarm.type, alarm.statsTag, nowELAPSED);
2880            mInFlight.add(inflight);
2881            mBroadcastRefCount++;
2882
2883            if (allowWhileIdle) {
2884                // Record the last time this uid handled an ALLOW_WHILE_IDLE alarm.
2885                mLastAllowWhileIdleDispatch.put(alarm.uid, nowELAPSED);
2886                if (RECORD_DEVICE_IDLE_ALARMS) {
2887                    IdleDispatchEntry ent = new IdleDispatchEntry();
2888                    ent.uid = alarm.uid;
2889                    ent.pkg = alarm.packageName;
2890                    ent.tag = alarm.statsTag;
2891                    ent.op = "DELIVER";
2892                    ent.elapsedRealtime = nowELAPSED;
2893                    mAllowWhileIdleDispatches.add(ent);
2894                }
2895            }
2896
2897            final BroadcastStats bs = inflight.mBroadcastStats;
2898            bs.count++;
2899            if (bs.nesting == 0) {
2900                bs.nesting = 1;
2901                bs.startTime = nowELAPSED;
2902            } else {
2903                bs.nesting++;
2904            }
2905            final FilterStats fs = inflight.mFilterStats;
2906            fs.count++;
2907            if (fs.nesting == 0) {
2908                fs.nesting = 1;
2909                fs.startTime = nowELAPSED;
2910            } else {
2911                fs.nesting++;
2912            }
2913            if (alarm.type == ELAPSED_REALTIME_WAKEUP
2914                    || alarm.type == RTC_WAKEUP) {
2915                bs.numWakeup++;
2916                fs.numWakeup++;
2917                if (alarm.workSource != null && alarm.workSource.size() > 0) {
2918                    for (int wi=0; wi<alarm.workSource.size(); wi++) {
2919                        ActivityManagerNative.noteWakeupAlarm(
2920                                alarm.operation, alarm.workSource.get(wi),
2921                                alarm.workSource.getName(wi), alarm.statsTag);
2922                    }
2923                } else {
2924                    ActivityManagerNative.noteWakeupAlarm(
2925                            alarm.operation, -1, alarm.packageName, alarm.statsTag);
2926                }
2927            }
2928        }
2929    }
2930}
2931