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