OSDN Git Service

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