对Android广播接收与发出机制的一些AMS以外的源码分析

来源:互联网 发布:左飞 算法之美 编辑:程序博客网 时间:2024/06/06 05:40

1.简介


在安卓的广播机制中,用户自定义的Activity或自定义的子类BroadcastReceiver扮演着接收器的角色,Activity本身以及各类系统事件(如有电话拨入)也可以扮演广播发出者的角色。而其中,Android的Activity Manager Service无疑扮演着核心角色。总体上,安卓的广播采用的是订阅者、发布者的设计模式。


本文中,我们不深入AMS进行源码分析,而是关于接收与发出广播前,Activity周边依赖的一些类进行的一些初始化操作。本文也更倾向于从体系结构层次探讨广播的实现机制。


2.注册一个广播接收器


我们结合实例来进行分析。首先,我们定义一个MyActivity,用于接收广播:

public class MyActivity extends Activity implements OnClickListener {        ......        @Override         public void onCreate() {            super.onCreate();              IntentFilter counterActionFilter = new IntentFilter(CounterService.BROADCAST_COUNTER_ACTION);            registerReceiver(counterActionReceiver, counterActionFilter);        }         ......    }  

在这里,我们就通过registerReceiver方法将自己注册到广播接收器之中。让我们进行一下细致的分析。

阅读源码可知,Activity实现了Context接口,而registerReceiver正是Context的一个成员方法,而Activity继承的是ContextWrapper包装类,我们调用的是ContextWrapper实现中的registerReceiver方法,源码为:

    @Override    public Intent registerReceiver(        BroadcastReceiver receiver, IntentFilter filter) {        return mBase.registerReceiver(receiver, filter);    }

这里,mBase是ContextImpl的一个实例(在Activity初始化时,将实现类绑定到ContextWrapper包装类上,也就是我们常说的装饰者模式,这里不展开讲了)。

接下来我们看到ContextImpl中的

registerReceiver(receiver, filter);

方法:

@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;//开始寻找IIntentReceiver实例        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 {//找到实例后,调用ActivityManagerService的注册接收器方法            final Intent intent = ActivityManagerNative.getDefault().registerReceiver(                    mMainThread.getApplicationThread(), mBasePackageName,                    rd, filter, broadcastPermission, userId);            if (intent != null) {                intent.setExtrasClassLoader(getClassLoader());                intent.prepareToEnterProcess();            }            return intent;        } catch (RemoteException e) {            throw e.rethrowFromSystemServer();        }    }

我们可以看到,经过多层跳转,最后进入registerReceiverInternal方法中。此方法内先是寻找IIntentReceiver实例(这是一个Binder对象),再调用ActivityManagerNatice中的方法。

我们进入ActivityManagerNative.java中的ActivityManagerProxy的的registerReceiver中看一看:

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底层通信机制去调用AMS中的registerReceiver函数,至此,在广播接收器注册过程中,对AMS的调用的前期初始化代码已全部分析完了。

3.发送广播


大家都知道,在Service或Activity等组件类中向外发送广播可以直接调用sendBroadcast(intent);

而这里sendBroadcast方法事实上是在其父类ContextWrapper中定义的,源码如下:

    @Override    public void sendBroadcast(Intent intent) {        mBase.sendBroadcast(intent);    }
和第二章中提到的一样,mBase是ContextImpl的一个实例,因此我们看到ContextImpl中的sendBroadcast方法

    @Override    public void sendBroadcast(Intent intent) {        warnIfCallingFromSystemProcess();        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());        try {            intent.prepareToLeaveProcess(this);            ActivityManagerNative.getDefault().broadcastIntent(                    mMainThread.getApplicationThread(), intent, resolvedType, null,                    Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,                    getUserId());        } catch (RemoteException e) {            throw e.rethrowFromSystemServer();        }    }
因此,会直接深入调用ActivityManagerNative.java中的ActivityManagerProxy的broadcastIntent方法:

public int broadcastIntent(IApplicationThread caller,            Intent intent, String resolvedType, IIntentReceiver resultTo,            int resultCode, String resultData, Bundle map,            String[] requiredPermissions, int appOp, Bundle options, boolean serialized,            boolean sticky, int userId) throws RemoteException    {        Parcel data = Parcel.obtain();        Parcel reply = Parcel.obtain();        data.writeInterfaceToken(IActivityManager.descriptor);        data.writeStrongBinder(caller != null ? caller.asBinder() : null);        intent.writeToParcel(data, 0);        data.writeString(resolvedType);        data.writeStrongBinder(resultTo != null ? resultTo.asBinder() : null);        data.writeInt(resultCode);        data.writeString(resultData);        data.writeBundle(map);        data.writeStringArray(requiredPermissions);        data.writeInt(appOp);        data.writeBundle(options);        data.writeInt(serialized ? 1 : 0);        data.writeInt(sticky ? 1 : 0);        data.writeInt(userId);        mRemote.transact(BROADCAST_INTENT_TRANSACTION, data, reply, 0);        reply.readException();        int res = reply.readInt();        reply.recycle();        data.recycle();        return res;    }

随后,此进程通过Binder通信机制调用AMS中的相关方法进行广播的发送。


4. 小结


总体上,AMS外部的代码就是层层深入,进行初始化操作,而AMS内部则是通过订阅/发布的设计模式来实现广播。


下一章,我们将探讨AMS内部对于广播发送/接收机制的处理,或对Binder机制进行一些讨论



原创粉丝点击