1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server; 18 19 import android.app.Activity; 20 import android.app.ActivityManager; 21 import android.app.ActivityManagerNative; 22 import android.app.AlarmManager; 23 import android.app.IAlarmManager; 24 import android.app.PendingIntent; 25 import android.content.BroadcastReceiver; 26 import android.content.Context; 27 import android.content.Intent; 28 import android.content.IntentFilter; 29 import android.content.pm.PackageManager; 30 import android.net.Uri; 31 import android.os.Binder; 32 import android.os.Bundle; 33 import android.os.Handler; 34 import android.os.IBinder; 35 import android.os.Message; 36 import android.os.PowerManager; 37 import android.os.SystemClock; 38 import android.os.SystemProperties; 39 import android.os.UserHandle; 40 import android.os.WorkSource; 41 import android.provider.Settings; 42 import android.text.TextUtils; 43 import android.text.format.DateFormat; 44 import android.util.ArrayMap; 45 import android.util.Log; 46 import android.util.Slog; 47 import android.util.SparseArray; 48 import android.util.SparseBooleanArray; 49 import android.util.TimeUtils; 50 51 import java.io.ByteArrayOutputStream; 52 import java.io.FileDescriptor; 53 import java.io.PrintWriter; 54 import java.text.SimpleDateFormat; 55 import java.util.ArrayList; 56 import java.util.Arrays; 57 import java.util.Calendar; 58 import java.util.Collections; 59 import java.util.Comparator; 60 import java.util.Date; 61 import java.util.HashMap; 62 import java.util.LinkedList; 63 import java.util.Locale; 64 import java.util.TimeZone; 65 66 import static android.app.AlarmManager.RTC_WAKEUP; 67 import static android.app.AlarmManager.RTC; 68 import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP; 69 import static android.app.AlarmManager.ELAPSED_REALTIME; 70 71 import com.android.internal.util.LocalLog; 72 73 class 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 windowLength == AlarmManager.WINDOW_EXACT, 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 // always update the kernel alarms, as a backstop against missed wakeups 1234 if (firstWakeup != null) { 1235 mNextWakeup = firstWakeup.start; 1236 setLocked(ELAPSED_REALTIME_WAKEUP, firstWakeup.start); 1237 } 1238 if (firstBatch != firstWakeup) { 1239 nextNonWakeup = firstBatch.start; 1240 } 1241 } 1242 if (mPendingNonWakeupAlarms.size() > 0) { 1243 if (nextNonWakeup == 0 || mNextNonWakeupDeliveryTime < nextNonWakeup) { 1244 nextNonWakeup = mNextNonWakeupDeliveryTime; 1245 } 1246 } 1247 // always update the kernel alarm, as a backstop against missed wakeups 1248 if (nextNonWakeup != 0) { 1249 mNextNonWakeup = nextNonWakeup; 1250 setLocked(ELAPSED_REALTIME, nextNonWakeup); 1251 } 1252 } 1253 1254 private void removeLocked(PendingIntent operation) { 1255 boolean didRemove = false; 1256 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) { 1257 Batch b = mAlarmBatches.get(i); 1258 didRemove |= b.remove(operation); 1259 if (b.size() == 0) { 1260 mAlarmBatches.remove(i); 1261 } 1262 } 1263 1264 if (didRemove) { 1265 if (DEBUG_BATCH) { 1266 Slog.v(TAG, "remove(operation) changed bounds; rebatching"); 1267 } 1268 rebatchAllAlarmsLocked(true); 1269 rescheduleKernelAlarmsLocked(); 1270 updateNextAlarmClockLocked(); 1271 } 1272 } 1273 1274 void removeLocked(String packageName) { 1275 boolean didRemove = false; 1276 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) { 1277 Batch b = mAlarmBatches.get(i); 1278 didRemove |= b.remove(packageName); 1279 if (b.size() == 0) { 1280 mAlarmBatches.remove(i); 1281 } 1282 } 1283 1284 if (didRemove) { 1285 if (DEBUG_BATCH) { 1286 Slog.v(TAG, "remove(package) changed bounds; rebatching"); 1287 } 1288 rebatchAllAlarmsLocked(true); 1289 rescheduleKernelAlarmsLocked(); 1290 updateNextAlarmClockLocked(); 1291 } 1292 } 1293 1294 void removeUserLocked(int userHandle) { 1295 boolean didRemove = false; 1296 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) { 1297 Batch b = mAlarmBatches.get(i); 1298 didRemove |= b.remove(userHandle); 1299 if (b.size() == 0) { 1300 mAlarmBatches.remove(i); 1301 } 1302 } 1303 1304 if (didRemove) { 1305 if (DEBUG_BATCH) { 1306 Slog.v(TAG, "remove(user) changed bounds; rebatching"); 1307 } 1308 rebatchAllAlarmsLocked(true); 1309 rescheduleKernelAlarmsLocked(); 1310 updateNextAlarmClockLocked(); 1311 } 1312 } 1313 1314 void interactiveStateChangedLocked(boolean interactive) { 1315 if (mInteractive != interactive) { 1316 mInteractive = interactive; 1317 final long nowELAPSED = SystemClock.elapsedRealtime(); 1318 if (interactive) { 1319 if (mPendingNonWakeupAlarms.size() > 0) { 1320 final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime; 1321 mTotalDelayTime += thisDelayTime; 1322 if (mMaxDelayTime < thisDelayTime) { 1323 mMaxDelayTime = thisDelayTime; 1324 } 1325 deliverAlarmsLocked(mPendingNonWakeupAlarms, nowELAPSED); 1326 mPendingNonWakeupAlarms.clear(); 1327 } 1328 if (mNonInteractiveStartTime > 0) { 1329 long dur = nowELAPSED - mNonInteractiveStartTime; 1330 if (dur > mNonInteractiveTime) { 1331 mNonInteractiveTime = dur; 1332 } 1333 } 1334 } else { 1335 mNonInteractiveStartTime = nowELAPSED; 1336 } 1337 } 1338 } 1339 1340 boolean lookForPackageLocked(String packageName) { 1341 for (int i = 0; i < mAlarmBatches.size(); i++) { 1342 Batch b = mAlarmBatches.get(i); 1343 if (b.hasPackage(packageName)) { 1344 return true; 1345 } 1346 } 1347 return false; 1348 } 1349 1350 private void setLocked(int type, long when) { 1351 if (mNativeData != 0) { 1352 // The kernel never triggers alarms with negative wakeup times 1353 // so we ensure they are positive. 1354 long alarmSeconds, alarmNanoseconds; 1355 if (when < 0) { 1356 alarmSeconds = 0; 1357 alarmNanoseconds = 0; 1358 } else { 1359 alarmSeconds = when / 1000; 1360 alarmNanoseconds = (when % 1000) * 1000 * 1000; 1361 } 1362 1363 set(mNativeData, type, alarmSeconds, alarmNanoseconds); 1364 } else { 1365 Message msg = Message.obtain(); 1366 msg.what = ALARM_EVENT; 1367 1368 mHandler.removeMessages(ALARM_EVENT); 1369 mHandler.sendMessageAtTime(msg, when); 1370 } 1371 } 1372 1373 private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list, 1374 String prefix, String label, long nowRTC, long nowELAPSED, SimpleDateFormat sdf) { 1375 for (int i=list.size()-1; i>=0; i--) { 1376 Alarm a = list.get(i); 1377 pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i); 1378 pw.print(": "); pw.println(a); 1379 a.dump(pw, prefix + " ", nowRTC, nowELAPSED, sdf); 1380 } 1381 } 1382 1383 private static final String labelForType(int type) { 1384 switch (type) { 1385 case RTC: return "RTC"; 1386 case RTC_WAKEUP : return "RTC_WAKEUP"; 1387 case ELAPSED_REALTIME : return "ELAPSED"; 1388 case ELAPSED_REALTIME_WAKEUP: return "ELAPSED_WAKEUP"; 1389 default: 1390 break; 1391 } 1392 return "--unknown--"; 1393 } 1394 1395 private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list, 1396 String prefix, long nowELAPSED, long nowRTC, SimpleDateFormat sdf) { 1397 for (int i=list.size()-1; i>=0; i--) { 1398 Alarm a = list.get(i); 1399 final String label = labelForType(a.type); 1400 pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i); 1401 pw.print(": "); pw.println(a); 1402 a.dump(pw, prefix + " ", nowRTC, nowELAPSED, sdf); 1403 } 1404 } 1405 1406 private native long init(); 1407 private native void close(long nativeData); 1408 private native void set(long nativeData, int type, long seconds, long nanoseconds); 1409 private native int waitForAlarm(long nativeData); 1410 private native int setKernelTime(long nativeData, long millis); 1411 private native int setKernelTimezone(long nativeData, int minuteswest); 1412 1413 boolean triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED, 1414 final long nowRTC) { 1415 boolean hasWakeup = false; 1416 // batches are temporally sorted, so we need only pull from the 1417 // start of the list until we either empty it or hit a batch 1418 // that is not yet deliverable 1419 while (mAlarmBatches.size() > 0) { 1420 Batch batch = mAlarmBatches.get(0); 1421 if (batch.start > nowELAPSED) { 1422 // Everything else is scheduled for the future 1423 break; 1424 } 1425 1426 // We will (re)schedule some alarms now; don't let that interfere 1427 // with delivery of this current batch 1428 mAlarmBatches.remove(0); 1429 1430 final int N = batch.size(); 1431 for (int i = 0; i < N; i++) { 1432 Alarm alarm = batch.get(i); 1433 alarm.count = 1; 1434 triggerList.add(alarm); 1435 1436 // Recurring alarms may have passed several alarm intervals while the 1437 // phone was asleep or off, so pass a trigger count when sending them. 1438 if (alarm.repeatInterval > 0) { 1439 // this adjustment will be zero if we're late by 1440 // less than one full repeat interval 1441 alarm.count += (nowELAPSED - alarm.whenElapsed) / alarm.repeatInterval; 1442 1443 // Also schedule its next recurrence 1444 final long delta = alarm.count * alarm.repeatInterval; 1445 final long nextElapsed = alarm.whenElapsed + delta; 1446 setImplLocked(alarm.type, alarm.when + delta, nextElapsed, alarm.windowLength, 1447 maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval), 1448 alarm.repeatInterval, alarm.operation, batch.standalone, true, 1449 alarm.workSource, alarm.alarmClock, alarm.userId); 1450 } 1451 1452 if (alarm.wakeup) { 1453 hasWakeup = true; 1454 } 1455 1456 // We removed an alarm clock. Let the caller recompute the next alarm clock. 1457 if (alarm.alarmClock != null) { 1458 mNextAlarmClockMayChange = true; 1459 } 1460 } 1461 } 1462 1463 // This is a new alarm delivery set; bump the sequence number to indicate that 1464 // all apps' alarm delivery classes should be recalculated. 1465 mCurrentSeq++; 1466 calculateDeliveryPriorities(triggerList); 1467 Collections.sort(triggerList, mAlarmDispatchComparator); 1468 1469 if (localLOGV) { 1470 for (int i=0; i<triggerList.size(); i++) { 1471 Slog.v(TAG, "Triggering alarm #" + i + ": " + triggerList.get(i)); 1472 } 1473 } 1474 1475 return hasWakeup; 1476 } 1477 1478 /** 1479 * This Comparator sorts Alarms into increasing time order. 1480 */ 1481 public static class IncreasingTimeOrder implements Comparator<Alarm> { 1482 public int compare(Alarm a1, Alarm a2) { 1483 long when1 = a1.when; 1484 long when2 = a2.when; 1485 if (when1 - when2 > 0) { 1486 return 1; 1487 } 1488 if (when1 - when2 < 0) { 1489 return -1; 1490 } 1491 return 0; 1492 } 1493 } 1494 1495 private static class Alarm { 1496 public final int type; 1497 public final boolean wakeup; 1498 public final PendingIntent operation; 1499 public final String tag; 1500 public final WorkSource workSource; 1501 public int count; 1502 public long when; 1503 public long windowLength; 1504 public long whenElapsed; // 'when' in the elapsed time base 1505 public long maxWhen; // also in the elapsed time base 1506 public long repeatInterval; 1507 public final AlarmManager.AlarmClockInfo alarmClock; 1508 public final int userId; 1509 public PriorityClass priorityClass; 1510 1511 public Alarm(int _type, long _when, long _whenElapsed, long _windowLength, long _maxWhen, 1512 long _interval, PendingIntent _op, WorkSource _ws, 1513 AlarmManager.AlarmClockInfo _info, int _userId) { 1514 type = _type; 1515 wakeup = _type == AlarmManager.ELAPSED_REALTIME_WAKEUP 1516 || _type == AlarmManager.RTC_WAKEUP; 1517 when = _when; 1518 whenElapsed = _whenElapsed; 1519 windowLength = _windowLength; 1520 maxWhen = _maxWhen; 1521 repeatInterval = _interval; 1522 operation = _op; 1523 tag = makeTag(_op, _type); 1524 workSource = _ws; 1525 alarmClock = _info; 1526 userId = _userId; 1527 } 1528 1529 public static String makeTag(PendingIntent pi, int type) { 1530 return pi.getTag(type == ELAPSED_REALTIME_WAKEUP || type == RTC_WAKEUP 1531 ? "*walarm*:" : "*alarm*:"); 1532 } 1533 1534 @Override 1535 public String toString() { 1536 StringBuilder sb = new StringBuilder(128); 1537 sb.append("Alarm{"); 1538 sb.append(Integer.toHexString(System.identityHashCode(this))); 1539 sb.append(" type "); 1540 sb.append(type); 1541 sb.append(" when "); 1542 sb.append(when); 1543 sb.append(" "); 1544 sb.append(operation.getTargetPackage()); 1545 sb.append('}'); 1546 return sb.toString(); 1547 } 1548 1549 public void dump(PrintWriter pw, String prefix, long nowRTC, long nowELAPSED, 1550 SimpleDateFormat sdf) { 1551 final boolean isRtc = (type == RTC || type == RTC_WAKEUP); 1552 pw.print(prefix); pw.print("tag="); pw.println(tag); 1553 pw.print(prefix); pw.print("type="); pw.print(type); 1554 pw.print(" whenElapsed="); TimeUtils.formatDuration(whenElapsed, 1555 nowELAPSED, pw); 1556 if (isRtc) { 1557 pw.print(" when="); pw.print(sdf.format(new Date(when))); 1558 } else { 1559 pw.print(" when="); TimeUtils.formatDuration(when, nowELAPSED, pw); 1560 } 1561 pw.println(); 1562 pw.print(prefix); pw.print("window="); pw.print(windowLength); 1563 pw.print(" repeatInterval="); pw.print(repeatInterval); 1564 pw.print(" count="); pw.println(count); 1565 pw.print(prefix); pw.print("operation="); pw.println(operation); 1566 } 1567 } 1568 1569 void recordWakeupAlarms(ArrayList<Batch> batches, long nowELAPSED, long nowRTC) { 1570 final int numBatches = batches.size(); 1571 for (int nextBatch = 0; nextBatch < numBatches; nextBatch++) { 1572 Batch b = batches.get(nextBatch); 1573 if (b.start > nowELAPSED) { 1574 break; 1575 } 1576 1577 final int numAlarms = b.alarms.size(); 1578 for (int nextAlarm = 0; nextAlarm < numAlarms; nextAlarm++) { 1579 Alarm a = b.alarms.get(nextAlarm); 1580 WakeupEvent e = new WakeupEvent(nowRTC, 1581 a.operation.getCreatorUid(), 1582 a.operation.getIntent().getAction()); 1583 mRecentWakeups.add(e); 1584 } 1585 } 1586 } 1587 1588 long currentNonWakeupFuzzLocked(long nowELAPSED) { 1589 long timeSinceOn = nowELAPSED - mNonInteractiveStartTime; 1590 if (timeSinceOn < 5*60*1000) { 1591 // If the screen has been off for 5 minutes, only delay by at most two minutes. 1592 return 2*60*1000; 1593 } else if (timeSinceOn < 30*60*1000) { 1594 // If the screen has been off for 30 minutes, only delay by at most 15 minutes. 1595 return 15*60*1000; 1596 } else { 1597 // Otherwise, we will delay by at most an hour. 1598 return 60*60*1000; 1599 } 1600 } 1601 1602 boolean checkAllowNonWakeupDelayLocked(long nowELAPSED) { 1603 if (mInteractive) { 1604 return false; 1605 } 1606 if (mLastAlarmDeliveryTime <= 0) { 1607 return false; 1608 } 1609 if (mPendingNonWakeupAlarms.size() > 0 && mNextNonWakeupDeliveryTime > nowELAPSED) { 1610 // This is just a little paranoia, if somehow we have pending non-wakeup alarms 1611 // and the next delivery time is in the past, then just deliver them all. This 1612 // avoids bugs where we get stuck in a loop trying to poll for alarms. 1613 return false; 1614 } 1615 long timeSinceLast = nowELAPSED - mLastAlarmDeliveryTime; 1616 return timeSinceLast <= currentNonWakeupFuzzLocked(nowELAPSED); 1617 } 1618 1619 void deliverAlarmsLocked(ArrayList<Alarm> triggerList, long nowELAPSED) { 1620 mLastAlarmDeliveryTime = nowELAPSED; 1621 for (int i=0; i<triggerList.size(); i++) { 1622 Alarm alarm = triggerList.get(i); 1623 try { 1624 if (localLOGV) { 1625 Slog.v(TAG, "sending alarm " + alarm); 1626 } 1627 alarm.operation.send(getContext(), 0, 1628 mBackgroundIntent.putExtra( 1629 Intent.EXTRA_ALARM_COUNT, alarm.count), 1630 mResultReceiver, mHandler); 1631 1632 // we have an active broadcast so stay awake. 1633 if (mBroadcastRefCount == 0) { 1634 setWakelockWorkSource(alarm.operation, alarm.workSource, 1635 alarm.type, alarm.tag, true); 1636 mWakeLock.acquire(); 1637 } 1638 final InFlight inflight = new InFlight(AlarmManagerService.this, 1639 alarm.operation, alarm.workSource, alarm.type, alarm.tag); 1640 mInFlight.add(inflight); 1641 mBroadcastRefCount++; 1642 1643 final BroadcastStats bs = inflight.mBroadcastStats; 1644 bs.count++; 1645 if (bs.nesting == 0) { 1646 bs.nesting = 1; 1647 bs.startTime = nowELAPSED; 1648 } else { 1649 bs.nesting++; 1650 } 1651 final FilterStats fs = inflight.mFilterStats; 1652 fs.count++; 1653 if (fs.nesting == 0) { 1654 fs.nesting = 1; 1655 fs.startTime = nowELAPSED; 1656 } else { 1657 fs.nesting++; 1658 } 1659 if (alarm.type == ELAPSED_REALTIME_WAKEUP 1660 || alarm.type == RTC_WAKEUP) { 1661 bs.numWakeup++; 1662 fs.numWakeup++; 1663 if (alarm.workSource != null && alarm.workSource.size() > 0) { 1664 for (int wi=0; wi<alarm.workSource.size(); wi++) { 1665 ActivityManagerNative.noteWakeupAlarm( 1666 alarm.operation, alarm.workSource.get(wi), 1667 alarm.workSource.getName(wi)); 1668 } 1669 } else { 1670 ActivityManagerNative.noteWakeupAlarm( 1671 alarm.operation, -1, null); 1672 } 1673 } 1674 } catch (PendingIntent.CanceledException e) { 1675 if (alarm.repeatInterval > 0) { 1676 // This IntentSender is no longer valid, but this 1677 // is a repeating alarm, so toss the hoser. 1678 removeImpl(alarm.operation); 1679 } 1680 } catch (RuntimeException e) { 1681 Slog.w(TAG, "Failure sending alarm.", e); 1682 } 1683 } 1684 } 1685 1686 private class AlarmThread extends Thread 1687 { 1688 public AlarmThread() 1689 { 1690 super("AlarmManager"); 1691 } 1692 1693 public void run() 1694 { 1695 ArrayList<Alarm> triggerList = new ArrayList<Alarm>(); 1696 1697 while (true) 1698 { 1699 int result = waitForAlarm(mNativeData); 1700 1701 triggerList.clear(); 1702 1703 if ((result & TIME_CHANGED_MASK) != 0) { 1704 if (DEBUG_BATCH) { 1705 Slog.v(TAG, "Time changed notification from kernel; rebatching"); 1706 } 1707 removeImpl(mTimeTickSender); 1708 rebatchAllAlarms(); 1709 mClockReceiver.scheduleTimeTickEvent(); 1710 synchronized (mLock) { 1711 mNumTimeChanged++; 1712 } 1713 Intent intent = new Intent(Intent.ACTION_TIME_CHANGED); 1714 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING 1715 | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1716 getContext().sendBroadcastAsUser(intent, UserHandle.ALL); 1717 } 1718 1719 synchronized (mLock) { 1720 final long nowRTC = System.currentTimeMillis(); 1721 final long nowELAPSED = SystemClock.elapsedRealtime(); 1722 if (localLOGV) Slog.v( 1723 TAG, "Checking for alarms... rtc=" + nowRTC 1724 + ", elapsed=" + nowELAPSED); 1725 1726 if (WAKEUP_STATS) { 1727 if ((result & IS_WAKEUP_MASK) != 0) { 1728 long newEarliest = nowRTC - RECENT_WAKEUP_PERIOD; 1729 int n = 0; 1730 for (WakeupEvent event : mRecentWakeups) { 1731 if (event.when > newEarliest) break; 1732 n++; // number of now-stale entries at the list head 1733 } 1734 for (int i = 0; i < n; i++) { 1735 mRecentWakeups.remove(); 1736 } 1737 1738 recordWakeupAlarms(mAlarmBatches, nowELAPSED, nowRTC); 1739 } 1740 } 1741 1742 boolean hasWakeup = triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC); 1743 if (!hasWakeup && checkAllowNonWakeupDelayLocked(nowELAPSED)) { 1744 // if there are no wakeup alarms and the screen is off, we can 1745 // delay what we have so far until the future. 1746 if (mPendingNonWakeupAlarms.size() == 0) { 1747 mStartCurrentDelayTime = nowELAPSED; 1748 mNextNonWakeupDeliveryTime = nowELAPSED 1749 + ((currentNonWakeupFuzzLocked(nowELAPSED)*3)/2); 1750 } 1751 mPendingNonWakeupAlarms.addAll(triggerList); 1752 mNumDelayedAlarms += triggerList.size(); 1753 rescheduleKernelAlarmsLocked(); 1754 updateNextAlarmClockLocked(); 1755 } else { 1756 // now deliver the alarm intents; if there are pending non-wakeup 1757 // alarms, we need to merge them in to the list. note we don't 1758 // just deliver them first because we generally want non-wakeup 1759 // alarms delivered after wakeup alarms. 1760 rescheduleKernelAlarmsLocked(); 1761 updateNextAlarmClockLocked(); 1762 if (mPendingNonWakeupAlarms.size() > 0) { 1763 calculateDeliveryPriorities(mPendingNonWakeupAlarms); 1764 triggerList.addAll(mPendingNonWakeupAlarms); 1765 Collections.sort(triggerList, mAlarmDispatchComparator); 1766 final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime; 1767 mTotalDelayTime += thisDelayTime; 1768 if (mMaxDelayTime < thisDelayTime) { 1769 mMaxDelayTime = thisDelayTime; 1770 } 1771 mPendingNonWakeupAlarms.clear(); 1772 } 1773 deliverAlarmsLocked(triggerList, nowELAPSED); 1774 } 1775 } 1776 } 1777 } 1778 } 1779 1780 /** 1781 * Attribute blame for a WakeLock. 1782 * @param pi PendingIntent to attribute blame to if ws is null. 1783 * @param ws WorkSource to attribute blame. 1784 */ 1785 void setWakelockWorkSource(PendingIntent pi, WorkSource ws, int type, String tag, 1786 boolean first) { 1787 try { 1788 final boolean unimportant = pi == mTimeTickSender; 1789 mWakeLock.setUnimportantForLogging(unimportant); 1790 if (first || mLastWakeLockUnimportantForLogging) { 1791 mWakeLock.setHistoryTag(tag); 1792 } else { 1793 mWakeLock.setHistoryTag(null); 1794 } 1795 mLastWakeLockUnimportantForLogging = unimportant; 1796 if (ws != null) { 1797 mWakeLock.setWorkSource(ws); 1798 return; 1799 } 1800 1801 final int uid = ActivityManagerNative.getDefault() 1802 .getUidForIntentSender(pi.getTarget()); 1803 if (uid >= 0) { 1804 mWakeLock.setWorkSource(new WorkSource(uid)); 1805 return; 1806 } 1807 } catch (Exception e) { 1808 } 1809 1810 // Something went wrong; fall back to attributing the lock to the OS 1811 mWakeLock.setWorkSource(null); 1812 } 1813 1814 private class AlarmHandler extends Handler { 1815 public static final int ALARM_EVENT = 1; 1816 public static final int MINUTE_CHANGE_EVENT = 2; 1817 public static final int DATE_CHANGE_EVENT = 3; 1818 public static final int SEND_NEXT_ALARM_CLOCK_CHANGED = 4; 1819 1820 public AlarmHandler() { 1821 } 1822 1823 public void handleMessage(Message msg) { 1824 if (msg.what == ALARM_EVENT) { 1825 ArrayList<Alarm> triggerList = new ArrayList<Alarm>(); 1826 synchronized (mLock) { 1827 final long nowRTC = System.currentTimeMillis(); 1828 final long nowELAPSED = SystemClock.elapsedRealtime(); 1829 triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC); 1830 updateNextAlarmClockLocked(); 1831 } 1832 1833 // now trigger the alarms without the lock held 1834 for (int i=0; i<triggerList.size(); i++) { 1835 Alarm alarm = triggerList.get(i); 1836 try { 1837 alarm.operation.send(); 1838 } catch (PendingIntent.CanceledException e) { 1839 if (alarm.repeatInterval > 0) { 1840 // This IntentSender is no longer valid, but this 1841 // is a repeating alarm, so toss the hoser. 1842 removeImpl(alarm.operation); 1843 } 1844 } 1845 } 1846 } else if (msg.what == SEND_NEXT_ALARM_CLOCK_CHANGED) { 1847 sendNextAlarmClockChanged(); 1848 } 1849 } 1850 } 1851 1852 class ClockReceiver extends BroadcastReceiver { 1853 public ClockReceiver() { 1854 IntentFilter filter = new IntentFilter(); 1855 filter.addAction(Intent.ACTION_TIME_TICK); 1856 filter.addAction(Intent.ACTION_DATE_CHANGED); 1857 getContext().registerReceiver(this, filter); 1858 } 1859 1860 @Override 1861 public void onReceive(Context context, Intent intent) { 1862 if (intent.getAction().equals(Intent.ACTION_TIME_TICK)) { 1863 if (DEBUG_BATCH) { 1864 Slog.v(TAG, "Received TIME_TICK alarm; rescheduling"); 1865 } 1866 scheduleTimeTickEvent(); 1867 } else if (intent.getAction().equals(Intent.ACTION_DATE_CHANGED)) { 1868 // Since the kernel does not keep track of DST, we need to 1869 // reset the TZ information at the beginning of each day 1870 // based off of the current Zone gmt offset + userspace tracked 1871 // daylight savings information. 1872 TimeZone zone = TimeZone.getTimeZone(SystemProperties.get(TIMEZONE_PROPERTY)); 1873 int gmtOffset = zone.getOffset(System.currentTimeMillis()); 1874 setKernelTimezone(mNativeData, -(gmtOffset / 60000)); 1875 scheduleDateChangedEvent(); 1876 } 1877 } 1878 1879 public void scheduleTimeTickEvent() { 1880 final long currentTime = System.currentTimeMillis(); 1881 final long nextTime = 60000 * ((currentTime / 60000) + 1); 1882 1883 // Schedule this event for the amount of time that it would take to get to 1884 // the top of the next minute. 1885 final long tickEventDelay = nextTime - currentTime; 1886 1887 final WorkSource workSource = null; // Let system take blame for time tick events. 1888 setImpl(ELAPSED_REALTIME, SystemClock.elapsedRealtime() + tickEventDelay, 0, 1889 0, mTimeTickSender, true, workSource, null); 1890 } 1891 1892 public void scheduleDateChangedEvent() { 1893 Calendar calendar = Calendar.getInstance(); 1894 calendar.setTimeInMillis(System.currentTimeMillis()); 1895 calendar.set(Calendar.HOUR, 0); 1896 calendar.set(Calendar.MINUTE, 0); 1897 calendar.set(Calendar.SECOND, 0); 1898 calendar.set(Calendar.MILLISECOND, 0); 1899 calendar.add(Calendar.DAY_OF_MONTH, 1); 1900 1901 final WorkSource workSource = null; // Let system take blame for date change events. 1902 setImpl(RTC, calendar.getTimeInMillis(), 0, 0, mDateChangeSender, true, workSource, 1903 null); 1904 } 1905 } 1906 1907 class InteractiveStateReceiver extends BroadcastReceiver { 1908 public InteractiveStateReceiver() { 1909 IntentFilter filter = new IntentFilter(); 1910 filter.addAction(Intent.ACTION_SCREEN_OFF); 1911 filter.addAction(Intent.ACTION_SCREEN_ON); 1912 filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); 1913 getContext().registerReceiver(this, filter); 1914 } 1915 1916 @Override 1917 public void onReceive(Context context, Intent intent) { 1918 synchronized (mLock) { 1919 interactiveStateChangedLocked(Intent.ACTION_SCREEN_ON.equals(intent.getAction())); 1920 } 1921 } 1922 } 1923 1924 class UninstallReceiver extends BroadcastReceiver { 1925 public UninstallReceiver() { 1926 IntentFilter filter = new IntentFilter(); 1927 filter.addAction(Intent.ACTION_PACKAGE_REMOVED); 1928 filter.addAction(Intent.ACTION_PACKAGE_RESTARTED); 1929 filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART); 1930 filter.addDataScheme("package"); 1931 getContext().registerReceiver(this, filter); 1932 // Register for events related to sdcard installation. 1933 IntentFilter sdFilter = new IntentFilter(); 1934 sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); 1935 sdFilter.addAction(Intent.ACTION_USER_STOPPED); 1936 getContext().registerReceiver(this, sdFilter); 1937 } 1938 1939 @Override 1940 public void onReceive(Context context, Intent intent) { 1941 synchronized (mLock) { 1942 String action = intent.getAction(); 1943 String pkgList[] = null; 1944 if (Intent.ACTION_QUERY_PACKAGE_RESTART.equals(action)) { 1945 pkgList = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES); 1946 for (String packageName : pkgList) { 1947 if (lookForPackageLocked(packageName)) { 1948 setResultCode(Activity.RESULT_OK); 1949 return; 1950 } 1951 } 1952 return; 1953 } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) { 1954 pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); 1955 } else if (Intent.ACTION_USER_STOPPED.equals(action)) { 1956 int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); 1957 if (userHandle >= 0) { 1958 removeUserLocked(userHandle); 1959 } 1960 } else { 1961 if (Intent.ACTION_PACKAGE_REMOVED.equals(action) 1962 && intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { 1963 // This package is being updated; don't kill its alarms. 1964 return; 1965 } 1966 Uri data = intent.getData(); 1967 if (data != null) { 1968 String pkg = data.getSchemeSpecificPart(); 1969 if (pkg != null) { 1970 pkgList = new String[]{pkg}; 1971 } 1972 } 1973 } 1974 if (pkgList != null && (pkgList.length > 0)) { 1975 for (String pkg : pkgList) { 1976 removeLocked(pkg); 1977 mPriorities.remove(pkg); 1978 for (int i=mBroadcastStats.size()-1; i>=0; i--) { 1979 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(i); 1980 if (uidStats.remove(pkg) != null) { 1981 if (uidStats.size() <= 0) { 1982 mBroadcastStats.removeAt(i); 1983 } 1984 } 1985 } 1986 } 1987 } 1988 } 1989 } 1990 } 1991 1992 private final BroadcastStats getStatsLocked(PendingIntent pi) { 1993 String pkg = pi.getCreatorPackage(); 1994 int uid = pi.getCreatorUid(); 1995 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.get(uid); 1996 if (uidStats == null) { 1997 uidStats = new ArrayMap<String, BroadcastStats>(); 1998 mBroadcastStats.put(uid, uidStats); 1999 } 2000 BroadcastStats bs = uidStats.get(pkg); 2001 if (bs == null) { 2002 bs = new BroadcastStats(uid, pkg); 2003 uidStats.put(pkg, bs); 2004 } 2005 return bs; 2006 } 2007 2008 class ResultReceiver implements PendingIntent.OnFinished { 2009 public void onSendFinished(PendingIntent pi, Intent intent, int resultCode, 2010 String resultData, Bundle resultExtras) { 2011 synchronized (mLock) { 2012 InFlight inflight = null; 2013 for (int i=0; i<mInFlight.size(); i++) { 2014 if (mInFlight.get(i).mPendingIntent == pi) { 2015 inflight = mInFlight.remove(i); 2016 break; 2017 } 2018 } 2019 if (inflight != null) { 2020 final long nowELAPSED = SystemClock.elapsedRealtime(); 2021 BroadcastStats bs = inflight.mBroadcastStats; 2022 bs.nesting--; 2023 if (bs.nesting <= 0) { 2024 bs.nesting = 0; 2025 bs.aggregateTime += nowELAPSED - bs.startTime; 2026 } 2027 FilterStats fs = inflight.mFilterStats; 2028 fs.nesting--; 2029 if (fs.nesting <= 0) { 2030 fs.nesting = 0; 2031 fs.aggregateTime += nowELAPSED - fs.startTime; 2032 } 2033 } else { 2034 mLog.w("No in-flight alarm for " + pi + " " + intent); 2035 } 2036 mBroadcastRefCount--; 2037 if (mBroadcastRefCount == 0) { 2038 mWakeLock.release(); 2039 if (mInFlight.size() > 0) { 2040 mLog.w("Finished all broadcasts with " + mInFlight.size() 2041 + " remaining inflights"); 2042 for (int i=0; i<mInFlight.size(); i++) { 2043 mLog.w(" Remaining #" + i + ": " + mInFlight.get(i)); 2044 } 2045 mInFlight.clear(); 2046 } 2047 } else { 2048 // the next of our alarms is now in flight. reattribute the wakelock. 2049 if (mInFlight.size() > 0) { 2050 InFlight inFlight = mInFlight.get(0); 2051 setWakelockWorkSource(inFlight.mPendingIntent, inFlight.mWorkSource, 2052 inFlight.mAlarmType, inFlight.mTag, false); 2053 } else { 2054 // should never happen 2055 mLog.w("Alarm wakelock still held but sent queue empty"); 2056 mWakeLock.setWorkSource(null); 2057 } 2058 } 2059 } 2060 } 2061 } 2062 } 2063