BroadCast 研究分析

最近有些人对android的Broadcast机制颇有兴趣,因此小弟就把自己看到的背后原理跟各位分享.Android的发送广播跟接收机制其实就是一种Publish/subscribepattern, Publish(发布者)只会将不同类型的讯息传送出去,并不会在意subscribe(订阅者),而subscribe(订阅者)只在意想接收的讯息,并不会在意谁是Publish(发布者). 所以Android的broadcast的核心机制大概可分为Broadcast publish, Broadcast subscribe和Broadcast content.就先从注册Broadcast subscribe也就是Broadcast reciever的流程来看吧.

1      RegisterReceiver flow

    要注册Android Broadcast receiver有两种形式, 一为动态注册,一为静态注册.静态注册是在AndroidManifest.xml上多一个receiver tag

来指定,在编译android app就指定好了, 而动态注册则会利用Context的一个registerReceiver方法来注册是属于在执行的时候

才会指定特定的receiver.由程序代码来看, Context是一个abstract class所以是一个抽象接口,因此registerReceiver是一个抽象方法.

ContextImpl 是 Context的一个实现类别, 因此registerReceiver的实作就在ContextImpl class里

[ContextImpl.java]

    @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());

    }

    Android在程序代码的设计有个很有趣的地方,那就是一旦牵扯到核心的流程,都会取个xxxInternal为名子的方法来实作.

在这个registerReceiverInternal方法中只做两件事,先将传入reciever包装产生一个IIntentReceiver, 然后再将IIntentReceiver传送给Activity Manager service 去注册.顾名思义就是在Activity thread上注册一个subscribe(订阅者),用来接收特定讯息.

[ContextImpl.java]

private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,

            IntentFilter filter, String broadcastPermission,

            Handler scheduler, Context context) {

        IIntentReceiver rd = null;

        if (receiver != null) {

                […]

                rd = mPackageInfo.getReceiverDispatcher(

                    receiver, context, scheduler,

                    mMainThread.getInstrumentation(), true);

            } else {

               […]

                rd = new LoadedApk.ReceiverDispatcher(

                        receiver, context, scheduler, null, true).getIIntentReceiver();

            }

        }

        try {

            final Intent intent = ActivityManagerNative.getDefault().registerReceiver(

                    mMainThread.getApplicationThread(), mBasePackageName,

                    rd, filter, broadcastPermission, userId);

            […]

            return intent;

        } catch (RemoteException e) {

            throw e.rethrowFromSystemServer();

        }

    }

其中mPackageInfo是一个LoadedApk的对象, 因此可以到LoadedApk class里看getReceiverDispatcher方法的实作

[LoadedApk.java]

public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,

            Context context, Handler handler,

            Instrumentation instrumentation, boolean registered) {

         synchronized (mReceivers) {

 

              LoadedApk.ReceiverDispatcher rd = null;

            ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;

            […]

 

            if (rd == null) {

                rd = new ReceiverDispatcher(r, context, handler,

                        instrumentation, registered);

                if (registered) {

                    if (map == null) {

                        map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();

                        mReceivers.put(context, map);

                    }

                    map.put(r, rd);

                }

            } else {

                rd.validate(context, handler);

            }

 

           […]

           return rd.getIIntentReceiver();

         }

}

由实作可以知道, 此方法会先产生一个receiver的ReceiverDispatcher然后再产生一个ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>来做管理.最后会执行ReceiverDispatcher的getIIntentReceiver方法.因此上面registerReceiverInternal所产生的IIntentReceiver对象是由ReceiverDispatcher准备的.在这里值得要说的是在Android的设计中,大部分IXXX开头的都是一个

Binder interface, 甚么是Binder interface简单来说就是一道两个Process的通道.Binder 的详细运作不是这次的分享,所以有兴趣的可以自己Google.由getIIntentReceiver方法回传的IItentReciever是一道Receiver Binder interface.

[LoadedApk.java]

static final class ReceiverDispatcher {

     […]

     final IIntentReceiver.Stub mIIntentReceiver;

     […]

     ReceiverDispatcher(BroadcastReceiver receiver, Context context,

                Handler activityThread, Instrumentation instrumentation,

                boolean registered) {

            […]

            mIIntentReceiver = new InnerReceiver(this, !registered);

            […]

     }

     […]

}

由上面的程序代码可知,mIIntentReceiver确实是一道Binderinterface, 这一道Binderinterface里面的运作是由InnerReceiverclass来实作的.到此为止是建立了一道Receiver binder interface(InnerReceiver), 接下来就是藉由Activity manager service来注册这一道InnerReceiver.

由registerReceiverInternal方法的程序代码来看, 要注册InnerReciever会执行

ActivityManagerNative.getDefault().registerReceiver

ActivityManagerNative. getDefault()这是一个Activity manager service的proxy.请看以下分析

