if(receivers==null){
receivers=newArrayList();
}
//插入剩下的动态BroadcastReceiver
receivers.add(registeredReceivers.get(ir));
ir++;
}
if((receivers!
=null&&receivers.size()>0)
||resultTo!
=null){
BroadcastQueuequeue=broadcastQueueForIntent(intent);
//构造对应的BroadcastRecord
BroadcastRecordr=newBroadcastRecord(........);
............
//同样判断是否需要替换,这里是OrderedQueue
booleanreplaced=replacePending&&queue.replaceOrderedBroadcastLocked(r);
if(!
replaced){
//没替换时,就加入OrderedQueue
queue.enqueueOrderedBroadcastLocked(r);
//触发发送流程
queue.scheduleBroadcastsLocked();
}
}else{
//Therewasnobodyinterestedinthebroadcast,butwestillwanttorecord
//thatithappened.
if(intent.getComponent()==null&&intent.getPackage()==null
&&(intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)==0){
//Thiswasanimplicitbroadcast...let'srecorditforposterity.
//没有处理的静态或有序广播,保存起来
//感觉保存起来也没什么用啊
addBroadcastStatLocked(intent.getAction(),callerPackage,0,0,0);
}
}
...............
简单来说,broadcastIntentLocked的第四部分工作就是为有序广播和静态广播,构造对应的BroadcastRecord(按优先级顺序),
然后将BroadcastRecord加入到OrderedQueue中,并触发广播发送流程。
至此,整个broadcastIntentLocked函数分析完毕,除去一些条件判断的细节外,整个工作流程如下图所示:
1、处理粘性广播。
由于粘性广播的特性(BroadcastReceiver注册即可接收),系统必须首先保存粘性广播。
2、处理普通动态广播。
普通广播是并发的,系统优先为动态注册的BroadcastReceiver发送广播。
动态广播对应的BroadcastRecord加入到ParallelQueue中。
3、处理静态广播和有序广播。
这一步主要是为静态注册的BroadcastReceiver发送广播,对应的BroadcastRecord加入到OrderedQueue中。
此外,需要注意的是:
如果广播是有序的,那么第2步不会为动态注册的BroadcastReceiver发送广播,而是在第3步统一发送。
发送有序广播时,AMS将按照BroadcastReceiver的优先级,依次构造BroadcastRecord加入到OrderedQueue中。
四、BroadcastQueue的scheduleBroadcastsLocked函数流程分析
从上面的代码,我们知道广播发送方调用sendBroadcast后,AMS会构造对应的BroadcastRecord加入到BroadcastQueue中,
然后调用BroadcastQueue的scheduleBroadcastsLocked函数。
现在,我们就来看一下scheduleBroadcastsLocked相关的流程。
publicvoidscheduleBroadcastsLocked(){
...........
//避免短时间内重复发送BROADCAST_INTENT_MSG
if(mBroadcastsScheduled){
return;
}
mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG,this));
mBroadcastsScheduled=true;
}
上面的代码将发送BROADCAST_INTENT_MSG,触发BroadcastQueue调用processNextBroadcast进行处理。
processNextBroadcast函数同样非常的长,大概有500多行。
。
。
。
我们还是分段进行分析。
1processNextBroadcast函数PartI
finalvoidprocessNextBroadcast(booleanfromMsg){
synchronized(mService){
BroadcastRecordr;
..............
//更新CPU的使用情况
//处理静态广播时,可能需要拉起对应进程,因此在这里先记录一下CPU情况
mService.updateCpuStats();
if(fromMsg){
//处理BROADCAST_INTENT_MSG后,将mBroadcastsScheduled置为false
//scheduleBroadcastsLocked就可以再次被调用了
mBroadcastsScheduled=false;
}
//First,deliveranynon-serializedbroadcastsrightaway.
//先处理“并发”发送的普通广播
while(mParallelBroadcasts.size()>0){
//依次取出BroadcastRecord
r=mParallelBroadcasts.remove(0);
//记录发送的时间
r.dispatchTime=SystemClock.uptimeMillis();
r.dispatchClockTime=System.currentTimeMillis();
finalintN=r.receivers.size();
................
for(inti=0;i//mParallelBroadcasts中的每个成员均为BroadcastFilter类型
Objecttarget=r.receivers.get(i);
............
//为该BroadcastRecord对应的每个Receiver发送广播
deliverToRegisteredReceiverLocked(r,(BroadcastFilter)target,false,i);
}
//将这里处理过的信息加入到历史记录中
addBroadcastToHistoryLocked(r);
}
........................
}
}
从上面的代码可以看出,processNextBroadcast函数的第一部分主要是为动态注册的BroadcastReceiver发送普通广播。
发送普通广播的函数为deliverToRegisteredReceiverLocked:
privatevoiddeliverToRegisteredReceiverLocked(BroadcastRecordr,
BroadcastFilterfilter,booleanordered,intindex){
booleanskip=false;
//检查广播发送方是否有BroadcastReceiver指定的权限
if(filter.requiredPermission!
=null){
intperm=mService.checkComponentPermission(filter.requiredPermission,
r.callingPid,r.callingUid,-1,true);
if(perm!
=PackageManager.PERMISSION_GRANTED){
............
skip=true;
}else{
//进一步检查权限的合理性
finalintopCode=AppOpsManager.permissionToOpCode(filter.requiredPermission);
if(opCode!
=AppOpsManager.OP_NONE
&&mService.mAppOpsService.noteOperation(opCode,r.callingUid,
r.callerPackage)!
=AppOpsManager.MODE_ALLOWED){
............
skip=true;
}
}
}
//检查BroadcastReceiver是否有Broadcast要求的权限
if(!
skip&&r.requiredPermissions!
=null&&r.requiredPermissions.length>0){
for(inti=0;iStringrequiredPermission=r.requiredPermissions[i];
intperm=mService.checkComponentPermission(requiredPermission,
filter.receiverList.pid,filter.receiverList.uid,-1,true);
if(perm!
=PackageManager.PERMISSION_GRANTED){
.................
//只要一条权限不满足,就结束
skip=true;
break;
}
//进一步检查权限的合理性
intappOp=AppOpsManager.permissionToOpCode(requiredPermission);
if(appOp!
=AppOpsManager.OP_NONE&&appOp!
=r.appOp
&&mService.mAppOpsService.noteOperation(appOp,
filter.receiverList.uid,filter.packageName)
!
=AppOpsManager.MODE_ALLOWED){
...........
skip=true;
break;
}
}
}
//这段代码我看的有些懵逼,发送方没要求权限,还检查啥?
if(!
skip&&(r.requiredPermissions==null||r.requiredPermissions.length==0)){
intperm=mService.checkComponentPermission(null,
filter.receiverList.pid,filter.receiverList.uid,-1,true);
if(perm!
=PackageManager.PERMISSION_GRANTED){
............
skip=true;
}
}
//还有一些其它的检查,不再分析代码了。
。
。
。
。
//包括是否允许以background的方式发送、IntentFirewall是否允许广播中的Intent发送
...............................
if(skip){
//不满足发送条件的话,标记一下,结束发送
r.delivery[index]=BroadcastRecord.DELIVERY_SKIPPED;
return;
}
//Ifpermissionsneedareviewbeforeanyoftheappcomponentscanrun,wedrop
//thebroadcastandifthecallingappisintheforegroundandthebroadcastis
//explicitwelaunchthereviewUIpassingitapendingintenttosendtheskipped
//broadcast.
//特殊情况,还需要再次检查权限,中断广播发送
//再次满足发送条件后,会重新进入到后续的发送流程
if(Build.PERMISSIONS_REVIEW_REQUIRED){
if(!
requestStartTargetPermissionsReviewIfNeededLocked(r,filter.packageName,
filter.owningUserId)){
r.delivery[index]=BroadcastRecord.DELIVERY_SKIPPED;
return;
}
}
//可以发送了,标记一下
r.delivery[index]=BroadcastRecord.DELIVERY_DELIVERED;
//Ifthisisnotbeingsentasanorderedbroadcast,thenwe
//don'twanttotouchthefieldsthatkeeptrackofthecurrent
//stateoforderedbroadcasts.
if(ordered){
//如果发送的是有序广播,则记录一些状态信息等,不涉及广播发送的过程
.............
}
try{
..............
//若BroadcastReceiver对应的进程处于fullBackup状态(备份和恢复),则不发送广播
if(filter.receiverList.app!
=null&&filter.receiverList.app.inFullBackup){
if(ordered){
//有序广播必须处理完一个,才能处理下一个,因此这里主动触发一下
skipReceiverLocked(r);
}
}else{
//执行发送工作
performReceiveLocked(.............);
}
if(ordered){
r.state=BroadcastRecord.CALL_DONE_RECEIVE;
}
}catch(RemoteExceptione){
.............
}
}
deliverToRegisteredReceiverLocked看起来很长,但大部分内容都是进行权限检查等操作,实际的发送工作交给了performReceiveLocked函数。
广播是一种可以携带数据的跨进程、跨APP通信机制,为了避免安全泄露的问题,Android才在此处使用了大量的篇幅进行权限检查的工作。
在这一部分的最后,我们跟进一下performReceiveLocked函数:
voidperformReceiveLocked(.........){
//Sendtheintenttothereceiverasynchronouslyusingone-waybindercalls.
if(app!
=null){
if(app.thread!
=null){
//Ifwehaveanappthread,dothecallthroughthatsoitis
//correctlyorderedwithotherone-waycalls.
try{
//通过Binder通信,将广播信息发往BroadcastReceiver处在的进程
app.thread.scheduleRegisteredReceiver(.......);
}catch(RemoteExceptionex){
//Failedtocallintothe