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