[ActivityManagerNative.java]

static public IActivityManager getDefault() {

        return gDefault.get();

}

 

private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {

        protected IActivityManager create() {

            IBinder b = ServiceManager.getService("activity");

            if (false) {

                Log.v("ActivityManager", "default service binder = " + b);

            }

            IActivityManager am = asInterface(b);

            if (false) {

                Log.v("ActivityManager", "default service = " + am);

            }

            return am;

        }

};

由上面的程序代码可以知道,最后是一个IActivitManger的Activity Manger service Binder interface.这道binder interface通常称为binder proxy.所以大胆推测ActivityManagerNative里面的method都是用来使用Activity manager service的一道媒介.现在就直接来看ActivityManagerNative class的registerReceiver方法

[ActivityManagerNative.java]

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();

      […]

      mRemote.transact(REGISTER_RECEIVER_TRANSACTION, data, reply, 0);

      […]

}

mRemote.transact这一行程序代码就是要做Bindertransaction, 里面的参数就是IPCdata,经由这一道程序代码,Binder driver就会把REGISTER_RECEIVER_TRANSACTION request送给指定的service,这个service会需要看mRemote是指向哪一个 service.

[ActivityManagerNative.java]

 

static public IActivityManager asInterface(IBinder obj) {

        if (obj == null) {

            return null;

        }

        IActivityManager in =

            (IActivityManager)obj.queryLocalInterface(descriptor);

        if (in != null) {

            return in;

        }

 

        return new ActivityManagerProxy(obj);

    }

 

   […]

 

class ActivityManagerProxy implements IActivityManager

{

    public ActivityManagerProxy(IBinder remote)

{

        mRemote = remote;

}

[…]

}

[…]

由上面的程序代码可以知道,mRemote是由asInterface这个方法的参数所带进来的, 而asInterface这个方法是在上面要产生ActivityManger service Binder interface就会执行到, 要传入给asInterface方法的参数是由

IBinder b = ServiceManager.getService("activity");

这行程序代码产生, 其中的b就是activity manager service的BpBinder.所以mRemote就是activity manager service的BpBinder.因此Binder driver就会把REGISTER_RECEIVER_TRANSACTIONrequest传给Activitymanager service.

在javaframework layer中, 要接收Binder driver传送来的request都会继承一个Binder class, 里面有一个method onTransact就是用来作为接收器.

[ActivityManagerNative.java]

public boolean onTransact(int code, Parcel data, Parcel reply, int flags)

            throws RemoteException {

        switch (code) {

        […]

        case REGISTER_RECEIVER_TRANSACTION:

        // 读取IPC data

        Intent intent = registerReceiver(app, packageName, rec, filter, perm, userId);

        // 写入回传状态

        […]

        }

     return super.onTransact(code, data, reply, flags);

}

最后终于来到了Activitymanager service的registerReceivermethod

[ActivityManagerService.java]

public Intent registerReceiver(IApplicationThread caller, String callerPackage,

            IIntentReceiver receiver, IntentFilter filter, String permission, int userId) {

     

      […]

      mRegisteredReceivers.put(receiver.asBinder(), rl);

      […]

      BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,

                    permission, callingUid, userId);

      rl.add(bf);  // rl 是一个ReceiverList data.

      […]

      mReceiverResolver.addFilter(bf); // mReceiverResolver是一个IntentResolver<BroadcastFilter, BroadcastFilter> data

      […]

}

由此可知Activitymanager service会用个mRegisteredReceivers将IIntentReceiver放进Receiver list.最后在执行mReceiverResolver的addFilter新增一个BroadcastFilter.之后在发送讯息阶段时,就会利用mReceiverResolver来做传送媒介.

    由上面的分析可以做一个总结

1.    Broadcast receiver 只是一个简单的抽象类,并没有进程的通讯机制也就是Binder机制.

2.    要从Binderdriver接收讯息会需要借助InnerReceiver这一个receiver binder interface.因此LoadedApk要将BroadcastReceiver和InnerReceiver做个Map来管理.

3.    Activity manager service在将InnerReceiver记录在一个Receiver list来做维护,之后再跟IntentFilter包装成一个mReceiverResolver.

4.    整个Registerreceiver的核心都在Activitymanager service完成.

2. Send broadcast message flow

    一般要发送广播消息都会用到Context的sendBroadcast, 而Context是一个abstract class, 所以实作需要看Context的实作类别ContextImpl

[ContextImpl.java]

public void sendBroadcast(Intent intent, String receiverPermission) {

      […]

      ActivityManagerNative.getDefault().broadcastIntent(

                    mMainThread.getApplicationThread(), intent, resolvedType, null,

                    Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE,

                    null, false, false, getUserId());

      […]

}

 

 

