Boardcast Receiver 源码分析:广播的动态注册、发送和接收过程

动态注册过程

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

动态注册的过程从ContextWrapper的registerReceiver方法开始

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

和Activity、Service一样,ContextWrapper没有做任何操作,而是把任务交给了ContextImpl(mBase的实现类型是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);
    }

又调用自己的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转化为IIntentReceiver?

因为广播的注册过程是一个进程间通信的进程,而BroadcastReceiver是Android的一个组件,不能直接跨进程传递,而IIntentReceiver是一个Binder接口,可以跨进程,所以需要先将BroadcastReceiver转化为IIntentReceiver。

下面看一下IIntentReceiver的获取,无论是哪种情况,最后都是调用LoadedApk.ReceiverDispatcher的getIIntentReceiver方法

LoadedApk.ReceiverDispatcher#getIIntentReceiver

    IIntentReceiver getIIntentReceiver() {
        return mIIntentReceiver;
    }

其中mIIntentReceiver是一个IIntentReceiver.Stub对象

    final IIntentReceiver.Stub mIIntentReceiver;

mIIntentReceiver是在ReceiverDispatcher的构造方法中初始化的

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

        mIIntentReceiver = new InnerReceiver(this, !registered);

        //...
    }

可以看到,最终IIntentReceiver的实现类是LoadedApk.ReceiverDispatcher.InnerReceiver

继续看回注册过程:

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

可以看到,注册过程的真正实现是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对象)对应的ReceiverList
            //ReceiverList继承于ArrayList,是一个存储BroadcastFilter的集合
            ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
            
            //若rl为空,则根据receiver创建对应的ReceiverList,并使两者建立映射关系存入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添加进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 mRegisteredReceivers = new HashMap<>();

可以看到,一个IIntentReceiver对应着一个ReceiverList

最终,通过HashMap把IIntentReceiver与对应的ReceiverList保存起来;而ReceiverList又把可以启动该BroadcastReceiver的IntentFilter保存起来。

发送、接收普通广播

以下是一个发送普通广播的例子:

    Intent intent = new Intent();
    intent.setAction("FIRST_RECEIVER");     
    sendBroadcast(intent);      //发送广播

仍然是从ContextWrapper开始,调用其sendBroadcast方法

ContextWrapper#sendBroadcast

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

依然是交给ContextImpl来处理,调用其sendBroadcast方法

ContextImpl#sendBroadcast

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

ContextImpl也没做什么,它直接调用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;
        }
    }

继续调用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) {
        //...

        //添加这个标志后,广播不会发送给已经停止的应用
        intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);

        //...
       
        //判断是否有添加FLAG_RECEIVER_REPLACE_PENDING标记位
        //这个flag将会将之前的Intent替代掉。加了这个flag,在发送一系列的这样的Intent之后, //中间有些Intent有可能在你还没有来得及处理的时候,就被替代掉了。
        final boolean replacePending =
                (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
                
        //...

        if ((receivers != null && receivers.size() > 0)
                || resultTo != null) {
            //获取AMS的广播队列
            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插入广播队列queue中
                queue.enqueueOrderedBroadcastLocked(r);
                //在BroadcastRecord中发送广播
                queue.scheduleBroadcastsLocked();
            }
            
        } //...

        return ActivityManager.BROADCAST_SUCCESS;
    }

该方法最终将满足条件的广播接收器封装到BroadcastRecord中,并添加到广播队列BroadcastQueue中,通过BroadcastQueue的scheduleBroadcastsLocked方法发送给相应的广播接收器。接下来看一下BroadcastQueue的scheduleBroadcastsLocked方法。

BroadcastQueue#scheduleBroadcastsLocked

    public void scheduleBroadcastsLocked() {
        //...
        
        //mBroadcastsScheduled是一个布尔变量,表明是否发送过BROADCAST_INTENT_MSG消息
        if (mBroadcastsScheduled) { 
            return;
        }
        
        //发送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消息后,执行processNextBroadcast方法

BroadcastQueue#processNextBroadcast

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

            //...

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

            //发送无序广播,无序广播存储在mParallelBroadcasts中
            while (mParallelBroadcasts.size() > 0) {
                r = mParallelBroadcasts.remove(0);
                
                //...

                final int N = r.receivers.size();
                for (int i=0; i

可以看到,将广播发送到对应接收器的过程是通过deliverToRegisteredReceiverLocked方法实现的

BroadcastQueue#deliverToRegisteredReceiverLocked

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

继续看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的实现是ActivityThread.ApplicationThread
                    app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                            data, extras, ordered, sticky, sendingUser, app.repProcState);

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

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

ReceiverDispatcher.InnerReceiver

    final static class InnerReceiver extends IIntentReceiver.Stub {
        final WeakReference mDispatcher;
        final LoadedApk.ReceiverDispatcher mStrongRef;

        InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
            mDispatcher = new WeakReference(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) {
                //调用LoadedApk.ReceiverDispatcher的performReceive方法
                rd.performReceive(intent, resultCode, data, extras,
                        ordered, sticky, sendingUser);
            } //...
        }
    }

继续调用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的内部类
        final Args args = new Args(intent, resultCode, data, extras, ordered,
                sticky, sendingUser);
        
        //...
        
        //mActivityThread是一个Handler对象,指向ActivityThread中的handler对象
        if (intent == null || !mActivityThread.post(args.getRunnable())) {
            //...
        }
    }

在post里面执行了Args的getRunnable方法,其实现如下

LoadedApk.ReceiverDispatcher.Args#getRunnable

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

            //...

            try {
                //...
                
                //回调了BoradcastReceiver的onReceive方法
                receiver.onReceive(mContext, intent);
            } //...
        };
    }

可以看到,最终在Args抛出的一个Runnable的run方法中回调了BoradcastReceiver的onReceive方法,并且是在广播接收器的主线程中执行的。

至此,普通广播的发送及接收过程分析完毕。

参考

  • 《Android开发艺术探索》
  • BroadcastReceiver源码解析(二)

你可能感兴趣的:(Boardcast Receiver 源码分析:广播的动态注册、发送和接收过程)