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