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

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机制进行一些讨论



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值