Broadcast 分析之 registerReceiver()
注册广播接收者
// frameworks/base/core/java/android/content/Context.java
public abstract Intent registerReceiver(@Nullable BroadcastReceiver receiver,IntentFilter filter);
最后会调用到 ContextImpl
// frameworks/base/core/java/android/app/ContextImpl.java
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
return registerReceiver(receiver, filter, null, null);
}
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
IntentFilter filter, String broadcastPermission,
Handler scheduler, Context context, int flags) {
// frameworks/base/core/java/android/app/ContextImpl.java
IIntentReceiver rd = null;
if (receiver != null) {
if (mPackageInfo != null && context != null) {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
// 1. 构造 IIntentReceiver, 在这里会传入 receiver 实例,方便后面回调 onReceive()
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 {
// 2. 调用 AMS.registerReceiverWithFeature方法注册到AMS, 并把 IIntentReceiver 传递进去
final Intent intent = ActivityManager.getService().registerReceiverWithFeature(
mMainThread.getApplicationThread(), mBasePackageName, getAttributionTag(), rd,
filter, broadcastPermission, userId, flags);
if (intent != null) {
intent.setExtrasClassLoader(getClassLoader());
intent.prepareToEnterProcess();
}
return intent;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
- 构造 IIntentReceiver
// frameworks/base/core/java/android/app/LoadedApk.java
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) {
// map 中未缓存,则直接构造
rd = new ReceiverDispatcher(r, context, handler,
instrumentation, registered);
if (registered) {
if (map == null) {
map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
// private final ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers = new ArrayMap<>();
// 保存已注册的广播接收者,
// 一个 context 对应多个 map,
// map中: BroadcastReceiver 对应多个 ReceiverDispatcher
mReceivers.put(context, map);
}
map.put(r, rd);
}
} else {
rd.validate(context, handler);
}
rd.mForgotten = false;
return rd.getIIntentReceiver();
}
}
ReceiverDispatcher 是 LoadedApk的内部类
// frameworks/base/core/java/android/app/LoadedApk.java
ReceiverDispatcher(BroadcastReceiver receiver, Context context,
Handler activityThread, Instrumentation instrumentation,
boolean registered) {
if (activityThread == null) {
throw new NullPointerException("Handler must not be null");
}
// mIIntentReceiver 是 IIntentReceiver.Stub 的子类,作为跨进程通信实体
mIIntentReceiver = new InnerReceiver(this, !registered);
mReceiver = receiver;
mContext = context;
mActivityThread = activityThread;
mInstrumentation = instrumentation;
mRegistered = registered;
mLocation = new IntentReceiverLeaked(null);
mLocation.fillInStackTrace();
}
final static class InnerReceiver extends IIntentReceiver.Stub {
@Override
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
// 省略部分
// 实际上这里在其他地方发送广播时,经过一系列处理会被回调
}
}
- 调用 AMS.registerReceiverWithFeature方法注册到AMS, 并把 IIntentReceiver 传递进去
public Intent registerReceiverWithFeature(IApplicationThread caller, String callerPackage,
String callerFeatureId, IIntentReceiver receiver, IntentFilter filter,
String permission, int userId, int flags) {
// 省略部分
synchronized(this) {
// 省略部分
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
if (rl == null) {
//根据receiver创建出一个ReceiverList,为啥是个List?因为很有可能一个Receiver可能接受多个广播
rl = new ReceiverList(this, callerApp, callingPid, callingUid,
userId, receiver);
if (rl.app != null) {
final int totalReceiversForApp = rl.app.receivers.size();
if (totalReceiversForApp >= MAX_RECEIVERS_ALLOWED_PER_APP) {
throw new IllegalStateException("Too many receivers, total of "
+ totalReceiversForApp + ", registered for pid: "+ rl.pid + ", callerPackage: " + callerPackage);
}
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);
}
//构造出对应的BroadcastFilter,主要为了方便到时候发送端方便寻找到这个接受端
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, callerFeatureId,
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 {
// //bf被添加到了对应的rl
rl.add(bf);
if (!bf.debugCheck()) {
Slog.w(TAG, "==> For Dynamic broadcast");
}
mReceiverResolver.addFilter(bf);
}
}
}
在AMS中把广播的对应ReceiverList创建出来,而且与Filter进行映射好,这样广播接受者在AMS中的注册就算完成,销毁的原理大抵相似。
本文深入探讨了Android中的BroadcastReceiver注册流程,从ContextImpl的涉及,到IIntentReceiver的构造,再到ReceiverDispatcher和AMS的交互。通过AMS的registerReceiverWithFeature方法,广播接收者成功注册,并与过滤器映射,完成在系统中的登记。注销过程与此类似。
2701

被折叠的 条评论
为什么被折叠?



