广播 Broadcast
属于 Android
四大组件之一,通过观察者模式,用于实现进程间的异步通信。
广播的实现机制是观察者模式;消息发布/订阅模式的事件驱动模型,消息的生产者发布事件,而使用者订阅感兴趣的事件。Broadcast
机制和 Binder
机制不一样的地方在于:广播的发送者和接收者事先是不需要知道对方的存在的,这也是观察者模式的特点,显而易见的优点是系统的各个组件可以松耦合地组织在一起,所有的广播发送和接收都是通过系统 AMS
来调度的,它充当了广播总线的功能。
基础 广播实现进程间异步交互:进程间通信时通过 Binder
来实现的,异步通信是通过 Handler
实现。
广播接收器的分类
静态注册广播接收器:Manifest-declared receivers
在 AndroidManifest.xml
文件中通过 <receiver>
声明的广播接收器。
动态注册广播接收器:Context-registered receivers
通过 registerReceiver
注册的广播接收器。
广播的分类
普通广播 通过 sendBroadcast
发出的广播。
有序广播 通过 sendOrderedBroadcast
发出的广播;有序广播对应的广播接收器存在优先级关系,优先级越高越先收到广播。有序广播还可以有回调广播接收器,即广播匹配的所有广播接收器处理完毕后,系统会再向广播发送者,发回这个回调。
粘性广播 通过 sendStickyBroadcast
发出的广播。粘性广播发送后,系统会把代表这个广播的 Intent
保存下来,如果后面在动态注册相同 Action
的广播接收器时,系统就将最后发出的粘性广播重新发送给这个广播接收器。也就是说,尽管广播早就发送处理完毕了,但是后续如果有新注册的广播接收器能匹配这个广播,还是会响应广播事件的。但是粘性广播从 Android 5.0
开始就将相关系统接口全部标注为 @Deprecated
。它们不提供安全性(任何人都可以访问它们),没有保护(任何人都可以修改它们)以及许多其他问题。所以 Android
平台已经弃用,本文也不做介绍。
广播的标记 根据发送广播 Intent
设置的标记来区分:
FLAG_RECEIVER_FOREGROUND
表示广播为前台广播 ,允许接收者以前台的优先级运行,有更短的时间间隔。默认情况下广播都是后台广播
FLAG_RECEIVER_REPLACE_PENDING
表示新的广播会替换掉那些已存在的相同广播。相同的定义是通过 Intent.filterEquals
方法对两个广播的 Intent
比较,当匹配到相同的,新的广播和对应的接收器会将待发送的广播列表中已存在的替换掉,在列表中保留同样的位置。这个标志通常被粘性广播使用,只保证将最新的广播的值传递给接收器。
广播的 ANR
前台广播的 ANR
时间是 10 秒,后台广播是 60 秒。因为默认为后台广播,所以通常情况下,需要在 60 秒内处理完所有的广播事件。广播的 ANR
只会出现在有序处理的广播队列中(包含有序广播和静态注册的广播接收器匹配的普通广播)中 。
1 2 3 4 static final int BROADCAST_FG_TIMEOUT = 10 *1000 ;static final int BROADCAST_BG_TIMEOUT = 60 *1000 ;
相关类文件 速查表 1 2 3 4 5 6 7 8 9 10 11 12 13 14 framework/base ./core/java/android/app/ContextImpl.java ./core/java/android/app/ActivityThread.java ./core/java/android/app/LoadedApk.java ./core/java/android/app/BroadcastOptions.java ./core/java/android/content/IIntentReceiver.aidl ./core/java/android/content/pm/PackageParser.java ./core/java/android/content/BroadcastReceiver.java ./services/core/java/com/android/server/am/BroadcastRecord.java ./services/core/java/com/android/server/am/ReceiverList.java ./services/core/java/com/android/server/am/BroadcastFilter.java ./services/core/java/com/android/server/am/BroadcastQueue.java ./services/core/java/com/android/server/am/ActivityManagerService.java ./services/core/java/com/android/server/pm/PackageManagerService.java
类简介
BroadCastReceiver
广播接收器,用于处理接收的每个广播事件。
IIntentReceiver
是 AIDL
文件,每个 BroadCastReceiver
都会转换为一个 IIntentReceiver
,用来跨进程传递数据。
LoadedApk.ReceiverDispatcher
广播接收发布器,BroadCastReceiver
都是在这转换为 IIntentReceiver
的。每个动态注册的广播接收器 BroadcastReceiver
都对应一个 LoadedApk.ReceiverDispatcher
,最终都是在这进行响应调用 onReceive
的。
BroadcastFilter
是 IntentFilter
的子类,广播过滤器,用于匹配广播 Intent
;包含广播接收者相关信息,权限等。只有动态注册广播广播接收器会用到。
ReceiverList
是 ArrayList
的子类,是一个集合用来存储 BroadcastFilter
。记录广播接收器相关信息等,只有动态注册的广播接收器会用到,每个 BroadCastReceiver
对应一个 ReceiverList
,而每个 ReceiverList
可以包含多个 BroadcastFilter
,表示能够监听多个广播。
BroadcastRecord
继承了 Binder
,用来跨进程传递数据。发送的每个广播 Intent
,最后都会对应一个 BroadcastRecord
;它记录了广播的发送时间,发送者,接受者 ,广播携带的数据,回调,所在 BroadcastQueue
等等。
BroadcastQueue
广播队列,有两个 ArrayList<BroadcastRecord>
用于存储 BroadcastRecord
分别是:mParallelBroadcasts
存储并行处理的广播;mOrderedBroadcasts
存储有序处理的广播。
ContextImpl
广播发送,广播接收器动态注册的入口。
ActivityThread
应用主线程,广播发送过程都是由它进入系统进程 AMS
,广播接收器响应事件是有系统 AMS
进入它。
ActivityManagerService
AMS
系统四大组件大管家,类似广播总线:管理广播接收器的注册,管理广播的发送到匹配的广播接收器中处理。
PackageParser
包解析类,会从 AndroidManifest.xml
中解析出静态注册的广播接收器。
PackageManagerService
PMS
系统包管家,负责静态注册广播接收器的存储,查询。
BroadcastFilter
类详解BroadcastFilter
继承了 IntentFilter
类,广播信息过滤器,即动态注册广播接收器时,注册的是哪个广播过滤器。
源码分析 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 final class BroadcastFilter extends IntentFilter { final ReceiverList receiverList; final String packageName; final String requiredPermission; final int owningUid; final int owningUserId; BroadcastFilter(IntentFilter _filter, ReceiverList _receiverList, String _packageName, String _requiredPermission, int _owningUid, int _userId) { super (_filter); receiverList = _receiverList; packageName = _packageName; requiredPermission = _requiredPermission; owningUid = _owningUid; owningUserId = _userId; } public void dump (PrintWriter pw, String prefix) {...} public void dumpBrief (PrintWriter pw, String prefix) {...} public void dumpInReceiverList (PrintWriter pw, Printer pr, String prefix) {...} void dumpBroadcastFilterState (PrintWriter pw, String prefix) {...} public String toString () {...}
成员变量
receiverList
:当前对象属于哪个接收列表
packageName
:动态注册广播发起者的包名
requiredPermission
:设置发送广播时需要的权限
owningUid
:动态注册广播发起者 Uid
owningUserId
:动态注册广播发起者 UserId
这里简单介绍下 uid, userId
的区别:
uid
是 Linux
下的概念,表示 Linux
系统下的用户 ID
。
userId
是 Android
的多用户概念,从 4.2 开始系统支持多用户登录,记录登录用户的 ID
;不支持多用户登录的系统上,这个值是唯一的。多用户支持是在 frameworks/base/core/res/res/values/config.xml
文件中,config_multiuserMaximumUsers
值来决定的。
ReceiverList
类详解ReceiverList
继承了 ArrayList
,本质上是一个数据集合,数据类型为 BroadcastFilter
。动态注册广播接收器时,每个广播接收器 BroadCastReceiver
对应一个 ReceiverList
,记录了一系列 BroadcastFilter
的列表,表示这个广播接收器注册了一个或多个广播过滤器。
源码分析 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 final class ReceiverList extends ArrayList <BroadcastFilter > implements IBinder .DeathRecipient { final ActivityManagerService owner; public final IIntentReceiver receiver; public final ProcessRecord app; public final int pid; public final int uid; public final int userId; BroadcastRecord curBroadcast = null ; boolean linkedToDeath = false ; String stringName; ReceiverList(ActivityManagerService _owner, ProcessRecord _app, int _pid, int _uid, int _userId, IIntentReceiver _receiver) { owner = _owner; receiver = _receiver; app = _app; pid = _pid; uid = _uid; userId = _userId; } public boolean equals (Object o) {return this == o;} public int hashCode () {return System.identityHashCode(this );} public void binderDied () { linkedToDeath = false ; owner.unregisterReceiver(receiver); } void dumpLocal (PrintWriter pw, String prefix) {...} void dump (PrintWriter pw, String prefix) {...} public String toString () {...}
成员变量
ActivityManagerService owner
: AMS
对象
IIntentReceiver receiver
:当前 ReceiverList
对应的 IIntentReceiver
ProcessRecord app
:动态注册广播发起者进程相关信息
pid
:动态注册广播发起者进程 Id
uid
:动态注册广播发起者 uid
userId
:动态注册广播发起者 userId
BroadcastRecord curBroadcast
:动态注册的广播,其详细信息
linkedToDeath
:Binder
通信机制是否断开
stringName
:ReceiverList
转换成的字符串
BroadCastReceiver
类详解BroadCastReceiver
广播接收器,用来处理监听的广播事件。BroadcastReceiver
是抽象类,抽象方法为 onReceive
,注册广播接收器前,需要在其子类中实现。
PendingResult
类PendingResult
是广播接收器待处理的结果类,是异步结果类;简要介绍下这个类存在的意义: 通常情况下,UI
主线程阻塞超过 5 秒就会产生 ANR
,更不用说卡顿现象 UI Jank
;所以广播接收器中如果有耗时工作(比如磁盘读写,网络下载等),需要及时切换到后台工作线程中执行;而 PendingResult
就存储了广播处理器接收到广播所有相关信息,将 PendingResult
对象传递到后台工作线程完成广播处理,处理完后需要调用 PendingResult.finish()
通过系统该广播接收器已经处理完毕。 PendingResult
类有两个注意事项:
PendingResult
类中的状态不是线程安全的 ,使用时将整个对象交给后台工作线程,避免并发竞争,该线程将负责设置结果并最终调用 finish()
系统中关于广播接收器的 ANR
:前台广播接收器允许运行时间大概是 10 秒,后台广播是 60 秒,如果广播处理器没有处理完毕就会产生 ANR
。注意这个过程的计算时间是:从广播分发到广播处理器,直到广播处理器通知系统处理完毕的总时间。即使通过 PendingResult
切换到后台工作线程,直到调用 PendingResult.finish()
,这整个过程都受到了这个 ANR
时间的限制。所以长时间的工作是不能放到 BroadCastReceiver
中来实现的,PendingResult
仅仅是多争取到了几秒钟
PendingResult
类的两个子类PendingResult
类的构造方法是 @hide
隐藏的,通常在 BroadcastReceiver.onReceive()
中调用 goAsync()
返回得到;而实际构造是在其子类中,静态注册广播和动态注册广播对应不同的子类:
ActivityThread.ReceiverData
对应静态注册广播 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 static final class ReceiverData extends BroadcastReceiver .PendingResult { public ReceiverData (Intent intent,int resultCode,String resultData, Bundle resultExtras, boolean ordered, boolean sticky, IBinder token, int sendingUser) { super (resultCode, resultData, resultExtras, TYPE_COMPONENT, ordered, sticky,token, sendingUser, intent.getFlags()); this .intent = intent; } Intent intent; ActivityInfo info; CompatibilityInfo compatInfo; public String toString () {...} }
LoadedApk.ReceiverDispatcher.Args
对应动态注册广播 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 final class Args extends BroadcastReceiver .PendingResult implements Runnable { private Intent mCurIntent; private final boolean mOrdered; private boolean mDispatched; public Args (Intent intent, int resultCode, String resultData, Bundle resultExtras, boolean ordered, boolean sticky, int sendingUser) { super (resultCode, resultData, resultExtras, mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, ordered, sticky, mIIntentReceiver.asBinder(), sendingUser, intent.getFlags()); mCurIntent = intent; mOrdered = ordered; } public void run () {...} }
PendingResult
类源码分析PendingResult
对应的广播类型有三种:
TYPE_COMPONENT
:静态注册广播
TYPE_REGISTERED
:动态注册广播
TYPE_UNREGISTERED
:取消广播注册
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 public static class PendingResult { public static final int TYPE_COMPONENT = 0 ; public static final int TYPE_REGISTERED = 1 ; public static final int TYPE_UNREGISTERED = 2 ; final int mType; final boolean mOrderedHint; final boolean mInitialStickyHint; final IBinder mToken; final int mSendingUser; final int mFlags; int mResultCode; String mResultData; Bundle mResultExtras; boolean mAbortBroadcast; boolean mFinished; public PendingResult (int resultCode, String resultData, Bundle resultExtras, int type, boolean ordered, boolean sticky, IBinder token, int userId, int flags) { mResultCode = resultCode; mResultData = resultData; mResultExtras = resultExtras; mType = type; mOrderedHint = ordered; mInitialStickyHint = sticky; mToken = token; mSendingUser = userId; mFlags = flags; } public final void setResultCode (int code) {...} public final int getResultCode () {...} public final void setResultData (String data) {...} public final String getResultData () {...} public final void setResultExtras (Bundle extras) {...} public final Bundle getResultExtras (boolean makeMap) {...} public final void setResult (int code, String data, Bundle extras) {...} public int getSendingUserId () {...} public final boolean getAbortBroadcast () {return mAbortBroadcast;} public final void abortBroadcast () { checkSynchronousHint(); mAbortBroadcast = true ; } public final void clearAbortBroadcast () { mAbortBroadcast = false ; } public final void finish () { if (mType == TYPE_COMPONENT) { final IActivityManager mgr = ActivityManager.getService(); if (QueuedWork.hasPendingWork()) { QueuedWork.queue(new Runnable() { @Override public void run () { ... sendFinished(mgr); } }, false ); } else { ... sendFinished(mgr); } } else if (mOrderedHint && mType != TYPE_UNREGISTERED) { ... final IActivityManager mgr = ActivityManager.getService(); sendFinished(mgr); } } public void setExtrasClassLoader (ClassLoader cl) { if (mResultExtras != null ) { mResultExtras.setClassLoader(cl); } } public void sendFinished (IActivityManager am) { synchronized (this ) { if (mFinished) { throw new IllegalStateException("..." ); } mFinished = true ; try { if (mResultExtras != null ) { mResultExtras.setAllowFds(false ); } if (mOrderedHint) { am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras, mAbortBroadcast, mFlags); } else { am.finishReceiver(mToken, 0 , null , null , false , mFlags); } } catch (RemoteException ex) { } } } ... }
BroadcastReceiver
源码分析1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 public abstract class BroadcastReceiver { private PendingResult mPendingResult; ... public static class PendingResult {...} public BroadcastReceiver () {} public abstract void onReceive (Context context, Intent intent) ; public final PendingResult goAsync () { PendingResult res = mPendingResult; mPendingResult = null ; return res; } public IBinder peekService (Context myContext, Intent service) {...} public final void setPendingResult (PendingResult result) { mPendingResult = result; } public final PendingResult getPendingResult () { return mPendingResult; } public final String getResultData () { return mPendingResult != null ? mPendingResult.mResultData : null ; } public final void setResultExtras (Bundle extras) { checkSynchronousHint(); mPendingResult.mResultExtras = extras; } public final void setResultCode (int code) {...} public final int getResultCode () {...} public final Bundle getResultExtras (boolean makeMap) {...} public final void setResult (int code, String data, Bundle extras) {...} public int getSendingUserId () {...} public final boolean getAbortBroadcast () { return mPendingResult != null ? mPendingResult.mAbortBroadcast : false ; } public final void abortBroadcast () { checkSynchronousHint(); mPendingResult.mAbortBroadcast = true ; } public final void clearAbortBroadcast () { if (mPendingResult != null ) { mPendingResult.mAbortBroadcast = false ; } } public final boolean isOrderedBroadcast () {...} public final boolean isInitialStickyBroadcast () {...} ... }
BroadcastReceiver
重要方法BroadcastReceiver
大部分数据存储都是通过 PendingResult
实例来保存的。
onReceive
抽象方法,子类必须实现;广播接收器处理的入口。
goAsync
异步广播,返回 PendingResult
实例,进入后台线程处理;处理完毕后必须调用 PendingResult.finish()
结束。
abortBroadcast
如果广播接收器收到的是有序广播,则终止有序广播继续向下传递。
IIntentReceiver
详解IIntentReceiver
是一个 AIDL
文件,所以 IIntentReceiver
接口继承了 Binder
机制中的 IInterface
,表示服务端拥有的能力或者说能提供的功能。 IIntentReceiver
声明的方法,是在 LoadedApk.ReceiverDispatcher.InnerReceiver
中实现的。IIntentReceiver.aidl
源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 // frameworks/base/core/java/android/content/IIntentReceiver.aidl /** * System private API for dispatching intent broadcasts. * This is given to the activity manager as part of registering for * an intent broadcasts, and is called when it receives intents. * * {@hide} */ oneway interface IIntentReceiver { void performReceive(in Intent intent, int resultCode, String data, in Bundle extras, boolean ordered, boolean sticky, int sendingUser); }
BroadCastReceiver
是系统组件,并不支持跨进程传输,Android Broadcast
机制使用 IIntentReceiver
来进行代替 BroadCastReceiver
来进行跨进程传输。 可以看出 IIntentReceiver
只提供了一个方法 performReceive
,该方法仅仅在动态注册的广播接收器中会触发调用(静态注册广播接收器在 ActivityThread
中通过反射直接调用 onReceive
回调);系统进程 AMS
在分发广播处理事件时,会向注册了广播接收的应用进程调用该方法,最终调用 BroadcastReceiver.onReceive
触发回调。注意:方法使用了 oneway
关键字 ,表示非阻塞调用;即 AMS
进程分发广播事件时,不需要等待每个应用接收者执行完 onReceive
。
LoadedApk
类LoadedApk
类存储了当前加载的 Apk
相关信息,包括主线程,文件所在路径,类加载器,注册的广播列表,启动的服务列表等等;LoadedApk
类是在每个应用加载初始化进程、主线程时实例化的,每个应用对应一个 LoadedApk
实例。 本文只分析和广播 Broadcast
相关内容,LoadedApk
中存储了当前 Apk
中所有的普通广播接收器 BroadCastReceiver
,即通过 registerReceiver
注册到系统中的广播接收器。 而有序广播中的回调广播接收器 ,即广播发送出去后,等待所有广播接收器处理完毕,最后产生一个回调给广播发送者,作用类似 startActivityForResult
。回调 BroadCastReceiver
不需要通过 registerReceiver
注册到系统中,是以参数的形式在 sendOrderedBroadcast()
发送广播时传递出去,这类广播不会存储到 LoadedApk
中。
在 ContextImpl
代码中可以看到:LoadedApk
对这两类广播接收器的处理过程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 private Intent registerReceiverInternal (BroadcastReceiver receiver, int userId, IntentFilter filter, String broadcastPermission, Handler scheduler, Context context) { 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(); } } ... } @Override public void sendOrderedBroadcastAsUser (Intent intent, UserHandle user, String receiverPermission, int appOp, Bundle options, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras) { IIntentReceiver rd = null ; if (resultReceiver != null ) { if (mPackageInfo != null ) { if (scheduler == null ) { scheduler = mMainThread.getHandler(); } rd = mPackageInfo.getReceiverDispatcher( resultReceiver, getOuterContext(), scheduler, mMainThread.getInstrumentation(), false ); } else { if (scheduler == null ) { scheduler = mMainThread.getHandler(); } rd = new LoadedApk.ReceiverDispatcher(resultReceiver, getOuterContext(), scheduler, null , false ) .getIIntentReceiver(); } } }
部分源码分析 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 public final class LoadedApk { private final ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers = new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>(); private final ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>> mUnregisteredReceivers = new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>(); public IIntentReceiver getReceiverDispatcher (BroadcastReceiver r, Context context, Handler handler, Instrumentation instrumentation, boolean registered) { synchronized (mReceivers) { LoadedApk.ReceiverDispatcher rd = null ; ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map=null ; if (registered) { map = mReceivers.get(context); if (map != null ) { rd = map.get(r); } } if (rd == null ) { rd = new ReceiverDispatcher(r, context, handler, instrumentation, registered); if (registered) { if (map == null ) { map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>(); mReceivers.put(context, map); } map.put(r, rd); } } else { rd.validate(context, handler); } rd.mForgotten = false ; return rd.getIIntentReceiver(); } } public IIntentReceiver forgetReceiverDispatcher (Context context, BroadcastReceiver r) { synchronized (mReceivers) { ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = mReceivers.get(context); LoadedApk.ReceiverDispatcher rd = null ; if (map != null ) { rd = map.get(r); if (rd != null ) { map.remove(r); if (map.size() == 0 ) { mReceivers.remove(context); } if (r.getDebugUnregister()) { ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder = mUnregisteredReceivers.get(context); if (holder == null ) { holder = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>(); mUnregisteredReceivers.put(context, holder); } ... holder.put(r, rd); } rd.mForgotten = true ; return rd.getIIntentReceiver(); } } ... throw ... } } static final class ReceiverDispatcher { final static class InnerReceiver extends IIntentReceiver .Stub { ... 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 ) { Log.wtf(TAG, "Null intent received" ); rd = null ; } else { rd = mDispatcher.get(); } ... if (rd != null ) { rd.performReceive(intent, resultCode, data, extras, ordered, sticky, sendingUser); } else { ... IActivityManager mgr = ActivityManagerNative.getDefault(); try { if (extras != null ) { extras.setAllowFds(false ); } mgr.finishReceiver(this , resultCode, data, extras, false , intent.getFlags()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } } } final IIntentReceiver.Stub mIIntentReceiver; final BroadcastReceiver mReceiver; final Context mContext; final Handler mActivityThread; final Instrumentation mInstrumentation; final boolean mRegistered; final IntentReceiverLeaked mLocation; RuntimeException mUnregisterLocation; boolean mForgotten; final class Args extends BroadcastReceiver .PendingResult implements Runnable { private Intent mCurIntent; private final boolean mOrdered; private boolean mDispatched; public Args (Intent intent, int resultCode, String resultData, Bundle resultExtras, boolean ordered, boolean sticky, int sendingUser) { super (resultCode, resultData, resultExtras, mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, ordered, sticky, mIIntentReceiver.asBinder(), sendingUser, intent.getFlags()); mCurIntent = intent; mOrdered = ordered; } public void run () { final BroadcastReceiver receiver = mReceiver; final boolean ordered = mOrdered; ... final IActivityManager mgr=ActivityManagerNative.getDefault(); ... try { ClassLoader cl = mReceiver.getClass().getClassLoader(); intent.setExtrasClassLoader(cl); intent.prepareToEnterProcess(); setExtrasClassLoader(cl); receiver.setPendingResult(this ); receiver.onReceive(mContext, intent); } catch (Exception e) { if (mRegistered && ordered) { ... sendFinished(mgr); } ... } if (receiver.getPendingResult() != null ) { finish(); } ... } } 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; mInstrumentation = instrumentation; mRegistered = registered; mLocation = new IntentReceiverLeaked(null ); mLocation.fillInStackTrace(); } ... BroadcastReceiver getIntentReceiver () {return mReceiver;} IIntentReceiver getIIntentReceiver () {return mIIntentReceiver;} 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)) { if (mRegistered && ordered) { IActivityManager mgr=ActivityManagerNative.getDefault(); if (ActivityThread.DEBUG_BROADCAST) Slog.i(...); args.sendFinished(mgr); } } } } ... }
成员变量
mReceivers
:当前 Apk
注册的广播列表
mUnregisteredReceivers
:当前 Apk
取消广播注册的列表
这两个成员变量都是 Map
结构,Key
值都是 Context
,Value
仍然是一个 Map
结构:
Key: Context
每个 Activity
或者每个 Service
注册的广播分开记录,方便快速查找某个 Context
实例注册的所有广播。
Value: ArrayMap<BroadcastReceiver, ReceiverDispatcher>
BroadcastReceiver
和 ReceiverDispatcher
是一一对应的,每个广播接收器都会对应一个广播接收分发器 。ContextImpl.sendOrderedBroadcast, ContextImpl.registerReceiver
会对每个广播接收器 BroadCastReceiver
,通过 LoadedApk
找到或者生成对应的 ReceiverDispatcher
;在发送有序广播或者注册广播接收器,等到广播接收者开始执行时,AMS
通过 ReceiverDispatcher.InnerReceiver
来触发回调,即调用 BroadCastReceiver.onReceive
。
ReceiverDispatcher
静态内部类ReceiverDispatcher
是 LoadedApk
的静态内部类,同时它自己还包含两个内部类:
静态内部类 InnerReceiver
实现了 IIntentReceiver.performReceive
方法,实际最终调用的是外部类 ReceiverDispatcher.performReceive
方法。
成员内部类 Args
继承了 BroadCastReceiver.PendingResult
类,可以执行部分异步操作;同时实现了 Runnable
,通过传入的 Handler
发布这个任务,并调用 BroadCastReceiver.onReceive
,处理广播接收器回调事件。处理完后,通知系统该广播接收器处理完毕。
成员变量mRegistered
:记录该广播接收器是否通过 registerReceiver
注册的,即是否为动态注册的广播接收器。
ReceiverDispatcher
的几个重要方法:
getIIntentReceiver
:返回广播接收器 BroadCastReceiver
对应的 IIntentReceiver
对象
performReceive
:使用当前线程 Handler
发送 Args
对象并执行;所有动态注册的广播接收器,都是在这里回调 onReceive
方法
广播相关方法
getReceiverDispatcher
根据广播接收器获取广播接收分发器的 IIntentReceiver
,用于跨进程传递。主要是从 mReceivers
中获取;如果不存在则新建。
forgetReceiverDispatcher
从 mReceivers
中移除指定回调广播接收器,并放入 mUnregisteredReceivers
中,返回值也是该广播接收器对应的 IIntentReceiver
。
BroadcastRecord
类详解BroadcastRecord
继承了 Binder
,表明该对象作为数据容器,能被跨进程通信。BroadcastRecord
保存了广播发送者相关信息,包含发送者的:包名,进程信息,广播是否有序,请求的权限等等。
源码分析 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 final class BroadcastRecord extends Binder { final Intent intent; final ComponentName targetComp; final ProcessRecord callerApp; final String callerPackage; final int callingPid; final int callingUid; final boolean ordered; final boolean sticky; final boolean initialSticky; final int userId; final String resolvedType; final String[] requiredPermissions; final int appOp; final BroadcastOptions options; final List receivers; final int [] delivery; IIntentReceiver resultTo; long enqueueClockTime; long dispatchTime; long dispatchClockTime; long receiverTime; long finishTime; int resultCode; String resultData; Bundle resultExtras; boolean resultAbort; int nextReceiver; IBinder receiver; int state; int anrCount; int manifestCount; int manifestSkipCount; BroadcastQueue queue; static final int IDLE = 0 ; static final int APP_RECEIVE = 1 ; static final int CALL_IN_RECEIVE = 2 ; static final int CALL_DONE_RECEIVE = 3 ; static final int WAITING_SERVICES = 4 ; static final int DELIVERY_PENDING = 0 ; static final int DELIVERY_DELIVERED = 1 ; static final int DELIVERY_SKIPPED = 2 ; static final int DELIVERY_TIMEOUT = 3 ; BroadcastFilter curFilter; ProcessRecord curApp; ComponentName curComponent; ActivityInfo curReceiver; BroadcastRecord(BroadcastQueue _queue, Intent _intent, ProcessRecord _callerApp, String _callerPackage, int _callingPid, int _callingUid, String _resolvedType, String[] _requiredPermissions, int _appOp, BroadcastOptions _options, List _receivers, IIntentReceiver _resultTo, int _resultCode, String _resultData, Bundle _resultExtras, boolean _serialized, boolean _sticky, boolean _initialSticky, int _userId) { if (_intent == null ) { throw new NullPointerException(" Can't construct with a null intent" ); } queue = _queue; intent = _intent; targetComp = _intent.getComponent(); callerApp = _callerApp; callerPackage = _callerPackage; callingPid = _callingPid; callingUid = _callingUid; resolvedType = _resolvedType; requiredPermissions = _requiredPermissions; appOp = _appOp; options = _options; receivers = _receivers; delivery = new int [_receivers != null ? _receivers.size() : 0 ]; resultTo = _resultTo; resultCode = _resultCode; resultData = _resultData; resultExtras = _resultExtras; ordered = _serialized; sticky = _sticky; initialSticky = _initialSticky; userId = _userId; nextReceiver = 0 ; state = IDLE; } boolean cleanupDisabledPackageReceiversLocked (String packageName, Set<String> filterByClasses, int userId, boolean doit) { if ((userId != UserHandle.USER_ALL && this .userId != userId) || receivers == null ) { return false ; } boolean didSomething = false ; Object o; for (int i = receivers.size() - 1 ; i >= 0 ; i--) { o = receivers.get(i); if (!(o instanceof ResolveInfo)) { continue ; } ActivityInfo info = ((ResolveInfo)o).activityInfo; final boolean sameComponent = packageName == null || (info.applicationInfo.packageName.equals(packageName) && (filterByClasses == null || filterByClasses.contains(info.name))); if (sameComponent) { if (!doit) { return true ; } didSomething = true ; receivers.remove(i); if (i < nextReceiver) { nextReceiver--; } } } nextReceiver = Math.min(nextReceiver, receivers.size()); return didSomething; } void dump (PrintWriter pw, String prefix, SimpleDateFormat sdf) {...} public String toString () {...} }
重要成员变量
Intent intent
:广播发送时的 Intent
ComponentName targetComp
:广播发送者组件名称
ProcessRecord callerApp
:广播发送者进程记录
String callerPackage
:广播发送者包名
callingPid
:广播发送者 Pid
callingUid
:广播发送者 Uid
userId
:广播发送者 userId
ordered
:广播是否有序发送
sticky
:广播是否为粘性广播
initialSticky
:广播是否一开始就设置为粘性广播
resolvedType
:Intent
的类型
String[] requiredPermissions
:广播发送者拥有的广播权限
appOp
:广播对应的应用管理权限
BroadcastOptions options
:广播发送者设定的选项
List receivers
:广播接收者列表,特别需要注意的是:它包含了两种类型数据 ResolveInfo, BroadcastFilter
,分别对应静态注册广播接收器和动态注册广播接收器,取出时需要做类型判断
int[] delivery
:每个广播接收者的投递状态,状态分为四种
IIntentReceiver resultTo
:有序广播中回调的广播接收器,它也是有序广播的最后一个接收者
enqueueClockTime
:广播进入队列的时间
dispatchTime
:开始分派广播的开机时间
dispatchClockTime
:开始分派广播的系统绝对时间
receiverTime
:广播接收者接收到的时间
finishTime
:广播接收者处理完广播的完成时间
resultCode
:广播处理完毕的结果码
resultData
:广播处理完毕的简单数据
resultExtras
:广播处理完毕的复杂数据
resultAbort
:广播是否被终止
int nextReceiver
:下一个广播接收者索引
IBinder receiver
:广播当前接收者
int state
:广播的当前状态,状态分为五种
anrCount
:当前广播出现的 ANR
次数
manifestCount
:分发给静态注册广播接收者的次数
manifestSkipCount
:分发给静态注册广播接收者跳过的次数
BroadcastQueue queue
:处理当前广播所在队列
BroadcastFilter curFilter
:处理广播时当前广播过滤器
ProcessRecord curApp
:广播当前接收者的进程信息
ComponentName curComponent
:广播当前接收者的组件信息
ActivityInfo curReceiver
:广播当前接收者的信息
cleanupDisabledPackageReceiversLocked
方法BroadcastRecord
中只有一个包内可见的方法 cleanupDisabledPackageReceiversLocked
,该方法功能是从 List receivers
清理掉已经取消注册的广播注册接收者。
BroadcastQueue
类详解BroadcastQueue
用来保存系统和应用发出的广播信息;通常使用两个广播队列 BroadcastQueue
:一个用来保存前台广播,一个用来保存后台广播;而每个广播队列 BroadcastQueue
包含两个列表:一个用来并行处理;一个用来有序处理。
重要成员变量
ArrayList<BroadcastRecord> mParallelBroadcasts
存储并行处理的广播:首先它是普通广播,其次这些广播匹配的广播接收器必须是动态注册的。
ArrayList<BroadcastRecord> mOrderedBroadcasts
存储有序处理的广播:包含有序广播和普通广播(匹配的广播接收器时静态注册的 )。
mTimeoutPeriod
广播接收器 ANR
超时时间阀值。前台广播是 10 秒,后台广播是 60 秒。
BroadcastHandler
类BroadcastHandler
是成员内部类,用来处理下一条广播,或者处理广播超时 ANR
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 static final int BROADCAST_INTENT_MSG = ActivityManagerService.FIRST_BROADCAST_QUEUE_MSG; static final int BROADCAST_TIMEOUT_MSG = ActivityManagerService.FIRST_BROADCAST_QUEUE_MSG + 1 ; final BroadcastHandler mHandler;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 ; case BROADCAST_TIMEOUT_MSG: { synchronized (mService) { broadcastTimeoutLocked(true ); } } break ; } } }
AppNotResponding
类AppNotResponding
成员内部类,广播接收器处理广播事件时发生 ANR
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 private final class AppNotResponding implements Runnable { private final ProcessRecord mApp; private final String mAnnotation; public AppNotResponding (ProcessRecord app, String annotation) { mApp = app; mAnnotation = annotation; } @Override public void run () { mService.mAppErrors.appNotResponding(mApp, null , null , false , mAnnotation); } }
静态注册广播接收器流程分析 静态注册的广播接收器,又称为 Manifest
文件声明广播接收器,是在 PMS
扫描 AndroidManifest.xml
信息时解析的;所有静态注册的广播接收器,统一由 PMS
保存,广播在发送过程中,查找匹配的静态注册广播接收器也是在 PMS
中查询。
流程图
PackageParser.parseBaseApplication
详解PackageParser
主要用于详细解析包内相关信息,而 parseBaseApplication
主要解析 AndroidManifest.xml
,将每个 TAG
都解析并保存,其中静态注册的广播接收器存储到 receivers
中,而 PMS
会根据每个包解析的数据,保存整个系统全部的静态注册广播接收器(当然也保存其他 Activity, Services, ContentProvider
等信息)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 public final ArrayList<Activity> receivers = new ArrayList<Activity>(0 );private boolean parseBaseApplication (Package owner, Resources res, XmlResourceParser parser, int flags, String[] outError) ... while ((type = parser.next() ) ! = XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) { if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { continue ; } String tagName = parser.getName(); if (tagName.equals("activity" )) { ... } else if (tagName.equals("receiver" )) { Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, true , false ); if (a == null ) { mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; return false ; } owner.receivers.add(a); } ... } ... }
PMS
静态注册广播接收器PMS
在调用完 PackageParser.parsePackage
解析完指定包名信息后,将存储在 PackageParser.Package.receivers
的静态广播接收器信息,再保存到 PMS.mReceivers
中,方便后续全局查询。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 final ActivityIntentResolver mReceivers = new ActivityIntentResolver(); private void commitPackageSettings (PackageParser.Package pkg, PackageSetting pkgSetting, UserHandle user, int scanFlags, boolean chatty) throws PackageManagerException { final String pkgName = pkg.packageName; ... N = pkg.receivers.size(); r = null ; for (i=0 ; i<N; i++) { PackageParser.Activity a = pkg.receivers.get(i); a.info.processName=fixProcessName(pkg.applicationInfo.processName, a.info.processName); mReceivers.addActivity(a, "receiver" ); if (chatty) { if (r == null ) { r = new StringBuilder(256 ); } else { r.append(' ' ); } r.append(a.info.name); } } if (r != null ) { if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Receivers: " + r); } ... }
PMS
查询静态注册广播接收器AMS
在发送广播时,会从 PMS
中查询匹配的静态广播接收器;PMS.queryIntentReceiversInternal
根据广播 Intent
,从 mReceivers
中查询匹配的 ResolveInfo
,而 ResolveInfo.activityInfo
存储了对应的广播接收器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 private @NonNull List<ResolveInfo> queryIntentReceiversInternal ( Intent intent, String resolvedType, int flags, int userId, boolean allowDynamicSplits) { ... synchronized (mPackages) { String pkgName = intent.getPackage(); if (pkgName == null ) { final List<ResolveInfo> result = mReceivers.queryIntent( intent, resolvedType, flags, userId); return applyPostResolutionFilter(result, instantAppPkgName, allowDynamicSplits, callingUid, userId); } final PackageParser.Package pkg = mPackages.get(pkgName); if (pkg != null ) { final List<ResolveInfo> result=mReceivers.queryIntentForPackage( intent, resolvedType, flags, pkg.receivers, userId); return applyPostResolutionFilter(result, instantAppPkgName, allowDynamicSplits, callingUid, userId); } return Collections.emptyList(); } } final class ActivityIntentResolver extends IntentResolver < PackageParser .ActivityIntentInfo , ResolveInfo > { public List<ResolveInfo> queryIntent (Intent intent, String resolvedType, boolean defaultOnly, int userId) { if (!sUserManager.exists(userId)) return null ; mFlags = (defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0 ); return super .queryIntent(intent, resolvedType, defaultOnly, userId); } public List<ResolveInfo> queryIntent (Intent intent, String resolvedType, int flags, int userId) { if (!sUserManager.exists(userId)) return null ; mFlags = flags; return super .queryIntent(intent, resolvedType, (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0 , userId); } public List<ResolveInfo> queryIntentForPackage (Intent intent, String resolvedType, int flags, ArrayList<PackageParser.Activity> packageActivities, int userId) {...} ... }
protected-broadcast
受保护的广播在 AndroidManifest.xml
中声明的 protected-broadcast
受保护广播 ACTION
,表示它们只能被有系统权限的广播接收器接收。在 PackageParser.Package.protectedBroadcasts
中保存,同时 PMS.mProtectedBroadcasts
会做系统全局保存, AMS
发送广播时会查询 PMS
做权限检查,如果没有权限则不会分发给该广播接收器。
动态注册/取消广播接收器流程分析 流程图
动态注册 ContextImpl/LoadedApk
动态注册时统一由 ContextImpl.registerReceiverInternal
向系统注册广播接收器。这个过程主要功能:
将 BroadCastReceiver
转换为对应的 IIntentReceiver
,用于跨进程通信
LoadedApk.getReceiverDispatcher
会将当前 Apk
注册的每个广播接收器保存到 mReceivers
中;如果是有序广播的回调广播接收器则不保存
向 AMS
中注册 IIntentReceiver
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 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(); } } try { final Intent intent = ActivityManager.getService() .registerReceiver(mMainThread.getApplicationThread(), mBasePackageName, rd, filter, broadcastPermission, userId, flags); if (intent != null ) { intent.setExtrasClassLoader(getClassLoader()); intent.prepareToEnterProcess(); } return intent; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } public IIntentReceiver getReceiverDispatcher (BroadcastReceiver r, Context context, Handler handler, Instrumentation instrumentation, boolean registered) { synchronized (mReceivers) { LoadedApk.ReceiverDispatcher rd = null ; ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null ; if (registered) { map = mReceivers.get(context); if (map != null ) { rd = map.get(r); } } if (rd == null ) { rd = new ReceiverDispatcher(r, context, handler, instrumentation, registered); if (registered) { if (map == null ) { map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>(); mReceivers.put(context, map); } map.put(r, rd); } } else { rd.validate(context, handler); } rd.mForgotten = false ; return rd.getIIntentReceiver(); } }
动态注册 AMS
广播接收器动态注册时,广播接收器的相关信息保存在 AMS
中:
mRegisteredReceivers
保存所有动态注册的广播接收器对应的 ReceiverList
。mRegisteredReceivers
并没有太多作用,注册保存信息,取消注册时从这里删除。
mReceiverResolver
保存所有所有动态注册广播接收器时对应的广播过滤器 BroadcastFilter
。广播发送过程中,会根据 Intent
从 mReceiverResolver
中查找 BroadcastFilter
;每个 BroadcastFilter
都保存了它所属的 ReceiverList
;而 ReceiverList
保存了 BroadCastReceiver
对应的 IIntentReceiver
;动态注册广播接收器事件处理时,使用 IIntentReceiver
处理 onReceive
回调。
主要功能:
获取动态注册广播接收器,应用进程相关信息
处理粘性广播事件
BroadCastReceiver
生成对应的 ReceiverList
和 BroadcastFilter
将 ReceiverList
添加到 mRegisteredReceivers
中
将 BroadcastFilter
添加到 mReceiverResolver
中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 public Intent registerReceiver (IApplicationThread caller, String callerPackage, IIntentReceiver receiver, IntentFilter filter, String permission, int userId, int flags) { enforceNotIsolatedCaller("registerReceiver" ); ArrayList<Intent> stickyIntents = null ; ProcessRecord callerApp = null ; ... int callingUid; int callingPid; ... Intent sticky = allSticky != null ? allSticky.get(0 ) : null ; ... synchronized (this ) { if (callerApp != null && (callerApp.thread == null || callerApp.thread.asBinder() != caller.asBinder())) { 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 { ... } mRegisteredReceivers.put(receiver.asBinder(), rl); } else ... BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, permission, callingUid, userId, instantApp, visibleToInstantApps); rl.add(bf); ... mReceiverResolver.addFilter(bf); ... return sticky; } }
取消注册 ContextImpl/LoadedApk
取消注册时统一由 ContextImpl.unregisterReceiver
向系统取消注册广播接收器。这个过程主要功能:
将 BroadCastReceiver
转换为对应的 IIntentReceiver
,用于跨进程通信
LoadedApk.forgetReceiverDispatcher
会将当前需要取消注册的广播接收器,从 mReceivers
中移除;如果需要调试,会同时将它加入 mUnregisteredReceivers
中
向 AMS
中取消注册 IIntentReceiver
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 @Override public void unregisterReceiver (BroadcastReceiver receiver) { if (mPackageInfo != null ) { IIntentReceiver rd = mPackageInfo.forgetReceiverDispatcher( getOuterContext(), receiver); try { ActivityManager.getService().unregisterReceiver(rd); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } else { throw new RuntimeException("Not supported in system context" ); } } public IIntentReceiver forgetReceiverDispatcher (Context context, BroadcastReceiver r) { synchronized (mReceivers) { ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = mReceivers.get(context); LoadedApk.ReceiverDispatcher rd = null ; if (map != null ) { rd = map.get(r); if (rd != null ) { map.remove(r); if (map.size() == 0 ) { mReceivers.remove(context); } if (r.getDebugUnregister()) { ... mUnregisteredReceivers.put(context, holder); ... } rd.mForgotten = true ; return rd.getIIntentReceiver(); } } ... } }
取消注册 AMS
广播接收器取消注册时,从 AMS
中移除对应的数据,主要功能为:
从 mRegisteredReceivers
中移除 ReceiverList
从 mReceiverResolver
中移除 ReceiverList
中所有的 BroadcastFilter
如果还存在没有处理完的广播接收器,触发 BroadcastQueue.processNextBroadcast
继续处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 public void unregisterReceiver (IIntentReceiver receiver) { ... final long origId = Binder.clearCallingIdentity(); try { boolean doTrim = false ; synchronized (this ) { ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder()); if (rl != null ) { final BroadcastRecord r = rl.curBroadcast; if (r != null && r == r.queue.getMatchingOrderedReceiver(r)) { final boolean doNext = r.queue.finishReceiverLocked( r, r.resultCode, r.resultData, r.resultExtras, r.resultAbort, false ); if (doNext) { doTrim = true ; r.queue.processNextBroadcast(false ); } } if (rl.app != null ) { rl.app.receivers.remove(rl); } removeReceiverLocked(rl); ... } } ... } finally { Binder.restoreCallingIdentity(origId); } } void removeReceiverLocked (ReceiverList rl) { mRegisteredReceivers.remove(rl.receiver.asBinder()); for (int i = rl.size() - 1 ; i >= 0 ; i--) { mReceiverResolver.removeFilter(rl.get(i)); } }
广播发送流程分析 先回顾下基础概念,广播的类型:
普通广播:通过 sendBroadcast
发送的广播
有序广播:通过 sendOrderedBroadcast
发送的广播
系统对广播响应并处理的方式分为:
并行处理 广播存储位置:BroadcastQueue.mParallelBroadcasts
;并行处理的广播为:普通广播,且它对应的广播接收器一定是动态注册的。
有序处理 广播存储位置:BroadcastQueue.mOrderedBroadcasts
;有序处理的广播为:有序广播和普通广播(对应的广播接收器是静态注册的)。mOrderedBroadcasts
中处理普通广播(对应的广播接收器时静态注册的)非常费解,初看代码时很容易搞错,存储逻辑是在 AMS
调度时决定的。
流程图
广播发送过程,从广播发送所在应用进程进入系统进程 Context -> AMS -> BroadcastQueue
广播发送过程,从系统进程进入广播接收器应用所在进程 BroadcastQueue -> ActivityThread -> BroadCastReceiver.onReceive
ContextImpl.sendBroadcast
发送普通广播ContextImpl
对于普通广播并不做特别处理,比较简单,直接将 Intent
和广播发送应用相关信息传递给 AMS
,进入系统来处理分发流程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Override 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(); } }
ContextImpl.sendOrderedBroadcast
发送有序广播有序广播支持广播接收器回调,所以进入系统 AMS
处理前,会先将 BroadCastReceiver
转换为 IIntentReceiver
,回调广播接收器在 LoadedApk
中不做保存。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 void sendOrderedBroadcast (Intent intent, String receiverPermission, int appOp, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras, Bundle options) { warnIfCallingFromSystemProcess(); IIntentReceiver rd = null ; if (resultReceiver != null ) { if (mPackageInfo != null ) { if (scheduler == null ) { scheduler = mMainThread.getHandler(); } rd = mPackageInfo.getReceiverDispatcher( resultReceiver, getOuterContext(), scheduler, mMainThread.getInstrumentation(), false ); } else { if (scheduler == null ) { scheduler = mMainThread.getHandler(); } rd = new LoadedApk.ReceiverDispatcher( resultReceiver, getOuterContext(), scheduler, null , false ).getIIntentReceiver(); } } String resolvedType=intent.resolveTypeIfNeeded(getContentResolver()); String[] receiverPermissions = receiverPermission == null ? null : new String[] {receiverPermission}; try { intent.prepareToLeaveProcess(this ); ActivityManager.getService().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, rd, initialCode, initialData, initialExtras, receiverPermissions, appOp, options, true , false , getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
AMS.broadcastIntentLocked
广播发送解析不管是普通广播还是有序广播,在 AMS
中都是进入了 broadcastIntentLocked(Intent, ...)
方法来调度处理的。这个方法中会处理很多系统级广播,比如 Intent.ACTION_PACKAGE_ADDED, Intent.ACTION_PACKAGE_REMOVED, Intent.ACTION_TIME_CHANGED
等等,在 AMS
做预处理或者直接处理完毕。该方法主要功能:
各种权限检查
系统广播处理
收集该广播匹配的所有动态注册广播接收器
收集该广播匹配的所有静态注册广播接收器
将广播对应的广播记录存入广播队列(如果是有序广播,会按照优先级先排序再存入)
代码分析(代码有简化和调整位置)如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 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); ... List receivers = null ; List<BroadcastFilter> registeredReceivers = null ; receivers = collectReceiverComponents(intent, resolvedType, callingUid, users); ... registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false , users[i]); int NR = registeredReceivers != null ? registeredReceivers.size() : 0 ; if (!ordered && NR > 0 ) { ... final BroadcastQueue queue = broadcastQueueForIntent(intent); 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 ); if (!replaced) { queue.enqueueParallelBroadcastLocked(r); queue.scheduleBroadcastsLocked(); } registeredReceivers = null ; NR = 0 ; } int ir = 0 ; ... while (ir < NR) { if (receivers == null ) { receivers = new ArrayList(); } receivers.add(registeredReceivers.get(ir)); ir++; } if ((receivers != null && receivers.size() > 0 ) || resultTo != null ) { BroadcastQueue queue = broadcastQueueForIntent(intent); BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage, callingPid, callingUid, callerInstantApp, resolvedType, requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode, resultData, resultExtras, ordered, sticky, false , userId); ... queue.enqueueOrderedBroadcastLocked(r); queue.scheduleBroadcastsLocked(); } ... return ActivityManager.BROADCAST_SUCCESS; }
BroadcastQueue.processNextBroadcast
广播发送解析不管是并行处理还是有序处理,在 BroadcastQueue
中都是进入 processNextBroadcast(boolean fromMsg)
方法处理的。该方法主要功能:
并行处理的广播接收器,一次全部处理完
有序广播处理完毕后,处理回调广播接收器
各种权限检查
调用 deliverToRegisteredReceiverLocked
处理所有动态注册的广播接收器
如果是静态广播接收器,开启对应的应用进程
调用 processCurBroadcastLocked
处理所有静态注册的广播接收器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 final void processNextBroadcast (boolean fromMsg) { BroadcastRecord r = null ; ... 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); } ... } boolean looped = false ; do { if (mOrderedBroadcasts.size() == 0 ) { ... return ; } r = mOrderedBroadcasts.get(0 ); boolean forceReceive = false ; int numReceivers = (r.receivers != null ) ? r.receivers.size() : 0 ; ... if (r.receivers == null || r.nextReceiver >= numReceivers || r.resultAbort || forceReceive) { if (r.resultTo != null ) { try { if (DEBUG_BROADCAST) Slog.i(TAG_BROADCAST, "Finishing broadcast [" + mQueueName + "] " + r.intent.getAction() + " app=" + r.callerApp); performReceiveLocked(r.callerApp, r.resultTo, new Intent(r.intent), r.resultCode, r.resultData, r.resultExtras, false , false , r.userId); r.resultTo = null ; } catch (RemoteException e) { ... } } ... if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Finished with ordered broadcast " + r); ... mOrderedBroadcasts.remove(0 ); r = null ; looped = true ; continue ; } } while (r == null ); int recIdx = r.nextReceiver++; ... final Object nextReceiver = r.receivers.get(recIdx); if (nextReceiver instanceof BroadcastFilter) { BroadcastFilter filter = (BroadcastFilter)nextReceiver; if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Delivering ordered [" + mQueueName + "] to registered " + filter + ": " + r); deliverToRegisteredReceiverLocked(r, filter, r.ordered, recIdx); ... return ; } ResolveInfo info = (ResolveInfo)nextReceiver; ComponentName component = new ComponentName( info.activityInfo.applicationInfo.packageName, info.activityInfo.name); ... String targetProcess = info.activityInfo.processName; ProcessRecord app = mService.getProcessRecordLocked(targetProcess, info.activityInfo.applicationInfo.uid, false ); ... if (app != null && app.thread != null && !app.killed) { try { app.addPackage(info.activityInfo.packageName, info.activityInfo.applicationInfo.versionCode, mService.mProcessStats); processCurBroadcastLocked(r, app); return ; } catch (RuntimeException e) { ... return ; } } if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Need to start app [" + mQueueName + "] " + targetProcess + " for broadcast " + r); if ((r.curApp=mService.startProcessLocked(targetProcess, info.activityInfo.applicationInfo, true , r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND, "broadcast" , r.curComponent, (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0 , false , false )) == null ) { ... return ; } mPendingBroadcast = r; mPendingBroadcastRecvIndex = recIdx; ... }
deliverToRegisteredReceiverLocked
方法解析BroadcastQueue.deliverToRegisteredReceiverLocked
专门用来处理动态注册的广播接收器,最终是在 performReceiveLocked
方法中调用了 ActivityThread.scheduleRegisteredReceiver
,进入广播接收器所在进程处理具体的回调 onReceive
。这个阶段主要功能:
各种权限检查
添加完善广播记录
跨进程进入广播接收器所在应用进程,调用 onReceive
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 private void deliverToRegisteredReceiverLocked (BroadcastRecord r, BroadcastFilter filter, boolean ordered, int index) { boolean skip = false ; ... if (skip) { r.delivery[index] = BroadcastRecord.DELIVERY_SKIPPED; return ; } if (ordered) { r.receiver = filter.receiverList.receiver.asBinder(); r.curFilter = filter; filter.receiverList.curBroadcast = r; r.state = BroadcastRecord.CALL_IN_RECEIVE; if (filter.receiverList.app != null ) { r.curApp = filter.receiverList.app; filter.receiverList.app.curReceivers.add(r); mService.updateOomAdjLocked(r.curApp, true ); } } try { if (DEBUG_BROADCAST_LIGHT) Slog.i(TAG_BROADCAST, "Delivering to " + filter + " : " + r); 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); } if (ordered) { r.state = BroadcastRecord.CALL_DONE_RECEIVE; } } catch (RemoteException e) { Slog.w(TAG, "Failure sending broadcast " + r.intent, e); ... } } 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.scheduleRegisteredReceiver(receiver, intent, resultCode, data, extras, ordered, sticky, sendingUser, app.repProcState); } catch (RemoteException ex) { ... } } else { throw new RemoteException("app.thread must not be null" ); } } else { receiver.performReceive(intent, resultCode, data, extras, ordered, sticky, sendingUser); } }
ActivityThread.scheduleRegisteredReceiver
方法解析每个应用的主线程中 ActivityThread.scheduleRegisteredReceiver
来执行广播处理事件,performReceive
对应的是 LoadedApk.ReceiverDispatcher.InnerReceiver.performReceive
方法。
1 2 3 4 5 6 7 8 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); }
processCurBroadcastLocked
方法解析BroadcastQueue.processCurBroadcastLocked
专门处理静态注册的广播接收器。该方法主要功能:
将 BroadCastReceiver
子类存储到 intent
中
跨进程进入静态广播接收器所在进程,通过反射调用 onReceive
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 private final void processCurBroadcastLocked (BroadcastRecord r, ProcessRecord app) throws RemoteException { if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Process cur broadcast " + r + " for app " + app); ... r.receiver = app.thread.asBinder(); r.curApp = app; app.curReceivers.add(r); app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER); mService.updateLruProcessLocked(app, false , null ); mService.updateOomAdjLocked(); r.intent.setComponent(r.curComponent); boolean started = false ; try { ... app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver, mService.compatibilityInfoForPackageLocked( r.curReceiver.applicationInfo), r.resultCode, r.resultData, r.resultExtras, r.ordered, r.userId, app.repProcState); if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Process cur broadcast " + r + " DELIVERED for app " + app); started = true ; } finally { if (!started) { ... } } }
ActivityThread.scheduleReceiver
方法解析ActivityThread.scheduleReceiver
处理静态注册的广播接收器,从 intent
中获取具体的广播接收器子类组件名,在 handleReceiver
中使用反射技术生成对应的实例对象,并调用其 onReceive
方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 public final void scheduleReceiver (Intent intent, ActivityInfo info, CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras, boolean sync, int sendingUser, int processState) { updateProcessState(processState, false ); ReceiverData r = new ReceiverData(intent, resultCode, data, extras, sync, false , mAppThread.asBinder(), sendingUser); r.info = info; r.compatInfo = compatInfo; sendMessage(H.RECEIVER, r); } private void handleReceiver (ReceiverData data) { ... String component = data.intent.getComponent().getClassName(); LoadedApk packageInfo = getPackageInfoNoCheck( data.info.applicationInfo, data.compatInfo); IActivityManager mgr = ActivityManager.getService(); Application app; BroadcastReceiver receiver; ContextImpl context; try { app = packageInfo.makeApplication(false , mInstrumentation); context = (ContextImpl) app.getBaseContext(); if (data.info.splitName != null ) { context = (ContextImpl) context. createContextForSplit(data.info.splitName); } java.lang.ClassLoader cl = context.getClassLoader(); data.intent.setExtrasClassLoader(cl); data.intent.prepareToEnterProcess(); data.setExtrasClassLoader(cl); receiver = (BroadcastReceiver)cl.loadClass(component) .newInstance(); } catch (Exception e) { if (DEBUG_BROADCAST) Slog.i(...); data.sendFinished(mgr); throw new RuntimeException(...); } try { ... sCurrentBroadcastIntent.set(data.intent); receiver.setPendingResult(data); receiver.onReceive(context.getReceiverRestrictedContext(), data.intent); } catch (Exception e) { if (DEBUG_BROADCAST) Slog.i(...); data.sendFinished(mgr); if (!mInstrumentation.onException(receiver, e)) { throw new RuntimeException(...); } } finally { sCurrentBroadcastIntent.set(null ); } if (receiver.getPendingResult() != null ) { data.finish(); } }
AMS.finishReceiver
结束广播所有的广播接收器处理完毕后,最终会调用系统 ActivityManagerService.finishReceiver
结束整个流程。结束流程前会再次检查确认,是否还有广播接收器没有处理完(静态注册的广播接收器,如果应用没有启动,会先启动应用进程),存在的话就触发 BroadcastQueue.processNextBroadcast
继续分发。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public void finishReceiver (IBinder who, int resultCode, String resultData, Bundle resultExtras, boolean resultAbort, int flags) { ... final long origId = Binder.clearCallingIdentity(); try { boolean doNext = false ; BroadcastRecord r; synchronized (this ) { BroadcastQueue queue = (flags & Intent.FLAG_RECEIVER_FOREGROUND) != 0 ? mFgBroadcastQueue : mBgBroadcastQueue; r = queue.getMatchingOrderedReceiver(who); if (r != null ) { doNext = r.queue.finishReceiverLocked(r, resultCode, resultData, resultExtras, resultAbort, true ); } } if (doNext) { r.queue.processNextBroadcast(false ); } trimApplications(); } finally { Binder.restoreCallingIdentity(origId); } }
广播 ANR
processNextBroadcast
中可以看到,广播的 ANR
只会出现在有序处理的广播队列 mOrderedBroadcasts
中,也就是普通广播匹配的动态注册的广播接收器不会出现 ANR
。
setBroadcastTimeoutLocked
:设置广播超时延时消息
broadcastTimeoutLocked
:当广播接收者等待时间过长,触发 ANR
机制
cancelBroadcastTimeoutLocked
:当广播正常执行完毕清除
超时时间计算方式:从队列中取出有效广播开始计时,直到所有的广播接收器处理完毕,才取消计时。 示例:发送一个有序广播,AndroidManifest.xml
中静态注册的广播接收器和一个动态注册的广播接收器都能匹配到,同时有序广播带有回调广播接收器,也就是说该广播一共会有三个 BroadCastReceiver.onReceive
响应处理。看对应的 Log
文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 // 1. AMS.broadcastIntent 发送广播 06-17*.163: D/XMT(1485): ***********AMS: broadcastIntent########## 06-17*.163: V/ActivityManager(1485): Broadcast: Intent { act=broadcast.service.order flg=0x10 (has extras) } ordered=true userid=0 06-17*.163: V/ActivityManager(1485): Enqueueing broadcast: broadcast.service.order replacePending=false // 2. 广播是后台广播 06-17*.163: I/ActivityManager(1485): Broadcast intent Intent { act=broadcast.service.order flg=0x10 (has extras) } on background queue // 3. 存入 BroadcastQueue.mOrderedBroadcasts 中 06-17*.163: V/ActivityManager(1485): Enqueueing ordered broadcast BroadcastRecord{46a4f31 u0 broadcast.service.order}: prev had 0 06-17*.163: I/ActivityManager(1485): Enqueueing broadcast broadcast.service.order 06-17*.164: V/BroadcastQueue(1485): Schedule broadcasts [background]: current=false 06-17*.164: V/BroadcastQueue(1485): Received BROADCAST_INTENT_MSG // 4. 进入 BroadcastQueue.processNextBroadcast 处理具体的广播, mOrderedBroadcasts 中只有一个广播 06-17*.164: V/BroadcastQueue(1485): processNextBroadcast [background]: 0 parallel broadcasts, 1 ordered broadcasts // 5. 从 mOrderedBroadcasts 中取出有效广播 06-17*.164: V/BroadcastQueue(1485): Processing ordered broadcast [background] BroadcastRecord{46a4f31 u0 broadcast.service.order} // 6. 有序处理广播 ANR 开始计时 06-17*.164: V/BroadcastQueue(1485): Submitting BROADCAST_TIMEOUT_MSG [background] for BroadcastRecord{46a4f31 u0 broadcast.service.order} at 40095097 // 7. deliverToRegisteredReceiverLocked 开始处理动态注册的广播接收器 06-17*.164: V/BroadcastQueue(1485): Delivering ordered [background] to registered BroadcastFilter{d73ca43 u0 ReceiverList{a3cf3f2 9397 com.ymzs.androidbasicknowledge:broadcast/10076/u0 remote:550afd}}: BroadcastRecord{46a4f31 u0 broadcast.service.order} 06-17*.165: I/BroadcastQueue(1485): Delivering to BroadcastFilter{d73ca43 u0 ReceiverList{a3cf3f2 9397 com.ymzs.androidbasicknowledge:broadcast/10076/u0 remote:550afd}} : BroadcastRecord{46a4f31 u0 broadcast.service.order} // 8. 动态注册的广播接收器响应 onReceive 06-17*.168: D/XMT:BroadcastService(9397): mActionOrderBroadcastReceiver: onReceive = order // 9. 动态注册广播接收器响应完毕后,调用 finishReceiver 结束广播流程 06-17*.169: V/ActivityManager(1485): Finish receiver: android.os.BinderProxy@550afd // 10. 结束广播流程时,发现 mOrderedBroadcasts 中还有广播没有处理完毕 // 触发 processNextBroadcast 继续分发广播 06-17*.169: V/BroadcastQueue(1485): processNextBroadcast [background]: 0 parallel broadcasts, 1 ordered broadcasts // 11. processCurBroadcastLocked 开始处理静态注册的广播接收器 06-17*.169: V/BroadcastQueue(1485): Process cur broadcast BroadcastRecord{46a4f31 u0 broadcast.service.order} for app ProcessRecord{64ad616 9368:com.ymzs.androidbasicknowledge/u0a76} 06-17*.170: V/BroadcastQueue(1485): Delivering to component ComponentInfo{com.ymzs.androidbasicknowledge/com.ymzs.androidbasicknowledge.ipc.BroadcastReceiverMy}: BroadcastRecord{46a4f31 u0 broadcast.service.order} 06-17*.171: V/BroadcastQueue(1485): Process cur broadcast BroadcastRecord{46a4f31 u0 broadcast.service.order} DELIVERED for app ProcessRecord{64ad616 9368:com.ymzs.androidbasicknowledge/u0a76} // 12. 静态注册的广播接收器响应 onReceive 06-17*.175: D/XMT:BroadcastReceiverMy(9368): BroadcastReceiverMy: onReceive = order // 13. 静态注册广播接收器响应完毕后,调用 finishReceiver 结束广播流程 06-17*.176: V/ActivityManager(1485): Finish receiver: android.os.BinderProxy@61c0b97 // 14. 结束广播流程时,发现 mOrderedBroadcasts 中还有广播没有处理完毕 // 触发 processNextBroadcast 继续分发广播,处理有序广播的回调 06-17*.176: V/BroadcastQueue(1485): processNextBroadcast [background]: 0 parallel broadcasts, 1 ordered broadcasts // 15. 有序广播的回调广播接收器响应 onReceive 06-17*.176: D/XMT:BroadcastActivity(9397): mResultBroadcastReceiver: onReceive = order 06-17*.176: I/BroadcastQueue(1485): Finishing broadcast [background] broadcast.service.order app=ProcessRecord{64ad616 9368:com.ymzs.androidbasicknowledge/u0a76} // 17. 有序处理广播 ANR 计时取消 06-17*.177: V/BroadcastQueue(1485): Cancelling BROADCAST_TIMEOUT_MSG 06-17*.177: V/BroadcastQueue(1485): Finished with ordered broadcast BroadcastRecord{46a4f31 u0 broadcast.service.order}
示例 静态注册广播接收器
BroadCastReceiver
子类文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class BroadcastReceiverMy extends BroadcastReceiver { private static final String TAG = "XMT:BroadcastReceiverMy" ; @Override public void onReceive (Context context, Intent intent) { if (intent != null ){ String value = intent.getStringExtra("key" ); Log.d(TAG, "BroadcastReceiverMy: onReceive = " + value); } } }
在 AndroidManifest.xml
中声明 1 2 3 4 5 6 7 8 9 10 11 <receiver android:name=".ipc.BroadcastReceiverMy" android:enabled="true" android:exported="true" > <intent-filter> <action android:name="broadcast.service.normal"></action> </intent-filter> <intent-filter> <action android:name="broadcast.service.order"></action> </intent-filter> </receiver>
动态注册广播接收器 动态注册和取消注册广播必须在生命周期中成对出现,比如在 onCreate/onDestroy, onResume/onPause, onStart/onStop
对应出现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 private boolean registeredOrder;private boolean registeredNormal;private BroadcastReceiver mActionOrderBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive (Context context, Intent intent) { if (intent != null ) { String value = intent.getStringExtra("key" ); Log.d(TAG, "mActionOrderBroadcastReceiver: onReceive = " + value); setResultData("mActionOrderBroadcastReceiver:From Service" ); } } }; private BroadcastReceiver mActionNormalBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive (Context context, Intent intent) { if (intent != null ){ String value = intent.getStringExtra("key" ); Log.d(TAG, "mActionNormalBroadcastReceiver: onReceive = " + value); } } }; @Override public void onCreate () { super .onCreate(); Log.d(TAG, "onCreate: " ); IntentFilter intentFilter = new IntentFilter(BroadcastActivity.BROADCAST_ACTION_ORDER); registerReceiver(mActionOrderBroadcastReceiver, intentFilter); registeredOrder = true ; intentFilter = new IntentFilter(BroadcastActivity.BROADCAST_ACTION_NORMAL); registerReceiver(mActionNormalBroadcastReceiver, intentFilter); registeredNormal = true ; } @Override public int onStartCommand (Intent intent, int flags, int startId) { doLongWork(); return super .onStartCommand(intent, flags, startId); } @Override public void onDestroy () { super .onDestroy(); Log.d(TAG, "onDestroy: " ); if (registeredOrder){ unregisterReceiver(mActionOrderBroadcastReceiver); mActionOrderBroadcastReceiver = null ; registeredOrder = false ; } if (registeredNormal){ unregisterReceiver(mActionNormalBroadcastReceiver); mActionNormalBroadcastReceiver = null ; registeredNormal = false ; } }
广播发送 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 private void sendOrderBroadcast () { Log.d(TAG, "sendOrderBroadcast: " ); Intent intent = new Intent(BROADCAST_ACTION_ORDER); intent.putExtra("key" , "order" ); sendOrderedBroadcast(intent, null , mResultBroadcastReceiver, null , 0 , null , null ); } private BroadcastReceiver mResultBroadcastReceiver = new BroadcastReceiver(){ @Override public void onReceive (Context context, Intent intent) { String result = getResultData(); mTvResultReceiver.setText(result); } }; private void sendNormalBroadcast () { Log.d(TAG, "sendNormalBroadcast: sendNormalBroadcast" ); Intent intent = new Intent(BROADCAST_ACTION_NORMAL); intent.putExtra("key" , "normal" ); sendBroadcast(intent); }
小结 广播接收器静态注册过程 静态注册的广播接收器,是开机时 PMS
启动后解析扫描所有包时注册的,保存在每个包的 PackageParser.Package.receivers
中,系统 PMS.mReceivers
会全局保存所有静态注册的广播接收器。 AMS
中并不会保存静态注册的广播接收器信息,而是直接向 PMS
中查询。
AMS
中存储的广播相关信息
广播队列:前台广播队列 mFgBroadcastQueue
和后台广播队列 mBgBroadcastQueue
广播接收器哈希表 mRegisteredReceivers
:所有动态注册的广播接收器
广播过滤器符号表 mReceiverResolver
:所有动态注册的广播过滤器
1 2 3 4 5 6 BroadcastQueue mFgBroadcastQueue; BroadcastQueue mBgBroadcastQueue; final HashMap<IBinder, ReceiverList> mRegisteredReceivers = new HashMap<>();final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver = new IntentResolver<BroadcastFilter, BroadcastFilter>() {...}
权限检查 广播在发送的过程中,会有大量的权限检查,比如 AMS.broadcastIntentLocked, BroadcastQueue.processNextBroadcast, BroadcastQueue.deliverToRegisteredReceiverLocked
都会反复做权限检查。
广播接收器优先级 数字越大表示优先级越高,接收有序广播时优先级高的先接收到。
静态注册广播接收器 1 2 3 4 5 <receiver android:name =".smsReceiver" > <intent-filter android:priority ="1000" > <action android:name ="android.provider.Telephony.SMS_RECEIVED" /> </intent-filter > </receiver >
动态注册广播接收器 1 2 3 4 IntentFilter intentFilter = new IntentFilter( "android.provider.Telephony.SMS_RECEIVED" ); intentFilter.setPriority(1000 ); registerReceiver(broadcastReceiver, intentFilter);
广播接收器响应 广播接收器回调 onReceive
触发响应的位置
静态注册的广播接收器ActivityThread.handleReceiver
中使用反射,触发 onReceive
方法。静态注册的广播接收器并不会对应 ReceiverDispatcher
。
动态注册的广播接收器 动态注册的广播接收器对应一个 ReceiverDispatcher
,通过它找到 LoadedApk.Args
,在 Runnable.run
中触发 onReceive
方法。
前后台广播及 ANR
广播发送时,通过 Intent
是否设置 FLAG_RECEIVER_FOREGROUND
来区分,如果设置了表示前台广播,对应 ANR
超时为 10 秒;默认为后台广播,对应超时为 60 秒。 广播的 ANR
是会出现在有序处理广播队列中,在 BroadcastQueue.processNextBroadcast
中计算的,从有序队列 mOrderedBroadcasts
取出有效广播后开始计时,直到有序广播匹配的所有广播接收器包括有序广播的回调广播接收器,全部处理完毕才会取消计时。具体可以看“广播 ANR
” 这一节的 Log
分析。 注意:如果广播接收器的 onReceive
是在主线程中处理,同时还会受到 Activity
超时 5 秒产生 ANR
的限制!也就是说等不到 60 秒,可能 Activity
就出现 ANR
了。如果 onReceive
有耗时任务,请新开线程处理。
有序广播
可以被终止 优先级高的广播接收者接收到后,可以通过 abortBroadcast
来终止继续向下传递广播。
可以有回调 BroadCastReceiver
广播接收器回调,发送有序广播时,可以同时指定一个 BroadCastReceiver
回调;当有序广播全部被执行完后,会触发这个回调。也就是说有序广播,在顺序接收过程中,每个广播接收者都可以在回调 BroadCastReceiver
中向发送者写回数据。
广播发送过程
整个广播发送及响应过程都是异步的,大量使用 Handler
异步处理
源码中可以看到大量 synchronized
关键字,而且大多使用 AMS
作为对象锁,所以系统处理广播的过程有大量同步过程
并行处理和有序处理
mParallelBroadcasts
广播队列 存储的广播为普通广播(对应的广播接收器是动态注册的),该队列的所有广播都是并行处理的,在 processNextBroadcast
中一次全部处理完。
mOrderedBroadcasts
广播队列 存储的广播为有序广播和普通广播(对应的广播接收器时静态注册的)该队列的所有广播都是有序处理的,在 processNextBroadcast
中从队列中取出一个有效广播,处理完一个广播接收器后,会触发 AMS.finishReceiver
结束整个广播过程。但是 finishReceiver
方法每次都会调用 BroadcastQueue.finishReceiverLocked
检查 mOrderedBroadcasts
是否全部处理完毕。如果没有,调用 processNextBroadcast
继续从有序队列中取出广播处理。具体可以参考“广播 ANR
” 中的 Log
分析。
进程和线程间交互
Handler
线程间异步通信
LocalBroadcastManager
同一个应用相同进程内异步通信,本质上仍然是通过 Handler
实现的
BroadCastReceiver
进程间异步通信,不同应用不同进程间的通信,通过系统广播总线统一管理广播,用户使用很简单方便
Messenger
进程间异步通信,相同应用不同进程间的通信,常用于 Activity, Service
不在同一进程时使用
AIDL
进程间同步通信
参考文档