Loading services/core/java/com/android/server/am/ActivityManagerService.java +7 −0 Original line number Diff line number Diff line Loading @@ -18964,6 +18964,13 @@ public class ActivityManagerService extends IActivityManager.Stub pw.flush(); } void waitForBroadcastDispatch(@NonNull PrintWriter pw, @NonNull Intent intent) { enforceCallingPermission(permission.DUMP, "waitForBroadcastDispatch"); for (BroadcastQueue queue : mBroadcastQueues) { queue.waitForDispatched(intent, pw); } } void setIgnoreDeliveryGroupPolicy(@NonNull String broadcastAction) { Objects.requireNonNull(broadcastAction); enforceCallingPermission(permission.DUMP, "waitForBroadcastBarrier()"); services/core/java/com/android/server/am/ActivityManagerShellCommand.java +14 −0 Original line number Diff line number Diff line Loading @@ -368,6 +368,8 @@ final class ActivityManagerShellCommand extends ShellCommand { return runWaitForBroadcastBarrier(pw); case "wait-for-application-barrier": return runWaitForApplicationBarrier(pw); case "wait-for-broadcast-dispatch": return runWaitForBroadcastDispatch(pw); case "set-ignore-delivery-group-policy": return runSetIgnoreDeliveryGroupPolicy(pw); case "clear-ignore-delivery-group-policy": Loading Loading @@ -3472,6 +3474,18 @@ final class ActivityManagerShellCommand extends ShellCommand { return 0; } int runWaitForBroadcastDispatch(PrintWriter pw) throws RemoteException { pw = new PrintWriter(new TeeWriter(LOG_WRITER_INFO, pw)); final Intent intent; try { intent = makeIntent(UserHandle.USER_CURRENT); } catch (URISyntaxException e) { throw new RuntimeException(e.getMessage(), e); } mInternal.waitForBroadcastDispatch(pw, intent); return 0; } int runSetIgnoreDeliveryGroupPolicy(PrintWriter pw) throws RemoteException { final String broadcastAction = getNextArgRequired(); mInternal.setIgnoreDeliveryGroupPolicy(broadcastAction); Loading services/core/java/com/android/server/am/BroadcastDispatcher.java +32 −0 Original line number Diff line number Diff line Loading @@ -582,6 +582,38 @@ public class BroadcastDispatcher { } } private static boolean isDispatchedInDeferrals(@NonNull ArrayList<Deferrals> list, @NonNull Intent intent) { for (int i = 0; i < list.size(); i++) { if (!isDispatched(list.get(i).broadcasts, intent)) { return false; } } return true; } private static boolean isDispatched(@NonNull ArrayList<BroadcastRecord> list, @NonNull Intent intent) { for (int i = 0; i < list.size(); i++) { if (intent.filterEquals(list.get(i).intent)) { return false; } } return true; } public boolean isDispatched(@NonNull Intent intent) { synchronized (mLock) { if ((mCurrentBroadcast != null) && intent.filterEquals(mCurrentBroadcast.intent)) { return false; } return isDispatched(mOrderedBroadcasts, intent) && isDispatched(mAlarmQueue, intent) && isDispatchedInDeferrals(mDeferredBroadcasts, intent) && isDispatchedInDeferrals(mAlarmDeferrals, intent); } } private static int pendingInDeferralsList(ArrayList<Deferrals> list) { int pending = 0; final int numEntries = list.size(); Loading services/core/java/com/android/server/am/BroadcastProcessQueue.java +70 −10 Original line number Diff line number Diff line Loading @@ -182,7 +182,7 @@ class BroadcastProcessQueue { private int mCountInstrumented; private int mCountManifest; private boolean mPrioritizeEarliest; private int mCountPrioritizeEarliestRequests; private @UptimeMillisLong long mRunnableAt = Long.MAX_VALUE; private @Reason int mRunnableAtReason = REASON_EMPTY; Loading Loading @@ -748,7 +748,7 @@ class BroadcastProcessQueue { final BroadcastRecord nextLPRecord = (BroadcastRecord) nextLPArgs.arg1; final int nextLPRecordIndex = nextLPArgs.argi1; final BroadcastRecord nextHPRecord = (BroadcastRecord) highPriorityQueue.peekFirst().arg1; final boolean shouldConsiderLPQueue = (mPrioritizeEarliest final boolean shouldConsiderLPQueue = (mCountPrioritizeEarliestRequests > 0 || consecutiveHighPriorityCount >= maxHighPriorityDispatchLimit); final boolean isLPQueueEligible = shouldConsiderLPQueue && nextLPRecord.enqueueTime <= nextHPRecord.enqueueTime Loading @@ -761,10 +761,9 @@ class BroadcastProcessQueue { } /** * When {@code prioritizeEarliest} is set to {@code true}, then earliest enqueued * broadcasts would be prioritized for dispatching, even if there are urgent broadcasts * waiting. This is typically used in case there are callers waiting for "barrier" to be * reached. * Add a request to prioritize dispatching of broadcasts that have been enqueued the earliest, * even if there are urgent broadcasts waiting to be dispatched. This is typically used in * case there are callers waiting for "barrier" to be reached. * * @return if this operation may have changed internal state, indicating * that the caller is responsible for invoking Loading @@ -772,11 +771,37 @@ class BroadcastProcessQueue { */ @CheckResult @VisibleForTesting boolean setPrioritizeEarliest(boolean prioritizeEarliest) { if (mPrioritizeEarliest != prioritizeEarliest) { mPrioritizeEarliest = prioritizeEarliest; boolean addPrioritizeEarliestRequest() { if (mCountPrioritizeEarliestRequests == 0) { mCountPrioritizeEarliestRequests++; invalidateRunnableAt(); return true; } else { mCountPrioritizeEarliestRequests++; return false; } } /** * Remove a request to prioritize dispatching of broadcasts that have been enqueued the * earliest, even if there are urgent broadcasts waiting to be dispatched. This is typically * used in case there are callers waiting for "barrier" to be reached. * * <p> Once there are no more remaining requests, the dispatching order reverts back to normal. * * @return if this operation may have changed internal state, indicating * that the caller is responsible for invoking * {@link BroadcastQueueModernImpl#updateRunnableList} */ @CheckResult boolean removePrioritizeEarliestRequest() { mCountPrioritizeEarliestRequests--; if (mCountPrioritizeEarliestRequests == 0) { invalidateRunnableAt(); return true; } else if (mCountPrioritizeEarliestRequests < 0) { mCountPrioritizeEarliestRequests = 0; return false; } else { return false; } Loading Loading @@ -837,7 +862,7 @@ class BroadcastProcessQueue { } /** * Quickly determine if this queue has broadcasts enqueued before the given * Quickly determine if this queue has non-deferred broadcasts enqueued before the given * barrier timestamp that are still waiting to be delivered. */ public boolean isBeyondBarrierLocked(@UptimeMillisLong long barrierTime) { Loading @@ -859,6 +884,41 @@ class BroadcastProcessQueue { || isDeferredUntilActive(); } /** * Quickly determine if this queue has non-deferred broadcasts waiting to be dispatched, * that match {@code intent}, as defined by {@link Intent#filterEquals(Intent)}. */ public boolean isDispatched(@NonNull Intent intent) { final boolean activeDispatched = (mActive == null) || (!intent.filterEquals(mActive.intent)); final boolean dispatched = isDispatchedInQueue(mPending, intent); final boolean urgentDispatched = isDispatchedInQueue(mPendingUrgent, intent); final boolean offloadDispatched = isDispatchedInQueue(mPendingOffload, intent); return (activeDispatched && dispatched && urgentDispatched && offloadDispatched) || isDeferredUntilActive(); } /** * Quickly determine if the {@code queue} has non-deferred broadcasts waiting to be dispatched, * that match {@code intent}, as defined by {@link Intent#filterEquals(Intent)}. */ private boolean isDispatchedInQueue(@NonNull ArrayDeque<SomeArgs> queue, @NonNull Intent intent) { final Iterator<SomeArgs> it = queue.iterator(); while (it.hasNext()) { final SomeArgs args = it.next(); if (args == null) { return true; } final BroadcastRecord record = (BroadcastRecord) args.arg1; if (intent.filterEquals(record.intent)) { return false; } } return true; } public boolean isRunnable() { if (mRunnableAtInvalidated) updateRunnableAt(); return mRunnableAt != Long.MAX_VALUE; Loading services/core/java/com/android/server/am/BroadcastQueue.java +20 −2 Original line number Diff line number Diff line Loading @@ -192,7 +192,7 @@ public abstract class BroadcastQueue { public abstract boolean isIdleLocked(); /** * Quickly determine if this queue has broadcasts enqueued before the given * Quickly determine if this queue has non-deferred broadcasts enqueued before the given * barrier timestamp that are still waiting to be delivered. * * @see #waitForIdle Loading @@ -201,6 +201,15 @@ public abstract class BroadcastQueue { @GuardedBy("mService") public abstract boolean isBeyondBarrierLocked(@UptimeMillisLong long barrierTime); /** * Quickly determine if this queue has non-deferred broadcasts waiting to be dispatched, * that match {@code intent}, as defined by {@link Intent#filterEquals(Intent)}. * * @see #waitForDispatched(Intent, PrintWriter) */ @GuardedBy("mService") public abstract boolean isDispatchedLocked(@NonNull Intent intent); /** * Wait until this queue becomes completely idle. * <p> Loading @@ -214,7 +223,7 @@ public abstract class BroadcastQueue { public abstract void waitForIdle(@NonNull PrintWriter pw); /** * Wait until any currently waiting broadcasts have been dispatched. * Wait until any currently waiting non-deferred broadcasts have been dispatched. * <p> * Any broadcasts waiting to be delivered at some point in the future will * be dispatched as quickly as possible. Loading @@ -224,6 +233,15 @@ public abstract class BroadcastQueue { */ public abstract void waitForBarrier(@NonNull PrintWriter pw); /** * Wait until all non-deferred broadcasts matching {@code intent}, as defined by * {@link Intent#filterEquals(Intent)}, have been dispatched. * <p> * Any broadcasts waiting to be delivered at some point in the future will * be dispatched as quickly as possible. */ public abstract void waitForDispatched(@NonNull Intent intent, @NonNull PrintWriter pw); /** * Delays delivering broadcasts to the specified package. * Loading Loading
services/core/java/com/android/server/am/ActivityManagerService.java +7 −0 Original line number Diff line number Diff line Loading @@ -18964,6 +18964,13 @@ public class ActivityManagerService extends IActivityManager.Stub pw.flush(); } void waitForBroadcastDispatch(@NonNull PrintWriter pw, @NonNull Intent intent) { enforceCallingPermission(permission.DUMP, "waitForBroadcastDispatch"); for (BroadcastQueue queue : mBroadcastQueues) { queue.waitForDispatched(intent, pw); } } void setIgnoreDeliveryGroupPolicy(@NonNull String broadcastAction) { Objects.requireNonNull(broadcastAction); enforceCallingPermission(permission.DUMP, "waitForBroadcastBarrier()");
services/core/java/com/android/server/am/ActivityManagerShellCommand.java +14 −0 Original line number Diff line number Diff line Loading @@ -368,6 +368,8 @@ final class ActivityManagerShellCommand extends ShellCommand { return runWaitForBroadcastBarrier(pw); case "wait-for-application-barrier": return runWaitForApplicationBarrier(pw); case "wait-for-broadcast-dispatch": return runWaitForBroadcastDispatch(pw); case "set-ignore-delivery-group-policy": return runSetIgnoreDeliveryGroupPolicy(pw); case "clear-ignore-delivery-group-policy": Loading Loading @@ -3472,6 +3474,18 @@ final class ActivityManagerShellCommand extends ShellCommand { return 0; } int runWaitForBroadcastDispatch(PrintWriter pw) throws RemoteException { pw = new PrintWriter(new TeeWriter(LOG_WRITER_INFO, pw)); final Intent intent; try { intent = makeIntent(UserHandle.USER_CURRENT); } catch (URISyntaxException e) { throw new RuntimeException(e.getMessage(), e); } mInternal.waitForBroadcastDispatch(pw, intent); return 0; } int runSetIgnoreDeliveryGroupPolicy(PrintWriter pw) throws RemoteException { final String broadcastAction = getNextArgRequired(); mInternal.setIgnoreDeliveryGroupPolicy(broadcastAction); Loading
services/core/java/com/android/server/am/BroadcastDispatcher.java +32 −0 Original line number Diff line number Diff line Loading @@ -582,6 +582,38 @@ public class BroadcastDispatcher { } } private static boolean isDispatchedInDeferrals(@NonNull ArrayList<Deferrals> list, @NonNull Intent intent) { for (int i = 0; i < list.size(); i++) { if (!isDispatched(list.get(i).broadcasts, intent)) { return false; } } return true; } private static boolean isDispatched(@NonNull ArrayList<BroadcastRecord> list, @NonNull Intent intent) { for (int i = 0; i < list.size(); i++) { if (intent.filterEquals(list.get(i).intent)) { return false; } } return true; } public boolean isDispatched(@NonNull Intent intent) { synchronized (mLock) { if ((mCurrentBroadcast != null) && intent.filterEquals(mCurrentBroadcast.intent)) { return false; } return isDispatched(mOrderedBroadcasts, intent) && isDispatched(mAlarmQueue, intent) && isDispatchedInDeferrals(mDeferredBroadcasts, intent) && isDispatchedInDeferrals(mAlarmDeferrals, intent); } } private static int pendingInDeferralsList(ArrayList<Deferrals> list) { int pending = 0; final int numEntries = list.size(); Loading
services/core/java/com/android/server/am/BroadcastProcessQueue.java +70 −10 Original line number Diff line number Diff line Loading @@ -182,7 +182,7 @@ class BroadcastProcessQueue { private int mCountInstrumented; private int mCountManifest; private boolean mPrioritizeEarliest; private int mCountPrioritizeEarliestRequests; private @UptimeMillisLong long mRunnableAt = Long.MAX_VALUE; private @Reason int mRunnableAtReason = REASON_EMPTY; Loading Loading @@ -748,7 +748,7 @@ class BroadcastProcessQueue { final BroadcastRecord nextLPRecord = (BroadcastRecord) nextLPArgs.arg1; final int nextLPRecordIndex = nextLPArgs.argi1; final BroadcastRecord nextHPRecord = (BroadcastRecord) highPriorityQueue.peekFirst().arg1; final boolean shouldConsiderLPQueue = (mPrioritizeEarliest final boolean shouldConsiderLPQueue = (mCountPrioritizeEarliestRequests > 0 || consecutiveHighPriorityCount >= maxHighPriorityDispatchLimit); final boolean isLPQueueEligible = shouldConsiderLPQueue && nextLPRecord.enqueueTime <= nextHPRecord.enqueueTime Loading @@ -761,10 +761,9 @@ class BroadcastProcessQueue { } /** * When {@code prioritizeEarliest} is set to {@code true}, then earliest enqueued * broadcasts would be prioritized for dispatching, even if there are urgent broadcasts * waiting. This is typically used in case there are callers waiting for "barrier" to be * reached. * Add a request to prioritize dispatching of broadcasts that have been enqueued the earliest, * even if there are urgent broadcasts waiting to be dispatched. This is typically used in * case there are callers waiting for "barrier" to be reached. * * @return if this operation may have changed internal state, indicating * that the caller is responsible for invoking Loading @@ -772,11 +771,37 @@ class BroadcastProcessQueue { */ @CheckResult @VisibleForTesting boolean setPrioritizeEarliest(boolean prioritizeEarliest) { if (mPrioritizeEarliest != prioritizeEarliest) { mPrioritizeEarliest = prioritizeEarliest; boolean addPrioritizeEarliestRequest() { if (mCountPrioritizeEarliestRequests == 0) { mCountPrioritizeEarliestRequests++; invalidateRunnableAt(); return true; } else { mCountPrioritizeEarliestRequests++; return false; } } /** * Remove a request to prioritize dispatching of broadcasts that have been enqueued the * earliest, even if there are urgent broadcasts waiting to be dispatched. This is typically * used in case there are callers waiting for "barrier" to be reached. * * <p> Once there are no more remaining requests, the dispatching order reverts back to normal. * * @return if this operation may have changed internal state, indicating * that the caller is responsible for invoking * {@link BroadcastQueueModernImpl#updateRunnableList} */ @CheckResult boolean removePrioritizeEarliestRequest() { mCountPrioritizeEarliestRequests--; if (mCountPrioritizeEarliestRequests == 0) { invalidateRunnableAt(); return true; } else if (mCountPrioritizeEarliestRequests < 0) { mCountPrioritizeEarliestRequests = 0; return false; } else { return false; } Loading Loading @@ -837,7 +862,7 @@ class BroadcastProcessQueue { } /** * Quickly determine if this queue has broadcasts enqueued before the given * Quickly determine if this queue has non-deferred broadcasts enqueued before the given * barrier timestamp that are still waiting to be delivered. */ public boolean isBeyondBarrierLocked(@UptimeMillisLong long barrierTime) { Loading @@ -859,6 +884,41 @@ class BroadcastProcessQueue { || isDeferredUntilActive(); } /** * Quickly determine if this queue has non-deferred broadcasts waiting to be dispatched, * that match {@code intent}, as defined by {@link Intent#filterEquals(Intent)}. */ public boolean isDispatched(@NonNull Intent intent) { final boolean activeDispatched = (mActive == null) || (!intent.filterEquals(mActive.intent)); final boolean dispatched = isDispatchedInQueue(mPending, intent); final boolean urgentDispatched = isDispatchedInQueue(mPendingUrgent, intent); final boolean offloadDispatched = isDispatchedInQueue(mPendingOffload, intent); return (activeDispatched && dispatched && urgentDispatched && offloadDispatched) || isDeferredUntilActive(); } /** * Quickly determine if the {@code queue} has non-deferred broadcasts waiting to be dispatched, * that match {@code intent}, as defined by {@link Intent#filterEquals(Intent)}. */ private boolean isDispatchedInQueue(@NonNull ArrayDeque<SomeArgs> queue, @NonNull Intent intent) { final Iterator<SomeArgs> it = queue.iterator(); while (it.hasNext()) { final SomeArgs args = it.next(); if (args == null) { return true; } final BroadcastRecord record = (BroadcastRecord) args.arg1; if (intent.filterEquals(record.intent)) { return false; } } return true; } public boolean isRunnable() { if (mRunnableAtInvalidated) updateRunnableAt(); return mRunnableAt != Long.MAX_VALUE; Loading
services/core/java/com/android/server/am/BroadcastQueue.java +20 −2 Original line number Diff line number Diff line Loading @@ -192,7 +192,7 @@ public abstract class BroadcastQueue { public abstract boolean isIdleLocked(); /** * Quickly determine if this queue has broadcasts enqueued before the given * Quickly determine if this queue has non-deferred broadcasts enqueued before the given * barrier timestamp that are still waiting to be delivered. * * @see #waitForIdle Loading @@ -201,6 +201,15 @@ public abstract class BroadcastQueue { @GuardedBy("mService") public abstract boolean isBeyondBarrierLocked(@UptimeMillisLong long barrierTime); /** * Quickly determine if this queue has non-deferred broadcasts waiting to be dispatched, * that match {@code intent}, as defined by {@link Intent#filterEquals(Intent)}. * * @see #waitForDispatched(Intent, PrintWriter) */ @GuardedBy("mService") public abstract boolean isDispatchedLocked(@NonNull Intent intent); /** * Wait until this queue becomes completely idle. * <p> Loading @@ -214,7 +223,7 @@ public abstract class BroadcastQueue { public abstract void waitForIdle(@NonNull PrintWriter pw); /** * Wait until any currently waiting broadcasts have been dispatched. * Wait until any currently waiting non-deferred broadcasts have been dispatched. * <p> * Any broadcasts waiting to be delivered at some point in the future will * be dispatched as quickly as possible. Loading @@ -224,6 +233,15 @@ public abstract class BroadcastQueue { */ public abstract void waitForBarrier(@NonNull PrintWriter pw); /** * Wait until all non-deferred broadcasts matching {@code intent}, as defined by * {@link Intent#filterEquals(Intent)}, have been dispatched. * <p> * Any broadcasts waiting to be delivered at some point in the future will * be dispatched as quickly as possible. */ public abstract void waitForDispatched(@NonNull Intent intent, @NonNull PrintWriter pw); /** * Delays delivering broadcasts to the specified package. * Loading