[ActivityManagerNative.java]

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();

         […]

         mRemote.transact(BROADCAST_INTENT_TRANSACTION, data, reply, 0);

         […]

}

 

public boolean onTransact(int code, Parcel data, Parcel reply, int flags)

            throws RemoteException {

        switch (code) {

        […]

        case BROADCAST_INTENT_TRANSACTION:

        // 读取IPC data

        int res = broadcastIntent(app, intent, resolvedType, resultTo,

                    resultCode, resultData, resultExtras, perms, appOp,

                    options, serialized, sticky, userId);

        // 写入回传状态

        return true;

        […]

}

return super.onTransact(code, data, reply, flags);

}

[ActivityManagerService.java]

public final int broadcastIntent(IApplicationThread caller,

            Intent intent, String resolvedType, IIntentReceiver resultTo,

            int resultCode, String resultData, Bundle resultExtras,

            String[] requiredPermissions, int appOp, Bundle bOptions,

            boolean serialized, boolean sticky, int userId) {

            […]

            int res = broadcastIntentLocked(callerApp,

                    callerApp != null ? callerApp.info.packageName : null,

                    intent, resolvedType, resultTo, resultCode, resultData, resultExtras,

                    requiredPermissions, appOp, bOptions, serialized, sticky,

                    callingPid, callingUid, userId);

           return res;

}

 

final int broadcastIntentLocked(ProcessRecord callerApp,

            String callerPackage, Intent intent, String resolvedType,

            IIntentReceiver resultTo, int resultCode, String resultData,

            Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,

            boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) {

        

       […]

       // Figure out who all will receive this broadcast.

       List receivers = null;

List<BroadcastFilter> registeredReceivers = null;

 

[…]

registeredReceivers = mReceiverResolver.queryIntent(intent,

                        resolvedType, false, userId); // mReceiverResolver 是一个在register broadcast 阶段所产生的一个IntentResolver<BroadcastFilter, BroadcastFilter> data. 此方法会回传一个 BroadcastFilter list.

[…]

int NR = registeredReceivers != null ? registeredReceivers.size() : 0;

[…]

final BroadcastQueue queue = broadcastQueueForIntent(intent);

BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,

                    callerPackage, callingPid, callingUid, resolvedType, requiredPermissions,

                    appOp, brOptions, registeredReceivers, resultTo, resultCode, resultData,

                    resultExtras, ordered, sticky, false, userId);

[…]

queue.enqueueParallelBroadcastLocked(r);

queue.scheduleBroadcastsLocked();

[…]

while (ir < NR) {

    if (receivers == null) {

         receivers = new ArrayList();

    }

    receivers.add(registeredReceivers.get(ir));

    ir++;

}

[…]

BroadcastQueue queue = broadcastQueueForIntent(intent);

BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,

                    callerPackage, callingPid, callingUid, resolvedType,

                    requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,

                    resultData, resultExtras, ordered, sticky, false, userId);

        queue.enqueueOrderedBroadcastLocked(r);

        queue.scheduleBroadcastsLocked();

        […]

        return ActivityManager.BROADCAST_SUCCESS;

}

    由上面的执行流程,若指定为发送有次序的广播消息就会先执行BroadcastQueue 的enqueueOrderedBroadcastLocked方法. 若为一般的发送广播消息就会先执行BroadcastQueue 的enqueueParallelBroadcastLocked. 但不管是哪一个方法, 最后都会执行BroadcastQueue 的scheduleBroadcastsLocked方法来进行发送广播消息.

[BroadcastQueue.java]

public void scheduleBroadcastsLocked() {

        if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Schedule broadcasts ["

                + mQueueName + "]: current="

                + mBroadcastsScheduled);

 

        if (mBroadcastsScheduled) {

            return;

        }

        mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));

        mBroadcastsScheduled = true;

}

其中mHandler是BroadcastHandler的reference.

[BroadcastQueue.java]

private final class BroadcastHandler extends Handler {

      […]

      @Override

      public void handleMessage(Message msg) {

      […]

      case BROADCAST_INTENT_MSG: {

                    if (DEBUG_BROADCAST) Slog.v(

                            TAG_BROADCAST, "Received BROADCAST_INTENT_MSG");

                    processNextBroadcast(true);

                } break;

      […]

      }

      […]

}

[BroadcastQueue.java]

final void processNextBroadcast(boolean fromMsg) {

     […]

     BroadcastRecord r;

     […]

     if (fromMsg) {

        mBroadcastsScheduled = false;

     }

     […]

     while (mParallelBroadcasts.size() > 0) {

         r = mParallelBroadcasts.remove(0);

         […]

         final int N = r.receivers.size();

         for (int i=0; i<N; i++) {

            Object target = r.receivers.get(i);

            deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);

         }

         addBroadcastToHistoryLocked(r);

     }

     […]

}

