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