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