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