其中 mParallelBroadcasts是一串BroadcastRecord的list. r.receivers是一个BroadcastRecord中的包含BroadcastFilter 和ResolveInfo 的list.

[BroadcastQueue.java]

private void deliverToRegisteredReceiverLocked(BroadcastRecord r,

            BroadcastFilter filter, boolean ordered, int index) {

        […]

        performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,

                        new Intent(r.intent), r.resultCode, r.resultData,

                        r.resultExtras, r.ordered, r.initialSticky, r.userId);

        […]

}

[BroadcastQueue.java]

void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,

            Intent intent, int resultCode, String data, Bundle extras,

            boolean ordered, boolean sticky, int sendingUser) throws RemoteException {

       […]

       receiver.performReceive(intent, resultCode, data, extras, ordered,

                    sticky, sendingUser);

     […]

}

到最后终于要执行Receiverbinder interface IItentReceiver来传送广播消息了.

[LoadedApk.java]

static final class ReceiverDispatcher {

    final static class InnerReceiver extends IIntentReceiver.Stub {

        […]

        @Override

        public void performReceive(Intent intent, int resultCode, String data,

                    Bundle extras, boolean ordered, boolean sticky, int sendingUser) {

               […]

               rd.performReceive(intent, resultCode, data, extras,

                            ordered, sticky, sendingUser);

               […]

}

}

[…]

}

其中rd是LoadedApk.ReceiverDispatcher一个reference, 此ReceiverDispatcher在register broadcast receiver阶段就已经准备好了.

[LoadedApk.java]

public void performReceive(Intent intent, int resultCode, String data,

                Bundle extras, boolean ordered, boolean sticky, int sendingUser) {

        […]

        final Args args = new Args(intent, resultCode, data, extras, ordered,

                    sticky, sendingUser);

        […]

        if (intent == null || !mActivityThread.post(args)) {

             […]

        }

}

其中mActivityThread是一个activity thread的handler 的reference.而Args是一个runnable的handler task.所以mActivityThread.post这一行是利用Activity thread的handler来执行Args task.

[LoadedApk.java]

final class Args extends BroadcastReceiver.PendingResult implements Runnable {

        […]

        public void run() {

            final BroadcastReceiver receiver = mReceiver;

            […]

            ClassLoader cl =  mReceiver.getClass().getClassLoader();

            intent.setExtrasClassLoader(cl);

            intent.prepareToEnterProcess();

            setExtrasClassLoader(cl);

            receiver.setPendingResult(this);

            receiver.onReceive(mContext, intent);

 

        }

}

其中mReceiver在建构ReceiverDispatcher时就藉由参数传进来了.

[LoadedApk.java]

ReceiverDispatcher(BroadcastReceiver receiver, Context context,

                Handler activityThread, Instrumentation instrumentation,

                boolean registered) {

            if (activityThread == null) {

                throw new NullPointerException("Handler must not be null");

            }

 

            mIIntentReceiver = new InnerReceiver(this, !registered);

            mReceiver = receiver;

            mContext = context;

            mActivityThread = activityThread;

            mInstrumentation = instrumentation;

            mRegistered = registered;

            mLocation = new IntentReceiverLeaked(null);

            mLocation.fillInStackTrace();

}

由此可知这个receiver就是一开始在register receiver阶段就决定好了.

由上面的分析可以做一个总结

1.    从 mReceiverResolver寻找出一串 BroadcastFilterlist. 此BroadcastFilter是在regiester receiver阶段就产生了.

2.    将这一串BroadcastFilterlist包装成BroadcastRecord,在直接传给BroadcastQueue的enqueueParallelBroadcastLocked方法做发送广播消息的准备.

3.    执行BroadcastQueue的scheduleBroadcastsLocked方法开始发送广播消息.

4.    从BroadcastRecord中取得包含BroadcastFilter 和ResolveInfo 的list.

5.    从list中取得辅合条件的BroadcastFilter, BroadcastFilter中在register receiver 阶段就会包含特定的ReceiverList,这个ReceiverList就是IIntentReceiver的一个包装对象.因此可以从这个取得的BroadcastFilter得到相对应的IIntentReceiver也就是Receiver binder interface(InnerReceiver)

6.    执行Receiverbinder interface(InnerReceiver) 的 performReceive方法

7.    执行ReceiverDispatcher的performReceive方法,此方法只是单纯的利用Activity thread的handler来执行ReceiverDispatcher准备好的Args task.

8.    由于在registerreceiver阶段就经由产生ReceiverDispatcher时把BroadcastReceiver指定为ReceiverDispatcher的属性mReceiver, 所以在执行Args task,就直接执行BroadcastReceiver的onReceive的方法.这个onReceive也就是由Application实作的onReceive 方法.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值