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