剖析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模型



原创粉丝点击