AlarmManagerService.java revision e555cb9f4afdd7a8e7c55379a13e8be696cca3e2
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
1736                    if (DEBUG_ALARM_CLOCK) {
1737                        Log.v(TAG, "Found AlarmClockInfo at " +
1738                                formatNextAlarm(getContext(), a.alarmClock, userId) +
1739                                " for user " + userId);
1740                    }
1741
1742                    // Alarms and batches are sorted by time, no need to compare times here.
1743                    if (nextForUser.get(userId) == null) {
1744                        nextForUser.put(userId, a.alarmClock);
1745                    }
1746                }
1747            }
1748        }
1749
1750        // Update mNextAlarmForUser with new values.
1751        final int NN = nextForUser.size();
1752        for (int i = 0; i < NN; i++) {
1753            AlarmManager.AlarmClockInfo newAlarm = nextForUser.valueAt(i);
1754            int userId = nextForUser.keyAt(i);
1755            AlarmManager.AlarmClockInfo currentAlarm = mNextAlarmClockForUser.get(userId);
1756            if (!newAlarm.equals(currentAlarm)) {
1757                updateNextAlarmInfoForUserLocked(userId, newAlarm);
1758            }
1759        }
1760
1761        // Remove users without any alarm clocks scheduled.
1762        final int NNN = mNextAlarmClockForUser.size();
1763        for (int i = NNN - 1; i >= 0; i--) {
1764            int userId = mNextAlarmClockForUser.keyAt(i);
1765            if (nextForUser.get(userId) == null) {
1766                updateNextAlarmInfoForUserLocked(userId, null);
1767            }
1768        }
1769    }
1770
1771    private void updateNextAlarmInfoForUserLocked(int userId,
1772            AlarmManager.AlarmClockInfo alarmClock) {
1773        if (alarmClock != null) {
1774            if (DEBUG_ALARM_CLOCK) {
1775                Log.v(TAG, "Next AlarmClockInfoForUser(" + userId + "): " +
1776                        formatNextAlarm(getContext(), alarmClock, userId));
1777            }
1778            mNextAlarmClockForUser.put(userId, alarmClock);
1779        } else {
1780            if (DEBUG_ALARM_CLOCK) {
1781                Log.v(TAG, "Next AlarmClockInfoForUser(" + userId + "): None");
1782            }
1783            mNextAlarmClockForUser.remove(userId);
1784        }
1785
1786        mPendingSendNextAlarmClockChangedForUser.put(userId, true);
1787        mHandler.removeMessages(AlarmHandler.SEND_NEXT_ALARM_CLOCK_CHANGED);
1788        mHandler.sendEmptyMessage(AlarmHandler.SEND_NEXT_ALARM_CLOCK_CHANGED);
1789    }
1790
1791    /**
1792     * Updates NEXT_ALARM_FORMATTED and sends NEXT_ALARM_CLOCK_CHANGED_INTENT for all users
1793     * for which alarm clocks have changed since the last call to this.
1794     *
1795     * Do not call with a lock held. Only call from mHandler's thread.
1796     *
1797     * @see AlarmHandler#SEND_NEXT_ALARM_CLOCK_CHANGED
1798     */
1799    private void sendNextAlarmClockChanged() {
1800        SparseArray<AlarmManager.AlarmClockInfo> pendingUsers = mHandlerSparseAlarmClockArray;
1801        pendingUsers.clear();
1802
1803        synchronized (mLock) {
1804            final int N  = mPendingSendNextAlarmClockChangedForUser.size();
1805            for (int i = 0; i < N; i++) {
1806                int userId = mPendingSendNextAlarmClockChangedForUser.keyAt(i);
1807                pendingUsers.append(userId, mNextAlarmClockForUser.get(userId));
1808            }
1809            mPendingSendNextAlarmClockChangedForUser.clear();
1810        }
1811
1812        final int N = pendingUsers.size();
1813        for (int i = 0; i < N; i++) {
1814            int userId = pendingUsers.keyAt(i);
1815            AlarmManager.AlarmClockInfo alarmClock = pendingUsers.valueAt(i);
1816            Settings.System.putStringForUser(getContext().getContentResolver(),
1817                    Settings.System.NEXT_ALARM_FORMATTED,
1818                    formatNextAlarm(getContext(), alarmClock, userId),
1819                    userId);
1820
1821            getContext().sendBroadcastAsUser(NEXT_ALARM_CLOCK_CHANGED_INTENT,
1822                    new UserHandle(userId));
1823        }
1824    }
1825
1826    /**
1827     * Formats an alarm like platform/packages/apps/DeskClock used to.
1828     */
1829    private static String formatNextAlarm(final Context context, AlarmManager.AlarmClockInfo info,
1830            int userId) {
1831        String skeleton = DateFormat.is24HourFormat(context, userId) ? "EHm" : "Ehma";
1832        String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton);
1833        return (info == null) ? "" :
1834                DateFormat.format(pattern, info.getTriggerTime()).toString();
1835    }
1836
1837    void rescheduleKernelAlarmsLocked() {
1838        // Schedule the next upcoming wakeup alarm.  If there is a deliverable batch
1839        // prior to that which contains no wakeups, we schedule that as well.
1840        long nextNonWakeup = 0;
1841        if (mAlarmBatches.size() > 0) {
1842            final Batch firstWakeup = findFirstWakeupBatchLocked();
1843            final Batch firstBatch = mAlarmBatches.get(0);
1844            if (firstWakeup != null && mNextWakeup != firstWakeup.start) {
1845                mNextWakeup = firstWakeup.start;
1846                mLastWakeupSet = SystemClock.elapsedRealtime();
1847                setLocked(ELAPSED_REALTIME_WAKEUP, firstWakeup.start);
1848            }
1849            if (firstBatch != firstWakeup) {
1850                nextNonWakeup = firstBatch.start;
1851            }
1852        }
1853        if (mPendingNonWakeupAlarms.size() > 0) {
1854            if (nextNonWakeup == 0 || mNextNonWakeupDeliveryTime < nextNonWakeup) {
1855                nextNonWakeup = mNextNonWakeupDeliveryTime;
1856            }
1857        }
1858        if (nextNonWakeup != 0 && mNextNonWakeup != nextNonWakeup) {
1859            mNextNonWakeup = nextNonWakeup;
1860            setLocked(ELAPSED_REALTIME, nextNonWakeup);
1861        }
1862    }
1863
1864    private void removeLocked(PendingIntent operation, IAlarmListener directReceiver) {
1865        boolean didRemove = false;
1866        for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
1867            Batch b = mAlarmBatches.get(i);
1868            didRemove |= b.remove(operation, directReceiver);
1869            if (b.size() == 0) {
1870                mAlarmBatches.remove(i);
1871            }
1872        }
1873        for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
1874            if (mPendingWhileIdleAlarms.get(i).matches(operation, directReceiver)) {
1875                // Don't set didRemove, since this doesn't impact the scheduled alarms.
1876                mPendingWhileIdleAlarms.remove(i);
1877            }
1878        }
1879
1880        if (didRemove) {
1881            if (DEBUG_BATCH) {
1882                Slog.v(TAG, "remove(operation) changed bounds; rebatching");
1883            }
1884            boolean restorePending = false;
1885            if (mPendingIdleUntil != null && mPendingIdleUntil.matches(operation, directReceiver)) {
1886                mPendingIdleUntil = null;
1887                restorePending = true;
1888            }
1889            if (mNextWakeFromIdle != null && mNextWakeFromIdle.matches(operation, directReceiver)) {
1890                mNextWakeFromIdle = null;
1891            }
1892            rebatchAllAlarmsLocked(true);
1893            if (restorePending) {
1894                restorePendingWhileIdleAlarmsLocked();
1895            }
1896            updateNextAlarmClockLocked();
1897        }
1898    }
1899
1900    void removeLocked(String packageName) {
1901        boolean didRemove = false;
1902        for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
1903            Batch b = mAlarmBatches.get(i);
1904            didRemove |= b.remove(packageName);
1905            if (b.size() == 0) {
1906                mAlarmBatches.remove(i);
1907            }
1908        }
1909        for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
1910            final Alarm a = mPendingWhileIdleAlarms.get(i);
1911            if (a.matches(packageName)) {
1912                // Don't set didRemove, since this doesn't impact the scheduled alarms.
1913                mPendingWhileIdleAlarms.remove(i);
1914            }
1915        }
1916
1917        if (didRemove) {
1918            if (DEBUG_BATCH) {
1919                Slog.v(TAG, "remove(package) changed bounds; rebatching");
1920            }
1921            rebatchAllAlarmsLocked(true);
1922            rescheduleKernelAlarmsLocked();
1923            updateNextAlarmClockLocked();
1924        }
1925    }
1926
1927    void removeForStoppedLocked(int uid) {
1928        boolean didRemove = false;
1929        for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
1930            Batch b = mAlarmBatches.get(i);
1931            didRemove |= b.removeForStopped(uid);
1932            if (b.size() == 0) {
1933                mAlarmBatches.remove(i);
1934            }
1935        }
1936        for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
1937            final Alarm a = mPendingWhileIdleAlarms.get(i);
1938            try {
1939                if (a.uid == uid && ActivityManagerNative.getDefault().getAppStartMode(
1940                        uid, a.packageName) == ActivityManager.APP_START_MODE_DISABLED) {
1941                    // Don't set didRemove, since this doesn't impact the scheduled alarms.
1942                    mPendingWhileIdleAlarms.remove(i);
1943                }
1944            } catch (RemoteException e) {
1945            }
1946        }
1947
1948        if (didRemove) {
1949            if (DEBUG_BATCH) {
1950                Slog.v(TAG, "remove(package) changed bounds; rebatching");
1951            }
1952            rebatchAllAlarmsLocked(true);
1953            rescheduleKernelAlarmsLocked();
1954            updateNextAlarmClockLocked();
1955        }
1956    }
1957
1958    void removeUserLocked(int userHandle) {
1959        boolean didRemove = false;
1960        for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
1961            Batch b = mAlarmBatches.get(i);
1962            didRemove |= b.remove(userHandle);
1963            if (b.size() == 0) {
1964                mAlarmBatches.remove(i);
1965            }
1966        }
1967        for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
1968            if (UserHandle.getUserId(mPendingWhileIdleAlarms.get(i).creatorUid)
1969                    == userHandle) {
1970                // Don't set didRemove, since this doesn't impact the scheduled alarms.
1971                mPendingWhileIdleAlarms.remove(i);
1972            }
1973        }
1974        for (int i = mLastAllowWhileIdleDispatch.size() - 1; i >= 0; i--) {
1975            if (UserHandle.getUserId(mLastAllowWhileIdleDispatch.keyAt(i)) == userHandle) {
1976                mLastAllowWhileIdleDispatch.removeAt(i);
1977            }
1978        }
1979
1980        if (didRemove) {
1981            if (DEBUG_BATCH) {
1982                Slog.v(TAG, "remove(user) changed bounds; rebatching");
1983            }
1984            rebatchAllAlarmsLocked(true);
1985            rescheduleKernelAlarmsLocked();
1986            updateNextAlarmClockLocked();
1987        }
1988    }
1989
1990    void interactiveStateChangedLocked(boolean interactive) {
1991        if (mInteractive != interactive) {
1992            mInteractive = interactive;
1993            final long nowELAPSED = SystemClock.elapsedRealtime();
1994            if (interactive) {
1995                if (mPendingNonWakeupAlarms.size() > 0) {
1996                    final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
1997                    mTotalDelayTime += thisDelayTime;
1998                    if (mMaxDelayTime < thisDelayTime) {
1999                        mMaxDelayTime = thisDelayTime;
2000                    }
2001                    deliverAlarmsLocked(mPendingNonWakeupAlarms, nowELAPSED);
2002                    mPendingNonWakeupAlarms.clear();
2003                }
2004                if (mNonInteractiveStartTime > 0) {
2005                    long dur = nowELAPSED - mNonInteractiveStartTime;
2006                    if (dur > mNonInteractiveTime) {
2007                        mNonInteractiveTime = dur;
2008                    }
2009                }
2010            } else {
2011                mNonInteractiveStartTime = nowELAPSED;
2012            }
2013        }
2014    }
2015
2016    boolean lookForPackageLocked(String packageName) {
2017        for (int i = 0; i < mAlarmBatches.size(); i++) {
2018            Batch b = mAlarmBatches.get(i);
2019            if (b.hasPackage(packageName)) {
2020                return true;
2021            }
2022        }
2023        for (int i = 0; i < mPendingWhileIdleAlarms.size(); i++) {
2024            final Alarm a = mPendingWhileIdleAlarms.get(i);
2025            if (a.matches(packageName)) {
2026                return true;
2027            }
2028        }
2029        return false;
2030    }
2031
2032    private void setLocked(int type, long when) {
2033        if (mNativeData != 0) {
2034            // The kernel never triggers alarms with negative wakeup times
2035            // so we ensure they are positive.
2036            long alarmSeconds, alarmNanoseconds;
2037            if (when < 0) {
2038                alarmSeconds = 0;
2039                alarmNanoseconds = 0;
2040            } else {
2041                alarmSeconds = when / 1000;
2042                alarmNanoseconds = (when % 1000) * 1000 * 1000;
2043            }
2044
2045            set(mNativeData, type, alarmSeconds, alarmNanoseconds);
2046        } else {
2047            Message msg = Message.obtain();
2048            msg.what = ALARM_EVENT;
2049
2050            mHandler.removeMessages(ALARM_EVENT);
2051            mHandler.sendMessageAtTime(msg, when);
2052        }
2053    }
2054
2055    private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list,
2056            String prefix, String label, long nowRTC, long nowELAPSED, SimpleDateFormat sdf) {
2057        for (int i=list.size()-1; i>=0; i--) {
2058            Alarm a = list.get(i);
2059            pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i);
2060                    pw.print(": "); pw.println(a);
2061            a.dump(pw, prefix + "  ", nowRTC, nowELAPSED, sdf);
2062        }
2063    }
2064
2065    private static final String labelForType(int type) {
2066        switch (type) {
2067        case RTC: return "RTC";
2068        case RTC_WAKEUP : return "RTC_WAKEUP";
2069        case ELAPSED_REALTIME : return "ELAPSED";
2070        case ELAPSED_REALTIME_WAKEUP: return "ELAPSED_WAKEUP";
2071        default:
2072            break;
2073        }
2074        return "--unknown--";
2075    }
2076
2077    private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list,
2078            String prefix, long nowELAPSED, long nowRTC, SimpleDateFormat sdf) {
2079        for (int i=list.size()-1; i>=0; i--) {
2080            Alarm a = list.get(i);
2081            final String label = labelForType(a.type);
2082            pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i);
2083                    pw.print(": "); pw.println(a);
2084            a.dump(pw, prefix + "  ", nowRTC, nowELAPSED, sdf);
2085        }
2086    }
2087
2088    private native long init();
2089    private native void close(long nativeData);
2090    private native void set(long nativeData, int type, long seconds, long nanoseconds);
2091    private native int waitForAlarm(long nativeData);
2092    private native int setKernelTime(long nativeData, long millis);
2093    private native int setKernelTimezone(long nativeData, int minuteswest);
2094
2095    boolean triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED,
2096            final long nowRTC) {
2097        boolean hasWakeup = false;
2098        // batches are temporally sorted, so we need only pull from the
2099        // start of the list until we either empty it or hit a batch
2100        // that is not yet deliverable
2101        while (mAlarmBatches.size() > 0) {
2102            Batch batch = mAlarmBatches.get(0);
2103            if (batch.start > nowELAPSED) {
2104                // Everything else is scheduled for the future
2105                break;
2106            }
2107
2108            // We will (re)schedule some alarms now; don't let that interfere
2109            // with delivery of this current batch
2110            mAlarmBatches.remove(0);
2111
2112            final int N = batch.size();
2113            for (int i = 0; i < N; i++) {
2114                Alarm alarm = batch.get(i);
2115
2116                if ((alarm.flags&AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) {
2117                    // If this is an ALLOW_WHILE_IDLE alarm, we constrain how frequently the app can
2118                    // schedule such alarms.
2119                    long lastTime = mLastAllowWhileIdleDispatch.get(alarm.uid, 0);
2120                    long minTime = lastTime + mAllowWhileIdleMinTime;
2121                    if (nowELAPSED < minTime) {
2122                        // Whoops, it hasn't been long enough since the last ALLOW_WHILE_IDLE
2123                        // alarm went off for this app.  Reschedule the alarm to be in the
2124                        // correct time period.
2125                        alarm.whenElapsed = minTime;
2126                        if (alarm.maxWhenElapsed < minTime) {
2127                            alarm.maxWhenElapsed = minTime;
2128                        }
2129                        if (RECORD_DEVICE_IDLE_ALARMS) {
2130                            IdleDispatchEntry ent = new IdleDispatchEntry();
2131                            ent.uid = alarm.uid;
2132                            ent.pkg = alarm.operation.getCreatorPackage();
2133                            ent.tag = alarm.operation.getTag("");
2134                            ent.op = "RESCHEDULE";
2135                            ent.elapsedRealtime = nowELAPSED;
2136                            ent.argRealtime = lastTime;
2137                            mAllowWhileIdleDispatches.add(ent);
2138                        }
2139                        setImplLocked(alarm, true, false);
2140                        continue;
2141                    }
2142                }
2143
2144                alarm.count = 1;
2145                triggerList.add(alarm);
2146                if ((alarm.flags&AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) {
2147                    EventLogTags.writeDeviceIdleWakeFromIdle(mPendingIdleUntil != null ? 1 : 0,
2148                            alarm.statsTag);
2149                }
2150                if (mPendingIdleUntil == alarm) {
2151                    mPendingIdleUntil = null;
2152                    rebatchAllAlarmsLocked(false);
2153                    restorePendingWhileIdleAlarmsLocked();
2154                }
2155                if (mNextWakeFromIdle == alarm) {
2156                    mNextWakeFromIdle = null;
2157                    rebatchAllAlarmsLocked(false);
2158                }
2159
2160                // Recurring alarms may have passed several alarm intervals while the
2161                // phone was asleep or off, so pass a trigger count when sending them.
2162                if (alarm.repeatInterval > 0) {
2163                    // this adjustment will be zero if we're late by
2164                    // less than one full repeat interval
2165                    alarm.count += (nowELAPSED - alarm.whenElapsed) / alarm.repeatInterval;
2166
2167                    // Also schedule its next recurrence
2168                    final long delta = alarm.count * alarm.repeatInterval;
2169                    final long nextElapsed = alarm.whenElapsed + delta;
2170                    setImplLocked(alarm.type, alarm.when + delta, nextElapsed, alarm.windowLength,
2171                            maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval),
2172                            alarm.repeatInterval, alarm.operation, null, null, alarm.flags, true,
2173                            alarm.workSource, alarm.alarmClock, alarm.uid, alarm.packageName);
2174                }
2175
2176                if (alarm.wakeup) {
2177                    hasWakeup = true;
2178                }
2179
2180                // We removed an alarm clock. Let the caller recompute the next alarm clock.
2181                if (alarm.alarmClock != null) {
2182                    mNextAlarmClockMayChange = true;
2183                }
2184            }
2185        }
2186
2187        // This is a new alarm delivery set; bump the sequence number to indicate that
2188        // all apps' alarm delivery classes should be recalculated.
2189        mCurrentSeq++;
2190        calculateDeliveryPriorities(triggerList);
2191        Collections.sort(triggerList, mAlarmDispatchComparator);
2192
2193        if (localLOGV) {
2194            for (int i=0; i<triggerList.size(); i++) {
2195                Slog.v(TAG, "Triggering alarm #" + i + ": " + triggerList.get(i));
2196            }
2197        }
2198
2199        return hasWakeup;
2200    }
2201
2202    /**
2203     * This Comparator sorts Alarms into increasing time order.
2204     */
2205    public static class IncreasingTimeOrder implements Comparator<Alarm> {
2206        public int compare(Alarm a1, Alarm a2) {
2207            long when1 = a1.whenElapsed;
2208            long when2 = a2.whenElapsed;
2209            if (when1 > when2) {
2210                return 1;
2211            }
2212            if (when1 < when2) {
2213                return -1;
2214            }
2215            return 0;
2216        }
2217    }
2218
2219    private static class Alarm {
2220        public final int type;
2221        public final long origWhen;
2222        public final boolean wakeup;
2223        public final PendingIntent operation;
2224        public final IAlarmListener listener;
2225        public final String listenerTag;
2226        public final String statsTag;
2227        public final WorkSource workSource;
2228        public final int flags;
2229        public final AlarmManager.AlarmClockInfo alarmClock;
2230        public final int uid;
2231        public final int creatorUid;
2232        public final String packageName;
2233        public int count;
2234        public long when;
2235        public long windowLength;
2236        public long whenElapsed;    // 'when' in the elapsed time base
2237        public long maxWhenElapsed; // also in the elapsed time base
2238        public long repeatInterval;
2239        public PriorityClass priorityClass;
2240
2241        public Alarm(int _type, long _when, long _whenElapsed, long _windowLength, long _maxWhen,
2242                long _interval, PendingIntent _op, IAlarmListener _rec, String _listenerTag,
2243                WorkSource _ws, int _flags, AlarmManager.AlarmClockInfo _info,
2244                int _uid, String _pkgName) {
2245            type = _type;
2246            origWhen = _when;
2247            wakeup = _type == AlarmManager.ELAPSED_REALTIME_WAKEUP
2248                    || _type == AlarmManager.RTC_WAKEUP;
2249            when = _when;
2250            whenElapsed = _whenElapsed;
2251            windowLength = _windowLength;
2252            maxWhenElapsed = _maxWhen;
2253            repeatInterval = _interval;
2254            operation = _op;
2255            listener = _rec;
2256            listenerTag = _listenerTag;
2257            statsTag = makeTag(_op, _listenerTag, _type);
2258            workSource = _ws;
2259            flags = _flags;
2260            alarmClock = _info;
2261            uid = _uid;
2262            packageName = _pkgName;
2263
2264            creatorUid = (operation != null) ? operation.getCreatorUid() : uid;
2265        }
2266
2267        public static String makeTag(PendingIntent pi, String tag, int type) {
2268            final String alarmString = type == ELAPSED_REALTIME_WAKEUP || type == RTC_WAKEUP
2269                    ? "*walarm*:" : "*alarm*:";
2270            return (pi != null) ? pi.getTag(alarmString) : (alarmString + tag);
2271        }
2272
2273        public WakeupEvent makeWakeupEvent(long nowRTC) {
2274            return new WakeupEvent(nowRTC, creatorUid,
2275                    (operation != null)
2276                        ? operation.getIntent().getAction()
2277                        : ("<listener>:" + listenerTag));
2278        }
2279
2280        // Returns true if either matches
2281        public boolean matches(PendingIntent pi, IAlarmListener rec) {
2282            return (operation != null)
2283                    ? operation.equals(pi)
2284                    : rec != null && listener.asBinder().equals(rec.asBinder());
2285        }
2286
2287        public boolean matches(String packageName) {
2288            return (operation != null)
2289                    ? packageName.equals(operation.getTargetPackage())
2290                    : packageName.equals(this.packageName);
2291        }
2292
2293        @Override
2294        public String toString() {
2295            StringBuilder sb = new StringBuilder(128);
2296            sb.append("Alarm{");
2297            sb.append(Integer.toHexString(System.identityHashCode(this)));
2298            sb.append(" type ");
2299            sb.append(type);
2300            sb.append(" when ");
2301            sb.append(when);
2302            sb.append(" ");
2303            if (operation != null) {
2304                sb.append(operation.getTargetPackage());
2305            } else {
2306                sb.append(packageName);
2307            }
2308            sb.append('}');
2309            return sb.toString();
2310        }
2311
2312        public void dump(PrintWriter pw, String prefix, long nowRTC, long nowELAPSED,
2313                SimpleDateFormat sdf) {
2314            final boolean isRtc = (type == RTC || type == RTC_WAKEUP);
2315            pw.print(prefix); pw.print("tag="); pw.println(statsTag);
2316            pw.print(prefix); pw.print("type="); pw.print(type);
2317                    pw.print(" whenElapsed="); TimeUtils.formatDuration(whenElapsed,
2318                            nowELAPSED, pw);
2319                    pw.print(" when=");
2320                    if (isRtc) {
2321                        pw.print(sdf.format(new Date(when)));
2322                    } else {
2323                        TimeUtils.formatDuration(when, nowELAPSED, pw);
2324                    }
2325                    pw.println();
2326            pw.print(prefix); pw.print("window="); TimeUtils.formatDuration(windowLength, pw);
2327                    pw.print(" repeatInterval="); pw.print(repeatInterval);
2328                    pw.print(" count="); pw.print(count);
2329                    pw.print(" flags=0x"); pw.println(Integer.toHexString(flags));
2330            if (alarmClock != null) {
2331                pw.print(prefix); pw.println("Alarm clock:");
2332                pw.print(prefix); pw.print("  triggerTime=");
2333                pw.println(sdf.format(new Date(alarmClock.getTriggerTime())));
2334                pw.print(prefix); pw.print("  showIntent="); pw.println(alarmClock.getShowIntent());
2335            }
2336            pw.print(prefix); pw.print("operation="); pw.println(operation);
2337            if (listener != null) {
2338                pw.print(prefix); pw.print("listener="); pw.println(listener.asBinder());
2339            }
2340        }
2341    }
2342
2343    void recordWakeupAlarms(ArrayList<Batch> batches, long nowELAPSED, long nowRTC) {
2344        final int numBatches = batches.size();
2345        for (int nextBatch = 0; nextBatch < numBatches; nextBatch++) {
2346            Batch b = batches.get(nextBatch);
2347            if (b.start > nowELAPSED) {
2348                break;
2349            }
2350
2351            final int numAlarms = b.alarms.size();
2352            for (int nextAlarm = 0; nextAlarm < numAlarms; nextAlarm++) {
2353                Alarm a = b.alarms.get(nextAlarm);
2354                mRecentWakeups.add(a.makeWakeupEvent(nowRTC));
2355            }
2356        }
2357    }
2358
2359    long currentNonWakeupFuzzLocked(long nowELAPSED) {
2360        long timeSinceOn = nowELAPSED - mNonInteractiveStartTime;
2361        if (timeSinceOn < 5*60*1000) {
2362            // If the screen has been off for 5 minutes, only delay by at most two minutes.
2363            return 2*60*1000;
2364        } else if (timeSinceOn < 30*60*1000) {
2365            // If the screen has been off for 30 minutes, only delay by at most 15 minutes.
2366            return 15*60*1000;
2367        } else {
2368            // Otherwise, we will delay by at most an hour.
2369            return 60*60*1000;
2370        }
2371    }
2372
2373    static int fuzzForDuration(long duration) {
2374        if (duration < 15*60*1000) {
2375            // If the duration until the time is less than 15 minutes, the maximum fuzz
2376            // is the duration.
2377            return (int)duration;
2378        } else if (duration < 90*60*1000) {
2379            // If duration is less than 1 1/2 hours, the maximum fuzz is 15 minutes,
2380            return 15*60*1000;
2381        } else {
2382            // Otherwise, we will fuzz by at most half an hour.
2383            return 30*60*1000;
2384        }
2385    }
2386
2387    boolean checkAllowNonWakeupDelayLocked(long nowELAPSED) {
2388        if (mInteractive) {
2389            return false;
2390        }
2391        if (mLastAlarmDeliveryTime <= 0) {
2392            return false;
2393        }
2394        if (mPendingNonWakeupAlarms.size() > 0 && mNextNonWakeupDeliveryTime < nowELAPSED) {
2395            // This is just a little paranoia, if somehow we have pending non-wakeup alarms
2396            // and the next delivery time is in the past, then just deliver them all.  This
2397            // avoids bugs where we get stuck in a loop trying to poll for alarms.
2398            return false;
2399        }
2400        long timeSinceLast = nowELAPSED - mLastAlarmDeliveryTime;
2401        return timeSinceLast <= currentNonWakeupFuzzLocked(nowELAPSED);
2402    }
2403
2404    void deliverAlarmsLocked(ArrayList<Alarm> triggerList, long nowELAPSED) {
2405        mLastAlarmDeliveryTime = nowELAPSED;
2406        for (int i=0; i<triggerList.size(); i++) {
2407            Alarm alarm = triggerList.get(i);
2408            final boolean allowWhileIdle = (alarm.flags&AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0;
2409            try {
2410                if (localLOGV) {
2411                    Slog.v(TAG, "sending alarm " + alarm);
2412                }
2413                if (RECORD_ALARMS_IN_HISTORY) {
2414                    if (alarm.workSource != null && alarm.workSource.size() > 0) {
2415                        for (int wi=0; wi<alarm.workSource.size(); wi++) {
2416                            ActivityManagerNative.noteAlarmStart(
2417                                    alarm.operation, alarm.workSource.get(wi), alarm.statsTag);
2418                        }
2419                    } else {
2420                        ActivityManagerNative.noteAlarmStart(
2421                                alarm.operation, alarm.uid, alarm.statsTag);
2422                    }
2423                }
2424                mDeliveryTracker.deliverLocked(alarm, nowELAPSED, allowWhileIdle);
2425            } catch (RuntimeException e) {
2426                Slog.w(TAG, "Failure sending alarm.", e);
2427            }
2428        }
2429    }
2430
2431    private class AlarmThread extends Thread
2432    {
2433        public AlarmThread()
2434        {
2435            super("AlarmManager");
2436        }
2437
2438        public void run()
2439        {
2440            ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
2441
2442            while (true)
2443            {
2444                int result = waitForAlarm(mNativeData);
2445                mLastWakeup = SystemClock.elapsedRealtime();
2446
2447                triggerList.clear();
2448
2449                final long nowRTC = System.currentTimeMillis();
2450                final long nowELAPSED = SystemClock.elapsedRealtime();
2451
2452                if ((result & TIME_CHANGED_MASK) != 0) {
2453                    // The kernel can give us spurious time change notifications due to
2454                    // small adjustments it makes internally; we want to filter those out.
2455                    final long lastTimeChangeClockTime;
2456                    final long expectedClockTime;
2457                    synchronized (mLock) {
2458                        lastTimeChangeClockTime = mLastTimeChangeClockTime;
2459                        expectedClockTime = lastTimeChangeClockTime
2460                                + (nowELAPSED - mLastTimeChangeRealtime);
2461                    }
2462                    if (lastTimeChangeClockTime == 0 || nowRTC < (expectedClockTime-500)
2463                            || nowRTC > (expectedClockTime+500)) {
2464                        // The change is by at least +/- 500 ms (or this is the first change),
2465                        // let's do it!
2466                        if (DEBUG_BATCH) {
2467                            Slog.v(TAG, "Time changed notification from kernel; rebatching");
2468                        }
2469                        removeImpl(mTimeTickSender);
2470                        rebatchAllAlarms();
2471                        mClockReceiver.scheduleTimeTickEvent();
2472                        synchronized (mLock) {
2473                            mNumTimeChanged++;
2474                            mLastTimeChangeClockTime = nowRTC;
2475                            mLastTimeChangeRealtime = nowELAPSED;
2476                        }
2477                        Intent intent = new Intent(Intent.ACTION_TIME_CHANGED);
2478                        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
2479                                | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
2480                        getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
2481
2482                        // The world has changed on us, so we need to re-evaluate alarms
2483                        // regardless of whether the kernel has told us one went off.
2484                        result |= IS_WAKEUP_MASK;
2485                    }
2486                }
2487
2488                if (result != TIME_CHANGED_MASK) {
2489                    // If this was anything besides just a time change, then figure what if
2490                    // anything to do about alarms.
2491                    synchronized (mLock) {
2492                        if (localLOGV) Slog.v(
2493                            TAG, "Checking for alarms... rtc=" + nowRTC
2494                            + ", elapsed=" + nowELAPSED);
2495
2496                        if (WAKEUP_STATS) {
2497                            if ((result & IS_WAKEUP_MASK) != 0) {
2498                                long newEarliest = nowRTC - RECENT_WAKEUP_PERIOD;
2499                                int n = 0;
2500                                for (WakeupEvent event : mRecentWakeups) {
2501                                    if (event.when > newEarliest) break;
2502                                    n++; // number of now-stale entries at the list head
2503                                }
2504                                for (int i = 0; i < n; i++) {
2505                                    mRecentWakeups.remove();
2506                                }
2507
2508                                recordWakeupAlarms(mAlarmBatches, nowELAPSED, nowRTC);
2509                            }
2510                        }
2511
2512                        boolean hasWakeup = triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC);
2513                        if (!hasWakeup && checkAllowNonWakeupDelayLocked(nowELAPSED)) {
2514                            // if there are no wakeup alarms and the screen is off, we can
2515                            // delay what we have so far until the future.
2516                            if (mPendingNonWakeupAlarms.size() == 0) {
2517                                mStartCurrentDelayTime = nowELAPSED;
2518                                mNextNonWakeupDeliveryTime = nowELAPSED
2519                                        + ((currentNonWakeupFuzzLocked(nowELAPSED)*3)/2);
2520                            }
2521                            mPendingNonWakeupAlarms.addAll(triggerList);
2522                            mNumDelayedAlarms += triggerList.size();
2523                            rescheduleKernelAlarmsLocked();
2524                            updateNextAlarmClockLocked();
2525                        } else {
2526                            // now deliver the alarm intents; if there are pending non-wakeup
2527                            // alarms, we need to merge them in to the list.  note we don't
2528                            // just deliver them first because we generally want non-wakeup
2529                            // alarms delivered after wakeup alarms.
2530                            rescheduleKernelAlarmsLocked();
2531                            updateNextAlarmClockLocked();
2532                            if (mPendingNonWakeupAlarms.size() > 0) {
2533                                calculateDeliveryPriorities(mPendingNonWakeupAlarms);
2534                                triggerList.addAll(mPendingNonWakeupAlarms);
2535                                Collections.sort(triggerList, mAlarmDispatchComparator);
2536                                final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
2537                                mTotalDelayTime += thisDelayTime;
2538                                if (mMaxDelayTime < thisDelayTime) {
2539                                    mMaxDelayTime = thisDelayTime;
2540                                }
2541                                mPendingNonWakeupAlarms.clear();
2542                            }
2543                            deliverAlarmsLocked(triggerList, nowELAPSED);
2544                        }
2545                    }
2546
2547                } else {
2548                    // Just in case -- even though no wakeup flag was set, make sure
2549                    // we have updated the kernel to the next alarm time.
2550                    rescheduleKernelAlarmsLocked();
2551                }
2552            }
2553        }
2554    }
2555
2556    /**
2557     * Attribute blame for a WakeLock.
2558     * @param pi PendingIntent to attribute blame to if ws is null.
2559     * @param ws WorkSource to attribute blame.
2560     * @param knownUid attribution uid; < 0 if we need to derive it from the PendingIntent sender
2561     */
2562    void setWakelockWorkSource(PendingIntent pi, WorkSource ws, int type, String tag,
2563            int knownUid, boolean first) {
2564        try {
2565            final boolean unimportant = pi == mTimeTickSender;
2566            mWakeLock.setUnimportantForLogging(unimportant);
2567            if (first || mLastWakeLockUnimportantForLogging) {
2568                mWakeLock.setHistoryTag(tag);
2569            } else {
2570                mWakeLock.setHistoryTag(null);
2571            }
2572            mLastWakeLockUnimportantForLogging = unimportant;
2573            if (ws != null) {
2574                mWakeLock.setWorkSource(ws);
2575                return;
2576            }
2577
2578            final int uid = (knownUid >= 0)
2579                    ? knownUid
2580                    : ActivityManagerNative.getDefault().getUidForIntentSender(pi.getTarget());
2581            if (uid >= 0) {
2582                mWakeLock.setWorkSource(new WorkSource(uid));
2583                return;
2584            }
2585        } catch (Exception e) {
2586        }
2587
2588        // Something went wrong; fall back to attributing the lock to the OS
2589        mWakeLock.setWorkSource(null);
2590    }
2591
2592    private class AlarmHandler extends Handler {
2593        public static final int ALARM_EVENT = 1;
2594        public static final int SEND_NEXT_ALARM_CLOCK_CHANGED = 2;
2595        public static final int LISTENER_TIMEOUT = 3;
2596        public static final int REPORT_ALARMS_ACTIVE = 4;
2597
2598        public AlarmHandler() {
2599        }
2600
2601        public void handleMessage(Message msg) {
2602            switch (msg.what) {
2603                case ALARM_EVENT: {
2604                    ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
2605                    synchronized (mLock) {
2606                        final long nowRTC = System.currentTimeMillis();
2607                        final long nowELAPSED = SystemClock.elapsedRealtime();
2608                        triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC);
2609                        updateNextAlarmClockLocked();
2610                    }
2611
2612                    // now trigger the alarms without the lock held
2613                    for (int i=0; i<triggerList.size(); i++) {
2614                        Alarm alarm = triggerList.get(i);
2615                        try {
2616                            alarm.operation.send();
2617                        } catch (PendingIntent.CanceledException e) {
2618                            if (alarm.repeatInterval > 0) {
2619                                // This IntentSender is no longer valid, but this
2620                                // is a repeating alarm, so toss the hoser.
2621                                removeImpl(alarm.operation);
2622                            }
2623                        }
2624                    }
2625                    break;
2626                }
2627
2628                case SEND_NEXT_ALARM_CLOCK_CHANGED:
2629                    sendNextAlarmClockChanged();
2630                    break;
2631
2632                case LISTENER_TIMEOUT:
2633                    mDeliveryTracker.alarmTimedOut((IBinder) msg.obj);
2634                    break;
2635
2636                case REPORT_ALARMS_ACTIVE:
2637                    if (mLocalDeviceIdleController != null) {
2638                        mLocalDeviceIdleController.setAlarmsActive(msg.arg1 != 0);
2639                    }
2640                    break;
2641
2642                default:
2643                    // nope, just ignore it
2644                    break;
2645            }
2646        }
2647    }
2648
2649    class ClockReceiver extends BroadcastReceiver {
2650        public ClockReceiver() {
2651            IntentFilter filter = new IntentFilter();
2652            filter.addAction(Intent.ACTION_TIME_TICK);
2653            filter.addAction(Intent.ACTION_DATE_CHANGED);
2654            getContext().registerReceiver(this, filter);
2655        }
2656
2657        @Override
2658        public void onReceive(Context context, Intent intent) {
2659            if (intent.getAction().equals(Intent.ACTION_TIME_TICK)) {
2660                if (DEBUG_BATCH) {
2661                    Slog.v(TAG, "Received TIME_TICK alarm; rescheduling");
2662                }
2663                scheduleTimeTickEvent();
2664            } else if (intent.getAction().equals(Intent.ACTION_DATE_CHANGED)) {
2665                // Since the kernel does not keep track of DST, we need to
2666                // reset the TZ information at the beginning of each day
2667                // based off of the current Zone gmt offset + userspace tracked
2668                // daylight savings information.
2669                TimeZone zone = TimeZone.getTimeZone(SystemProperties.get(TIMEZONE_PROPERTY));
2670                int gmtOffset = zone.getOffset(System.currentTimeMillis());
2671                setKernelTimezone(mNativeData, -(gmtOffset / 60000));
2672                scheduleDateChangedEvent();
2673            }
2674        }
2675
2676        public void scheduleTimeTickEvent() {
2677            final long currentTime = System.currentTimeMillis();
2678            final long nextTime = 60000 * ((currentTime / 60000) + 1);
2679
2680            // Schedule this event for the amount of time that it would take to get to
2681            // the top of the next minute.
2682            final long tickEventDelay = nextTime - currentTime;
2683
2684            final WorkSource workSource = null; // Let system take blame for time tick events.
2685            setImpl(ELAPSED_REALTIME, SystemClock.elapsedRealtime() + tickEventDelay, 0,
2686                    0, mTimeTickSender, null, null, AlarmManager.FLAG_STANDALONE, workSource,
2687                    null, Process.myUid(), "android");
2688        }
2689
2690        public void scheduleDateChangedEvent() {
2691            Calendar calendar = Calendar.getInstance();
2692            calendar.setTimeInMillis(System.currentTimeMillis());
2693            calendar.set(Calendar.HOUR, 0);
2694            calendar.set(Calendar.MINUTE, 0);
2695            calendar.set(Calendar.SECOND, 0);
2696            calendar.set(Calendar.MILLISECOND, 0);
2697            calendar.add(Calendar.DAY_OF_MONTH, 1);
2698
2699            final WorkSource workSource = null; // Let system take blame for date change events.
2700            setImpl(RTC, calendar.getTimeInMillis(), 0, 0, mDateChangeSender, null, null,
2701                    AlarmManager.FLAG_STANDALONE, workSource, null,
2702                    Process.myUid(), "android");
2703        }
2704    }
2705
2706    class InteractiveStateReceiver extends BroadcastReceiver {
2707        public InteractiveStateReceiver() {
2708            IntentFilter filter = new IntentFilter();
2709            filter.addAction(Intent.ACTION_SCREEN_OFF);
2710            filter.addAction(Intent.ACTION_SCREEN_ON);
2711            filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
2712            getContext().registerReceiver(this, filter);
2713        }
2714
2715        @Override
2716        public void onReceive(Context context, Intent intent) {
2717            synchronized (mLock) {
2718                interactiveStateChangedLocked(Intent.ACTION_SCREEN_ON.equals(intent.getAction()));
2719            }
2720        }
2721    }
2722
2723    class UninstallReceiver extends BroadcastReceiver {
2724        public UninstallReceiver() {
2725            IntentFilter filter = new IntentFilter();
2726            filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
2727            filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
2728            filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
2729            filter.addDataScheme("package");
2730            getContext().registerReceiver(this, filter);
2731             // Register for events related to sdcard installation.
2732            IntentFilter sdFilter = new IntentFilter();
2733            sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
2734            sdFilter.addAction(Intent.ACTION_USER_STOPPED);
2735            sdFilter.addAction(Intent.ACTION_UID_REMOVED);
2736            getContext().registerReceiver(this, sdFilter);
2737        }
2738
2739        @Override
2740        public void onReceive(Context context, Intent intent) {
2741            synchronized (mLock) {
2742                String action = intent.getAction();
2743                String pkgList[] = null;
2744                if (Intent.ACTION_QUERY_PACKAGE_RESTART.equals(action)) {
2745                    pkgList = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
2746                    for (String packageName : pkgList) {
2747                        if (lookForPackageLocked(packageName)) {
2748                            setResultCode(Activity.RESULT_OK);
2749                            return;
2750                        }
2751                    }
2752                    return;
2753                } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
2754                    pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
2755                } else if (Intent.ACTION_USER_STOPPED.equals(action)) {
2756                    int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
2757                    if (userHandle >= 0) {
2758                        removeUserLocked(userHandle);
2759                    }
2760                } else if (Intent.ACTION_UID_REMOVED.equals(action)) {
2761                    int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
2762                    if (uid >= 0) {
2763                        mLastAllowWhileIdleDispatch.delete(uid);
2764                    }
2765                } else {
2766                    if (Intent.ACTION_PACKAGE_REMOVED.equals(action)
2767                            && intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
2768                        // This package is being updated; don't kill its alarms.
2769                        return;
2770                    }
2771                    Uri data = intent.getData();
2772                    if (data != null) {
2773                        String pkg = data.getSchemeSpecificPart();
2774                        if (pkg != null) {
2775                            pkgList = new String[]{pkg};
2776                        }
2777                    }
2778                }
2779                if (pkgList != null && (pkgList.length > 0)) {
2780                    for (String pkg : pkgList) {
2781                        removeLocked(pkg);
2782                        mPriorities.remove(pkg);
2783                        for (int i=mBroadcastStats.size()-1; i>=0; i--) {
2784                            ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(i);
2785                            if (uidStats.remove(pkg) != null) {
2786                                if (uidStats.size() <= 0) {
2787                                    mBroadcastStats.removeAt(i);
2788                                }
2789                            }
2790                        }
2791                    }
2792                }
2793            }
2794        }
2795    }
2796
2797    final class UidObserver extends IUidObserver.Stub {
2798        @Override public void onUidStateChanged(int uid, int procState) throws RemoteException {
2799        }
2800
2801        @Override public void onUidGone(int uid) throws RemoteException {
2802        }
2803
2804        @Override public void onUidActive(int uid) throws RemoteException {
2805        }
2806
2807        @Override public void onUidIdle(int uid) throws RemoteException {
2808            synchronized (mLock) {
2809                removeForStoppedLocked(uid);
2810            }
2811        }
2812    };
2813
2814    private final BroadcastStats getStatsLocked(PendingIntent pi) {
2815        String pkg = pi.getCreatorPackage();
2816        int uid = pi.getCreatorUid();
2817        return getStatsLocked(uid, pkg);
2818    }
2819
2820    private final BroadcastStats getStatsLocked(int uid, String pkgName) {
2821        ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.get(uid);
2822        if (uidStats == null) {
2823            uidStats = new ArrayMap<String, BroadcastStats>();
2824            mBroadcastStats.put(uid, uidStats);
2825        }
2826        BroadcastStats bs = uidStats.get(pkgName);
2827        if (bs == null) {
2828            bs = new BroadcastStats(uid, pkgName);
2829            uidStats.put(pkgName, bs);
2830        }
2831        return bs;
2832    }
2833
2834    class DeliveryTracker extends IAlarmCompleteListener.Stub implements PendingIntent.OnFinished {
2835        private InFlight removeLocked(PendingIntent pi, Intent intent) {
2836            for (int i = 0; i < mInFlight.size(); i++) {
2837                if (mInFlight.get(i).mPendingIntent == pi) {
2838                    return mInFlight.remove(i);
2839                }
2840            }
2841            mLog.w("No in-flight alarm for " + pi + " " + intent);
2842            return null;
2843        }
2844
2845        private InFlight removeLocked(IBinder listener) {
2846            for (int i = 0; i < mInFlight.size(); i++) {
2847                if (mInFlight.get(i).mListener == listener) {
2848                    return mInFlight.remove(i);
2849                }
2850            }
2851            mLog.w("No in-flight alarm for listener " + listener);
2852            return null;
2853        }
2854
2855        private void updateStatsLocked(InFlight inflight) {
2856            final long nowELAPSED = SystemClock.elapsedRealtime();
2857            BroadcastStats bs = inflight.mBroadcastStats;
2858            bs.nesting--;
2859            if (bs.nesting <= 0) {
2860                bs.nesting = 0;
2861                bs.aggregateTime += nowELAPSED - bs.startTime;
2862            }
2863            FilterStats fs = inflight.mFilterStats;
2864            fs.nesting--;
2865            if (fs.nesting <= 0) {
2866                fs.nesting = 0;
2867                fs.aggregateTime += nowELAPSED - fs.startTime;
2868            }
2869            if (RECORD_ALARMS_IN_HISTORY) {
2870                if (inflight.mWorkSource != null && inflight.mWorkSource.size() > 0) {
2871                    for (int wi=0; wi<inflight.mWorkSource.size(); wi++) {
2872                        ActivityManagerNative.noteAlarmFinish(
2873                                inflight.mPendingIntent, inflight.mWorkSource.get(wi), inflight.mTag);
2874                    }
2875                } else {
2876                    ActivityManagerNative.noteAlarmFinish(
2877                            inflight.mPendingIntent, inflight.mUid, inflight.mTag);
2878                }
2879            }
2880        }
2881
2882        private void updateTrackingLocked(InFlight inflight) {
2883            if (inflight != null) {
2884                updateStatsLocked(inflight);
2885            }
2886            mBroadcastRefCount--;
2887            if (mBroadcastRefCount == 0) {
2888                mHandler.obtainMessage(AlarmHandler.REPORT_ALARMS_ACTIVE, 0).sendToTarget();
2889                mWakeLock.release();
2890                if (mInFlight.size() > 0) {
2891                    mLog.w("Finished all dispatches with " + mInFlight.size()
2892                            + " remaining inflights");
2893                    for (int i=0; i<mInFlight.size(); i++) {
2894                        mLog.w("  Remaining #" + i + ": " + mInFlight.get(i));
2895                    }
2896                    mInFlight.clear();
2897                }
2898            } else {
2899                // the next of our alarms is now in flight.  reattribute the wakelock.
2900                if (mInFlight.size() > 0) {
2901                    InFlight inFlight = mInFlight.get(0);
2902                    setWakelockWorkSource(inFlight.mPendingIntent, inFlight.mWorkSource,
2903                            inFlight.mAlarmType, inFlight.mTag, -1, false);
2904                } else {
2905                    // should never happen
2906                    mLog.w("Alarm wakelock still held but sent queue empty");
2907                    mWakeLock.setWorkSource(null);
2908                }
2909            }
2910        }
2911
2912        /**
2913         * Callback that arrives when a direct-call alarm reports that delivery has finished
2914         */
2915        @Override
2916        public void alarmComplete(IBinder who) {
2917            if (who == null) {
2918                Slog.w(TAG, "Invalid alarmComplete: uid=" + Binder.getCallingUid()
2919                        + " pid=" + Binder.getCallingPid());
2920                return;
2921            }
2922
2923            final long ident = Binder.clearCallingIdentity();
2924            try {
2925                synchronized (mLock) {
2926                    mHandler.removeMessages(AlarmHandler.LISTENER_TIMEOUT, who);
2927                    InFlight inflight = removeLocked(who);
2928                    if (inflight != null) {
2929                        if (DEBUG_LISTENER_CALLBACK) {
2930                            Slog.i(TAG, "alarmComplete() from " + who);
2931                        }
2932                        updateTrackingLocked(inflight);
2933                    } else {
2934                        // Delivery timed out, and the timeout handling already took care of
2935                        // updating our tracking here, so we needn't do anything further.
2936                        if (DEBUG_LISTENER_CALLBACK) {
2937                            Slog.i(TAG, "Late alarmComplete() from " + who);
2938                        }
2939                    }
2940                }
2941            } finally {
2942                Binder.restoreCallingIdentity(ident);
2943            }
2944        }
2945
2946        /**
2947         * Callback that arrives when a PendingIntent alarm has finished delivery
2948         */
2949        @Override
2950        public void onSendFinished(PendingIntent pi, Intent intent, int resultCode,
2951                String resultData, Bundle resultExtras) {
2952            synchronized (mLock) {
2953                updateTrackingLocked(removeLocked(pi, intent));
2954            }
2955        }
2956
2957        /**
2958         * Timeout of a direct-call alarm delivery
2959         */
2960        public void alarmTimedOut(IBinder who) {
2961            synchronized (mLock) {
2962                InFlight inflight = removeLocked(who);
2963                if (inflight != null) {
2964                    // TODO: implement ANR policy for the target
2965                    if (DEBUG_LISTENER_CALLBACK) {
2966                        Slog.i(TAG, "Alarm listener " + who + " timed out in delivery");
2967                    }
2968                    updateTrackingLocked(inflight);
2969                } else {
2970                    if (DEBUG_LISTENER_CALLBACK) {
2971                        Slog.i(TAG, "Spurious timeout of listener " + who);
2972                    }
2973                }
2974            }
2975        }
2976
2977        /**
2978         * Deliver an alarm and set up the post-delivery handling appropriately
2979         */
2980        public void deliverLocked(Alarm alarm, long nowELAPSED, boolean allowWhileIdle) {
2981            if (alarm.operation != null) {
2982                // PendingIntent alarm
2983                try {
2984                    alarm.operation.send(getContext(), 0,
2985                            mBackgroundIntent.putExtra(
2986                                    Intent.EXTRA_ALARM_COUNT, alarm.count),
2987                                    mDeliveryTracker, mHandler, null,
2988                                    allowWhileIdle ? mIdleOptions : null);
2989                } catch (PendingIntent.CanceledException e) {
2990                    if (alarm.repeatInterval > 0) {
2991                        // This IntentSender is no longer valid, but this
2992                        // is a repeating alarm, so toss it
2993                        removeImpl(alarm.operation);
2994                    }
2995                    // No actual delivery was possible, so the delivery tracker's
2996                    // 'finished' callback won't be invoked.  We also don't need
2997                    // to do any wakelock or stats tracking, so we have nothing
2998                    // left to do here but go on to the next thing.
2999                    return;
3000                }
3001            } else {
3002                // Direct listener callback alarm
3003                try {
3004                    if (DEBUG_LISTENER_CALLBACK) {
3005                        Slog.v(TAG, "Alarm to uid=" + alarm.uid
3006                                + " listener=" + alarm.listener.asBinder());
3007                    }
3008                    alarm.listener.doAlarm(this);
3009                    mHandler.sendMessageDelayed(
3010                            mHandler.obtainMessage(AlarmHandler.LISTENER_TIMEOUT,
3011                                    alarm.listener.asBinder()),
3012                            mConstants.LISTENER_TIMEOUT);
3013                } catch (Exception e) {
3014                    if (DEBUG_LISTENER_CALLBACK) {
3015                        Slog.i(TAG, "Alarm undeliverable to listener "
3016                                + alarm.listener.asBinder(), e);
3017                    }
3018                    // As in the PendingIntent.CanceledException case, delivery of the
3019                    // alarm was not possible, so we have no wakelock or timeout or
3020                    // stats management to do.  It threw before we posted the delayed
3021                    // timeout message, so we're done here.
3022                    return;
3023                }
3024            }
3025
3026            // The alarm is now in flight; now arrange wakelock and stats tracking
3027            if (mBroadcastRefCount == 0) {
3028                setWakelockWorkSource(alarm.operation, alarm.workSource,
3029                        alarm.type, alarm.statsTag, (alarm.operation == null) ? alarm.uid : -1,
3030                        true);
3031                mWakeLock.acquire();
3032                mHandler.obtainMessage(AlarmHandler.REPORT_ALARMS_ACTIVE, 1).sendToTarget();
3033            }
3034            final InFlight inflight = new InFlight(AlarmManagerService.this,
3035                    alarm.operation, alarm.listener, alarm.workSource, alarm.uid,
3036                    alarm.packageName, alarm.type, alarm.statsTag, nowELAPSED);
3037            mInFlight.add(inflight);
3038            mBroadcastRefCount++;
3039
3040            if (allowWhileIdle) {
3041                // Record the last time this uid handled an ALLOW_WHILE_IDLE alarm.
3042                mLastAllowWhileIdleDispatch.put(alarm.uid, nowELAPSED);
3043                if (RECORD_DEVICE_IDLE_ALARMS) {
3044                    IdleDispatchEntry ent = new IdleDispatchEntry();
3045                    ent.uid = alarm.uid;
3046                    ent.pkg = alarm.packageName;
3047                    ent.tag = alarm.statsTag;
3048                    ent.op = "DELIVER";
3049                    ent.elapsedRealtime = nowELAPSED;
3050                    mAllowWhileIdleDispatches.add(ent);
3051                }
3052            }
3053
3054            final BroadcastStats bs = inflight.mBroadcastStats;
3055            bs.count++;
3056            if (bs.nesting == 0) {
3057                bs.nesting = 1;
3058                bs.startTime = nowELAPSED;
3059            } else {
3060                bs.nesting++;
3061            }
3062            final FilterStats fs = inflight.mFilterStats;
3063            fs.count++;
3064            if (fs.nesting == 0) {
3065                fs.nesting = 1;
3066                fs.startTime = nowELAPSED;
3067            } else {
3068                fs.nesting++;
3069            }
3070            if (alarm.type == ELAPSED_REALTIME_WAKEUP
3071                    || alarm.type == RTC_WAKEUP) {
3072                bs.numWakeup++;
3073                fs.numWakeup++;
3074                if (alarm.workSource != null && alarm.workSource.size() > 0) {
3075                    for (int wi=0; wi<alarm.workSource.size(); wi++) {
3076                        final String wsName = alarm.workSource.getName(wi);
3077                        ActivityManagerNative.noteWakeupAlarm(
3078                                alarm.operation, alarm.workSource.get(wi),
3079                                (wsName != null) ? wsName : alarm.packageName,
3080                                alarm.statsTag);
3081                    }
3082                } else {
3083                    ActivityManagerNative.noteWakeupAlarm(
3084                            alarm.operation, alarm.uid, alarm.packageName, alarm.statsTag);
3085                }
3086            }
3087        }
3088    }
3089}
3090