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