Boardcast Receiver 源碼分析:廣播的動態(tài)注冊、發(fā)送和接收過程

動態(tài)注冊過程

ContextWrapper#registerReceiver(以下代碼基于API26)

動態(tài)注冊的過程從ContextWrapper的registerReceiver方法開始

    @Override
    public Intent registerReceiver(
        BroadcastReceiver receiver, IntentFilter filter) {
        return mBase.registerReceiver(receiver, filter);
    }

和Activity、Service一樣,ContextWrapper沒有做任何操作,而是把任務(wù)交給了ContextImpl(mBase的實(shí)現(xiàn)類型是ContextImpl)來完成。接著看ContextImpl的registerReceiver方法。

ContextImpl#registerReceiver

    @Override
    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
        return registerReceiver(receiver, filter, null, null);
    }
    
    @Override
    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
            String broadcastPermission, Handler scheduler) {
        return registerReceiverInternal(receiver, getUserId(),
                filter, broadcastPermission, scheduler, getOuterContext(), 0);
    }

又調(diào)用自己的registerReceiverInternal方法

ContextImpl#registerReceiverInternal

    private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
            IntentFilter filter, String broadcastPermission,
            Handler scheduler, Context context, int flags) {
            
        IIntentReceiver rd = null;
        
        //廣播接收器不為空時,獲取IIntentReceiver對象(IIntentReceiver是一個Binder接口)
        if (receiver != null) {
            if (mPackageInfo != null && context != null) {
                //...
                rd = mPackageInfo.getReceiverDispatcher(
                    receiver, context, scheduler,
                    mMainThread.getInstrumentation(), true);
            } else {
                //...
                rd = new LoadedApk.ReceiverDispatcher(
                        receiver, context, scheduler, null, true).getIIntentReceiver();
            }
        }
        
        try {
            //通過AMS的registerReceiver方法注冊廣播
            final Intent intent = ActivityManager.getService().registerReceiver(
                    mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
                    broadcastPermission, userId, flags);
            //...
            return intent;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

為什么需要先將BroadcastReceiver轉(zhuǎn)化為IIntentReceiver?

因?yàn)閺V播的注冊過程是一個進(jìn)程間通信的進(jìn)程,而BroadcastReceiver是Android的一個組件,不能直接跨進(jìn)程傳遞,而IIntentReceiver是一個Binder接口,可以跨進(jìn)程,所以需要先將BroadcastReceiver轉(zhuǎn)化為IIntentReceiver。

下面看一下IIntentReceiver的獲取,無論是哪種情況,最后都是調(diào)用LoadedApk.ReceiverDispatcher的getIIntentReceiver方法

LoadedApk.ReceiverDispatcher#getIIntentReceiver

    IIntentReceiver getIIntentReceiver() {
        return mIIntentReceiver;
    }

其中mIIntentReceiver是一個IIntentReceiver.Stub對象

    final IIntentReceiver.Stub mIIntentReceiver;

mIIntentReceiver是在ReceiverDispatcher的構(gòu)造方法中初始化的

    ReceiverDispatcher(BroadcastReceiver receiver, Context context,
            Handler activityThread, Instrumentation instrumentation,
            boolean registered) {
        //...

        mIIntentReceiver = new InnerReceiver(this, !registered);

        //...
    }

可以看到,最終IIntentReceiver的實(shí)現(xiàn)類是LoadedApk.ReceiverDispatcher.InnerReceiver

繼續(xù)看回注冊過程:

    //ActivityManager.getService()返回的是ActivityManagerService對象
    final Intent intent = ActivityManager.getService().registerReceiver(
            mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
            broadcastPermission, userId, flags);
    //...
    return intent;

可以看到,注冊過程的真正實(shí)現(xiàn)是AMS的registerReceiver方法

ActivityManagerService#registerReceiver

    public Intent registerReceiver(IApplicationThread caller, String callerPackage,
            IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
            int flags) {
        
        //...

        synchronized (this) {
            //...
            
            //獲取該receiver(IIntentReceiver對象)對應(yīng)的ReceiverList
            //ReceiverList繼承于ArrayList<BroadcastFilter>,是一個存儲BroadcastFilter的集合
            ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
            
            //若rl為空,則根據(jù)receiver創(chuàng)建對應(yīng)的ReceiverList,并使兩者建立映射關(guān)系存入HashMap中
            if (rl == null) {
                rl = new ReceiverList(this, callerApp, callingPid, callingUid,
                        userId, receiver);
                //...
                
                mRegisteredReceivers.put(receiver.asBinder(), rl);
            }   
            //...
            
            //BroadcastFilter繼承于IntentFilter
            BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
                    permission, callingUid, userId, instantApp, visibleToInstantApps);
            //將該BroadcastFilter添加進(jìn)ReceiverList中
            rl.add(bf);

            mReceiverResolver.addFilter(bf);

            //...
        }
    }

