注册广播接收器
Android系统的广播机制是一种消息订阅/发布机制,因此,使用这种消息驱动模型的第一步便是订阅消息;而对Android应用程序来说,订阅消息其实就是注册广播接收器。在Android的广播机制中,ActivityManagerService扮演着广播中心的角色,负责系统中所有广播的注册和发布操作,因此,Android应用程序注册广播接收器的过程就把是广播接收器注册到ActivityManagerService的过程。Android应用程序是通过调用ContextWrapper类的registerReceiver函数来把广播接收器BroadcastReceiver注册到ActivityManagerService中去的,而ContextWrapper类本身又借助ContextImpl类来注册广播接收器。在Android应用程序框架中,Activity和Service类都继承了ContextWrapper类,因此,我们可以在Activity或者Service的子类中调用registerReceiver函数来注册广播接收器。Activity、Service、ContextWrapper和ContextImpl这四个类的关系:
registerReceiver函数播接收器注册过程的时序图如下:
接下来对registerReceiver注册广播接收器的源码进行详细分析,由于Activity继承于Context类,Context类是一个抽象类,定义了registerReceiver接口函数,因此在Activity的子类中,可以直接调用registerregisterReceiver函数,但是Activity及其父类都没有实现registerReceiver接口函数,在Activity调用registerReceiver来注册广播接收器时,根据Activity类继承关系,会依次调用一遍其父类的registerReceiver函数,父类ContextWrapper对registerReceiver函数实现如下:
@Override
public Intent registerReceiver(
BroadcastReceiver receiver, IntentFilter filter) {
return mBase.registerReceiver(receiver, filter);
}
@Override
public Intent registerReceiver(
BroadcastReceiver receiver, IntentFilter filter,
String broadcastPermission, Handler scheduler) {
return mBase.registerReceiver(receiver, filter, broadcastPermission,
scheduler);
}
这里定义了两个registerReceiver重载函数,以上两个函数的实现都是间接调用mBase对象的registerReceiver函数,mBase定义为Context类型,在Context的子类中,ContextImpl类实现了registerReceiver函数。
@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, filter, broadcastPermission,
scheduler, getOuterContext());
}
在ContextImpl类中仍然实现了两个registerReceiver函数的重载,但他们都并没有真正实现该函数,而是调用函数registerReceiverInternal函数来完成,registerReceiverInternal函数的定义如下:
private Intent registerReceiverInternal(BroadcastReceiver receiver,
IntentFilter filter, String broadcastPermission,
Handler scheduler, Context context) {
/* broadcastPermission = null
scheduler = null */
IIntentReceiver rd = null;
if (receiver != null) {
if (mPackageInfo != null && context != null) {
if (scheduler == null) {
//获取应用程序主线程的handle对象
scheduler = mMainThread.getHandler();
}
//获取IIntentReceiver广播接收分发器
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 {
/* ActivityManagerNative.getDefault()得到ActivityManagerService在客户进程的代理类对象
ActivityManagerProxy,通过Binder进程间通信,远程调用ActivityManagerService的registerReceiver函数 */
return ActivityManagerNative.getDefault().registerReceiver(
mMainThread.getApplicationThread(), mBasePackageName,
rd, filter, broadcastPermission);
} catch (RemoteException e) {
return null;
}
}
获取Activity的上下文
final Context getOuterContext() {
return mOuterContext;
}
ContextImpl() {
mOuterContext = this;
}
由于ContextImpl类为Activity的父类,因此getOuterContext()函数得到的是注册广播接收器的Activity的上下文。
获取应用程序主线程的消息分发器handle
mMainThread.getHandler()
frameworks\base\core\java\android\app\ActivityThread.java
final Handler getHandler() {
return mH;
}
final H mH = new H();
private class H extends Handler {
public static final int LAUNCH_ACTIVITY = 100;
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
}
}
}
该handle是在ActivityThread类中定义,用于处理应用程序主线程的消息分发处理。
获取广播接收分发器
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;
HashMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
//注册广播接收器
if (registered) {
//以注册广播接收器的Activity为key从mReceivers的Hashmap表中取出该上下文对应的广播接收器表
map = mReceivers.get(context);
//根据BroadcastReceiver从广播接收器表中取出对应的LoadedApk.ReceiverDispatcher
if (map != null) {
rd = map.get(r);
}
}
//如果表中不存在,直接创建ReceiverDispatcher对象
if (rd == null) {
rd = new ReceiverDispatcher(r, context, handler,
instrumentation, registered);
//并且以<BroadcastReceiver,LoadedApk.ReceiverDispatcher>为键值对的形式保存
if (registered) {
if (map == null) {
map = new HashMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
mReceivers.put(context, map);
}
map.put(r, rd);
}
} else {
rd.validate(context, handler);
}
rd.mForgotten = false;
//取得ReceiverDispatcher对象的成员变量mIIntentReceiver
return rd.getIIntentReceiver();
}
}
注册的广播接收器的存储方式如下:
LoadedApk.mReceivers
该广播接收器表保存在LoadedApk对象的成员变量mReceivers中。
IIntentReceiver getIIntentReceiver() {
return 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();
}
InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
mStrongRef = strong ? rd : null;
}
ActivityManagerProxy注册广播接收器
public Intent registerReceiver(IApplicationThread caller, String packageName,
IIntentReceiver receiver,
IntentFilter filter, String perm) 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);
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;
}
ActivityManagerProxy通过Binder驱动程序远程调用服务进程的ActivityManagerService的registerReceiver函数来注册广播接收器。
ActivityManagerService注册广播接收器
关于广播接收器的数据结构图:public Intent registerReceiver(IApplicationThread caller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter, String permission) {
enforceNotIsolatedCaller("registerReceiver");
synchronized(this) {
ProcessRecord callerApp = null;
if (caller != null) {
//caller = mMainThread.getApplicationThread()
//获取应用程序的ProcessRecord
callerApp = getRecordForAppLocked(caller);
if (callerApp == null) {
throw new SecurityException(
"Unable to find app for caller " + caller
+ " (pid=" + Binder.getCallingPid()
+ ") when registering receiver " + receiver);
}
if (callerApp.info.uid != Process.SYSTEM_UID &&
!callerApp.pkgList.contains(callerPackage)) {
throw new SecurityException("Given caller package " + callerPackage
+ " is not running in process " + callerApp);
}
} else {
callerPackage = null;
}
List allSticky = null;
// Look for any matching sticky broadcasts...
Iterator actions = filter.actionsIterator();
if (actions != null) {
while (actions.hasNext()) {
String action = (String)actions.next();
allSticky = getStickiesLocked(action, filter, allSticky);
}
} else {
allSticky = getStickiesLocked(null, filter, allSticky);
}
// The first sticky in the list is returned directly back to
// the client.
Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
if (receiver == null) {
return sticky;
}
//从mRegisteredReceivers表中取出receiver对应的ReceiverList,ReceiverList列表用于保存BroadcastFilter
ReceiverList rl = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
if (rl == null) {
//创建ReceiverList对象
rl = new ReceiverList(this, callerApp,
Binder.getCallingPid(),
Binder.getCallingUid(), receiver);
if (rl.app != null) {
//保存到ProcessRecord的receivers成员变量中
rl.app.receivers.add(rl);
} else {
try {
receiver.asBinder().linkToDeath(rl, 0);
} catch (RemoteException e) {
return sticky;
}
rl.linkedToDeath = true;
}
//注册到mRegisteredReceivers HashMap表中
mRegisteredReceivers.put(receiver.asBinder(), rl);
}
//根据IntentFilter创建广播接收过滤器
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, permission);
//为当前广播接收器设置Action过滤器
rl.add(bf);
if (!bf.debugCheck()) {
Slog.w(TAG, "==> For Dynamic broadast");
}
mReceiverResolver.addFilter(bf);
// Enqueue broadcasts for all existing stickies that match
// this filter.
if (allSticky != null) {
ArrayList receivers = new ArrayList();
receivers.add(bf);
int N = allSticky.size();
for (int i=0; i<N; i++) {
Intent intent = (Intent)allSticky.get(i);
BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, null,
null, -1, -1, null, receivers, null, 0, null, null,
false, true, true);
queue.enqueueParallelBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
}
}
return sticky;
}
}
在ActivityManagerService中,用一个进程记录块来表示这个应用程序进程,它里面有一个列表receivers,专门用来保存这个进程注册的广播接收器。接着,又把这个ReceiverList列表以receiver为Key值保存在ActivityManagerService的成员变量mRegisteredReceivers中。创建BroadcastFilter来把广播接收器列表rl和filter关联起来,然后保存在ActivityManagerService中的成员变量mReceiverResolver中去。
注消广播接收器
frameworks\base\core\java\android\content\ContextWrapper.java
public void unregisterReceiver(BroadcastReceiver receiver) {
mBase.unregisterReceiver(receiver);
}
frameworks\base\core\java\android\app\ContextImpl.java
public void unregisterReceiver(BroadcastReceiver receiver) {
if (mPackageInfo != null) {
IIntentReceiver rd = mPackageInfo.forgetReceiverDispatcher(
getOuterContext(), receiver);
try {
ActivityManagerNative.getDefault().unregisterReceiver(rd);
} catch (RemoteException e) {
}
} else {
throw new RuntimeException("Not supported in system context");
}
}
函数首先从表中查找指定广播接收器的IIntentReceiver
public IIntentReceiver forgetReceiverDispatcher(Context context,
BroadcastReceiver r) {
synchronized (mReceivers) {
//从mReceivers表中取出对应的广播接收器表
HashMap<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()) {
HashMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
= mUnregisteredReceivers.get(context);
if (holder == null) {
holder = new HashMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
mUnregisteredReceivers.put(context, holder);
}
RuntimeException ex = new IllegalArgumentException(
"Originally unregistered here:");
ex.fillInStackTrace();
rd.setUnregisterLocation(ex);
holder.put(r, rd);
}
//返回ReceiverDispatcher的IntentReceiver
rd.mForgotten = true;
return rd.getIIntentReceiver();
}
}
HashMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
= mUnregisteredReceivers.get(context);
if (holder != null) {
rd = holder.get(r);
if (rd != null) {
RuntimeException ex = rd.getUnregisterLocation();
throw new IllegalArgumentException(
"Unregistering Receiver " + r
+ " that was already unregistered", ex);
}
}
if (context == null) {
throw new IllegalStateException("Unbinding Receiver " + r
+ " from Context that is no longer in use: " + context);
} else {
throw new IllegalArgumentException("Receiver not registered: " + r);
}
}
}
通过ActivityManagerProxy代理向ActivityManagerService发送注销广播接收器的请求
public void unregisterReceiver(IIntentReceiver receiver) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(receiver.asBinder());
mRemote.transact(UNREGISTER_RECEIVER_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
reply.recycle();
}
ActivityManagerService负责广播接收器的注销工作:
public void unregisterReceiver(IIntentReceiver receiver) {
if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
final long origId = Binder.clearCallingIdentity();
try {
boolean doTrim = false;
synchronized(this) {
//从mRegisteredReceivers表中查找到receiver对应的ReceiverList
ReceiverList rl = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
if (rl != null) {
if (rl.curBroadcast != null) {
BroadcastRecord r = rl.curBroadcast;
final boolean doNext = finishReceiverLocked(
receiver.asBinder(), r.resultCode, r.resultData,
r.resultExtras, r.resultAbort, true);
if (doNext) {
doTrim = true;
r.queue.processNextBroadcast(false);
}
}
if (rl.app != null) {
//从应用进程的receivers表中移除当前广播接收器对应的ReceiverList
rl.app.receivers.remove(rl);
}
//从mRegisteredReceivers表中移除receiver,同时从mReceiverResolver的过滤Action
removeReceiverLocked(rl);
if (rl.linkedToDeath) {
rl.linkedToDeath = false;
rl.receiver.asBinder().unlinkToDeath(rl, 0);
}
}
}
// If we actually concluded any broadcasts, we might now be able
// to trim the recipients' apps from our working set
if (doTrim) {
trimApplications();
return;
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
至此广播接收器的注册与注销就介绍完了,注册的本质其实就是将广播接收器添加到ActivityManagerService的相应成员变量中存储,从而在分发广播的时候,可以根据表中注册的接收器来分发;而广播接收器的注销工作就是从相应的存储表中移除。