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