其中mRegisteredReceivers的定義如下:

    /**
     * Keeps track of all IIntentReceivers that have been registered for broadcasts.
     * Hash keys are the receiver IBinder, hash value is a ReceiverList.
     */
    final HashMap<IBinder, ReceiverList> mRegisteredReceivers = new HashMap<>();

可以看到,一個IIntentReceiver對應(yīng)著一個ReceiverList

最終,通過HashMap把IIntentReceiver與對應(yīng)的ReceiverList保存起來;而ReceiverList又把可以啟動該BroadcastReceiver的IntentFilter保存起來。

發(fā)送、接收普通廣播

以下是一個發(fā)送普通廣播的例子:

    Intent intent = new Intent();
    intent.setAction("FIRST_RECEIVER");     
    sendBroadcast(intent);      //發(fā)送廣播

仍然是從ContextWrapper開始,調(diào)用其sendBroadcast方法

ContextWrapper#sendBroadcast

    @Override
    public void sendBroadcast(Intent intent) {
        mBase.sendBroadcast(intent);
    }

依然是交給ContextImpl來處理,調(diào)用其sendBroadcast方法

ContextImpl#sendBroadcast

    @Override
    public void sendBroadcast(Intent intent) {
        //...
        try {
            intent.prepareToLeaveProcess(this);
            //調(diào)用AMS的broadcastIntent方法
            ActivityManager.getService().broadcastIntent(
                    mMainThread.getApplicationThread(), intent, resolvedType, null,
                    Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
                    getUserId());
        } //...
    }

ContextImpl也沒做什么,它直接調(diào)用AMS的broadcastIntent方法

ActivityManagerService#broadcastIntent

    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) {
        //...
        synchronized(this) {
            //...
            
            int res = broadcastIntentLocked(callerApp,
                    callerApp != null ? callerApp.info.packageName : null,
                    intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
                    requiredPermissions, appOp, bOptions, serialized, sticky,
                    callingPid, callingUid, userId);

            //...
            return res;
        }
    }

繼續(xù)調(diào)用broadcastIntentLocked方法

ActivityManagerService#broadcastIntentLocked

    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) {
        //...

        //添加這個標(biāo)志后,廣播不會發(fā)送給已經(jīng)停止的應(yīng)用
        intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);

        //...
       
        //判斷是否有添加FLAG_RECEIVER_REPLACE_PENDING標(biāo)記位
        //這個flag將會將之前的Intent替代掉。加了這個flag,在發(fā)送一系列的這樣的Intent之后, //中間有些Intent有可能在你還沒有來得及處理的時候,就被替代掉了。
        final boolean replacePending =
                (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
                
        //...

        if ((receivers != null && receivers.size() > 0)
                || resultTo != null) {
            //獲取AMS的廣播隊(duì)列
            BroadcastQueue queue = broadcastQueueForIntent(intent);
            //先將匹配的廣播接收器封裝成一個BroadcastRecord對象r
            BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                    callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
                    requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
                    resultData, resultExtras, ordered, sticky, false, userId);

            //...

            final BroadcastRecord oldRecord =
                    replacePending ? queue.replaceOrderedBroadcastLocked(r) : null;
            if (oldRecord != null) {
                // Replaced, fire the result-to receiver.
                //...
            } else {
                //將BroadcastRecord對象r插入廣播隊(duì)列queue中
                queue.enqueueOrderedBroadcastLocked(r);
                //在BroadcastRecord中發(fā)送廣播
                queue.scheduleBroadcastsLocked();
            }
            
        } //...

        return ActivityManager.BROADCAST_SUCCESS;
    }

該方法最終將滿足條件的廣播接收器封裝到BroadcastRecord中,并添加到廣播隊(duì)列BroadcastQueue中,通過BroadcastQueue的scheduleBroadcastsLocked方法發(fā)送給相應(yīng)的廣播接收器。接下來看一下BroadcastQueue的scheduleBroadcastsLocked方法。

