Android Broadcast广播机制分析
基于Android 6.0的源碼剖析, 分析android廣播的發(fā)送與接收流程。
一、概述
廣播(Broadcast)機(jī)制用于進(jìn)程/線(xiàn)程間通信,廣播分為廣播發(fā)送和廣播接收兩個(gè)過(guò)程,其中廣播接收者BroadcastReceiver便是Android四大組件之一。
BroadcastReceiver分為兩類(lèi):
- 靜態(tài)廣播接收者:通過(guò)AndroidManifest.xml的標(biāo)簽來(lái)申明的BroadcastReceiver。
- 動(dòng)態(tài)廣播接收者:通過(guò)AMS.registerReceiver()方式注冊(cè)的BroadcastReceiver,動(dòng)態(tài)注冊(cè)更為靈活,可在不需要時(shí)通過(guò)unregisterReceiver()取消注冊(cè)。
從廣播發(fā)送方式可分為三類(lèi):
- 普通廣播:通過(guò)Context.sendBroadcast()發(fā)送,可并行處理
- 有序廣播:通過(guò)Context.sendOrderedBroadcast()發(fā)送,串行處理
- Sticky廣播:通過(guò)Context.sendOrderedBroadcast()發(fā)送
二、注冊(cè)廣播
2.1 registerReceiver
廣播注冊(cè),對(duì)于應(yīng)用開(kāi)發(fā)來(lái)說(shuō),往往是在Activity/Service中調(diào)用registerReceiver()方法,而Activity/Service都間接繼承于Context抽象類(lèi),真正干活是交給ContextImpl類(lèi)。另外調(diào)用getOuterContext()可獲取最外層的調(diào)用者Activity/Service。
[ContextImpl.java]
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {return registerReceiver(receiver, filter, null, null); } public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,String broadcastPermission, Handler scheduler) {//【見(jiàn)小節(jié)2.2】return registerReceiverInternal(receiver, getUserId(),filter, broadcastPermission, scheduler, getOuterContext()); }當(dāng)執(zhí)行兩參數(shù)的registerReceiver方法,增加兩個(gè)broadcastPermission=null和scheduler=null調(diào)用四參數(shù)的注冊(cè)方法。其中broadcastPermission擁有廣播的權(quán)限控制,scheduler用于指定接收到廣播時(shí)onRecive執(zhí)行線(xiàn)程,當(dāng)scheduler=null則默認(rèn)代表在主線(xiàn)程中執(zhí)行,這也是最常見(jiàn)的用法。 再然后調(diào)用6參數(shù)的registerReceiverInternal。
2.2 registerReceiverInternal
[ContextImpl.java]
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,IntentFilter filter, String broadcastPermission,Handler scheduler, Context context) {IIntentReceiver rd = null;if (receiver != null) {if (mPackageInfo != null && context != null) {if (scheduler == null) {//將主線(xiàn)程Handler賦予scheulerscheduler = mMainThread.getHandler();}//獲取IIntentReceiver對(duì)象【2.3】rd = mPackageInfo.getReceiverDispatcher(receiver, context, scheduler,mMainThread.getInstrumentation(), true);} else {if (scheduler == null) {scheduler = mMainThread.getHandler();}rd = new LoadedApk.ReceiverDispatcher(receiver, context, scheduler, null, true).getIIntentReceiver();}}try {//調(diào)用AMP.registerReceiver 【2.4】return ActivityManagerNative.getDefault().registerReceiver(mMainThread.getApplicationThread(), mBasePackageName,rd, filter, broadcastPermission, userId);} catch (RemoteException e) {return null;} }ActivityManagerNative.getDefault()返回的是ActivityManagerProxy對(duì)象,簡(jiǎn)稱(chēng)AMP,該方法中參數(shù)有mMainThread.getApplicationThread()返回的是ApplicationThread,這是Binder的Bn端,用于system_server進(jìn)程與該進(jìn)程的通信。
2.3 LoadedApk.getReceiverDispatcher
[-> LoadedApk.java]
public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,Context context, Handler handler,Instrumentation instrumentation, boolean registered) {synchronized (mReceivers) {LoadedApk.ReceiverDispatcher rd = null;ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;//此處registered=true,則進(jìn)入該分支if (registered) {map = mReceivers.get(context);if (map != null) {rd = map.get(r);}}if (rd == null) {//當(dāng)廣播分發(fā)者為空,則創(chuàng)建ReceiverDispatcher【2.3.1】rd = new ReceiverDispatcher(r, context, handler,instrumentation, registered);if (registered) {if (map == null) {map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();mReceivers.put(context, map);}map.put(r, rd);}} else {//驗(yàn)證廣播分發(fā)者的context、handler是否一致rd.validate(context, handler);}rd.mForgotten = false;//獲取IIntentReceiver對(duì)象return rd.getIIntentReceiver();} }不妨令 以BroadcastReceiver(廣播接收者)為key,LoadedApk.ReceiverDispatcher(分發(fā)者)為value的ArrayMap 記為A。此處mReceivers是一個(gè)以Context為key,以A為value的ArrayMap。對(duì)于ReceiverDispatcher(廣播分發(fā)者),當(dāng)不存在時(shí)則創(chuàng)建一個(gè)。
2.3.1 創(chuàng)建ReceiverDispatcher
ReceiverDispatcher(BroadcastReceiver receiver, Context context,Handler activityThread, Instrumentation instrumentation,boolean registered) {//創(chuàng)建InnerReceiver【2.3.2】mIIntentReceiver = new InnerReceiver(this, !registered);mReceiver = receiver;mContext = context;mActivityThread = activityThread;mInstrumentation = instrumentation;mRegistered = registered;mLocation = new IntentReceiverLeaked(null);mLocation.fillInStackTrace(); }2.3.2 創(chuàng)建InnerReceiver
final static class InnerReceiver extends IIntentReceiver.Stub {final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;final LoadedApk.ReceiverDispatcher mStrongRef;InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);mStrongRef = strong ? rd : null;}... }ReceiverDispatcher(廣播分發(fā)者)有一個(gè)內(nèi)部類(lèi)InnerReceiver,該類(lèi)繼承于IIntentReceiver.Stub。顯然,這是一個(gè)Binder服務(wù)端,廣播分發(fā)者通過(guò)rd.getIIntentReceiver()可獲取該Binder服務(wù)端對(duì)象InnerReceiver,用于Binder IPC通信。
2.4 AMP.registerReceiver
[-> ActivityManagerNative.java]
public Intent registerReceiver(IApplicationThread caller, String packageName,IIntentReceiver receiver,IntentFilter filter, String perm, int userId) throws RemoteException {Parcel data = Parcel.obtain();Parcel reply = Parcel.obtain();data.writeInterfaceToken(IActivityManager.descriptor);data.writeStrongBinder(caller != null ? caller.asBinder() : null);data.writeString(packageName);data.writeStrongBinder(receiver != null ? receiver.asBinder() : null);filter.writeToParcel(data, 0);data.writeString(perm);data.writeInt(userId);//Command為REGISTER_RECEIVER_TRANSACTIONmRemote.transact(REGISTER_RECEIVER_TRANSACTION, data, reply, 0);reply.readException();Intent intent = null;int haveIntent = reply.readInt();if (haveIntent != 0) {intent = Intent.CREATOR.createFromParcel(reply);}reply.recycle();data.recycle();return intent; }這里有兩個(gè)Binder服務(wù)端對(duì)象caller和receiver,AMP通過(guò)Binder驅(qū)動(dòng)將這些信息發(fā)送給system_server進(jìn)程中的AMS對(duì)象,接下來(lái)進(jìn)入AMS.registerReceiver。
2.5 AMS.registerReceiver
[-> ActivityManagerService.java]
public Intent registerReceiver(IApplicationThread caller, String callerPackage,IIntentReceiver receiver, IntentFilter filter, String permission, int userId) {//孤立進(jìn)程不允許注冊(cè)廣播接收者enforceNotIsolatedCaller("registerReceiver");ArrayList<Intent> stickyIntents = null;ProcessRecord callerApp = null;int callingUid;int callingPid;synchronized(this) {if (caller != null) {//從mLruProcesses隊(duì)列中查找調(diào)用者的ProcessRecord 【見(jiàn)2.5.1】callerApp = getRecordForAppLocked(caller);//查詢(xún)不到目標(biāo)進(jìn)程,則拋出異常if (callerApp == null) {throw new SecurityException("");}//非系統(tǒng)進(jìn)程且包名不等于“android”,同時(shí)調(diào)用者進(jìn)程不包括該包名時(shí)拋異常if (callerApp.info.uid != Process.SYSTEM_UID &&!callerApp.pkgList.containsKey(callerPackage) &&!"android".equals(callerPackage)) {throw new SecurityException("");}callingUid = callerApp.info.uid;callingPid = callerApp.pid;} else {callerPackage = null;callingUid = Binder.getCallingUid();callingPid = Binder.getCallingPid();}userId = handleIncomingUser(callingPid, callingUid, userId,true, ALLOW_FULL_ONLY, "registerReceiver", callerPackage);//獲取IntentFilter中的actionsIterator<String> actions = filter.actionsIterator();if (actions == null) {ArrayList<String> noAction = new ArrayList<String>(1);noAction.add(null);actions = noAction.iterator();}int[] userIds = { UserHandle.USER_ALL, UserHandle.getUserId(callingUid) };while (actions.hasNext()) {String action = actions.next();for (int id : userIds) {//從mStickyBroadcasts中查看用戶(hù)的sticky IntentArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(id);if (stickies != null) {ArrayList<Intent> intents = stickies.get(action);if (intents != null) {if (stickyIntents == null) {stickyIntents = new ArrayList<Intent>();}//將sticky Intent加入到隊(duì)列stickyIntents.addAll(intents);}}}}}ArrayList<Intent> allSticky = null;if (stickyIntents != null) {final ContentResolver resolver = mContext.getContentResolver();for (int i = 0, N = stickyIntents.size(); i < N; i++) {Intent intent = stickyIntents.get(i);//查詢(xún)匹配的sticky廣播 【見(jiàn)2.5.2】if (filter.match(resolver, intent, true, TAG) >= 0) {if (allSticky == null) {allSticky = new ArrayList<Intent>();}//匹配成功,則將給intent添加到allSticky隊(duì)列allSticky.add(intent);}}}//當(dāng)IIntentReceiver為空,則直接返回第一個(gè)sticky Intent,Intent sticky = allSticky != null ? allSticky.get(0) : null;if (receiver == null) {return sticky;}synchronized (this) {if (callerApp != null && (callerApp.thread == null|| callerApp.thread.asBinder() != caller.asBinder())) {//調(diào)用者已經(jīng)死亡return null;}ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());if (rl == null) {//對(duì)于沒(méi)有注冊(cè)的廣播,則創(chuàng)建接收者隊(duì)列rl = new ReceiverList(this, callerApp, callingPid, callingUid,userId, receiver);if (rl.app != null) {rl.app.receivers.add(rl);} else {try {//注冊(cè)死亡通知receiver.asBinder().linkToDeath(rl, 0);} catch (RemoteException e) {return sticky;}rl.linkedToDeath = true;}//新創(chuàng)建的接收者隊(duì)列,添加到已注冊(cè)廣播隊(duì)列。mRegisteredReceivers.put(receiver.asBinder(), rl);}...//創(chuàng)建BroadcastFilter對(duì)象,并添加到接收者隊(duì)列BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,permission, callingUid, userId);rl.add(bf);//新創(chuàng)建的廣播過(guò)濾者,添加到ReceiverResolver隊(duì)列mReceiverResolver.addFilter(bf);//所有匹配該filter的sticky廣播執(zhí)行入隊(duì)操作//如果沒(méi)有使用sendStickyBroadcast,則allSticky=null。if (allSticky != null) {ArrayList receivers = new ArrayList();receivers.add(bf);final int stickyCount = allSticky.size();for (int i = 0; i < stickyCount; i++) {Intent intent = allSticky.get(i);//當(dāng)intent為前臺(tái)廣播,則返回mFgBroadcastQueue//當(dāng)intent為后臺(tái)廣播,則返回mBgBroadcastQueueBroadcastQueue queue = broadcastQueueForIntent(intent);//創(chuàng)建BroadcastRecordBroadcastRecord r = new BroadcastRecord(queue, intent, null,null, -1, -1, null, null, AppOpsManager.OP_NONE, null, receivers,null, 0, null, null, false, true, true, -1);//該廣播加入到并行廣播隊(duì)列queue.enqueueParallelBroadcastLocked(r);//調(diào)度廣播,發(fā)送BROADCAST_INTENT_MSG消息,觸發(fā)處理下一個(gè)廣播。queue.scheduleBroadcastsLocked();}}return sticky;} }其中mRegisteredReceivers記錄著所有已注冊(cè)的廣播,以receiver IBinder為key, ReceiverList為value為HashMap。另外,這個(gè)過(guò)程涉及對(duì)象ReceiverList,BroadcastFilter,BroadcastRecord的創(chuàng)建。
在BroadcastQueue中有兩個(gè)廣播隊(duì)列mParallelBroadcasts,mOrderedBroadcasts,數(shù)據(jù)類(lèi)型都為ArrayList:
- mParallelBroadcasts:并行廣播隊(duì)列,可以立刻執(zhí)行,而無(wú)需等待另一個(gè)廣播運(yùn)行完成,該隊(duì)列只允許動(dòng)態(tài)已注冊(cè)的廣播,從而避免發(fā)生同時(shí)拉起大量進(jìn)程來(lái)執(zhí)行廣播,前臺(tái)的和后臺(tái)的廣播分別位于獨(dú)立的隊(duì)列。
- mOrderedBroadcasts:有序廣播隊(duì)列,同一時(shí)間只允許執(zhí)行一個(gè)廣播,該隊(duì)列頂部的廣播便是活動(dòng)廣播,其他廣播必須等待該廣播結(jié)束才能運(yùn)行,也是獨(dú)立區(qū)別前臺(tái)的和后臺(tái)的廣播。
2.5.1 AMS.getRecordForAppLocked
final ProcessRecord getRecordForAppLocked(IApplicationThread thread) {if (thread == null) {return null;}//從mLruProcesses隊(duì)列中查看int appIndex = getLRURecordIndexForAppLocked(thread);return appIndex >= 0 ? mLruProcesses.get(appIndex) : null; }mLruProcesses數(shù)據(jù)類(lèi)型為ArrayList<ProcessRecord>,而ProcessRecord對(duì)象有一個(gè)IApplicationThread字段,根據(jù)該字段查找出滿(mǎn)足條件的ProcessRecord對(duì)象。
2.5.2 IntentFilter.match
public final int match(ContentResolver resolver, Intent intent,boolean resolve, String logTag) {String type = resolve ? intent.resolveType(resolver) : intent.getType();return match(intent.getAction(), type, intent.getScheme(),intent.getData(), intent.getCategories(), logTag); }public final int match(String action, String type, String scheme,Uri data, Set<String> categories, String logTag) {//不存在匹配的actionif (action != null && !matchAction(action)) {return NO_MATCH_ACTION; }//不存在匹配的type或dataint dataMatch = matchData(type, scheme, data);if (dataMatch < 0) {return dataMatch; }//不存在匹配的categoryString categoryMismatch = matchCategories(categories);if (categoryMismatch != null) {return NO_MATCH_CATEGORY;}return dataMatch; }該方法用于匹配發(fā)起的Intent數(shù)據(jù)是否匹配成功,匹配項(xiàng)共有4項(xiàng)action, type, data, category,任何一項(xiàng)匹配不成功都會(huì)失敗。
小結(jié)
注冊(cè)廣播的過(guò)程,主要功能:
- 創(chuàng)建ReceiverList(接收者隊(duì)列),并添加到AMS.mRegisteredReceivers(已注冊(cè)廣播隊(duì)列);
- 創(chuàng)建BroadcastFilter(廣播過(guò)濾者),并添加到AMS.mReceiverResolver(接收者的解析人);
- 當(dāng)注冊(cè)的是Sticky廣播,則創(chuàng)建BroadcastRecord,并添加到BroadcastQueue的mParallelBroadcasts(并行廣播隊(duì)列),注冊(cè)后調(diào)用AMS來(lái)盡快處理該廣播。
三、 發(fā)送廣播
發(fā)送廣播,同樣往往是在Activity/Service中調(diào)用registerReceiver()方法,而Activity/Service都間接繼承于Context抽象類(lèi),真正干活是交給ContextImpl類(lèi)。
3.1 sendBroadcast
[ContextImpl.java]
public void sendBroadcast(Intent intent) {warnIfCallingFromSystemProcess();String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());try {intent.prepareToLeaveProcess();// 調(diào)用AMP.broadcastIntent 【見(jiàn)3.2】ActivityManagerNative.getDefault().broadcastIntent(mMainThread.getApplicationThread(), intent, resolvedType, null,Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,getUserId());} catch (RemoteException e) {throw new RuntimeException("Failure from system", e);} }3.2 AMP.broadcastIntent
[-> ActivityManagerNative.java]
public int broadcastIntent(IApplicationThread caller,Intent intent, String resolvedType, IIntentReceiver resultTo,int resultCode, String resultData, Bundle map,String[] requiredPermissions, int appOp, Bundle options, boolean serialized,boolean sticky, int userId) throws RemoteException {Parcel data = Parcel.obtain();Parcel reply = Parcel.obtain();data.writeInterfaceToken(IActivityManager.descriptor);data.writeStrongBinder(caller != null ? caller.asBinder() : null);intent.writeToParcel(data, 0);data.writeString(resolvedType);data.writeStrongBinder(resultTo != null ? resultTo.asBinder() : null);data.writeInt(resultCode);data.writeString(resultData);data.writeBundle(map);data.writeStringArray(requiredPermissions);data.writeInt(appOp);data.writeBundle(options);data.writeInt(serialized ? 1 : 0);data.writeInt(sticky ? 1 : 0);data.writeInt(userId);//Command為BROADCAST_INTENT_TRANSACTIONmRemote.transact(BROADCAST_INTENT_TRANSACTION, data, reply, 0);reply.readException();int res = reply.readInt();reply.recycle();data.recycle();return res; }3.3 AMS.broadcastIntent
[-> ActivityManagerService.java]
public final int broadcastIntent(IApplicationThread caller,Intent intent, String resolvedType, IIntentReceiver resultTo,int resultCode, String resultData, Bundle resultExtras,String[] requiredPermissions, int appOp, Bundle options,boolean serialized, boolean sticky, int userId) {enforceNotIsolatedCaller("broadcastIntent");synchronized(this) {//驗(yàn)證廣播intent是否有效intent = verifyBroadcastLocked(intent);//獲取調(diào)用者進(jìn)程記錄對(duì)象final ProcessRecord callerApp = getRecordForAppLocked(caller);final int callingPid = Binder.getCallingPid();final int callingUid = Binder.getCallingUid();final long origId = Binder.clearCallingIdentity();//【見(jiàn)小節(jié)3.4】int res = 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);return res;} }broadcastIntent()方法有兩個(gè)布爾參數(shù)serialized和sticky來(lái)共同決定是普通廣播,有序廣播,還是Sticky廣播,參數(shù)如下:
| sendBroadcast | false | false |
| sendOrderedBroadcast | true | false |
| sendStickyBroadcast | false | true |
3.4 AMS.broadcastIntentLocked
private final int broadcastIntentLocked(ProcessRecord callerApp,String callerPackage, Intent intent, String resolvedType,IIntentReceiver resultTo, int resultCode, String resultData,Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle options,boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) {//part 1: 設(shè)置flag//part 2: 廣播權(quán)限驗(yàn)證//part 3: 處理系統(tǒng)相關(guān)廣播//part 4: 增加sticky廣播//part 5: 查詢(xún)r(jià)eceivers和registeredReceivers//part 6: 處理并行廣播//part 7: 合并registeredReceivers到receivers//part 8: 處理串行廣播return ActivityManager.BROADCAST_SUCCESS; }broadcastIntentLocked方法比較長(zhǎng),這里劃分為8個(gè)部分來(lái)分別說(shuō)明。
part 1: 設(shè)置廣播flag
intent = new Intent(intent);//增加該flag,則廣播不會(huì)發(fā)送給已停止的packageintent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);//當(dāng)沒(méi)有啟動(dòng)完成時(shí),不允許啟動(dòng)新進(jìn)程if (!mProcessesReady && (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) {intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);}userId = handleIncomingUser(callingPid, callingUid, userId,true, ALLOW_NON_FULL, "broadcast", callerPackage);//檢查發(fā)送廣播時(shí)用戶(hù)狀態(tài)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())) {return ActivityManager.BROADCAST_FAILED_USER_STOPPED;}}這個(gè)過(guò)程最重要的工作是:
- 添加flag=FLAG_EXCLUDE_STOPPED_PACKAGES,保證已停止app不會(huì)收到該廣播;
- 當(dāng)系統(tǒng)還沒(méi)有啟動(dòng)完成,則不允許啟動(dòng)新進(jìn)程,,即只有動(dòng)態(tài)注冊(cè)receiver才能接受廣播
- 當(dāng)非USER_ALL廣播且當(dāng)前用戶(hù)并沒(méi)有處于Running的情況下,除非是系統(tǒng)升級(jí)廣播或者關(guān)機(jī)廣播,否則直接返回。
BroadcastReceiver還有其他flag,位于Intent.java常量:
FLAG_RECEIVER_REGISTERED_ONLY //只允許已注冊(cè)receiver接收廣播 FLAG_RECEIVER_REPLACE_PENDING //新廣播會(huì)替代相同廣播 FLAG_RECEIVER_FOREGROUND //只允許前臺(tái)receiver接收廣播 FLAG_RECEIVER_NO_ABORT //對(duì)于有序廣播,先接收到的receiver無(wú)權(quán)拋棄廣播 FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT //Boot完成之前,只允許已注冊(cè)receiver接收廣播 FLAG_RECEIVER_BOOT_UPGRADE //升級(jí)模式下,允許系統(tǒng)準(zhǔn)備就緒前可以發(fā)送廣播part 2: 廣播權(quán)限驗(yàn)證
int callingAppId = 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) {//直接通過(guò)} else if (callerApp == null || !callerApp.persistent) {try {if (AppGlobals.getPackageManager().isProtectedBroadcast(intent.getAction())) {//不允許發(fā)送給受保護(hù)的廣播throw new SecurityException(msg);} else if (AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(intent.getAction())) {//這個(gè)case是出于兼容性考慮,限制只允許發(fā)送給自己。...}} catch (RemoteException e) {return ActivityManager.BROADCAST_SUCCESS;}}主要功能:
- 對(duì)于callingAppId為SYSTEM_UID,PHONE_UID,SHELL_UID,BLUETOOTH_UID,NFC_UID之一或者callingUid == 0時(shí)都暢通無(wú)阻;
- 否則對(duì)于調(diào)用者進(jìn)程為空并且不是persistent進(jìn)程的情況下:
- 當(dāng)發(fā)送的是受保護(hù)廣播mProtectedBroadcasts(只允許系統(tǒng)使用),則拋出異常;
- 當(dāng)action為ACTION_APPWIDGET_CONFIGURE時(shí),雖然不希望該應(yīng)用發(fā)送這種廣播,處于兼容性考慮,限制該廣播只允許發(fā)送給自己,否則拋出異常。
part 3: 處理系統(tǒng)相關(guān)廣播
final String action = intent.getAction();if (action != null) {switch (action) {case Intent.ACTION_UID_REMOVED:mBatteryStatsService.removeUid(uid);mAppOpsService.uidRemoved(uid);break;case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);if (list != null && list.length > 0) {for (int i = 0; i < list.length; i++) {forceStopPackageLocked(list[i], -1, false, true, true,false, false, userId, "storage unmount");}mRecentTasks.cleanupLocked(UserHandle.USER_ALL);sendPackageBroadcastLocked(IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list,userId);}break;case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLEmRecentTasks.cleanupLocked(UserHandle.USER_ALL);break;case Intent.ACTION_PACKAGE_REMOVED:case Intent.ACTION_PACKAGE_CHANGED:Uri data = intent.getData();boolean removed = Intent.ACTION_PACKAGE_REMOVED.equals(action);boolean fullUninstall = removed && !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);final boolean killProcess = !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 ? "pkg removed" : "pkg changed");}if (removed) {sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,new String[] {ssp}, userId);if (fullUninstall) {mAppOpsService.packageRemoved(intent.getIntExtra(Intent.EXTRA_UID, -1), ssp);removeUriPermissionsForPackageLocked(ssp, userId, true);removeTasksByPackageNameLocked(ssp, userId);mBatteryStatsService.notePackageUninstalled(ssp);}} else {cleanupDisabledPackageComponentsLocked(ssp, userId, killProcess,intent.getStringArrayExtra(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST));}break;case Intent.ACTION_PACKAGE_ADDED:Uri data = intent.getData();final boolean replacing =intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);mCompatModePackages.handlePackageAddedLocked(ssp, replacing);ApplicationInfo ai = AppGlobals.getPackageManager().getApplicationInfo(ssp, 0, 0);break;case Intent.ACTION_TIMEZONE_CHANGED:mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);break;case Intent.ACTION_TIME_CHANGED:final int is24Hour = intent.getBooleanExtra(Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT, false) ? 1: 0;mHandler.sendMessage(mHandler.obtainMessage(UPDATE_TIME, is24Hour, 0));BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();synchronized (stats) {stats.noteCurrentTimeChangedLocked();}break;case Intent.ACTION_CLEAR_DNS_CACHE: mHandler.sendEmptyMessage(CLEAR_DNS_CACHE_MSG);break;case Proxy.PROXY_CHANGE_ACTION:ProxyInfo proxy = intent.getParcelableExtra(Proxy.EXTRA_PROXY_INFO);mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY_MSG, proxy));break;}}這個(gè)過(guò)程代碼較長(zhǎng),主要處于系統(tǒng)相關(guān)的廣播,如下10個(gè)case:
case Intent.ACTION_UID_REMOVED: //uid移除case Intent.ACTION_PACKAGE_REMOVED: //package移除,case Intent.ACTION_PACKAGE_CHANGED: //package改變case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE: //外部設(shè)備不可用時(shí),強(qiáng)制停止所有波及的應(yīng)用并清空cache數(shù)據(jù)case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE: //外部設(shè)備可用case Intent.ACTION_PACKAGE_ADDED: //增加package,處于兼容考慮case Intent.ACTION_TIMEZONE_CHANGED: //時(shí)區(qū)改變,通知所有運(yùn)行中的進(jìn)程case Intent.ACTION_TIME_CHANGED: //時(shí)間改變,通知所有運(yùn)行中的進(jìn)程case Intent.ACTION_CLEAR_DNS_CACHE: //dns緩存清空case Proxy.PROXY_CHANGE_ACTION: //網(wǎng)絡(luò)代理改變part 4:增加sticky廣播
if (sticky) {if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,callingPid, callingUid)!= PackageManager.PERMISSION_GRANTED) {throw new SecurityException("");}if (requiredPermissions != null && requiredPermissions.length > 0) {return ActivityManager.BROADCAST_STICKY_CANT_HAVE_PERMISSION;}if (intent.getComponent() != null) {//當(dāng)sticky廣播發(fā)送給指定組件,則throw Exception}if (userId != UserHandle.USER_ALL) {//當(dāng)非USER_ALL廣播跟USER_ALL廣播出現(xiàn)沖突,則throw Exception}ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);if (stickies == null) {stickies = new ArrayMap<>();mStickyBroadcasts.put(userId, stickies);}ArrayList<Intent> list = stickies.get(intent.getAction());if (list == null) {list = new ArrayList<>();stickies.put(intent.getAction(), list);}final int stickiesCount = list.size();int i;for (i = 0; i < stickiesCount; i++) {if (intent.filterEquals(list.get(i))) {//替換已存在的sticky intentlist.set(i, new Intent(intent));break;}}//新的intent追加到listif (i >= stickiesCount) {list.add(new Intent(intent));}}這個(gè)過(guò)程主要是將sticky廣播增加到list,并放入mStickyBroadcasts里面。
part 5:查詢(xún)r(jià)eceivers和registeredReceivers
int[] users;if (userId == UserHandle.USER_ALL) {users = mStartedUserArray; //廣播給所有已啟動(dòng)用戶(hù)} else {users = new int[] {userId}; //廣播給指定用戶(hù)}List receivers = null;List<BroadcastFilter> registeredReceivers = null;//找出所有能接收該廣播的receiversif ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {//根據(jù)intent查找相應(yīng)的receiversreceivers = collectReceiverComponents(intent, resolvedType, callingUid, users);}if (intent.getComponent() == null) {if (userId == UserHandle.USER_ALL && callingUid == Process.SHELL_UID) {UserManagerService ums = getUserManagerLocked();for (int i = 0; i < users.length; i++) {//shell用戶(hù)是否開(kāi)啟允許debug功能if (ums.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, users[i])) {continue;}// 查詢(xún)動(dòng)態(tài)注冊(cè)的廣播List<BroadcastFilter> registeredReceiversForUser =mReceiverResolver.queryIntent(intent,resolvedType, false, users[i]);if (registeredReceivers == null) {registeredReceivers = registeredReceiversForUser;} else if (registeredReceiversForUser != null) {registeredReceivers.addAll(registeredReceiversForUser);}}} else {// 查詢(xún)動(dòng)態(tài)注冊(cè)的廣播registeredReceivers = mReceiverResolver.queryIntent(intent,resolvedType, false, userId);}}- receivers:記錄著匹配當(dāng)前intent的所有靜態(tài)注冊(cè)廣播接收者;
- registeredReceivers:記錄著匹配當(dāng)前的所有動(dòng)態(tài)注冊(cè)的廣播接收者。
其中,mReceiverResolver是AMS的成員變量,記錄著已注冊(cè)的廣播接收者的resolver.
AMS.collectReceiverComponents:
private List<ResolveInfo> collectReceiverComponents(Intent intent, String resolvedType,int callingUid, int[] users) {List<ResolveInfo> receivers = null;for (int user : users) {//調(diào)用PKMS.queryIntentReceivers,可獲取AndroidManifest.xml聲明的接收者信息List<ResolveInfo> newReceivers = AppGlobals.getPackageManager().queryIntentReceivers(intent, resolvedType, STOCK_PM_FLAGS, user);if (receivers == null) {receivers = newReceivers;} else if (newReceivers != null) {...//將所用戶(hù)的receiver整合到receivers}}return receivers; }part 6:處理并行廣播
//用于標(biāo)識(shí)是否需要用新intent替換舊的intent。final boolean replacePending = (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;//處理并行廣播int NR = registeredReceivers != null ? registeredReceivers.size() : 0;if (!ordered && NR > 0) {final BroadcastQueue queue = broadcastQueueForIntent(intent);//創(chuàng)建BroadcastRecord對(duì)象BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,callerPackage, callingPid, callingUid, resolvedType, requiredPermissions,appOp, brOptions, registeredReceivers, resultTo, resultCode, resultData,resultExtras, ordered, sticky, false, userId);final boolean replaced = replacePending && queue.replaceParallelBroadcastLocked(r);if (!replaced) {//將BroadcastRecord加入到并行廣播隊(duì)列queue.enqueueParallelBroadcastLocked(r);//處理廣播【見(jiàn)小節(jié)4.1】queue.scheduleBroadcastsLocked();}registeredReceivers = null;NR = 0;}廣播隊(duì)列中有一個(gè)成員變量mParallelBroadcasts,類(lèi)型為ArrayList,記錄著所有的并行廣播。
part 7:合并registeredReceivers到receivers
int ir = 0;if (receivers != null) {//防止應(yīng)用監(jiān)聽(tīng)該廣播,在安裝時(shí)直接運(yùn)行。String skipPackages[] = null;if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())|| Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())|| Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {Uri data = intent.getData();if (data != null) {String pkgName = data.getSchemeSpecificPart();if (pkgName != null) {skipPackages = new String[] { pkgName };}}} else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);}//將skipPackages相關(guān)的廣播接收者從receivers列表中移除if (skipPackages != null && (skipPackages.length > 0)) {for (String skipPackage : skipPackages) {if (skipPackage != null) {int NT = receivers.size();for (int it=0; it<NT; it++) {ResolveInfo curt = (ResolveInfo)receivers.get(it);if (curt.activityInfo.packageName.equals(skipPackage)) {receivers.remove(it);it--;NT--;}}}}}//前面part6有一個(gè)處理動(dòng)態(tài)廣播的過(guò)程,處理完后再執(zhí)行將動(dòng)態(tài)注冊(cè)的registeredReceivers合并到receiversint NT = receivers != null ? receivers.size() : 0;int it = 0;ResolveInfo curt = null;BroadcastFilter curr = null;while (it < NT && ir < NR) {if (curt == null) {curt = (ResolveInfo)receivers.get(it);}if (curr == null) {curr = registeredReceivers.get(ir);}if (curr.getPriority() >= curt.priority) {receivers.add(it, curr);ir++;curr = null;it++;NT++;} else { it++;curt = null;}}}while (ir < NR) {if (receivers == null) {receivers = new ArrayList();}receivers.add(registeredReceivers.get(ir));ir++;}part 8: 處理串行廣播
if ((receivers != null && receivers.size() > 0)|| resultTo != null) {BroadcastQueue queue = broadcastQueueForIntent(intent);//創(chuàng)建BroadcastRecordBroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,callerPackage, callingPid, callingUid, resolvedType,requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,resultData, resultExtras, ordered, sticky, false, userId);boolean replaced = replacePending && queue.replaceOrderedBroadcastLocked(r);if (!replaced) {//將BroadcastRecord加入到有序廣播隊(duì)列queue.enqueueOrderedBroadcastLocked(r);//處理廣播【見(jiàn)小節(jié)4.1】queue.scheduleBroadcastsLocked(); }}廣播隊(duì)列中有一個(gè)成員變量mOrderedBroadcasts,類(lèi)型為ArrayList,記錄著所有的有序廣播。
四、 處理廣播
在發(fā)送廣播過(guò)程中會(huì)執(zhí)行scheduleBroadcastsLocked方法來(lái)處理相關(guān)的廣播
4.1 scheduleBroadcastsLocked
[-> BroadcastQueue.java]
public void scheduleBroadcastsLocked() { // 正在處理BROADCAST_INTENT_MSG消息if (mBroadcastsScheduled) {return;}//發(fā)送BROADCAST_INTENT_MSG消息mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));mBroadcastsScheduled = true; }在BroadcastQueue對(duì)象創(chuàng)建時(shí),mHandler=new BroadcastHandler(handler.getLooper());那么此處交由mHandler的handleMessage來(lái)處理:
private final class BroadcastHandler extends Handler {public BroadcastHandler(Looper looper) {super(looper, null, true);}public void handleMessage(Message msg) {switch (msg.what) {case BROADCAST_INTENT_MSG: {processNextBroadcast(true); //【見(jiàn)小節(jié)4.2】} break;...} }4.2 processNextBroadcast
[-> BroadcastQueue.java]
final void processNextBroadcast(boolean fromMsg) {synchronized(mService) {//part 1: 處理并行廣播//part 2: 處理有序廣播//part 3: 獲取下條有序廣播//part 4: 處理下條有序廣播} }此處mService為AMS,整個(gè)流程還是比較長(zhǎng)的,全程持有AMS鎖,所以廣播效率低的情況下,直接會(huì)嚴(yán)重影響這個(gè)手機(jī)的性能與流暢度,這里應(yīng)該考慮細(xì)化同步鎖的粒度。
part 1: 處理并行廣播
BroadcastRecord r; mService.updateCpuStats(); //更新CPU統(tǒng)計(jì)信息 if (fromMsg) mBroadcastsScheduled = false;while (mParallelBroadcasts.size() > 0) {r = mParallelBroadcasts.remove(0);r.dispatchTime = SystemClock.uptimeMillis();r.dispatchClockTime = System.currentTimeMillis();final int N = r.receivers.size();for (int i=0; i<N; i++) {Object target = r.receivers.get(i);//分發(fā)廣播給已注冊(cè)的receiver 【見(jiàn)小節(jié)4.3】deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);}addBroadcastToHistoryLocked(r);//將廣播添加歷史統(tǒng)計(jì) }part 2:處理有序廣播
if (mPendingBroadcast != null) {boolean isDead;synchronized (mService.mPidsSelfLocked) {//從mPidsSelfLocked獲取正在處理該廣播進(jìn)程,判斷該進(jìn)程是否死亡ProcessRecord proc = mService.mPidsSelfLocked.get(mPendingBroadcast.curApp.pid);isDead = proc == null || proc.crashing;}if (!isDead) {//正在處理廣播的進(jìn)程保持活躍狀態(tài),則繼續(xù)等待其執(zhí)行完成return;} else {mPendingBroadcast.state = BroadcastRecord.IDLE;mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;mPendingBroadcast = null;} }boolean looped = false; do {if (mOrderedBroadcasts.size() == 0) {//所有串行廣播處理完成,則調(diào)度執(zhí)行g(shù)cmService.scheduleAppGcsLocked();if (looped) {mService.updateOomAdjLocked();}return;}r = mOrderedBroadcasts.get(0);boolean forceReceive = false;//獲取所有該廣播所有的接收者int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;if (mService.mProcessesReady && r.dispatchTime > 0) {long now = SystemClock.uptimeMillis();if ((numReceivers > 0) &&(now > r.dispatchTime + (2*mTimeoutPeriod*numReceivers))) {//當(dāng)廣播處理時(shí)間超時(shí),則強(qiáng)制結(jié)束這條廣播broadcastTimeoutLocked(false);forceReceive = true;r.state = BroadcastRecord.IDLE;}}if (r.state != BroadcastRecord.IDLE) {return;}if (r.receivers == null || r.nextReceiver >= numReceivers|| r.resultAbort || forceReceive) {if (r.resultTo != null) {//處理廣播消息消息performReceiveLocked(r.callerApp, r.resultTo,new Intent(r.intent), r.resultCode,r.resultData, r.resultExtras, false, false, r.userId);r.resultTo = null;}//取消BROADCAST_TIMEOUT_MSG消息cancelBroadcastTimeoutLocked();addBroadcastToHistoryLocked(r);mOrderedBroadcasts.remove(0);r = null;looped = true;continue;} } while (r == null);mTimeoutPeriod,對(duì)于前臺(tái)廣播則為10s,對(duì)于后臺(tái)廣播則為60s,此時(shí)廣播超時(shí)為2*mTimeoutPeriod*numReceivers,接收者越多則廣播超時(shí)總時(shí)長(zhǎng)越長(zhǎng)。
part 3: 獲取下條有序廣播
//獲取下一個(gè)receiver的index int recIdx = r.nextReceiver++;r.receiverTime = SystemClock.uptimeMillis(); if (recIdx == 0) {r.dispatchTime = r.receiverTime;r.dispatchClockTime = System.currentTimeMillis(); } if (!mPendingBroadcastTimeoutMessage) {long timeoutTime = r.receiverTime + mTimeoutPeriod;//設(shè)置廣播超時(shí)時(shí)間,發(fā)送BROADCAST_TIMEOUT_MSGsetBroadcastTimeoutLocked(timeoutTime); }final BroadcastOptions brOptions = r.options; //獲取下一個(gè)廣播接收者 final Object nextReceiver = r.receivers.get(recIdx);if (nextReceiver instanceof BroadcastFilter) {//對(duì)于動(dòng)態(tài)注冊(cè)的廣播接收者,deliverToRegisteredReceiverLocked處理廣播BroadcastFilter filter = (BroadcastFilter)nextReceiver;deliverToRegisteredReceiverLocked(r, filter, r.ordered);if (r.receiver == null || !r.ordered) {r.state = BroadcastRecord.IDLE;scheduleBroadcastsLocked();} else {...}return; }//對(duì)于靜態(tài)注冊(cè)的廣播接收者 ResolveInfo info = (ResolveInfo)nextReceiver; ComponentName component = new ComponentName(info.activityInfo.applicationInfo.packageName,info.activityInfo.name); ... //執(zhí)行各種權(quán)限檢測(cè),此處省略,當(dāng)權(quán)限不滿(mǎn)足時(shí)skip=trueif (skip) {r.receiver = null;r.curFilter = null;r.state = BroadcastRecord.IDLE;scheduleBroadcastsLocked();return; }r.state = BroadcastRecord.APP_RECEIVE; String targetProcess = info.activityInfo.processName; r.curComponent = component; final int receiverUid = info.activityInfo.applicationInfo.uid; if (r.callingUid != Process.SYSTEM_UID && isSingleton&& mService.isValidSingletonCall(r.callingUid, receiverUid)) {info.activityInfo = mService.getActivityInfoForUser(info.activityInfo, 0); } r.curReceiver = info.activityInfo; ...//Broadcast正在執(zhí)行中,stopped狀態(tài)設(shè)置成false AppGlobals.getPackageManager().setPackageStoppedState(r.curComponent.getPackageName(), false, UserHandle.getUserId(r.callingUid));part 4: 處理下條有序廣播
//該receiver所對(duì)應(yīng)的進(jìn)程已經(jīng)運(yùn)行,則直接處理 ProcessRecord app = 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 (RemoteException e) {} catch (RuntimeException e) {finishReceiverLocked(r, r.resultCode, r.resultData, r.resultExtras, r.resultAbort, false);scheduleBroadcastsLocked();r.state = BroadcastRecord.IDLE; //啟動(dòng)receiver失敗則重置狀態(tài)return;} }//該receiver所對(duì)應(yīng)的進(jìn)程尚未啟動(dòng),則創(chuàng)建該進(jìn)程 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) {//創(chuàng)建失敗,則結(jié)束該receiverfinishReceiverLocked(r, r.resultCode, r.resultData,r.resultExtras, r.resultAbort, false);scheduleBroadcastsLocked();r.state = BroadcastRecord.IDLE;return; } mPendingBroadcast = r; mPendingBroadcastRecvIndex = recIdx;- 如果是動(dòng)態(tài)廣播接收者,則調(diào)用deliverToRegisteredReceiverLocked處理;
- 如果是動(dòng)態(tài)廣播接收者,且對(duì)應(yīng)進(jìn)程已經(jīng)創(chuàng)建,則調(diào)用processCurBroadcastLocked處理;
- 如果是動(dòng)態(tài)廣播接收者,且對(duì)應(yīng)進(jìn)程尚未創(chuàng)建,則調(diào)用startProcessLocked創(chuàng)建進(jìn)程。
4.3 deliverToRegisteredReceiverLocked
[-> BroadcastQueue.java]
private void deliverToRegisteredReceiverLocked(BroadcastRecord r,BroadcastFilter filter, boolean ordered) {...//檢查發(fā)送者是否有BroadcastFilter所需權(quán)限//以及接收者是否有發(fā)送者所需的權(quán)限等等//當(dāng)權(quán)限不滿(mǎn)足要求,則skip=true。if (!skip) {//并行廣播ordered = false,只有串行廣播才進(jìn)入該分支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) {r.curApp = filter.receiverList.app;filter.receiverList.app.curReceiver = r;mService.updateOomAdjLocked(r.curApp);}}// 處理廣播【見(jiàn)小節(jié)4.4】performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,new Intent(r.intent), r.resultCode, r.resultData,r.resultExtras, r.ordered, r.initialSticky, r.userId);if (ordered) {r.state = BroadcastRecord.CALL_DONE_RECEIVE;}...} }4.4 deliverToRegisteredReceiverLocked
[-> BroadcastQueue.java]
private static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,Intent intent, int resultCode, String data, Bundle extras,boolean ordered, boolean sticky, int sendingUser) throws RemoteException {//通過(guò)binder異步機(jī)制,向receiver發(fā)送intentif (app != null) {if (app.thread != null) {//調(diào)用ApplicationThreadProxy類(lèi)對(duì)應(yīng)的方法 【4.5】app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,data, extras, ordered, sticky, sendingUser, app.repProcState);} else {//應(yīng)用進(jìn)程死亡,則Recevier并不存在throw new RemoteException("app.thread must not be null");}} else {//調(diào)用者進(jìn)程為空,則執(zhí)行該分支receiver.performReceive(intent, resultCode, data, extras, ordered,sticky, sendingUser);} }4.5 ATP.scheduleRegisteredReceiver
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,int resultCode, String dataStr, Bundle extras, boolean ordered,boolean sticky, int sendingUser, int processState) throws RemoteException {Parcel data = Parcel.obtain();data.writeInterfaceToken(IApplicationThread.descriptor);data.writeStrongBinder(receiver.asBinder());intent.writeToParcel(data, 0);data.writeInt(resultCode);data.writeString(dataStr);data.writeBundle(extras);data.writeInt(ordered ? 1 : 0);data.writeInt(sticky ? 1 : 0);data.writeInt(sendingUser);data.writeInt(processState);//command=SCHEDULE_REGISTERED_RECEIVER_TRANSACTIONmRemote.transact(SCHEDULE_REGISTERED_RECEIVER_TRANSACTION, data, null,IBinder.FLAG_ONEWAY);data.recycle(); }ATP位于system_server進(jìn)程,是Binder Bp端通過(guò)Binder驅(qū)動(dòng)向Binder Bn端發(fā)送消息, ATP所對(duì)應(yīng)的Bn端位于發(fā)送廣播調(diào)用端所在進(jìn)程的ApplicationThread,即進(jìn)入AT.scheduleRegisteredReceiver, 接下來(lái)說(shuō)明該方法。
4.6 AT.scheduleRegisteredReceiver
[-> ActivityThread.java]
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,int resultCode, String dataStr, Bundle extras, boolean ordered,boolean sticky, int sendingUser, int processState) throws RemoteException {//更新虛擬機(jī)進(jìn)程狀態(tài)updateProcessState(processState, false);//【見(jiàn)小節(jié)4.7】receiver.performReceive(intent, resultCode, dataStr, extras, ordered,sticky, sendingUser); }此處receiver是注冊(cè)廣播時(shí)創(chuàng)建的,見(jiàn)小節(jié)[2.3],可知該receiver=LoadedApk.ReceiverDispatcher.InnerReceiver。
4.7 InnerReceiver.performReceive
[-> LoadedApk.java]
public void performReceive(Intent intent, int resultCode, String data,Bundle extras, boolean ordered, boolean sticky, int sendingUser) {LoadedApk.ReceiverDispatcher rd = mDispatcher.get();if (rd != null) {//【4.8】rd.performReceive(intent, resultCode, data, extras, ordered, sticky, sendingUser);} else {...} }4.8 ReceiverDispatcher.performReceive
[-> LoadedApk.java]
public void performReceive(Intent intent, int resultCode, String data,Bundle extras, boolean ordered, boolean sticky, int sendingUser) {Args args = new Args(intent, resultCode, data, extras, ordered,sticky, sendingUser);//通過(guò)handler消息機(jī)制發(fā)送args.if (!mActivityThread.post(args)) {if (mRegistered && ordered) {IActivityManager mgr = ActivityManagerNative.getDefault();args.sendFinished(mgr);}} }其中Args繼承于BroadcastReceiver.PendingResult,實(shí)現(xiàn)了接口Runnable。這里mActivityThread.post(args) 消息機(jī)制,關(guān)于Handler消息機(jī)制,見(jiàn)Android消息機(jī)制1-Handler(Java層),把消息放入MessageQueue,再調(diào)用Args的run()方法。
4.9 Args.run
[-> LoadedApk.java]
public final class LoadedApk {static final class ReceiverDispatcher {final class Args extends BroadcastReceiver.PendingResult implements Runnable {public void run() {final BroadcastReceiver receiver = mReceiver;final boolean ordered = mOrdered;final IActivityManager mgr = ActivityManagerNative.getDefault();final Intent intent = mCurIntent;mCurIntent = null;if (receiver == null || mForgotten) {if (mRegistered && ordered) {sendFinished(mgr);}return;}try {//獲取mReceiver的類(lèi)加載器ClassLoader cl = mReceiver.getClass().getClassLoader();intent.setExtrasClassLoader(cl);setExtrasClassLoader(cl);receiver.setPendingResult(this);//回調(diào)廣播onReceive方法receiver.onReceive(mContext, intent);} catch (Exception e) {...}if (receiver.getPendingResult() != null) {finish();}}}}最終調(diào)用BroadcastReceiver具體實(shí)現(xiàn)類(lèi)的onReceive()方法。
4.10 PendingResult.finish
[-> BroadcastReceiver.java]
public final void finish() {final IActivityManager mgr = ActivityManagerNative.getDefault();sendFinished(mgr);... }public void sendFinished(IActivityManager am) {synchronized (this) {try {if (mResultExtras != null) {mResultExtras.setAllowFds(false);}if (mOrderedHint) {//串行廣播am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras,mAbortBroadcast, mFlags);} else {//并行廣播am.finishReceiver(mToken, 0, null, null, false, mFlags);}} catch (RemoteException ex) {}} }此處AMP.finishReceiver,經(jīng)過(guò)binder調(diào)用,進(jìn)入AMS.finishReceiver方法
4.11 AMS.finishReceiver
public void finishReceiver(IBinder who, int resultCode, String resultData,Bundle resultExtras, boolean resultAbort, int flags) { ...final long origId = Binder.clearCallingIdentity();try {boolean doNext = false;BroadcastRecord r;synchronized(this) {BroadcastQueue queue = (flags & Intent.FLAG_RECEIVER_FOREGROUND) != 0? mFgBroadcastQueue : mBgBroadcastQueue;r = queue.getMatchingOrderedReceiver(who);if (r != null) {doNext = r.queue.finishReceiverLocked(r, resultCode,resultData, resultExtras, resultAbort, true);}}if (doNext) {//處理下一條廣播r.queue.processNextBroadcast(false);}trimApplications();} finally {Binder.restoreCallingIdentity(origId);} }五、總結(jié)
未完留坑,后續(xù)總結(jié)以及增加流程圖說(shuō)明…
附錄
本文所涉及的源碼:
framework/base/core/java/android/content/BroadcastReceiver.java framework/base/core/java/android/content/Context.java framework/base/core/java/android/content/IntentFilter.javaframework/base/core/java/android/app/ContextImpl.java framework/base/core/java/android/app/LoadedApk framework/base/core/java/android/app/ActivityManagerNative.java framework/base/core/java/android/app/ApplicationThreadNative.java framework/base/core/java/android/app/ActivityThread.javaframework/base/services/core/java/com/android/server/ActivityManagerService.java framework/base/services/core/java/com/android/server/am/BroadcastQueue.java framework/base/services/core/java/com/android/server/am/BroadcastFilter.java framework/base/services/core/java/com/android/server/am/BroadcastRecord.java framework/base/services/core/java/com/android/server/am/ReceiverList.java原文地址:http://gityuan.com/2016/06/04/broadcast-receiver/
總結(jié)
以上是生活随笔為你收集整理的Android Broadcast广播机制分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Android系统启动-zygote篇
- 下一篇: Android JNI原理分析