編輯:關於Android編程
前面文章介紹了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.receiver=null;
r.curFilter=null;
filter.receiverList.curBroadcast=null;
if(filter.receiverList.app!=null){
filter.receiverList.app.curReceiver=null;
}
}
}
}
}
privatestaticvoidperformReceiveLocked(ProcessRecordapp,IIntentReceiverreceiver,
Intentintent,intresultCode,Stringdata,Bundleextras,
booleanordered,booleansticky,intsendingUser)throwsRemoteException{
//Sendtheintenttothereceiverasynchronouslyusingone-waybindercalls.
//如果目標廣播接收者需要通過它所運行在的應用程序進程來間接接收廣播
if(app!=null){
if(app.thread!=null){
//Ifwehaveanappthread,dothecallthroughthatsoitis
//correctlyorderedwithotherone-waycalls.
//調用運行在該應用程序進程中的一個ApplicationThread對象的Binder代理對象的
//scheduleRegisteredReceiver方法來向它發送這個廣播
app.thread.scheduleRegisteredReceiver(receiver,intent,resultCode,
data,extras,ordered,sticky,sendingUser,app.repProcState);
}else{
//Applicationhasdied.Receiverdoesn'texist.
thrownewRemoteException("app.threadmustnotbenull");
}
}else{
//否者直接調用與它關聯的一個IIntentReceiver對象的Binder代理對象的performReceive方法
//來向它發送這個廣播
receiver.performReceive(intent,resultCode,data,extras,ordered,
sticky,sendingUser);
}
}
上面performReceiveLocked方法中的參數app指向一個ProcessRecord對象,用來描述目標廣播接收者所運行在的應用程序進程;參數receiver指向了一個實現了IIntentReceiver接口的Binder代理對象,用來描述目標廣播接收者;參數intent用來描述即將要發送給目標廣播接收者的一個廣播。
下面看ActivityThread的內部類ApplicationThread的scheduleRegisteredReceiver方法:
[java]view plaincopy
//Thisfunctionexiststomakesureallreceiverdispatchingis
//correctlyordered,sincetheseareone-waycallsandthebinderdriver
//appliestransactionorderingperobjectforsuchcalls.
publicvoidscheduleRegisteredReceiver(IIntentReceiverreceiver,Intentintent,
intresultCode,StringdataStr,Bundleextras,booleanordered,
booleansticky,intsendingUser,intprocessState)throwsRemoteException{
updateProcessState(processState,false);
receiver.performReceive(intent,resultCode,dataStr,extras,ordered,
sticky,sendingUser);
}
參數receiver指向了一個IIntentReceiver對象,前面講過每一個IIntentReceiver對象在內部都封裝了一個廣播接收者,並且代替它所封裝的廣播接收者注冊到AMS中。這樣當AMS將一個廣播發送給一個目標廣播接收者時,實際上是將這個廣播發送給了與目標廣播接收者相關聯的一個IIntentReceiver對象,而這個IIntentReceiver對象是通過它的performReceive方法來接收這個廣播的。
來看LoadedApk類中的內部類ReceiverDispatcher中的performReceive方法:
[java]view plaincopy
staticfinalclassReceiverDispatcher{
finalstaticclassInnerReceiverextendsIIntentReceiver.Stub{
finalWeakReferencemDispatcher;
finalLoadedApk.ReceiverDispatchermStrongRef;
InnerReceiver(LoadedApk.ReceiverDispatcherrd,booleanstrong){
mDispatcher=newWeakReference(rd);
mStrongRef=strong?rd:null;
}
publicvoidperformReceive(Intentintent,intresultCode,Stringdata,
Bundleextras,booleanordered,booleansticky,intsendingUser){
LoadedApk.ReceiverDispatcherrd=mDispatcher.get();
if(ActivityThread.DEBUG_BROADCAST){
intseq=intent.getIntExtra("seq",-1);
Slog.i(ActivityThread.TAG,"Receivingbroadcast"+intent.getAction()+"seq="+seq
+"to"+(rd!=null?rd.mReceiver:null));
}
if(rd!=null){
//調用ReceiverDispatcher的performReceive方法來接收intent所描述的廣播
rd.performReceive(intent,resultCode,data,extras,
ordered,sticky,sendingUser);
}else{
//Theactivitymanagerdispatchedabroadcasttoaregistered
//receiverinthisprocess,butbeforeitcouldbedeliveredthe
//receiverwasunregistered.Acknowledgethebroadcastonits
//behalfsothatthesystem'sbroadcastsequencecancontinue.
if(ActivityThread.DEBUG_BROADCAST)Slog.i(ActivityThread.TAG,
"Finishingbroadcasttounregisteredreceiver");
IActivityManagermgr=ActivityManagerNative.getDefault();
try{
if(extras!=null){
extras.setAllowFds(false);
}
mgr.finishReceiver(this,resultCode,data,extras,false,intent.getFlags());
}catch(RemoteExceptione){
Slog.w(ActivityThread.TAG,"Couldn'tfinishbroadcasttounregisteredreceiver");
}
}
}
}
finalIIntentReceiver.StubmIIntentReceiver;
//目標廣播接收者
finalBroadcastReceivermReceiver;
finalContextmContext;
finalHandlermActivityThread;
finalInstrumentationmInstrumentation;
//目標廣播接收者是否已經注冊到AMS中
finalbooleanmRegistered;
finalIntentReceiverLeakedmLocation;
RuntimeExceptionmUnregisterLocation;
booleanmForgotten;
finalclassArgsextendsBroadcastReceiver.PendingResultimplementsRunnable{
privateIntentmCurIntent;
privatefinalbooleanmOrdered;
publicArgs(Intentintent,intresultCode,StringresultData,BundleresultExtras,
booleanordered,booleansticky,intsendingUser){
super(resultCode,resultData,resultExtras,
mRegistered?TYPE_REGISTERED:TYPE_UNREGISTERED,ordered,
sticky,mIIntentReceiver.asBinder(),sendingUser,intent.getFlags());
//要接收的廣播
mCurIntent=intent;
//描述該廣播是否是有序廣播
mOrdered=ordered;
}
publicvoidrun(){
//目標廣播接收者
finalBroadcastReceiverreceiver=mReceiver;
finalbooleanordered=mOrdered;
if(ActivityThread.DEBUG_BROADCAST){
intseq=mCurIntent.getIntExtra("seq",-1);
Slog.i(ActivityThread.TAG,"Dispatchingbroadcast"+mCurIntent.getAction()
+"seq="+seq+"to"+mReceiver);
Slog.i(ActivityThread.TAG,"mRegistered="+mRegistered
+"mOrderedHint="+ordered);
}
finalIActivityManagermgr=ActivityManagerNative.getDefault();
finalIntentintent=mCurIntent;
mCurIntent=null;
if(receiver==null||mForgotten){
if(mRegistered&&ordered){
if(ActivityThread.DEBUG_BROADCAST)Slog.i(ActivityThread.TAG,
"Finishingnullbroadcastto"+mReceiver);
sendFinished(mgr);
}
return;
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,"broadcastReceiveReg");
try{
ClassLoadercl=mReceiver.getClass().getClassLoader();
intent.setExtrasClassLoader(cl);
setExtrasClassLoader(cl);
receiver.setPendingResult(this);
//回調目標廣播接收者的onReceive方法來接收這個廣播
receiver.onReceive(mContext,intent);
}catch(Exceptione){
if(mRegistered&&ordered){
if(ActivityThread.DEBUG_BROADCAST)Slog.i(ActivityThread.TAG,
"Finishingfailedbroadcastto"+mReceiver);
sendFinished(mgr);
}
if(mInstrumentation==null||
!mInstrumentation.onException(mReceiver,e)){
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
thrownewRuntimeException(
"Errorreceivingbroadcast"+intent
+"in"+mReceiver,e);
}
}
if(receiver.getPendingResult()!=null){
finish();
}
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}
ReceiverDispatcher(BroadcastReceiverreceiver,Contextcontext,
HandleractivityThread,Instrumentationinstrumentation,
booleanregistered){
if(activityThread==null){
thrownewNullPointerException("Handlermustnotbenull");
}
mIIntentReceiver=newInnerReceiver(this,!registered);
mReceiver=receiver;
mContext=context;
mActivityThread=activityThread;
mInstrumentation=instrumentation;
mRegistered=registered;
mLocation=newIntentReceiverLeaked(null);
mLocation.fillInStackTrace();
}
...
RuntimeExceptiongetUnregisterLocation(){
returnmUnregisterLocation;
}
publicvoidperformReceive(Intentintent,intresultCode,Stringdata,
Bundleextras,booleanordered,booleansticky,intsendingUser){
if(ActivityThread.DEBUG_BROADCAST){
intseq=intent.getIntExtra("seq",-1);
Slog.i(ActivityThread.TAG,"Enqueueingbroadcast"+intent.getAction()+"seq="+seq
+"to"+mReceiver);
}
//將參數intent所描述的廣播封裝成一個Args對象
Argsargs=newArgs(intent,resultCode,data,extras,ordered,
sticky,sendingUser);
//將Args對象封裝成一個消息發送到目標廣播接收者所運行在的應用程序進程的消息隊列中,
//這個消息最終在Args類的run方法中處理
if(!mActivityThread.post(args)){
if(mRegistered&&ordered){
IActivityManagermgr=ActivityManagerNative.getDefault();
if(ActivityThread.DEBUG_BROADCAST)Slog.i(ActivityThread.TAG,
"Finishingsyncbroadcastto"+mReceiver);
//由於這裡已經把廣播發給接收者處理了,故現在通知AMS繼續給下一個目標廣播接收者發送廣播了
args.sendFinished(mgr);
}
}
}
}
說到這裡,我們分析了動態注冊的廣播接收者處理有序廣播和無序廣播的過程,下面說下靜態廣播的處理過程,看BroadcastQueue類中的processCurBroadcastLocked方法:
[java]view plaincopy
privatefinalvoidprocessCurBroadcastLocked(BroadcastRecordr,
ProcessRecordapp)throwsRemoteException{
if(DEBUG_BROADCAST)Slog.v(TAG_BROADCAST,
"Processcurbroadcast"+r+"forapp"+app);
//如果目標廣播接收者所運行在的應用程序進程沒有啟動起來,則拋異常
if(app.thread==null){
thrownewRemoteException();
}
r.receiver=app.thread.asBinder();
r.curApp=app;
app.curReceiver=r;
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
mService.updateLruProcessLocked(app,false,null);
mService.updateOomAdjLocked();
//Telltheapplicationtolaunchthisreceiver.
r.intent.setComponent(r.curComponent);
booleanstarted=false;
try{
if(DEBUG_BROADCAST_LIGHT)Slog.v(TAG_BROADCAST,
"Deliveringtocomponent"+r.curComponent
+":"+r);
mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
//調用運行在該應用程序進程中的一個ApplicationThread對象的Binder代理對象的
//scheduleReceiver方法來向它發送這個廣播
app.thread.scheduleReceiver(newIntent(r.intent),r.curReceiver,
mService.compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
r.resultCode,r.resultData,r.resultExtras,r.ordered,r.userId,
app.repProcState);
if(DEBUG_BROADCAST)Slog.v(TAG_BROADCAST,
"Processcurbroadcast"+r+"DELIVEREDforapp"+app);
started=true;
}finally{
if(!started){
if(DEBUG_BROADCAST)Slog.v(TAG_BROADCAST,
"Processcurbroadcast"+r+":NOTSTARTED!");
r.receiver=null;
r.curApp=null;
app.curReceiver=null;
}
}
}
下面看ActivityThread的內部類ApplicationThread的scheduleReceiver方法:
[java]view plaincopy
publicfinalvoidscheduleReceiver(Intentintent,ActivityInfoinfo,
CompatibilityInfocompatInfo,intresultCode,Stringdata,Bundleextras,
booleansync,intsendingUser,intprocessState){
updateProcessState(processState,false);
//將參數封裝成一個ReceiverData對象,通過sendMessage方法向應用程序主線程消息隊列中發送一個RECEIVER消息
ReceiverDatar=newReceiverData(intent,resultCode,data,extras,
sync,false,mAppThread.asBinder(),sendingUser);
r.info=info;
r.compatInfo=compatInfo;
sendMessage(H.RECEIVER,r);
}
privateclassHextendsHandler{
...
publicstaticfinalintRECEIVER=113;
publicvoidhandleMessage(Messagemsg){
switch(msg.what){
...
caseRECEIVER:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,"broadcastReceiveComp");
handleReceiver((ReceiverData)msg.obj);
maybeSnapshot();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
}
}
}
privatevoidhandleReceiver(ReceiverDatadata){
//Ifwearegettingreadytogcaftergoingtothebackground,well
//wearebackactivesoskipit.
unscheduleGcIdler();
//目標廣播接收者類名
Stringcomponent=data.intent.getComponent().getClassName();
LoadedApkpackageInfo=getPackageInfoNoCheck(
data.info.applicationInfo,data.compatInfo);
IActivityManagermgr=ActivityManagerNative.getDefault();
BroadcastReceiverreceiver;
try{
java.lang.ClassLoadercl=packageInfo.getClassLoader();
data.intent.setExtrasClassLoader(cl);
data.intent.prepareToEnterProcess();
data.setExtrasClassLoader(cl);
//根據目標廣播接收者類名實例化一個接收對象
receiver=(BroadcastReceiver)cl.loadClass(component).newInstance();
}catch(Exceptione){
if(DEBUG_BROADCAST)Slog.i(TAG,
"Finishingfailedbroadcastto"+data.intent.getComponent());
data.sendFinished(mgr);
thrownewRuntimeException(
"Unabletoinstantiatereceiver"+component
+":"+e.toString(),e);
}
try{
Applicationapp=packageInfo.makeApplication(false,mInstrumentation);
if(localLOGV)Slog.v(
TAG,"Performingreceiveof"+data.intent
+":app="+app
+",appName="+app.getPackageName()
+",pkg="+packageInfo.getPackageName()
+",comp="+data.intent.getComponent().toShortString()
+",dir="+packageInfo.getAppDir());
ContextImplcontext=(ContextImpl)app.getBaseContext();
sCurrentBroadcastIntent.set(data.intent);
receiver.setPendingResult(data);
//回調目標廣播接收者的onReceive方法來接收這個廣播
receiver.onReceive(context.getReceiverRestrictedContext(),
data.intent);
}catch(Exceptione){
if(DEBUG_BROADCAST)Slog.i(TAG,
"Finishingfailedbroadcastto"+data.intent.getComponent());
data.sendFinished(mgr);
if(!mInstrumentation.onException(receiver,e)){
thrownewRuntimeException(
"Unabletostartreceiver"+component
+":"+e.toString(),e);
}
}finally{
sCurrentBroadcastIntent.set(null);
}
if(receiver.getPendingResult()!=null){
//處理完本次接收後通知AMS繼續給下一個目標廣播接收者發送廣播
data.finish();
}
}
到這裡,廣播的發送流程就終於分析完了。
內容有理解錯誤或偏差之處請包涵指正,謝謝!
字體管家是最好的字體下載工具,提供字體下載、字體備份、字體預覽、字體修復功能,永久免費的好軟件,為您提供最好用的字體下載字體備份字體安裝軟件。我們來看看如何
(1)布局文件 (2)在values中新建xml文件 fill_pare
上一篇說到了通知欄Notification,提起通知欄,不得讓人想到Service以及BroadcastReceive,作為android的4大組建的2個重要成員,我們沒
MainActivity.javapackage com.heima52.pullrefresh;import java.util.ArrayList;import co