前面文章介绍了Android注册广播的过程,这篇介绍下广播的发送过程。
广播的发送过程比广播的注册过程复杂的多,主要有以下几个步骤:
1.广播的发送者将一个特定类型的广播发送给ActivityManagerService。
2.AMS接收到这个广播后,首先找到与这个广播对应的广播接收者,然后将它们添加到一个广播调度队列中,再将这个调度队列传递给BroadcastQueue,最后向BroadcastQueue的消息队列发送一个类型为BROADCAST_INTENT_MSG的消息,此时对于广播发送者来说,一个广播的发送就完成了。
3.当消息队列中的BROADCAST_INTENT_MSG消息被处理时,BroadcastQueue就会从广播调度队列中找对需要接收广播的接收者,并且将对应的广播发送给它们所运行在的应用程序进程。
4.广播接收者所运行在的应用程序进程接收到广播后,并不是直接将接收到的广播分发给各个广播接收者来处理,而是将接收到的广播封装成一个消息,并且发送到主线程的消息队列中。当这个消息被处理时,应用程序进程才会将它所描述的广播发送给相应的广播接收者处理。
惯例先看时序图,由于发送广播的过程有点复杂,所以时序图分开画的。sendBroadcast、sendOrderedBroadcast和sendStickyBroadcast方法在调用broadcastIntent方法之前的流程是一样的,这里只画出sendBroadcast方法的时序图:
说明:一个广播是使用一个Intent对象来描述的,而这个Intent对象的action名称就是用来描述它所对应的广播类型。
广播的发送也是从ContextWrapper类开始的:
@Override
publicvoidsendBroadcast(Intentintent){
mBase.sendBroadcast(intent);
}
ContextImpl类的sendBroadcast方法:
@Override
publicvoidsendBroadcast(Intentintent){
//如果调用者是系统进程的话打印log
warnIfCallingFromSystemProcess();
//Intent的MIME数据类型,没有设置则为null
StringresolvedType=intent.resolveTypeIfNeeded(getContentResolver());
try{
//准备离开应用程序进程,进入AMS进程
intent.prepareToLeaveProcess();
//调用ActivityManagerProxy类的broadcastIntent方法来实现广播的发送
//ActivityManagerProxy是一个Binder对象的远程接口,而这个Binder对象就是ActivityManagerService
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(),intent,resolvedType,null,
Activity.RESULT_OK,null,null,null,AppOpsManager.OP_NONE,null,false,false,
getUserId());
}catch(RemoteExceptione){
thrownewRuntimeException("Failurefromsystem",e);
}
}
ActivityManagerService类的broadcastIntent方法:
[java]view plaincopy
publicfinalintbroadcastIntent(IApplicationThreadcaller,
Intentintent,StringresolvedType,IIntentReceiverresultTo,
intresultCode,StringresultData,BundleresultExtras,
String[]requiredPermissions,intappOp,Bundleoptions,
booleanserialized,booleansticky,intuserId){
//执行调用者不是独立进程的判断
enforceNotIsolatedCaller("broadcastIntent");
synchronized(this){
intent=verifyBroadcastLocked(intent);
//通过ApplicationThread对象从成员变量mLruProcesses列表中查找调用者的ProcessRecord对象
finalProcessRecordcallerApp=getRecordForAppLocked(caller);
finalintcallingPid=Binder.getCallingPid();
finalintcallingUid=Binder.getCallingUid();
finallongorigId=Binder.clearCallingIdentity();
//调用broadcastIntentLocked方法处理intent所描述的广播
intres=broadcastIntentLocked(callerApp,
callerApp!=null?callerApp.info.packageName:null,
intent,resolvedType,resultTo,resultCode,resultData,resultExtras,
requiredPermissions,appOp,null,serialized,sticky,
callingPid,callingUid,userId);
Binder.restoreCallingIdentity(origId);
returnres;
}
}
再看后续时序图:
broadcastIntentLocked方法中主要是用来查找目标广播接收者的:
[java]view plaincopy
/**
*Stateofallactivestickybroadcastsperuser.Keysaretheactionofthe
*stickyIntent,valuesareanArrayListofallbroadcastedintentswith
*thataction(whichshouldusuallybeone).TheSparseArrayiskeyed
*bytheuserIDthestickyisfor,andcanincludeUserHandle.USER_ALL
*forstickiesthataresenttoallusers.
*/
finalSparseArray>>mStickyBroadcasts=
newSparseArray>>();
privatefinalintbroadcastIntentLocked(ProcessRecordcallerApp,
StringcallerPackage,Intentintent,StringresolvedType,
IIntentReceiverresultTo,intresultCode,StringresultData,
BundleresultExtras,String[]requiredPermissions,intappOp,Bundleoptions,
booleanordered,booleansticky,intcallingPid,intcallingUid,intuserId){
intent=newIntent(intent);
//Bydefaultbroadcastsdonotgotostoppedapps.
//设置这个flag后,intent将不会去匹配这个package中当前停止运行的组件。
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
//Ifwehavenotfinishedbooting,don'tallowthistolaunchnewprocesses.
//FLAG_RECEIVER_BOOT_UPGRADE标志是广播用于系统升级的,如果设置了该标记,允许系统在启动完成前发送广播
if(!mProcessesReady&&(intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE)==0){
//追加FLAG_RECEIVER_REGISTERED_ONLY标志后,只有动态注册的广播接收者能收到广播
//这是因为在系统启动过程中,PackageManagerService可能还未启动,此时AMS是无法获得静态注册的广播接收者的
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
}
if(DEBUG_BROADCAST_LIGHT)Slog.v(TAG_BROADCAST,
(sticky?"Broadcaststicky:":"Broadcast:")+intent
+"ordered="+ordered+"userid="+userId);
if((resultTo!=null)&&!ordered){
Slog.w(TAG,"Broadcast"+intent+"notorderedbutresultcallbackrequested!");
}
//处理调用者uid
userId=handleIncomingUser(callingPid,callingUid,userId,
true,ALLOW_NON_FULL,"broadcast",callerPackage);
//Makesurethattheuserwhoisreceivingthisbroadcastisrunning.
//Ifnot,wewilljustskipit.Makeanexceptionforshutdownbroadcasts
//andupgradesteps.
if(userId!=UserHandle.USER_ALL&&!isUserRunningLocked(userId,false)){
if((callingUid!=Process.SYSTEM_UID
||(intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE)==0)
&&!Intent.ACTION_SHUTDOWN.equals(intent.getAction())){
Slog.w(TAG,"Skippingbroadcastof"+intent
+":user"+userId+"isstopped");
returnActivityManager.BROADCAST_FAILED_USER_STOPPED;
}
}
BroadcastOptionsbrOptions=null;
if(options!=null){
brOptions=newBroadcastOptions(options);
if(brOptions.getTemporaryAppWhitelistDuration()>0){
//Seeifthecallerisallowedtodothis.Notewearecheckingagainst
//theactualrealcaller(notwhoeverprovidedtheoperationassaya
//PendingIntent),becausethatwhoisactuallysuppliedthearguments.
if(checkComponentPermission(
android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
Binder.getCallingPid(),Binder.getCallingUid(),-1,true)
!=PackageManager.PERMISSION_GRANTED){
Stringmsg="PermissionDenial:"+intent.getAction()
+"broadcastfrom"+callerPackage+"(pid="+callingPid
+",uid="+callingUid+")"
+"requires"
+android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST;
Slog.w(TAG,msg);
thrownewSecurityException(msg);
}
}
}
/*
*Preventnon-systemcode(definedheretobenon-persistent
*processes)fromsendingprotectedbroadcasts.
*防止非系统代码(这里定义为非持久性进程)发送受保护的广播
*/
intcallingAppId=UserHandle.getAppId(callingUid);
if(callingAppId==Process.SYSTEM_UID||callingAppId==Process.PHONE_UID
||callingAppId==Process.SHELL_UID||callingAppId==Process.BLUETOOTH_UID
||callingAppId==Process.NFC_UID||callingUid==0){
//Alwaysokay.
}elseif(callerApp==null||!callerApp.persistent){//调用者为null或者调用者不是持久性进程
try{
//非系统应用不能发送受保护的广播
if(AppGlobals.getPackageManager().isProtectedBroadcast(
intent.getAction())){
Stringmsg="PermissionDenial:notallowedtosendbroadcast"
+intent.getAction()+"frompid="
+callingPid+",uid="+callingUid;
Slog.w(TAG,msg);
thrownewSecurityException(msg);
}elseif(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(intent.getAction())){
//Specialcaseforcompatibility(兼容性):wedon'twantappstosendthis,
//buthistoricallyithasnotbeenprotectedandappsmaybeusingit
//topoke(干涉)theirownappwidget.So,insteadofmakingitprotected,
//justlimitittothecaller.
if(callerApp==null){
Stringmsg="PermissionDenial:notallowedtosendbroadcast"
+intent.getAction()+"fromunknowncaller.";
Slog.w(TAG,msg);
thrownewSecurityException(msg);
//接收目标组件不为null
}elseif(intent.getComponent()!=null){
//Theyaregoodenoughtosendtoanexplicitcomponent...verify
//itisbeingsenttothecallingapp.
if(!intent.getComponent().getPackageName().equals(
callerApp.info.packageName)){
Stringmsg="PermissionDenial:notallowedtosendbroadcast"
+intent.getAction()+"to"
+intent.getComponent().getPackageName()+"from"
+callerApp.info.packageName;
Slog.w(TAG,msg);
thrownewSecurityException(msg);
}
}else{
//发送者不为null,接收者组件为null时,设置接收者只能是发送者
//Limitbroadcasttotheirownpackage.
intent.setPackage(callerApp.info.packageName);
}
}
}catch(RemoteExceptione){
Slog.w(TAG,"Remoteexception",e);
returnActivityManager.BROADCAST_SUCCESS;
}
}
finalStringaction=intent.getAction();
if(action!=null){
//特殊的Action有不同的处理方式
switch(action){
caseIntent.ACTION_UID_REMOVED:
caseIntent.ACTION_PACKAGE_REMOVED:
caseIntent.ACTION_PACKAGE_CHANGED:
caseIntent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
caseIntent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:
//Handlespecialintents:ifthisbroadcastisfromthepackage
//manageraboutapackagebeingremoved,weneedtoremoveallof
//itsactivitiesfromthehistorystack.
if(checkComponentPermission(
android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
callingPid,callingUid,-1,true)
!=PackageManager.PERMISSION_GRANTED){
Stringmsg="PermissionDenial:"+intent.getAction()
+"broadcastfrom"+callerPackage+"(pid="+callingPid
+",uid="+callingUid+")"
+"requires"
+android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Slog.w(TAG,msg);
thrownewSecurityException(msg);
}
switch(action){
caseIntent.ACTION_UID_REMOVED:
finalBundleintentExtras=intent.getExtras();
finalintuid=intentExtras!=null
?intentExtras.getInt(Intent.EXTRA_UID):-1;
if(uid>=0){
mBatteryStatsService.removeUid(uid);
mAppOpsService.uidRemoved(uid);
}
break;
//app正在移动到SD卡中,发出的广播
caseIntent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
//Ifresourcesareunavailablejustforcestopallthosepackages
//andflushtheattributecacheaswell.
Stringlist[]=
intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
if(list!=null&&list.length>0){
for(inti=0;i forceStopPackageLocked(list[i],-1,false,true,true,
false,false,userId,"storageunmount");
}
//清空app的任务栈
mRecentTasks.cleanupLocked(UserHandle.USER_ALL);
//发送app不可用的广播
sendPackageBroadcastLocked(
IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE,list,
userId);
}
break;
//app完成移动到SD的操作,发出的广播
caseIntent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:
mRecentTasks.cleanupLocked(UserHandle.USER_ALL);
break;
caseIntent.ACTION_PACKAGE_REMOVED:
caseIntent.ACTION_PACKAGE_CHANGED:
Uridata=intent.getData();
Stringssp;
if(data!=null&&(ssp=data.getSchemeSpecificPart())!=null){
booleanremoved=Intent.ACTION_PACKAGE_REMOVED.equals(action);
booleanfullUninstall=removed&&
!intent.getBooleanExtra(Intent.EXTRA_REPLACING,false);
finalbooleankillProcess=
!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP,false);
if(killProcess){
forceStopPackageLocked(ssp,UserHandle.getAppId(
intent.getIntExtra(Intent.EXTRA_UID,-1)),
false,true,true,false,fullUninstall,userId,
removed?"pkgremoved":"pkgchanged");
}
if(removed){
sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
newString[]{ssp},userId);
if(fullUninstall){
mAppOpsService.packageRemoved(
intent.getIntExtra(Intent.EXTRA_UID,-1),ssp);
//Removeallpermissionsgrantedfrom/tothispackage
removeUriPermissionsForPackageLocked(ssp,userId,true);
removeTasksByPackageNameLocked(ssp,userId);
mBatteryStatsService.notePackageUninstalled(ssp);
}
}else{
cleanupDisabledPackageComponentsLocked(ssp,userId,killProcess,
intent.getStringArrayExtra(
Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST));
}
}
break;
}
break;
caseIntent.ACTION_PACKAGE_ADDED:
//Specialcaseforaddingapackage:bydefaultturnoncompatibilitymode.
Uridata=intent.getData();
Stringssp;
if(data!=null&&(ssp=data.getSchemeSpecificPart())!=null){
finalbooleanreplacing=
intent.getBooleanExtra(Intent.EXTRA_REPLACING,false);
mCompatModePackages.handlePackageAddedLocked(ssp,replacing);
try{
ApplicationInfoai=AppGlobals.getPackageManager().
getApplicationInfo(ssp,0,0);
mBatteryStatsService.notePackageInstalled(ssp,
ai!=null?ai.versionCode:0);
}catch(RemoteExceptione){
}
}
break;
caseIntent.ACTION_TIMEZONE_CHANGED:
//Ifthisisthetimezonechangedaction,queueupamessagethatwillreset
//thetimezoneofallcurrentlyrunningprocesses.Thismessagewillget
//queuedupbeforethebroadcasthappens.
mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
break;
caseIntent.ACTION_TIME_CHANGED:
//Iftheusersetthetime,letallrunningprocessesknow.
finalintis24Hour=
intent.getBooleanExtra(Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT,false)?1
:0;
mHandler.sendMessage(mHandler.obtainMessage(UPDATE_TIME,is24Hour,0));
BatteryStatsImplstats=mBatteryStatsService.getActiveStatistics();
synchronized(stats){
stats.noteCurrentTimeChangedLocked();
}
break;
caseIntent.ACTION_CLEAR_DNS_CACHE:
mHandler.sendEmptyMessage(CLEAR_DNS_CACHE_MSG);
break;
caseProxy.PROXY_CHANGE_ACTION:
ProxyInfoproxy=intent.getParcelableExtra(Proxy.EXTRA_PROXY_INFO);
mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY_MSG,proxy));
break;
}
}
//SmartContainermodifiedbegin
if(!SmartContainerConfig.WITH_OUT_VIRTUAL_BOX){
if(mAMSFunc.processSpecialIntent(intent,callingUid,userId)!=0)
returnActivityManager.BROADCAST_SUCCESS;
}
//SmartContainermodifiedend
//Addtothestickylistifrequested.
if(sticky){
//粘性广播要加BROADCAST_STICKY权限
if(checkPermission(android.Manifest.permission.BROADCAST_STICKY,
callingPid,callingUid)
!=PackageManager.PERMISSION_GRANTED){
Stringmsg="PermissionDenial:broadcastIntent()requestingastickybroadcastfrompid="
+callingPid+",uid="+callingUid
+"requires"+android.Manifest.permission.BROADCAST_STICKY;
Slog.w(TAG,msg);
thrownewSecurityException(msg);
}
//发送粘性广播不能有其他权限
if(requiredPermissions!=null&&requiredPermissions.length>0){
Slog.w(TAG,"Can'tbroadcaststickyintent"+intent
+"andenforcepermissions"+Arrays.toString(requiredPermissions));
returnActivityManager.BROADCAST_STICKY_CANT_HAVE_PERMISSION;
}
//粘性广播不能发给指定的接收组件
if(intent.getComponent()!=null){
thrownewSecurityException(
"Stickybroadcastscan'ttargetaspecificcomponent");
}
//WeuseuserIddirectlyhere,sincethe"all"targetismaintained
//asaseparatesetofstickybroadcasts.
if(userId!=UserHandle.USER_ALL){
//Butfirst,ifthisisnotabroadcasttoallusers,then
//makesureitdoesn'tconflictwithanexistingbroadcastto
//allusers.
//如果广播不是发给所有用户的,则确认对所有用户它不会跟当前存在的广播冲突
ArrayMap>stickies=mStickyBroadcasts.get(
UserHandle.USER_ALL);
if(stickies!=null){
//根据Action获取action相同的Intent列表
ArrayListlist=stickies.get(intent.getAction());
if(list!=null){
intN=list.size();
inti;
for(i=0;i //粘性广播发送后是会保存下来的,故如果已经存在则不需要重新发送
if(intent.filterEquals(list.get(i))){
thrownewIllegalArgumentException(
"Stickybroadcast"+intent+"foruser"
+userId+"conflictswithexistingglobalbroadcast");
}
}
}
}
}
//在mStickyBroadcasts中根据参数userId查找以Action、广播列表为键值对的stickies,
//如果不存在,则创建并添加
ArrayMap>stickies=mStickyBroadcasts.get(userId);
if(stickies==null){
stickies=newArrayMap<>();
mStickyBroadcasts.put(userId,stickies);
}
//在stickies中查找是否存在与参数intent的Action名称对应的一个粘性广播列表list,
//如果不存在,则创建并添加
ArrayListlist=stickies.get(intent.getAction());
if(list==null){
list=newArrayList<>();
stickies.put(intent.getAction(),list);
}
finalintstickiesCount=list.size();
inti;
//遍历检查在粘性广播列表list中是否存在一个与参数intent一致的广播
for(i=0;i //如果存在则用intent参数所描述的广播来替换它
if(intent.filterEquals(list.get(i))){
//Thisstickyalreadyexists,replaceit.
list.set(i,newIntent(intent));
break;
}
}
//说明list列表中不存在与intent参数一致的广播
if(i>=stickiesCount){
//则把该intent所描述的广播添加到list列表中
list.add(newIntent(intent));
}
}
int[]users;
if(userId==UserHandle.USER_ALL){
//Callerwantsbroadcasttogotoallstartedusers.
users=mStartedUserArray;
}else{
//Callerwantsbroadcasttogotoonespecificuser.
users=newint[]{userId};
}
//SmartContainerModifiedbegin
intalternativeBoxId=userId;
SetboxesToReceive=newHashSet();
boxesToReceive.add(userId);
//SmartContainerModifiedend
//Figureoutwhoallwillreceivethisbroadcast.
Listreceivers=null;//静态广播接收器列表
ListregisteredReceivers=null;//动态广播接收器列表
//Needtoresolvetheintenttointerestedreceivers...
if((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
==0){
//之前讲解注册广播时,静态注册的广播都保存在PMS中的mReceivers中了,
//现在到PMS中找到所有静态注册的目标广播接收者,并保存在列表receivers中
receivers=collectReceiverComponents(intent,resolvedType,callingUid,users);
}
//SmartContainermodifiedbegin
if(!SmartContainerConfig.WITH_OUT_VIRTUAL_BOX){
if(receivers!=null&&receivers.size()>0&&callerPackage!=null){
mAMSFunc.processReceiverComponents(boxesToReceive,receivers,callerPackage,userId);
}
}
//SmartContainermodifiedend
//没有指定接收者组件名
if(intent.getComponent()==null){
if(userId==UserHandle.USER_ALL&&callingUid==Process.SHELL_UID){
//Queryonetargetuseratatime,excludingshell-restrictedusers
UserManagerServiceums=getUserManagerLocked();
for(inti=0;i if(ums.hasUserRestriction(
UserManager.DISALLOW_DEBUGGING_FEATURES,users[i])){
continue;
}
ListregisteredReceiversForUser=
mReceiverResolver.queryIntent(intent,
resolvedType,false,users[i]);
if(registeredReceivers==null){
registeredReceivers=registeredReceiversForUser;
}elseif(registeredReceiversForUser!=null){
registeredReceivers.addAll(registeredReceiversForUser);
}
}
}else{
//之前讲解注册广播时,动态注册的广播都存放在AMS的mReceiverResolver中了,
//这里就在里面找到动态注册的目标广播接收者,并保存在registeredReceivers列表中
registeredReceivers=mReceiverResolver.queryIntent(intent,
resolvedType,false,userId);
//SmartContainermodifiedbegin
if(userId!=UserHandle.USER_ALL&&!SmartContainerConfig.WITH_OUT_VIRTUAL_BOX&&
(registeredReceivers==null||registeredReceivers.size()==0)){
alternativeBoxId=mAMSFunc.processRegisterReceivers(registeredReceivers,
boxesToReceive,intent,resolvedType,userId,alternativeBoxId,callingUid);
}
//SmartContainermodifiedend
}
}
//查看intent的flag有没有设置FLAG_RECEIVER_REPLACE_PENDING,如果设置的话,
//AMS就会在当前的系统中查看有没有相同的intent还未处理,如果有的话,就用当前这个新的intent
//来替换旧的intent。
finalbooleanreplacePending=
(intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING)!=0;
if(DEBUG_BROADCAST)Slog.v(TAG_BROADCAST,"Enqueingbroadcast:"+intent.getAction()
+"replacePending="+replacePending);
intNR=registeredReceivers!=null?registeredReceivers.size():0;
//参数ordered标记当前发送的广播是否是有序广播,如果不是,并且存在动态注册的目标广播接收者
if(!ordered&&NR>0){
//Ifwearenotserializingthisbroadcast,thensendthe
//registeredreceiversseparatelysotheydon'twaitforthe
//componentstobelaunched.
//broadcastQueueForIntent方法判断要发送的广播是前台广播还是后台广播,如果是前台广播则返回前台广播队列,
//不同队列处理超时的时间不一样:前台10秒、后台60秒
finalBroadcastQueuequeue=broadcastQueueForIntent(intent);
//SmartContainermodifiedbegin
if(SmartContainerConfig.WITH_OUT_APP_CLONE||boxesToReceive.size()==1
||userId==UserHandle.USER_ALL){
//将intent所描述的广播,以及动态注册的目标广播接收者封装成一个BroadcastRecord对象r,
//用来描述AMS要执行的一个广播转发任务
BroadcastRecordr=newBroadcastRecord(queue,intent,callerApp,
callerPackage,callingPid,callingUid,resolvedType,requiredPermissions,
appOp,brOptions,registeredReceivers,resultTo,resultCode,resultData,
resultExtras,ordered,sticky,false,alternativeBoxId);
Slog.v(TAG_BROADCAST,"Enqueueingparallelbroadcast"+r+"intent"+intent);
//replaceParallelBroadcastLocked方法根据r到queue中的无序调度队列中查找是否存在与intent描述一致的广播,存在则替换并返回true
finalbooleanreplaced=replacePending&&queue.replaceParallelBroadcastLocked(r);
//如果replaced为true,说明不需要在无序广播调度队列中增加新的广播转发任务
if(!replaced){
//否者就把r所描述的广播转发任务放在BroadcastQueue类中的mParallelBroadcasts无序调度队列中
queue.enqueueParallelBroadcastLocked(r);
//重新调度这个队列中的广播转发任务,从这里可以看出动态注册的广播接收者
//比静态注册的广播接收者优先接收到无序广播
queue.scheduleBroadcastsLocked();
}
}else{
ListbroadcastFilterList=newArrayList();
BroadcastRecordr=newBroadcastRecord(queue,intent,callerApp,
callerPackage,callingPid,callingUid,resolvedType,requiredPermissions,
appOp,brOptions,broadcastFilterList,resultTo,resultCode,resultData,
resultExtras,ordered,sticky,false,-1);
mAMSFunc.queueNOrderedRegisteredBroadcastForClone(registeredReceivers,r,boxesToReceive,intent,replacePending);
}
//SmartContainermodifiedend
//到这里,对于无序广播来说,AMS就相当于已经将参数intent描述的广播发给那些动态注册的目标广播接收者了。
//故,这里就将列表registeredReceivers设置为null,将标记动态注册的目标广播接收者个数的变量NR设置为0
registeredReceivers=null;
NR=0;
}
//执行到这里,无论AMS当前接收到的是一个无序广播还是有序广播,都会将该广播及其目标广播接收者封装成一个广播转发任务,
//并添加到一个有序广播调度队列中。但对于无序广播来说,当它们被真正转发时,并不会按照有序广播来转发。
//Mergeintoonelist.
intir=0;
if(receivers!=null){
//AspecialcaseforPACKAGE_ADDED:donotallowthepackage
//beingaddedtoseethisbroadcast.Thispreventsthemfrom
//usingthisasabackdoortogetrunassoonastheyare
//installed.Maybeinthefuturewewanttohaveaspecialinstall
//broadcastorsuchforapps,butwe'dliketodeliberatelymake
//thisdecision.
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){
//特殊广播查看ssp有没有指定包名,有则赋值给skipPackages
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);
//如果静态注册的广播接收者应用的包名和skipPackage一致,则从receivers移除
if(curt.activityInfo.packageName.equals(skipPackage)){
receivers.remove(it);
it--;
NT--;
}
}
}
}
}
intNT=receivers!=null?receivers.size():0;
intit=0;
ResolveInfocurt=null;
BroadcastFiltercurr=null;
//这里动态注册广播合并的是有序的,因为无序动态广播处理中NR最后被赋值为0了
while(it if(curt==null){
//静态注册的广播是ResolveInfo类型
curt=(ResolveInfo)receivers.get(it);
}
if(curr==null){
//动态注册的广播是BroadcastFilter类型,后面会根据类型判断广播是动态注册还是静态注册的
curr=registeredReceivers.get(ir);
}
//如果动态注册广播接收者优先级高于等于静态广播接收者,则把动态注册的广播接收者插入到当前位置,
//静态注册的广播接收者后移,这说明同优先级动态注册的先于静态注册的接收到广播
if(curr.getPriority()>=curt.priority){
//Insertthisbroadcastrecordintothefinallist.
receivers.add(it,curr);
ir++;
curr=null;
it++;
NT++;
}else{
//SkiptothenextResolveInfointhefinallist.
it++;
curt=null;
}
}
}
//把优先级低于所有静态注册广播接收者的动态广播接收者都追加到receivers列表中的末尾
while(ir if(receivers==null){
receivers=newArrayList();
}
receivers.add(registeredReceivers.get(ir));
ir++;
}
//到这里,对于无序广播来说,静态注册的目标广播接收者就全部保存在列表receivers中了;
//而对于有序广播来说,静态注册和动态注册的目标广播接收者也全部保存在列表receivers中了。
if((receivers!=null&&receivers.size()>0)
||resultTo!=null){
//SmartContainerModifiedbegin
if(SmartContainerConfig.WITH_OUT_VIRTUAL_BOX||userId==UserHandle.USER_ALL
||receivers==null||receivers.size()==0){
BroadcastQueuequeue=broadcastQueueForIntent(intent);
//将intent所描述的广播,以及剩余的其他目标广播接收者封装成另外一个BroadcastRecord对象r,
//用来描述AMS要执行的另一个广播转发任务,并且添加到有序广播调度队列中。
BroadcastRecordr=newBroadcastRecord(queue,intent,callerApp,
callerPackage,callingPid,callingUid,resolvedType,
requiredPermissions,appOp,brOptions,receivers,resultTo,resultCode,
resultData,resultExtras,ordered,sticky,false,userId);
Slog.v(TAG_BROADCAST,"Enqueueingorderedbroadcast"+r
+":prevhad"+queue.mOrderedBroadcasts.size());
Slog.i(TAG_BROADCAST,
"Enqueueingbroadcast"+r.intent.getAction());
//replaceOrderedBroadcastLocked方法根据r到queue中的有序调度队列中查找是否存在与intent描述一致的广播,存在则替换并返回true
booleanreplaced=replacePending&&queue.replaceOrderedBroadcastLocked(r);
//如果replaced为true,说明不需要在有序广播调度队列中增加新的广播转发任务
if(!replaced){
//否者把r所描述的广播转发任务放在BroadcastQueue类中的mOrderedBroadcasts有序广播调度队列中
queue.enqueueOrderedBroadcastLocked(r);
//重新调度这个队列中的广播转发任务
queue.scheduleBroadcastsLocked();
}
}else{
ListreceiverList=newArrayList();
BroadcastQueuequeue=broadcastQueueForIntent(intent);
BroadcastRecordr=newBroadcastRecord(queue,intent,callerApp,
callerPackage,callingPid,callingUid,resolvedType,
requiredPermissions,appOp,brOptions,receiverList,resultTo,resultCode,
resultData,resultExtras,ordered,sticky,false,-1);
mAMSFunc.queueFinalBroadcastForClone(receivers,r,boxesToReceive,intent,userId,replacePending);
}
//SmartContainerModifiedend
}
returnActivityManager.BROADCAST_SUCCESS;
}
至此,AMS就找到参数intent所描述广播的目标广播接收者了,并且分别将它们保存在了BroadcastRecord类的无序广播调度队列mParallelBroadcasts(包括动态注册的无序广播接收者)中和有序广播调度队列mOrderedBroadcasts(包括动态注册的有序广播接收者和所有静态注册的广播接收者)中。
接下来,AMS就会调用BroadcastQueue类中的scheduleBroadcastsLocked方法将intent所描述的广播转发给目标广播接收者处理:
[java]view plaincopy
publicvoidscheduleBroadcastsLocked(){
if(DEBUG_BROADCAST)Slog.v(TAG_BROADCAST,"Schedulebroadcasts["
+mQueueName+"]:current="
+mBroadcastsScheduled);
if(mBroadcastsScheduled){
return;
}
mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG,this));
mBroadcastsScheduled=true;
}
上面mBroadcastsScheduled参数是用来标记是否已经向消息队列发送了一个类型为BROADCAST_INTENT_MSG消息。BroadcastQueue就是通过这个消息来调度保存在无序广播调度队列和有序广播调度队列中的广播转发任务的。
这里,虽然还没有将广播转发给各目标广播接收者,但是当它执行完成这一步之后,广播发送者就会认为这个广播已经发送成功了。从这里就可以看出,广播的发送和接收是异步的。
mHandler是BroadcastQueue类的内部类BroadcastHandler的实例,在BroadcastQueue类的构造方法中赋初值。
下面看下它的handleMessage方法:
[java]view plaincopy
finalBroadcastHandlermHandler;
privatefinalclassBroadcastHandlerextendsHandler{
publicBroadcastHandler(Looperlooper){
super(looper,null,true);
}
@Override
publicvoidhandleMessage(Messagemsg){
switch(msg.what){
caseBROADCAST_INTENT_MSG:{
if(DEBUG_BROADCAST)Slog.v(
TAG_BROADCAST,"ReceivedBROADCAST_INTENT_MSG");
//处理广播的转发任务
processNextBroadcast(true);
}break;
caseBROADCAST_TIMEOUT_MSG:{
synchronized(mService){
//处理广播超时的操作,报ANR异常
broadcastTimeoutLocked(true);
}
}break;
caseSCHEDULE_TEMP_WHITELIST_MSG:{
DeviceIdleController.LocalServicedic=mService.mLocalDeviceIdleController;
if(dic!=null){
dic.addPowerSaveTempWhitelistAppDirect(UserHandle.getAppId(msg.arg1),
msg.arg2,true,(String)msg.obj);
}
}break;
}
}
};
processNextBroadcast方法主要是用来将广播转发给各目标广播接收者处理:
[java]view plaincopy
finalvoidprocessNextBroadcast(booleanfromMsg){
/*可以在这里获取允许自启动的名单*/
synchronized(mService){
BroadcastRecordr;
if(DEBUG_BROADCAST)Slog.v(TAG_BROADCAST,"processNextBroadcast["
+mQueueName+"]:"
+mParallelBroadcasts.size()+"broadcasts,"
+mOrderedBroadcasts.size()+"orderedbroadcasts");
mService.updateCpuStats();
//fromMsg字段标记是否是从handleMessage中调用的该方法
if(fromMsg){
//设置该参数为false,表示前面发送到消息队列中的BROADCAST_INTENT_MSG消息已经被处理了
mBroadcastsScheduled=false;
}
//First,deliveranynon-serializedbroadcastsrightaway.
//循环处理保存在无序广播调度队列mParallelBroadcasts中的广播转发任务,
//即:将保存在无序广播调度队列中的广播发送给它的目标广播接收者(动态无序)处理
while(mParallelBroadcasts.size()>0){
//得到mParallelBroadcasts中保存的第一个广播转发任务r
r=mParallelBroadcasts.remove(0);
r.dispatchTime=SystemClock.uptimeMillis();
r.dispatchClockTime=System.currentTimeMillis();
finalintN=r.receivers.size();
if(DEBUG_BROADCAST_LIGHT)Slog.v(TAG_BROADCAST,"Processingparallelbroadcast["
+mQueueName+"]"+r);
for(inti=0;i Objecttarget=r.receivers.get(i);
if(DEBUG_BROADCAST)Slog.v(TAG_BROADCAST,
"Deliveringnon-orderedon["+mQueueName+"]toregistered"
+target+":"+r);
//遍历循环将无序广播发送给每一个目标广播接收者(动态注册的)
deliverToRegisteredReceiverLocked(r,(BroadcastFilter)target,false);
}
//添加r到历史队列中
addBroadcastToHistoryLocked(r);
if(DEBUG_BROADCAST_LIGHT)Slog.v(TAG_BROADCAST,"Donewithparallelbroadcast["
+mQueueName+"]"+r);
}
//Nowtakecareofthenextserializedone...
//接下来,继续处理保存在有序广播调度队列mOrderedBroadcasts中的广播转发任务。
//前面讲到有序广播调度队列mOrderedBroadcasts中描述的广播的目标接收者有可能是静态注册的,
//而这些静态注册的目标广播接收者可能还没有被启动起来,因此,将一个广播发送给它们处理时,先要
//将它们启动起来。事实上,只需要将它们所运行在的应用程序进程启动起来就可以了,因为当这些应用程序
//进程接收到广播时,就会主动将目标广播接收者启动起来。
//Ifwearewaitingforaprocesstocomeuptohandlethenext
//broadcast,thendonothingatthispoint.Justincase,we
//checkthattheprocesswe'rewaitingforstillexists.
//该参数是用来描述一个正在等待静态注册的目标广播接收者启动起来的广播转发任务的
if(mPendingBroadcast!=null){
if(DEBUG_BROADCAST_LIGHT)Slog.v(TAG_BROADCAST,
"processNextBroadcast["+mQueueName+"]:waitingfor"
+mPendingBroadcast.curApp);
booleanisDead;
//检查这个静态注册的目标广播接收者所运行在的应用程序进程是否已经启动起来
synchronized(mService.mPidsSelfLocked){
ProcessRecordproc=mService.mPidsSelfLocked.get(mPendingBroadcast.curApp.pid);
isDead=proc==null||proc.crashing;
}
//如果这个应用程序进程没有死亡,就会继续等待
if(!isDead){
//It'sstillalive,sokeepwaiting
return;
}else{
Slog.w(TAG,"pendingapp["
+mQueueName+"]"+mPendingBroadcast.curApp
+"diedbeforerespondingtobroadcast");
mPendingBroadcast.state=BroadcastRecord.IDLE;
mPendingBroadcast.nextReceiver=mPendingBroadcastRecvIndex;
mPendingBroadcast=null;
}
}
booleanlooped=false;
//循环在有序广播调度队列mOrderedBroadcasts(动态有序、所有静态)中找到下一个需要处理的广播转发任务
do{
//判断有序广播调度队列中的广播转发任务是否已经处理完了
if(mOrderedBroadcasts.size()==0){
//Nomorebroadcastspending,soalldone!
mService.scheduleAppGcsLocked();
if(looped){
//Ifwehadfinishedthelastorderedbroadcast,then
//makesureallprocesseshavecorrectoomandsched
//adjustments.
mService.updateOomAdjLocked();
}
return;
}
//取出第一个广播转发任务r
r=mOrderedBroadcasts.get(0);
/*这里可以统计广播转发任务r中是否包含操作widget的Action:ACTION_APPWIDGET_ENABLED和
*ACTION_APPWIDGET_DISABLED的包名r.targetComp.getPackageName()和
*类名r.targetComp.getClassName()以便于后面增加控制自启动的过滤操作*/
booleanforceReceive=false;
//Ensurethatevenifsomethinggoesawry(出现差错)withthetimeout
//detection(超时检测),wecatch"hung"broadcastshere,discard(丢弃)them,
//andcontinuetomakeprogress.
//
//ThisisonlydoneifthesystemisreadysothatPRE_BOOT_COMPLETED
//receiversdon'tgetexecutedwithtimeouts.They'reintendedfor
//onetimeheavyliftingaftersystemupgradesandcantake
//significantamountsoftime.
//获取到r所描述的广播转发任务的目标广播接收者的个数
intnumReceivers=(r.receivers!=null)?r.receivers.size():0;
//检查前一个目标广播接收者是否在规定时间内处理完广播
if(mService.mProcessesReady&&r.dispatchTime>0){
longnow=SystemClock.uptimeMillis();
if((numReceivers>0)&&
(now>r.dispatchTime+(2*mTimeoutPeriod*numReceivers))){
Slog.w(TAG,"Hungbroadcast["
+mQueueName+"]discardedaftertimeoutfailure:"
+"now="+now
+"dispatchTime="+r.dispatchTime
+"startTime="+r.receiverTime
+"intent="+r.intent
+"numReceivers="+numReceivers
+"nextReceiver="+r.nextReceiver
+"state="+r.state);
//如果目标广播接收者不能按时处理完广播,就强制结束这个广播转发任务
broadcastTimeoutLocked(false);//forcibly(强制)finishthisbroadcast
//下面两个参数的设置表示要继续处理有序广播调度队列中的下一个广播转发任务
forceReceive=true;
r.state=BroadcastRecord.IDLE;
}
}
//检查r所描述的广播转发任务是否正在处理中,即:正在将一个有序广播转发给它的前一个目标广播接收者处理
if(r.state!=BroadcastRecord.IDLE){
if(DEBUG_BROADCAST)Slog.d(TAG_BROADCAST,
"processNextBroadcast("
+mQueueName+")calledwhennotidle(state="
+r.state+")");
//如果正在将r所描述的广播转发给它的前一个目标接收者处理,则需要等待这个目标广播接收者处理完
//该有序广播,然后再转发给下一个目标接收者处理。故这里直接返回
return;
}
//检查r所描述的广播转发任务是否已经处理完成或者已经被强制结束了
if(r.receivers==null||r.nextReceiver>=numReceivers
||r.resultAbort||forceReceive){
//Nomorereceiversforthisbroadcast!Sendthefinal
//resultifrequested...
if(r.resultTo!=null){
try{
if(DEBUG_BROADCAST)Slog.i(TAG_BROADCAST,
"Finishingbroadcast["+mQueueName+"]"
+r.intent.getAction()+"app="+r.callerApp);
//执行广播的发送操作
performReceiveLocked(r.callerApp,r.resultTo,
newIntent(r.intent),r.resultCode,
r.resultData,r.resultExtras,false,false,r.userId);
//Setthistonullsothatthereference
//(localandremote)isn'tkeptinthemBroadcastHistory.
r.resultTo=null;
}catch(RemoteExceptione){
r.resultTo=null;
Slog.w(TAG,"Failure["
+mQueueName+"]sendingbroadcastresultof"
+r.intent,e);
}
}
if(DEBUG_BROADCAST)Slog.v(TAG_BROADCAST,"CancellingBROADCAST_TIMEOUT_MSG");
//remove掉前面给mHandler发送的BROADCAST_TIMEOUT_MSG消息,
//表示r所描述的广播转发任务已经在规定时间内处理完了
cancelBroadcastTimeoutLocked();
if(DEBUG_BROADCAST_LIGHT)Slog.v(TAG_BROADCAST,
"Finishedwithorderedbroadcast"+r);
//...andontothenext...
addBroadcastToHistoryLocked(r);
//将r所描述的广播转发任务从有序广播队列中删除
mOrderedBroadcasts.remove(0);
//这里将r设为null以便继续执行while循环来找到下一个需要处理的广播转发任务
r=null;
looped=true;
continue;
}
}while(r==null);
//上面循环执行完后,下一个需要处理的广播转发任务就保存在r中了
//r所描述的广播转发任务的目标广播接收者保存在它的成员变量receivers列表中,
//而下一个目标广播接收者就保存在它的成员变量nextReceiver中,这里得到的是
//r所描述的广播转发任务的下一个目标广播接收者在其目标广播接收者列表中的位置
//Getthenextreceiver...
intrecIdx=r.nextReceiver++;
//Keeptrackofwhenthisreceiverstarted,andmakesurethere
//isatimeoutmessagependingtokillitifneedbe.
r.receiverTime=SystemClock.uptimeMillis();
//如果recIdx为0说明广播转发任务刚开始被处理
if(recIdx==0){
//广播刚被处理,保存当前时间到r.dispatchTime变量中
r.dispatchTime=r.receiverTime;
r.dispatchClockTime=System.currentTimeMillis();
if(DEBUG_BROADCAST_LIGHT)Slog.v(TAG_BROADCAST,"Processingorderedbroadcast["
+mQueueName+"]"+r);
}
//检查是否已经向消息队列发送了BROADCAST_TIMEOUT_MSG消息
if(!mPendingBroadcastTimeoutMessage){
longtimeoutTime=r.receiverTime+mTimeoutPeriod;
if(DEBUG_BROADCAST)Slog.v(TAG_BROADCAST,
"SubmittingBROADCAST_TIMEOUT_MSG["
+mQueueName+"]for"+r+"at"+timeoutTime);
//如果还没有发送,则向消息队列发送该消息,并且指定它在timeoutTime时间后处理
setBroadcastTimeoutLocked(timeoutTime);
}
finalBroadcastOptionsbrOptions=r.options;
//取出r所描述的广播转发任务的下一个目标广播接收者
finalObjectnextReceiver=r.receivers.get(recIdx);
//前面说过动态注册广播接收者是BroadcastFilter类型的,这里处理动态有序广播接收者
if(nextReceiverinstanceofBroadcastFilter){
//Simplecase:thisisaregisteredreceiverwhogets
//adirectcall.
BroadcastFilterfilter=(BroadcastFilter)nextReceiver;
if(DEBUG_BROADCAST)Slog.v(TAG_BROADCAST,
"Deliveringordered["
+mQueueName+"]toregistered"
+filter+":"+r);
//这里直接向动态注册的广播接收者发送广播,因为动态注册的广播接收者肯定是已经启动起来的
deliverToRegisteredReceiverLocked(r,filter,r.ordered);
//判断r所描述的广播转发任务是否是用来转发无序广播的
if(r.receiver==null||!r.ordered){
//Thereceiverhasalreadyfinished,soscheduleto
//processthenextone.
if(DEBUG_BROADCAST)Slog.v(TAG_BROADCAST,"Quickfinishing["
+mQueueName+"]:ordered="
+r.ordered+"receiver="+r.receiver);
//如果是则将r.state设置为IDLE,表示不需要等待它的前一个目标广播接收者处理完成一个广播,
//就可以将该广播继续发送给它的下一个目标广播接收者处理
r.state=BroadcastRecord.IDLE;
//为了将广播继续发送给r所描述的广播转发任务的下一个目标广播接收者处理,
//方法中实现发送BROADCAST_INTENT_MSG消息给消息队列以便继续处理
scheduleBroadcastsLocked();
}else{
if(brOptions!=null&&brOptions.getTemporaryAppWhitelistDuration()>0){
scheduleTempWhitelistLocked(filter.owningUid,
brOptions.getTemporaryAppWhitelistDuration(),r);
}
}
return;
}
//如果r所描述的广播转发任务的下一个目标广播接收者不是BroadcastFilter类型的,那就说明这
//是一个静态注册的广播接收者,这种情况略复杂,因为静态注册的广播接收者可能还没有被启动起来
//Hardcase:needtoinstantiatethereceiver,possibly
//startingitsapplicationprocesstohostit.
//前面说过,静态注册的广播接收者是ResolveInfo类型的,这里直接强转
ResolveInfoinfo=
(ResolveInfo)nextReceiver;
ComponentNamecomponent=newComponentName(
info.activityInfo.applicationInfo.packageName,
info.activityInfo.name);
//下面主要是根据是否得到权限来决定是否跳过本次广播的发送
booleanskip=false;
//根据目标广播接收者所需要的权限检查发送者的Pid和Uid是否符合要求
intperm=mService.checkComponentPermission(info.activityInfo.permission,
r.callingPid,r.callingUid,info.activityInfo.applicationInfo.uid,
info.activityInfo.exported);
//如果发送者不符合要求,则直接跳过本次转发
if(perm!=PackageManager.PERMISSION_GRANTED){
if(!info.activityInfo.exported){
Slog.w(TAG,"PermissionDenial:broadcasting"
+r.intent.toString()
+"from"+r.callerPackage+"(pid="+r.callingPid
+",uid="+r.callingUid+")"
+"isnotexportedfromuid"+info.activityInfo.applicationInfo.uid
+"duetoreceiver"+component.flattenToShortString());
}else{
Slog.w(TAG,"PermissionDenial:broadcasting"
+r.intent.toString()
+"from"+r.callerPackage+"(pid="+r.callingPid
+",uid="+r.callingUid+")"
+"requires"+info.activityInfo.permission
+"duetoreceiver"+component.flattenToShortString());
}
skip=true;
//如果发送者符合要求,就检查发送者申请的权限是否被用户拒绝,拒绝的话也直接跳过本次转发
}elseif(info.activityInfo.permission!=null){
finalintopCode=AppOpsManager.permissionToOpCode(info.activityInfo.permission);
if(opCode!=AppOpsManager.OP_NONE
&&mService.mAppOpsService.noteOperation(opCode,r.callingUid,
r.callerPackage)!=AppOpsManager.MODE_ALLOWED){
Slog.w(TAG,"AppopDenial:broadcasting"
+r.intent.toString()
+"from"+r.callerPackage+"(pid="
+r.callingPid+",uid="+r.callingUid+")"
+"requiresappop"+AppOpsManager.permissionToOp(
info.activityInfo.permission)
+"duetoregisteredreceiver"
+component.flattenToShortString());
skip=true;
}
}
/*可以添加关联唤醒的判断逻辑:如根据目标广播接收者的包名/类名前缀判断是否属于第三方push平台,如果是则设置skip为true*/
//检查接收者权限
if(!skip&&info.activityInfo.applicationInfo.uid!=Process.SYSTEM_UID&&
r.requiredPermissions!=null&&r.requiredPermissions.length>0){
//循环根据发送者所需的权限检查所有的目标广播接收者的Pid和Uid是否符合要求,一项不符合就直接跳过
//符合要求,就检查接收者申请的权限是否被用户拒绝,拒绝的话也直接跳过
for(inti=0;i StringrequiredPermission=r.requiredPermissions[i];
try{
perm=AppGlobals.getPackageManager().
checkPermission(requiredPermission,
info.activityInfo.applicationInfo.packageName,
UserHandle
.getUserId(info.activityInfo.applicationInfo.uid));
}catch(RemoteExceptione){
perm=PackageManager.PERMISSION_DENIED;
}
if(perm!=PackageManager.PERMISSION_GRANTED){
Slog.w(TAG,"PermissionDenial:receiving"
+r.intent+"to"
+component.flattenToShortString()
+"requires"+requiredPermission
+"duetosender"+r.callerPackage
+"(uid"+r.callingUid+")");
skip=true;
break;
}
intappOp=AppOpsManager.permissionToOpCode(requiredPermission);
if(appOp!=AppOpsManager.OP_NONE&&appOp!=r.appOp
&&mService.mAppOpsService.noteOperation(appOp,
info.activityInfo.applicationInfo.uid,info.activityInfo.packageName)
!=AppOpsManager.MODE_ALLOWED){
Slog.w(TAG,"AppopDenial:receiving"
+r.intent+"to"
+component.flattenToShortString()
+"requiresappop"+AppOpsManager.permissionToOp(
requiredPermission)
+"duetosender"+r.callerPackage
+"(uid"+r.callingUid+")");
skip=true;
break;
}
}
}
if(!skip&&r.appOp!=AppOpsManager.OP_NONE
&&mService.mAppOpsService.noteOperation(r.appOp,
info.activityInfo.applicationInfo.uid,info.activityInfo.packageName)
!=AppOpsManager.MODE_ALLOWED){
Slog.w(TAG,"AppopDenial:receiving"
+r.intent+"to"
+component.flattenToShortString()
+"requiresappop"+AppOpsManager.opToName(r.appOp)
+"duetosender"+r.callerPackage
+"(uid"+r.callingUid+")");
skip=true;
}
if(!skip){
skip=!mService.mIntentFirewall.checkBroadcast(r.intent,r.callingUid,
r.callingPid,r.resolvedType,info.activityInfo.applicationInfo.uid);
}
booleanisSingleton=false;
try{
isSingleton=mService.isSingleton(info.activityInfo.processName,
info.activityInfo.applicationInfo,
info.activityInfo.name,info.activityInfo.flags);
}catch(SecurityExceptione){
Slog.w(TAG,e.getMessage());
skip=true;
}
if((info.activityInfo.flags&ActivityInfo.FLAG_SINGLE_USER)!=0){
if(ActivityManager.checkUidPermission(
android.Manifest.permission.INTERACT_ACROSS_USERS,
info.activityInfo.applicationInfo.uid)
!=PackageManager.PERMISSION_GRANTED){
Slog.w(TAG,"PermissionDenial:Receiver"+component.flattenToShortString()
+"requestsFLAG_SINGLE_USER,butappdoesnothold"
+android.Manifest.permission.INTERACT_ACROSS_USERS);
skip=true;
}
}
if(r.curApp!=null&&r.curApp.crashing){
//Ifthetargetprocessiscrashing,justskipit.
Slog.w(TAG,"Skippingdeliverordered["+mQueueName+"]"+r
+"to"+r.curApp+":processcrashing");
skip=true;
}
if(!skip){
booleanisAvailable=false;
try{
isAvailable=AppGlobals.getPackageManager().isPackageAvailable(
info.activityInfo.packageName,
UserHandle.getUserId(info.activityInfo.applicationInfo.uid));
}catch(Exceptione){
//allsuchfailuresmeanweskipthisreceiver
Slog.w(TAG,"Exceptiongettingrecipientinfofor"
+info.activityInfo.packageName,e);
}
if(!isAvailable){
if(DEBUG_BROADCAST)Slog.v(TAG_BROADCAST,
"Skippingdeliveryto"+info.activityInfo.packageName+"/"
+info.activityInfo.applicationInfo.uid
+":packagenolongeravailable");
skip=true;
}
}
if(skip){
if(DEBUG_BROADCAST)Slog.v(TAG_BROADCAST,
"Skippingdeliveryofordered["+mQueueName+"]"
+r+"forwhateverreason");
r.receiver=null;
r.curFilter=null;
r.state=BroadcastRecord.IDLE;
//如果跳过,直接继续发送给r所描述的广播转发任务的下一个目标广播接收者处理
scheduleBroadcastsLocked();
return;
}
r.state=BroadcastRecord.APP_RECEIVE;
//得到静态注册的广播接收者的android:process属性值,即它需要运行在的应用程序进程的名字
StringtargetProcess=info.activityInfo.processName;
r.curComponent=component;
finalintreceiverUid=info.activityInfo.applicationInfo.uid;
//Ifit'sasingleton,itneedstobethesameapporaspecialapp
if(r.callingUid!=Process.SYSTEM_UID&&isSingleton
&&mService.isValidSingletonCall(r.callingUid,receiverUid)){
info.activityInfo=mService.getActivityInfoForUser(info.activityInfo,0);
}
r.curReceiver=info.activityInfo;
if(DEBUG_MU&&r.callingUid>UserHandle.PER_USER_RANGE){
Slog.v(TAG_MU,"Updatedbroadcastrecordactivityinfoforsecondaryuser,"
+info.activityInfo+",callingUid="+r.callingUid+",uid="
+info.activityInfo.applicationInfo.uid);
}
if(brOptions!=null&&brOptions.getTemporaryAppWhitelistDuration()>0){
scheduleTempWhitelistLocked(receiverUid,
brOptions.getTemporaryAppWhitelistDuration(),r);
}
//Broadcastisbeingexecuted,itspackagecan'tbestopped.
try{
AppGlobals.getPackageManager().setPackageStoppedState(
r.curComponent.getPackageName(),false,UserHandle.getUserId(r.callingUid));
}catch(RemoteExceptione){
}catch(IllegalArgumentExceptione){
Slog.w(TAG,"Failedtryingtounstoppackage"
+r.curComponent.getPackageName()+":"+e);
}
//Isthisreceiver'sapplicationalreadyrunning?
ProcessRecordapp=mService.getProcessRecordLocked(targetProcess,
info.activityInfo.applicationInfo.uid,false);
//判断静态注册的广播接收者所运行在的应用程序进程是否已经启动起来
if(app!=null&&app.thread!=null){
try{
app.addPackage(info.activityInfo.packageName,
info.activityInfo.applicationInfo.versionCode,mService.mProcessStats);
//如果已经启动,则直接将广播发送给它处理
processCurBroadcastLocked(r,app);
return;
}catch(RemoteExceptione){
Slog.w(TAG,"Exceptionwhensendingbroadcastto"
+r.curComponent,e);
}catch(RuntimeExceptione){
Slog.wtf(TAG,"Failedsendingbroadcastto"
+r.curComponent+"with"+r.intent,e);
//Ifsomeunexpectedexceptionhappened,justskip
//thisbroadcast.Atthispointwearenotinthecall
//fromaclient,sothrowinganexceptionoutfromhere
//willcrashtheentiresysteminsteadofjustwhoever
//sentthebroadcast.
logBroadcastReceiverDiscardLocked(r);
finishReceiverLocked(r,r.resultCode,r.resultData,
r.resultExtras,r.resultAbort,false);
scheduleBroadcastsLocked();
//Weneedtoresetthestateifwefailedtostartthereceiver.
r.state=BroadcastRecord.IDLE;
return;
}
//Ifadeadobjectexceptionwasthrown--fallthroughto
//restarttheapplication.
}
//Notrunning--getitstarted,tobeexecutedwhentheappcomesup.
if(DEBUG_BROADCAST)Slog.v(TAG_BROADCAST,
"Needtostartapp["
+mQueueName+"]"+targetProcess+"forbroadcast"+r);
/*因为下面要开始启动进程了,故这里可以增加禁止自启动判断:如果要启动进程的包名在黑名单中或者不是默认允许启动的,则直接执行启动失败的逻辑*/
//调用startProcessLocked方法启动这个应用程序进程
if((r.curApp=mService.startProcessLocked(targetProcess,
info.activityInfo.applicationInfo,true,
r.intent.getFlags()|Intent.FLAG_FROM_BACKGROUND,
"broadcast",r.curComponent,
(r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE)!=0,false,false))
==null){
//Ah,thisrecipientisunavailable.Finishitifnecessary,
//andmarkthebroadcastrecordasreadyforthenext.
Slog.w(TAG,"Unabletolaunchapp"
+info.activityInfo.applicationInfo.packageName+"/"
+info.activityInfo.applicationInfo.uid+"forbroadcast"
+r.intent+":processisbad");
logBroadcastReceiverDiscardLocked(r);
finishReceiverLocked(r,r.resultCode,r.resultData,
r.resultExtras,r.resultAbort,false);
//如果进程启动失败,继续发送给r所描述的广播转发任务的下一个目标广播接收者处理
scheduleBroadcastsLocked();
r.state=BroadcastRecord.IDLE;
return;
}
//如果成功启动进程,则保存r和recIdx,表示正在等待r所描述的广播转发任务的
//下一个目标广播接收者所在的应用程序进程启动起来
mPendingBroadcast=r;
mPendingBroadcastRecvIndex=recIdx;
}
}
假设r所描述的广播转发任务的下一个目标广播接收者是一个动态注册的广播接收者,那么执行完上面步骤后,接下来就会调用BroadcastQueue类的deliverToRegisteredReceiverLocked方法将一个广播转发给它处理:
[java]view plaincopy
privatevoiddeliverToRegisteredReceiverLocked(BroadcastRecordr,
BroadcastFilterfilter,booleanordered){
booleanskip=false;
//BroadcastQueue将一个广播转发给一个目标广播接收者之前,需要检查这个广播的发送者和接收者的权限。
//目标广播接收者所需权限不为null
if(filter.requiredPermission!=null){
//根据目标广播接收者所需的权限检验广播的发送者的Pid和Uid是否符合要求
intperm=mService.checkComponentPermission(filter.requiredPermission,
r.callingPid,r.callingUid,-1,true);
//如果发送者不符合要求,则直接跳过本次转发
if(perm!=PackageManager.PERMISSION_GRANTED){
Slog.w(TAG,"PermissionDenial:broadcasting"
+r.intent.toString()
+"from"+r.callerPackage+"(pid="
+r.callingPid+",uid="+r.callingUid+")"
+"requires"+filter.requiredPermission
+"duetoregisteredreceiver"+filter);
skip=true;
//如果发送者符合要求,就检查发送者申请的权限是否被用户拒绝,拒绝的话也直接跳过本次转发
}else{
finalintopCode=AppOpsManager.permissionToOpCode(filter.requiredPermission);
if(opCode!=AppOpsManager.OP_NONE
&&mService.mAppOpsService.noteOperation(opCode,r.callingUid,
r.callerPackage)!=AppOpsManager.MODE_ALLOWED){
Slog.w(TAG,"AppopDenial:broadcasting"
+r.intent.toString()
+"from"+r.callerPackage+"(pid="
+r.callingPid+",uid="+r.callingUid+")"
+"requiresappop"+AppOpsManager.permissionToOp(
filter.requiredPermission)
+"duetoregisteredreceiver"+filter);
skip=true;
}
}
}
//发送者所需权限不为null
if(!skip&&r.requiredPermissions!=null&&r.requiredPermissions.length>0){
//循环根据发送者所需的权限检验所有的目标广播接收者的Pid和Uid是否符合要求,一项不符合就直接跳过
//符合要求,就检查接收者申请的权限是否被用户拒绝,拒绝的话也直接跳过本次转发
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){
Slog.w(TAG,"PermissionDenial:receiving"
+r.intent.toString()
+"to"+filter.receiverList.app
+"(pid="+filter.receiverList.pid
+",uid="+filter.receiverList.uid+")"
+"requires"+requiredPermission
+"duetosender"+r.callerPackage
+"(uid"+r.callingUid+")");
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){
Slog.w(TAG,"AppopDenial:receiving"
+r.intent.toString()
+"to"+filter.receiverList.app
+"(pid="+filter.receiverList.pid
+",uid="+filter.receiverList.uid+")"
+"requiresappop"+AppOpsManager.permissionToOp(
requiredPermission)
+"duetosender"+r.callerPackage
+"(uid"+r.callingUid+")");
skip=true;
break;
}
}
}
//如果发送者不需要权限,则检查目标广播接收者的Pid和Uid是否符合要求
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){
Slog.w(TAG,"PermissionDenial:securitycheckfailedwhenreceiving"
+r.intent.toString()
+"to"+filter.receiverList.app
+"(pid="+filter.receiverList.pid
+",uid="+filter.receiverList.uid+")"
+"duetosender"+r.callerPackage
+"(uid"+r.callingUid+")");
skip=true;
}
}
if(!skip&&r.appOp!=AppOpsManager.OP_NONE
&&mService.mAppOpsService.noteOperation(r.appOp,
filter.receiverList.uid,filter.packageName)
!=AppOpsManager.MODE_ALLOWED){
Slog.w(TAG,"AppopDenial:receiving"
+r.intent.toString()
+"to"+filter.receiverList.app
+"(pid="+filter.receiverList.pid
+",uid="+filter.receiverList.uid+")"
+"requiresappop"+AppOpsManager.opToName(r.appOp)
+"duetosender"+r.callerPackage
+"(uid"+r.callingUid+")");
skip=true;
}
if(!mService.mIntentFirewall.checkBroadcast(r.intent,r.callingUid,
r.callingPid,r.resolvedType,filter.receiverList.uid)){
return;
}
if(filter.receiverList.app==null||filter.receiverList.app.crashing){
Slog.w(TAG,"Skippingdeliver["+mQueueName+"]"+r
+"to"+filter.receiverList+":processcrashing");
skip=true;
}
if(!skip){
//Ifthisisnotbeingsentasanorderedbroadcast,thenwe
//don'twanttotouchthefieldsthatkeeptrackofthecurrent
//stateoforderedbroadcasts.
if(ordered){
r.receiver=filter.receiverList.receiver.asBinder();
r.curFilter=filter;
filter.receiverList.curBroadcast=r;
r.state=BroadcastRecord.CALL_IN_RECEIVE;
if(filter.receiverList.app!=null){
//Bumphostingapplicationtonolongerbeinbackground
//schedulingclass.Notethatwecan'tdothatifthere
//isn'tanapp...butwecanonlybeinthatcasefor
//thingsthatdirectlycalltheIActivityManagerAPI,which
//arealreadycoresystemstuffsodon'tmatterforthis.
r.curApp=filter.receiverList.app;
filter.receiverList.app.curReceiver=r;
mService.updateOomAdjLocked(r.curApp);
}
}
try{
if(DEBUG_BROADCAST_LIGHT)Slog.i(TAG_BROADCAST,
"Deliveringto"+filter+":"+r);
//将r所描述的广播转发给filter所描述的目标广播接收者处理
performReceiveLocked(filter.receiverList.app,filter.receiverList.receiver,
newIntent(r.intent),r.resultCode,r.resultData,
r.resultExtras,r.ordered,r.initialSticky,r.userId);
if(ordered){
r.state=BroadcastRecord.CALL_DONE_RECEIVE;
}
}catch(RemoteExceptione){
Slog.w(TAG,"Failuresendingbroadcast"+r.intent,e);
if(ordered){
r.
来源: