剖析ActivityManagerService源码,了解广播接收和发送机制

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

    原文作者:朱宇翔
    原文地址: https://blog.csdn.net/Honored_/article/details/73089389
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