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