当前位置: 首页 > news >正文

asp 公司网站源码网站建设中图片是什么

asp 公司网站源码,网站建设中图片是什么,qq推广大联盟,漯河做网站zrguandroid U广播详解#xff08;一#xff09; 基础代码介绍 广播相关 // 用作单个进程批量分发receivers#xff0c;已被丢弃 frameworks/base/services/core/java/com/android/server/am/BroadcastReceiverBatch.java // 主要逻辑所在类#xff0c;包括入队、分发、结束…android U广播详解一 基础代码介绍 广播相关 // 用作单个进程批量分发receivers已被丢弃 frameworks/base/services/core/java/com/android/server/am/BroadcastReceiverBatch.java // 主要逻辑所在类包括入队、分发、结束等 frameworks/base/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java // 进程队列分发广播时的单位 frameworks/base/services/core/java/com/android/server/am/BroadcastProcessQueue.java // 之前的BroadcastQueue frameworks/base/services/core/java/com/android/server/am/BroadcastQueueImpl.java // 决定是否跳过分发当前receiver frameworks/base/services/core/java/com/android/server/am/BroadcastSkipPolicy.java默认使用BroadcastQueueModernImpl类来处理广播相关逻辑 // 默认使用modern Queue if (mEnableModernQueue) {mBroadcastQueues new BroadcastQueue[1];mBroadcastQueues[0] new BroadcastQueueModernImpl(this, mHandler,foreConstants, backConstants); } else {...... }每个接收者的交付状态 // BroadcastRecord.javaIntDef(flag false, prefix { DELIVERY_ }, value {DELIVERY_PENDING, // 初始状态等待未来运行DELIVERY_DELIVERED, // 终端状态成功完成DELIVERY_SKIPPED, // 终端状态由于内部政策而跳过DELIVERY_TIMEOUT, // 终端状态尝试投递时超时DELIVERY_SCHEDULED, // 中间状态当前正在执行DELIVERY_FAILURE, // 终端状态派送失败})final DeliveryState int[] delivery; // 每个接受者的交付状态// 获取指定index对应receiver的交付状态DeliveryState int getDeliveryState(int index) {return delivery[index];}// 如果给定的交付状态为“终端”则返回其中不会进行额外的交付状态更改。static boolean isDeliveryStateTerminal(DeliveryState int deliveryState) {switch (deliveryState) {case DELIVERY_DELIVERED:case DELIVERY_SKIPPED:case DELIVERY_TIMEOUT:case DELIVERY_FAILURE:return true;default:return false;}}// 如果给定的传递状态为“超出”则返回这意味着我们已经超出了该接收器并且未来的接收器现在已解锁。static boolean isDeliveryStateBeyond(DeliveryState int deliveryState) {switch (deliveryState) {case DELIVERY_DELIVERED:case DELIVERY_SKIPPED:case DELIVERY_TIMEOUT:case DELIVERY_FAILURE:case DELIVERY_DEFERRED:return true;default:return false;}// 更新给定索引的{link #receivers}传递状态。自动更新与状态变化相关的任何时间测量// 如果由于此状态转换{link #beyondCount}而发生变化则返回true表明其他事件可能会被解除阻塞。CheckResultboolean setDeliveryState(int index, DeliveryState int newDeliveryState,NonNull String reason) {final int oldDeliveryState delivery[index];if (isDeliveryStateTerminal(oldDeliveryState)|| newDeliveryState oldDeliveryState) {// 我们已经到达终端或请求状态因此请保留第一次转换时的所有统计数据和原因完整无缺return false;}switch (oldDeliveryState) {case DELIVERY_DEFERRED:deferredCount--;break;}switch (newDeliveryState) {case DELIVERY_PENDING:scheduledTime[index] 0;break;case DELIVERY_SCHEDULED:scheduledTime[index] SystemClock.uptimeMillis();break;case DELIVERY_DEFERRED:deferredCount;break;case DELIVERY_DELIVERED:case DELIVERY_SKIPPED:case DELIVERY_TIMEOUT:case DELIVERY_FAILURE:terminalTime[index] SystemClock.uptimeMillis();terminalCount;break;}delivery[index] newDeliveryState;deliveryReasons[index] reason;// 如果当前receiver的状态变化可能会让我们达到一个新的beyondCountfinal int oldBeyondCount beyondCount;if (index beyondCount) {for (int i beyondCount; i delivery.length; i) {if (isDeliveryStateBeyond(getDeliveryState(i))) {beyondCount i 1;} else {break;}}}return (beyondCount ! oldBeyondCount);}广播种类 // BroadcastRecord.java// 紧急广播关于此广播传送优先级的核心策略确定前台、用户交互触发、闹钟触发boolean isUrgent() {return (isForeground()|| interactive|| alarm);}// 负载广播boolean isOffload() {return (intent.getFlags() Intent.FLAG_RECEIVER_OFFLOAD) ! 0;}// 确定 {link #calculateBlockedUntilTerminalCount} 的结果是否对接收方进行了优先排序。VisibleForTestingstatic boolean isPrioritized(NonNull int[] blockedUntilBeyondCount,boolean ordered) {return !ordered (blockedUntilBeyondCount.length 0) (blockedUntilBeyondCount[0] ! -1);}// BroadcastProcessQueue.java // 等待发送到此进程的广播的有序集合作为一对 {link BroadcastRecord} 和代表接收者的 {link BroadcastRecord#receivers} 的索引。 private final ArrayDequeSomeArgs mPending new ArrayDeque();// 等待分派到此进程的“紧急”广播的有序集合与 {link #mPending} 的表示相同。 private final ArrayDequeSomeArgs mPendingUrgent new ArrayDeque(4);// 等待分派到此进程的“卸载”广播的有序集合与{link #mPending} 的表示相同。 private final ArrayDequeSomeArgs mPendingOffload new ArrayDeque(4); // 持有等待调度的广播的所有队列的列表 private final ListArrayDequeSomeArgs mPendingQueues List.of(mPendingUrgent, mPending, mPendingOffload);进程队列状态 可运行状态 // BroadcastProcessQueue.javaprivate UptimeMillisLong long mRunnableAt Long.MAX_VALUE;private Reason int mRunnableAtReason REASON_EMPTY;private boolean mRunnableAtInvalidated;// 未处于Blocked状态且队列不为空public boolean isRunnable() {if (mRunnableAtInvalidated) updateRunnableAt();return mRunnableAt ! Long.MAX_VALUE;}// 返回此进程被视为可运行的时间通常是下一个pending广播的首次入队时间也有可能是暂停或延迟时间public UptimeMillisLong long getRunnableAt() {if (mRunnableAtInvalidated) updateRunnableAt();return mRunnableAt;}// 返回当前 {link #getRunnableAt()} 值背后的“原因”例如表明队列延迟或暂停的原因。public Reason int getRunnableAtReason() {if (mRunnableAtInvalidated) updateRunnableAt();return mRunnableAtReason;}// 前一个receiver分发完则应刷新下一个receiver所在队列的runnablepublic void invalidateRunnableAt() {mRunnableAtInvalidated true;}// 快速确定此队列是否有等待传递给清单接收者的广播这表明我们应该请求 OOM 调整。public boolean isPendingManifest() {return mCountManifest 0;}// BroadcastQueueModernImpl.java// 从 UID 映射到每个进程的广播队列。 如果一个 UID 托管多个进程则每个额外的进程都使用 {link BroadcastProcessQueue#next} 存储为链表。GuardedBy(mService)private final SparseArrayBroadcastProcessQueue mProcessQueues new SparseArray();// 包含“可运行”队列的链表头。 它们按 {link BroadcastProcessQueue#getRunnableAt()} 排序因此我们更喜欢首先调度等待时间较长的广播。private BroadcastProcessQueue mRunnableHead null;运行中状态 // BroadcastProcessQueue.java// 正在调度的活动广播private Nullable BroadcastRecord mActive;// 这是 {link #mActive} 的 {link BroadcastRecord#receivers} 列表的索引。private int mActiveIndex;public boolean isActive() {return mActive ! null;}// 将当前活动的广播设置为下一个待处理的广播。public void makeActiveNextPending() {// TODO: what if the next broadcast isnt runnable yet?final SomeArgs next removeNextBroadcast();mActive (BroadcastRecord) next.arg1;mActiveIndex next.argi1;mActiveCountSinceIdle;mActiveViaColdStart false;next.recycle();onBroadcastDequeued(mActive, mActiveIndex);}// BroadcastQueueModernImpl.java// 当前正在“运行”的队列数组可能有 {code null} 的间隙。GuardedBy(mService)private final BroadcastProcessQueue[] mRunning;// 正在“运行”但正在等待通过 {link #onApplicationAttachedLocked} 完成冷启动的单个队列。 为了优化系统健康我们一次只请求一个冷启动。GuardedBy(mService)private Nullable BroadcastProcessQueue mRunningColdStart;// 返回 {link #mRunning} 中包含的活动队列总数。private int getRunningSize() {int size 0;for (int i 0; i mRunning.length; i) {if (mRunning[i] ! null) size;}return size;}idle状态 // BroadcastProcessQueue.java // 快速确定此队列是否有仍在等待在未来某个时间点传送的广播。public boolean isIdle() {return !isActive() isEmpty();}// 将当前运行的广播设置为空闲。public void makeActiveIdle() {mActive null;mActiveIndex 0;mActiveCountSinceIdle 0;mActiveViaColdStart false;invalidateRunnableAt();}分发相关 有序广播分发阻塞 // BroadcastRecord.java// 已经接收完成/失败/Defer状态的receiver数量即receiver状态不会影响后续receiver接收的数量 int beyondCount;// 根据整体广播的当前状态是否应将给定的 {link #receivers} 索引视为已Blocked。 boolean isBlocked(int index) {return (beyondCount blockedUntilBeyondCount[index]); }计算每个接收器应被视为阻塞的 {link #beyondCount} 。 例如在有序广播中接收器 {code N} 被阻塞直到接收器 {code N-1} 达到终止状态。 同样在一个优先级广播接收者 {code N} 被阻塞直到所有更高优先级的接收者达到终止状态。 当没有终端计数约束时每个接收者的阻塞值为 {code -1}。 // BroadcastRecord.java VisibleForTesting static NonNull int[] calculateBlockedUntilBeyondCount(NonNull ListObject receivers, boolean ordered) {final int N receivers.size();final int[] blockedUntilBeyondCount new int[N];int lastPriority 0;int lastPriorityIndex 0;for (int i 0; i N; i) {if (ordered) {// 当发送有序广播时我们需要阻塞这个接收者直到所有之前的接收者都终止blockedUntilBeyondCount[i] i;} else {// 发送优先级广播时我们只需要等待前一批接收者终止final int thisPriority getReceiverPriority(receivers.get(i));if ((i 0) || (thisPriority ! lastPriority)) {lastPriority thisPriority;lastPriorityIndex i;blockedUntilBeyondCount[i] i;} else {blockedUntilBeyondCount[i] lastPriorityIndex;}}}// 如果整个列表都在同一个优先级中标记为-1表示它们都不需要等待if (N 0 blockedUntilBeyondCount[N - 1] 0) {Arrays.fill(blockedUntilBeyondCount, -1);}return blockedUntilBeyondCount; }选取队列中下一个待执行广播 // BroadcastProcessQueue.java// 自上次非紧急调度以来已调度的连续紧急广播数。 private int mActiveCountConsecutiveUrgent;// 自上次负载调度以来已调度的连续正常广播数。 private int mActiveCountConsecutiveNormal;// BroadcastProcessQueue.java// 将当前活动的广播设置为下一个待处理的广播。public void makeActiveNextPending() {// TODO: what if the next broadcast isnt runnable yet?final SomeArgs next removeNextBroadcast();mActive (BroadcastRecord) next.arg1;mActiveIndex next.argi1;mActiveCountSinceIdle;mActiveAssumedDeliveryCountSinceIdle (mActive.isAssumedDelivered(mActiveIndex) ? 1 : 0);mActiveViaColdStart false;mActiveWasStopped false;next.recycle();onBroadcastDequeued(mActive, mActiveIndex);}Nullable ArrayDequeSomeArgs queueForNextBroadcast() {// 普通优先级大于负载但是限制为10final ArrayDequeSomeArgs nextNormal queueForNextBroadcast(mPending, mPendingOffload,mActiveCountConsecutiveNormal, constants.MAX_CONSECUTIVE_NORMAL_DISPATCHES); //10// 紧急优先级大于普通限制为3final ArrayDequeSomeArgs nextBroadcastQueue queueForNextBroadcast(mPendingUrgent, nextNormal,mActiveCountConsecutiveUrgent, constants.MAX_CONSECUTIVE_URGENT_DISPATCHES); //3return nextBroadcastQueue;}private Nullable ArrayDequeSomeArgs queueForNextBroadcast(Nullable ArrayDequeSomeArgs highPriorityQueue,Nullable ArrayDequeSomeArgs lowPriorityQueue,int consecutiveHighPriorityCount, // 连续高优先级计数int maxHighPriorityDispatchLimit) { // 最大高优先级调度限制 10 or 3// 没有高优先级pending没有进一步的决策if (isQueueEmpty(highPriorityQueue)) {return lowPriorityQueue;}// 只有高优先级pending也没有进一步的决策if (isQueueEmpty(lowPriorityQueue)) {return highPriorityQueue;}// 缓解饥饿虽然我们默认优先考虑高优先级队列但我们允许低优先级队列稳定前进即使高优先级队列中的广播到达速度快于它们的调度速度。// 我们不会尝试推迟到低优先级队列中的下一个广播如果该广播是有序的并且在传递给其他receiver时仍然被阻止。final SomeArgs nextLPArgs lowPriorityQueue.peekFirst();final BroadcastRecord nextLPRecord (BroadcastRecord) nextLPArgs.arg1;final int nextLPRecordIndex nextLPArgs.argi1;final BroadcastRecord nextHPRecord (BroadcastRecord) highPriorityQueue.peekFirst().arg1;final boolean shouldConsiderLPQueue (mCountPrioritizeEarliestRequests // 最早优先waitFor// 连续高优先级处理达到阈值3 or 10|| consecutiveHighPriorityCount maxHighPriorityDispatchLimit);// 低优先级队列符合条件final boolean isLPQueueEligible shouldConsiderLPQueue// 低优先级队列入队时间更早 nextLPRecord.enqueueTime nextHPRecord.enqueueTime// 低优先级队列未处于有序广播分发的阻塞状态 !nextLPRecord.isBlocked(nextLPRecordIndex);return isLPQueueEligible ? lowPriorityQueue : highPriorityQueue;}队列是否继续调度 // BroadcastProcessQueue.java// 自此队列上次空闲以来已分派的 {link #mActive} 广播计数会在shouldContinueScheduling被使用一个进程一次最多可分发8 or 16个广播private int mActiveCountSinceIdle;public int getActiveCountSinceIdle() {return mActiveCountSinceIdle;}// 如果我们知道此队列正在运行的“热”进程则返回。public boolean isProcessWarm() {return (app ! null) (app.getOnewayThread() ! null) !app.isKilled();}// BroadcastQueueModernImpl.java// 如果队列中不再有广播或者队列不可运行则返回 true。private boolean shouldRetire(NonNull BroadcastProcessQueue queue) {// 如果我们已经取得了合理的进展请定期退出以避免其他进程饥饿和广播立即完成而无需等待时堆栈溢出final boolean shouldRetire;if (UserHandle.isCore(queue.uid)) {// 动态注册的无序广播数量final int nonBlockingDeliveryCount queue.getActiveAssumedDeliveryCountSinceIdle();// 有序广播 清单注册的广播数量final int blockingDeliveryCount (queue.getActiveCountSinceIdle()- queue.getActiveAssumedDeliveryCountSinceIdle());shouldRetire (blockingDeliveryCount// 16低内存8 mConstants.MAX_CORE_RUNNING_BLOCKING_BROADCASTS) || (nonBlockingDeliveryCount// 64 低内存32 mConstants.MAX_CORE_RUNNING_NON_BLOCKING_BROADCASTS);} else {// 默认16低内存8系统可配置shouldRetire (queue.getActiveCountSinceIdle() mConstants.MAX_RUNNING_ACTIVE_BROADCASTS);}return !queue.isRunnable() || !queue.isProcessWarm() || shouldRetire;}整体流程 入队流程 冷启会多如下流程 分发流程 静态注册或有序广播结束分发后回调到AMS的流程 入队 // BroadcastQueueModernImpl.javaOverridepublic void enqueueBroadcastLocked(NonNull BroadcastRecord r) {if (DEBUG_BROADCAST) logv(Enqueuing r for r.receivers.size() receivers);final int cookie traceBegin(enqueueBroadcast);// 通过将它们重新定位到 {link UserHandle#USER_SYSTEM}对单例进程托管的清单接收器进行特殊处理。r.applySingletonPolicy(mService);// 下发组策略遍历所有队列决定之前的广播是否跳过分发或合并分发applyDeliveryGroupPolicy(r);// 设置入队时间r.enqueueTime SystemClock.uptimeMillis();r.enqueueRealTime SystemClock.elapsedRealtime();r.enqueueClockTime System.currentTimeMillis();mHistory.onBroadcastEnqueuedLocked(r);ArraySetBroadcastRecord replacedBroadcasts mReplacedBroadcastsCache.getAndSet(null);if (replacedBroadcasts null) {replacedBroadcasts new ArraySet();}boolean enqueuedBroadcast false;for (int i 0; i r.receivers.size(); i) {final Object receiver r.receivers.get(i);final BroadcastProcessQueue queue getOrCreateProcessQueue(getReceiverProcessName(receiver), getReceiverUid(receiver));// 如果要跳过此接收器请立即跳过它甚至不要将其加入队列。// 诸如一些权限校验等final String skipReason mSkipPolicy.shouldSkipMessage(r, receiver);if (skipReason ! null) {setDeliveryState(null, null, r, i, receiver, BroadcastRecord.DELIVERY_SKIPPED,skipped by policy at enqueue: skipReason);continue;}// 入队对应的进程队列enqueuedBroadcast true;final BroadcastRecord replacedBroadcast queue.enqueueOrReplaceBroadcast(r, i, mBroadcastConsumerDeferApply);if (replacedBroadcast ! null) {replacedBroadcasts.add(replacedBroadcast);}// 更新可运行时间updateRunnableList(queue);// schedule 运行队列enqueueUpdateRunningList();}// 跳过任何已被带有 FLAG_RECEIVER_REPLACE_PENDING 的新广播取代的广播。skipAndCancelReplacedBroadcasts(replacedBroadcasts);replacedBroadcasts.clear();// If nothing to dispatch, send any pending result immediatelyif (r.receivers.isEmpty()) {scheduleResultTo(r);notifyFinishBroadcast(r);}traceEnd(cookie);}应用对应的传递组策略 // BroadcastQueueModernImpl.javaprivate void applyDeliveryGroupPolicy(NonNull BroadcastRecord r) {if (mService.shouldIgnoreDeliveryGroupPolicy(r.intent.getAction())) {return;}// 发送广播时可以指定下发策略final int policy (r.options ! null)? r.options.getDeliveryGroupPolicy() : BroadcastOptions.DELIVERY_GROUP_POLICY_ALL;final BroadcastConsumer broadcastConsumer;switch (policy) {case BroadcastOptions.DELIVERY_GROUP_POLICY_ALL:// 在这种情况下需要保留较旧的广播因此无事可做。return;case BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT:// 匹配上则直接skip当前派发broadcastConsumer mBroadcastConsumerSkipAndCanceled;break;case BroadcastOptions.DELIVERY_GROUP_POLICY_MERGED:final BundleMerger extrasMerger r.options.getDeliveryGroupExtrasMerger();if (extrasMerger null) {// Extras合并需要能够合并extras。 因此如果未提供则忽略交付组策略。return;}// 先合并额外的数据再跳过分发broadcastConsumer (record, recordIndex) - {r.intent.mergeExtras(record.intent, extrasMerger);mBroadcastConsumerSkipAndCanceled.accept(record, recordIndex);};break;default:logw(Unknown delivery group policy: policy);return;}final ArrayMapBroadcastRecord, Boolean recordsLookupCache getRecordsLookupCache();forEachMatchingBroadcast(QUEUE_PREDICATE_ANY, (testRecord, testIndex) - {// 如果接收方已经处于终端状态则忽略它。if (isDeliveryStateTerminal(testRecord.getDeliveryState(testIndex))) {return false;}// 我们只允许调用者删除他们排队的广播if ((r.callingUid ! testRecord.callingUid)|| (r.userId ! testRecord.userId)|| !r.matchesDeliveryGroup(testRecord)) {return false;}// 对于有序广播请检查新广播的接收器是否是前一个广播的接收器的超集// 因为跳过和仅删除其中一个可能会导致不一致的状态。if (testRecord.ordered || testRecord.prioritized) {return containsAllReceivers(r, testRecord, recordsLookupCache);} else if (testRecord.resultTo ! null) {return testRecord.getDeliveryState(testIndex) DELIVERY_DEFERRED? r.containsReceiver(testRecord.receivers.get(testIndex)): containsAllReceivers(r, testRecord, recordsLookupCache);} else {return r.containsReceiver(testRecord.receivers.get(testIndex));}}, broadcastConsumer, true);recordsLookupCache.clear();mRecordsLookupCache.compareAndSet(null, recordsLookupCache);}// 典型的消费者会跳过给定的广播并将其标记为已取消通常是因为它与predicate匹配。private final BroadcastConsumer mBroadcastConsumerSkipAndCanceled (r, i) - {setDeliveryState(null, null, r, i, r.receivers.get(i), BroadcastRecord.DELIVERY_SKIPPED,mBroadcastConsumerSkipAndCanceled);r.resultCode Activity.RESULT_CANCELED;r.resultData null;r.resultExtras null;};添加广播到对应的进程队列 将给定的广播排队以便在未来的某个时间点发送到此进程。 目标接收器由 {link BroadcastRecord#receivers} 中的给定索引指示。 如果广播被标记为 {link BroadcastRecord#isReplacePending()}则此调用将替换任何待处理的调度 否则它将作为普通广播排队。 定义后此接收器被视为“阻塞”直到至少给定计数的其他接收器达到终止状态 通常用于有序广播和优先级广播。 // BroadcastProcessQueue.javapublic BroadcastRecord enqueueOrReplaceBroadcast(NonNull BroadcastRecord record, int recordIndex,NonNull BroadcastConsumer replacedBroadcastConsumer) {// 当 updateDeferredStates() 已将延迟状态应用于所有待处理项目时也应用于此新广播if (mLastDeferredStates record.deferUntilActive (record.getDeliveryState(recordIndex) BroadcastRecord.DELIVERY_PENDING)) {deferredStatesApplyConsumer.accept(record, recordIndex);}// 如果发件人使用 BroadcastOptions 交付组 API 指定了策略则忽略 FLAG_RECEIVER_REPLACE_PENDING。if (record.isReplacePending() record.getDeliveryGroupPolicy() BroadcastOptions.DELIVERY_GROUP_POLICY_ALL) {final BroadcastRecord replacedBroadcastRecord replaceBroadcast(record, recordIndex);if (replacedBroadcastRecord ! null) {return replacedBroadcastRecord;}}// 调用者对替换不感兴趣或者我们没有在上面找到任何待替换的项目因此作为新广播排队SomeArgs newBroadcastArgs SomeArgs.obtain();newBroadcastArgs.arg1 record;newBroadcastArgs.argi1 recordIndex;// 交叉广播优先级策略一些广播可能保证在其他已经pending的广播之前发布例如如果这个新广播处于不同的交付类别或与具有隐式响应期望的直接用户交互相关联。getQueueForBroadcast(record).addLast(newBroadcastArgs);onBroadcastEnqueued(record, recordIndex);return null;}// 判断广播类别紧急、负载、普通private NonNull ArrayDequeSomeArgs getQueueForBroadcast(NonNull BroadcastRecord record) {// 前台、用户交互、闹钟if (record.isUrgent()) {return mPendingUrgent;} else if (record.isOffload()) {return mPendingOffload;} else {return mPending;}}当给定的记录已入队时更新摘要统计信息跟onBroadcastDequeued对应。 // BroadcastProcessQueue.javaprivate void onBroadcastEnqueued(NonNull BroadcastRecord record, int recordIndex) {if (record.deferUntilActive) {mCountDeferred;}if (record.isForeground()) {if (record.deferUntilActive) {mCountForegroundDeferred;}mCountForeground;}if (record.ordered) {mCountOrdered;}if (record.alarm) {mCountAlarm;}if (record.prioritized) {if (record.deferUntilActive) {mCountPrioritizedDeferred;}mCountPrioritized;}if (record.interactive) {mCountInteractive;}if (record.resultTo ! null) {mCountResultTo;}if (record.callerInstrumented) {mCountInstrumented;}if (record.receivers.get(recordIndex) instanceof ResolveInfo) {mCountManifest;}invalidateRunnableAt();}更新当前队列的RunnbaleAt 默认mRunnableAt时间为广播的入队时间500ms当前队列中有有序、闹钟、优先级、receiver为manifest或当前是persistent进程等mRunnableAt时间为广播的入队时间。当前进程队列有前台广播、源于用户交互广播、由由root/shell/active instrument发送广播或当前进程为instrumented或当前app为top app则mRunnableAt为入队时间-120s当前进程处于冻结状态mRunnableAt为入队时间120s或者defer // BroadcastProcessQueue.javaprivate void updateRunnableAt() {if (!mRunnableAtInvalidated) return;mRunnableAtInvalidated false;// 获取下一个待处理的广播final SomeArgs next peekNextBroadcast();if (next ! null) {final BroadcastRecord r (BroadcastRecord) next.arg1;final int index next.argi1;final long runnableAt r.enqueueTime;// 如果我们特别排在其他有序调度活动之后我们还不能运行if (r.isBlocked(index)) {mRunnableAt Long.MAX_VALUE;mRunnableAtReason REASON_BLOCKED;return;}// 对此进程的任何广播需要延迟的持续时间if (mForcedDelayedDurationMs 0) {mRunnableAt runnableAt mForcedDelayedDurationMs;mRunnableAtReason REASON_FORCE_DELAYED;// 前台广播数量 mCountForegroundDeferred} else if (mCountForeground mCountForegroundDeferred) {mRunnableAt runnableAt constants.DELAY_URGENT_MILLIS; //-120smRunnableAtReason REASON_CONTAINS_FOREGROUND;// 源于用户交互广播数量 0} else if (mCountInteractive 0) {mRunnableAt runnableAt constants.DELAY_URGENT_MILLIS; //-120smRunnableAtReason REASON_CONTAINS_INTERACTIVE;// 广播由root/shell/active instrument发送数量 0} else if (mCountInstrumented 0) {mRunnableAt runnableAt constants.DELAY_URGENT_MILLIS; //-120smRunnableAtReason REASON_CONTAINS_INSTRUMENTED;// 当前进程处于instrumented} else if (mProcessInstrumented) {mRunnableAt runnableAt constants.DELAY_URGENT_MILLIS; //-120smRunnableAtReason REASON_INSTRUMENTED;// PROCESS_STATE_TOP top app} else if (mUidForeground) {mRunnableAt runnableAt constants.DELAY_FOREGROUND_PROC_MILLIS; //-120smRunnableAtReason REASON_FOREGROUND;} else if (app ! null app.getSetProcState() ActivityManager.PROCESS_STATE_TOP) {// TODO (b/287676625): Use a callback to check when a process goes in and out of// the TOP state.mRunnableAt runnableAt constants.DELAY_FOREGROUND_PROC_MILLIS;mRunnableAtReason REASON_TOP_PROCESS;} else if (mProcessPersistent) {mRunnableAt runnableAt constants.DELAY_PERSISTENT_PROC_MILLIS;mRunnableAtReason REASON_PERSISTENT;} else if (UserHandle.isCore(uid)) {mRunnableAt runnableAt;mRunnableAtReason REASON_CORE_UID;// 有序广播数量 0 else if (mCountOrdered 0) {mRunnableAt runnableAt;mRunnableAtReason REASON_CONTAINS_ORDERED;// 闹钟触发的广播 0} else if (mCountAlarm 0) {mRunnableAt runnableAt;mRunnableAtReason REASON_CONTAINS_ALARM;// 优先级广播数量 mCountPrioritizedDeferred} else if (mCountPrioritized mCountPrioritizedDeferred) {mRunnableAt runnableAt;mRunnableAtReason REASON_CONTAINS_PRIORITIZED;// 有final receiver的广播 mCountPrioritizedDeferred} else if (mCountManifest 0) {mRunnableAt runnableAt;mRunnableAtReason REASON_CONTAINS_MANIFEST;// 进程冻结} else if (mProcessFreezable) {// 广播有设置deferUntilActiveif (r.deferUntilActive) {// 所有排队的广播都是可推迟的deferif (mCountDeferred mCountEnqueued) {mRunnableAt Long.MAX_VALUE;mRunnableAtReason REASON_CACHED_INFINITE_DEFER;} else {// 至少有一个排队的广播不可推迟请重新选择此记录的时间和原因。 // 如果后来的记录不可推迟并且是这些特殊情况之一则上述情况之一已经捕获了这一点。if (r.isForeground()) {mRunnableAt runnableAt constants.DELAY_URGENT_MILLIS;mRunnableAtReason REASON_CONTAINS_FOREGROUND;} else if (r.prioritized) {mRunnableAt runnableAt;mRunnableAtReason REASON_CONTAINS_PRIORITIZED;} else if (r.resultTo ! null) {mRunnableAt runnableAt;mRunnableAtReason REASON_CONTAINS_RESULT_TO;} else {mRunnableAt runnableAt constants.DELAY_CACHED_MILLIS; //120smRunnableAtReason REASON_CACHED;}}} else {// This record isnt deferrablemRunnableAt runnableAt constants.DELAY_CACHED_MILLIS;// 120smRunnableAtReason REASON_CACHED;}} else if (mCountResultTo 0) {mRunnableAt runnableAt;mRunnableAtReason REASON_CONTAINS_RESULT_TO;// 当前进程的为manifest的receiver数量 0} else {mRunnableAt runnableAt constants.DELAY_NORMAL_MILLIS; // 500msmRunnableAtReason REASON_NORMAL;}// 如果我们有太多待处理的广播绕过上面可能应用的任何延迟以帮助耗尽if (mPending.size() mPendingUrgent.size() mPendingOffload.size() constants.MAX_PENDING_BROADCASTS) {mRunnableAt Math.min(mRunnableAt, runnableAt);mRunnableAtReason REASON_MAX_PENDING;}} else {mRunnableAt Long.MAX_VALUE;mRunnableAtReason REASON_EMPTY;}}更新可运行队列 考虑更新“可运行”队列的列表特别是与给定队列相关的列表。 通常在 {link BroadcastProcessQueue#getRunnableAt()} 可能已更改时调用因为这会影响我们将“可运行”队列提升为“正在运行”的顺序。 // BroadcastQueueModernImpl.javaGuardedBy(mService)private void updateRunnableList(NonNull BroadcastProcessQueue queue) {if (getRunningIndexOf(queue) 0) {// 已经运行; 一旦它们运行完毕它们将被重新插入到可运行列表中所以现在不需要更新它们return;}// 为了将自己正确地放入可运行列表中我们可能需要更新可能已失效的内部结构 // 我们在最后一刻才等到以避免重复工作queue.updateDeferredStates(mBroadcastConsumerDeferApply, mBroadcastConsumerDeferClear);queue.updateRunnableAt();// 是可运行状态final boolean wantQueue queue.isRunnable();// 已在队列中final boolean inQueue (queue mRunnableHead) || (queue.runnableAtPrev ! null)|| (queue.runnableAtNext ! null);if (wantQueue) {if (inQueue) {// 我们处于队列中但我们在链表中的位置可能需要根据 // runnableAt 更改进行移动链表前面的额队列总是应先被分发final boolean prevLower (queue.runnableAtPrev ! null)? queue.runnableAtPrev.getRunnableAt() queue.getRunnableAt() : true;final boolean nextHigher (queue.runnableAtNext ! null)? queue.runnableAtNext.getRunnableAt() queue.getRunnableAt() : true;if (!prevLower || !nextHigher) {mRunnableHead removeFromRunnableList(mRunnableHead, queue);mRunnableHead insertIntoRunnableList(mRunnableHead, queue);}} else {mRunnableHead insertIntoRunnableList(mRunnableHead, queue);}// 从队列中移除} else if (inQueue) {mRunnableHead removeFromRunnableList(mRunnableHead, queue);}// 当前队列为空、不是正在调度、进程不存活等移除该队列if (queue.isEmpty() !queue.isActive() !queue.isProcessWarm()) {removeProcessQueue(queue.processName, queue.uid);}}分发 更新正在运行队列 考虑更新“正在运行”队列的列表。 此方法可以将“可运行”队列提升为“正在运行”受限于最多 {link BroadcastConstants#MAX_RUNNING_PROCESS_QUEUES}2 or 4 热进程和只有一个挂起的冷启动。 一次可运行的队列数量为MAX_RUNNING_PROCESS_QUEUES低内存2个否则4个EXTRA_RUNNING_URGENT_PROCESS_QUEUES1个 如果当前正在运行的列表 (2 or 4)则取紧急的队列当前队列未到执行时间则在指定时间再次执行更新当前队列的进程是冷启动但是已经有一个需要冷启动的队列正在运行则取下一个队列 // BroadcastQueueModernImpl.javaGuardedBy(mService)private void updateRunningListLocked() {// 此处分配的大小隐含地包括超出正常并行性的 MAX_RUNNING_QUEUES 软限制的紧急调度的额外预留。// 如果我们已经在调度一些紧急广播请先将其与额外广播放在一起 - 它的作用是在正常预留完全被不太紧急的调度占用时允许紧急广播流量的进展而不是通常扩展并行性。final int usedExtra Math.min(getRunningUrgentCount(),mConstants.EXTRA_RUNNING_URGENT_PROCESS_QUEUES); //1 // 空闲数量int avail mRunning.length - getRunningSize() - usedExtra;if (avail 0) return;final int cookie traceBegin(updateRunningList);final long now SystemClock.uptimeMillis();// 如果有人正在等待一个状态那么现在一切都可以运行final boolean waitingFor !mWaitingFor.isEmpty();// 我们现在正在进行更新因此删除任何未来的更新请求// 如果需要我们会在下面重新发布mLocalHandler.removeMessages(MSG_UPDATE_RUNNING_LIST);boolean updateOomAdj false;BroadcastProcessQueue queue mRunnableHead;while (queue ! null avail 0) {BroadcastProcessQueue nextQueue queue.runnableAtNext;final long runnableAt queue.getRunnableAt();// 当广播在列表遍历过程中被跳过或失败时我们可能会遇到一个不再可运行的队列 跳过它if (!queue.isRunnable()) {queue nextQueue;continue;}// 如果我们达到了非紧急调度并行度的软限制if (getRunningSize() mConstants.MAX_RUNNING_PROCESS_QUEUES) { // 2 or 4 // 则只考虑从就绪广播为紧急的队列进行交付if (!queue.isPendingUrgent()) {queue nextQueue;continue;}}// 最早的一个队列运行时间超出当前时间跳出循环并post 延时消息以便及时分发if (runnableAt now !waitingFor) {mLocalHandler.sendEmptyMessageAtTime(MSG_UPDATE_RUNNING_LIST, runnableAt);break;}// 我们可能还没有听说过新运行的进程所以如果我们是冷启请考虑刷新updateWarmProcess(queue);final boolean processWarm queue.isProcessWarm();if (processWarm) {mService.mOomAdjuster.unfreezeTemporarily(queue.app,CachedAppOptimizer.UNFREEZE_REASON_START_RECEIVER);// 该进程可能会作为解冻的一部分被终止。 所以再检查一下是否仍然存在。if (!queue.isProcessWarm()) {queue nextQueue;enqueueUpdateRunningList();continue;}} else {// 我们只提供一次运行一个冷启动以节省系统资源// 下面我们要么声明单个插槽要么跳到寻找另一个warm进程if (mRunningColdStart null) {mRunningColdStart queue;} else if (isPendingColdStartValid()) {// 转向考虑下一个可运行队列queue nextQueue;continue;} else {// 挂起的冷启动无效因此请清除它并继续。clearInvalidPendingColdStart();mRunningColdStart queue;}}if (DEBUG_BROADCAST) logv(Promoting queue from runnable to running; process is queue.app);promoteToRunningLocked(queue);boolean completed;if (processWarm) {updateOomAdj | queue.runningOomAdjusted;try {completed scheduleReceiverWarmLocked(queue);} catch (BroadcastDeliveryFailedException e) {reEnqueueActiveBroadcast(queue);completed true;}} else {completed scheduleReceiverColdLocked(queue);}// 如果我们完成了向进程传递广播我们可以将其从“运行”列表中降级。if (completed) {demoteFromRunningLocked(queue);}// 可运行数量-1avail--;// Move to considering next runnable queuequeue nextQueue;}// 更新adjif (updateOomAdj) {mService.updateOomAdjPendingTargetsLocked(OOM_ADJ_REASON_START_RECEIVER);}checkPendingColdStartValidity();checkAndRemoveWaitingFor();traceEnd(cookie);} 将进程提升到“正在运行”列表 // BroadcastQueueModernImpl.javaGuardedBy(mService)private void promoteToRunningLocked(NonNull BroadcastProcessQueue queue) {// 分配此可用许可证并开始运行final int queueIndex getRunningIndexOf(null);// 将当前队列放在可运行数组中mRunning[queueIndex] queue;// 从可运行链表中删除当前队列mRunnableHead removeFromRunnableList(mRunnableHead, queue);// 将此进程的所有跟踪事件发送到一致的轨道中queue.runningTraceTrackName TAG .mRunning[ queueIndex ];// 指示此过程是否应进行 OOM 调整的标志定义为升级到正在运行的插槽的一部分queue.runningOomAdjusted queue.isPendingManifest()|| queue.isPendingOrdered()|| queue.isPendingResultTo();// 如果已经处于热启动我们可以立即提出OOM调整请求 否则我们需要等到进程变暖final boolean processWarm queue.isProcessWarm();if (processWarm) {notifyStartedRunning(queue);}// 如果我们已经暖和了现在就安排下一个待定的广播 否则我们将等待冷启动回来// 设置队列的下一个active广播queue.makeActiveNextPending();if (processWarm) {queue.traceProcessRunningBegin();} else {queue.traceProcessStartingBegin();}}// 通知操作系统的其他部分给定的广播队列已开始运行通常用于内部簿记。private void notifyStartedRunning(NonNull BroadcastProcessQueue queue) {if (queue.app ! null) {// 当前进程的ProcessReceiverRecord计数queue.app.mReceivers.incrementCurReceivers();// 如果它在后台受限不要改变它的 LRU 位置。.if (mService.mInternal.getRestrictionLevel(queue.uid) ActivityManager.RESTRICTION_LEVEL_RESTRICTED_BUCKET) {mService.updateLruProcessLocked(queue.app, false, null);}mService.mOomAdjuster.unfreezeTemporarily(queue.app,CachedAppOptimizer.UNFREEZE_REASON_START_RECEIVER);// manifest receiver/有序/有最终接受者所在进程需要将procState提升到11if (queue.runningOomAdjusted) {queue.app.mState.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);mService.enqueueOomAdjTargetLocked(queue.app);}}}将进程从“正在运行”列表中降级 // BroadcastQueueModernImpl.javaGuardedBy(mService)private void demoteFromRunningLocked(NonNull BroadcastProcessQueue queue) {if (!queue.isActive()) {logw(Ignoring demoteFromRunning; no active broadcast for queue);return;}final int cookie traceBegin(demoteFromRunning);// 我们已经耗尽了正在运行的广播 也许回到可运行状态queue.makeActiveIdle();queue.traceProcessEnd();final int queueIndex getRunningIndexOf(queue);mRunning[queueIndex] null;// 更新可运行列表和Running列表尝试进行下一个进程队列的分发updateRunnableList(queue);enqueueUpdateRunningList();// 告诉其他操作系统组件应用程序没有主动运行从而有机会更新 OOM 调整notifyStoppedRunning(queue);traceEnd(cookie);}热启分发 当我们知道进程处于热状态时在给定队列上安排当前活动的广播。 无论是在远程应用程序处理广播的情况下还是在没有远程应用程序的情况下在本地完成广播的情况下都强烈希望通过调用 {link #finishReceiverLocked} 来始终如一地处理所有涉及结果 。 CheckResultGuardedBy(mService)private boolean scheduleReceiverWarmLocked(NonNull BroadcastProcessQueue queue)throws BroadcastDeliveryFailedException {// 检查状态是否是activecheckState(queue.isActive(), isActive);final int cookie traceBegin(scheduleReceiverWarmLocked);// 有序广播或静态注仅执行一次循环while (queue.isActive()) {final BroadcastRecord r queue.getActive();final int index queue.getActiveIndex();// 标记分发时间if (r.terminalCount 0) {r.dispatchTime SystemClock.uptimeMillis();r.dispatchRealTime SystemClock.elapsedRealtime();r.dispatchClockTime System.currentTimeMillis();}// 是否应该跳过分发final String skipReason shouldSkipReceiver(queue, r, index);// 正常分发if (skipReason null) {final boolean isBlockingDispatch dispatchReceivers(queue, r, index);if (isBlockingDispatch) {traceEnd(cookie);return false;}} else {// 跳过则标记结束状态为DELIVERY_SKIPPEDfinishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_SKIPPED, skipReason);}// 是否应该退出分发循环达到数量限制会退出if (shouldRetire(queue)) {break;}// 标记下一个活动广播queue.makeActiveNextPending();}traceEnd(cookie);return true;}冷启分发 当我们知道进程处于冷状态时在给定队列上安排当前活动的广播。 这将导致冷启动并最终会在准备就绪后调用 {link #scheduleReceiverWarmLocked}。 // BroadcastQueueModernImpl.javaCheckResultGuardedBy(mService)private boolean scheduleReceiverColdLocked(NonNull BroadcastProcessQueue queue) {checkState(queue.isActive(), isActive);// 标记活动广播是通过冷启动安排的queue.setActiveViaColdStart(true);final BroadcastRecord r queue.getActive();final int index queue.getActiveIndex();final Object receiver r.receivers.get(index);// 忽略通过动态注册的receiver来冷启动if (receiver instanceof BroadcastFilter) {mRunningColdStart null;finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_SKIPPED,BroadcastFilter for cold app);return true;}// 判断是否需要跳过此次分发final String skipReason shouldSkipReceiver(queue, r, index);if (skipReason ! null) {mRunningColdStart null;finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_SKIPPED, skipReason);return true;}final ApplicationInfo info ((ResolveInfo) receiver).activityInfo.applicationInfo;final ComponentName component ((ResolveInfo) receiver).activityInfo.getComponentName();if ((info.flags ApplicationInfo.FLAG_STOPPED) ! 0) {queue.setActiveWasStopped(true);}final int intentFlags r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND;final HostingRecord hostingRecord new HostingRecord(HostingRecord.HOSTING_TYPE_BROADCAST,component, r.intent.getAction(), r.getHostingRecordTriggerType());final boolean isActivityCapable (r.options ! null r.options.getTemporaryAppAllowlistDuration() 0);final int zygotePolicyFlags isActivityCapable ? ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE: ZYGOTE_POLICY_FLAG_EMPTY;final boolean allowWhileBooting (r.intent.getFlags() Intent.FLAG_RECEIVER_BOOT_UPGRADE) ! 0;if (DEBUG_BROADCAST) logv(Scheduling r to cold queue);queue.app mService.startProcessLocked(queue.processName, info, true, intentFlags,hostingRecord, zygotePolicyFlags, allowWhileBooting, false);// 启动进程失败if (queue.app null) {mRunningColdStart null;finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_FAILURE,startProcessLocked failed);return true;}return false;}冷启进程启动后走跟热启一样的流程 // BroadcastQueueModernImpl.javaOverridepublic boolean onApplicationAttachedLocked(NonNull ProcessRecord app)throws BroadcastDeliveryFailedException {if (DEBUG_BROADCAST) {logv(Process app is attached);}// 进程记录可以被回收所以总是从查找相关的每个进程队列开始final BroadcastProcessQueue queue getProcessQueue(app);if (queue ! null) {setQueueProcess(queue, app);}boolean didSomething false;if ((mRunningColdStart ! null) (mRunningColdStart queue)) {// 我们一直在等待这个应用程序冷启动现在已经准备好了 调度它的下一个广播并清除插槽mRunningColdStart null;// 现在我们已经启动我们终于可以请求我们一直在等待的 OOM 调整notifyStartedRunning(queue);mService.updateOomAdjPendingTargetsLocked(OOM_ADJ_REASON_START_RECEIVER);queue.traceProcessEnd();queue.traceProcessRunningBegin();try {// 跟热启流程一样了if (scheduleReceiverWarmLocked(queue)) {// 当前进程分发完成从可运行列表中移除demoteFromRunningLocked(queue);}} catch (BroadcastDeliveryFailedException e) {reEnqueueActiveBroadcast(queue);demoteFromRunningLocked(queue);throw e;}// 我们可能愿意开始另一个冷启动在ActivityManager线程中触发enqueueUpdateRunningList();didSomething true;}return didSomething;}分发到App进程 接收者即将被发送。 如有必要启动 ANR 计时器。 如果需要等待finishReceiver回调则返回true // BroadcastQueueModernImpl.java CheckResult private boolean dispatchReceivers(NonNull BroadcastProcessQueue queue,NonNull BroadcastRecord r, int index) throws BroadcastDeliveryFailedException {final ProcessRecord app queue.app;final Object receiver r.receivers.get(index);// 当有请求时或当我们立即假设交付成功时在启动期间尽早跳过 ANR 跟踪final boolean assumeDelivered r.isAssumedDelivered(index);if (mService.mProcessesReady !r.timeoutExempt !assumeDelivered) {queue.lastCpuDelayTime queue.app.getCpuDelayTime();// 前台10s后台60sfinal int softTimeoutMillis (int) (r.isForeground() ? mFgConstants.TIMEOUT: mBgConstants.TIMEOUT);mLocalHandler.sendMessageDelayed(Message.obtain(mLocalHandler,MSG_DELIVERY_TIMEOUT_SOFT, softTimeoutMillis, 0, queue), softTimeoutMillis);}// 添加或更新后台启动权限if (r.mBackgroundStartPrivileges.allowsAny()) {app.addOrUpdateBackgroundStartPrivileges(r, r.mBackgroundStartPrivileges);// 10s豁免final long timeout r.isForeground() ? mFgConstants.ALLOW_BG_ACTIVITY_START_TIMEOUT: mBgConstants.ALLOW_BG_ACTIVITY_START_TIMEOUT;final SomeArgs args SomeArgs.obtain();args.arg1 app;args.arg2 r;mLocalHandler.sendMessageDelayed(Message.obtain(mLocalHandler, MSG_BG_ACTIVITY_START_TIMEOUT, args), timeout);}if (r.options ! null r.options.getTemporaryAppAllowlistDuration() 0) {if (r.options.getTemporaryAppAllowlistType() PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_APP_FREEZING_DELAYED) {// Only delay freezer, dont add to any temp allowlist// TODO: Add a unit testmService.mOomAdjuster.mCachedAppOptimizer.unfreezeTemporarily(app,CachedAppOptimizer.UNFREEZE_REASON_START_RECEIVER,r.options.getTemporaryAppAllowlistDuration());} else {// 临时白名单相关mService.tempAllowlistUidLocked(queue.uid,r.options.getTemporaryAppAllowlistDuration(),r.options.getTemporaryAppAllowlistReasonCode(), r.toShortString(),r.options.getTemporaryAppAllowlistType(), r.callingUid);}}if (DEBUG_BROADCAST) logv(Scheduling r to warm app);// 设置传递状态为SCHEDULEDsetDeliveryState(queue, app, r, index, receiver, BroadcastRecord.DELIVERY_SCHEDULED,scheduleReceiverWarmLocked);final Intent receiverIntent r.getReceiverIntent(receiver);final IApplicationThread thread app.getOnewayThread();if (thread ! null) {try {if (r.shareIdentity) {mService.mPackageManagerInt.grantImplicitAccess(r.userId, r.intent,UserHandle.getAppId(app.uid), r.callingUid, true);}queue.lastProcessState app.mState.getCurProcState();// 动态分发if (receiver instanceof BroadcastFilter) {notifyScheduleRegisteredReceiver(app, r, (BroadcastFilter) receiver);thread.scheduleRegisteredReceiver(((BroadcastFilter) receiver).receiverList.receiver,receiverIntent, r.resultCode, r.resultData, r.resultExtras,r.ordered, r.initialSticky, assumeDelivered, r.userId,app.mState.getReportedProcState(),r.shareIdentity ? r.callingUid : Process.INVALID_UID,r.shareIdentity ? r.callerPackage : null);// TODO: consider making registered receivers of unordered// broadcasts report results to detect ANRs// 如果无序广播直接标记分发状态为DELIVEREDif (assumeDelivered) {finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_DELIVERED,assuming delivered);return false;}} else {// 静态分发notifyScheduleReceiver(app, r, (ResolveInfo) receiver);thread.scheduleReceiver(receiverIntent, ((ResolveInfo) receiver).activityInfo,null, r.resultCode, r.resultData, r.resultExtras, r.ordered,assumeDelivered, r.userId,app.mState.getReportedProcState(),r.shareIdentity ? r.callingUid : Process.INVALID_UID,r.shareIdentity ? r.callerPackage : null);}// 有序或静态则block下个广播的分发return true;} catch (RemoteException e) {final String msg Failed to schedule r to receiver via app : e;logw(msg);app.killLocked(Cant deliver broadcast, ApplicationExitInfo.REASON_OTHER,ApplicationExitInfo.SUBREASON_UNDELIVERED_BROADCAST, true);// If we were trying to deliver a manifest broadcast, throw the error as we need// to try redelivering the broadcast to this receiver.if (receiver instanceof ResolveInfo) {mLocalHandler.removeMessages(MSG_DELIVERY_TIMEOUT_SOFT, queue);throw new BroadcastDeliveryFailedException(e);}finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_FAILURE,remote app);return false;}} else {// 进程不存在finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_FAILURE,missing IApplicationThread);return false;} }如果应假定此接收者已交付则返回 true。 // BroadcastRecord.java boolean isAssumedDelivered(int index) {return (receivers.get(index) instanceof BroadcastFilter) !ordered (resultTo null); }结束分发 有序广播或静态注册需要等待app执行完后binder回调finishReceiverLocked方法结束分发运行在binder线程。 // BroadcastQueueModernImpl.javaOverridepublic boolean finishReceiverLocked(NonNull ProcessRecord app, int resultCode,Nullable String resultData, Nullable Bundle resultExtras, boolean resultAbort,boolean waitForServices) {final BroadcastProcessQueue queue getProcessQueue(app);if ((queue null) || !queue.isActive()) {logw(Ignoring finishReceiverLocked; no active broadcast for queue);return false;}final BroadcastRecord r queue.getActive();final int index queue.getActiveIndex();// 有序广播相关属性赋值if (r.ordered) {r.resultCode resultCode;r.resultData resultData;r.resultExtras resultExtras;if (!r.isNoAbort()) {r.resultAbort resultAbort;}}// 为了确保以单调方式更新“超出”高水位线我们在可能跳过任何剩余的中止接收器之前完成此接收器finishReceiverActiveLocked(queue,BroadcastRecord.DELIVERY_DELIVERED, remote app);// 当调用者中止有序广播时我们将所有剩余的接收者标记为已跳过if (r.resultAbort) {for (int i index 1; i r.receivers.size(); i) {setDeliveryState(null, null, r, i, r.receivers.get(i),BroadcastRecord.DELIVERY_SKIPPED, resultAbort);}}// 如果当前分发的广播达到限制则从可运行列表中移除if (shouldRetire(queue)) {demoteFromRunningLocked(queue);return true;}// 我们进展顺利 进入该过程的下一个广播queue.makeActiveNextPending();try {// 如果执行广播流程已达到限制则从可运行列表中移除当前进程队列if (scheduleReceiverWarmLocked(queue)) {demoteFromRunningLocked(queue);return true;}} catch (BroadcastDeliveryFailedException e) {reEnqueueActiveBroadcast(queue);demoteFromRunningLocked(queue);return true;}return false;}终止队列中所有活动的广播。 // BroadcastQueueModernImpl.javaprivate void finishReceiverActiveLocked(NonNull BroadcastProcessQueue queue,DeliveryState int deliveryState, NonNull String reason) {if (!queue.isActive()) {logw(Ignoring finishReceiverActiveLocked; no active broadcast for queue);return;}final int cookie traceBegin(finishReceiver);final ProcessRecord app queue.app;final BroadcastRecord r queue.getActive();final int index queue.getActiveIndex();final Object receiver r.receivers.get(index);// 标记终端传递状态setDeliveryState(queue, app, r, index, receiver, deliveryState, reason);// 处理anr超时if (deliveryState BroadcastRecord.DELIVERY_TIMEOUT) {r.anrCount;if (app ! null !app.isDebugging()) {final String packageName getReceiverPackageName(receiver);final String className getReceiverClassName(receiver);mService.appNotResponding(queue.app,TimeoutRecord.forBroadcastReceiver(r.intent, packageName, className));}} else {// 移除超时消息mLocalHandler.removeMessages(MSG_DELIVERY_TIMEOUT_SOFT, queue);mLocalHandler.removeMessages(MSG_DELIVERY_TIMEOUT_HARD, queue);}// 假设接收方刚刚完成检查是否满足“waitingFor”条件。checkAndRemoveWaitingFor();traceEnd(cookie);}设置给定广播的传递状态然后应用与有序广播相关的任何额外簿记。 // BroadcastQueueModernImpl.javaprivate void setDeliveryState(Nullable BroadcastProcessQueue queue,Nullable ProcessRecord app, NonNull BroadcastRecord r, int index,NonNull Object receiver, DeliveryState int newDeliveryState,NonNull String reason) {final int cookie traceBegin(setDeliveryState);// 记住旧状态并应用新状态final int oldDeliveryState getDeliveryState(r, index);final boolean beyondCountChanged r.setDeliveryState(index, newDeliveryState, reason);// 当我们改变交付状态作为从队列运行的一部分时发出任何相关的跟踪结果if (queue ! null) {if (newDeliveryState BroadcastRecord.DELIVERY_SCHEDULED) {queue.traceActiveBegin();} else if ((oldDeliveryState BroadcastRecord.DELIVERY_SCHEDULED) isDeliveryStateTerminal(newDeliveryState)) {queue.traceActiveEnd();}}// 如果我们进入最终状态我们可能会有内部簿记来更新有序广播if (!isDeliveryStateTerminal(oldDeliveryState) isDeliveryStateTerminal(newDeliveryState)) {if (DEBUG_BROADCAST newDeliveryState ! BroadcastRecord.DELIVERY_DELIVERED) {logw(Delivery state of r to receiver via app changed from deliveryStateToString(oldDeliveryState) to deliveryStateToString(newDeliveryState) because reason);}notifyFinishReceiver(queue, app, r, index, receiver);}//当我们达到新的高水位线时我们可能能够解锁其他接收者或最终结果if (beyondCountChanged) {if (r.beyondCount r.receivers.size()) {// 已经派发完成则回调最终receiverscheduleResultTo(r);}// 我们这里的终端状态可能足以让我们阻塞的另一个进程现在可以运行if (r.ordered || r.prioritized) {for (int i 0; i r.receivers.size(); i) {if (!isDeliveryStateTerminal(getDeliveryState(r, i)) || (i index)) {final Object otherReceiver r.receivers.get(i);final BroadcastProcessQueue otherQueue getProcessQueue(getReceiverProcessName(otherReceiver),getReceiverUid(otherReceiver));if (otherQueue ! null) {otherQueue.invalidateRunnableAt();updateRunnableList(otherQueue);}}}enqueueUpdateRunningList();}}traceEnd(cookie);}
http://www.dnsts.com.cn/news/145251.html

