發送廣播(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

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