android广播动态注册与发送流程分析

1、相关代码

\frameworks\base\core\java\android\app\ContextImpl.java

\frameworks\base\core\java\android\app\LoadedApk.java

\frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java

\frameworks\base\services\core\java\com\android\server\am\BroadcastQueue.java

\frameworks\base\core\java\android\app\BroadcastOptions.java

\frameworks\base\services\core\java\com\android\server\am\ReceiverList.java

\frameworks\base\services\core\java\com\android\server\IntentResolver.java

\frameworks\base\services\core\java\com\android\server\am\BroadcastFilter.java

2.1广播动态注册流程

简要流程如上图,注册过程主要通过AMS调用,将注册的intentFilter添加到BroadcastFilter中的队列mFilters中,同时将IIntentReceiver对象添加到mRegisteredReceivers中。

public Intent registerReceiver(IApplicationThread caller, String callerPackage,
        IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
        int flags) {
    ArrayList<Intent> stickyIntents = null;
    //...... 对调用者,instantApp、flag等做检查
    //......处理粘性广播,将粘性广播加到粘性广播队列中
    synchronized (this) {
       //从现有队列中查找本地的IIntentReceiver
        ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
        if (rl == null) {
            //如果当前没有,则新建,并且每个应用只能创建1000个receiver超过会报异常
            rl = new ReceiverList(this, callerApp, callingPid, callingUid,
                    userId, receiver);
            //......
            mRegisteredReceivers.put(receiver.asBinder(), rl);
        } else if (rl.uid != callingUid) {
            //跟已有uid不同报异常
        } else if (rl.pid != callingPid) {
           //跟已有pid不同报异常
        } else if (rl.userId != userId) {
            //跟已有userId不同报异常
        }
        BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
                permission, callingUid, userId, instantApp, visibleToInstantApps);
        if (rl.containsFilter(filter)) {
            //intentfilter已存在,不再重复添加
        } else {
            rl.add(bf);
            //添加intentFilter到mReceiverResolver表中
            mReceiverResolver.addFilter(bf);
        }

        if (allSticky != null) {
            //发送粘性广播
            for (int i = 0; i < stickyCount; i++) {
                Intent intent = allSticky.get(i);
                BroadcastQueue queue = broadcastQueueForIntent(intent);
                BroadcastRecord r = new BroadcastRecord(queue, intent, null,
                        null, -1, -1, false, null, null, OP_NONE, null, receivers,
                        null, 0, null, null, false, true, true, -1);
                queue.enqueueParallelBroadcastLocked(r);
                queue.scheduleBroadcastsLocked();
            }
        }
     //......
    }
}

注册过程主要涉及两个重要标量:

final HashMap<IBinder, ReceiverList> mRegisteredReceivers = new HashMap<>();
final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
        = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
    //......
};
final class ReceiverList extends ArrayList<BroadcastFilter>
        implements IBinder.DeathRecipient {
    final ActivityManagerService owner;
    public final IIntentReceiver receiver;
    public final ProcessRecord app;
    public final int pid;
    public final int uid;
    public final int userId;
    BroadcastRecord curBroadcast = null;
    boolean linkedToDeath = false;
final class BroadcastFilter extends IntentFilter {
    // Back-pointer to the list this filter is in.
    final ReceiverList receiverList;
    final String packageName;
    final String requiredPermission;
    final int owningUid;
    final int owningUserId;
    final boolean instantApp;
    final boolean visibleToInstantApp;

 

ReceiverList类相当于我们代码中的具体receiver,BroadcastFilter则相当于我们在注册广播时候施使用的intentFilter,一个进程不能注册超过1000个receiver,每个receiver中可以有多个BroadcastFilte,每次注册时候,先查找该receiver是否已经存在于当前的mRegisteredReceivers列表中了,如果已经存在,则检查这次注册者的pid、uid、userId是否跟已经存在的receiver中的这三个值相同,不同则抛出异常。

然后根据现有的或者新生成的ReceiverList名称rl,生成BroadcastFilter,如果该rl中已经包含给intentFilter,表示该已经存在了相同的receiver,包含了相同的intentfilter,不用再重复注册了,如果不包含,则将新生成的BroadcastFilter加入到rl中,将新建的BroadcastFilter加入到mReceiverResolver中。

 

解除注册,最重要的就是从这两个表中移出对象:

void removeReceiverLocked(ReceiverList rl) {
    mRegisteredReceivers.remove(rl.receiver.asBinder());
    for (int i = rl.size() - 1; i >= 0; i--) {
        mReceiverResolver.removeFilter(rl.get(i));
    }
}

2.2 广播发送流程

 

广播发送简略流程如上图所示,在进行了一些列的检查,包括参数,调用者,广播flag,特殊action,系统广播,等之后,从mReceiverResolver中检索出广播接收者,然后按照优先无序广播,之后发送有序广播的顺序,依次调用所有接收者的IIntentReceiver中的onReceive中。

两个广播发送序列,前台序列、后台序列

BroadcastQueue mFgBroadcastQueue;
BroadcastQueue mBgBroadcastQueue;

 

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) {
    enforceNotIsolatedCaller("broadcastIntent");
    synchronized(this) {
        intent = verifyBroadcastLocked(intent);

        final ProcessRecord callerApp = getRecordForAppLocked(caller);
        final int callingPid = Binder.getCallingPid();
        final int callingUid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        int res = broadcastIntentLocked(callerApp,
                callerApp != null ? callerApp.info.packageName : null,
                intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
                requiredPermissions, appOp, bOptions, serialized, sticky,
                callingPid, callingUid, userId);
        Binder.restoreCallingIdentity(origId);
        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,
        boole
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值