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