Android 70 ActivityManagerService5 广播Broadcast相关流程分析2.docx
- 文档编号:27027506
- 上传时间:2023-06-25
- 格式:DOCX
- 页数:43
- 大小:355.01KB
Android 70 ActivityManagerService5 广播Broadcast相关流程分析2.docx
《Android 70 ActivityManagerService5 广播Broadcast相关流程分析2.docx》由会员分享,可在线阅读,更多相关《Android 70 ActivityManagerService5 广播Broadcast相关流程分析2.docx(43页珍藏版)》请在冰豆网上搜索。
Android70ActivityManagerService5广播Broadcast相关流程分析2
Android7.0ActivityManagerService(5)广播(Broadcast)相关流程分析
(2)
4broadcastIntentLocked函数PartIV
.................
//Mergeintoonelist.
intir=0;
if(receivers!
=null){
//AspecialcaseforPACKAGE_ADDED:
donotallowthepackage
//beingaddedtoseethisbroadcast.Thispreventsthemfrom
//usingthisasabackdoortogetrunassoonastheyare
//installed.Maybeinthefuturewewanttohaveaspecialinstall
//broadcastorsuchforapps,butwe'dliketodeliberatelymake
//thisdecision.
//处理特殊的Action,例如PACKAGE_ADDED,系统不希望有些应用一安装就能启动
//APP安装后,PKMS将发送PACKAGE_ADDED广播
//若没有这个限制,在刚安装的APP内部静态注册监听该消息的BroadcastReceiver,新安装的APP就能直接启动
StringskipPackages[]=null;
if(Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
||Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
||Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())){
Uridata=intent.getData();
if(data!
=null){
StringpkgName=data.getSchemeSpecificPart();
if(pkgName!
=null){
skipPackages=newString[]{pkgName};
}
}
}elseif(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())){
skipPackages=intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
}
if(skipPackages!
=null&&(skipPackages.length>0)){
for(StringskipPackage:
skipPackages){
if(skipPackage!
=null){
intNT=receivers.size();
for(intit=0;it ResolveInfocurt=(ResolveInfo)receivers.get(it); if(curt.activityInfo.packageName.equals(skipPackage)){ //将skipPackages对应的BroadcastReceiver移出receivers receivers.remove(it); it--; NT--; } } } } } intNT=receivers! =null? receivers.size(): 0; intit=0; ResolveInfocurt=null; BroadcastFiltercurr=null; //NT对应的是静态BroadcastReceiver的数量 //NR对应的是动态BroadcastReceiver的数量 //若发送的是无序广播,此时NR为0 //若是有序广播,才会进入下面两个while循环 //下面两个while循环就是将静态注册的BroadcastReceiver和动态注册的BroadcastReceiver //按照优先级合并到一起(有序广播才会合并) while(it if(curt==null){ curt=(ResolveInfo)receivers.get(it); } if(curr==null){ curr=registeredReceivers.get(ir); } //动态优先级大于静态时,将动态插入到receivers中 if(curr.getPriority()>=curt.priority){ //Insertthisbroadcastrecordintothefinallist. receivers.add(it,curr); ir++; curr=null; it++; NT++; }else{ //SkiptothenextResolveInfointhefinallist. it++; curt=null; } } } while(ir 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;i StringrequiredPermission=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
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Android 70 ActivityManagerService5 广播Broadcast相关流程分析2 广播 Broadcast 相关 流程 分析
![提示](https://static.bdocx.com/images/bang_tan.gif)
链接地址:https://www.bdocx.com/doc/27027506.html