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