引言
广播是一种典型的发布/订阅模式,消息的生产者发布消息,而接收者订阅感兴趣的信息。高内聚低耦合性是判断软件设计好坏的标准,Broadcast把高内聚低耦合做得非常好,当你想发送广播的时候,你根本不用知道接收者的名字,也不用关心谁来接收,你只管发消息即可。
由图可知:广播主要分为三个阶段。第一个阶段:广播接收者APP1、APP2、APP3先往AMS注册感兴趣的广播。第二个阶段:广播发送者APP4发送一个广播。第三个阶段:AMS查找谁对APP4发送的广播感兴趣,找到后就把广播发送给对其感兴趣的广播接收者APP1、APP2、APP3.
应用层如何注册动态广播
private static final String TAG = "TEST_BROADCAST";
public static final String ACTION_TEST_BROADCAST = "android.intent.action.TEST_BROADCAST";
public static final String ACTION_TEST_BROADCAST2 = "android.intent.action.TEST_BROADCAST2";
private void registerReceiver() {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ACTION_TEST_BROADCAST);
intentFilter.addAction(ACTION_TEST_BROADCAST2);
registerReceiver(mBroadcastReceiver,intentFilter);
}
public static BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_TEST_BROADCAST)){
Log.d(TAG, "mBroadcastReceiver onReceive action = " + ACTION_TEST_BROADCAST);
} else if (intent.getAction().equals(ACTION_TEST_BROADCAST2)){
Log.d(TAG, "mBroadcastReceiver onReceive action = " + ACTION_TEST_BROADCAST2);
}
}
};
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mBroadcastReceiver);
}
通过方法registerReceiver注册一个广播。它需要两个参数,第一个参数类型是BroadcastReceiver,第二个参数类型是IntentFilter。BroadcastReceiver用来接收广播,IntentFilter用来存放广播的Action等信息。目的在将Action与BroadcastReceiver进行绑定,Action与BroadcastReceiver在这里是多对一的关系,在其他场景下可能是多对多的关系。
流程分析
应用进程部分
registerReceiver是广播进行注册的核心方法,我们看看这个方法的调用过程。registerReceiver调用的是定义在ContextWrapper中的方法。
@Override
public Intent registerReceiver(@Nullable BroadcastReceiver receiver, IntentFilter filter) {
return mBase.registerReceiver(receiver, filter);
}
ContextWrapper类中的registerReceiver方法又调用了mBase对象的registerReceiver,mBase指的是ContextImpl对象。
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
return registerReceiver(receiver, filter, null, null);
}
两个参数的会调用4个参数的。其中broadcastPermission和Handler类型的数据传入null。
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
String broadcastPermission, Handler scheduler) {
return registerReceiverInternal(receiver, getUserId(),
filter, broadcastPermission, scheduler, getOuterContext(), 0);
}
registerReceiver又会调用registerReceiverInternal。这里增加了三个参数。第一个getUserId()是进程的userid,第二个getOuterContext()是MainActivity对象,第三个flags是一个int类型的值,这里传入的是0. 我们看下registerReceiverInternal。
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();
}
}
receiver是前面传递过来的BroadcastReceiver类型的对象,它不为空,第一个if条件成立。context是getOuterContext的值,值为MainActivity对象,也不为空。变量mPackageInfo是一个LoadedApk类型的变量,它用来负责处理广播的接收,发送广播之后会经过它分发出去,它也不为空(这个的赋值过程以后再讲,我们着眼于重点部分),所以if (mPackageInfo != null && context != null) {成立。scheduler为空,因为传递的过程中赋值给null,所以这里scheduler会通过mMainThread的getHandler方法获得Handler对象,这个Handler就是ActivityThread中的Handler对象,也就是主线程的Handler对象。接着,会通过mPackageInfo的getReceiverDispatcher获取一个IIntentReceiver类型的对象rd,它是一个binder对象。
我们看下getReceiverDispatcher方法。它一共有5个参数,分别是BroadcastReceiver类型的对象,MainActivity对象,Handler对象,Instrumentation对象,以及一个bool类型的变量。
public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
Context context, Handler handler,
Instrumentation instrumentation, boolean registered) {
synchronized (mReceivers) {
LoadedApk.ReceiverDispatcher rd = null;
ArrayMap 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();
mReceivers.put(context, map);
}
map.put(r, rd);
}
} else {
rd.validate(context, handler);
}
rd.mForgotten = false;
return rd.getIIntentReceiver();
}
}
private final ArrayMap> mReceivers
= new ArrayMap<>();
这里首先会拿一把锁mReceivers,mReceivers如上,是一个ArrayMap数组,key是Context类型的,value也是一个ArrayMap,k是BroadcastReceiver类型,v是ReceiverDispatcher类型。
接着看第一个if,registered是传递进来的,是true,所以这个条件成立,条件成立就会去mReceivers中查找是否有以传入进来的context对象为key的value,如果有取出这个value,也就是ArrayMap
ReceiverDispatcher,顾名思义,是一个广播分发器。从mReceivers数据结构就可以得出,通过MainActivity对象就可以找到ArrayMap
现在看下getReceiverDispatcher的返回值,它的类型是IIntentReceiver,通过ReceiverDispatcher的getIIntentReceiver方法获取。我们看下ReceiverDispatcher和getIIntentReceiver。
static final class ReceiverDispatcher {
final static class InnerReceiver extends IIntentReceiver.Stub {
final WeakReference mDispatcher;
final LoadedApk.ReceiverDispatcher mStrongRef;
InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
mDispatcher = new WeakReference(rd);
mStrongRef = strong ? rd : null;
}
...
final IIntentReceiver.Stub mIIntentReceiver;
...
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;
}
...
}
由上可知,getIIntentReceiver返回mIIntentReceiver,它是InnerReceiver类的对象。InnerReceiver是ReceiverDispatcher的内部类,创建是在ReceiverDispatcher构造方法中,InnerReceiver继承自IIntentReceiver.Stub,它是一个Binder对象。InnerReceiver保存了外部类ReceiverDispatcher的对象。所以通过返回的InnerReceiver binder对象,就可以找到ReceiverDispatcher对象。如图所示:
现在返回registerReceiverInternal方法中。
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();
}
registerReceiverInternal获取到IIntentReceiver binder对象之后,会通过ActivityManager调用registerReceiver,它是一个binder调用,它一共有7个参数:第一个参数是ApplicationThread binder对象,第二个参数是包名,第三个参数IIntentReceiver binder对象,第四个参数Intentfilter对象,第五个参数是广播权限,第六个参数是进程的userid,第七个参数是一个int类型的flag。
总结:
-
一个Context(Activity或者Service)可能会有多个BroadcastReceiver,多个BroadcastReceiver又一一对应多个ReceiverDispatcher,多个ReceiverDispatcher又一一对应多个IIntentReceiver。
- 你会发现在应用层并没有处理filter对象,而是当作参数传给了system_server进程。
system_server 部分
ActivityManager.getService().registerReceiver会调用到AMS的registerReceiver方法。
public Intent registerReceiver(IApplicationThread caller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
int flags) {
...
ProcessRecord callerApp = null;
...
int callingUid;
int callingPid;
...
synchronized(this) {
// 1
if (caller != null) {
callerApp = getRecordForAppLocked(caller);
...
callingUid = callerApp.info.uid;
callingPid = callerApp.pid;
} else {
callerPackage = null;
callingUid = Binder.getCallingUid();
callingPid = Binder.getCallingPid();
}
...
// Collect stickies of users
...
}
...
// The first sticky in the list is returned directly back to the client.
...
synchronized (this) {
...
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);
}
...
// 2
mRegisteredReceivers.put(receiver.asBinder(), rl);
}
...
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
permission, callingUid, userId, instantApp, visibleToInstantApps);
if (rl.containsFilter(filter)) {
Slog.w(TAG, "Receiver with filter " + filter
+ " already registered for pid " + rl.pid
+ ", callerPackage is " + callerPackage);
} else {
rl.add(bf);
...
// 3
mReceiverResolver.addFilter(bf);
}
// Enqueue broadcasts for all existing stickies that match
// this filter.
...
return sticky;
}
}
/**
* Keeps track of all IIntentReceivers that have been registered for broadcasts.
* Hash keys are the receiver IBinder, hash value is a ReceiverList.
*/
final HashMap mRegisteredReceivers = new HashMap<>();
/**
* Resolver for broadcast intents to registered receivers.
* Holds BroadcastFilter (subclass of IntentFilter).
*/
final IntentResolver mReceiverResolver
= new IntentResolver() {
...
};
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;
}
BroadcastFilter(IntentFilter _filter, ReceiverList _receiverList,
String _packageName, String _requiredPermission, int _owningUid, int _userId,
boolean _instantApp, boolean _visibleToInstantApp) {
super(_filter);
receiverList = _receiverList;
packageName = _packageName;
requiredPermission = _requiredPermission;
owningUid = _owningUid;
owningUserId = _userId;
instantApp = _instantApp;
visibleToInstantApp = _visibleToInstantApp;
}
/**
* All filters that have been registered.
*/
private final ArraySet mFilters = new ArraySet();
AMS的registerReceiver主要分为三个部分,分别是代码1,代码2,代码3.
代码1:利用传递过来的ApplicationThread binder对象获取注册广播的应用的信息的存储变量callerApp,它的类型是ProcessRecord。在这里获取应用的uid和进程的pid。system_server如果注册的广播,会走到else部分,即callerPackage=null。
代码2:mRegisteredReceivers是一个以IIntentReceiver为key,以rl即ReceiverList列表为value的hashmap,IIntentReceiver不再多做解释,ReceiverList用来保存IIntentReceiver。
代码3:BroadcastFilter对象的目的是关联ReceiverList和IntentFilter。mReceiverResolver存储所有的BroadcastFilter到mFilters。
参考
忘了参考的哪里了,大部分自己看的。继续努力。