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