BroadcastQueue#scheduleBroadcastsLocked

    public void scheduleBroadcastsLocked() {
        //...
        
        //mBroadcastsScheduled是一個布爾變量,表明是否發(fā)送過BROADCAST_INTENT_MSG消息
        if (mBroadcastsScheduled) { 
            return;
        }
        
        //發(fā)送BROADCAST_INTENT_MSG消息
        mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
        mBroadcastsScheduled = true;
    }

對BROADCAST_INTENT_MSG消息的處理是

    case BROADCAST_INTENT_MSG: {
        //...
        processNextBroadcast(true);
    } break;

可以看到,收到BROADCAST_INTENT_MSG消息后,執(zhí)行processNextBroadcast方法

BroadcastQueue#processNextBroadcast

    final void processNextBroadcast(boolean fromMsg) {
        synchronized(mService) {
            BroadcastRecord r;

            //...

            //如果是從BROADCAST_INTENT_MSG消息而來,重置mBroadcastsScheduled
            if (fromMsg) {
                mBroadcastsScheduled = false;
            }

            //發(fā)送無序廣播,無序廣播存儲在mParallelBroadcasts中
            while (mParallelBroadcasts.size() > 0) {
                r = mParallelBroadcasts.remove(0);
                
                //...

                final int N = r.receivers.size();
                for (int i=0; i<N; i++) {
                    Object target = r.receivers.get(i);
                    //該方法負(fù)責(zé)將廣播發(fā)送給特定的接收器
                    deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
                }
                addBroadcastToHistoryLocked(r);

            }
    }

可以看到,將廣播發(fā)送到對應(yīng)接收器的過程是通過deliverToRegisteredReceiverLocked方法實(shí)現(xiàn)的

BroadcastQueue#deliverToRegisteredReceiverLocked

    private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
            BroadcastFilter filter, boolean ordered, int index) {
        
        //...
        
        try {
            if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {
                //...
            } else {
                //通過該方法完成具體的發(fā)送過程
                performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
                        new Intent(r.intent), r.resultCode, r.resultData,
                        r.resultExtras, r.ordered, r.initialSticky, r.userId);
            }
            //...
        } //...
    }

繼續(xù)看performReceiveLocked方法

BroadcastQueue#performReceiveLocked

    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) {
                try {
                    //app.thread的實(shí)現(xiàn)是ActivityThread.ApplicationThread
                    app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                            data, extras, ordered, sticky, sendingUser, app.repProcState);

                } //...
            } //...
        } //...
    }

接著調(diào)用ApplicationThread的scheduleRegisteredReceiver方法

ActivityThread.ApplicationThread#scheduleRegisteredReceiver

    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);
        //調(diào)用InnerReceiver的performReceive方法
        receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
                sticky, sendingUser);
    }

ReceiverDispatcher.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;
        }

        @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) {
                rd = null;
            } else {
                rd = mDispatcher.get();
            }
            //...
            
            if (rd != null) {
                //調(diào)用LoadedApk.ReceiverDispatcher的performReceive方法
                rd.performReceive(intent, resultCode, data, extras,
                        ordered, sticky, sendingUser);
            } //...
        }
    }

繼續(xù)調(diào)用LoadedApk.ReceiverDispatcher的performReceive方法

LoadedApk.ReceiverDispatcher#performReceive

    public void performReceive(Intent intent, int resultCode, String data,
            Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
        
        //Args是LoadedApk.ReceiverDispatcher的內(nèi)部類
        final Args args = new Args(intent, resultCode, data, extras, ordered,
                sticky, sendingUser);
        
        //...
        
        //mActivityThread是一個Handler對象,指向ActivityThread中的handler對象
        if (intent == null || !mActivityThread.post(args.getRunnable())) {
            //...
        }
    }

在post里面執(zhí)行了Args的getRunnable方法,其實(shí)現(xiàn)如下

LoadedApk.ReceiverDispatcher.Args#getRunnable

    public final Runnable getRunnable() {
        return () -> {
            final BroadcastReceiver receiver = mReceiver;

            //...

            try {
                //...
                
                //回調(diào)了BoradcastReceiver的onReceive方法
                receiver.onReceive(mContext, intent);
            } //...
        };
    }

可以看到,最終在Args拋出的一個Runnable的run方法中回調(diào)了BoradcastReceiver的onReceive方法,并且是在廣播接收器的主線程中執(zhí)行的。

至此,普通廣播的發(fā)送及接收過程分析完畢。

參考

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容