剖析ActivityManagerService源码,了解广播接收和发送机制
来源:互联网 发布:seo服务web678.cn 编辑:程序博客网 时间:2024/06/05 11:24
1.简介
“在安卓的广播机制中,用户自定义的Activity或自定义的子类BroadcastReceiver扮演着接收器的角色,Activity本身以及各类系统事件(如有电话拨入)也可以扮演广播发出者的角色。而其中,Android的Activity Manager Service无疑扮演着核心角色。总体上,安卓的广播采用的是订阅者、发布者的设计模式。”
---来自本人上一篇博客《对Android广播接收与发出机制的一些AMS以外的源码分析》
上一节,我们在AMS以外的部分,描述了广播接收和发送机制的原理,主要是一些初始化操作,今天我们在AMS内部观察注册广播接收器机制的原理。
2.注册广播接收器
我们先从上一篇博客的内容开始回顾。注册者线程的最后几步先是1.寻找ActivityManagerService的本地代理对象,即ActivityManagerProxy。这部分代码为:
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, filter, broadcastPermission, scheduler, getOuterContext()); } private Intent registerReceiverInternal(BroadcastReceiver receiver, 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 { ...... } } try { //这个ActivityManagerNative.getDefault(),就是事先填充的代理对象,具体大家可以参照源码研究 return ActivityManagerNative.getDefault().registerReceiver( mMainThread.getApplicationThread(), rd, filter, broadcastPermission); } catch (RemoteException e) { return null; } } ...... }
然后在ActivityManagerProxy中,使用binder机制,通过调用,mRemote.transact()方法,将数据传送给ActivityManagerService进程,至此进入ActivityManagerService内部。具体看以下代码:
public Intent registerReceiver(IApplicationThread caller, String packageName, IIntentReceiver receiver, IntentFilter filter, String perm, int userId) throws RemoteException { //这部分是向Parcel填充数据 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); //调用transact方法,注意第一个参数是“注册接收器事务”。这里的mRemote是事先填充的代理对象 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机制的介绍,具体请参照http://www.cnblogs.com/a284628487/p/3187320.html。
“客户端:客户端要想访问远程服务,必须获取远程服务在Binder对象中对应的mRemote引用,至于如何获取,下面将会介绍。获得该mRemote对象后,就可以调用其transact()方法,而在Binder驱动中,mRemote对象也重载了transact()方法,重载的内容主要包括以下几项。”
以上就是客户端的代码,我们可以容易发现mRemote是在ActivityManagerProxy的构造函数中注入的
class ActivityManagerProxy implements IActivityManager{ public ActivityManagerProxy(IBinder remote) { mRemote = remote; } public IBinder asBinder() { return mRemote; } ...........}
以上,我们对客户端的介绍就告一段落。下面是服务端的介绍:
“服务端:一个Binder服务端实际上就是一个Binder类的对象,该对象一旦创建,内部就启动一个隐藏线程。该线程接下来会接收Binder驱动发送的消息,收到消息后,会执行到Binder对象中的onTransact()函数,并按照该函数的参数执行不同的服务代码。因此,要实现一个Binder服务,就必须重载onTransact()方法。重载onTransact()函数的主要内容是把onTransact()函数的参数转换为服务函数的参数,而onTransact()函数的参数来源是客户端调用transact()函数时输入的,因此,如果transact()有固定格式的输入,那么onTransact()就会有固定格式的输出。”
因此我们必须关注到ActivityManagerProxy代理的目标进程:ActivityManagerService中的onTransact方法:
public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {.......................................@Override public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { //由于code的值为REGISTER_RECEIVER_TRANSACTION,因此不会执行if代码块的内容,所以我们划去if (code == SYSPROPS_TRANSACTION) { // We need to tell all apps about the system property change. ArrayList<IBinder> procs = new ArrayList<IBinder>(); synchronized(this) { final int NP = mProcessNames.getMap().size(); for (int ip=0; ip<NP; ip++) { SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip); final int NA = apps.size(); for (int ia=0; ia<NA; ia++) { ProcessRecord app = apps.valueAt(ia); if (app.thread != null) { procs.add(app.thread.asBinder()); } } } } int N = procs.size(); for (int i=0; i<N; i++) { Parcel data2 = Parcel.obtain(); try { procs.get(i).transact(IBinder.SYSPROPS_TRANSACTION, data2, null, 0); } catch (RemoteException e) { } data2.recycle(); } }try { //事实上我们直接调用父类的onTransact方法 return super.onTransact(code, data, reply, flags); } catch (RuntimeException e) { // The activity manager only throws security exceptions, so let's // log all others. if (!(e instanceof SecurityException)) { Slog.wtf(TAG, "Activity Manager Crash", e); } throw e; } }.....................}
而由于ActivityManagerService是ActivityManagerNative的子类,因此会调用其父类ActivityManagerNative的onTransact方法:
public abstract class ActivityManagerNative extends Binder implements IActivityManager{.................................@Override public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { switch (code) {.................................... case REGISTER_RECEIVER_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); IBinder b = data.readStrongBinder(); IApplicationThread app = b != null ? ApplicationThreadNative.asInterface(b) : null; String packageName = data.readString(); b = data.readStrongBinder(); IIntentReceiver rec = b != null ? IIntentReceiver.Stub.asInterface(b) : null; IntentFilter filter = IntentFilter.CREATOR.createFromParcel(data); String perm = data.readString(); int userId = data.readInt(); Intent intent = registerReceiver(app, packageName, rec, filter, perm, userId); reply.writeNoException(); if (intent != null) { reply.writeInt(1); intent.writeToParcel(reply, 0); } else { reply.writeInt(0); } return true; }........................ return super.onTransact(code, data, reply, flags); }}
我们注意到,这个方法根据传入的第一个参数code做switch选择。我们回顾到我们传入的参数是REGISTER_RECEIVER_TRANSACTION,因此进入了如上的case代码块.然后我们调用registerReceiver函数。需要注意的是,registerReceiver在ActivityManagerService被实现,有点像是模板方法的思想:父类使用的方法在子类延迟实现。
然后程序便跳转到ActivityManagerService中的registerReceiver方法。详情请看注释
public Intent registerReceiver(IApplicationThread caller, String callerPackage, IIntentReceiver receiver, IntentFilter filter, String permission, int userId) { enforceNotIsolatedCaller("registerReceiver"); int callingUid; int callingPid; synchronized(this) { //初始化一些值 ProcessRecord callerApp = null; if (caller != null) { 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.containsKey(callerPackage)) { throw new SecurityException("Given caller package " + callerPackage + " is not running in process " + callerApp); } callingUid = callerApp.info.uid; callingPid = callerApp.pid; } else { callerPackage = null; callingUid = Binder.getCallingUid(); callingPid = Binder.getCallingPid(); } userId = this.handleIncomingUser(callingPid, callingUid, userId, true, true, "registerReceiver", callerPackage); 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, UserHandle.USER_ALL); allSticky = getStickiesLocked(action, filter, allSticky, UserHandle.getUserId(callingUid)); } } else { allSticky = getStickiesLocked(null, filter, allSticky, UserHandle.USER_ALL); allSticky = getStickiesLocked(null, filter, allSticky, UserHandle.getUserId(callingUid)); } // The first sticky in the list is returned directly back to // the client. Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null; if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter + ": " + sticky); if (receiver == null) { return sticky; } //获取receiver列表 ReceiverList rl = (ReceiverList)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; } //把receiver添加到接收器列表中 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); rl.add(bf);//把filter和列表关联起来 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, null, AppOpsManager.OP_NONE, receivers, null, 0, null, null, false, true, true, -1); queue.enqueueParallelBroadcastLocked(r); queue.scheduleBroadcastsLocked(); } } return sticky; } }
总体上,在AMS的registerReceiver方法中就是将这个接收器添加到接收器列表中,并将接收器和他的filter对应起来。就是发布/订阅模式的订阅模型。
那么我们就介绍完了注册接收器部分,下次我们介绍发出广播的AMS模型
- 剖析ActivityManagerService源码,了解广播接收和发送机制
- 剖析ActivityManagerService源码,了解广播接收和发送机制(二)
- 发送广播和接收广播
- 接收和发送广播
- 接收和发送广播
- BroadcastReceiver源码分析系列(二):发送和接收广播
- 广播的发送和接收
- Java发送和接收广播
- C#发送和接收广播
- android 广播发送和接收
- android发送和接收广播
- 发送和接收无序广播
- 广播发送,接收和跳转
- 广播接收机制,广播发送者,广播接收者
- Android广播发送机制剖析【android广播系列二】
- 接收和发送广播 2(未完待续)
- -自定义广播的发送和接收-
- Android动态广播的发送和接收
- 使用Aspera从EBI或NCBI下载基因组数据
- 建造者模式(builder模式)
- phpredis中文手册——《redis中文手册》 php版
- 十大Intellij IDEA快捷键
- 生成式对抗网络 NIPS 2016 课程 第 2 节
- 剖析ActivityManagerService源码,了解广播接收和发送机制
- jQuery选择器总结
- 二分查找法binarySearch
- Android 华为荣耀8 logcat不打印问题解决
- 小程序开发系列(七)事件传参
- linux work queue
- JVM的自动内存管理机制
- React-Native 错误集锦
- K&R《C程序设计语言》p4:华氏温度与摄氏温度对照表