相关文章:

  • 义务教育标准化建设网站小清新文章网站
  • 网站源码建站视频全屋定制十大名牌排行最新
  • 建设银行网站怎么下载地址网站内页没有排名
  • 网站jquery上传源代码自动优化网站建设咨询
  • 云南建设厅网站备案厂家寿光市建设局网站
  • 攻击网站步骤大学生网站建设与网页设计报告
  • 重庆电视台新闻频道百度网站优化排行
  • 瑞安市网站建设网站负责人备案采集照具体要求
  • 上饶专业企业网站建设网站制作是不是要先用ps做
  • 网站方案编写网站代码如何优化
  • 青岛市崂山区建设局网站网站建设的具体过程
  • 北京门户网站设计天津企业seo
  • 我想来做外贸网站来推广泰州网站快速排名优化
  • 谷歌云宝塔搭建WordPress济南网站搜索优化
  • 网站建设中企动力最佳a5网站开发课程设计培训
  • 网站每年多少钱深圳app开发怎么选
  • 工业智能科技网站设计seo是什么技术
  • 检测网站安全怎么开公司
  • 建设网站的工作总结网页制作app
  • 简洁大气的企业网站电子商务网站开发与设计
  • 科技部网站改版方案wordpress frame
  • 网站建设ppt方案结语wordpress主题the 7特点
  • 株洲网站建设优化企业保山网站建设多少钱
  • 动易网站 首页模板修改网站建设 洪塔
  • 网站维护需要多久时间网站好坏标准
  • 做的网站百度排名没有图片显示求个网站知乎
  • 做外贸生意在哪个网站手机微信小程序免费制作平台
  • 看案例网站东莞网站建设方案报价
  • 中国域名网站餐饮logo设计
  • 淄博网站建设至信网络台州城乡建设局网站