【私人備忘錄】Android P ActivityManagerService(四)BroadcastReceiver的工作過程

靜態註冊的廣播是有PMS完成註冊的,不在AMS系列中討論,只看動態註冊。

一、註冊廣播代碼流程

ContextWrapper.java
registerReceiver();Activity.java調用的是爺爺類ContextWrapper.java的registerReceiver()
ContextImpl.java
registerReceiver() → registerReceiverInternal(ActivityManager.getService().registerReceiver())
ActivityManagerService.java
registerReceiver()

備註:
1、ContextImpl.registerReceiverInternal()中用mPackageInfo.getReceiverDispatcher獲取了IIntentReceiver,IIntentReceiver是Binder接口,是LoadedApk.ReceiverDispatcher.InnerReceiver,看着和Service的有點像,原理是類似的。這玩樣兒用於進程間通訊的,所以不用BroadcastReceiver而使用IIntentReceiver。
2、ActivityManagerService.registerReceiver()主要工作:
    2.1、存儲遠程的IIntentReceiver對象:mRegisteredReceivers.put(receiver.asBinder(), rl);
    2.2、存儲IntentFilter對象:BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, permission, callingUid, userId, instantApp, visibleToInstantApps);mReceiverResolver.addFilter(bf);
3、每一個應用都持有一個LoadedApk實例,LoadedApk實例中包含多個Context實例,每個Context實例可能創建了多個BroadcastReceiver實例,每個BroadcastReceiver實例在動態註冊的時候都會生成一個對應的ReceiverDispatcher實例,每個ReceiverDispatcher實例內部又會由InnerReceiver類生成一個IIntentReceiver實例。這個IIntentReceiver實例在動態註冊BroadcastReceiver的時候會被傳遞給AMS,AMS會爲每個IIntentReceiver實例創建一個ReceiverList實例,每個ReceiverList實例中保存了多個BroadcastFilter實例,而這個BroadcastFilter實例裏面包含了具體的IntentFilter和ReceiverList等相關信息。

二、廣播的收發代碼流程

ContextWrapper.java
sendBroadcast();Activity.java調用的是爺爺類ContextWrapper.java的sendBroadcast()
ContextImpl.java
sendBroadcast(ActivityManager.getService().broadcastIntent())
ActivityManagerService.java
broadcastIntent() → broadcastIntentLocked(queue.scheduleBroadcastsLocked())
BroadcastQueue.java
scheduleBroadcastsLocked(mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this))) → BroadcastHandler.handleMessage(case BROADCAST_INTENT_MSG) → processNextBroadcast() → processNextBroadcastLocked() → deliverToRegisteredReceiverLocked() → performReceiveLocked(app.thread.scheduleRegisteredReceiver())
ActivityThread.java
ApplicationThread.scheduleRegisteredReceiver(receiver.performReceive())
LoadedApk.java
ReceiverDispatcher.performReceive(mActivityThread.post(args.getRunnable())) → Args.getRunnable()
BroadcastReceiver.java
onReceive()

備註:
1、ActivityManagerService.broadcastIntentLocked()剛開始地方有:intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);代碼也有註釋,默認情況下廣播不會發送給已經停止的應用,如果想發給已經停止的應用,可以加上Intent.FLAG_INCLUDE_STOPPED_PACKAGES的flag。
2、ActivityManagerService.broadcastIntentLocked()賊長,主要是根據Filter查找滿足條件的接受者並添加到BroadcastQueue中。
    2.1、receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);靜態註冊廣播接收者
    2.2、registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false, userId);動態註冊的廣播接收者
    2.3、receivers.add(registeredReceivers.get(ir));動態註冊的registeredReceivers,全部合併到receivers賦值給BroadcastRecord,再統一按串行方式處理:queue.enqueueOrderedBroadcastLocked(r);queue.scheduleBroadcastsLocked();
3、BroadcastQueue.processNextBroadcastLocked()賊長,這裏只主要看下//First, deliver any non-serialized broadcasts right away.無需廣播處理,走了一波deliverToRegisteredReceiverLocked()。
4、Args.getRunnable()主要代碼有:final BroadcastReceiver receiver = mReceiver;receiver.setPendingResult(this);receiver.onReceive(mContext, intent);這裏onReceive已經被執行了,因爲是mActivityThread.post執行的,所以是在主線程執行的。

三、關係圖

類關係圖

 

流程關係圖

備註:
1、動態註冊過程可理解爲建立LoadedApk、Context、BroadcastReceiver和ReceiverDispatcher的映射關係;建立ReceiverList和BroadcastFilter的映射關係。兩個映射關係共同持有同一個IIntentReceiver。
2、廣播的收發AMS根據Context廣播的Intent信息對照映射關係表從BroadcastFilter開始,反向一層一層找到與之對應的BroadcastReceiver,最終完成BroadcastReceiver.OnReceive的調用,把Intent傳遞給對應的BroadcastReceiver。 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章