Android BroadcastReceiver的工作流程源码分析(8.0)

来源:互联网 发布:nginx location server 编辑:程序博客网 时间:2024/06/03 20:20

一,写在前面

       本篇文章会从源码角度分析广播的工作流程,具体来说是分为两部分:广播的注册,发送广播。在阅读本篇文章前,建议先了解Activity,Service相关的工作流程。本篇文章将不再分析工作流程中的重复细节,参考文章:
Android Activity的启动流程源码解析(8.0) 
Android Service的启动流程源码分析(8.0)
Android Service的绑定流程源码分析(8.0)

二,广播的注册,交给ContextImpl

        广播的注册分为静态注册,以及动态注册。静态注册是在xml中配置<receiver>节点,在应用程序启动后会解析xml文件,具体的注册流程是交给PackagerManagerService来处理。本篇文章主要分析广播的动态注册,也就是在Java代码中调用registerReceiver方法来注册广播,开发中具体的使用这里不再介绍。
       不管是在Activity,还是Service中注册广播,都是调用ContextWrapper$registerReceiver方法。其中,ContextWrapper是Context的一个子类,在抽象类Context中定义了抽象方法registerReceiver,具体实现在子类ContextWrapper中。
       查看ContextWrapper$registerReceiver源码:
@Override    public Intent registerReceiver(        BroadcastReceiver receiver, IntentFilter filter) {        return mBase.registerReceiver(receiver, filter);    }
       第4行,变量mBase是Context类型,而Context是一个抽象类,其实mBase的具体实现类是ContextImpl。至于具体原因,可以查看文章 Android Activity的启动流程源码解析(8.0) ,这里不再重复阐述。

       查看ContextImpl相关源码:
    @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);    }    //继续查看...    private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,            IntentFilter filter, String broadcastPermission,            Handler scheduler, Context context, int flags) {        IIntentReceiver rd = null;        if (receiver != null) {            if (mPackageInfo != null && context != null) {                if (scheduler == null) {                    scheduler = mMainThread.getHandler();                }                rd = mPackageInfo.getReceiverDispatcher(                    receiver, context, scheduler,                    mMainThread.getInstrumentation(), true);            } else {                if (scheduler == null) {                    scheduler = mMainThread.getHandler();                }                rd = new LoadedApk.ReceiverDispatcher(                        receiver, context, scheduler, null, true).getIIntentReceiver();            }        }        //...code            final Intent intent = ActivityManager.getService().registerReceiver(                    mMainThread.getApplicationThread(), mBasePackageName, rd, filter,                    broadcastPermission, userId, flags);                             //...code    }
       第17行,ContextImpl$registerReceiver有多个重载方法,但最终都会调用ContextImpl$registerReceiverInternal方法。
       第24行,mMainThread是一个ActivityThread类型的变量,它的实例化在ContextImpl的构造方法中。mMainThread.getHandler()返回一个H类型的对象,H是ActivityThread的内部类,继承了Handler。值得一提的是,在启动Activity,Service的工作流程中,都会创建一个上下文环境,也就是会创建ContextImpl对象。具体分析,见文章 Android Activity的启动流程源码解析(8.0) ,这里不再重复阐述。
       
       第26行,变量mPackageInfo是一个LoadedApk的变量,这里是将BroadcastReceiver对象封装到ReceiverDispatcher中,并最终返回IIntentReceiver类型的对象。有意思的是,ReceiverDispatcher与绑定服务中的ServiceDispatcher比较类似,都是将组件对象进行封装,并返回一个Binder对象,用于实现组件对象在进程间的通信。      
       由于逻辑与绑定服务流程中的LoadedApk$ServiceDispacher类似,具体分析可参考文章 Android Service的绑定流程源码分析(8.0) 。这里rd返回IIntentReceiver类型的对象,它的具体实现类是LoadedApk$ReceiverDispatcher$InnerReceiver,其具体结构:final static class InnerReceiver extends IIntentReceiver.Stub 。
       第33行,当mPackageInfo为null时,给rd赋值,做的事情与前面讲到的第26行一样。

       第40行,ActivityManager.getService()返回一个IActivityManager的代理对象,调用其registerReceiver方法会向系统服务发送一个请求,基于Binder机制,会调用ActivityManagerService$ActivityManage方法。具体分析,见文章 Android Activity的启动流程源码解析(8.0) ,这里不再重复阐述。

三,广播的注册,交给ActivityManagerService处理

       查看ActivityManagerService$ActivityManage方法源码:
