傳送廣播(sendBroadcast)的過程原始碼分析
傳送廣播(sendBroadcast)的過程原始碼分析
一、簡介
這篇文章我們來分析sendBroadcast的過程。
二、原始碼分析
一般我們通過以下程式碼來發送一個廣播
Intent intent = new Intent(XXX_ACTION);
sendBroadcast(intent);
sendBroadcast的具體實現是在 ContextImpl類中
class ContextImpl extends Context { public void sendBroadcast(Intent intent) { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { intent.prepareToLeaveProcess(this); ActivityManager.getService().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false, getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } }
其中呼叫了AMS的broadcastIntent方法
public class ActivityManagerService extends IActivityManager.Stub implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback { public final int broadcastIntent(IApplicationThread caller, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions, boolean serialized, boolean sticky, int userId) { enforceNotIsolatedCaller("broadcastIntent"); synchronized(this) { intent = verifyBroadcastLocked(intent); final ProcessRecord callerApp = getRecordForAppLocked(caller); final int callingPid = Binder.getCallingPid(); final int callingUid = Binder.getCallingUid(); final long origId = Binder.clearCallingIdentity(); int res = broadcastIntentLocked(callerApp, callerApp != null ? callerApp.info.packageName : null, intent, resolvedType, resultTo, resultCode, resultData, resultExtras, requiredPermissions, appOp, bOptions, serialized, sticky, callingPid, callingUid, userId); Binder.restoreCallingIdentity(origId); return res; } } final int broadcastIntentLocked(ProcessRecord callerApp, String callerPackage, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions, boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) { intent = new Intent(intent); //... // Figure out who all will receive this broadcast. List receivers = null; List<BroadcastFilter> registeredReceivers = null; if (intent.getComponent() == null) {//1 因為我們傳入的intent Component為空,所以此處符合條件 if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) { // Query one target user at a time, excluding shell-restricted users for (int i = 0; i < users.length; i++) { if (mUserController.hasUserRestriction( UserManager.DISALLOW_DEBUGGING_FEATURES, users[i])) { continue; } List<BroadcastFilter> registeredReceiversForUser = mReceiverResolver.queryIntent(intent, resolvedType, false /*defaultOnly*/, users[i]);//2 通過mReceiverResolver.queryIntent找出相應的廣播接收器,你是否還記得在之前的廣播註冊過程中我們把BroadcastFilter存到了mReceiverResolver, // 此處是取出我們存入的BroadcastFilter,BroadcastFilter,因為有可能有多個廣播接收器註冊了同一個廣播所以此處返回的是一個list,該list包含了註冊了當前廣播的所有receiver if (registeredReceivers == null) { registeredReceivers = registeredReceiversForUser; } else if (registeredReceiversForUser != null) { registeredReceivers.addAll(registeredReceiversForUser); } } } else { registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false /*defaultOnly*/, userId); } } //... int NR = registeredReceivers != null ? registeredReceivers.size() : 0; if (!ordered && NR > 0) { // If we are not serializing this broadcast, then send the // registered receivers separately so they don't wait for the // components to be launched. if (isCallerSystem) { checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid, isProtectedBroadcast, registeredReceivers); } final BroadcastQueue queue = broadcastQueueForIntent(intent); //3 構造一個BroadcastRecord 裡面記錄了這個廣播是由誰發出的以及要發給誰等相關資訊 BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage, callingPid, callingUid, callerInstantApp, resolvedType, requiredPermissions, appOp, brOptions, registeredReceivers, resultTo, resultCode, resultData, resultExtras, ordered, sticky, false, userId); if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing parallel broadcast " + r); final boolean replaced = replacePending && (queue.replaceParallelBroadcastLocked(r) != null); // Note: We assume resultTo is null for non-ordered broadcasts. if (!replaced) { queue.enqueueParallelBroadcastLocked(r);//4 儲存BroadcastRecord到mParallelBroadcasts中 queue.scheduleBroadcastsLocked();//5 處理廣播 } registeredReceivers = null; NR = 0; } //... }
在broadcastIntentLocked中會通過mReceiverResolver.queryIntent找出相應的廣播接收器,然後在註釋3處構造一個BroadcastRecord 因為傳入callerApp、registeredReceivers等引數所以BroadcastRecord裡面記錄了這個廣播是由誰發出的以及要發給誰等相關資訊。在註釋4處把上面構造的BroadcastRecord存到了mParallelBroadcasts變數中,mParallelBroadcasts是一個儲存即將執行的廣播的list,之後便是呼叫BroadcastQueue.scheduleBroadcastsLocked()對廣播進行處理。
到這裡廣播的傳送實際上就已經完成了,下面的操作是對廣播的處理,廣播的處理是在BroadcastQueue類中,這個類儲存了已經發送且尚未處理的廣播。
public final class BroadcastQueue {
public void scheduleBroadcastsLocked() {
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Schedule broadcasts ["
+ mQueueName + "]: current="
+ mBroadcastsScheduled);
if (mBroadcastsScheduled) {//1 mBroadcastsScheduled為true表示當前AMS正在處理某個廣播
return;
}
mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));//2 用handler傳送message
mBroadcastsScheduled = true;
}
}
scheduleBroadcastsLocked實現很簡單首先判斷當前AMS是否正在處理某個廣播如果是返回,如果沒有則傳送message並把mBroadcastsScheduled置為true。這樣就可以保證所有廣播都是序列處理的。
public void handleMessage(Message msg) {
switch (msg.what) {
case BROADCAST_INTENT_MSG: {
if (DEBUG_BROADCAST) Slog.v(
TAG_BROADCAST, "Received BROADCAST_INTENT_MSG");
processNextBroadcast(true);//呼叫processNextBroadcast
} break;
case BROADCAST_TIMEOUT_MSG: {
synchronized (mService) {
broadcastTimeoutLocked(true);
}
} break;
}
}
public final class BroadcastQueue {
final void processNextBroadcast(boolean fromMsg) {
if (fromMsg) {//mBroadcastsScheduled置為false
mBroadcastsScheduled = false;
}
while (mParallelBroadcasts.size() > 0) {//1 你是否還記得在AMS中我們把傳送的廣播所對應BroadcastRecord存入到了mParallelBroadcasts中,在這裡會迴圈取出存入的BroadcastRecord
r = mParallelBroadcasts.remove(0);
r.dispatchTime = SystemClock.uptimeMillis();
r.dispatchClockTime = System.currentTimeMillis();
if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER,
createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_PENDING),
System.identityHashCode(r));
Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_DELIVERED),
System.identityHashCode(r));
}
final int N = r.receivers.size(); //2 receivers儲存了註冊當前廣播的接收器
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing parallel broadcast ["
+ mQueueName + "] " + r);
for (int i=0; i<N; i++) {//3 迴圈取出註冊當前廣播的接收器
Object target = r.receivers.get(i);
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Delivering non-ordered on [" + mQueueName + "] to registered "
+ target + ": " + r);
deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);//4 把當前廣播發送給每一個訂閱了該廣播的接收器
}
addBroadcastToHistoryLocked(r);
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["
+ mQueueName + "] " + r);
}
}
}
processNextBroadcast會把mBroadcastsScheduled置為false這樣下一個廣播到來就可以進行處理了。之後就是在註釋1迴圈取出存入mParallelBroadcasts的BroadcastRecord,然後迴圈取出註冊當前廣播的接收器,最後通過deliverToRegisteredReceiverLocked把當前廣播發送給每一個訂閱了該廣播的接收器。
private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
BroadcastFilter filter, boolean ordered, int index) {
boolean skip = false;
if (filter.requiredPermission != null) {
int perm = mService.checkComponentPermission(filter.requiredPermission,
r.callingPid, r.callingUid, -1, true);
if (perm != PackageManager.PERMISSION_GRANTED) {//1 首先檢查一下廣播發送和接收的許可權
Slog.w(TAG, "Permission Denial: broadcasting "
+ r.intent.toString()
+ " from " + r.callerPackage + " (pid="
+ r.callingPid + ", uid=" + r.callingUid + ")"
+ " requires " + filter.requiredPermission
+ " due to registered receiver " + filter);
skip = true;
} else {
final int opCode = AppOpsManager.permissionToOpCode(filter.requiredPermission);
if (opCode != AppOpsManager.OP_NONE
&& mService.mAppOpsService.noteOperation(opCode, r.callingUid,
r.callerPackage) != AppOpsManager.MODE_ALLOWED) {
Slog.w(TAG, "Appop Denial: broadcasting "
+ r.intent.toString()
+ " from " + r.callerPackage + " (pid="
+ r.callingPid + ", uid=" + r.callingUid + ")"
+ " requires appop " + AppOpsManager.permissionToOp(
filter.requiredPermission)
+ " due to registered receiver " + filter);
skip = true;
}
}
}
//...
try {
if (DEBUG_BROADCAST_LIGHT) Slog.i(TAG_BROADCAST,
"Delivering to " + filter + " : " + r);
if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {
// Skip delivery if full backup in progress
// If it's an ordered broadcast, we need to continue to the next receiver.
if (ordered) {
skipReceiverLocked(r);
}
} else {
//2 傳送廣播
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;
}
}
}
deliverToRegisteredReceiverLocked做的主要是兩件事,檢查許可權然後傳送廣播。
void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Intent intent, int resultCode, String data, Bundle extras,
boolean ordered, boolean sticky, int sendingUser) throws RemoteException {
if (app != null) {
if (app.thread != null) {
// If we have an app thread, do the call through that so it is
// correctly ordered with other one-way calls.
try {
app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
data, extras, ordered, sticky, sendingUser, app.repProcState);//1 分發廣播
// TODO: Uncomment this when (b/28322359) is fixed and we aren't getting
// DeadObjectException when the process isn't actually dead.
//} catch (DeadObjectException ex) {
// Failed to call into the process. It's dying so just let it die and move on.
// throw ex;
} catch (RemoteException ex) {
// Failed to call into the process. It's either dying or wedged. Kill it gently.
synchronized (mService) {
Slog.w(TAG, "Can't deliver broadcast to " + app.processName
+ " (pid " + app.pid + "). Crashing it.");
app.scheduleCrash("can't deliver broadcast");
}
throw ex;
}
} else {
// Application has died. Receiver doesn't exist.
throw new RemoteException("app.thread must not be null");
}
} else {
receiver.performReceive(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
}
}
performReceiveLocked呼叫app.thread.scheduleRegisteredReceiver函式來把這個廣播分發出去,此處的app.thread一個Binder遠端物件,最終呼叫的是ActivityThread的scheduleRegisteredReceiver。
public final class ActivityThread {
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
int resultCode, String dataStr, Bundle extras, boolean ordered,
boolean sticky, int sendingUser, int processState) throws RemoteException {
updateProcessState(processState, false);
receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
sticky, sendingUser);//1
}
}
scheduleRegisteredReceiver中的receiver具體型別是LoadedApk.ReceiverDispatcher.InnerReceiver
@Override
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
final LoadedApk.ReceiverDispatcher rd;
if (intent == null) {
Log.wtf(TAG, "Null intent received");
rd = null;
} else {
rd = mDispatcher.get();
}
if (ActivityThread.DEBUG_BROADCAST) {
int seq = intent.getIntExtra("seq", -1);
Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction()
+ " seq=" + seq + " to " + (rd != null ? rd.mReceiver : null));
}
if (rd != null) {
rd.performReceive(intent, resultCode, data, extras,
ordered, sticky, sendingUser);//1
} else {
// The activity manager dispatched a broadcast to a registered
// receiver in this process, but before it could be delivered the
// receiver was unregistered. Acknowledge the broadcast on its
// behalf so that the system's broadcast sequence can continue.
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing broadcast to unregistered receiver");
IActivityManager mgr = ActivityManager.getService();
try {
if (extras != null) {
extras.setAllowFds(false);
}
mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
performReceive呼叫了LoadedApk.ReceiverDispatcher的performReceive
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
final Args args = new Args(intent, resultCode, data, extras, ordered,
sticky, sendingUser);//1 構造Args
if (intent == null) {
Log.wtf(TAG, "Null intent received");
} else {
if (ActivityThread.DEBUG_BROADCAST) {
int seq = intent.getIntExtra("seq", -1);
Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction()
+ " seq=" + seq + " to " + mReceiver);
}
}
if (intent == null || !mActivityThread.post(args.getRunnable())) {//2 呼叫handler post傳送args
if (mRegistered && ordered) {
IActivityManager mgr = ActivityManager.getService();
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing sync broadcast to " + mReceiver);
args.sendFinished(mgr);
}
}
}
我們看到首先構造了一個Args 例項,然後在註釋2處呼叫了args.getRunnable(),這個方法會返回一個Runnable例項。然後通過mActivityThread傳送出去,此處的mActivityThread實際是一個Handler並且是ReceiverDispatcher的一個內部變數。mActivityThread是在ReceiverDispatcher的建構函式中進行賦值的。
static final class ReceiverDispatcher {
final Handler mActivityThread;
ReceiverDispatcher(BroadcastReceiver receiver, Context context,
Handler activityThread, Instrumentation instrumentation,
boolean registered) {
if (activityThread == null) {
throw new NullPointerException("Handler must not be null");
}
mIIntentReceiver = new InnerReceiver(this, !registered);
mReceiver = receiver;
mContext = context;
mActivityThread = activityThread;//為mActivityThread賦值
mInstrumentation = instrumentation;
mRegistered = registered;
mLocation = new IntentReceiverLeaked(null);
mLocation.fillInStackTrace();
}
}
那麼此處的mActivityThread實際是從哪裡傳入的呢。不知道你是否還記得廣播註冊流程分析中在ContextImpl.registerReceiverInternal函式中我們曾獲取過ReceiverDispatcher,handler就是在那時傳入並賦值的。而當時傳入的handler是通過mMainThread.getHandler()獲取的這個handler是ActivityThread的H也就是註冊廣播接收器的主執行緒的handler。
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
IntentFilter filter, String broadcastPermission,
Handler scheduler, Context context, int flags) {
IIntentReceiver rd = null;
if (scheduler == null) {
scheduler = mMainThread.getHandler();//傳入的handler
}
rd = mPackageInfo.getReceiverDispatcher(
receiver, context, scheduler,
mMainThread.getInstrumentation(), true);//獲取ReceiverDispatcher
}
mActivityThread是註冊廣播接收器所在程序主執行緒的handler,那我們通過post操作就向其傳送一條訊息。註冊廣播接收器所在程序主執行緒收到後會進行處理,此處就是執行post中的runnable。runnable是通過args.getRunnable()獲取的。
final class Args extends BroadcastReceiver.PendingResult {
public final Runnable getRunnable() {
return () -> {
final BroadcastReceiver receiver = mReceiver;
final boolean ordered = mOrdered;
//...
try {
ClassLoader cl = mReceiver.getClass().getClassLoader();
intent.setExtrasClassLoader(cl);
intent.prepareToEnterProcess();
setExtrasClassLoader(cl);
receiver.setPendingResult(this);
receiver.onReceive(mContext, intent);//呼叫onReceive
}
}
我們看到在 getRunnable()返回的runnable的run方法中呼叫了receiver.onReceive,此處的receiver就是註冊廣播接收器是傳入的廣播接收器。至此廣播接收器就接收到傳送的廣播了。
最後,我們總結一下這個Android應用程式傳送廣播的過程:
1、通過sendBroadcast把一個廣播通過Binder程序間通訊機制傳送給ActivityManagerService,ActivityManagerService根據這個廣播的Action型別找到相應的廣播接收器,然後把這個廣播放進自己的訊息佇列中去,就完成第一階段對這個廣播的非同步分發了;
2、ActivityManagerService在訊息迴圈中處理這個廣播,並通過Binder程序間通訊機制把這個廣播分發給註冊的廣播接收分發器ReceiverDispatcher,ReceiverDispatcher把這個廣播放進廣播接收器所在的執行緒的訊息佇列中去,就完成第二階段對這個廣播的非同步分發了;
3、ReceiverDispatcher的內部類Args在廣播接收器所在的執行緒訊息迴圈中處理這個廣播,最終是將這個廣播分發給所註冊的BroadcastReceiver例項的onReceive函式進行處理。
傳送廣播就是傳送端把廣播intent通過IPC傳送給AMS,AMS在收到廣播intent後會根據廣播intent在已註冊的廣播接收器中查詢匹配的接收器。然後把廣播intent封裝成BroadcastRecord存入BroadcastQueue到這一步廣播的傳送就完成了,接下來就是廣播的分發,上一步我們已經把廣播存入BroadcastQueue,廣播分發就是取出BroadcastQueue中的廣播通過IPC分發至對應的廣播接收器。
下面我們來看下整個流程部分核心操作是如何完成的:
1、傳送廣播就是傳送端把廣播intent通過IPC傳送給AMS,AMS在收到廣播intent後會根據廣播intent在已註冊的廣播接收器中查詢匹配的接收器,AMS查詢匹配的接收器是通過mReceiverResolver.queryIntent,我們之前分析過廣播的註冊過程,在AMS端註冊最後階段我們會把註冊器所對應的BroadcastFilter存入mReceiverResolver。mReceiverResolver通過解析廣播的intent找到匹配的BroadcastFilter,這一步操作可以這樣理解:廣播是基於訂閱/釋出模型的,該模型需要一個數據中心,資料中心需要一張記錄訂閱廣播的記錄表,這樣廣播A到達後資料中心可以通過查表找到訂閱廣播A的接收者,AMS充當資料中心的角色,mReceiverResolver可以看做是資料中心那張記錄表,而BroadcastFilter可以看做是表中的一條記錄,該記錄表明自己感興趣的廣播。所以當AMS收到廣播時會查詢mReceiverResolver。
final int broadcastIntentLocked(ProcessRecord callerApp, String callerPackage, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions, boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) { ... List receivers = null; List<BroadcastFilter> registeredReceivers = null; // Need to resolve the intent to interested receivers... if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) { receivers = collectReceiverComponents(intent, resolvedType, callingUid, users); } if (intent.getComponent() == null) { if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) { // Query one target user at a time, excluding shell-restricted users for (int i = 0; i < users.length; i++) { if (mUserController.hasUserRestriction( UserManager.DISALLOW_DEBUGGING_FEATURES, users[i])) { continue; } //通過在mReceiverResolver找到該廣播的接收者 List<BroadcastFilter> registeredReceiversForUser = mReceiverResolver.queryIntent(intent, resolvedType, false /*defaultOnly*/, users[i]); if (registeredReceivers == null) { registeredReceivers = registeredReceiversForUser; } else if (registeredReceiversForUser != null) { registeredReceivers.addAll(registeredReceiversForUser); } } } else { registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false /*defaultOnly*/, userId); } }
2、當發現有接收該廣播的接收器時,AMS會進行記錄即建立BroadcastRecord物件,BroadcastRecord是AMS端用來詳細記錄一個廣播相關資訊的類,比如廣播所在queue、廣播發送者、接受者等等資訊。
BroadcastQueue queue = broadcastQueueForIntent(intent); //建立BroadcastRecord記錄一個廣播相關資訊 BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage, callingPid, callingUid, callerInstantApp, resolvedType, requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode, resultData, resultExtras, ordered, sticky, false, userId);
3、下一步就是廣播的分發了。廣播的分發會根據廣播型別的不同而有所不同這裡只關注普通廣播的分發過程。普通廣播會先存入mParallelBroadcasts中,mParallelBroadcasts是一個存放即將執行的list集合,然後就是呼叫BroadcastQueue分發廣播
final ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<>(); //把之前建立的BroadcastRecord存入mParallelBroadcasts queue.enqueueParallelBroadcastLocked(r); //分發廣播 queue.scheduleBroadcastsLocked();
4、大致分發流程
final void processNextBroadcast(boolean fromMsg) { while (mParallelBroadcasts.size() > 0) { r = mParallelBroadcasts.remove(0); final int N = r.receivers.size(); for (int i=0; i<N; i++) { deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i); }
private void deliverToRegisteredReceiverLocked(BroadcastRecord r, BroadcastFilter filter, boolean ordered, int index) { performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver, new Intent(r.intent), r.resultCode, r.resultData, r.resultExtras, r.ordered, r.initialSticky, r.userId); }
void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver, Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) throws RemoteException { try { app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,data, extras, ordered, sticky, sendingUser, app.repProcState); }
可以到先是從mParallelBroadcasts依次取出待分發的廣播,然後經過呼叫最終通過廣播接收器所在程序的ApplicationThread進行分發。
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent, int resultCode, String dataStr, Bundle extras, boolean ordered, boolean sticky, int sendingUser, int processState) throws RemoteException { updateProcessState(processState, false); receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky, sendingUser); }
廣播接收端收到AMS的訊息後呼叫了IIntentReceiver.performReceive進行處理,此處的IIntentReceiver物件是我們在註冊廣播接收器時穿給AMS的。在IIntentReceiver.performReceive方法中取獲取了LoadedApk.ReceiverDispatcher然後呼叫其performReceive函式
public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) { final LoadedApk.ReceiverDispatcher rd; rd = mDispatcher.get(); if (rd != null) { rd.performReceive(intent, resultCode, data, extras, ordered, sticky, sendingUser); }
performReceive如下所示
public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) { final Args args = new Args(intent, resultCode, data, extras, ordered,sticky, sendingUser); ... if (intent == null || !mActivityThread.post(args.getRunnable())) { if (mRegistered && ordered) { IActivityManager mgr = ActivityManager.getService(); if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, "Finishing sync broadcast to " + mReceiver); args.sendFinished(mgr); } }
構造Args例項然後通過該例項獲取一個Runnable例項,並通過mActivityThread.post(args.getRunnable())執行,此處mActivityThread就是主執行緒的Handler
當主執行緒收到訊息處理時會呼叫Args例項獲取的Runnable物件,Args獲取的Runnable如下所示
public final Runnable getRunnable() { final BroadcastReceiver receiver = mReceiver; .... ClassLoader cl = mReceiver.getClass().getClassLoader(); intent.setExtrasClassLoader(cl); intent.prepareToEnterProcess(); setExtrasClassLoader(cl); receiver.setPendingResult(this); receiver.onReceive(mContext, intent);
我們看到它會通過ClassLoader構造一個BroadcastReceiver,然後呼叫其onReceive函式,至此我們的廣播接收器就收到廣播了。
參考連結:
https://blog.csdn.net/luoshengyang/article/details/6744448