广播作为 Android 开发的四大组间之一,当我们发送广播以后,发生了什么?广播接收者最终如何收到了广播。
一、复盘广播的使用在 Android 开发中使用广播分为三个步骤:
1.新建广播接收者 BroadcastReceiver;
2.注册广播接收者,分为静态和动态注册两种方式;
3.其他组间通过 sendBroadcast 向 BroadcastReceiver 发送广播,然后接收者处理。
我在分析流程中使用了动态注册的方式。在 Activity onResume 中注册,onPause 中取消注册。以下是创建 BroadcastReceiver 的代码。
class MainActivity : AppCompatActivity() {
......
inner class MainActivityBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
if (null != intent && intent.action == ACTION) {
val str = intent.getStringExtra(VALUE_KEY)
Log.d(TAG, "MainActivityBroadcastReceiver onReceive str=$str")
}
}
}
......
}
接着在 Service 中调用 sendBroadcast。
二、广播接收者注册广播接收者注册调用了 registerReceiver 方法。
class MainActivity : AppCompatActivity() {
companion object {
const val TAG = "MainActivity"
const val ACTION = "com.demo.framework.ACTION"
const val VALUE_KEY = "value_key"
}
private var mMainActivityBroadcastReceiver: MainActivityBroadcastReceiver = MainActivityBroadcastReceiver()
......
override fun onResume() {
super.onResume()
val intentFilter = IntentFilter(ACTION)
registerReceiver(mMainActivityBroadcastReceiver, intentFilter)
}
override fun onPause() {
super.onPause()
unregisterReceiver(mMainActivityBroadcastReceiver)
}
......
}
registerReceiver 方法来自 ContextWrapper 类,回顾 Android AOSP 6.0.1 startService启动流程分析 一节可知,最终调用了 ContextImpl 类中的 registerReceiver 方法。registerReceiver 方法最后调用了 registerReceiverInternal 方法。
frameworks/base/core/java/android/content/ContextWrapper.java
public class ContextWrapper extends Context {
......
@Override
public Intent registerReceiver(
BroadcastReceiver receiver, IntentFilter filter) {
return mBase.registerReceiver(receiver, filter);
}
......
}
frameworks/base/core/java/android/app/ContextImpl.java
class ContextImpl extends Context {
......
@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());
}
......
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;
}
}
}
熟悉的流程,在 registerReceiverInternal 方法中先获取 ActivityManagerProxy,然后调用它的 registerReceiver 方法。在 registerReceiverInternal 函数中主要用来构建 rd 局部变量,它是 IIntentReceiver 类型。rd 对象是经过 mPackageInfo 调用它的 getReceiverDispatcher 方法获取的。mPackageInfo 是一个 LoadedApk 类型。
frameworks/base/core/java/android/app/LoadedApk.java
public final class LoadedApk {
......
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();
}
}
......
}
以上一段代码并不难理解,mReceivers 是 ArrayMap<Context, ArrayMap> 类型的对象,它是以 Context 作为 key, ArrayMap 作为值的。这个 Context 其实就是对应的 Activity,而值是 BroadcastReceiver-ReceiverDispatcher 组成的键值对。同一个 Activity 里可以创建很多个 BroadcastReceiver,每个 BroadcastReceiver 都会对应一个 ReceiverDispatcher。没有注册过的 BroadcastReceiver,rd == null 分支会为 true,然后 new 一个 ReceiverDispatcher 对象。最后把键值对添加到 mReceivers 中。
frameworks/base/core/java/android/app/LoadedApk.java
public final class LoadedApk {
......
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;
final BroadcastReceiver mReceiver;
final Context mContext;
final Handler mActivityThread;
final Instrumentation mInstrumentation;
final boolean mRegistered;
final IntentReceiverLeaked mLocation;
RuntimeException mUnregisterLocation;
boolean mForgotten;
......
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 Field 是一个 InnerReceiver 类型,它的构造函数只是简单的为其 Field 赋值, mDispatcher 是一个弱引用对象。这里 mStrongRef 为 null。现在继续前面的思路,拿到 ActivityManagerProxy 对象,调用其 registerReceiver 方法。
frameworks/base/core/java/android/app/ActivityManagerNative.java
class ActivityManagerProxy implements IActivityManager
{
......
public Intent registerReceiver(IApplicationThread caller, String packageName,
IIntentReceiver receiver,
IntentFilter filter, String perm, int userId) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
data.writeString(packageName);
data.writeStrongBinder(receiver != null ? receiver.asBinder() : null);
filter.writeToParcel(data, 0);
data.writeString(perm);
data.writeInt(userId);
mRemote.transact(REGISTER_RECEIVER_TRANSACTION, data, reply, 0);
reply.readException();
Intent intent = null;
int haveIntent = reply.readInt();
if (haveIntent != 0) {
intent = Intent.CREATOR.createFromParcel(reply);
}
reply.recycle();
data.recycle();
return intent;
}
......
}
通过 Binder 机制实际远程调用了 ActivityManagerService 中的同名 registerReceiver 方法。
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
......
// 跟踪已注册用于广播的所有 IIntentReceiver。 哈希键是接收者 IBinder,哈希值是 ReceiverList。
final HashMap mRegisteredReceivers = new HashMap();
......
public Intent registerReceiver(IApplicationThread caller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter, String permission, int userId) {
enforceNotIsolatedCaller("registerReceiver");
ArrayList stickyIntents = null;
ProcessRecord callerApp = null;
int callingUid;
int callingPid;
synchronized(this) {
if (caller != null) {
callerApp = getRecordForAppLocked(caller);
......
// 给调用者 uid 和 pid 赋值
callingUid = callerApp.info.uid;
callingPid = callerApp.pid;
} else {
......
}
userId = handleIncomingUser(callingPid, callingUid, userId,
true, ALLOW_FULL_ONLY, "registerReceiver", callerPackage);
// 获取 IntentFilter 中 action 迭代器
Iterator actions = filter.actionsIterator();
if (actions == null) {
ArrayList noAction = new ArrayList(1);
noAction.add(null);
actions = noAction.iterator();
}
......
}
......
synchronized (this) {
if (callerApp != null && (callerApp.thread == null
|| callerApp.thread.asBinder() != caller.asBinder())) {
// Original caller already died
return null;
}
// 1.获取 ReceiverList 对象
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
if (rl == null) {
rl = new ReceiverList(this, callerApp, callingPid, callingUid,
userId, receiver);
if (rl.app != null) {
// 2.添加 ReceiverList 对象到 ProcessRecord 对象的 receivers field
rl.app.receivers.add(rl);
} else {
try {
receiver.asBinder().linkToDeath(rl, 0);
} catch (RemoteException e) {
return sticky;
}
rl.linkedToDeath = true;
}
// 3.添加 ReceiverList 对象到 mRegisteredReceivers
mRegisteredReceivers.put(receiver.asBinder(), rl);
} else if (rl.uid != callingUid) {
throw new IllegalArgumentException(
"Receiver requested to register for uid " + callingUid
+ " was previously registered for uid " + rl.uid);
} else if (rl.pid != callingPid) {
throw new IllegalArgumentException(
"Receiver requested to register for pid " + callingPid
+ " was previously registered for pid " + rl.pid);
} else if (rl.userId != userId) {
throw new IllegalArgumentException(
"Receiver requested to register for user " + userId
+ " was previously registered for user " + rl.userId);
}
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
permission, callingUid, userId);
// 4.ReceiverList 添加对应的 BroadcastFilter
rl.add(bf);
if (!bf.debugCheck()) {
Slog.w(TAG, "==> For Dynamic broadcast");
}
// 5.添加 BroadcastFilter 对象到 mReceiverResolver
mReceiverResolver.addFilter(bf);
......
}
}
......
}
1.获取 ReceiverList 对象
mRegisteredReceivers 是一个 HashMap,现从这个 HashMap 中查找对应的 ReceiverList 是否存在,如果不存在就 new 一个 ReceiverList 对象。
frameworks/base/services/core/java/com/android/server/am/ReceiverList.java
final class ReceiverList extends ArrayList
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;
}
......
}
2.添加 ReceiverList 对象到 ProcessRecord 对象的 receivers,实际上是一个 ArraySet 对象。
frameworks/base/services/core/java/com/android/server/am/ProcessRecord.java
final class ProcessRecord {
......
// 该进程注册的所有 IIntentReceivers。
final ArraySet receivers = new ArraySet();
......
}
3.添加新创建的 ReceiverList 对象到 mRegisteredReceivers。
4.ReceiverList 添加对应的 BroadcastFilter。
frameworks/base/services/core/java/com/android/server/am/BroadcastFilter.java
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;
}
......
}
5.添加 BroadcastFilter 对象到 mReceiverResolver,mReceiverResolver 是 IntentResolver 类型,它实现了 IntentResolver 抽象类。 其 addFilter 方法调用 mFilters 的 add 方法将 BroadcastFilter 添加到 ArraySet,这个 Set 代表所有已注册的过滤器。然后调用 register_intent_filter 和 register_mime_types 方法将 BroadcastFilter “分解”添加到各个容器中。
frameworks/base/services/core/java/com/android/server/IntentResolver.java
public abstract class IntentResolver {
final private static String TAG = "IntentResolver";
final private static boolean DEBUG = false;
final private static boolean localLOGV = DEBUG || false;
final private static boolean localVerificationLOGV = DEBUG || false;
public void addFilter(F f) {
if (localLOGV) {
Slog.v(TAG, "Adding filter: " + f);
f.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), " ");
Slog.v(TAG, " Building Lookup Maps:");
}
mFilters.add(f);
int numS = register_intent_filter(f, f.schemesIterator(),
mSchemeToFilter, " Scheme: ");
int numT = register_mime_types(f, " Type: ");
if (numS == 0 && numT == 0) {
register_intent_filter(f, f.actionsIterator(),
mActionToFilter, " Action: ");
}
if (numT != 0) {
register_intent_filter(f, f.actionsIterator(),
mTypedActionToFilter, " TypedAction: ");
}
}
......
private final ArraySet mFilters = new ArraySet();
private final ArrayMap mTypeToFilter = new ArrayMap();
private final ArrayMap mBaseTypeToFilter = new ArrayMap();
private final ArrayMap mWildTypeToFilter = new ArrayMap();
private final ArrayMap mSchemeToFilter = new ArrayMap();
private final ArrayMap mActionToFilter = new ArrayMap();
private final ArrayMap mTypedActionToFilter = new ArrayMap();
}
打印一下 Log 查看调用过程。
07-10 01:58:24.078 2481-2481/com.demo.framework V/lhw: ContextImpl registerReceiver receiver=com.demo.framework.MainActivity$MainActivityBroadcastReceiver@8b54cc8,filter=android.content.IntentFilter@d46d161
07-10 01:58:24.078 2481-2481/com.demo.framework V/lhw: ContextImpl registerReceiverInternal receiver=com.demo.framework.MainActivity$MainActivityBroadcastReceiver@8b54cc8,userId=0,filter=android.content.IntentFilter@d46d161,broadcastPermission=null,context=com.demo.framework.MainActivity@5ad9602
07-10 01:58:24.078 2481-2481/com.demo.framework V/lhw: ContextImpl registerReceiverInternal mPackageInfo=android.app.LoadedApk@6f21ea2,scheduler=Handler (android.app.ActivityThread$H) {db89733}
07-10 01:58:24.078 2481-2481/com.demo.framework V/lhw: ActivityManagerProxy registerReceiver caller=android.app.ActivityThread$ApplicationThread@a1c1af0,packageName=com.demo.framework,receiver=android.app.LoadedApk$ReceiverDispatcher$InnerReceiver@cf8e486,filter=android.content.IntentFilter@d46d161,perm=null,userId=0
07-10 01:58:24.079 774-1388/system_process V/lhw: ActivityManagerService registerReceiver caller=android.app.ApplicationThreadProxy@6775003,callerPackage=com.demo.framework,receiver=android.content.IIntentReceiver$Stub$Proxy@802b80,filter=android.content.IntentFilter@8d3b5b9,permission=null,userId=0
最后画时序图作为总结。
作者:tyyj90