public Intent registerReceiver(IApplicationThread caller, String callerPackage,            IIntentReceiver receiver, IntentFilter filter, String permission, int userId,            int flags) {        //...code                if (callerApp != null && (callerApp.thread == null                    || callerApp.thread.asBinder() != caller.asBinder())) {                // Original caller already died                return null;            }            ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());            if (rl == null) {                rl = new ReceiverList(this, callerApp, callingPid, callingUid,                        userId, receiver);                if (rl.app != null) {                    rl.app.receivers.add(rl);                } else {                    try {                        receiver.asBinder().linkToDeath(rl, 0);                    } catch (RemoteException e) {                        return sticky;                    }                    rl.linkedToDeath = true;                }                mRegisteredReceivers.put(receiver.asBinder(), rl);            }     //...code            BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,                    permission, callingUid, userId, instantApp, visibleToInstantApps);            rl.add(bf);            if (!bf.debugCheck()) {                Slog.w(TAG, "==> For Dynamic broadcast");            }            mReceiverResolver.addFilter(bf);    //...code            }
       第8行,caller是一个IApplicationThread类型的变量,是一个Binder对象,具体源码见文章 Android Activity的启动流程源码解析(8.0) ,这里会检查它的对应的Binder对象。
       
       第12行,变量mRegisteredReceivers的定义: HashMap<IBinder, ReceiverList> mRegisteredReceivers = new HashMap<>()。
       key:receiver.asBinder()返回的是IIntentReceiver对象对应的Binder对象。IIntentReceiver前面已经分析过了,它封装了BroadcastReceiver对象,且是一个Binder对象。    
       value:ReceiverList类型的对象,它是一个存储BroadcastFilter对象的List集合。结构:class ReceiverList extends ArrayList<BroadcastFilter> implements IBinder.DeathRecipient。

       第14行,创建ReceiverList对象,注意最后一个参数receiver,说明ReceiverList封装了InnerReceiver对象。
       第31行,BroadcastFilter结构:class BroadcastFilter extends IntentFilter 。BroadcastFilter对象中封装了ReceiverList对象,IntentFilter对象。
       第37行,mReceiverResolver是一个IntentResolver类型的变量,该类里面维护了集合,并调用addFilter方法将bf存储起来。
       
       也就是说,注册广播的就是将InnerReceiver对象,IntentFilter对象封装在类BroadcastFilter中,并最终将BroadcastFilter对象存储在变量mReceiverResolver中。值得一提的是,在发送广播的流程中,会取出变量mReceiverResolver中存储的广播接受者相关的数据。动态注册广播的分析,到此就结束了~

四,发送广播,交给ContextImpl处理

       与动态注册广播一样,发送广播实际上调用的ContextWrapper$sendBroadcast方法;
       查看ContextWrapper$sendBroadcast方法源码:
@Override    public void sendBroadcast(Intent intent) {        mBase.sendBroadcast(intent);    }
       第3行,变量mBase实现类是ContextImpl,与动态注册广播一样的。
       
       查看ContextImpl$sendBroadcast方法源码:
public void sendBroadcast(Intent intent) {    //...    ActivityManager.getService().broadcastIntent(                    mMainThread.getApplicationThread(), intent, resolvedType, null,                    Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,                    getUserId());       //... }
       ActivityManager.getService()返回一个IActivityManager接口的代理对象,向系统服务AMS发起一个请求,会调用ActivityManagerService$broadcastIntent方法。具体细节不再分析,动态注册广播时已经提到。

五,发送广播,交给ActivityManagerService处理

       查看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) {            intent = verifyBroadcastLocked(intent);        //...            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;        }    }
       第9行,主要对intent的flag进行检查;
       第13行,查看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) {    //...    // By default broadcasts do not go to stopped apps.            intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);    //...    registeredReceivers = mReceiverResolver.queryIntent(intent,                        resolvedType, false /*defaultOnly*/, userId);            //...    BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,                    callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,                    requiredPermissions, appOp, brOptions, registeredReceivers, resultTo,                    resultCode, resultData, resultExtras, ordered, sticky, false, userId);    //...    queue.enqueueParallelBroadcastLocked(r);            queue.scheduleBroadcastsLocked();        //...}
       第10行,设置flag为FLAG_EXCLUDE_STOPPED_PACKAGES时,广播不会发送给已经停止的应用。本篇文章是基于8.0的源码,其实从Android3.1开始,发送广播会默认添加flag为FLAG_EXCLUDE_STOPPED_PACKAGES,禁止向停止应用发送广播,为了避免调用已经停止的应用。另外,若想将广播发送给已经停止的应用,也可以设置flag为FLAG_INCLUDE_STOPPED_PACKAGES。值得一提的是,应用处于停止状态意思是:应用安装后没有启动,或被手动,其他应用强行停止了。

       第14行,前面分析广播注册流程,最后有提到变量mReceiverResolver,它存储了BroadcastFilter对象,也就是存放了广播接受者相关的信息。调用IntentResolver$queryIntent方法用于获取与该intent相匹配的广播接受者,返回的是一个List集合,因此变量registeredReceivers是一个List类型变量。

       第21行,将变量registeredReceivers封装在BroadcastRecord对象中。
       第26行,变量queue是一个BroadcastQueue类型的对象,BroadcastQueue queue = broadcastQueueForIntent(intent)。
       查看BroadcastQueue$enqueueParallelBroadcastLocked方法源码:
public void enqueueParallelBroadcastLocked(BroadcastRecord r) {        mParallelBroadcasts.add(r);        enqueueBroadcastHelper(r);    }
       第2行,变量mParallelBroadcasts是一个ArrayList类型的对象,用于存放BroadcastRecord对象。ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<>()。后面,会取出mParallelBroadcasts集合中的数据,完成广播的接受。

       继续回到ActivityManagerService$broadcastIntentLocked的第27行,调用了queue.scheduleBroadcastsLocked(),这个是重点入口。

六,广播的接收

       查看BroadcastQueue相关方法源码:
public void scheduleBroadcastsLocked() {//...codemHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));//...code}//继续查看...private final class BroadcastHandler extends Handler {        public BroadcastHandler(Looper looper) {            super(looper, null, true);        }        @Override        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);                } break;                //...code            }        }    }//继续查看...final void processNextBroadcast(boolean fromMsg) {    synchronized(mService) {         BroadcastRecord r;   //...=     if (fromMsg) {                mBroadcastsScheduled = false;         }            // First, deliver any non-serialized broadcasts right away.            while (mParallelBroadcasts.size() > 0) {                r = mParallelBroadcasts.remove(0);                r.dispatchTime = SystemClock.uptimeMillis();                r.dispatchClockTime = System.currentTimeMillis();                //...                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);                }                //...            }                   //...            }}
       第4行,发送一个what为BROADCAST_INTENT_MSG的消息;
       第19行,处理what为BROADCAST_INTENT_MSG的消息;
       第22行,继续调用processNextBroadcast方法;

       第44行,变量mParallelBroadcasts前面已经讲过,是一个ArrayList集合,存储了BroadcastRecord对象,而BroadcastRecord对象封装了广播接受者相关的信息;
       第45行,取出index为0的BroadcastRecord对象,并将该对象删除;
       第51行,r.receivers返回一个List集合,里面存放了BroadcastFilter对象。注册广播流程中已经分析过BroadcastFilter对象,它封装了广播接受者相关的信息。
       第55行,对r.receivers对应的集合进行遍历,完成所有匹配的BroadcastReceiver对广播的接受。然后会调用deliverToRegisteredReceiverLocked方法,这个是一个重要入口。

       查看BroadcastQueue$deliverToRegisteredReceiverLocked方法源码:
private void deliverToRegisteredReceiverLocked(BroadcastRecord r,            BroadcastFilter filter, boolean ordered, int index) {//...codeperformReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,                        new Intent(r.intent), r.resultCode, r.resultData,                        r.resultExtras, r.ordered, r.initialSticky, r.userId);//...code}//继续查看...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);    //...    }     //... }//...}
       第21,22行,对app,app.thread进行判空检查;
       第26行,app.thread返回IApplicationThread接口的代理对象,最终会调用ApplicationThread$scheduleRegisteredReceiver方法。关于ApplicationThread的描述,这里不能理解的,请参考文章 Android Activity的启动流程源码解析(8.0)  ,这里不再重复阐述。

       查看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);            receiver.performReceive(intent, resultCode, dataStr, extras, ordered,                    sticky, sendingUser);}
       第5行,变量receiver是一个IIntentReceiver类型的对象,在注册广播的流程中提到过IIntentReceiver,它的具体实现类是LoadedApk$ReceiverDispatcher$InnerReceiver。其实InnerReceiver是一个Binder接口,封装BroadcastReceiver对象后,使组件对象可以在进程间传递。
       
       查看LoadedApk$ReceiverDispatcher$InnerReceiver$performReceive方法源码:
    @Override    public void performReceive(Intent intent, int resultCode, String data,    Bundle extras, boolean ordered, boolean sticky, int sendingUser) {//...final LoadedApk.ReceiverDispatcher rd;//...rd.performReceive(intent, resultCode, data, extras,                            ordered, sticky, sendingUser);//...            }
       第10行,调用LoadedApk$ReceiverDispatcher$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);//...if (intent == null || !mActivityThread.post(args.getRunnable())) {//...}}
       第10行,变量mActivityThread是ActivityThread$H类型的对象,它继承了Handler,接受广播的操作是在Handler所在的线程中执行,也就是在ActivityThread主线程中执行。
       args.getRunnable()返回一个Runnable接口;
       
       查看LoadedApk$ReceiverDispatcher$Args源码如下:
final class Args extends BroadcastReceiver.PendingResult {    //...    public final Runnable getRunnable() {return () -> {    final BroadcastReceiver receiver = mReceiver;        //...        receiver.onReceive(mContext, intent);        //...       };    }}
       第10行,回调BroadcastReceiver$onReceive方法,于是前面注册的广播接受者,就接收到发送的广播了~

七,最后

       本篇文章,从动态注册广播,发送广播,接收广播来分析BroadcastReceiver的工作机制。
       阅读本篇文章前,建议先阅读如下文章:
       Android Activity的启动流程源码解析(8.0) 
       Android Service的启动流程源码分析(8.0)
       Android Service的绑定流程源码分析(8.0)














       

       






       
       
       
原创粉丝点击