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