1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server; 18 19 import android.app.Activity; 20 import android.app.ActivityManager; 21 import android.app.ActivityManagerNative; 22 import android.app.AlarmManager; 23 import android.app.AppOpsManager; 24 import android.app.BroadcastOptions; 25 import android.app.IAlarmCompleteListener; 26 import android.app.IAlarmListener; 27 import android.app.IAlarmManager; 28 import android.app.IUidObserver; 29 import android.app.PendingIntent; 30 import android.content.BroadcastReceiver; 31 import android.content.ContentResolver; 32 import android.content.Context; 33 import android.content.Intent; 34 import android.content.IntentFilter; 35 import android.content.pm.PackageManager; 36 import android.database.ContentObserver; 37 import android.net.Uri; 38 import android.os.Binder; 39 import android.os.Bundle; 40 import android.os.Handler; 41 import android.os.IBinder; 42 import android.os.Message; 43 import android.os.PowerManager; 44 import android.os.Process; 45 import android.os.RemoteException; 46 import android.os.SystemClock; 47 import android.os.SystemProperties; 48 import android.os.UserHandle; 49 import android.os.WorkSource; 50 import android.provider.Settings; 51 import android.text.TextUtils; 52 import android.text.format.DateFormat; 53 import android.util.ArrayMap; 54 import android.util.KeyValueListParser; 55 import android.util.Log; 56 import android.util.Slog; 57 import android.util.SparseArray; 58 import android.util.SparseBooleanArray; 59 import android.util.SparseLongArray; 60 import android.util.TimeUtils; 61 62 import java.io.ByteArrayOutputStream; 63 import java.io.FileDescriptor; 64 import java.io.PrintWriter; 65 import java.text.SimpleDateFormat; 66 import java.util.ArrayList; 67 import java.util.Arrays; 68 import java.util.Calendar; 69 import java.util.Collections; 70 import java.util.Comparator; 71 import java.util.Date; 72 import java.util.HashMap; 73 import java.util.LinkedList; 74 import java.util.Locale; 75 import java.util.Random; 76 import java.util.TimeZone; 77 import java.util.TreeSet; 78 79 import static android.app.AlarmManager.RTC_WAKEUP; 80 import static android.app.AlarmManager.RTC; 81 import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP; 82 import static android.app.AlarmManager.ELAPSED_REALTIME; 83 84 import com.android.internal.util.LocalLog; 85 86 class 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 AlarmManager.AlarmClockInfo current = mNextAlarmClockForUser.get(userId); 1736 1737 if (DEBUG_ALARM_CLOCK) { 1738 Log.v(TAG, "Found AlarmClockInfo " + a.alarmClock + " at " + 1739 formatNextAlarm(getContext(), a.alarmClock, userId) + 1740 " for user " + userId); 1741 } 1742 1743 // Alarms and batches are sorted by time, no need to compare times here. 1744 if (nextForUser.get(userId) == null) { 1745 nextForUser.put(userId, a.alarmClock); 1746 } else if (a.alarmClock.equals(current) 1747 && current.getTriggerTime() <= nextForUser.get(userId).getTriggerTime()) { 1748 // same/earlier time and it's the one we cited before, so stick with it 1749 nextForUser.put(userId, current); 1750 } 1751 } 1752 } 1753 } 1754 1755 // Update mNextAlarmForUser with new values. 1756 final int NN = nextForUser.size(); 1757 for (int i = 0; i < NN; i++) { 1758 AlarmManager.AlarmClockInfo newAlarm = nextForUser.valueAt(i); 1759 int userId = nextForUser.keyAt(i); 1760 AlarmManager.AlarmClockInfo currentAlarm = mNextAlarmClockForUser.get(userId); 1761 if (!newAlarm.equals(currentAlarm)) { 1762 updateNextAlarmInfoForUserLocked(userId, newAlarm); 1763 } 1764 } 1765 1766 // Remove users without any alarm clocks scheduled. 1767 final int NNN = mNextAlarmClockForUser.size(); 1768 for (int i = NNN - 1; i >= 0; i--) { 1769 int userId = mNextAlarmClockForUser.keyAt(i); 1770 if (nextForUser.get(userId) == null) { 1771 updateNextAlarmInfoForUserLocked(userId, null); 1772 } 1773 } 1774 } 1775 1776 private void updateNextAlarmInfoForUserLocked(int userId, 1777 AlarmManager.AlarmClockInfo alarmClock) { 1778 if (alarmClock != null) { 1779 if (DEBUG_ALARM_CLOCK) { 1780 Log.v(TAG, "Next AlarmClockInfoForUser(" + userId + "): " + 1781 formatNextAlarm(getContext(), alarmClock, userId)); 1782 } 1783 mNextAlarmClockForUser.put(userId, alarmClock); 1784 } else { 1785 if (DEBUG_ALARM_CLOCK) { 1786 Log.v(TAG, "Next AlarmClockInfoForUser(" + userId + "): None"); 1787 } 1788 mNextAlarmClockForUser.remove(userId); 1789 } 1790 1791 mPendingSendNextAlarmClockChangedForUser.put(userId, true); 1792 mHandler.removeMessages(AlarmHandler.SEND_NEXT_ALARM_CLOCK_CHANGED); 1793 mHandler.sendEmptyMessage(AlarmHandler.SEND_NEXT_ALARM_CLOCK_CHANGED); 1794 } 1795 1796 /** 1797 * Updates NEXT_ALARM_FORMATTED and sends NEXT_ALARM_CLOCK_CHANGED_INTENT for all users 1798 * for which alarm clocks have changed since the last call to this. 1799 * 1800 * Do not call with a lock held. Only call from mHandler's thread. 1801 * 1802 * @see AlarmHandler#SEND_NEXT_ALARM_CLOCK_CHANGED 1803 */ 1804 private void sendNextAlarmClockChanged() { 1805 SparseArray<AlarmManager.AlarmClockInfo> pendingUsers = mHandlerSparseAlarmClockArray; 1806 pendingUsers.clear(); 1807 1808 synchronized (mLock) { 1809 final int N = mPendingSendNextAlarmClockChangedForUser.size(); 1810 for (int i = 0; i < N; i++) { 1811 int userId = mPendingSendNextAlarmClockChangedForUser.keyAt(i); 1812 pendingUsers.append(userId, mNextAlarmClockForUser.get(userId)); 1813 } 1814 mPendingSendNextAlarmClockChangedForUser.clear(); 1815 } 1816 1817 final int N = pendingUsers.size(); 1818 for (int i = 0; i < N; i++) { 1819 int userId = pendingUsers.keyAt(i); 1820 AlarmManager.AlarmClockInfo alarmClock = pendingUsers.valueAt(i); 1821 Settings.System.putStringForUser(getContext().getContentResolver(), 1822 Settings.System.NEXT_ALARM_FORMATTED, 1823 formatNextAlarm(getContext(), alarmClock, userId), 1824 userId); 1825 1826 getContext().sendBroadcastAsUser(NEXT_ALARM_CLOCK_CHANGED_INTENT, 1827 new UserHandle(userId)); 1828 } 1829 } 1830 1831 /** 1832 * Formats an alarm like platform/packages/apps/DeskClock used to. 1833 */ 1834 private static String formatNextAlarm(final Context context, AlarmManager.AlarmClockInfo info, 1835 int userId) { 1836 String skeleton = DateFormat.is24HourFormat(context, userId) ? "EHm" : "Ehma"; 1837 String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton); 1838 return (info == null) ? "" : 1839 DateFormat.format(pattern, info.getTriggerTime()).toString(); 1840 } 1841 1842 void rescheduleKernelAlarmsLocked() { 1843 // Schedule the next upcoming wakeup alarm. If there is a deliverable batch 1844 // prior to that which contains no wakeups, we schedule that as well. 1845 long nextNonWakeup = 0; 1846 if (mAlarmBatches.size() > 0) { 1847 final Batch firstWakeup = findFirstWakeupBatchLocked(); 1848 final Batch firstBatch = mAlarmBatches.get(0); 1849 if (firstWakeup != null && mNextWakeup != firstWakeup.start) { 1850 mNextWakeup = firstWakeup.start; 1851 mLastWakeupSet = SystemClock.elapsedRealtime(); 1852 setLocked(ELAPSED_REALTIME_WAKEUP, firstWakeup.start); 1853 } 1854 if (firstBatch != firstWakeup) { 1855 nextNonWakeup = firstBatch.start; 1856 } 1857 } 1858 if (mPendingNonWakeupAlarms.size() > 0) { 1859 if (nextNonWakeup == 0 || mNextNonWakeupDeliveryTime < nextNonWakeup) { 1860 nextNonWakeup = mNextNonWakeupDeliveryTime; 1861 } 1862 } 1863 if (nextNonWakeup != 0 && mNextNonWakeup != nextNonWakeup) { 1864 mNextNonWakeup = nextNonWakeup; 1865 setLocked(ELAPSED_REALTIME, nextNonWakeup); 1866 } 1867 } 1868 1869 private void removeLocked(PendingIntent operation, IAlarmListener directReceiver) { 1870 boolean didRemove = false; 1871 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) { 1872 Batch b = mAlarmBatches.get(i); 1873 didRemove |= b.remove(operation, directReceiver); 1874 if (b.size() == 0) { 1875 mAlarmBatches.remove(i); 1876 } 1877 } 1878 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) { 1879 if (mPendingWhileIdleAlarms.get(i).matches(operation, directReceiver)) { 1880 // Don't set didRemove, since this doesn't impact the scheduled alarms. 1881 mPendingWhileIdleAlarms.remove(i); 1882 } 1883 } 1884 1885 if (didRemove) { 1886 if (DEBUG_BATCH) { 1887 Slog.v(TAG, "remove(operation) changed bounds; rebatching"); 1888 } 1889 boolean restorePending = false; 1890 if (mPendingIdleUntil != null && mPendingIdleUntil.matches(operation, directReceiver)) { 1891 mPendingIdleUntil = null; 1892 restorePending = true; 1893 } 1894 if (mNextWakeFromIdle != null && mNextWakeFromIdle.matches(operation, directReceiver)) { 1895 mNextWakeFromIdle = null; 1896 } 1897 rebatchAllAlarmsLocked(true); 1898 if (restorePending) { 1899 restorePendingWhileIdleAlarmsLocked(); 1900 } 1901 updateNextAlarmClockLocked(); 1902 } 1903 } 1904 1905 void removeLocked(String packageName) { 1906 boolean didRemove = false; 1907 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) { 1908 Batch b = mAlarmBatches.get(i); 1909 didRemove |= b.remove(packageName); 1910 if (b.size() == 0) { 1911 mAlarmBatches.remove(i); 1912 } 1913 } 1914 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) { 1915 final Alarm a = mPendingWhileIdleAlarms.get(i); 1916 if (a.matches(packageName)) { 1917 // Don't set didRemove, since this doesn't impact the scheduled alarms. 1918 mPendingWhileIdleAlarms.remove(i); 1919 } 1920 } 1921 1922 if (didRemove) { 1923 if (DEBUG_BATCH) { 1924 Slog.v(TAG, "remove(package) changed bounds; rebatching"); 1925 } 1926 rebatchAllAlarmsLocked(true); 1927 rescheduleKernelAlarmsLocked(); 1928 updateNextAlarmClockLocked(); 1929 } 1930 } 1931 1932 void removeForStoppedLocked(int uid) { 1933 boolean didRemove = false; 1934 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) { 1935 Batch b = mAlarmBatches.get(i); 1936 didRemove |= b.removeForStopped(uid); 1937 if (b.size() == 0) { 1938 mAlarmBatches.remove(i); 1939 } 1940 } 1941 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) { 1942 final Alarm a = mPendingWhileIdleAlarms.get(i); 1943 try { 1944 if (a.uid == uid && ActivityManagerNative.getDefault().getAppStartMode( 1945 uid, a.packageName) == ActivityManager.APP_START_MODE_DISABLED) { 1946 // Don't set didRemove, since this doesn't impact the scheduled alarms. 1947 mPendingWhileIdleAlarms.remove(i); 1948 } 1949 } catch (RemoteException e) { 1950 } 1951 } 1952 1953 if (didRemove) { 1954 if (DEBUG_BATCH) { 1955 Slog.v(TAG, "remove(package) changed bounds; rebatching"); 1956 } 1957 rebatchAllAlarmsLocked(true); 1958 rescheduleKernelAlarmsLocked(); 1959 updateNextAlarmClockLocked(); 1960 } 1961 } 1962 1963 void removeUserLocked(int userHandle) { 1964 boolean didRemove = false; 1965 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) { 1966 Batch b = mAlarmBatches.get(i); 1967 didRemove |= b.remove(userHandle); 1968 if (b.size() == 0) { 1969 mAlarmBatches.remove(i); 1970 } 1971 } 1972 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) { 1973 if (UserHandle.getUserId(mPendingWhileIdleAlarms.get(i).creatorUid) 1974 == userHandle) { 1975 // Don't set didRemove, since this doesn't impact the scheduled alarms. 1976 mPendingWhileIdleAlarms.remove(i); 1977 } 1978 } 1979 for (int i = mLastAllowWhileIdleDispatch.size() - 1; i >= 0; i--) { 1980 if (UserHandle.getUserId(mLastAllowWhileIdleDispatch.keyAt(i)) == userHandle) { 1981 mLastAllowWhileIdleDispatch.removeAt(i); 1982 } 1983 } 1984 1985 if (didRemove) { 1986 if (DEBUG_BATCH) { 1987 Slog.v(TAG, "remove(user) changed bounds; rebatching"); 1988 } 1989 rebatchAllAlarmsLocked(true); 1990 rescheduleKernelAlarmsLocked(); 1991 updateNextAlarmClockLocked(); 1992 } 1993 } 1994 1995 void interactiveStateChangedLocked(boolean interactive) { 1996 if (mInteractive != interactive) { 1997 mInteractive = interactive; 1998 final long nowELAPSED = SystemClock.elapsedRealtime(); 1999 if (interactive) { 2000 if (mPendingNonWakeupAlarms.size() > 0) { 2001 final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime; 2002 mTotalDelayTime += thisDelayTime; 2003 if (mMaxDelayTime < thisDelayTime) { 2004 mMaxDelayTime = thisDelayTime; 2005 } 2006 deliverAlarmsLocked(mPendingNonWakeupAlarms, nowELAPSED); 2007 mPendingNonWakeupAlarms.clear(); 2008 } 2009 if (mNonInteractiveStartTime > 0) { 2010 long dur = nowELAPSED - mNonInteractiveStartTime; 2011 if (dur > mNonInteractiveTime) { 2012 mNonInteractiveTime = dur; 2013 } 2014 } 2015 } else { 2016 mNonInteractiveStartTime = nowELAPSED; 2017 } 2018 } 2019 } 2020 2021 boolean lookForPackageLocked(String packageName) { 2022 for (int i = 0; i < mAlarmBatches.size(); i++) { 2023 Batch b = mAlarmBatches.get(i); 2024 if (b.hasPackage(packageName)) { 2025 return true; 2026 } 2027 } 2028 for (int i = 0; i < mPendingWhileIdleAlarms.size(); i++) { 2029 final Alarm a = mPendingWhileIdleAlarms.get(i); 2030 if (a.matches(packageName)) { 2031 return true; 2032 } 2033 } 2034 return false; 2035 } 2036 2037 private void setLocked(int type, long when) { 2038 if (mNativeData != 0) { 2039 // The kernel never triggers alarms with negative wakeup times 2040 // so we ensure they are positive. 2041 long alarmSeconds, alarmNanoseconds; 2042 if (when < 0) { 2043 alarmSeconds = 0; 2044 alarmNanoseconds = 0; 2045 } else { 2046 alarmSeconds = when / 1000; 2047 alarmNanoseconds = (when % 1000) * 1000 * 1000; 2048 } 2049 2050 set(mNativeData, type, alarmSeconds, alarmNanoseconds); 2051 } else { 2052 Message msg = Message.obtain(); 2053 msg.what = ALARM_EVENT; 2054 2055 mHandler.removeMessages(ALARM_EVENT); 2056 mHandler.sendMessageAtTime(msg, when); 2057 } 2058 } 2059 2060 private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list, 2061 String prefix, String label, long nowRTC, long nowELAPSED, SimpleDateFormat sdf) { 2062 for (int i=list.size()-1; i>=0; i--) { 2063 Alarm a = list.get(i); 2064 pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i); 2065 pw.print(": "); pw.println(a); 2066 a.dump(pw, prefix + " ", nowRTC, nowELAPSED, sdf); 2067 } 2068 } 2069 2070 private static final String labelForType(int type) { 2071 switch (type) { 2072 case RTC: return "RTC"; 2073 case RTC_WAKEUP : return "RTC_WAKEUP"; 2074 case ELAPSED_REALTIME : return "ELAPSED"; 2075 case ELAPSED_REALTIME_WAKEUP: return "ELAPSED_WAKEUP"; 2076 default: 2077 break; 2078 } 2079 return "--unknown--"; 2080 } 2081 2082 private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list, 2083 String prefix, long nowELAPSED, long nowRTC, SimpleDateFormat sdf) { 2084 for (int i=list.size()-1; i>=0; i--) { 2085 Alarm a = list.get(i); 2086 final String label = labelForType(a.type); 2087 pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i); 2088 pw.print(": "); pw.println(a); 2089 a.dump(pw, prefix + " ", nowRTC, nowELAPSED, sdf); 2090 } 2091 } 2092 2093 private native long init(); 2094 private native void close(long nativeData); 2095 private native void set(long nativeData, int type, long seconds, long nanoseconds); 2096 private native int waitForAlarm(long nativeData); 2097 private native int setKernelTime(long nativeData, long millis); 2098 private native int setKernelTimezone(long nativeData, int minuteswest); 2099 2100 boolean triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED, 2101 final long nowRTC) { 2102 boolean hasWakeup = false; 2103 // batches are temporally sorted, so we need only pull from the 2104 // start of the list until we either empty it or hit a batch 2105 // that is not yet deliverable 2106 while (mAlarmBatches.size() > 0) { 2107 Batch batch = mAlarmBatches.get(0); 2108 if (batch.start > nowELAPSED) { 2109 // Everything else is scheduled for the future 2110 break; 2111 } 2112 2113 // We will (re)schedule some alarms now; don't let that interfere 2114 // with delivery of this current batch 2115 mAlarmBatches.remove(0); 2116 2117 final int N = batch.size(); 2118 for (int i = 0; i < N; i++) { 2119 Alarm alarm = batch.get(i); 2120 2121 if ((alarm.flags&AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) { 2122 // If this is an ALLOW_WHILE_IDLE alarm, we constrain how frequently the app can 2123 // schedule such alarms. 2124 long lastTime = mLastAllowWhileIdleDispatch.get(alarm.uid, 0); 2125 long minTime = lastTime + mAllowWhileIdleMinTime; 2126 if (nowELAPSED < minTime) { 2127 // Whoops, it hasn't been long enough since the last ALLOW_WHILE_IDLE 2128 // alarm went off for this app. Reschedule the alarm to be in the 2129 // correct time period. 2130 alarm.whenElapsed = minTime; 2131 if (alarm.maxWhenElapsed < minTime) { 2132 alarm.maxWhenElapsed = minTime; 2133 } 2134 if (RECORD_DEVICE_IDLE_ALARMS) { 2135 IdleDispatchEntry ent = new IdleDispatchEntry(); 2136 ent.uid = alarm.uid; 2137 ent.pkg = alarm.operation.getCreatorPackage(); 2138 ent.tag = alarm.operation.getTag(""); 2139 ent.op = "RESCHEDULE"; 2140 ent.elapsedRealtime = nowELAPSED; 2141 ent.argRealtime = lastTime; 2142 mAllowWhileIdleDispatches.add(ent); 2143 } 2144 setImplLocked(alarm, true, false); 2145 continue; 2146 } 2147 } 2148 2149 alarm.count = 1; 2150 triggerList.add(alarm); 2151 if ((alarm.flags&AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) { 2152 EventLogTags.writeDeviceIdleWakeFromIdle(mPendingIdleUntil != null ? 1 : 0, 2153 alarm.statsTag); 2154 } 2155 if (mPendingIdleUntil == alarm) { 2156 mPendingIdleUntil = null; 2157 rebatchAllAlarmsLocked(false); 2158 restorePendingWhileIdleAlarmsLocked(); 2159 } 2160 if (mNextWakeFromIdle == alarm) { 2161 mNextWakeFromIdle = null; 2162 rebatchAllAlarmsLocked(false); 2163 } 2164 2165 // Recurring alarms may have passed several alarm intervals while the 2166 // phone was asleep or off, so pass a trigger count when sending them. 2167 if (alarm.repeatInterval > 0) { 2168 // this adjustment will be zero if we're late by 2169 // less than one full repeat interval 2170 alarm.count += (nowELAPSED - alarm.whenElapsed) / alarm.repeatInterval; 2171 2172 // Also schedule its next recurrence 2173 final long delta = alarm.count * alarm.repeatInterval; 2174 final long nextElapsed = alarm.whenElapsed + delta; 2175 setImplLocked(alarm.type, alarm.when + delta, nextElapsed, alarm.windowLength, 2176 maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval), 2177 alarm.repeatInterval, alarm.operation, null, null, alarm.flags, true, 2178 alarm.workSource, alarm.alarmClock, alarm.uid, alarm.packageName); 2179 } 2180 2181 if (alarm.wakeup) { 2182 hasWakeup = true; 2183 } 2184 2185 // We removed an alarm clock. Let the caller recompute the next alarm clock. 2186 if (alarm.alarmClock != null) { 2187 mNextAlarmClockMayChange = true; 2188 } 2189 } 2190 } 2191 2192 // This is a new alarm delivery set; bump the sequence number to indicate that 2193 // all apps' alarm delivery classes should be recalculated. 2194 mCurrentSeq++; 2195 calculateDeliveryPriorities(triggerList); 2196 Collections.sort(triggerList, mAlarmDispatchComparator); 2197 2198 if (localLOGV) { 2199 for (int i=0; i<triggerList.size(); i++) { 2200 Slog.v(TAG, "Triggering alarm #" + i + ": " + triggerList.get(i)); 2201 } 2202 } 2203 2204 return hasWakeup; 2205 } 2206 2207 /** 2208 * This Comparator sorts Alarms into increasing time order. 2209 */ 2210 public static class IncreasingTimeOrder implements Comparator<Alarm> { 2211 public int compare(Alarm a1, Alarm a2) { 2212 long when1 = a1.whenElapsed; 2213 long when2 = a2.whenElapsed; 2214 if (when1 > when2) { 2215 return 1; 2216 } 2217 if (when1 < when2) { 2218 return -1; 2219 } 2220 return 0; 2221 } 2222 } 2223 2224 private static class Alarm { 2225 public final int type; 2226 public final long origWhen; 2227 public final boolean wakeup; 2228 public final PendingIntent operation; 2229 public final IAlarmListener listener; 2230 public final String listenerTag; 2231 public final String statsTag; 2232 public final WorkSource workSource; 2233 public final int flags; 2234 public final AlarmManager.AlarmClockInfo alarmClock; 2235 public final int uid; 2236 public final int creatorUid; 2237 public final String packageName; 2238 public int count; 2239 public long when; 2240 public long windowLength; 2241 public long whenElapsed; // 'when' in the elapsed time base 2242 public long maxWhenElapsed; // also in the elapsed time base 2243 public long repeatInterval; 2244 public PriorityClass priorityClass; 2245 2246 public Alarm(int _type, long _when, long _whenElapsed, long _windowLength, long _maxWhen, 2247 long _interval, PendingIntent _op, IAlarmListener _rec, String _listenerTag, 2248 WorkSource _ws, int _flags, AlarmManager.AlarmClockInfo _info, 2249 int _uid, String _pkgName) { 2250 type = _type; 2251 origWhen = _when; 2252 wakeup = _type == AlarmManager.ELAPSED_REALTIME_WAKEUP 2253 || _type == AlarmManager.RTC_WAKEUP; 2254 when = _when; 2255 whenElapsed = _whenElapsed; 2256 windowLength = _windowLength; 2257 maxWhenElapsed = _maxWhen; 2258 repeatInterval = _interval; 2259 operation = _op; 2260 listener = _rec; 2261 listenerTag = _listenerTag; 2262 statsTag = makeTag(_op, _listenerTag, _type); 2263 workSource = _ws; 2264 flags = _flags; 2265 alarmClock = _info; 2266 uid = _uid; 2267 packageName = _pkgName; 2268 2269 creatorUid = (operation != null) ? operation.getCreatorUid() : uid; 2270 } 2271 2272 public static String makeTag(PendingIntent pi, String tag, int type) { 2273 final String alarmString = type == ELAPSED_REALTIME_WAKEUP || type == RTC_WAKEUP 2274 ? "*walarm*:" : "*alarm*:"; 2275 return (pi != null) ? pi.getTag(alarmString) : (alarmString + tag); 2276 } 2277 2278 public WakeupEvent makeWakeupEvent(long nowRTC) { 2279 return new WakeupEvent(nowRTC, creatorUid, 2280 (operation != null) 2281 ? operation.getIntent().getAction() 2282 : ("<listener>:" + listenerTag)); 2283 } 2284 2285 // Returns true if either matches 2286 public boolean matches(PendingIntent pi, IAlarmListener rec) { 2287 return (operation != null) 2288 ? operation.equals(pi) 2289 : rec != null && listener.asBinder().equals(rec.asBinder()); 2290 } 2291 2292 public boolean matches(String packageName) { 2293 return (operation != null) 2294 ? packageName.equals(operation.getTargetPackage()) 2295 : packageName.equals(this.packageName); 2296 } 2297 2298 @Override 2299 public String toString() { 2300 StringBuilder sb = new StringBuilder(128); 2301 sb.append("Alarm{"); 2302 sb.append(Integer.toHexString(System.identityHashCode(this))); 2303 sb.append(" type "); 2304 sb.append(type); 2305 sb.append(" when "); 2306 sb.append(when); 2307 sb.append(" "); 2308 if (operation != null) { 2309 sb.append(operation.getTargetPackage()); 2310 } else { 2311 sb.append(packageName); 2312 } 2313 sb.append('}'); 2314 return sb.toString(); 2315 } 2316 2317 public void dump(PrintWriter pw, String prefix, long nowRTC, long nowELAPSED, 2318 SimpleDateFormat sdf) { 2319 final boolean isRtc = (type == RTC || type == RTC_WAKEUP); 2320 pw.print(prefix); pw.print("tag="); pw.println(statsTag); 2321 pw.print(prefix); pw.print("type="); pw.print(type); 2322 pw.print(" whenElapsed="); TimeUtils.formatDuration(whenElapsed, 2323 nowELAPSED, pw); 2324 pw.print(" when="); 2325 if (isRtc) { 2326 pw.print(sdf.format(new Date(when))); 2327 } else { 2328 TimeUtils.formatDuration(when, nowELAPSED, pw); 2329 } 2330 pw.println(); 2331 pw.print(prefix); pw.print("window="); TimeUtils.formatDuration(windowLength, pw); 2332 pw.print(" repeatInterval="); pw.print(repeatInterval); 2333 pw.print(" count="); pw.print(count); 2334 pw.print(" flags=0x"); pw.println(Integer.toHexString(flags)); 2335 if (alarmClock != null) { 2336 pw.print(prefix); pw.println("Alarm clock:"); 2337 pw.print(prefix); pw.print(" triggerTime="); 2338 pw.println(sdf.format(new Date(alarmClock.getTriggerTime()))); 2339 pw.print(prefix); pw.print(" showIntent="); pw.println(alarmClock.getShowIntent()); 2340 } 2341 pw.print(prefix); pw.print("operation="); pw.println(operation); 2342 if (listener != null) { 2343 pw.print(prefix); pw.print("listener="); pw.println(listener.asBinder()); 2344 } 2345 } 2346 } 2347 2348 void recordWakeupAlarms(ArrayList<Batch> batches, long nowELAPSED, long nowRTC) { 2349 final int numBatches = batches.size(); 2350 for (int nextBatch = 0; nextBatch < numBatches; nextBatch++) { 2351 Batch b = batches.get(nextBatch); 2352 if (b.start > nowELAPSED) { 2353 break; 2354 } 2355 2356 final int numAlarms = b.alarms.size(); 2357 for (int nextAlarm = 0; nextAlarm < numAlarms; nextAlarm++) { 2358 Alarm a = b.alarms.get(nextAlarm); 2359 mRecentWakeups.add(a.makeWakeupEvent(nowRTC)); 2360 } 2361 } 2362 } 2363 2364 long currentNonWakeupFuzzLocked(long nowELAPSED) { 2365 long timeSinceOn = nowELAPSED - mNonInteractiveStartTime; 2366 if (timeSinceOn < 5*60*1000) { 2367 // If the screen has been off for 5 minutes, only delay by at most two minutes. 2368 return 2*60*1000; 2369 } else if (timeSinceOn < 30*60*1000) { 2370 // If the screen has been off for 30 minutes, only delay by at most 15 minutes. 2371 return 15*60*1000; 2372 } else { 2373 // Otherwise, we will delay by at most an hour. 2374 return 60*60*1000; 2375 } 2376 } 2377 2378 static int fuzzForDuration(long duration) { 2379 if (duration < 15*60*1000) { 2380 // If the duration until the time is less than 15 minutes, the maximum fuzz 2381 // is the duration. 2382 return (int)duration; 2383 } else if (duration < 90*60*1000) { 2384 // If duration is less than 1 1/2 hours, the maximum fuzz is 15 minutes, 2385 return 15*60*1000; 2386 } else { 2387 // Otherwise, we will fuzz by at most half an hour. 2388 return 30*60*1000; 2389 } 2390 } 2391 2392 boolean checkAllowNonWakeupDelayLocked(long nowELAPSED) { 2393 if (mInteractive) { 2394 return false; 2395 } 2396 if (mLastAlarmDeliveryTime <= 0) { 2397 return false; 2398 } 2399 if (mPendingNonWakeupAlarms.size() > 0 && mNextNonWakeupDeliveryTime < nowELAPSED) { 2400 // This is just a little paranoia, if somehow we have pending non-wakeup alarms 2401 // and the next delivery time is in the past, then just deliver them all. This 2402 // avoids bugs where we get stuck in a loop trying to poll for alarms. 2403 return false; 2404 } 2405 long timeSinceLast = nowELAPSED - mLastAlarmDeliveryTime; 2406 return timeSinceLast <= currentNonWakeupFuzzLocked(nowELAPSED); 2407 } 2408 2409 void deliverAlarmsLocked(ArrayList<Alarm> triggerList, long nowELAPSED) { 2410 mLastAlarmDeliveryTime = nowELAPSED; 2411 for (int i=0; i<triggerList.size(); i++) { 2412 Alarm alarm = triggerList.get(i); 2413 final boolean allowWhileIdle = (alarm.flags&AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0; 2414 try { 2415 if (localLOGV) { 2416 Slog.v(TAG, "sending alarm " + alarm); 2417 } 2418 if (RECORD_ALARMS_IN_HISTORY) { 2419 if (alarm.workSource != null && alarm.workSource.size() > 0) { 2420 for (int wi=0; wi<alarm.workSource.size(); wi++) { 2421 ActivityManagerNative.noteAlarmStart( 2422 alarm.operation, alarm.workSource.get(wi), alarm.statsTag); 2423 } 2424 } else { 2425 ActivityManagerNative.noteAlarmStart( 2426 alarm.operation, alarm.uid, alarm.statsTag); 2427 } 2428 } 2429 mDeliveryTracker.deliverLocked(alarm, nowELAPSED, allowWhileIdle); 2430 } catch (RuntimeException e) { 2431 Slog.w(TAG, "Failure sending alarm.", e); 2432 } 2433 } 2434 } 2435 2436 private class AlarmThread extends Thread 2437 { 2438 public AlarmThread() 2439 { 2440 super("AlarmManager"); 2441 } 2442 2443 public void run() 2444 { 2445 ArrayList<Alarm> triggerList = new ArrayList<Alarm>(); 2446 2447 while (true) 2448 { 2449 int result = waitForAlarm(mNativeData); 2450 mLastWakeup = SystemClock.elapsedRealtime(); 2451 2452 triggerList.clear(); 2453 2454 final long nowRTC = System.currentTimeMillis(); 2455 final long nowELAPSED = SystemClock.elapsedRealtime(); 2456 2457 if ((result & TIME_CHANGED_MASK) != 0) { 2458 // The kernel can give us spurious time change notifications due to 2459 // small adjustments it makes internally; we want to filter those out. 2460 final long lastTimeChangeClockTime; 2461 final long expectedClockTime; 2462 synchronized (mLock) { 2463 lastTimeChangeClockTime = mLastTimeChangeClockTime; 2464 expectedClockTime = lastTimeChangeClockTime 2465 + (nowELAPSED - mLastTimeChangeRealtime); 2466 } 2467 if (lastTimeChangeClockTime == 0 || nowRTC < (expectedClockTime-500) 2468 || nowRTC > (expectedClockTime+500)) { 2469 // The change is by at least +/- 500 ms (or this is the first change), 2470 // let's do it! 2471 if (DEBUG_BATCH) { 2472 Slog.v(TAG, "Time changed notification from kernel; rebatching"); 2473 } 2474 removeImpl(mTimeTickSender); 2475 removeImpl(mDateChangeSender); 2476 rebatchAllAlarms(); 2477 mClockReceiver.scheduleTimeTickEvent(); 2478 mClockReceiver.scheduleDateChangedEvent(); 2479 synchronized (mLock) { 2480 mNumTimeChanged++; 2481 mLastTimeChangeClockTime = nowRTC; 2482 mLastTimeChangeRealtime = nowELAPSED; 2483 } 2484 Intent intent = new Intent(Intent.ACTION_TIME_CHANGED); 2485 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING 2486 | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 2487 getContext().sendBroadcastAsUser(intent, UserHandle.ALL); 2488 2489 // The world has changed on us, so we need to re-evaluate alarms 2490 // regardless of whether the kernel has told us one went off. 2491 result |= IS_WAKEUP_MASK; 2492 } 2493 } 2494 2495 if (result != TIME_CHANGED_MASK) { 2496 // If this was anything besides just a time change, then figure what if 2497 // anything to do about alarms. 2498 synchronized (mLock) { 2499 if (localLOGV) Slog.v( 2500 TAG, "Checking for alarms... rtc=" + nowRTC 2501 + ", elapsed=" + nowELAPSED); 2502 2503 if (WAKEUP_STATS) { 2504 if ((result & IS_WAKEUP_MASK) != 0) { 2505 long newEarliest = nowRTC - RECENT_WAKEUP_PERIOD; 2506 int n = 0; 2507 for (WakeupEvent event : mRecentWakeups) { 2508 if (event.when > newEarliest) break; 2509 n++; // number of now-stale entries at the list head 2510 } 2511 for (int i = 0; i < n; i++) { 2512 mRecentWakeups.remove(); 2513 } 2514 2515 recordWakeupAlarms(mAlarmBatches, nowELAPSED, nowRTC); 2516 } 2517 } 2518 2519 boolean hasWakeup = triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC); 2520 if (!hasWakeup && checkAllowNonWakeupDelayLocked(nowELAPSED)) { 2521 // if there are no wakeup alarms and the screen is off, we can 2522 // delay what we have so far until the future. 2523 if (mPendingNonWakeupAlarms.size() == 0) { 2524 mStartCurrentDelayTime = nowELAPSED; 2525 mNextNonWakeupDeliveryTime = nowELAPSED 2526 + ((currentNonWakeupFuzzLocked(nowELAPSED)*3)/2); 2527 } 2528 mPendingNonWakeupAlarms.addAll(triggerList); 2529 mNumDelayedAlarms += triggerList.size(); 2530 rescheduleKernelAlarmsLocked(); 2531 updateNextAlarmClockLocked(); 2532 } else { 2533 // now deliver the alarm intents; if there are pending non-wakeup 2534 // alarms, we need to merge them in to the list. note we don't 2535 // just deliver them first because we generally want non-wakeup 2536 // alarms delivered after wakeup alarms. 2537 rescheduleKernelAlarmsLocked(); 2538 updateNextAlarmClockLocked(); 2539 if (mPendingNonWakeupAlarms.size() > 0) { 2540 calculateDeliveryPriorities(mPendingNonWakeupAlarms); 2541 triggerList.addAll(mPendingNonWakeupAlarms); 2542 Collections.sort(triggerList, mAlarmDispatchComparator); 2543 final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime; 2544 mTotalDelayTime += thisDelayTime; 2545 if (mMaxDelayTime < thisDelayTime) { 2546 mMaxDelayTime = thisDelayTime; 2547 } 2548 mPendingNonWakeupAlarms.clear(); 2549 } 2550 deliverAlarmsLocked(triggerList, nowELAPSED); 2551 } 2552 } 2553 2554 } else { 2555 // Just in case -- even though no wakeup flag was set, make sure 2556 // we have updated the kernel to the next alarm time. 2557 synchronized (mLock) { 2558 rescheduleKernelAlarmsLocked(); 2559 } 2560 } 2561 } 2562 } 2563 } 2564 2565 /** 2566 * Attribute blame for a WakeLock. 2567 * @param pi PendingIntent to attribute blame to if ws is null. 2568 * @param ws WorkSource to attribute blame. 2569 * @param knownUid attribution uid; < 0 if we need to derive it from the PendingIntent sender 2570 */ 2571 void setWakelockWorkSource(PendingIntent pi, WorkSource ws, int type, String tag, 2572 int knownUid, boolean first) { 2573 try { 2574 final boolean unimportant = pi == mTimeTickSender; 2575 mWakeLock.setUnimportantForLogging(unimportant); 2576 if (first || mLastWakeLockUnimportantForLogging) { 2577 mWakeLock.setHistoryTag(tag); 2578 } else { 2579 mWakeLock.setHistoryTag(null); 2580 } 2581 mLastWakeLockUnimportantForLogging = unimportant; 2582 if (ws != null) { 2583 mWakeLock.setWorkSource(ws); 2584 return; 2585 } 2586 2587 final int uid = (knownUid >= 0) 2588 ? knownUid 2589 : ActivityManagerNative.getDefault().getUidForIntentSender(pi.getTarget()); 2590 if (uid >= 0) { 2591 mWakeLock.setWorkSource(new WorkSource(uid)); 2592 return; 2593 } 2594 } catch (Exception e) { 2595 } 2596 2597 // Something went wrong; fall back to attributing the lock to the OS 2598 mWakeLock.setWorkSource(null); 2599 } 2600 2601 private class AlarmHandler extends Handler { 2602 public static final int ALARM_EVENT = 1; 2603 public static final int SEND_NEXT_ALARM_CLOCK_CHANGED = 2; 2604 public static final int LISTENER_TIMEOUT = 3; 2605 public static final int REPORT_ALARMS_ACTIVE = 4; 2606 2607 public AlarmHandler() { 2608 } 2609 2610 public void handleMessage(Message msg) { 2611 switch (msg.what) { 2612 case ALARM_EVENT: { 2613 ArrayList<Alarm> triggerList = new ArrayList<Alarm>(); 2614 synchronized (mLock) { 2615 final long nowRTC = System.currentTimeMillis(); 2616 final long nowELAPSED = SystemClock.elapsedRealtime(); 2617 triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC); 2618 updateNextAlarmClockLocked(); 2619 } 2620 2621 // now trigger the alarms without the lock held 2622 for (int i=0; i<triggerList.size(); i++) { 2623 Alarm alarm = triggerList.get(i); 2624 try { 2625 alarm.operation.send(); 2626 } catch (PendingIntent.CanceledException e) { 2627 if (alarm.repeatInterval > 0) { 2628 // This IntentSender is no longer valid, but this 2629 // is a repeating alarm, so toss the hoser. 2630 removeImpl(alarm.operation); 2631 } 2632 } 2633 } 2634 break; 2635 } 2636 2637 case SEND_NEXT_ALARM_CLOCK_CHANGED: 2638 sendNextAlarmClockChanged(); 2639 break; 2640 2641 case LISTENER_TIMEOUT: 2642 mDeliveryTracker.alarmTimedOut((IBinder) msg.obj); 2643 break; 2644 2645 case REPORT_ALARMS_ACTIVE: 2646 if (mLocalDeviceIdleController != null) { 2647 mLocalDeviceIdleController.setAlarmsActive(msg.arg1 != 0); 2648 } 2649 break; 2650 2651 default: 2652 // nope, just ignore it 2653 break; 2654 } 2655 } 2656 } 2657 2658 class ClockReceiver extends BroadcastReceiver { 2659 public ClockReceiver() { 2660 IntentFilter filter = new IntentFilter(); 2661 filter.addAction(Intent.ACTION_TIME_TICK); 2662 filter.addAction(Intent.ACTION_DATE_CHANGED); 2663 getContext().registerReceiver(this, filter); 2664 } 2665 2666 @Override 2667 public void onReceive(Context context, Intent intent) { 2668 if (intent.getAction().equals(Intent.ACTION_TIME_TICK)) { 2669 if (DEBUG_BATCH) { 2670 Slog.v(TAG, "Received TIME_TICK alarm; rescheduling"); 2671 } 2672 scheduleTimeTickEvent(); 2673 } else if (intent.getAction().equals(Intent.ACTION_DATE_CHANGED)) { 2674 // Since the kernel does not keep track of DST, we need to 2675 // reset the TZ information at the beginning of each day 2676 // based off of the current Zone gmt offset + userspace tracked 2677 // daylight savings information. 2678 TimeZone zone = TimeZone.getTimeZone(SystemProperties.get(TIMEZONE_PROPERTY)); 2679 int gmtOffset = zone.getOffset(System.currentTimeMillis()); 2680 setKernelTimezone(mNativeData, -(gmtOffset / 60000)); 2681 scheduleDateChangedEvent(); 2682 } 2683 } 2684 2685 public void scheduleTimeTickEvent() { 2686 final long currentTime = System.currentTimeMillis(); 2687 final long nextTime = 60000 * ((currentTime / 60000) + 1); 2688 2689 // Schedule this event for the amount of time that it would take to get to 2690 // the top of the next minute. 2691 final long tickEventDelay = nextTime - currentTime; 2692 2693 final WorkSource workSource = null; // Let system take blame for time tick events. 2694 setImpl(ELAPSED_REALTIME, SystemClock.elapsedRealtime() + tickEventDelay, 0, 2695 0, mTimeTickSender, null, null, AlarmManager.FLAG_STANDALONE, workSource, 2696 null, Process.myUid(), "android"); 2697 } 2698 2699 public void scheduleDateChangedEvent() { 2700 Calendar calendar = Calendar.getInstance(); 2701 calendar.setTimeInMillis(System.currentTimeMillis()); 2702 calendar.set(Calendar.HOUR_OF_DAY, 0); 2703 calendar.set(Calendar.MINUTE, 0); 2704 calendar.set(Calendar.SECOND, 0); 2705 calendar.set(Calendar.MILLISECOND, 0); 2706 calendar.add(Calendar.DAY_OF_MONTH, 1); 2707 2708 final WorkSource workSource = null; // Let system take blame for date change events. 2709 setImpl(RTC, calendar.getTimeInMillis(), 0, 0, mDateChangeSender, null, null, 2710 AlarmManager.FLAG_STANDALONE, workSource, null, 2711 Process.myUid(), "android"); 2712 } 2713 } 2714 2715 class InteractiveStateReceiver extends BroadcastReceiver { 2716 public InteractiveStateReceiver() { 2717 IntentFilter filter = new IntentFilter(); 2718 filter.addAction(Intent.ACTION_SCREEN_OFF); 2719 filter.addAction(Intent.ACTION_SCREEN_ON); 2720 filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); 2721 getContext().registerReceiver(this, filter); 2722 } 2723 2724 @Override 2725 public void onReceive(Context context, Intent intent) { 2726 synchronized (mLock) { 2727 interactiveStateChangedLocked(Intent.ACTION_SCREEN_ON.equals(intent.getAction())); 2728 } 2729 } 2730 } 2731 2732 class UninstallReceiver extends BroadcastReceiver { 2733 public UninstallReceiver() { 2734 IntentFilter filter = new IntentFilter(); 2735 filter.addAction(Intent.ACTION_PACKAGE_REMOVED); 2736 filter.addAction(Intent.ACTION_PACKAGE_RESTARTED); 2737 filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART); 2738 filter.addDataScheme("package"); 2739 getContext().registerReceiver(this, filter); 2740 // Register for events related to sdcard installation. 2741 IntentFilter sdFilter = new IntentFilter(); 2742 sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); 2743 sdFilter.addAction(Intent.ACTION_USER_STOPPED); 2744 sdFilter.addAction(Intent.ACTION_UID_REMOVED); 2745 getContext().registerReceiver(this, sdFilter); 2746 } 2747 2748 @Override 2749 public void onReceive(Context context, Intent intent) { 2750 synchronized (mLock) { 2751 String action = intent.getAction(); 2752 String pkgList[] = null; 2753 if (Intent.ACTION_QUERY_PACKAGE_RESTART.equals(action)) { 2754 pkgList = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES); 2755 for (String packageName : pkgList) { 2756 if (lookForPackageLocked(packageName)) { 2757 setResultCode(Activity.RESULT_OK); 2758 return; 2759 } 2760 } 2761 return; 2762 } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) { 2763 pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); 2764 } else if (Intent.ACTION_USER_STOPPED.equals(action)) { 2765 int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); 2766 if (userHandle >= 0) { 2767 removeUserLocked(userHandle); 2768 } 2769 } else if (Intent.ACTION_UID_REMOVED.equals(action)) { 2770 int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); 2771 if (uid >= 0) { 2772 mLastAllowWhileIdleDispatch.delete(uid); 2773 } 2774 } else { 2775 if (Intent.ACTION_PACKAGE_REMOVED.equals(action) 2776 && intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { 2777 // This package is being updated; don't kill its alarms. 2778 return; 2779 } 2780 Uri data = intent.getData(); 2781 if (data != null) { 2782 String pkg = data.getSchemeSpecificPart(); 2783 if (pkg != null) { 2784 pkgList = new String[]{pkg}; 2785 } 2786 } 2787 } 2788 if (pkgList != null && (pkgList.length > 0)) { 2789 for (String pkg : pkgList) { 2790 removeLocked(pkg); 2791 mPriorities.remove(pkg); 2792 for (int i=mBroadcastStats.size()-1; i>=0; i--) { 2793 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(i); 2794 if (uidStats.remove(pkg) != null) { 2795 if (uidStats.size() <= 0) { 2796 mBroadcastStats.removeAt(i); 2797 } 2798 } 2799 } 2800 } 2801 } 2802 } 2803 } 2804 } 2805 2806 final class UidObserver extends IUidObserver.Stub { 2807 @Override public void onUidStateChanged(int uid, int procState) throws RemoteException { 2808 } 2809 2810 @Override public void onUidGone(int uid) throws RemoteException { 2811 } 2812 2813 @Override public void onUidActive(int uid) throws RemoteException { 2814 } 2815 2816 @Override public void onUidIdle(int uid) throws RemoteException { 2817 synchronized (mLock) { 2818 removeForStoppedLocked(uid); 2819 } 2820 } 2821 }; 2822 2823 private final BroadcastStats getStatsLocked(PendingIntent pi) { 2824 String pkg = pi.getCreatorPackage(); 2825 int uid = pi.getCreatorUid(); 2826 return getStatsLocked(uid, pkg); 2827 } 2828 2829 private final BroadcastStats getStatsLocked(int uid, String pkgName) { 2830 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.get(uid); 2831 if (uidStats == null) { 2832 uidStats = new ArrayMap<String, BroadcastStats>(); 2833 mBroadcastStats.put(uid, uidStats); 2834 } 2835 BroadcastStats bs = uidStats.get(pkgName); 2836 if (bs == null) { 2837 bs = new BroadcastStats(uid, pkgName); 2838 uidStats.put(pkgName, bs); 2839 } 2840 return bs; 2841 } 2842 2843 class DeliveryTracker extends IAlarmCompleteListener.Stub implements PendingIntent.OnFinished { 2844 private InFlight removeLocked(PendingIntent pi, Intent intent) { 2845 for (int i = 0; i < mInFlight.size(); i++) { 2846 if (mInFlight.get(i).mPendingIntent == pi) { 2847 return mInFlight.remove(i); 2848 } 2849 } 2850 mLog.w("No in-flight alarm for " + pi + " " + intent); 2851 return null; 2852 } 2853 2854 private InFlight removeLocked(IBinder listener) { 2855 for (int i = 0; i < mInFlight.size(); i++) { 2856 if (mInFlight.get(i).mListener == listener) { 2857 return mInFlight.remove(i); 2858 } 2859 } 2860 mLog.w("No in-flight alarm for listener " + listener); 2861 return null; 2862 } 2863 2864 private void updateStatsLocked(InFlight inflight) { 2865 final long nowELAPSED = SystemClock.elapsedRealtime(); 2866 BroadcastStats bs = inflight.mBroadcastStats; 2867 bs.nesting--; 2868 if (bs.nesting <= 0) { 2869 bs.nesting = 0; 2870 bs.aggregateTime += nowELAPSED - bs.startTime; 2871 } 2872 FilterStats fs = inflight.mFilterStats; 2873 fs.nesting--; 2874 if (fs.nesting <= 0) { 2875 fs.nesting = 0; 2876 fs.aggregateTime += nowELAPSED - fs.startTime; 2877 } 2878 if (RECORD_ALARMS_IN_HISTORY) { 2879 if (inflight.mWorkSource != null && inflight.mWorkSource.size() > 0) { 2880 for (int wi=0; wi<inflight.mWorkSource.size(); wi++) { 2881 ActivityManagerNative.noteAlarmFinish( 2882 inflight.mPendingIntent, inflight.mWorkSource.get(wi), inflight.mTag); 2883 } 2884 } else { 2885 ActivityManagerNative.noteAlarmFinish( 2886 inflight.mPendingIntent, inflight.mUid, inflight.mTag); 2887 } 2888 } 2889 } 2890 2891 private void updateTrackingLocked(InFlight inflight) { 2892 if (inflight != null) { 2893 updateStatsLocked(inflight); 2894 } 2895 mBroadcastRefCount--; 2896 if (mBroadcastRefCount == 0) { 2897 mHandler.obtainMessage(AlarmHandler.REPORT_ALARMS_ACTIVE, 0).sendToTarget(); 2898 mWakeLock.release(); 2899 if (mInFlight.size() > 0) { 2900 mLog.w("Finished all dispatches with " + mInFlight.size() 2901 + " remaining inflights"); 2902 for (int i=0; i<mInFlight.size(); i++) { 2903 mLog.w(" Remaining #" + i + ": " + mInFlight.get(i)); 2904 } 2905 mInFlight.clear(); 2906 } 2907 } else { 2908 // the next of our alarms is now in flight. reattribute the wakelock. 2909 if (mInFlight.size() > 0) { 2910 InFlight inFlight = mInFlight.get(0); 2911 setWakelockWorkSource(inFlight.mPendingIntent, inFlight.mWorkSource, 2912 inFlight.mAlarmType, inFlight.mTag, -1, false); 2913 } else { 2914 // should never happen 2915 mLog.w("Alarm wakelock still held but sent queue empty"); 2916 mWakeLock.setWorkSource(null); 2917 } 2918 } 2919 } 2920 2921 /** 2922 * Callback that arrives when a direct-call alarm reports that delivery has finished 2923 */ 2924 @Override 2925 public void alarmComplete(IBinder who) { 2926 if (who == null) { 2927 Slog.w(TAG, "Invalid alarmComplete: uid=" + Binder.getCallingUid() 2928 + " pid=" + Binder.getCallingPid()); 2929 return; 2930 } 2931 2932 final long ident = Binder.clearCallingIdentity(); 2933 try { 2934 synchronized (mLock) { 2935 mHandler.removeMessages(AlarmHandler.LISTENER_TIMEOUT, who); 2936 InFlight inflight = removeLocked(who); 2937 if (inflight != null) { 2938 if (DEBUG_LISTENER_CALLBACK) { 2939 Slog.i(TAG, "alarmComplete() from " + who); 2940 } 2941 updateTrackingLocked(inflight); 2942 } else { 2943 // Delivery timed out, and the timeout handling already took care of 2944 // updating our tracking here, so we needn't do anything further. 2945 if (DEBUG_LISTENER_CALLBACK) { 2946 Slog.i(TAG, "Late alarmComplete() from " + who); 2947 } 2948 } 2949 } 2950 } finally { 2951 Binder.restoreCallingIdentity(ident); 2952 } 2953 } 2954 2955 /** 2956 * Callback that arrives when a PendingIntent alarm has finished delivery 2957 */ 2958 @Override 2959 public void onSendFinished(PendingIntent pi, Intent intent, int resultCode, 2960 String resultData, Bundle resultExtras) { 2961 synchronized (mLock) { 2962 updateTrackingLocked(removeLocked(pi, intent)); 2963 } 2964 } 2965 2966 /** 2967 * Timeout of a direct-call alarm delivery 2968 */ 2969 public void alarmTimedOut(IBinder who) { 2970 synchronized (mLock) { 2971 InFlight inflight = removeLocked(who); 2972 if (inflight != null) { 2973 // TODO: implement ANR policy for the target 2974 if (DEBUG_LISTENER_CALLBACK) { 2975 Slog.i(TAG, "Alarm listener " + who + " timed out in delivery"); 2976 } 2977 updateTrackingLocked(inflight); 2978 } else { 2979 if (DEBUG_LISTENER_CALLBACK) { 2980 Slog.i(TAG, "Spurious timeout of listener " + who); 2981 } 2982 } 2983 } 2984 } 2985 2986 /** 2987 * Deliver an alarm and set up the post-delivery handling appropriately 2988 */ 2989 public void deliverLocked(Alarm alarm, long nowELAPSED, boolean allowWhileIdle) { 2990 if (alarm.operation != null) { 2991 // PendingIntent alarm 2992 try { 2993 alarm.operation.send(getContext(), 0, 2994 mBackgroundIntent.putExtra( 2995 Intent.EXTRA_ALARM_COUNT, alarm.count), 2996 mDeliveryTracker, mHandler, null, 2997 allowWhileIdle ? mIdleOptions : null); 2998 } catch (PendingIntent.CanceledException e) { 2999 if (alarm.repeatInterval > 0) { 3000 // This IntentSender is no longer valid, but this 3001 // is a repeating alarm, so toss it 3002 removeImpl(alarm.operation); 3003 } 3004 // No actual delivery was possible, so the delivery tracker's 3005 // 'finished' callback won't be invoked. We also don't need 3006 // to do any wakelock or stats tracking, so we have nothing 3007 // left to do here but go on to the next thing. 3008 return; 3009 } 3010 } else { 3011 // Direct listener callback alarm 3012 try { 3013 if (DEBUG_LISTENER_CALLBACK) { 3014 Slog.v(TAG, "Alarm to uid=" + alarm.uid 3015 + " listener=" + alarm.listener.asBinder()); 3016 } 3017 alarm.listener.doAlarm(this); 3018 mHandler.sendMessageDelayed( 3019 mHandler.obtainMessage(AlarmHandler.LISTENER_TIMEOUT, 3020 alarm.listener.asBinder()), 3021 mConstants.LISTENER_TIMEOUT); 3022 } catch (Exception e) { 3023 if (DEBUG_LISTENER_CALLBACK) { 3024 Slog.i(TAG, "Alarm undeliverable to listener " 3025 + alarm.listener.asBinder(), e); 3026 } 3027 // As in the PendingIntent.CanceledException case, delivery of the 3028 // alarm was not possible, so we have no wakelock or timeout or 3029 // stats management to do. It threw before we posted the delayed 3030 // timeout message, so we're done here. 3031 return; 3032 } 3033 } 3034 3035 // The alarm is now in flight; now arrange wakelock and stats tracking 3036 if (mBroadcastRefCount == 0) { 3037 setWakelockWorkSource(alarm.operation, alarm.workSource, 3038 alarm.type, alarm.statsTag, (alarm.operation == null) ? alarm.uid : -1, 3039 true); 3040 mWakeLock.acquire(); 3041 mHandler.obtainMessage(AlarmHandler.REPORT_ALARMS_ACTIVE, 1).sendToTarget(); 3042 } 3043 final InFlight inflight = new InFlight(AlarmManagerService.this, 3044 alarm.operation, alarm.listener, alarm.workSource, alarm.uid, 3045 alarm.packageName, alarm.type, alarm.statsTag, nowELAPSED); 3046 mInFlight.add(inflight); 3047 mBroadcastRefCount++; 3048 3049 if (allowWhileIdle) { 3050 // Record the last time this uid handled an ALLOW_WHILE_IDLE alarm. 3051 mLastAllowWhileIdleDispatch.put(alarm.uid, nowELAPSED); 3052 if (RECORD_DEVICE_IDLE_ALARMS) { 3053 IdleDispatchEntry ent = new IdleDispatchEntry(); 3054 ent.uid = alarm.uid; 3055 ent.pkg = alarm.packageName; 3056 ent.tag = alarm.statsTag; 3057 ent.op = "DELIVER"; 3058 ent.elapsedRealtime = nowELAPSED; 3059 mAllowWhileIdleDispatches.add(ent); 3060 } 3061 } 3062 3063 final BroadcastStats bs = inflight.mBroadcastStats; 3064 bs.count++; 3065 if (bs.nesting == 0) { 3066 bs.nesting = 1; 3067 bs.startTime = nowELAPSED; 3068 } else { 3069 bs.nesting++; 3070 } 3071 final FilterStats fs = inflight.mFilterStats; 3072 fs.count++; 3073 if (fs.nesting == 0) { 3074 fs.nesting = 1; 3075 fs.startTime = nowELAPSED; 3076 } else { 3077 fs.nesting++; 3078 } 3079 if (alarm.type == ELAPSED_REALTIME_WAKEUP 3080 || alarm.type == RTC_WAKEUP) { 3081 bs.numWakeup++; 3082 fs.numWakeup++; 3083 if (alarm.workSource != null && alarm.workSource.size() > 0) { 3084 for (int wi=0; wi<alarm.workSource.size(); wi++) { 3085 final String wsName = alarm.workSource.getName(wi); 3086 ActivityManagerNative.noteWakeupAlarm( 3087 alarm.operation, alarm.workSource.get(wi), 3088 (wsName != null) ? wsName : alarm.packageName, 3089 alarm.statsTag); 3090 } 3091 } else { 3092 ActivityManagerNative.noteWakeupAlarm( 3093 alarm.operation, alarm.uid, alarm.packageName, alarm.statsTag); 3094 } 3095 } 3096 } 3097 } 3098 } 3099