1 /* 2 * Copyright (C) 2018 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.am; 18 19 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST; 20 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST_DEFERRAL; 21 import static com.android.server.am.BroadcastConstants.DEFER_BOOT_COMPLETED_BROADCAST_NONE; 22 23 import android.annotation.NonNull; 24 import android.annotation.Nullable; 25 import android.annotation.UptimeMillisLong; 26 import android.content.Intent; 27 import android.content.pm.ResolveInfo; 28 import android.os.Handler; 29 import android.os.SystemClock; 30 import android.os.UserHandle; 31 import android.util.Slog; 32 import android.util.SparseArray; 33 import android.util.SparseBooleanArray; 34 import android.util.SparseIntArray; 35 import android.util.proto.ProtoOutputStream; 36 37 import com.android.internal.annotations.VisibleForTesting; 38 import com.android.server.AlarmManagerInternal; 39 import com.android.server.LocalServices; 40 41 import dalvik.annotation.optimization.NeverCompile; 42 43 import java.io.PrintWriter; 44 import java.text.SimpleDateFormat; 45 import java.util.ArrayList; 46 import java.util.Set; 47 48 /** 49 * Manages ordered broadcast delivery, applying policy to mitigate the effects of 50 * slow receivers. 51 */ 52 public class BroadcastDispatcher { 53 private static final String TAG = "BroadcastDispatcher"; 54 55 // Deferred broadcasts to one app; times are all uptime time base like 56 // other broadcast-related timekeeping 57 static class Deferrals { 58 final int uid; 59 long deferredAt; // when we started deferring 60 long deferredBy; // how long did we defer by last time? 61 long deferUntil; // when does the next element become deliverable? 62 int alarmCount; 63 64 final ArrayList<BroadcastRecord> broadcasts; 65 Deferrals(int uid, long now, long backoff, int count)66 Deferrals(int uid, long now, long backoff, int count) { 67 this.uid = uid; 68 this.deferredAt = now; 69 this.deferredBy = backoff; 70 this.deferUntil = now + backoff; 71 this.alarmCount = count; 72 broadcasts = new ArrayList<>(); 73 } 74 add(BroadcastRecord br)75 void add(BroadcastRecord br) { 76 broadcasts.add(br); 77 } 78 size()79 int size() { 80 return broadcasts.size(); 81 } 82 isEmpty()83 boolean isEmpty() { 84 return broadcasts.isEmpty(); 85 } 86 87 @NeverCompile dumpDebug(ProtoOutputStream proto, long fieldId)88 void dumpDebug(ProtoOutputStream proto, long fieldId) { 89 for (BroadcastRecord br : broadcasts) { 90 br.dumpDebug(proto, fieldId); 91 } 92 } 93 94 @NeverCompile dumpLocked(Dumper d)95 void dumpLocked(Dumper d) { 96 for (BroadcastRecord br : broadcasts) { 97 d.dump(br); 98 } 99 } 100 101 @Override toString()102 public String toString() { 103 StringBuilder sb = new StringBuilder(128); 104 sb.append("Deferrals{uid="); 105 sb.append(uid); 106 sb.append(", deferUntil="); 107 sb.append(deferUntil); 108 sb.append(", #broadcasts="); 109 sb.append(broadcasts.size()); 110 sb.append("}"); 111 return sb.toString(); 112 } 113 } 114 115 // Carrying dump formatting state across multiple concatenated datasets 116 class Dumper { 117 final PrintWriter mPw; 118 final String mQueueName; 119 final String mDumpPackage; 120 final SimpleDateFormat mSdf; 121 boolean mPrinted; 122 boolean mNeedSep; 123 String mHeading; 124 String mLabel; 125 int mOrdinal; 126 Dumper(PrintWriter pw, String queueName, String dumpPackage, SimpleDateFormat sdf)127 Dumper(PrintWriter pw, String queueName, String dumpPackage, SimpleDateFormat sdf) { 128 mPw = pw; 129 mQueueName = queueName; 130 mDumpPackage = dumpPackage; 131 mSdf = sdf; 132 133 mPrinted = false; 134 mNeedSep = true; 135 } 136 setHeading(String heading)137 void setHeading(String heading) { 138 mHeading = heading; 139 mPrinted = false; 140 } 141 setLabel(String label)142 void setLabel(String label) { 143 //" Active Ordered Broadcast " + mQueueName + " #" + i + ":" 144 mLabel = " " + label + " " + mQueueName + " #"; 145 mOrdinal = 0; 146 } 147 didPrint()148 boolean didPrint() { 149 return mPrinted; 150 } 151 152 @NeverCompile dump(BroadcastRecord br)153 void dump(BroadcastRecord br) { 154 if (mDumpPackage == null || mDumpPackage.equals(br.callerPackage)) { 155 if (!mPrinted) { 156 if (mNeedSep) { 157 mPw.println(); 158 } 159 mPrinted = true; 160 mNeedSep = true; 161 mPw.println(" " + mHeading + " [" + mQueueName + "]:"); 162 } 163 mPw.println(mLabel + mOrdinal + ":"); 164 mOrdinal++; 165 166 br.dump(mPw, " ", mSdf); 167 } 168 } 169 } 170 171 private final Object mLock; 172 private final BroadcastQueueImpl mQueue; 173 private final BroadcastConstants mConstants; 174 private final Handler mHandler; 175 private AlarmManagerInternal mAlarm; 176 177 // Current alarm targets; mapping uid -> in-flight alarm count 178 final SparseIntArray mAlarmUids = new SparseIntArray(); 179 final AlarmManagerInternal.InFlightListener mAlarmListener = 180 new AlarmManagerInternal.InFlightListener() { 181 @Override 182 public void broadcastAlarmPending(final int recipientUid) { 183 synchronized (mLock) { 184 final int newCount = mAlarmUids.get(recipientUid, 0) + 1; 185 mAlarmUids.put(recipientUid, newCount); 186 // any deferred broadcasts to this app now get fast-tracked 187 final int numEntries = mDeferredBroadcasts.size(); 188 for (int i = 0; i < numEntries; i++) { 189 if (recipientUid == mDeferredBroadcasts.get(i).uid) { 190 Deferrals d = mDeferredBroadcasts.remove(i); 191 mAlarmDeferrals.add(d); 192 break; 193 } 194 } 195 } 196 } 197 198 @Override 199 public void broadcastAlarmComplete(final int recipientUid) { 200 synchronized (mLock) { 201 final int newCount = mAlarmUids.get(recipientUid, 0) - 1; 202 if (newCount >= 0) { 203 mAlarmUids.put(recipientUid, newCount); 204 } else { 205 Slog.wtf(TAG, "Undercount of broadcast alarms in flight for " + recipientUid); 206 mAlarmUids.put(recipientUid, 0); 207 } 208 209 // No longer an alarm target, so resume ordinary deferral policy 210 if (newCount <= 0) { 211 final int numEntries = mAlarmDeferrals.size(); 212 for (int i = 0; i < numEntries; i++) { 213 if (recipientUid == mAlarmDeferrals.get(i).uid) { 214 Deferrals d = mAlarmDeferrals.remove(i); 215 insertLocked(mDeferredBroadcasts, d); 216 break; 217 } 218 } 219 } 220 } 221 } 222 }; 223 224 // Queue recheck operation used to tickle broadcast delivery when appropriate 225 final Runnable mScheduleRunnable = new Runnable() { 226 @Override 227 public void run() { 228 synchronized (mLock) { 229 if (DEBUG_BROADCAST_DEFERRAL) { 230 Slog.v(TAG, "Deferral recheck of pending broadcasts"); 231 } 232 mQueue.scheduleBroadcastsLocked(); 233 mRecheckScheduled = false; 234 } 235 } 236 }; 237 private boolean mRecheckScheduled = false; 238 239 // Usual issuance-order outbound queue 240 private final ArrayList<BroadcastRecord> mOrderedBroadcasts = new ArrayList<>(); 241 // General deferrals not holding up alarms 242 private final ArrayList<Deferrals> mDeferredBroadcasts = new ArrayList<>(); 243 // Deferrals that *are* holding up alarms; ordered by alarm dispatch time 244 private final ArrayList<Deferrals> mAlarmDeferrals = new ArrayList<>(); 245 // Under the "deliver alarm broadcasts immediately" policy, the queue of 246 // upcoming alarm broadcasts. These are always delivered first - if the 247 // policy is changed on the fly from immediate-alarm-delivery to the previous 248 // in-order-queueing behavior, pending immediate alarm deliveries will drain 249 // and then the behavior settle into the pre-U semantics. 250 private final ArrayList<BroadcastRecord> mAlarmQueue = new ArrayList<>(); 251 252 // Next outbound broadcast, established by getNextBroadcastLocked() 253 private BroadcastRecord mCurrentBroadcast; 254 255 // Map userId to its deferred boot completed broadcasts. 256 private SparseArray<DeferredBootCompletedBroadcastPerUser> mUser2Deferred = new SparseArray<>(); 257 258 /** 259 * Deferred LOCKED_BOOT_COMPLETED and BOOT_COMPLETED broadcasts that is sent to a user. 260 */ 261 static class DeferredBootCompletedBroadcastPerUser { 262 private int mUserId; 263 // UID that has process started at least once, ready to execute LOCKED_BOOT_COMPLETED 264 // receivers. 265 @VisibleForTesting 266 SparseBooleanArray mUidReadyForLockedBootCompletedBroadcast = new SparseBooleanArray(); 267 // UID that has process started at least once, ready to execute BOOT_COMPLETED receivers. 268 @VisibleForTesting 269 SparseBooleanArray mUidReadyForBootCompletedBroadcast = new SparseBooleanArray(); 270 // Map UID to deferred LOCKED_BOOT_COMPLETED broadcasts. 271 // LOCKED_BOOT_COMPLETED broadcast receivers are deferred until the first time the uid has 272 // any process started. 273 @VisibleForTesting 274 SparseArray<BroadcastRecord> mDeferredLockedBootCompletedBroadcasts = new SparseArray<>(); 275 // is the LOCKED_BOOT_COMPLETED broadcast received by the user. 276 @VisibleForTesting 277 boolean mLockedBootCompletedBroadcastReceived; 278 // Map UID to deferred BOOT_COMPLETED broadcasts. 279 // BOOT_COMPLETED broadcast receivers are deferred until the first time the uid has any 280 // process started. 281 @VisibleForTesting 282 SparseArray<BroadcastRecord> mDeferredBootCompletedBroadcasts = new SparseArray<>(); 283 // is the BOOT_COMPLETED broadcast received by the user. 284 @VisibleForTesting 285 boolean mBootCompletedBroadcastReceived; 286 DeferredBootCompletedBroadcastPerUser(int userId)287 DeferredBootCompletedBroadcastPerUser(int userId) { 288 this.mUserId = userId; 289 } 290 updateUidReady(int uid)291 public void updateUidReady(int uid) { 292 if (!mLockedBootCompletedBroadcastReceived 293 || mDeferredLockedBootCompletedBroadcasts.size() != 0) { 294 mUidReadyForLockedBootCompletedBroadcast.put(uid, true); 295 } 296 if (!mBootCompletedBroadcastReceived 297 || mDeferredBootCompletedBroadcasts.size() != 0) { 298 mUidReadyForBootCompletedBroadcast.put(uid, true); 299 } 300 } 301 enqueueBootCompletedBroadcasts(String action, SparseArray<BroadcastRecord> deferred)302 public void enqueueBootCompletedBroadcasts(String action, 303 SparseArray<BroadcastRecord> deferred) { 304 if (Intent.ACTION_LOCKED_BOOT_COMPLETED.equals(action)) { 305 enqueueBootCompletedBroadcasts(deferred, mDeferredLockedBootCompletedBroadcasts, 306 mUidReadyForLockedBootCompletedBroadcast); 307 mLockedBootCompletedBroadcastReceived = true; 308 if (DEBUG_BROADCAST_DEFERRAL) { 309 dumpBootCompletedBroadcastRecord(mDeferredLockedBootCompletedBroadcasts); 310 } 311 } else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) { 312 enqueueBootCompletedBroadcasts(deferred, mDeferredBootCompletedBroadcasts, 313 mUidReadyForBootCompletedBroadcast); 314 mBootCompletedBroadcastReceived = true; 315 if (DEBUG_BROADCAST_DEFERRAL) { 316 dumpBootCompletedBroadcastRecord(mDeferredBootCompletedBroadcasts); 317 } 318 } 319 } 320 321 /** 322 * Merge UID to BroadcastRecord map into {@link #mDeferredBootCompletedBroadcasts} or 323 * {@link #mDeferredLockedBootCompletedBroadcasts} 324 * @param from the UID to BroadcastRecord map. 325 * @param into The UID to list of BroadcastRecord map. 326 */ enqueueBootCompletedBroadcasts(SparseArray<BroadcastRecord> from, SparseArray<BroadcastRecord> into, SparseBooleanArray uidReadyForReceiver)327 private void enqueueBootCompletedBroadcasts(SparseArray<BroadcastRecord> from, 328 SparseArray<BroadcastRecord> into, SparseBooleanArray uidReadyForReceiver) { 329 // remove unwanted uids from uidReadyForReceiver. 330 for (int i = uidReadyForReceiver.size() - 1; i >= 0; i--) { 331 if (from.indexOfKey(uidReadyForReceiver.keyAt(i)) < 0) { 332 uidReadyForReceiver.removeAt(i); 333 } 334 } 335 for (int i = 0, size = from.size(); i < size; i++) { 336 final int uid = from.keyAt(i); 337 into.put(uid, from.valueAt(i)); 338 if (uidReadyForReceiver.indexOfKey(uid) < 0) { 339 // uid is wanted but not ready. 340 uidReadyForReceiver.put(uid, false); 341 } 342 } 343 } 344 dequeueDeferredBootCompletedBroadcast( boolean isAllUidReady)345 public @Nullable BroadcastRecord dequeueDeferredBootCompletedBroadcast( 346 boolean isAllUidReady) { 347 BroadcastRecord next = dequeueDeferredBootCompletedBroadcast( 348 mDeferredLockedBootCompletedBroadcasts, 349 mUidReadyForLockedBootCompletedBroadcast, isAllUidReady); 350 if (next == null) { 351 next = dequeueDeferredBootCompletedBroadcast(mDeferredBootCompletedBroadcasts, 352 mUidReadyForBootCompletedBroadcast, isAllUidReady); 353 } 354 return next; 355 } 356 dequeueDeferredBootCompletedBroadcast( SparseArray<BroadcastRecord> uid2br, SparseBooleanArray uidReadyForReceiver, boolean isAllUidReady)357 private @Nullable BroadcastRecord dequeueDeferredBootCompletedBroadcast( 358 SparseArray<BroadcastRecord> uid2br, SparseBooleanArray uidReadyForReceiver, 359 boolean isAllUidReady) { 360 for (int i = 0, size = uid2br.size(); i < size; i++) { 361 final int uid = uid2br.keyAt(i); 362 if (isAllUidReady || uidReadyForReceiver.get(uid)) { 363 final BroadcastRecord br = uid2br.valueAt(i); 364 if (DEBUG_BROADCAST_DEFERRAL) { 365 final Object receiver = br.receivers.get(0); 366 if (receiver instanceof BroadcastFilter) { 367 if (DEBUG_BROADCAST_DEFERRAL) { 368 Slog.i(TAG, "getDeferredBootCompletedBroadcast uid:" + uid 369 + " BroadcastFilter:" + (BroadcastFilter) receiver 370 + " broadcast:" + br.intent.getAction()); 371 } 372 } else /* if (receiver instanceof ResolveInfo) */ { 373 ResolveInfo info = (ResolveInfo) receiver; 374 String packageName = info.activityInfo.applicationInfo.packageName; 375 if (DEBUG_BROADCAST_DEFERRAL) { 376 Slog.i(TAG, "getDeferredBootCompletedBroadcast uid:" + uid 377 + " packageName:" + packageName 378 + " broadcast:" + br.intent.getAction()); 379 } 380 } 381 } 382 // remove the BroadcastRecord. 383 uid2br.removeAt(i); 384 if (uid2br.size() == 0) { 385 // All deferred receivers are executed, do not need uidReadyForReceiver 386 // any more. 387 uidReadyForReceiver.clear(); 388 } 389 return br; 390 } 391 } 392 return null; 393 } 394 getDeferredList(String action)395 private @Nullable SparseArray<BroadcastRecord> getDeferredList(String action) { 396 SparseArray<BroadcastRecord> brs = null; 397 if (action.equals(Intent.ACTION_LOCKED_BOOT_COMPLETED)) { 398 brs = mDeferredLockedBootCompletedBroadcasts; 399 } else if (action.equals(Intent.ACTION_BOOT_COMPLETED)) { 400 brs = mDeferredBootCompletedBroadcasts; 401 } 402 return brs; 403 } 404 405 /** 406 * Return the total number of UIDs in all BroadcastRecord in 407 * {@link #mDeferredBootCompletedBroadcasts} or 408 * {@link #mDeferredLockedBootCompletedBroadcasts} 409 */ getBootCompletedBroadcastsUidsSize(String action)410 private int getBootCompletedBroadcastsUidsSize(String action) { 411 SparseArray<BroadcastRecord> brs = getDeferredList(action); 412 return brs != null ? brs.size() : 0; 413 } 414 415 /** 416 * Return the total number of receivers in all BroadcastRecord in 417 * {@link #mDeferredBootCompletedBroadcasts} or 418 * {@link #mDeferredLockedBootCompletedBroadcasts} 419 */ getBootCompletedBroadcastsReceiversSize(String action)420 private int getBootCompletedBroadcastsReceiversSize(String action) { 421 SparseArray<BroadcastRecord> brs = getDeferredList(action); 422 if (brs == null) { 423 return 0; 424 } 425 int size = 0; 426 for (int i = 0, s = brs.size(); i < s; i++) { 427 size += brs.valueAt(i).receivers.size(); 428 } 429 return size; 430 } 431 432 @NeverCompile dump(Dumper dumper, String action)433 public void dump(Dumper dumper, String action) { 434 SparseArray<BroadcastRecord> brs = getDeferredList(action); 435 if (brs == null) { 436 return; 437 } 438 for (int i = 0, size = brs.size(); i < size; i++) { 439 dumper.dump(brs.valueAt(i)); 440 } 441 } 442 443 @NeverCompile dumpDebug(ProtoOutputStream proto, long fieldId)444 public void dumpDebug(ProtoOutputStream proto, long fieldId) { 445 for (int i = 0, size = mDeferredLockedBootCompletedBroadcasts.size(); i < size; i++) { 446 mDeferredLockedBootCompletedBroadcasts.valueAt(i).dumpDebug(proto, fieldId); 447 } 448 for (int i = 0, size = mDeferredBootCompletedBroadcasts.size(); i < size; i++) { 449 mDeferredBootCompletedBroadcasts.valueAt(i).dumpDebug(proto, fieldId); 450 } 451 } 452 453 @NeverCompile dumpBootCompletedBroadcastRecord(SparseArray<BroadcastRecord> brs)454 private void dumpBootCompletedBroadcastRecord(SparseArray<BroadcastRecord> brs) { 455 for (int i = 0, size = brs.size(); i < size; i++) { 456 final Object receiver = brs.valueAt(i).receivers.get(0); 457 String packageName = null; 458 if (receiver instanceof BroadcastFilter) { 459 BroadcastFilter recv = (BroadcastFilter) receiver; 460 packageName = recv.receiverList.app.processName; 461 } else /* if (receiver instanceof ResolveInfo) */ { 462 ResolveInfo info = (ResolveInfo) receiver; 463 packageName = info.activityInfo.applicationInfo.packageName; 464 } 465 Slog.i(TAG, "uid:" + brs.keyAt(i) 466 + " packageName:" + packageName 467 + " receivers:" + brs.valueAt(i).receivers.size()); 468 } 469 } 470 } 471 getDeferredPerUser(int userId)472 private DeferredBootCompletedBroadcastPerUser getDeferredPerUser(int userId) { 473 if (mUser2Deferred.contains(userId)) { 474 return mUser2Deferred.get(userId); 475 } else { 476 final DeferredBootCompletedBroadcastPerUser temp = 477 new DeferredBootCompletedBroadcastPerUser(userId); 478 mUser2Deferred.put(userId, temp); 479 return temp; 480 } 481 } 482 483 /** 484 * ActivityManagerService.attachApplication() call this method to notify that the UID is ready 485 * to accept deferred LOCKED_BOOT_COMPLETED and BOOT_COMPLETED broadcasts. 486 * @param uid 487 */ updateUidReadyForBootCompletedBroadcastLocked(int uid)488 public void updateUidReadyForBootCompletedBroadcastLocked(int uid) { 489 getDeferredPerUser(UserHandle.getUserId(uid)).updateUidReady(uid); 490 } 491 dequeueDeferredBootCompletedBroadcast()492 private @Nullable BroadcastRecord dequeueDeferredBootCompletedBroadcast() { 493 final boolean isAllUidReady = (mQueue.mService.mConstants.mDeferBootCompletedBroadcast 494 == DEFER_BOOT_COMPLETED_BROADCAST_NONE); 495 BroadcastRecord next = null; 496 for (int i = 0, size = mUser2Deferred.size(); i < size; i++) { 497 next = mUser2Deferred.valueAt(i).dequeueDeferredBootCompletedBroadcast(isAllUidReady); 498 if (next != null) { 499 break; 500 } 501 } 502 return next; 503 } 504 505 /** 506 * Constructed & sharing a lock with its associated BroadcastQueue instance 507 */ BroadcastDispatcher(BroadcastQueueImpl queue, BroadcastConstants constants, Handler handler, Object lock)508 public BroadcastDispatcher(BroadcastQueueImpl queue, BroadcastConstants constants, 509 Handler handler, Object lock) { 510 mQueue = queue; 511 mConstants = constants; 512 mHandler = handler; 513 mLock = lock; 514 } 515 516 /** 517 * Spin up the integration with the alarm manager service; done lazily to manage 518 * service availability ordering during boot. 519 */ start()520 public void start() { 521 // Set up broadcast alarm tracking 522 mAlarm = LocalServices.getService(AlarmManagerInternal.class); 523 mAlarm.registerInFlightListener(mAlarmListener); 524 } 525 526 /** 527 * Standard contents-are-empty check 528 */ isEmpty()529 public boolean isEmpty() { 530 synchronized (mLock) { 531 return isIdle() 532 && getBootCompletedBroadcastsUidsSize(Intent.ACTION_LOCKED_BOOT_COMPLETED) == 0 533 && getBootCompletedBroadcastsUidsSize(Intent.ACTION_BOOT_COMPLETED) == 0; 534 } 535 } 536 537 /** 538 * Have less check than {@link #isEmpty()}. 539 * The dispatcher is considered as idle even with deferred LOCKED_BOOT_COMPLETED/BOOT_COMPLETED 540 * broadcasts because those can be deferred until the first time the uid's process is started. 541 * @return 542 */ isIdle()543 public boolean isIdle() { 544 synchronized (mLock) { 545 return mCurrentBroadcast == null 546 && mOrderedBroadcasts.isEmpty() 547 && mAlarmQueue.isEmpty() 548 && isDeferralsListEmpty(mDeferredBroadcasts) 549 && isDeferralsListEmpty(mAlarmDeferrals); 550 } 551 } 552 isDeferralsBeyondBarrier(@onNull ArrayList<Deferrals> list, @UptimeMillisLong long barrierTime)553 private static boolean isDeferralsBeyondBarrier(@NonNull ArrayList<Deferrals> list, 554 @UptimeMillisLong long barrierTime) { 555 for (int i = 0; i < list.size(); i++) { 556 if (!isBeyondBarrier(list.get(i).broadcasts, barrierTime)) { 557 return false; 558 } 559 } 560 return true; 561 } 562 isBeyondBarrier(@onNull ArrayList<BroadcastRecord> list, @UptimeMillisLong long barrierTime)563 private static boolean isBeyondBarrier(@NonNull ArrayList<BroadcastRecord> list, 564 @UptimeMillisLong long barrierTime) { 565 for (int i = 0; i < list.size(); i++) { 566 if (list.get(i).enqueueTime <= barrierTime) { 567 return false; 568 } 569 } 570 return true; 571 } 572 isBeyondBarrier(@ptimeMillisLong long barrierTime)573 public boolean isBeyondBarrier(@UptimeMillisLong long barrierTime) { 574 synchronized (mLock) { 575 if ((mCurrentBroadcast != null) && mCurrentBroadcast.enqueueTime <= barrierTime) { 576 return false; 577 } 578 return isBeyondBarrier(mOrderedBroadcasts, barrierTime) 579 && isBeyondBarrier(mAlarmQueue, barrierTime) 580 && isDeferralsBeyondBarrier(mDeferredBroadcasts, barrierTime) 581 && isDeferralsBeyondBarrier(mAlarmDeferrals, barrierTime); 582 } 583 } 584 isDispatchedInDeferrals(@onNull ArrayList<Deferrals> list, @NonNull Intent intent)585 private static boolean isDispatchedInDeferrals(@NonNull ArrayList<Deferrals> list, 586 @NonNull Intent intent) { 587 for (int i = 0; i < list.size(); i++) { 588 if (!isDispatched(list.get(i).broadcasts, intent)) { 589 return false; 590 } 591 } 592 return true; 593 } 594 isDispatched(@onNull ArrayList<BroadcastRecord> list, @NonNull Intent intent)595 private static boolean isDispatched(@NonNull ArrayList<BroadcastRecord> list, 596 @NonNull Intent intent) { 597 for (int i = 0; i < list.size(); i++) { 598 if (intent.filterEquals(list.get(i).intent)) { 599 return false; 600 } 601 } 602 return true; 603 } 604 isDispatched(@onNull Intent intent)605 public boolean isDispatched(@NonNull Intent intent) { 606 synchronized (mLock) { 607 if ((mCurrentBroadcast != null) && intent.filterEquals(mCurrentBroadcast.intent)) { 608 return false; 609 } 610 return isDispatched(mOrderedBroadcasts, intent) 611 && isDispatched(mAlarmQueue, intent) 612 && isDispatchedInDeferrals(mDeferredBroadcasts, intent) 613 && isDispatchedInDeferrals(mAlarmDeferrals, intent); 614 } 615 } 616 pendingInDeferralsList(ArrayList<Deferrals> list)617 private static int pendingInDeferralsList(ArrayList<Deferrals> list) { 618 int pending = 0; 619 final int numEntries = list.size(); 620 for (int i = 0; i < numEntries; i++) { 621 pending += list.get(i).size(); 622 } 623 return pending; 624 } 625 isDeferralsListEmpty(ArrayList<Deferrals> list)626 private static boolean isDeferralsListEmpty(ArrayList<Deferrals> list) { 627 return pendingInDeferralsList(list) == 0; 628 } 629 630 /** 631 * Strictly for logging, describe the currently pending contents in a human- 632 * readable way 633 */ describeStateLocked()634 public String describeStateLocked() { 635 final StringBuilder sb = new StringBuilder(128); 636 if (mCurrentBroadcast != null) { 637 sb.append("1 in flight, "); 638 } 639 sb.append(mOrderedBroadcasts.size()); 640 sb.append(" ordered"); 641 int n = mAlarmQueue.size(); 642 if (n > 0) { 643 sb.append(", "); 644 sb.append(n); 645 sb.append(" alarms"); 646 } 647 n = pendingInDeferralsList(mAlarmDeferrals); 648 if (n > 0) { 649 sb.append(", "); 650 sb.append(n); 651 sb.append(" deferrals in alarm recipients"); 652 } 653 n = pendingInDeferralsList(mDeferredBroadcasts); 654 if (n > 0) { 655 sb.append(", "); 656 sb.append(n); 657 sb.append(" deferred"); 658 } 659 n = getBootCompletedBroadcastsUidsSize(Intent.ACTION_LOCKED_BOOT_COMPLETED); 660 if (n > 0) { 661 sb.append(", "); 662 sb.append(n); 663 sb.append(" deferred LOCKED_BOOT_COMPLETED/"); 664 sb.append(getBootCompletedBroadcastsReceiversSize(Intent.ACTION_LOCKED_BOOT_COMPLETED)); 665 sb.append(" receivers"); 666 } 667 668 n = getBootCompletedBroadcastsUidsSize(Intent.ACTION_BOOT_COMPLETED); 669 if (n > 0) { 670 sb.append(", "); 671 sb.append(n); 672 sb.append(" deferred BOOT_COMPLETED/"); 673 sb.append(getBootCompletedBroadcastsReceiversSize(Intent.ACTION_BOOT_COMPLETED)); 674 sb.append(" receivers"); 675 } 676 return sb.toString(); 677 } 678 679 // ---------------------------------- 680 // BroadcastQueue operation support enqueueOrderedBroadcastLocked(BroadcastRecord r)681 void enqueueOrderedBroadcastLocked(BroadcastRecord r) { 682 final ArrayList<BroadcastRecord> queue = 683 (r.alarm && mQueue.mService.mConstants.mPrioritizeAlarmBroadcasts) 684 ? mAlarmQueue 685 : mOrderedBroadcasts; 686 687 if (r.receivers == null || r.receivers.isEmpty()) { 688 // Fast no-op path for broadcasts that won't actually be dispatched to 689 // receivers - we still need to handle completion callbacks and historical 690 // records, but we don't need to consider the fancy cases. 691 queue.add(r); 692 return; 693 } 694 695 if (Intent.ACTION_LOCKED_BOOT_COMPLETED.equals(r.intent.getAction())) { 696 // Create one BroadcastRecord for each UID that can be deferred. 697 final SparseArray<BroadcastRecord> deferred = 698 r.splitDeferredBootCompletedBroadcastLocked(mQueue.mService.mInternal, 699 mQueue.mService.mConstants.mDeferBootCompletedBroadcast); 700 getDeferredPerUser(r.userId).enqueueBootCompletedBroadcasts( 701 Intent.ACTION_LOCKED_BOOT_COMPLETED, deferred); 702 if (!r.receivers.isEmpty()) { 703 // The non-deferred receivers. 704 mOrderedBroadcasts.add(r); 705 return; 706 } 707 } else if (Intent.ACTION_BOOT_COMPLETED.equals(r.intent.getAction())) { 708 // Create one BroadcastRecord for each UID that can be deferred. 709 final SparseArray<BroadcastRecord> deferred = 710 r.splitDeferredBootCompletedBroadcastLocked(mQueue.mService.mInternal, 711 mQueue.mService.mConstants.mDeferBootCompletedBroadcast); 712 getDeferredPerUser(r.userId).enqueueBootCompletedBroadcasts( 713 Intent.ACTION_BOOT_COMPLETED, deferred); 714 if (!r.receivers.isEmpty()) { 715 // The non-deferred receivers. 716 mOrderedBroadcasts.add(r); 717 return; 718 } 719 } else { 720 // Ordinary broadcast, so put it on the appropriate queue and carry on 721 queue.add(r); 722 } 723 } 724 725 /** 726 * Return the total number of UIDs in all deferred boot completed BroadcastRecord. 727 */ getBootCompletedBroadcastsUidsSize(String action)728 private int getBootCompletedBroadcastsUidsSize(String action) { 729 int size = 0; 730 for (int i = 0, s = mUser2Deferred.size(); i < s; i++) { 731 size += mUser2Deferred.valueAt(i).getBootCompletedBroadcastsUidsSize(action); 732 } 733 return size; 734 } 735 736 /** 737 * Return the total number of receivers in all deferred boot completed BroadcastRecord. 738 */ getBootCompletedBroadcastsReceiversSize(String action)739 private int getBootCompletedBroadcastsReceiversSize(String action) { 740 int size = 0; 741 for (int i = 0, s = mUser2Deferred.size(); i < s; i++) { 742 size += mUser2Deferred.valueAt(i).getBootCompletedBroadcastsReceiversSize(action); 743 } 744 return size; 745 } 746 747 // Returns the now-replaced broadcast record, or null if none replaceBroadcastLocked(BroadcastRecord r, String typeForLogging)748 BroadcastRecord replaceBroadcastLocked(BroadcastRecord r, String typeForLogging) { 749 // Simple case, in the ordinary queue. 750 BroadcastRecord old = replaceBroadcastLocked(mOrderedBroadcasts, r, typeForLogging); 751 // ... or possibly in the simple alarm queue 752 if (old == null) { 753 old = replaceBroadcastLocked(mAlarmQueue, r, typeForLogging); 754 } 755 // If we didn't find it, less-simple: in a deferral queue? 756 if (old == null) { 757 old = replaceDeferredBroadcastLocked(mAlarmDeferrals, r, typeForLogging); 758 } 759 if (old == null) { 760 old = replaceDeferredBroadcastLocked(mDeferredBroadcasts, r, typeForLogging); 761 } 762 return old; 763 } 764 replaceDeferredBroadcastLocked(ArrayList<Deferrals> list, BroadcastRecord r, String typeForLogging)765 private BroadcastRecord replaceDeferredBroadcastLocked(ArrayList<Deferrals> list, 766 BroadcastRecord r, String typeForLogging) { 767 BroadcastRecord old; 768 final int numEntries = list.size(); 769 for (int i = 0; i < numEntries; i++) { 770 final Deferrals d = list.get(i); 771 old = replaceBroadcastLocked(d.broadcasts, r, typeForLogging); 772 if (old != null) { 773 return old; 774 } 775 } 776 return null; 777 } 778 replaceBroadcastLocked(ArrayList<BroadcastRecord> list, BroadcastRecord r, String typeForLogging)779 private BroadcastRecord replaceBroadcastLocked(ArrayList<BroadcastRecord> list, 780 BroadcastRecord r, String typeForLogging) { 781 BroadcastRecord old; 782 final Intent intent = r.intent; 783 // Any in-flight broadcast has already been popped, and cannot be replaced. 784 // (This preserves existing behavior of the replacement API) 785 for (int i = list.size() - 1; i >= 0; i--) { 786 old = list.get(i); 787 if (old.userId == r.userId && intent.filterEquals(old.intent)) { 788 if (DEBUG_BROADCAST) { 789 Slog.v(TAG, "***** Replacing " + typeForLogging 790 + " [" + mQueue.mQueueName + "]: " + intent); 791 } 792 // Clone deferral state too if any 793 r.deferred = old.deferred; 794 list.set(i, r); 795 return old; 796 } 797 } 798 return null; 799 } 800 cleanupDisabledPackageReceiversLocked(final String packageName, Set<String> filterByClasses, final int userId, final boolean doit)801 boolean cleanupDisabledPackageReceiversLocked(final String packageName, 802 Set<String> filterByClasses, final int userId, final boolean doit) { 803 // Note: fast short circuits when 'doit' is false, as soon as we hit any 804 // "yes we would do something" circumstance 805 boolean didSomething = cleanupBroadcastListDisabledReceiversLocked(mOrderedBroadcasts, 806 packageName, filterByClasses, userId, doit); 807 if (doit || !didSomething) { 808 didSomething = cleanupBroadcastListDisabledReceiversLocked(mAlarmQueue, 809 packageName, filterByClasses, userId, doit); 810 } 811 if (doit || !didSomething) { 812 ArrayList<BroadcastRecord> lockedBootCompletedBroadcasts = new ArrayList<>(); 813 for (int u = 0, usize = mUser2Deferred.size(); u < usize; u++) { 814 SparseArray<BroadcastRecord> brs = 815 mUser2Deferred.valueAt(u).mDeferredLockedBootCompletedBroadcasts; 816 for (int i = 0, size = brs.size(); i < size; i++) { 817 lockedBootCompletedBroadcasts.add(brs.valueAt(i)); 818 } 819 } 820 didSomething = cleanupBroadcastListDisabledReceiversLocked( 821 lockedBootCompletedBroadcasts, 822 packageName, filterByClasses, userId, doit); 823 } 824 if (doit || !didSomething) { 825 ArrayList<BroadcastRecord> bootCompletedBroadcasts = new ArrayList<>(); 826 for (int u = 0, usize = mUser2Deferred.size(); u < usize; u++) { 827 SparseArray<BroadcastRecord> brs = 828 mUser2Deferred.valueAt(u).mDeferredBootCompletedBroadcasts; 829 for (int i = 0, size = brs.size(); i < size; i++) { 830 bootCompletedBroadcasts.add(brs.valueAt(i)); 831 } 832 } 833 didSomething = cleanupBroadcastListDisabledReceiversLocked(bootCompletedBroadcasts, 834 packageName, filterByClasses, userId, doit); 835 } 836 if (doit || !didSomething) { 837 didSomething |= cleanupDeferralsListDisabledReceiversLocked(mAlarmDeferrals, 838 packageName, filterByClasses, userId, doit); 839 } 840 if (doit || !didSomething) { 841 didSomething |= cleanupDeferralsListDisabledReceiversLocked(mDeferredBroadcasts, 842 packageName, filterByClasses, userId, doit); 843 } 844 if ((doit || !didSomething) && mCurrentBroadcast != null) { 845 didSomething |= mCurrentBroadcast.cleanupDisabledPackageReceiversLocked( 846 packageName, filterByClasses, userId, doit); 847 } 848 849 return didSomething; 850 } 851 cleanupDeferralsListDisabledReceiversLocked(ArrayList<Deferrals> list, final String packageName, Set<String> filterByClasses, final int userId, final boolean doit)852 private boolean cleanupDeferralsListDisabledReceiversLocked(ArrayList<Deferrals> list, 853 final String packageName, Set<String> filterByClasses, final int userId, 854 final boolean doit) { 855 boolean didSomething = false; 856 for (Deferrals d : list) { 857 didSomething = cleanupBroadcastListDisabledReceiversLocked(d.broadcasts, 858 packageName, filterByClasses, userId, doit); 859 if (!doit && didSomething) { 860 return true; 861 } 862 } 863 return didSomething; 864 } 865 cleanupBroadcastListDisabledReceiversLocked(ArrayList<BroadcastRecord> list, final String packageName, Set<String> filterByClasses, final int userId, final boolean doit)866 private boolean cleanupBroadcastListDisabledReceiversLocked(ArrayList<BroadcastRecord> list, 867 final String packageName, Set<String> filterByClasses, final int userId, 868 final boolean doit) { 869 boolean didSomething = false; 870 for (BroadcastRecord br : list) { 871 didSomething |= br.cleanupDisabledPackageReceiversLocked(packageName, 872 filterByClasses, userId, doit); 873 if (!doit && didSomething) { 874 return true; 875 } 876 } 877 return didSomething; 878 } 879 880 /** 881 * Standard proto dump entry point 882 */ 883 @NeverCompile dumpDebug(ProtoOutputStream proto, long fieldId)884 public void dumpDebug(ProtoOutputStream proto, long fieldId) { 885 if (mCurrentBroadcast != null) { 886 mCurrentBroadcast.dumpDebug(proto, fieldId); 887 } 888 for (Deferrals d : mAlarmDeferrals) { 889 d.dumpDebug(proto, fieldId); 890 } 891 for (BroadcastRecord br : mOrderedBroadcasts) { 892 br.dumpDebug(proto, fieldId); 893 } 894 for (BroadcastRecord br : mAlarmQueue) { 895 br.dumpDebug(proto, fieldId); 896 } 897 for (Deferrals d : mDeferredBroadcasts) { 898 d.dumpDebug(proto, fieldId); 899 } 900 901 for (int i = 0, size = mUser2Deferred.size(); i < size; i++) { 902 mUser2Deferred.valueAt(i).dumpDebug(proto, fieldId); 903 } 904 } 905 906 // ---------------------------------- 907 // Dispatch & deferral management 908 getActiveBroadcastLocked()909 public BroadcastRecord getActiveBroadcastLocked() { 910 return mCurrentBroadcast; 911 } 912 913 /** 914 * If there is a deferred broadcast that is being sent to an alarm target, return 915 * that one. If there's no deferred alarm target broadcast but there is one 916 * that has reached the end of its deferral, return that. 917 * 918 * This stages the broadcast internally until it is retired, and returns that 919 * staged record if this is called repeatedly, until retireBroadcast(r) is called. 920 */ getNextBroadcastLocked(final long now)921 public BroadcastRecord getNextBroadcastLocked(final long now) { 922 if (mCurrentBroadcast != null) { 923 return mCurrentBroadcast; 924 } 925 926 BroadcastRecord next = null; 927 928 // Alarms in flight take precedence over everything else. This queue 929 // will be non-empty only when the relevant policy is in force, but if 930 // policy has changed on the fly we still need to drain this before we 931 // settle into the legacy behavior. 932 if (!mAlarmQueue.isEmpty()) { 933 next = mAlarmQueue.remove(0); 934 } 935 936 // Next in precedence are deferred BOOT_COMPLETED broadcasts 937 if (next == null) { 938 next = dequeueDeferredBootCompletedBroadcast(); 939 } 940 941 // Alarm-related deferrals are next in precedence... 942 if (next == null && !mAlarmDeferrals.isEmpty()) { 943 next = popLocked(mAlarmDeferrals); 944 if (DEBUG_BROADCAST_DEFERRAL && next != null) { 945 Slog.i(TAG, "Next broadcast from alarm targets: " + next); 946 } 947 } 948 949 final boolean someQueued = !mOrderedBroadcasts.isEmpty(); 950 951 if (next == null && !mDeferredBroadcasts.isEmpty()) { 952 // A this point we're going to deliver either: 953 // 1. the next "overdue" deferral; or 954 // 2. the next ordinary ordered broadcast; *or* 955 // 3. the next not-yet-overdue deferral. 956 957 for (int i = 0; i < mDeferredBroadcasts.size(); i++) { 958 Deferrals d = mDeferredBroadcasts.get(i); 959 if (now < d.deferUntil && someQueued) { 960 // stop looking when we haven't hit the next time-out boundary 961 // but only if we have un-deferred broadcasts waiting, 962 // otherwise we can deliver whatever deferred broadcast 963 // is next available. 964 break; 965 } 966 967 if (d.broadcasts.size() > 0) { 968 next = d.broadcasts.remove(0); 969 // apply deferral-interval decay policy and move this uid's 970 // deferred broadcasts down in the delivery queue accordingly 971 mDeferredBroadcasts.remove(i); // already 'd' 972 d.deferredBy = calculateDeferral(d.deferredBy); 973 d.deferUntil += d.deferredBy; 974 insertLocked(mDeferredBroadcasts, d); 975 if (DEBUG_BROADCAST_DEFERRAL) { 976 Slog.i(TAG, "Next broadcast from deferrals " + next 977 + ", deferUntil now " + d.deferUntil); 978 } 979 break; 980 } 981 } 982 } 983 984 if (next == null && someQueued) { 985 next = mOrderedBroadcasts.remove(0); 986 if (DEBUG_BROADCAST_DEFERRAL) { 987 Slog.i(TAG, "Next broadcast from main queue: " + next); 988 } 989 } 990 991 mCurrentBroadcast = next; 992 return next; 993 } 994 995 /** 996 * Called after the broadcast queue finishes processing the currently 997 * active broadcast (obtained by calling getNextBroadcastLocked()). 998 */ retireBroadcastLocked(final BroadcastRecord r)999 public void retireBroadcastLocked(final BroadcastRecord r) { 1000 // ERROR if 'r' is not the active broadcast 1001 if (r != mCurrentBroadcast) { 1002 Slog.wtf(TAG, "Retiring broadcast " + r 1003 + " doesn't match current outgoing " + mCurrentBroadcast); 1004 } 1005 mCurrentBroadcast = null; 1006 } 1007 1008 /** 1009 * Called prior to broadcast dispatch to check whether the intended 1010 * recipient is currently subject to deferral policy. 1011 */ isDeferringLocked(final int uid)1012 public boolean isDeferringLocked(final int uid) { 1013 Deferrals d = findUidLocked(uid); 1014 if (d != null && d.broadcasts.isEmpty()) { 1015 // once we've caught up with deferred broadcasts to this uid 1016 // and time has advanced sufficiently that we wouldn't be 1017 // deferring newly-enqueued ones, we're back to normal policy. 1018 if (SystemClock.uptimeMillis() >= d.deferUntil) { 1019 if (DEBUG_BROADCAST_DEFERRAL) { 1020 Slog.i(TAG, "No longer deferring broadcasts to uid " + d.uid); 1021 } 1022 removeDeferral(d); 1023 return false; 1024 } 1025 } 1026 return (d != null); 1027 } 1028 1029 /** 1030 * Defer broadcasts for the given app. If 'br' is non-null, this also makes 1031 * sure that broadcast record is enqueued as the next upcoming broadcast for 1032 * the app. 1033 */ startDeferring(final int uid)1034 public void startDeferring(final int uid) { 1035 synchronized (mLock) { 1036 Deferrals d = findUidLocked(uid); 1037 1038 // If we're not yet tracking this app, set up that bookkeeping 1039 if (d == null) { 1040 // Start a new deferral 1041 final long now = SystemClock.uptimeMillis(); 1042 d = new Deferrals(uid, 1043 now, 1044 mConstants.DEFERRAL, 1045 mAlarmUids.get(uid, 0)); 1046 if (DEBUG_BROADCAST_DEFERRAL) { 1047 Slog.i(TAG, "Now deferring broadcasts to " + uid 1048 + " until " + d.deferUntil); 1049 } 1050 // where it goes depends on whether it is coming into an alarm-related situation 1051 if (d.alarmCount == 0) { 1052 // common case, put it in the ordinary priority queue 1053 insertLocked(mDeferredBroadcasts, d); 1054 scheduleDeferralCheckLocked(true); 1055 } else { 1056 // alarm-related: strict order-encountered 1057 mAlarmDeferrals.add(d); 1058 } 1059 } else { 1060 // We're already deferring, but something was slow again. Reset the 1061 // deferral decay progression. 1062 d.deferredBy = mConstants.DEFERRAL; 1063 if (DEBUG_BROADCAST_DEFERRAL) { 1064 Slog.i(TAG, "Uid " + uid + " slow again, deferral interval reset to " 1065 + d.deferredBy); 1066 } 1067 } 1068 } 1069 } 1070 1071 /** 1072 * Key entry point when a broadcast about to be delivered is instead 1073 * set aside for deferred delivery 1074 */ addDeferredBroadcast(final int uid, BroadcastRecord br)1075 public void addDeferredBroadcast(final int uid, BroadcastRecord br) { 1076 if (DEBUG_BROADCAST_DEFERRAL) { 1077 Slog.i(TAG, "Enqueuing deferred broadcast " + br); 1078 } 1079 synchronized (mLock) { 1080 Deferrals d = findUidLocked(uid); 1081 if (d == null) { 1082 Slog.wtf(TAG, "Adding deferred broadcast but not tracking " + uid); 1083 } else { 1084 if (br == null) { 1085 Slog.wtf(TAG, "Deferring null broadcast to " + uid); 1086 } else { 1087 br.deferred = true; 1088 d.add(br); 1089 } 1090 } 1091 } 1092 } 1093 1094 /** 1095 * When there are deferred broadcasts, we need to make sure to recheck the 1096 * dispatch queue when they come due. Alarm-sensitive deferrals get dispatched 1097 * aggressively, so we only need to use the ordinary deferrals timing to figure 1098 * out when to recheck. 1099 */ scheduleDeferralCheckLocked(boolean force)1100 public void scheduleDeferralCheckLocked(boolean force) { 1101 if ((force || !mRecheckScheduled) && !mDeferredBroadcasts.isEmpty()) { 1102 final Deferrals d = mDeferredBroadcasts.get(0); 1103 if (!d.broadcasts.isEmpty()) { 1104 mHandler.removeCallbacks(mScheduleRunnable); 1105 mHandler.postAtTime(mScheduleRunnable, d.deferUntil); 1106 mRecheckScheduled = true; 1107 if (DEBUG_BROADCAST_DEFERRAL) { 1108 Slog.i(TAG, "Scheduling deferred broadcast recheck at " + d.deferUntil); 1109 } 1110 } 1111 } 1112 } 1113 1114 /** 1115 * Cancel all current deferrals; that is, make all currently-deferred broadcasts 1116 * immediately deliverable. Used by the wait-for-broadcast-idle mechanism. 1117 */ cancelDeferralsLocked()1118 public void cancelDeferralsLocked() { 1119 zeroDeferralTimes(mAlarmDeferrals); 1120 zeroDeferralTimes(mDeferredBroadcasts); 1121 } 1122 zeroDeferralTimes(ArrayList<Deferrals> list)1123 private static void zeroDeferralTimes(ArrayList<Deferrals> list) { 1124 final int num = list.size(); 1125 for (int i = 0; i < num; i++) { 1126 Deferrals d = list.get(i); 1127 // Safe to do this in-place because it won't break ordering 1128 d.deferUntil = d.deferredBy = 0; 1129 } 1130 } 1131 1132 // ---------------------------------- 1133 1134 /** 1135 * If broadcasts to this uid are being deferred, find the deferrals record about it. 1136 * @return null if this uid's broadcasts are not being deferred 1137 */ findUidLocked(final int uid)1138 private Deferrals findUidLocked(final int uid) { 1139 // The common case is that they it isn't also an alarm target... 1140 Deferrals d = findUidLocked(uid, mDeferredBroadcasts); 1141 // ...but if not there, also check alarm-prioritized deferrals 1142 if (d == null) { 1143 d = findUidLocked(uid, mAlarmDeferrals); 1144 } 1145 return d; 1146 } 1147 1148 /** 1149 * Remove the given deferral record from whichever queue it might be in at present 1150 * @return true if the deferral was in fact found, false if this made no changes 1151 */ removeDeferral(Deferrals d)1152 private boolean removeDeferral(Deferrals d) { 1153 boolean didRemove = mDeferredBroadcasts.remove(d); 1154 if (!didRemove) { 1155 didRemove = mAlarmDeferrals.remove(d); 1156 } 1157 return didRemove; 1158 } 1159 1160 /** 1161 * Find the deferrals record for the given uid in the given list 1162 */ findUidLocked(final int uid, ArrayList<Deferrals> list)1163 private static Deferrals findUidLocked(final int uid, ArrayList<Deferrals> list) { 1164 final int numElements = list.size(); 1165 for (int i = 0; i < numElements; i++) { 1166 Deferrals d = list.get(i); 1167 if (uid == d.uid) { 1168 return d; 1169 } 1170 } 1171 return null; 1172 } 1173 1174 /** 1175 * Pop the next broadcast record from the head of the given deferrals list, 1176 * if one exists. 1177 */ popLocked(ArrayList<Deferrals> list)1178 private static BroadcastRecord popLocked(ArrayList<Deferrals> list) { 1179 final Deferrals d = list.get(0); 1180 return d.broadcasts.isEmpty() ? null : d.broadcasts.remove(0); 1181 } 1182 1183 /** 1184 * Insert the given Deferrals into the priority queue, sorted by defer-until milestone 1185 */ insertLocked(ArrayList<Deferrals> list, Deferrals d)1186 private static void insertLocked(ArrayList<Deferrals> list, Deferrals d) { 1187 // Simple linear search is appropriate here because we expect to 1188 // have very few entries in the deferral lists (i.e. very few badly- 1189 // behaving apps currently facing deferral) 1190 int i; 1191 final int numElements = list.size(); 1192 for (i = 0; i < numElements; i++) { 1193 if (d.deferUntil < list.get(i).deferUntil) { 1194 break; 1195 } 1196 } 1197 list.add(i, d); 1198 } 1199 1200 /** 1201 * Calculate a new deferral time based on the previous time. This should decay 1202 * toward zero, though a small nonzero floor is an option. 1203 */ calculateDeferral(long previous)1204 private long calculateDeferral(long previous) { 1205 return Math.max(mConstants.DEFERRAL_FLOOR, 1206 (long) (previous * mConstants.DEFERRAL_DECAY_FACTOR)); 1207 } 1208 1209 // ---------------------------------- 1210 1211 @NeverCompile dumpLocked(PrintWriter pw, String dumpPackage, String queueName, SimpleDateFormat sdf)1212 boolean dumpLocked(PrintWriter pw, String dumpPackage, String queueName, 1213 SimpleDateFormat sdf) { 1214 final Dumper dumper = new Dumper(pw, queueName, dumpPackage, sdf); 1215 boolean printed = false; 1216 1217 dumper.setHeading("Currently in flight"); 1218 dumper.setLabel("In-Flight Ordered Broadcast"); 1219 if (mCurrentBroadcast != null) { 1220 dumper.dump(mCurrentBroadcast); 1221 } else { 1222 pw.println(" (null)"); 1223 } 1224 printed |= dumper.didPrint(); 1225 1226 dumper.setHeading("Active alarm broadcasts"); 1227 dumper.setLabel("Active Alarm Broadcast"); 1228 for (BroadcastRecord br : mAlarmQueue) { 1229 dumper.dump(br); 1230 } 1231 printed |= dumper.didPrint(); 1232 1233 dumper.setHeading("Active ordered broadcasts"); 1234 dumper.setLabel("Active Ordered Broadcast"); 1235 for (Deferrals d : mAlarmDeferrals) { 1236 d.dumpLocked(dumper); 1237 } 1238 for (BroadcastRecord br : mOrderedBroadcasts) { 1239 dumper.dump(br); 1240 } 1241 printed |= dumper.didPrint(); 1242 1243 dumper.setHeading("Deferred ordered broadcasts"); 1244 dumper.setLabel("Deferred Ordered Broadcast"); 1245 for (Deferrals d : mDeferredBroadcasts) { 1246 d.dumpLocked(dumper); 1247 } 1248 printed |= dumper.didPrint(); 1249 1250 dumper.setHeading("Deferred LOCKED_BOOT_COMPLETED broadcasts"); 1251 dumper.setLabel("Deferred LOCKED_BOOT_COMPLETED Broadcast"); 1252 for (int i = 0, size = mUser2Deferred.size(); i < size; i++) { 1253 mUser2Deferred.valueAt(i).dump(dumper, Intent.ACTION_LOCKED_BOOT_COMPLETED); 1254 } 1255 printed |= dumper.didPrint(); 1256 1257 dumper.setHeading("Deferred BOOT_COMPLETED broadcasts"); 1258 dumper.setLabel("Deferred BOOT_COMPLETED Broadcast"); 1259 for (int i = 0, size = mUser2Deferred.size(); i < size; i++) { 1260 mUser2Deferred.valueAt(i).dump(dumper, Intent.ACTION_BOOT_COMPLETED); 1261 } 1262 printed |= dumper.didPrint(); 1263 1264 return printed; 1265 } 1266 } 1267