💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
BROADCAST_INTENT_MSG消息将触发processNextBroadcast函数,下面分阶段来分析它。 1. processNextBroadcast分析之一 **ActivityManagerService.java::processNextBroadcast** ~~~ private final void processNextBroadcast(booleanfromMsg) { //如果是BROADCAST_INTENT_MSG消息触发该函数,则fromMsg为true synchronized(this) { BroadcastRecord r; updateCpuStats();//更新CPU使用情况 if(fromMsg) mBroadcastsScheduled = false; //先处理mParallelBroadcasts中的成员。如前所述,AMS在一个循环中处理它们 while(mParallelBroadcasts.size() > 0) { r =mParallelBroadcasts.remove(0); r.dispatchTime =SystemClock.uptimeMillis(); r.dispatchClockTime =System.currentTimeMillis(); final int N = r.receivers.size(); for(int i=0; i<N; i++) { Object target = r.receivers.get(i); //①mParallelBroadcasts中的成员全为BroadcastFilter类型,所以下面的函数 //将target直接转换成BroadcastFilter类型。注意,最后一个参数为false deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false); } //将这条处理过的记录保存到mHistoryBroadcast中,供调试使用 addBroadcastToHistoryLocked(r); } ~~~ deliverToRegisteredReceiverLocked函数的功能就是派发广播给接收者,其代码如下: **ActivityManagerService.java::deliverToRegisteredReceiverLocked** ~~~ private final voiddeliverToRegisteredReceiverLocked(BroadcastRecord r, BroadcastFilter filter, booleanordered) { booleanskip = false; //检查发送进程是否有filter要求的权限 if(filter.requiredPermission != null) { intperm = checkComponentPermission(filter.requiredPermission, r.callingPid, r.callingUid, -1, true); if(perm != PackageManager.PERMISSION_GRANTED) skip = true; } //检查接收者是否有发送者要求的权限 if(r.requiredPermission != null) { intperm = checkComponentPermission(r.requiredPermission, filter.receiverList.pid, filter.receiverList.uid, -1, true); if(perm != PackageManager.PERMISSION_GRANTED) skip = true; } if(!skip) { if(ordered) { ......//设置一些状态,成员变量等信息,不涉及广播发送 } try { //发送广播 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,new Intent(r.intent), r.resultCode, r.resultData, r.resultExtras, r.ordered, r.initialSticky); if(ordered) r.state = BroadcastRecord.CALL_DONE_RECEIVE; }...... } } } ~~~ 来看performReceiveLocked函数,其代码如下: **ActivityManagerService.java::performReceiveLocked** ~~~ static void performReceiveLocked(ProcessRecordapp, IIntentReceiver receiver, Intentintent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky) throws RemoteException { if(app != null && app.thread != null) { //如果app及app.thread不为null,则调度scheduleRegisteredReceiver, //注意这个函数名为scheduleRegisteredReceiver,它只针对动态注册的广播接收者 app.thread.scheduleRegisteredReceiver(receiver,intent, resultCode, data, extras, ordered, sticky); } else{ //否则调用IIntentReceiver的performReceive函数 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky); } } ~~~ 对于动态注册者而言,在大部分情况下会执行if分支,所以应用进程ApplicationThread的scheduleRegisteredReceiver函数将被调用。稍后再分析应用进程的广播处理流程。 2. processNextBroadcast分析之二 至此,processNextBroadcast已经在一个while循环中处理完mParallelBroadcasts的所有成员了,实际上,这种处理方式也会造成惊群效应,但影响相对较少。这是因为对于动态注册者来说,它们所在的应用进程已经创建并初始化成功。此处的广播发送只是调用应用进程的一个函数而已。相比于创建进程,再初始化Android运行环境所需的工作量,调用scheduleRegisteredReceiver的工作就比较轻松了。 来看processNextBroadcast第二阶段的工作,代码如下: **ActivityManagerService.java::processNextBroadcast** ~~~ /* 现在要处理mOrderedBroadcasts中的成员。如前所述,它要处理一个接一个的接受者,如果 接收者所在进程还未启动,则需要等待。mPendingBroadcast变量用于标识因为应用进程还未 启动而处于等待状态的BroadcastRecord。 */ if(mPendingBroadcast != null) { boolean isDead; synchronized (mPidsSelfLocked) { isDead= (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null); } /*重要说明 判断要等待的进程是否为dead进程,如果没有dead进程,则继续等待。仔细思考,此处直接 返回会有什么问题。 问题不小!假设有两个ordered广播A和B,有两个接收者,AR和BR,并且BR所 在进程已经启动并完成初始化Android运行环境。如果processNextBroadcast先处理A, 再处理B,那么此处B的处理将因为mPendingBroadcast不为空而被延后。虽然B和A 之间没有任何关系(例如完全是两个不同的广播消息), 但是事实上,大多数开发人员理解的order是针对单个广播的,例如A有5个接收者,那么对这 5个接收者的广播的处理是串行的。通过此处的代码发现,系统竟然串行处理A和B广播,即 B广播要待到A的5个接收者都处理完了才能处理。 */ if(!isDead) return; else { mPendingBroadcast.state = BroadcastRecord.IDLE; mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex; mPendingBroadcast = null; } } boolean looped = false; do { // mOrderedBroadcasts处理完毕 if (mOrderedBroadcasts.size() == 0) { scheduleAppGcsLocked(); if (looped) updateOomAdjLocked(); return; } r =mOrderedBroadcasts.get(0); boolean forceReceive = false; //下面这段代码用于判断此条广播是否处理时间过长 //先得到该条广播的所有接收者 intnumReceivers = (r.receivers != null) ? r.receivers.size() : 0; if(mProcessesReady && r.dispatchTime > 0) { long now = SystemClock.uptimeMillis(); //如果总耗时超过2倍的接收者个数*每个接收者最长处理时间(10秒),则 //强制结束这条广播的处理 if ((numReceivers > 0) && (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))){ broadcastTimeoutLocked(false);//读者阅读完本节后可自行研究该函数 forceReceive = true; r.state = BroadcastRecord.IDLE; } }//if(mProcessesReady...)判断结束 if (r.state != BroadcastRecord.IDLE) return; //如果下面这个if条件满足,则表示该条广播要么已经全部被处理,要么被中途取消 if(r.receivers == null || r.nextReceiver >= numReceivers || r.resultAbort || forceReceive) { if(r.resultTo != null) { try { //将该广播的处理结果传给设置了resultTo的接收者 performReceiveLocked(r.callerApp, r.resultTo, new Intent(r.intent), r.resultCode, r.resultData, r.resultExtras, false, false); r.resultTo = null; }...... } cancelBroadcastTimeoutLocked(); addBroadcastToHistoryLocked(r); mOrderedBroadcasts.remove(0); r = null; looped = true; continue; } } while (r== null); ~~~ processNextBroadcast第二阶段的工作比较简单: - 首先根据是否处于pending状态(mPendingBroadcast不为null)进行相关操作。读者要认真体会代码中的重要说明。 - 处理超时的广播记录。这个超时时间是2*BROADCAST_TIMEOUT*numReceivers。BROADCAST_TIMEOUT默认为10秒。由于涉及创建进程,初始化Android运行环境等重体力活,故此处超时时间还乘以一个固定倍数2。 3. processNextBroadcast分析之三 来看processNextBroadcast第三阶段的工作,代码如下: **ActivityManagerService.java::processNextBroadcast** ~~~ int recIdx= r.nextReceiver++; r.receiverTime = SystemClock.uptimeMillis(); if (recIdx== 0) { r.dispatchTime = r.receiverTime;//记录本广播第一次处理开始的时间 r.dispatchClockTime= System.currentTimeMillis(); } //设置广播处理超时时间,BROADCAST_TIMEOUT为10秒 if (!mPendingBroadcastTimeoutMessage) { longtimeoutTime = r.receiverTime + BROADCAST_TIMEOUT; setBroadcastTimeoutLocked(timeoutTime); } //取该条广播下一个接收者 ObjectnextReceiver = r.receivers.get(recIdx); if(nextReceiver instanceof BroadcastFilter) { //如果是动态接收者,则直接调用deliverToRegisteredReceiverLocked处理 BroadcastFilter filter = (BroadcastFilter)nextReceiver; deliverToRegisteredReceiverLocked(r, filter, r.ordered); if(r.receiver == null || !r.ordered) { r.state = BroadcastRecord.IDLE; scheduleBroadcastsLocked(); } return;//已经通知一个接收者去处理该广播,需要等它的处理结果,所以此处直接返回 } //如果是静态接收者,则它的真实类型是ResolveInfo ResolveInfo info = (ResolveInfo)nextReceiver; booleanskip = false; //检查权限 int perm =checkComponentPermission(info.activityInfo.permission, r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid, info.activityInfo.exported); if (perm!= PackageManager.PERMISSION_GRANTED) skip = true; if(info.activityInfo.applicationInfo.uid != Process.SYSTEM_UID && r.requiredPermission != null) { ...... } //设置skip为true if(r.curApp != null && r.curApp.crashing) skip = true; if (skip){ r.receiver = null; r.curFilter = null; r.state = BroadcastRecord.IDLE; scheduleBroadcastsLocked();//再调度一次广播处理 return; } r.state= BroadcastRecord.APP_RECEIVE; StringtargetProcess = info.activityInfo.processName; r.curComponent = new ComponentName( info.activityInfo.applicationInfo.packageName, info.activityInfo.name); r.curReceiver = info.activityInfo; try { //设置Package stopped的状态为false AppGlobals.getPackageManager().setPackageStoppedState( r.curComponent.getPackageName(),false); } ...... ProcessRecord app = getProcessRecordLocked(targetProcess, info.activityInfo.applicationInfo.uid); //如果该接收者对应的进程已经存在 if (app!= null && app.thread != null) { try { app.addPackage(info.activityInfo.packageName); //该函数内部调用应用进程的scheduleReceiver函数,读者可自行分析 processCurBroadcastLocked(r, app); return;//已经触发该接收者处理本广播,需要等待处理结果 }...... } //最糟的情况就是该进程还没有启动 if((r.curApp=startProcessLocked(targetProcess, info.activityInfo.applicationInfo, true,......)!= 0)) == null) { ......//进程启动失败的处理 return; } mPendingBroadcast = r; //设置mPendingBroadcast mPendingBroadcastRecvIndex = recIdx; } ~~~ 对processNextBroadcast第三阶段的工作总结如下: - 如果广播接收者为动态注册对象,则直接调用deliverToRegisteredReceiverLocked处理它。 - 如果广播接收者为静态注册对象,并且该对象对应的进程已经存在,则调用processCurBroadcastLocked处理它。 - 如果广播接收者为静态注册对象,并且该对象对应的进程还不存在,则需要创建该进程。这是最糟糕的情况。 此处,不再讨论新进程创建及Android运行环境初始化相关的逻辑,读者可返回阅读“attachApplicationLocked分析之三”,其中有处理mPendingBroadcast的内容。