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