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