Home | History | Annotate | Download | only in server
      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.IAlarmManager;
     24 import android.app.PendingIntent;
     25 import android.content.BroadcastReceiver;
     26 import android.content.Context;
     27 import android.content.Intent;
     28 import android.content.IntentFilter;
     29 import android.content.pm.PackageManager;
     30 import android.net.Uri;
     31 import android.os.Binder;
     32 import android.os.Bundle;
     33 import android.os.Handler;
     34 import android.os.IBinder;
     35 import android.os.Message;
     36 import android.os.PowerManager;
     37 import android.os.SystemClock;
     38 import android.os.SystemProperties;
     39 import android.os.UserHandle;
     40 import android.os.WorkSource;
     41 import android.provider.Settings;
     42 import android.text.TextUtils;
     43 import android.text.format.DateFormat;
     44 import android.util.ArrayMap;
     45 import android.util.Log;
     46 import android.util.Slog;
     47 import android.util.SparseArray;
     48 import android.util.SparseBooleanArray;
     49 import android.util.TimeUtils;
     50 
     51 import java.io.ByteArrayOutputStream;
     52 import java.io.FileDescriptor;
     53 import java.io.PrintWriter;
     54 import java.text.SimpleDateFormat;
     55 import java.util.ArrayList;
     56 import java.util.Arrays;
     57 import java.util.Calendar;
     58 import java.util.Collections;
     59 import java.util.Comparator;
     60 import java.util.Date;
     61 import java.util.HashMap;
     62 import java.util.LinkedList;
     63 import java.util.Locale;
     64 import java.util.TimeZone;
     65 
     66 import static android.app.AlarmManager.RTC_WAKEUP;
     67 import static android.app.AlarmManager.RTC;
     68 import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP;
     69 import static android.app.AlarmManager.ELAPSED_REALTIME;
     70 
     71 import com.android.internal.util.LocalLog;
     72 
     73 class AlarmManagerService extends SystemService {
     74     // The threshold for how long an alarm can be late before we print a
     75     // warning message.  The time duration is in milliseconds.
     76     private static final long LATE_ALARM_THRESHOLD = 10 * 1000;
     77 
     78     // Minimum futurity of a new alarm
     79     private static final long MIN_FUTURITY = 5 * 1000;  // 5 seconds, in millis
     80 
     81     // Minimum alarm recurrence interval
     82     private static final long MIN_INTERVAL = 60 * 1000;  // one minute, in millis
     83 
     84     private static final int RTC_WAKEUP_MASK = 1 << RTC_WAKEUP;
     85     private static final int RTC_MASK = 1 << RTC;
     86     private static final int ELAPSED_REALTIME_WAKEUP_MASK = 1 << ELAPSED_REALTIME_WAKEUP;
     87     private static final int ELAPSED_REALTIME_MASK = 1 << ELAPSED_REALTIME;
     88     static final int TIME_CHANGED_MASK = 1 << 16;
     89     static final int IS_WAKEUP_MASK = RTC_WAKEUP_MASK|ELAPSED_REALTIME_WAKEUP_MASK;
     90 
     91     // Mask for testing whether a given alarm type is wakeup vs non-wakeup
     92     static final int TYPE_NONWAKEUP_MASK = 0x1; // low bit => non-wakeup
     93 
     94     static final String TAG = "AlarmManager";
     95     static final String ClockReceiver_TAG = "ClockReceiver";
     96     static final boolean localLOGV = false;
     97     static final boolean DEBUG_BATCH = localLOGV || false;
     98     static final boolean DEBUG_VALIDATE = localLOGV || false;
     99     static final boolean DEBUG_ALARM_CLOCK = localLOGV || false;
    100     static final int ALARM_EVENT = 1;
    101     static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
    102 
    103     static final Intent mBackgroundIntent
    104             = new Intent().addFlags(Intent.FLAG_FROM_BACKGROUND);
    105     static final IncreasingTimeOrder sIncreasingTimeOrder = new IncreasingTimeOrder();
    106 
    107     static final boolean WAKEUP_STATS = false;
    108 
    109     private static final Intent NEXT_ALARM_CLOCK_CHANGED_INTENT = new Intent(
    110             AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED);
    111 
    112     final LocalLog mLog = new LocalLog(TAG);
    113 
    114     final Object mLock = new Object();
    115 
    116     long mNativeData;
    117     private long mNextWakeup;
    118     private long mNextNonWakeup;
    119     int mBroadcastRefCount = 0;
    120     PowerManager.WakeLock mWakeLock;
    121     boolean mLastWakeLockUnimportantForLogging;
    122     ArrayList<Alarm> mPendingNonWakeupAlarms = new ArrayList<Alarm>();
    123     ArrayList<InFlight> mInFlight = new ArrayList<InFlight>();
    124     final AlarmHandler mHandler = new AlarmHandler();
    125     ClockReceiver mClockReceiver;
    126     InteractiveStateReceiver mInteractiveStateReceiver;
    127     private UninstallReceiver mUninstallReceiver;
    128     final ResultReceiver mResultReceiver = new ResultReceiver();
    129     PendingIntent mTimeTickSender;
    130     PendingIntent mDateChangeSender;
    131     boolean mInteractive = true;
    132     long mNonInteractiveStartTime;
    133     long mNonInteractiveTime;
    134     long mLastAlarmDeliveryTime;
    135     long mStartCurrentDelayTime;
    136     long mNextNonWakeupDeliveryTime;
    137     int mNumTimeChanged;
    138 
    139     private final SparseArray<AlarmManager.AlarmClockInfo> mNextAlarmClockForUser =
    140             new SparseArray<>();
    141     private final SparseArray<AlarmManager.AlarmClockInfo> mTmpSparseAlarmClockArray =
    142             new SparseArray<>();
    143     private final SparseBooleanArray mPendingSendNextAlarmClockChangedForUser =
    144             new SparseBooleanArray();
    145     private boolean mNextAlarmClockMayChange;
    146 
    147     // May only use on mHandler's thread, locking not required.
    148     private final SparseArray<AlarmManager.AlarmClockInfo> mHandlerSparseAlarmClockArray =
    149             new SparseArray<>();
    150 
    151     // Alarm delivery ordering bookkeeping
    152     static final int PRIO_TICK = 0;
    153     static final int PRIO_WAKEUP = 1;
    154     static final int PRIO_NORMAL = 2;
    155 
    156     class PriorityClass {
    157         int seq;
    158         int priority;
    159 
    160         PriorityClass() {
    161             seq = mCurrentSeq - 1;
    162             priority = PRIO_NORMAL;
    163         }
    164     }
    165 
    166     final HashMap<String, PriorityClass> mPriorities =
    167             new HashMap<String, PriorityClass>();
    168     int mCurrentSeq = 0;
    169 
    170     class WakeupEvent {
    171         public long when;
    172         public int uid;
    173         public String action;
    174 
    175         public WakeupEvent(long theTime, int theUid, String theAction) {
    176             when = theTime;
    177             uid = theUid;
    178             action = theAction;
    179         }
    180     }
    181 
    182     final LinkedList<WakeupEvent> mRecentWakeups = new LinkedList<WakeupEvent>();
    183     final long RECENT_WAKEUP_PERIOD = 1000L * 60 * 60 * 24; // one day
    184 
    185     final class Batch {
    186         long start;     // These endpoints are always in ELAPSED
    187         long end;
    188         boolean standalone; // certain "batches" don't participate in coalescing
    189 
    190         final ArrayList<Alarm> alarms = new ArrayList<Alarm>();
    191 
    192         Batch() {
    193             start = 0;
    194             end = Long.MAX_VALUE;
    195         }
    196 
    197         Batch(Alarm seed) {
    198             start = seed.whenElapsed;
    199             end = seed.maxWhen;
    200             alarms.add(seed);
    201         }
    202 
    203         int size() {
    204             return alarms.size();
    205         }
    206 
    207         Alarm get(int index) {
    208             return alarms.get(index);
    209         }
    210 
    211         boolean canHold(long whenElapsed, long maxWhen) {
    212             return (end >= whenElapsed) && (start <= maxWhen);
    213         }
    214 
    215         boolean add(Alarm alarm) {
    216             boolean newStart = false;
    217             // narrows the batch if necessary; presumes that canHold(alarm) is true
    218             int index = Collections.binarySearch(alarms, alarm, sIncreasingTimeOrder);
    219             if (index < 0) {
    220                 index = 0 - index - 1;
    221             }
    222             alarms.add(index, alarm);
    223             if (DEBUG_BATCH) {
    224                 Slog.v(TAG, "Adding " + alarm + " to " + this);
    225             }
    226             if (alarm.whenElapsed > start) {
    227                 start = alarm.whenElapsed;
    228                 newStart = true;
    229             }
    230             if (alarm.maxWhen < end) {
    231                 end = alarm.maxWhen;
    232             }
    233 
    234             if (DEBUG_BATCH) {
    235                 Slog.v(TAG, "    => now " + this);
    236             }
    237             return newStart;
    238         }
    239 
    240         boolean remove(final PendingIntent operation) {
    241             boolean didRemove = false;
    242             long newStart = 0;  // recalculate endpoints as we go
    243             long newEnd = Long.MAX_VALUE;
    244             for (int i = 0; i < alarms.size(); ) {
    245                 Alarm alarm = alarms.get(i);
    246                 if (alarm.operation.equals(operation)) {
    247                     alarms.remove(i);
    248                     didRemove = true;
    249                     if (alarm.alarmClock != null) {
    250                         mNextAlarmClockMayChange = true;
    251                     }
    252                 } else {
    253                     if (alarm.whenElapsed > newStart) {
    254                         newStart = alarm.whenElapsed;
    255                     }
    256                     if (alarm.maxWhen < newEnd) {
    257                         newEnd = alarm.maxWhen;
    258                     }
    259                     i++;
    260                 }
    261             }
    262             if (didRemove) {
    263                 // commit the new batch bounds
    264                 start = newStart;
    265                 end = newEnd;
    266             }
    267             return didRemove;
    268         }
    269 
    270         boolean remove(final String packageName) {
    271             boolean didRemove = false;
    272             long newStart = 0;  // recalculate endpoints as we go
    273             long newEnd = Long.MAX_VALUE;
    274             for (int i = 0; i < alarms.size(); ) {
    275                 Alarm alarm = alarms.get(i);
    276                 if (alarm.operation.getTargetPackage().equals(packageName)) {
    277                     alarms.remove(i);
    278                     didRemove = true;
    279                     if (alarm.alarmClock != null) {
    280                         mNextAlarmClockMayChange = true;
    281                     }
    282                 } else {
    283                     if (alarm.whenElapsed > newStart) {
    284                         newStart = alarm.whenElapsed;
    285                     }
    286                     if (alarm.maxWhen < newEnd) {
    287                         newEnd = alarm.maxWhen;
    288                     }
    289                     i++;
    290                 }
    291             }
    292             if (didRemove) {
    293                 // commit the new batch bounds
    294                 start = newStart;
    295                 end = newEnd;
    296             }
    297             return didRemove;
    298         }
    299 
    300         boolean remove(final int userHandle) {
    301             boolean didRemove = false;
    302             long newStart = 0;  // recalculate endpoints as we go
    303             long newEnd = Long.MAX_VALUE;
    304             for (int i = 0; i < alarms.size(); ) {
    305                 Alarm alarm = alarms.get(i);
    306                 if (UserHandle.getUserId(alarm.operation.getCreatorUid()) == userHandle) {
    307                     alarms.remove(i);
    308                     didRemove = true;
    309                     if (alarm.alarmClock != null) {
    310                         mNextAlarmClockMayChange = true;
    311                     }
    312                 } else {
    313                     if (alarm.whenElapsed > newStart) {
    314                         newStart = alarm.whenElapsed;
    315                     }
    316                     if (alarm.maxWhen < newEnd) {
    317                         newEnd = alarm.maxWhen;
    318                     }
    319                     i++;
    320                 }
    321             }
    322             if (didRemove) {
    323                 // commit the new batch bounds
    324                 start = newStart;
    325                 end = newEnd;
    326             }
    327             return didRemove;
    328         }
    329 
    330         boolean hasPackage(final String packageName) {
    331             final int N = alarms.size();
    332             for (int i = 0; i < N; i++) {
    333                 Alarm a = alarms.get(i);
    334                 if (a.operation.getTargetPackage().equals(packageName)) {
    335                     return true;
    336                 }
    337             }
    338             return false;
    339         }
    340 
    341         boolean hasWakeups() {
    342             final int N = alarms.size();
    343             for (int i = 0; i < N; i++) {
    344                 Alarm a = alarms.get(i);
    345                 // non-wakeup alarms are types 1 and 3, i.e. have the low bit set
    346                 if ((a.type & TYPE_NONWAKEUP_MASK) == 0) {
    347                     return true;
    348                 }
    349             }
    350             return false;
    351         }
    352 
    353         @Override
    354         public String toString() {
    355             StringBuilder b = new StringBuilder(40);
    356             b.append("Batch{"); b.append(Integer.toHexString(this.hashCode()));
    357             b.append(" num="); b.append(size());
    358             b.append(" start="); b.append(start);
    359             b.append(" end="); b.append(end);
    360             if (standalone) {
    361                 b.append(" STANDALONE");
    362             }
    363             b.append('}');
    364             return b.toString();
    365         }
    366     }
    367 
    368     static class BatchTimeOrder implements Comparator<Batch> {
    369         public int compare(Batch b1, Batch b2) {
    370             long when1 = b1.start;
    371             long when2 = b2.start;
    372             if (when1 - when2 > 0) {
    373                 return 1;
    374             }
    375             if (when1 - when2 < 0) {
    376                 return -1;
    377             }
    378             return 0;
    379         }
    380     }
    381 
    382     final Comparator<Alarm> mAlarmDispatchComparator = new Comparator<Alarm>() {
    383         @Override
    384         public int compare(Alarm lhs, Alarm rhs) {
    385             // priority class trumps everything.  TICK < WAKEUP < NORMAL
    386             if (lhs.priorityClass.priority < rhs.priorityClass.priority) {
    387                 return -1;
    388             } else if (lhs.priorityClass.priority > rhs.priorityClass.priority) {
    389                 return 1;
    390             }
    391 
    392             // within each class, sort by nominal delivery time
    393             if (lhs.whenElapsed < rhs.whenElapsed) {
    394                 return -1;
    395             } else if (lhs.whenElapsed > rhs.whenElapsed) {
    396                 return 1;
    397             }
    398 
    399             // same priority class + same target delivery time
    400             return 0;
    401         }
    402     };
    403 
    404     void calculateDeliveryPriorities(ArrayList<Alarm> alarms) {
    405         final int N = alarms.size();
    406         for (int i = 0; i < N; i++) {
    407             Alarm a = alarms.get(i);
    408 
    409             final int alarmPrio;
    410             if (Intent.ACTION_TIME_TICK.equals(a.operation.getIntent().getAction())) {
    411                 alarmPrio = PRIO_TICK;
    412             } else if (a.wakeup) {
    413                 alarmPrio = PRIO_WAKEUP;
    414             } else {
    415                 alarmPrio = PRIO_NORMAL;
    416             }
    417 
    418             PriorityClass packagePrio = a.priorityClass;
    419             if (packagePrio == null) packagePrio = mPriorities.get(a.operation.getCreatorPackage());
    420             if (packagePrio == null) {
    421                 packagePrio = a.priorityClass = new PriorityClass(); // lowest prio & stale sequence
    422                 mPriorities.put(a.operation.getCreatorPackage(), packagePrio);
    423             }
    424             a.priorityClass = packagePrio;
    425 
    426             if (packagePrio.seq != mCurrentSeq) {
    427                 // first alarm we've seen in the current delivery generation from this package
    428                 packagePrio.priority = alarmPrio;
    429                 packagePrio.seq = mCurrentSeq;
    430             } else {
    431                 // Multiple alarms from this package being delivered in this generation;
    432                 // bump the package's delivery class if it's warranted.
    433                 // TICK < WAKEUP < NORMAL
    434                 if (alarmPrio < packagePrio.priority) {
    435                     packagePrio.priority = alarmPrio;
    436                 }
    437             }
    438         }
    439     }
    440 
    441     // minimum recurrence period or alarm futurity for us to be able to fuzz it
    442     static final long MIN_FUZZABLE_INTERVAL = 10000;
    443     static final BatchTimeOrder sBatchOrder = new BatchTimeOrder();
    444     final ArrayList<Batch> mAlarmBatches = new ArrayList<Batch>();
    445 
    446     public AlarmManagerService(Context context) {
    447         super(context);
    448     }
    449 
    450     static long convertToElapsed(long when, int type) {
    451         final boolean isRtc = (type == RTC || type == RTC_WAKEUP);
    452         if (isRtc) {
    453             when -= System.currentTimeMillis() - SystemClock.elapsedRealtime();
    454         }
    455         return when;
    456     }
    457 
    458     // Apply a heuristic to { recurrence interval, futurity of the trigger time } to
    459     // calculate the end of our nominal delivery window for the alarm.
    460     static long maxTriggerTime(long now, long triggerAtTime, long interval) {
    461         // Current heuristic: batchable window is 75% of either the recurrence interval
    462         // [for a periodic alarm] or of the time from now to the desired delivery time,
    463         // with a minimum delay/interval of 10 seconds, under which we will simply not
    464         // defer the alarm.
    465         long futurity = (interval == 0)
    466                 ? (triggerAtTime - now)
    467                 : interval;
    468         if (futurity < MIN_FUZZABLE_INTERVAL) {
    469             futurity = 0;
    470         }
    471         return triggerAtTime + (long)(.75 * futurity);
    472     }
    473 
    474     // returns true if the batch was added at the head
    475     static boolean addBatchLocked(ArrayList<Batch> list, Batch newBatch) {
    476         int index = Collections.binarySearch(list, newBatch, sBatchOrder);
    477         if (index < 0) {
    478             index = 0 - index - 1;
    479         }
    480         list.add(index, newBatch);
    481         return (index == 0);
    482     }
    483 
    484     // Return the index of the matching batch, or -1 if none found.
    485     int attemptCoalesceLocked(long whenElapsed, long maxWhen) {
    486         final int N = mAlarmBatches.size();
    487         for (int i = 0; i < N; i++) {
    488             Batch b = mAlarmBatches.get(i);
    489             if (!b.standalone && b.canHold(whenElapsed, maxWhen)) {
    490                 return i;
    491             }
    492         }
    493         return -1;
    494     }
    495 
    496     // The RTC clock has moved arbitrarily, so we need to recalculate all the batching
    497     void rebatchAllAlarms() {
    498         synchronized (mLock) {
    499             rebatchAllAlarmsLocked(true);
    500         }
    501     }
    502 
    503     void rebatchAllAlarmsLocked(boolean doValidate) {
    504         ArrayList<Batch> oldSet = (ArrayList<Batch>) mAlarmBatches.clone();
    505         mAlarmBatches.clear();
    506         final long nowElapsed = SystemClock.elapsedRealtime();
    507         final int oldBatches = oldSet.size();
    508         for (int batchNum = 0; batchNum < oldBatches; batchNum++) {
    509             Batch batch = oldSet.get(batchNum);
    510             final int N = batch.size();
    511             for (int i = 0; i < N; i++) {
    512                 Alarm a = batch.get(i);
    513                 long whenElapsed = convertToElapsed(a.when, a.type);
    514                 final long maxElapsed;
    515                 if (a.whenElapsed == a.maxWhen) {
    516                     // Exact
    517                     maxElapsed = whenElapsed;
    518                 } else {
    519                     // Not exact.  Preserve any explicit window, otherwise recalculate
    520                     // the window based on the alarm's new futurity.  Note that this
    521                     // reflects a policy of preferring timely to deferred delivery.
    522                     maxElapsed = (a.windowLength > 0)
    523                             ? (whenElapsed + a.windowLength)
    524                             : maxTriggerTime(nowElapsed, whenElapsed, a.repeatInterval);
    525                 }
    526                 setImplLocked(a.type, a.when, whenElapsed, a.windowLength, maxElapsed,
    527                         a.repeatInterval, a.operation, batch.standalone, doValidate, a.workSource,
    528                         a.alarmClock, a.userId);
    529             }
    530         }
    531     }
    532 
    533     static final class InFlight extends Intent {
    534         final PendingIntent mPendingIntent;
    535         final WorkSource mWorkSource;
    536         final String mTag;
    537         final BroadcastStats mBroadcastStats;
    538         final FilterStats mFilterStats;
    539         final int mAlarmType;
    540 
    541         InFlight(AlarmManagerService service, PendingIntent pendingIntent, WorkSource workSource,
    542                 int alarmType, String tag) {
    543             mPendingIntent = pendingIntent;
    544             mWorkSource = workSource;
    545             mTag = tag;
    546             mBroadcastStats = service.getStatsLocked(pendingIntent);
    547             FilterStats fs = mBroadcastStats.filterStats.get(mTag);
    548             if (fs == null) {
    549                 fs = new FilterStats(mBroadcastStats, mTag);
    550                 mBroadcastStats.filterStats.put(mTag, fs);
    551             }
    552             mFilterStats = fs;
    553             mAlarmType = alarmType;
    554         }
    555     }
    556 
    557     static final class FilterStats {
    558         final BroadcastStats mBroadcastStats;
    559         final String mTag;
    560 
    561         long aggregateTime;
    562         int count;
    563         int numWakeup;
    564         long startTime;
    565         int nesting;
    566 
    567         FilterStats(BroadcastStats broadcastStats, String tag) {
    568             mBroadcastStats = broadcastStats;
    569             mTag = tag;
    570         }
    571     }
    572 
    573     static final class BroadcastStats {
    574         final int mUid;
    575         final String mPackageName;
    576 
    577         long aggregateTime;
    578         int count;
    579         int numWakeup;
    580         long startTime;
    581         int nesting;
    582         final ArrayMap<String, FilterStats> filterStats = new ArrayMap<String, FilterStats>();
    583 
    584         BroadcastStats(int uid, String packageName) {
    585             mUid = uid;
    586             mPackageName = packageName;
    587         }
    588     }
    589 
    590     final SparseArray<ArrayMap<String, BroadcastStats>> mBroadcastStats
    591             = new SparseArray<ArrayMap<String, BroadcastStats>>();
    592 
    593     int mNumDelayedAlarms = 0;
    594     long mTotalDelayTime = 0;
    595     long mMaxDelayTime = 0;
    596 
    597     @Override
    598     public void onStart() {
    599         mNativeData = init();
    600         mNextWakeup = mNextNonWakeup = 0;
    601 
    602         // We have to set current TimeZone info to kernel
    603         // because kernel doesn't keep this after reboot
    604         setTimeZoneImpl(SystemProperties.get(TIMEZONE_PROPERTY));
    605 
    606         PowerManager pm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE);
    607         mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*alarm*");
    608 
    609         mTimeTickSender = PendingIntent.getBroadcastAsUser(getContext(), 0,
    610                 new Intent(Intent.ACTION_TIME_TICK).addFlags(
    611                         Intent.FLAG_RECEIVER_REGISTERED_ONLY
    612                         | Intent.FLAG_RECEIVER_FOREGROUND), 0,
    613                         UserHandle.ALL);
    614         Intent intent = new Intent(Intent.ACTION_DATE_CHANGED);
    615         intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
    616         mDateChangeSender = PendingIntent.getBroadcastAsUser(getContext(), 0, intent,
    617                 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT, UserHandle.ALL);
    618 
    619         // now that we have initied the driver schedule the alarm
    620         mClockReceiver = new ClockReceiver();
    621         mClockReceiver.scheduleTimeTickEvent();
    622         mClockReceiver.scheduleDateChangedEvent();
    623         mInteractiveStateReceiver = new InteractiveStateReceiver();
    624         mUninstallReceiver = new UninstallReceiver();
    625 
    626         if (mNativeData != 0) {
    627             AlarmThread waitThread = new AlarmThread();
    628             waitThread.start();
    629         } else {
    630             Slog.w(TAG, "Failed to open alarm driver. Falling back to a handler.");
    631         }
    632 
    633         publishBinderService(Context.ALARM_SERVICE, mService);
    634     }
    635 
    636     @Override
    637     protected void finalize() throws Throwable {
    638         try {
    639             close(mNativeData);
    640         } finally {
    641             super.finalize();
    642         }
    643     }
    644 
    645     void setTimeZoneImpl(String tz) {
    646         if (TextUtils.isEmpty(tz)) {
    647             return;
    648         }
    649 
    650         TimeZone zone = TimeZone.getTimeZone(tz);
    651         // Prevent reentrant calls from stepping on each other when writing
    652         // the time zone property
    653         boolean timeZoneWasChanged = false;
    654         synchronized (this) {
    655             String current = SystemProperties.get(TIMEZONE_PROPERTY);
    656             if (current == null || !current.equals(zone.getID())) {
    657                 if (localLOGV) {
    658                     Slog.v(TAG, "timezone changed: " + current + ", new=" + zone.getID());
    659                 }
    660                 timeZoneWasChanged = true;
    661                 SystemProperties.set(TIMEZONE_PROPERTY, zone.getID());
    662             }
    663 
    664             // Update the kernel timezone information
    665             // Kernel tracks time offsets as 'minutes west of GMT'
    666             int gmtOffset = zone.getOffset(System.currentTimeMillis());
    667             setKernelTimezone(mNativeData, -(gmtOffset / 60000));
    668         }
    669 
    670         TimeZone.setDefault(null);
    671 
    672         if (timeZoneWasChanged) {
    673             Intent intent = new Intent(Intent.ACTION_TIMEZONE_CHANGED);
    674             intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
    675             intent.putExtra("time-zone", zone.getID());
    676             getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
    677         }
    678     }
    679 
    680     void removeImpl(PendingIntent operation) {
    681         if (operation == null) {
    682             return;
    683         }
    684         synchronized (mLock) {
    685             removeLocked(operation);
    686         }
    687     }
    688 
    689     void setImpl(int type, long triggerAtTime, long windowLength, long interval,
    690             PendingIntent operation, boolean isStandalone, WorkSource workSource,
    691             AlarmManager.AlarmClockInfo alarmClock) {
    692         if (operation == null) {
    693             Slog.w(TAG, "set/setRepeating ignored because there is no intent");
    694             return;
    695         }
    696 
    697         // Sanity check the window length.  This will catch people mistakenly
    698         // trying to pass an end-of-window timestamp rather than a duration.
    699         if (windowLength > AlarmManager.INTERVAL_HALF_DAY) {
    700             Slog.w(TAG, "Window length " + windowLength
    701                     + "ms suspiciously long; limiting to 1 hour");
    702             windowLength = AlarmManager.INTERVAL_HOUR;
    703         }
    704 
    705         // Sanity check the recurrence interval.  This will catch people who supply
    706         // seconds when the API expects milliseconds.
    707         if (interval > 0 && interval < MIN_INTERVAL) {
    708             Slog.w(TAG, "Suspiciously short interval " + interval
    709                     + " millis; expanding to " + (int)(MIN_INTERVAL/1000)
    710                     + " seconds");
    711             interval = MIN_INTERVAL;
    712         }
    713 
    714         if (type < RTC_WAKEUP || type > ELAPSED_REALTIME) {
    715             throw new IllegalArgumentException("Invalid alarm type " + type);
    716         }
    717 
    718         if (triggerAtTime < 0) {
    719             final long who = Binder.getCallingUid();
    720             final long what = Binder.getCallingPid();
    721             Slog.w(TAG, "Invalid alarm trigger time! " + triggerAtTime + " from uid=" + who
    722                     + " pid=" + what);
    723             triggerAtTime = 0;
    724         }
    725 
    726         final long nowElapsed = SystemClock.elapsedRealtime();
    727         final long nominalTrigger = convertToElapsed(triggerAtTime, type);
    728         // Try to prevent spamming by making sure we aren't firing alarms in the immediate future
    729         final long minTrigger = nowElapsed + MIN_FUTURITY;
    730         final long triggerElapsed = (nominalTrigger > minTrigger) ? nominalTrigger : minTrigger;
    731 
    732         final long maxElapsed;
    733         if (windowLength == AlarmManager.WINDOW_EXACT) {
    734             maxElapsed = triggerElapsed;
    735         } else if (windowLength < 0) {
    736             maxElapsed = maxTriggerTime(nowElapsed, triggerElapsed, interval);
    737         } else {
    738             maxElapsed = triggerElapsed + windowLength;
    739         }
    740 
    741         final int userId = UserHandle.getCallingUserId();
    742 
    743         synchronized (mLock) {
    744             if (DEBUG_BATCH) {
    745                 Slog.v(TAG, "set(" + operation + ") : type=" + type
    746                         + " triggerAtTime=" + triggerAtTime + " win=" + windowLength
    747                         + " tElapsed=" + triggerElapsed + " maxElapsed=" + maxElapsed
    748                         + " interval=" + interval + " standalone=" + isStandalone);
    749             }
    750             setImplLocked(type, triggerAtTime, triggerElapsed, windowLength, maxElapsed,
    751                     interval, operation, isStandalone, true, workSource, alarmClock, userId);
    752         }
    753     }
    754 
    755     private void setImplLocked(int type, long when, long whenElapsed, long windowLength,
    756             long maxWhen, long interval, PendingIntent operation, boolean isStandalone,
    757             boolean doValidate, WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock,
    758             int userId) {
    759         Alarm a = new Alarm(type, when, whenElapsed, windowLength, maxWhen, interval,
    760                 operation, workSource, alarmClock, userId);
    761         removeLocked(operation);
    762 
    763         int whichBatch = (isStandalone) ? -1 : attemptCoalesceLocked(whenElapsed, maxWhen);
    764         if (whichBatch < 0) {
    765             Batch batch = new Batch(a);
    766             batch.standalone = isStandalone;
    767             addBatchLocked(mAlarmBatches, batch);
    768         } else {
    769             Batch batch = mAlarmBatches.get(whichBatch);
    770             if (batch.add(a)) {
    771                 // The start time of this batch advanced, so batch ordering may
    772                 // have just been broken.  Move it to where it now belongs.
    773                 mAlarmBatches.remove(whichBatch);
    774                 addBatchLocked(mAlarmBatches, batch);
    775             }
    776         }
    777 
    778         if (alarmClock != null) {
    779             mNextAlarmClockMayChange = true;
    780             updateNextAlarmClockLocked();
    781         }
    782 
    783         if (DEBUG_VALIDATE) {
    784             if (doValidate && !validateConsistencyLocked()) {
    785                 Slog.v(TAG, "Tipping-point operation: type=" + type + " when=" + when
    786                         + " when(hex)=" + Long.toHexString(when)
    787                         + " whenElapsed=" + whenElapsed + " maxWhen=" + maxWhen
    788                         + " interval=" + interval + " op=" + operation
    789                         + " standalone=" + isStandalone);
    790                 rebatchAllAlarmsLocked(false);
    791             }
    792         }
    793 
    794         rescheduleKernelAlarmsLocked();
    795     }
    796 
    797     private final IBinder mService = new IAlarmManager.Stub() {
    798         @Override
    799         public void set(int type, long triggerAtTime, long windowLength, long interval,
    800                 PendingIntent operation, WorkSource workSource,
    801                 AlarmManager.AlarmClockInfo alarmClock) {
    802             if (workSource != null) {
    803                 getContext().enforceCallingPermission(
    804                         android.Manifest.permission.UPDATE_DEVICE_STATS,
    805                         "AlarmManager.set");
    806             }
    807 
    808             setImpl(type, triggerAtTime, windowLength, interval, operation,
    809                     windowLength == AlarmManager.WINDOW_EXACT, workSource, alarmClock);
    810         }
    811 
    812         @Override
    813         public boolean setTime(long millis) {
    814             getContext().enforceCallingOrSelfPermission(
    815                     "android.permission.SET_TIME",
    816                     "setTime");
    817 
    818             if (mNativeData == 0) {
    819                 Slog.w(TAG, "Not setting time since no alarm driver is available.");
    820                 return false;
    821             }
    822 
    823             synchronized (mLock) {
    824                 return setKernelTime(mNativeData, millis) == 0;
    825             }
    826         }
    827 
    828         @Override
    829         public void setTimeZone(String tz) {
    830             getContext().enforceCallingOrSelfPermission(
    831                     "android.permission.SET_TIME_ZONE",
    832                     "setTimeZone");
    833 
    834             final long oldId = Binder.clearCallingIdentity();
    835             try {
    836                 setTimeZoneImpl(tz);
    837             } finally {
    838                 Binder.restoreCallingIdentity(oldId);
    839             }
    840         }
    841 
    842         @Override
    843         public void remove(PendingIntent operation) {
    844             removeImpl(operation);
    845 
    846         }
    847 
    848         @Override
    849         public AlarmManager.AlarmClockInfo getNextAlarmClock(int userId) {
    850             userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
    851                     Binder.getCallingUid(), userId, false /* allowAll */, false /* requireFull */,
    852                     "getNextAlarmClock", null);
    853 
    854             return getNextAlarmClockImpl(userId);
    855         }
    856 
    857         @Override
    858         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
    859             if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
    860                     != PackageManager.PERMISSION_GRANTED) {
    861                 pw.println("Permission Denial: can't dump AlarmManager from from pid="
    862                         + Binder.getCallingPid()
    863                         + ", uid=" + Binder.getCallingUid());
    864                 return;
    865             }
    866 
    867             dumpImpl(pw);
    868         }
    869     };
    870 
    871     void dumpImpl(PrintWriter pw) {
    872         synchronized (mLock) {
    873             pw.println("Current Alarm Manager state:");
    874             final long nowRTC = System.currentTimeMillis();
    875             final long nowELAPSED = SystemClock.elapsedRealtime();
    876             SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    877 
    878             pw.print("nowRTC="); pw.print(nowRTC);
    879             pw.print("="); pw.print(sdf.format(new Date(nowRTC)));
    880             pw.print(" nowELAPSED="); TimeUtils.formatDuration(nowELAPSED, pw);
    881             pw.println();
    882             if (!mInteractive) {
    883                 pw.print("Time since non-interactive: ");
    884                 TimeUtils.formatDuration(nowELAPSED - mNonInteractiveStartTime, pw);
    885                 pw.println();
    886                 pw.print("Max wakeup delay: ");
    887                 TimeUtils.formatDuration(currentNonWakeupFuzzLocked(nowELAPSED), pw);
    888                 pw.println();
    889                 pw.print("Time since last dispatch: ");
    890                 TimeUtils.formatDuration(nowELAPSED - mLastAlarmDeliveryTime, pw);
    891                 pw.println();
    892                 pw.print("Next non-wakeup delivery time: ");
    893                 TimeUtils.formatDuration(nowELAPSED - mNextNonWakeupDeliveryTime, pw);
    894                 pw.println();
    895             }
    896 
    897             long nextWakeupRTC = mNextWakeup + (nowRTC - nowELAPSED);
    898             long nextNonWakeupRTC = mNextNonWakeup + (nowRTC - nowELAPSED);
    899             pw.print("Next non-wakeup alarm: ");
    900                     TimeUtils.formatDuration(mNextNonWakeup, nowELAPSED, pw);
    901                     pw.print(" = "); pw.println(sdf.format(new Date(nextNonWakeupRTC)));
    902             pw.print("Next wakeup: "); TimeUtils.formatDuration(mNextWakeup, nowELAPSED, pw);
    903                     pw.print(" = "); pw.println(sdf.format(new Date(nextWakeupRTC)));
    904             pw.print("Num time change events: "); pw.println(mNumTimeChanged);
    905 
    906             if (mAlarmBatches.size() > 0) {
    907                 pw.println();
    908                 pw.print("Pending alarm batches: ");
    909                 pw.println(mAlarmBatches.size());
    910                 for (Batch b : mAlarmBatches) {
    911                     pw.print(b); pw.println(':');
    912                     dumpAlarmList(pw, b.alarms, "  ", nowELAPSED, nowRTC, sdf);
    913                 }
    914             }
    915 
    916             pw.println();
    917             pw.print("Past-due non-wakeup alarms: ");
    918             if (mPendingNonWakeupAlarms.size() > 0) {
    919                 pw.println(mPendingNonWakeupAlarms.size());
    920                 dumpAlarmList(pw, mPendingNonWakeupAlarms, "  ", nowELAPSED, nowRTC, sdf);
    921             } else {
    922                 pw.println("(none)");
    923             }
    924             pw.print("  Number of delayed alarms: "); pw.print(mNumDelayedAlarms);
    925             pw.print(", total delay time: "); TimeUtils.formatDuration(mTotalDelayTime, pw);
    926             pw.println();
    927             pw.print("  Max delay time: "); TimeUtils.formatDuration(mMaxDelayTime, pw);
    928             pw.print(", max non-interactive time: ");
    929             TimeUtils.formatDuration(mNonInteractiveTime, pw);
    930             pw.println();
    931 
    932             pw.println();
    933             pw.print("  Broadcast ref count: "); pw.println(mBroadcastRefCount);
    934             pw.println();
    935 
    936             if (mLog.dump(pw, "  Recent problems", "    ")) {
    937                 pw.println();
    938             }
    939 
    940             final FilterStats[] topFilters = new FilterStats[10];
    941             final Comparator<FilterStats> comparator = new Comparator<FilterStats>() {
    942                 @Override
    943                 public int compare(FilterStats lhs, FilterStats rhs) {
    944                     if (lhs.aggregateTime < rhs.aggregateTime) {
    945                         return 1;
    946                     } else if (lhs.aggregateTime > rhs.aggregateTime) {
    947                         return -1;
    948                     }
    949                     return 0;
    950                 }
    951             };
    952             int len = 0;
    953             for (int iu=0; iu<mBroadcastStats.size(); iu++) {
    954                 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(iu);
    955                 for (int ip=0; ip<uidStats.size(); ip++) {
    956                     BroadcastStats bs = uidStats.valueAt(ip);
    957                     for (int is=0; is<bs.filterStats.size(); is++) {
    958                         FilterStats fs = bs.filterStats.valueAt(is);
    959                         int pos = len > 0
    960                                 ? Arrays.binarySearch(topFilters, 0, len, fs, comparator) : 0;
    961                         if (pos < 0) {
    962                             pos = -pos - 1;
    963                         }
    964                         if (pos < topFilters.length) {
    965                             int copylen = topFilters.length - pos - 1;
    966                             if (copylen > 0) {
    967                                 System.arraycopy(topFilters, pos, topFilters, pos+1, copylen);
    968                             }
    969                             topFilters[pos] = fs;
    970                             if (len < topFilters.length) {
    971                                 len++;
    972                             }
    973                         }
    974                     }
    975                 }
    976             }
    977             if (len > 0) {
    978                 pw.println("  Top Alarms:");
    979                 for (int i=0; i<len; i++) {
    980                     FilterStats fs = topFilters[i];
    981                     pw.print("    ");
    982                     if (fs.nesting > 0) pw.print("*ACTIVE* ");
    983                     TimeUtils.formatDuration(fs.aggregateTime, pw);
    984                     pw.print(" running, "); pw.print(fs.numWakeup);
    985                     pw.print(" wakeups, "); pw.print(fs.count);
    986                     pw.print(" alarms: "); UserHandle.formatUid(pw, fs.mBroadcastStats.mUid);
    987                     pw.print(":"); pw.print(fs.mBroadcastStats.mPackageName);
    988                     pw.println();
    989                     pw.print("      "); pw.print(fs.mTag);
    990                     pw.println();
    991                 }
    992             }
    993 
    994             pw.println(" ");
    995             pw.println("  Alarm Stats:");
    996             final ArrayList<FilterStats> tmpFilters = new ArrayList<FilterStats>();
    997             for (int iu=0; iu<mBroadcastStats.size(); iu++) {
    998                 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(iu);
    999                 for (int ip=0; ip<uidStats.size(); ip++) {
   1000                     BroadcastStats bs = uidStats.valueAt(ip);
   1001                     pw.print("  ");
   1002                     if (bs.nesting > 0) pw.print("*ACTIVE* ");
   1003                     UserHandle.formatUid(pw, bs.mUid);
   1004                     pw.print(":");
   1005                     pw.print(bs.mPackageName);
   1006                     pw.print(" "); TimeUtils.formatDuration(bs.aggregateTime, pw);
   1007                             pw.print(" running, "); pw.print(bs.numWakeup);
   1008                             pw.println(" wakeups:");
   1009                     tmpFilters.clear();
   1010                     for (int is=0; is<bs.filterStats.size(); is++) {
   1011                         tmpFilters.add(bs.filterStats.valueAt(is));
   1012                     }
   1013                     Collections.sort(tmpFilters, comparator);
   1014                     for (int i=0; i<tmpFilters.size(); i++) {
   1015                         FilterStats fs = tmpFilters.get(i);
   1016                         pw.print("    ");
   1017                                 if (fs.nesting > 0) pw.print("*ACTIVE* ");
   1018                                 TimeUtils.formatDuration(fs.aggregateTime, pw);
   1019                                 pw.print(" "); pw.print(fs.numWakeup);
   1020                                 pw.print(" wakes " ); pw.print(fs.count);
   1021                                 pw.print(" alarms: ");
   1022                                 pw.print(fs.mTag);
   1023                                 pw.println();
   1024                     }
   1025                 }
   1026             }
   1027 
   1028             if (WAKEUP_STATS) {
   1029                 pw.println();
   1030                 pw.println("  Recent Wakeup History:");
   1031                 long last = -1;
   1032                 for (WakeupEvent event : mRecentWakeups) {
   1033                     pw.print("    "); pw.print(sdf.format(new Date(event.when)));
   1034                     pw.print('|');
   1035                     if (last < 0) {
   1036                         pw.print('0');
   1037                     } else {
   1038                         pw.print(event.when - last);
   1039                     }
   1040                     last = event.when;
   1041                     pw.print('|'); pw.print(event.uid);
   1042                     pw.print('|'); pw.print(event.action);
   1043                     pw.println();
   1044                 }
   1045                 pw.println();
   1046             }
   1047         }
   1048     }
   1049 
   1050     private void logBatchesLocked(SimpleDateFormat sdf) {
   1051         ByteArrayOutputStream bs = new ByteArrayOutputStream(2048);
   1052         PrintWriter pw = new PrintWriter(bs);
   1053         final long nowRTC = System.currentTimeMillis();
   1054         final long nowELAPSED = SystemClock.elapsedRealtime();
   1055         final int NZ = mAlarmBatches.size();
   1056         for (int iz = 0; iz < NZ; iz++) {
   1057             Batch bz = mAlarmBatches.get(iz);
   1058             pw.append("Batch "); pw.print(iz); pw.append(": "); pw.println(bz);
   1059             dumpAlarmList(pw, bz.alarms, "  ", nowELAPSED, nowRTC, sdf);
   1060             pw.flush();
   1061             Slog.v(TAG, bs.toString());
   1062             bs.reset();
   1063         }
   1064     }
   1065 
   1066     private boolean validateConsistencyLocked() {
   1067         if (DEBUG_VALIDATE) {
   1068             long lastTime = Long.MIN_VALUE;
   1069             final int N = mAlarmBatches.size();
   1070             for (int i = 0; i < N; i++) {
   1071                 Batch b = mAlarmBatches.get(i);
   1072                 if (b.start >= lastTime) {
   1073                     // duplicate start times are okay because of standalone batches
   1074                     lastTime = b.start;
   1075                 } else {
   1076                     Slog.e(TAG, "CONSISTENCY FAILURE: Batch " + i + " is out of order");
   1077                     SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
   1078                     logBatchesLocked(sdf);
   1079                     return false;
   1080                 }
   1081             }
   1082         }
   1083         return true;
   1084     }
   1085 
   1086     private Batch findFirstWakeupBatchLocked() {
   1087         final int N = mAlarmBatches.size();
   1088         for (int i = 0; i < N; i++) {
   1089             Batch b = mAlarmBatches.get(i);
   1090             if (b.hasWakeups()) {
   1091                 return b;
   1092             }
   1093         }
   1094         return null;
   1095     }
   1096 
   1097     private AlarmManager.AlarmClockInfo getNextAlarmClockImpl(int userId) {
   1098         synchronized (mLock) {
   1099             return mNextAlarmClockForUser.get(userId);
   1100         }
   1101     }
   1102 
   1103     /**
   1104      * Recomputes the next alarm clock for all users.
   1105      */
   1106     private void updateNextAlarmClockLocked() {
   1107         if (!mNextAlarmClockMayChange) {
   1108             return;
   1109         }
   1110         mNextAlarmClockMayChange = false;
   1111 
   1112         SparseArray<AlarmManager.AlarmClockInfo> nextForUser = mTmpSparseAlarmClockArray;
   1113         nextForUser.clear();
   1114 
   1115         final int N = mAlarmBatches.size();
   1116         for (int i = 0; i < N; i++) {
   1117             ArrayList<Alarm> alarms = mAlarmBatches.get(i).alarms;
   1118             final int M = alarms.size();
   1119 
   1120             for (int j = 0; j < M; j++) {
   1121                 Alarm a = alarms.get(j);
   1122                 if (a.alarmClock != null) {
   1123                     final int userId = a.userId;
   1124 
   1125                     if (DEBUG_ALARM_CLOCK) {
   1126                         Log.v(TAG, "Found AlarmClockInfo at " +
   1127                                 formatNextAlarm(getContext(), a.alarmClock, userId) +
   1128                                 " for user " + userId);
   1129                     }
   1130 
   1131                     // Alarms and batches are sorted by time, no need to compare times here.
   1132                     if (nextForUser.get(userId) == null) {
   1133                         nextForUser.put(userId, a.alarmClock);
   1134                     }
   1135                 }
   1136             }
   1137         }
   1138 
   1139         // Update mNextAlarmForUser with new values.
   1140         final int NN = nextForUser.size();
   1141         for (int i = 0; i < NN; i++) {
   1142             AlarmManager.AlarmClockInfo newAlarm = nextForUser.valueAt(i);
   1143             int userId = nextForUser.keyAt(i);
   1144             AlarmManager.AlarmClockInfo currentAlarm = mNextAlarmClockForUser.get(userId);
   1145             if (!newAlarm.equals(currentAlarm)) {
   1146                 updateNextAlarmInfoForUserLocked(userId, newAlarm);
   1147             }
   1148         }
   1149 
   1150         // Remove users without any alarm clocks scheduled.
   1151         final int NNN = mNextAlarmClockForUser.size();
   1152         for (int i = NNN - 1; i >= 0; i--) {
   1153             int userId = mNextAlarmClockForUser.keyAt(i);
   1154             if (nextForUser.get(userId) == null) {
   1155                 updateNextAlarmInfoForUserLocked(userId, null);
   1156             }
   1157         }
   1158     }
   1159 
   1160     private void updateNextAlarmInfoForUserLocked(int userId,
   1161             AlarmManager.AlarmClockInfo alarmClock) {
   1162         if (alarmClock != null) {
   1163             if (DEBUG_ALARM_CLOCK) {
   1164                 Log.v(TAG, "Next AlarmClockInfoForUser(" + userId + "): " +
   1165                         formatNextAlarm(getContext(), alarmClock, userId));
   1166             }
   1167             mNextAlarmClockForUser.put(userId, alarmClock);
   1168         } else {
   1169             if (DEBUG_ALARM_CLOCK) {
   1170                 Log.v(TAG, "Next AlarmClockInfoForUser(" + userId + "): None");
   1171             }
   1172             mNextAlarmClockForUser.remove(userId);
   1173         }
   1174 
   1175         mPendingSendNextAlarmClockChangedForUser.put(userId, true);
   1176         mHandler.removeMessages(AlarmHandler.SEND_NEXT_ALARM_CLOCK_CHANGED);
   1177         mHandler.sendEmptyMessage(AlarmHandler.SEND_NEXT_ALARM_CLOCK_CHANGED);
   1178     }
   1179 
   1180     /**
   1181      * Updates NEXT_ALARM_FORMATTED and sends NEXT_ALARM_CLOCK_CHANGED_INTENT for all users
   1182      * for which alarm clocks have changed since the last call to this.
   1183      *
   1184      * Do not call with a lock held. Only call from mHandler's thread.
   1185      *
   1186      * @see AlarmHandler#SEND_NEXT_ALARM_CLOCK_CHANGED
   1187      */
   1188     private void sendNextAlarmClockChanged() {
   1189         SparseArray<AlarmManager.AlarmClockInfo> pendingUsers = mHandlerSparseAlarmClockArray;
   1190         pendingUsers.clear();
   1191 
   1192         synchronized (mLock) {
   1193             final int N  = mPendingSendNextAlarmClockChangedForUser.size();
   1194             for (int i = 0; i < N; i++) {
   1195                 int userId = mPendingSendNextAlarmClockChangedForUser.keyAt(i);
   1196                 pendingUsers.append(userId, mNextAlarmClockForUser.get(userId));
   1197             }
   1198             mPendingSendNextAlarmClockChangedForUser.clear();
   1199         }
   1200 
   1201         final int N = pendingUsers.size();
   1202         for (int i = 0; i < N; i++) {
   1203             int userId = pendingUsers.keyAt(i);
   1204             AlarmManager.AlarmClockInfo alarmClock = pendingUsers.valueAt(i);
   1205             Settings.System.putStringForUser(getContext().getContentResolver(),
   1206                     Settings.System.NEXT_ALARM_FORMATTED,
   1207                     formatNextAlarm(getContext(), alarmClock, userId),
   1208                     userId);
   1209 
   1210             getContext().sendBroadcastAsUser(NEXT_ALARM_CLOCK_CHANGED_INTENT,
   1211                     new UserHandle(userId));
   1212         }
   1213     }
   1214 
   1215     /**
   1216      * Formats an alarm like platform/packages/apps/DeskClock used to.
   1217      */
   1218     private static String formatNextAlarm(final Context context, AlarmManager.AlarmClockInfo info,
   1219             int userId) {
   1220         String skeleton = DateFormat.is24HourFormat(context, userId) ? "EHm" : "Ehma";
   1221         String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton);
   1222         return (info == null) ? "" :
   1223                 DateFormat.format(pattern, info.getTriggerTime()).toString();
   1224     }
   1225 
   1226     void rescheduleKernelAlarmsLocked() {
   1227         // Schedule the next upcoming wakeup alarm.  If there is a deliverable batch
   1228         // prior to that which contains no wakeups, we schedule that as well.
   1229         long nextNonWakeup = 0;
   1230         if (mAlarmBatches.size() > 0) {
   1231             final Batch firstWakeup = findFirstWakeupBatchLocked();
   1232             final Batch firstBatch = mAlarmBatches.get(0);
   1233             // always update the kernel alarms, as a backstop against missed wakeups
   1234             if (firstWakeup != null) {
   1235                 mNextWakeup = firstWakeup.start;
   1236                 setLocked(ELAPSED_REALTIME_WAKEUP, firstWakeup.start);
   1237             }
   1238             if (firstBatch != firstWakeup) {
   1239                 nextNonWakeup = firstBatch.start;
   1240             }
   1241         }
   1242         if (mPendingNonWakeupAlarms.size() > 0) {
   1243             if (nextNonWakeup == 0 || mNextNonWakeupDeliveryTime < nextNonWakeup) {
   1244                 nextNonWakeup = mNextNonWakeupDeliveryTime;
   1245             }
   1246         }
   1247         // always update the kernel alarm, as a backstop against missed wakeups
   1248         if (nextNonWakeup != 0) {
   1249             mNextNonWakeup = nextNonWakeup;
   1250             setLocked(ELAPSED_REALTIME, nextNonWakeup);
   1251         }
   1252     }
   1253 
   1254     private void removeLocked(PendingIntent operation) {
   1255         boolean didRemove = false;
   1256         for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
   1257             Batch b = mAlarmBatches.get(i);
   1258             didRemove |= b.remove(operation);
   1259             if (b.size() == 0) {
   1260                 mAlarmBatches.remove(i);
   1261             }
   1262         }
   1263 
   1264         if (didRemove) {
   1265             if (DEBUG_BATCH) {
   1266                 Slog.v(TAG, "remove(operation) changed bounds; rebatching");
   1267             }
   1268             rebatchAllAlarmsLocked(true);
   1269             rescheduleKernelAlarmsLocked();
   1270             updateNextAlarmClockLocked();
   1271         }
   1272     }
   1273 
   1274     void removeLocked(String packageName) {
   1275         boolean didRemove = false;
   1276         for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
   1277             Batch b = mAlarmBatches.get(i);
   1278             didRemove |= b.remove(packageName);
   1279             if (b.size() == 0) {
   1280                 mAlarmBatches.remove(i);
   1281             }
   1282         }
   1283 
   1284         if (didRemove) {
   1285             if (DEBUG_BATCH) {
   1286                 Slog.v(TAG, "remove(package) changed bounds; rebatching");
   1287             }
   1288             rebatchAllAlarmsLocked(true);
   1289             rescheduleKernelAlarmsLocked();
   1290             updateNextAlarmClockLocked();
   1291         }
   1292     }
   1293 
   1294     void removeUserLocked(int userHandle) {
   1295         boolean didRemove = false;
   1296         for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
   1297             Batch b = mAlarmBatches.get(i);
   1298             didRemove |= b.remove(userHandle);
   1299             if (b.size() == 0) {
   1300                 mAlarmBatches.remove(i);
   1301             }
   1302         }
   1303 
   1304         if (didRemove) {
   1305             if (DEBUG_BATCH) {
   1306                 Slog.v(TAG, "remove(user) changed bounds; rebatching");
   1307             }
   1308             rebatchAllAlarmsLocked(true);
   1309             rescheduleKernelAlarmsLocked();
   1310             updateNextAlarmClockLocked();
   1311         }
   1312     }
   1313 
   1314     void interactiveStateChangedLocked(boolean interactive) {
   1315         if (mInteractive != interactive) {
   1316             mInteractive = interactive;
   1317             final long nowELAPSED = SystemClock.elapsedRealtime();
   1318             if (interactive) {
   1319                 if (mPendingNonWakeupAlarms.size() > 0) {
   1320                     final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
   1321                     mTotalDelayTime += thisDelayTime;
   1322                     if (mMaxDelayTime < thisDelayTime) {
   1323                         mMaxDelayTime = thisDelayTime;
   1324                     }
   1325                     deliverAlarmsLocked(mPendingNonWakeupAlarms, nowELAPSED);
   1326                     mPendingNonWakeupAlarms.clear();
   1327                 }
   1328                 if (mNonInteractiveStartTime > 0) {
   1329                     long dur = nowELAPSED - mNonInteractiveStartTime;
   1330                     if (dur > mNonInteractiveTime) {
   1331                         mNonInteractiveTime = dur;
   1332                     }
   1333                 }
   1334             } else {
   1335                 mNonInteractiveStartTime = nowELAPSED;
   1336             }
   1337         }
   1338     }
   1339 
   1340     boolean lookForPackageLocked(String packageName) {
   1341         for (int i = 0; i < mAlarmBatches.size(); i++) {
   1342             Batch b = mAlarmBatches.get(i);
   1343             if (b.hasPackage(packageName)) {
   1344                 return true;
   1345             }
   1346         }
   1347         return false;
   1348     }
   1349 
   1350     private void setLocked(int type, long when) {
   1351         if (mNativeData != 0) {
   1352             // The kernel never triggers alarms with negative wakeup times
   1353             // so we ensure they are positive.
   1354             long alarmSeconds, alarmNanoseconds;
   1355             if (when < 0) {
   1356                 alarmSeconds = 0;
   1357                 alarmNanoseconds = 0;
   1358             } else {
   1359                 alarmSeconds = when / 1000;
   1360                 alarmNanoseconds = (when % 1000) * 1000 * 1000;
   1361             }
   1362 
   1363             set(mNativeData, type, alarmSeconds, alarmNanoseconds);
   1364         } else {
   1365             Message msg = Message.obtain();
   1366             msg.what = ALARM_EVENT;
   1367 
   1368             mHandler.removeMessages(ALARM_EVENT);
   1369             mHandler.sendMessageAtTime(msg, when);
   1370         }
   1371     }
   1372 
   1373     private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list,
   1374             String prefix, String label, long nowRTC, long nowELAPSED, SimpleDateFormat sdf) {
   1375         for (int i=list.size()-1; i>=0; i--) {
   1376             Alarm a = list.get(i);
   1377             pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i);
   1378                     pw.print(": "); pw.println(a);
   1379             a.dump(pw, prefix + "  ", nowRTC, nowELAPSED, sdf);
   1380         }
   1381     }
   1382 
   1383     private static final String labelForType(int type) {
   1384         switch (type) {
   1385         case RTC: return "RTC";
   1386         case RTC_WAKEUP : return "RTC_WAKEUP";
   1387         case ELAPSED_REALTIME : return "ELAPSED";
   1388         case ELAPSED_REALTIME_WAKEUP: return "ELAPSED_WAKEUP";
   1389         default:
   1390             break;
   1391         }
   1392         return "--unknown--";
   1393     }
   1394 
   1395     private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list,
   1396             String prefix, long nowELAPSED, long nowRTC, SimpleDateFormat sdf) {
   1397         for (int i=list.size()-1; i>=0; i--) {
   1398             Alarm a = list.get(i);
   1399             final String label = labelForType(a.type);
   1400             pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i);
   1401                     pw.print(": "); pw.println(a);
   1402             a.dump(pw, prefix + "  ", nowRTC, nowELAPSED, sdf);
   1403         }
   1404     }
   1405 
   1406     private native long init();
   1407     private native void close(long nativeData);
   1408     private native void set(long nativeData, int type, long seconds, long nanoseconds);
   1409     private native int waitForAlarm(long nativeData);
   1410     private native int setKernelTime(long nativeData, long millis);
   1411     private native int setKernelTimezone(long nativeData, int minuteswest);
   1412 
   1413     boolean triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED,
   1414             final long nowRTC) {
   1415         boolean hasWakeup = false;
   1416         // batches are temporally sorted, so we need only pull from the
   1417         // start of the list until we either empty it or hit a batch
   1418         // that is not yet deliverable
   1419         while (mAlarmBatches.size() > 0) {
   1420             Batch batch = mAlarmBatches.get(0);
   1421             if (batch.start > nowELAPSED) {
   1422                 // Everything else is scheduled for the future
   1423                 break;
   1424             }
   1425 
   1426             // We will (re)schedule some alarms now; don't let that interfere
   1427             // with delivery of this current batch
   1428             mAlarmBatches.remove(0);
   1429 
   1430             final int N = batch.size();
   1431             for (int i = 0; i < N; i++) {
   1432                 Alarm alarm = batch.get(i);
   1433                 alarm.count = 1;
   1434                 triggerList.add(alarm);
   1435 
   1436                 // Recurring alarms may have passed several alarm intervals while the
   1437                 // phone was asleep or off, so pass a trigger count when sending them.
   1438                 if (alarm.repeatInterval > 0) {
   1439                     // this adjustment will be zero if we're late by
   1440                     // less than one full repeat interval
   1441                     alarm.count += (nowELAPSED - alarm.whenElapsed) / alarm.repeatInterval;
   1442 
   1443                     // Also schedule its next recurrence
   1444                     final long delta = alarm.count * alarm.repeatInterval;
   1445                     final long nextElapsed = alarm.whenElapsed + delta;
   1446                     setImplLocked(alarm.type, alarm.when + delta, nextElapsed, alarm.windowLength,
   1447                             maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval),
   1448                             alarm.repeatInterval, alarm.operation, batch.standalone, true,
   1449                             alarm.workSource, alarm.alarmClock, alarm.userId);
   1450                 }
   1451 
   1452                 if (alarm.wakeup) {
   1453                     hasWakeup = true;
   1454                 }
   1455 
   1456                 // We removed an alarm clock. Let the caller recompute the next alarm clock.
   1457                 if (alarm.alarmClock != null) {
   1458                     mNextAlarmClockMayChange = true;
   1459                 }
   1460             }
   1461         }
   1462 
   1463         // This is a new alarm delivery set; bump the sequence number to indicate that
   1464         // all apps' alarm delivery classes should be recalculated.
   1465         mCurrentSeq++;
   1466         calculateDeliveryPriorities(triggerList);
   1467         Collections.sort(triggerList, mAlarmDispatchComparator);
   1468 
   1469         if (localLOGV) {
   1470             for (int i=0; i<triggerList.size(); i++) {
   1471                 Slog.v(TAG, "Triggering alarm #" + i + ": " + triggerList.get(i));
   1472             }
   1473         }
   1474 
   1475         return hasWakeup;
   1476     }
   1477 
   1478     /**
   1479      * This Comparator sorts Alarms into increasing time order.
   1480      */
   1481     public static class IncreasingTimeOrder implements Comparator<Alarm> {
   1482         public int compare(Alarm a1, Alarm a2) {
   1483             long when1 = a1.when;
   1484             long when2 = a2.when;
   1485             if (when1 - when2 > 0) {
   1486                 return 1;
   1487             }
   1488             if (when1 - when2 < 0) {
   1489                 return -1;
   1490             }
   1491             return 0;
   1492         }
   1493     }
   1494 
   1495     private static class Alarm {
   1496         public final int type;
   1497         public final boolean wakeup;
   1498         public final PendingIntent operation;
   1499         public final String  tag;
   1500         public final WorkSource workSource;
   1501         public int count;
   1502         public long when;
   1503         public long windowLength;
   1504         public long whenElapsed;    // 'when' in the elapsed time base
   1505         public long maxWhen;        // also in the elapsed time base
   1506         public long repeatInterval;
   1507         public final AlarmManager.AlarmClockInfo alarmClock;
   1508         public final int userId;
   1509         public PriorityClass priorityClass;
   1510 
   1511         public Alarm(int _type, long _when, long _whenElapsed, long _windowLength, long _maxWhen,
   1512                 long _interval, PendingIntent _op, WorkSource _ws,
   1513                 AlarmManager.AlarmClockInfo _info, int _userId) {
   1514             type = _type;
   1515             wakeup = _type == AlarmManager.ELAPSED_REALTIME_WAKEUP
   1516                     || _type == AlarmManager.RTC_WAKEUP;
   1517             when = _when;
   1518             whenElapsed = _whenElapsed;
   1519             windowLength = _windowLength;
   1520             maxWhen = _maxWhen;
   1521             repeatInterval = _interval;
   1522             operation = _op;
   1523             tag = makeTag(_op, _type);
   1524             workSource = _ws;
   1525             alarmClock = _info;
   1526             userId = _userId;
   1527         }
   1528 
   1529         public static String makeTag(PendingIntent pi, int type) {
   1530             return pi.getTag(type == ELAPSED_REALTIME_WAKEUP || type == RTC_WAKEUP
   1531                     ? "*walarm*:" : "*alarm*:");
   1532         }
   1533 
   1534         @Override
   1535         public String toString() {
   1536             StringBuilder sb = new StringBuilder(128);
   1537             sb.append("Alarm{");
   1538             sb.append(Integer.toHexString(System.identityHashCode(this)));
   1539             sb.append(" type ");
   1540             sb.append(type);
   1541             sb.append(" when ");
   1542             sb.append(when);
   1543             sb.append(" ");
   1544             sb.append(operation.getTargetPackage());
   1545             sb.append('}');
   1546             return sb.toString();
   1547         }
   1548 
   1549         public void dump(PrintWriter pw, String prefix, long nowRTC, long nowELAPSED,
   1550                 SimpleDateFormat sdf) {
   1551             final boolean isRtc = (type == RTC || type == RTC_WAKEUP);
   1552             pw.print(prefix); pw.print("tag="); pw.println(tag);
   1553             pw.print(prefix); pw.print("type="); pw.print(type);
   1554                     pw.print(" whenElapsed="); TimeUtils.formatDuration(whenElapsed,
   1555                             nowELAPSED, pw);
   1556                     if (isRtc) {
   1557                         pw.print(" when="); pw.print(sdf.format(new Date(when)));
   1558                     } else {
   1559                         pw.print(" when="); TimeUtils.formatDuration(when, nowELAPSED, pw);
   1560                     }
   1561                     pw.println();
   1562             pw.print(prefix); pw.print("window="); pw.print(windowLength);
   1563                     pw.print(" repeatInterval="); pw.print(repeatInterval);
   1564                     pw.print(" count="); pw.println(count);
   1565             pw.print(prefix); pw.print("operation="); pw.println(operation);
   1566         }
   1567     }
   1568 
   1569     void recordWakeupAlarms(ArrayList<Batch> batches, long nowELAPSED, long nowRTC) {
   1570         final int numBatches = batches.size();
   1571         for (int nextBatch = 0; nextBatch < numBatches; nextBatch++) {
   1572             Batch b = batches.get(nextBatch);
   1573             if (b.start > nowELAPSED) {
   1574                 break;
   1575             }
   1576 
   1577             final int numAlarms = b.alarms.size();
   1578             for (int nextAlarm = 0; nextAlarm < numAlarms; nextAlarm++) {
   1579                 Alarm a = b.alarms.get(nextAlarm);
   1580                 WakeupEvent e = new WakeupEvent(nowRTC,
   1581                         a.operation.getCreatorUid(),
   1582                         a.operation.getIntent().getAction());
   1583                 mRecentWakeups.add(e);
   1584             }
   1585         }
   1586     }
   1587 
   1588     long currentNonWakeupFuzzLocked(long nowELAPSED) {
   1589         long timeSinceOn = nowELAPSED - mNonInteractiveStartTime;
   1590         if (timeSinceOn < 5*60*1000) {
   1591             // If the screen has been off for 5 minutes, only delay by at most two minutes.
   1592             return 2*60*1000;
   1593         } else if (timeSinceOn < 30*60*1000) {
   1594             // If the screen has been off for 30 minutes, only delay by at most 15 minutes.
   1595             return 15*60*1000;
   1596         } else {
   1597             // Otherwise, we will delay by at most an hour.
   1598             return 60*60*1000;
   1599         }
   1600     }
   1601 
   1602     boolean checkAllowNonWakeupDelayLocked(long nowELAPSED) {
   1603         if (mInteractive) {
   1604             return false;
   1605         }
   1606         if (mLastAlarmDeliveryTime <= 0) {
   1607             return false;
   1608         }
   1609         if (mPendingNonWakeupAlarms.size() > 0 && mNextNonWakeupDeliveryTime > nowELAPSED) {
   1610             // This is just a little paranoia, if somehow we have pending non-wakeup alarms
   1611             // and the next delivery time is in the past, then just deliver them all.  This
   1612             // avoids bugs where we get stuck in a loop trying to poll for alarms.
   1613             return false;
   1614         }
   1615         long timeSinceLast = nowELAPSED - mLastAlarmDeliveryTime;
   1616         return timeSinceLast <= currentNonWakeupFuzzLocked(nowELAPSED);
   1617     }
   1618 
   1619     void deliverAlarmsLocked(ArrayList<Alarm> triggerList, long nowELAPSED) {
   1620         mLastAlarmDeliveryTime = nowELAPSED;
   1621         for (int i=0; i<triggerList.size(); i++) {
   1622             Alarm alarm = triggerList.get(i);
   1623             try {
   1624                 if (localLOGV) {
   1625                     Slog.v(TAG, "sending alarm " + alarm);
   1626                 }
   1627                 alarm.operation.send(getContext(), 0,
   1628                         mBackgroundIntent.putExtra(
   1629                                 Intent.EXTRA_ALARM_COUNT, alarm.count),
   1630                         mResultReceiver, mHandler);
   1631 
   1632                 // we have an active broadcast so stay awake.
   1633                 if (mBroadcastRefCount == 0) {
   1634                     setWakelockWorkSource(alarm.operation, alarm.workSource,
   1635                             alarm.type, alarm.tag, true);
   1636                     mWakeLock.acquire();
   1637                 }
   1638                 final InFlight inflight = new InFlight(AlarmManagerService.this,
   1639                         alarm.operation, alarm.workSource, alarm.type, alarm.tag);
   1640                 mInFlight.add(inflight);
   1641                 mBroadcastRefCount++;
   1642 
   1643                 final BroadcastStats bs = inflight.mBroadcastStats;
   1644                 bs.count++;
   1645                 if (bs.nesting == 0) {
   1646                     bs.nesting = 1;
   1647                     bs.startTime = nowELAPSED;
   1648                 } else {
   1649                     bs.nesting++;
   1650                 }
   1651                 final FilterStats fs = inflight.mFilterStats;
   1652                 fs.count++;
   1653                 if (fs.nesting == 0) {
   1654                     fs.nesting = 1;
   1655                     fs.startTime = nowELAPSED;
   1656                 } else {
   1657                     fs.nesting++;
   1658                 }
   1659                 if (alarm.type == ELAPSED_REALTIME_WAKEUP
   1660                         || alarm.type == RTC_WAKEUP) {
   1661                     bs.numWakeup++;
   1662                     fs.numWakeup++;
   1663                     if (alarm.workSource != null && alarm.workSource.size() > 0) {
   1664                         for (int wi=0; wi<alarm.workSource.size(); wi++) {
   1665                             ActivityManagerNative.noteWakeupAlarm(
   1666                                     alarm.operation, alarm.workSource.get(wi),
   1667                                     alarm.workSource.getName(wi));
   1668                         }
   1669                     } else {
   1670                         ActivityManagerNative.noteWakeupAlarm(
   1671                                 alarm.operation, -1, null);
   1672                     }
   1673                 }
   1674             } catch (PendingIntent.CanceledException e) {
   1675                 if (alarm.repeatInterval > 0) {
   1676                     // This IntentSender is no longer valid, but this
   1677                     // is a repeating alarm, so toss the hoser.
   1678                     removeImpl(alarm.operation);
   1679                 }
   1680             } catch (RuntimeException e) {
   1681                 Slog.w(TAG, "Failure sending alarm.", e);
   1682             }
   1683         }
   1684     }
   1685 
   1686     private class AlarmThread extends Thread
   1687     {
   1688         public AlarmThread()
   1689         {
   1690             super("AlarmManager");
   1691         }
   1692 
   1693         public void run()
   1694         {
   1695             ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
   1696 
   1697             while (true)
   1698             {
   1699                 int result = waitForAlarm(mNativeData);
   1700 
   1701                 triggerList.clear();
   1702 
   1703                 if ((result & TIME_CHANGED_MASK) != 0) {
   1704                     if (DEBUG_BATCH) {
   1705                         Slog.v(TAG, "Time changed notification from kernel; rebatching");
   1706                     }
   1707                     removeImpl(mTimeTickSender);
   1708                     rebatchAllAlarms();
   1709                     mClockReceiver.scheduleTimeTickEvent();
   1710                     synchronized (mLock) {
   1711                         mNumTimeChanged++;
   1712                     }
   1713                     Intent intent = new Intent(Intent.ACTION_TIME_CHANGED);
   1714                     intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
   1715                             | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
   1716                     getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
   1717                 }
   1718 
   1719                 synchronized (mLock) {
   1720                     final long nowRTC = System.currentTimeMillis();
   1721                     final long nowELAPSED = SystemClock.elapsedRealtime();
   1722                     if (localLOGV) Slog.v(
   1723                         TAG, "Checking for alarms... rtc=" + nowRTC
   1724                         + ", elapsed=" + nowELAPSED);
   1725 
   1726                     if (WAKEUP_STATS) {
   1727                         if ((result & IS_WAKEUP_MASK) != 0) {
   1728                             long newEarliest = nowRTC - RECENT_WAKEUP_PERIOD;
   1729                             int n = 0;
   1730                             for (WakeupEvent event : mRecentWakeups) {
   1731                                 if (event.when > newEarliest) break;
   1732                                 n++; // number of now-stale entries at the list head
   1733                             }
   1734                             for (int i = 0; i < n; i++) {
   1735                                 mRecentWakeups.remove();
   1736                             }
   1737 
   1738                             recordWakeupAlarms(mAlarmBatches, nowELAPSED, nowRTC);
   1739                         }
   1740                     }
   1741 
   1742                     boolean hasWakeup = triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC);
   1743                     if (!hasWakeup && checkAllowNonWakeupDelayLocked(nowELAPSED)) {
   1744                         // if there are no wakeup alarms and the screen is off, we can
   1745                         // delay what we have so far until the future.
   1746                         if (mPendingNonWakeupAlarms.size() == 0) {
   1747                             mStartCurrentDelayTime = nowELAPSED;
   1748                             mNextNonWakeupDeliveryTime = nowELAPSED
   1749                                     + ((currentNonWakeupFuzzLocked(nowELAPSED)*3)/2);
   1750                         }
   1751                         mPendingNonWakeupAlarms.addAll(triggerList);
   1752                         mNumDelayedAlarms += triggerList.size();
   1753                         rescheduleKernelAlarmsLocked();
   1754                         updateNextAlarmClockLocked();
   1755                     } else {
   1756                         // now deliver the alarm intents; if there are pending non-wakeup
   1757                         // alarms, we need to merge them in to the list.  note we don't
   1758                         // just deliver them first because we generally want non-wakeup
   1759                         // alarms delivered after wakeup alarms.
   1760                         rescheduleKernelAlarmsLocked();
   1761                         updateNextAlarmClockLocked();
   1762                         if (mPendingNonWakeupAlarms.size() > 0) {
   1763                             calculateDeliveryPriorities(mPendingNonWakeupAlarms);
   1764                             triggerList.addAll(mPendingNonWakeupAlarms);
   1765                             Collections.sort(triggerList, mAlarmDispatchComparator);
   1766                             final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
   1767                             mTotalDelayTime += thisDelayTime;
   1768                             if (mMaxDelayTime < thisDelayTime) {
   1769                                 mMaxDelayTime = thisDelayTime;
   1770                             }
   1771                             mPendingNonWakeupAlarms.clear();
   1772                         }
   1773                         deliverAlarmsLocked(triggerList, nowELAPSED);
   1774                     }
   1775                 }
   1776             }
   1777         }
   1778     }
   1779 
   1780     /**
   1781      * Attribute blame for a WakeLock.
   1782      * @param pi PendingIntent to attribute blame to if ws is null.
   1783      * @param ws WorkSource to attribute blame.
   1784      */
   1785     void setWakelockWorkSource(PendingIntent pi, WorkSource ws, int type, String tag,
   1786             boolean first) {
   1787         try {
   1788             final boolean unimportant = pi == mTimeTickSender;
   1789             mWakeLock.setUnimportantForLogging(unimportant);
   1790             if (first || mLastWakeLockUnimportantForLogging) {
   1791                 mWakeLock.setHistoryTag(tag);
   1792             } else {
   1793                 mWakeLock.setHistoryTag(null);
   1794             }
   1795             mLastWakeLockUnimportantForLogging = unimportant;
   1796             if (ws != null) {
   1797                 mWakeLock.setWorkSource(ws);
   1798                 return;
   1799             }
   1800 
   1801             final int uid = ActivityManagerNative.getDefault()
   1802                     .getUidForIntentSender(pi.getTarget());
   1803             if (uid >= 0) {
   1804                 mWakeLock.setWorkSource(new WorkSource(uid));
   1805                 return;
   1806             }
   1807         } catch (Exception e) {
   1808         }
   1809 
   1810         // Something went wrong; fall back to attributing the lock to the OS
   1811         mWakeLock.setWorkSource(null);
   1812     }
   1813 
   1814     private class AlarmHandler extends Handler {
   1815         public static final int ALARM_EVENT = 1;
   1816         public static final int MINUTE_CHANGE_EVENT = 2;
   1817         public static final int DATE_CHANGE_EVENT = 3;
   1818         public static final int SEND_NEXT_ALARM_CLOCK_CHANGED = 4;
   1819 
   1820         public AlarmHandler() {
   1821         }
   1822 
   1823         public void handleMessage(Message msg) {
   1824             if (msg.what == ALARM_EVENT) {
   1825                 ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
   1826                 synchronized (mLock) {
   1827                     final long nowRTC = System.currentTimeMillis();
   1828                     final long nowELAPSED = SystemClock.elapsedRealtime();
   1829                     triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC);
   1830                     updateNextAlarmClockLocked();
   1831                 }
   1832 
   1833                 // now trigger the alarms without the lock held
   1834                 for (int i=0; i<triggerList.size(); i++) {
   1835                     Alarm alarm = triggerList.get(i);
   1836                     try {
   1837                         alarm.operation.send();
   1838                     } catch (PendingIntent.CanceledException e) {
   1839                         if (alarm.repeatInterval > 0) {
   1840                             // This IntentSender is no longer valid, but this
   1841                             // is a repeating alarm, so toss the hoser.
   1842                             removeImpl(alarm.operation);
   1843                         }
   1844                     }
   1845                 }
   1846             } else if (msg.what == SEND_NEXT_ALARM_CLOCK_CHANGED) {
   1847                 sendNextAlarmClockChanged();
   1848             }
   1849         }
   1850     }
   1851 
   1852     class ClockReceiver extends BroadcastReceiver {
   1853         public ClockReceiver() {
   1854             IntentFilter filter = new IntentFilter();
   1855             filter.addAction(Intent.ACTION_TIME_TICK);
   1856             filter.addAction(Intent.ACTION_DATE_CHANGED);
   1857             getContext().registerReceiver(this, filter);
   1858         }
   1859 
   1860         @Override
   1861         public void onReceive(Context context, Intent intent) {
   1862             if (intent.getAction().equals(Intent.ACTION_TIME_TICK)) {
   1863                 if (DEBUG_BATCH) {
   1864                     Slog.v(TAG, "Received TIME_TICK alarm; rescheduling");
   1865                 }
   1866                 scheduleTimeTickEvent();
   1867             } else if (intent.getAction().equals(Intent.ACTION_DATE_CHANGED)) {
   1868                 // Since the kernel does not keep track of DST, we need to
   1869                 // reset the TZ information at the beginning of each day
   1870                 // based off of the current Zone gmt offset + userspace tracked
   1871                 // daylight savings information.
   1872                 TimeZone zone = TimeZone.getTimeZone(SystemProperties.get(TIMEZONE_PROPERTY));
   1873                 int gmtOffset = zone.getOffset(System.currentTimeMillis());
   1874                 setKernelTimezone(mNativeData, -(gmtOffset / 60000));
   1875                 scheduleDateChangedEvent();
   1876             }
   1877         }
   1878 
   1879         public void scheduleTimeTickEvent() {
   1880             final long currentTime = System.currentTimeMillis();
   1881             final long nextTime = 60000 * ((currentTime / 60000) + 1);
   1882 
   1883             // Schedule this event for the amount of time that it would take to get to
   1884             // the top of the next minute.
   1885             final long tickEventDelay = nextTime - currentTime;
   1886 
   1887             final WorkSource workSource = null; // Let system take blame for time tick events.
   1888             setImpl(ELAPSED_REALTIME, SystemClock.elapsedRealtime() + tickEventDelay, 0,
   1889                     0, mTimeTickSender, true, workSource, null);
   1890         }
   1891 
   1892         public void scheduleDateChangedEvent() {
   1893             Calendar calendar = Calendar.getInstance();
   1894             calendar.setTimeInMillis(System.currentTimeMillis());
   1895             calendar.set(Calendar.HOUR, 0);
   1896             calendar.set(Calendar.MINUTE, 0);
   1897             calendar.set(Calendar.SECOND, 0);
   1898             calendar.set(Calendar.MILLISECOND, 0);
   1899             calendar.add(Calendar.DAY_OF_MONTH, 1);
   1900 
   1901             final WorkSource workSource = null; // Let system take blame for date change events.
   1902             setImpl(RTC, calendar.getTimeInMillis(), 0, 0, mDateChangeSender, true, workSource,
   1903                     null);
   1904         }
   1905     }
   1906 
   1907     class InteractiveStateReceiver extends BroadcastReceiver {
   1908         public InteractiveStateReceiver() {
   1909             IntentFilter filter = new IntentFilter();
   1910             filter.addAction(Intent.ACTION_SCREEN_OFF);
   1911             filter.addAction(Intent.ACTION_SCREEN_ON);
   1912             filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
   1913             getContext().registerReceiver(this, filter);
   1914         }
   1915 
   1916         @Override
   1917         public void onReceive(Context context, Intent intent) {
   1918             synchronized (mLock) {
   1919                 interactiveStateChangedLocked(Intent.ACTION_SCREEN_ON.equals(intent.getAction()));
   1920             }
   1921         }
   1922     }
   1923 
   1924     class UninstallReceiver extends BroadcastReceiver {
   1925         public UninstallReceiver() {
   1926             IntentFilter filter = new IntentFilter();
   1927             filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
   1928             filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
   1929             filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
   1930             filter.addDataScheme("package");
   1931             getContext().registerReceiver(this, filter);
   1932              // Register for events related to sdcard installation.
   1933             IntentFilter sdFilter = new IntentFilter();
   1934             sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
   1935             sdFilter.addAction(Intent.ACTION_USER_STOPPED);
   1936             getContext().registerReceiver(this, sdFilter);
   1937         }
   1938 
   1939         @Override
   1940         public void onReceive(Context context, Intent intent) {
   1941             synchronized (mLock) {
   1942                 String action = intent.getAction();
   1943                 String pkgList[] = null;
   1944                 if (Intent.ACTION_QUERY_PACKAGE_RESTART.equals(action)) {
   1945                     pkgList = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
   1946                     for (String packageName : pkgList) {
   1947                         if (lookForPackageLocked(packageName)) {
   1948                             setResultCode(Activity.RESULT_OK);
   1949                             return;
   1950                         }
   1951                     }
   1952                     return;
   1953                 } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
   1954                     pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
   1955                 } else if (Intent.ACTION_USER_STOPPED.equals(action)) {
   1956                     int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
   1957                     if (userHandle >= 0) {
   1958                         removeUserLocked(userHandle);
   1959                     }
   1960                 } else {
   1961                     if (Intent.ACTION_PACKAGE_REMOVED.equals(action)
   1962                             && intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
   1963                         // This package is being updated; don't kill its alarms.
   1964                         return;
   1965                     }
   1966                     Uri data = intent.getData();
   1967                     if (data != null) {
   1968                         String pkg = data.getSchemeSpecificPart();
   1969                         if (pkg != null) {
   1970                             pkgList = new String[]{pkg};
   1971                         }
   1972                     }
   1973                 }
   1974                 if (pkgList != null && (pkgList.length > 0)) {
   1975                     for (String pkg : pkgList) {
   1976                         removeLocked(pkg);
   1977                         mPriorities.remove(pkg);
   1978                         for (int i=mBroadcastStats.size()-1; i>=0; i--) {
   1979                             ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(i);
   1980                             if (uidStats.remove(pkg) != null) {
   1981                                 if (uidStats.size() <= 0) {
   1982                                     mBroadcastStats.removeAt(i);
   1983                                 }
   1984                             }
   1985                         }
   1986                     }
   1987                 }
   1988             }
   1989         }
   1990     }
   1991 
   1992     private final BroadcastStats getStatsLocked(PendingIntent pi) {
   1993         String pkg = pi.getCreatorPackage();
   1994         int uid = pi.getCreatorUid();
   1995         ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.get(uid);
   1996         if (uidStats == null) {
   1997             uidStats = new ArrayMap<String, BroadcastStats>();
   1998             mBroadcastStats.put(uid, uidStats);
   1999         }
   2000         BroadcastStats bs = uidStats.get(pkg);
   2001         if (bs == null) {
   2002             bs = new BroadcastStats(uid, pkg);
   2003             uidStats.put(pkg, bs);
   2004         }
   2005         return bs;
   2006     }
   2007 
   2008     class ResultReceiver implements PendingIntent.OnFinished {
   2009         public void onSendFinished(PendingIntent pi, Intent intent, int resultCode,
   2010                 String resultData, Bundle resultExtras) {
   2011             synchronized (mLock) {
   2012                 InFlight inflight = null;
   2013                 for (int i=0; i<mInFlight.size(); i++) {
   2014                     if (mInFlight.get(i).mPendingIntent == pi) {
   2015                         inflight = mInFlight.remove(i);
   2016                         break;
   2017                     }
   2018                 }
   2019                 if (inflight != null) {
   2020                     final long nowELAPSED = SystemClock.elapsedRealtime();
   2021                     BroadcastStats bs = inflight.mBroadcastStats;
   2022                     bs.nesting--;
   2023                     if (bs.nesting <= 0) {
   2024                         bs.nesting = 0;
   2025                         bs.aggregateTime += nowELAPSED - bs.startTime;
   2026                     }
   2027                     FilterStats fs = inflight.mFilterStats;
   2028                     fs.nesting--;
   2029                     if (fs.nesting <= 0) {
   2030                         fs.nesting = 0;
   2031                         fs.aggregateTime += nowELAPSED - fs.startTime;
   2032                     }
   2033                 } else {
   2034                     mLog.w("No in-flight alarm for " + pi + " " + intent);
   2035                 }
   2036                 mBroadcastRefCount--;
   2037                 if (mBroadcastRefCount == 0) {
   2038                     mWakeLock.release();
   2039                     if (mInFlight.size() > 0) {
   2040                         mLog.w("Finished all broadcasts with " + mInFlight.size()
   2041                                 + " remaining inflights");
   2042                         for (int i=0; i<mInFlight.size(); i++) {
   2043                             mLog.w("  Remaining #" + i + ": " + mInFlight.get(i));
   2044                         }
   2045                         mInFlight.clear();
   2046                     }
   2047                 } else {
   2048                     // the next of our alarms is now in flight.  reattribute the wakelock.
   2049                     if (mInFlight.size() > 0) {
   2050                         InFlight inFlight = mInFlight.get(0);
   2051                         setWakelockWorkSource(inFlight.mPendingIntent, inFlight.mWorkSource,
   2052                                 inFlight.mAlarmType, inFlight.mTag, false);
   2053                     } else {
   2054                         // should never happen
   2055                         mLog.w("Alarm wakelock still held but sent queue empty");
   2056                         mWakeLock.setWorkSource(null);
   2057                     }
   2058                 }
   2059             }
   2060         }
   2061     }
   2062 }
   2063