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