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