从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());
}
这里从参数中可以看到两个特殊参数,一个时权限,一个是Handler,于此同时传递进去的还有getOuterContext()
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();
}
}
try {
return ActivityManagerNative.getDefault().registerReceiver(
mMainThread.getApplicationThread(), mBasePackageName,
rd, filter, broadcastPermission, userId);
} catch (RemoteException e) {
return null;
}
}
有个参数是通过ActivityThread得到的,这个对象是一个监控对象,在ActivityThread创建的时候创建
public Instrumentation getInstrumentation()
{
return mInstrumentation;
}
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();
}
}
在这里需要注意几个数据结构
private final ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers = new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();
这个方法的逻辑是:
首先会从这个mReceivers数据结构中根据Context获取
ArrayMap<BroadcastReceiver, ReceiverDispatcher>
这个数据结构,如果这个广播有ReceiverDispatcher,则调用
LoadedApk.ReceiverDispatcher.getIIntentReceiver();
将结果返回,如果没有的话将传递进来的
BroadcastReceiver r
Context context
Handler handler
Instrumentation instrumentation
封装成一个ReceiverDispatcher然后添加到mReceivers.put(context, map);
总体来说,就是mReceivers这个数据结构是根据Context存储一个ArrayMap<BroadcastReceiver, ReceiverDispatcher> map
的数据结构,这也就是一个Context可以存储多个广播,一个广播是以广播注册者为单位,可以对应多个广播派发者。
==那我们要知道==
LoadedApk.ReceiverDispatcher.getIIntentReceiver();
这个到底是什么?
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();
}
我们通过
IIntentReceiver getIIntentReceiver() {
return mIIntentReceiver;
}
得到的就是ReceiverDispatcher构造中创建的这个:
mIIntentReceiver = new InnerReceiver(this, !registered);
我们好奇这个对象干啥
final static class InnerReceiver extends IIntentReceiver.Stub {
final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
final LoadedApk.ReceiverDispatcher mStrongRef;
InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
mStrongRef = strong ? rd : null;
}
通过构造和类的声明我们知道目的是包装了LoadedApk.ReceiverDispatcher,我们记得之前传递的时false,现在这里就是true,所以保存的强弱引用都有。并且这个时Binder对象。
也就是说getReceiverDispatcher将这个对象返回出去。传递到了AMS中。
return ActivityManagerNative.getDefault().registerReceiver(
mMainThread.getApplicationThread(), mBasePackageName,
rd, filter, broadcastPermission, userId);
所以传递进去的参数有:
- ActivityThread
- 包名
- Dispatcher
- IntentFilter
- broadcastPermission
- userId
AMS中的registerReceiver
public Intent registerReceiver(IApplicationThread caller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter, String permission, int userId) {
enforceNotIsolatedCaller("registerReceiver");
ArrayList<Intent> stickyIntents = null;
ProcessRecord callerApp = null;
int callingUid;
int callingPid;
synchronized(this) {
//得到调用者进程的信息
if (caller != null) {
callerApp = getRecordForAppLocked(caller);
callingUid = callerApp.info.uid;
callingPid = callerApp.pid;
} else {
callerPackage = null;
callingUid = Binder.getCallingUid();
callingPid = Binder.getCallingPid();
}
//得到userid
userId = handleIncomingUser(callingPid, callingUid, userId,
true, ALLOW_FULL_ONLY, "registerReceiver", callerPackage);
//遍历filter的action
Iterator<String> actions = filter.actionsIterator();
if (actions == null) {
ArrayList<String> noAction = new ArrayList<String>(1);
noAction.add(null);
actions = noAction.iterator();
}
//所有都会有一个actions列表
//得到userId列表
int[] userIds = { UserHandle.USER_ALL, UserHandle.getUserId(callingUid) };
//遍历所有的actions,对于每一个action遍历所有的id
//并且从粘连广播集合中根据id获取一个以Activity对应多个Intent的列表
while (actions.hasNext()) {
String action = actions.next();
for (int id : userIds) {
ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(id);
if (stickies != null) {
ArrayList<Intent> intents = stickies.get(action);
if (intents != null) {
if (stickyIntents == null) {
stickyIntents = new ArrayList<Intent>();
}
stickyIntents.addAll(intents);
}
}
}
}
//这块也就是说,如果有粘连广播,并且粘连广播有intent则将这些intents添加到粘连广播列表集合中。
//小结就是:
//根据filter得到这条广播所有的actions
//根据actions得到每一条action
//然后看看总体的粘连广播列表中有没有对应的action如果有,则将所有的intent遍历出来,添加到一个缓存集合中。
//也就是说如果mStickyBroadcasts有当前记录的action则将其缓存到stickyIntents的集合中
//这块代码时粘连广播intent将其将其与filter进行匹配将匹配到的intent添加到一个缓存中去(allSticky)
ArrayList<Intent> allSticky = null;
if (stickyIntents != null) {
final ContentResolver resolver = mContext.getContentResolver();
// Look for any matching sticky broadcasts...
for (int i = 0, N = stickyIntents.size(); i < N; i++) {
Intent intent = stickyIntents.get(i);
// If intent has scheme "content", it will need to acccess
// provider that needs to lock mProviderMap in ActivityThread
// and also it may need to wait application response, so we
// cannot lock ActivityManagerService here.
if (filter.match(resolver, intent, true, TAG) >= 0) {
if (allSticky == null) {
allSticky = new ArrayList<Intent>();
}
allSticky.add(intent);
}
}
}
//到了这一步allSticky就存储有关当前这个广播对应的所有intent
Intent sticky = allSticky != null ? allSticky.get(0) : null; 如果intent的话,拿出第一个intent赋给sticky,否则就是null
synchronized (this) {
if (callerApp != null && (callerApp.thread == null
|| callerApp.thread.asBinder() != caller.asBinder())) {
return null;
}
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
//从一个HashMap<IBinder, ReceiverList>中看这个receiver有木有ReceiverList
//如果木有则进行添加到这个列表中,并且注册死亡回调。
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);
}
//将filter进行封装,并且添加到ReceiverList中
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
permission, callingUid, userId);
rl.add(bf);
if (!bf.debugCheck()) {
Slog.w(TAG, "==> For Dynamic broadcast");
}
mReceiverResolver.addFilter(bf);
// Enqueue broadcasts for all existing stickies that match
// this filter.
if (allSticky != null) {
ArrayList receivers = new ArrayList();
receivers.add(bf);
final int stickyCount = allSticky.size();
for (int i = 0; i < stickyCount; i++) {
Intent intent = allSticky.get(i);
BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, null,
null, -1, -1, null, null, AppOpsManager.OP_NONE, null, receivers,
null, 0, null, null, false, true, true, -1);
queue.enqueueParallelBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
}
}
return sticky;
}
这里需要清楚数据结构的关系
如果第一次进入则:
rl = new ReceiverList(this, callerApp, callingPid, callingUid, userId, receiver);
rl.app.receivers.add(rl);
也就是将生成的rl添加到调用者的ProcessRecord的ArraySet<ReceiverList> receivers
中
然后将这个ReceiverList添加到AMS的HashMap<IBinder, ReceiverList> mRegisteredReceivers
,也就是ReceiverList,在那个app进程中有记录,在AMS中也有记录.于此同时mReceiverResolver中有对应的BroadcastFilter,这个BroadcastFilter也在那个app进程中也有.
最后面是将匹配到的粘连广播发送,所以粘连广播时在广播注册的时候发送的.
也就是说,只要有一个广播注册,就会匹配看是不粘连广播,如果是粘连则将粘连广播发送给这个接收者.
清楚这些数据结构之间的关系
final HashMap<IBinder, ReceiverList> mRegisteredReceivers = new HashMap<>();
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
if (rl == null) {
ReceiverList rl = new ReceiverList(this, callerApp, callingPid, callingUid,userId, receiver);
mRegisteredReceivers.put(receiver.asBinder(), rl);
}
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,permission, callingUid, userId);
rl.add(bf);
也就是说,mRegisteredReceivers中是根据receiver.asBinder()进行匹配的,然后对应一个集合,这个集合存储的时一个BroadcastFilter列表.说明一个接收者对应多个Filter.
==我们在看看ContextImpl中==
在LoadedApk.getReceiverDispatcher()中
private final ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceiversx= new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();
这个是以BroadcastReceiver为键ReceiverDispatcher为值
网友评论