美文网首页
Boardcast Receiver 源码分析:广播的动态注册、

Boardcast Receiver 源码分析:广播的动态注册、

作者: MrFengZH | 来源:发表于2019-06-06 15:47 被阅读0次

    动态注册过程

    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>,是一个存储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<IBinder, ReceiverList> 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<N; i++) {
                        Object target = r.receivers.get(i);
                        //该方法负责将广播发送给特定的接收器
                        deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
                    }
                    addBroadcastToHistoryLocked(r);
    
                }
        }
    

    可以看到,将广播发送到对应接收器的过程是通过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<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) {
                    //调用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方法,并且是在广播接收器的主线程中执行的。

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

    参考

    相关文章

      网友评论

          本文标题:Boardcast Receiver 源码分析:广播的动态注册、

          本文链接:https://www.haomeiwen.com/subject/ueruxctx.html