广播发送过程

下面说广播发送过程

sendBroadcast()

Context.java

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

我们通过传递参数来看,使用到了一下参数:

  • PocessRecord 发送者的进程记录
  • callingPid 发送者的PID
  • callingUid 发送者的UID
  • intent 意图
  • resultExtras Bundle类型的数据
  • sticky boolean是不是粘连广播

broadcastIntentLocked()

private final int broadcastIntentLocked(ProcessRecord callerApp,
        String callerPackage, Intent intent, String resolvedType,
        IIntentReceiver resultTo, int resultCode, String resultData,
        Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle options,
        boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) {

part-1

intent = new Intent(intent);
//增加该flag,则广播不会发送给已停止的package
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);

//当没有启动完成时,不允许启动新进程
if (!mProcessesReady && (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) {
    intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
}
userId = handleIncomingUser(callingPid, callingUid, userId,
        true, ALLOW_NON_FULL, "broadcast", callerPackage);
//检查发送广播时用户状态
if (userId != UserHandle.USER_ALL && !isUserRunningLocked(userId, false)) {
    if ((callingUid != Process.SYSTEM_UID
            || (intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0)
            && !Intent.ACTION_SHUTDOWN.equals(intent.getAction())) {
        return ActivityManager.BROADCAST_FAILED_USER_STOPPED;
    }
}
  • 添加flag = FLAG_EXCLUDE_STOPPED_PACKAGES,保证已停止app不会收到该广播
  • 当系统还没有启动完成,则不允许启动新进程,,即只有动态注册receiver才能接受广播
  • 当非USER_ALL广播且当前用户并没有处于Running的情况下,除非是系统升级广播或者关机广播,否则直接返回。

也就是大量的检查信息

part-1

..............
// Add to the sticky list if requested.
// 处理粘性广播相关的内容
if (sticky) {
    //检查是否有发送权限
    if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
            callingPid, callingUid)
            != PackageManager.PERMISSION_GRANTED) {
        ..................
    }

    //粘性广播不能指定接收权限
    if (requiredPermissions != null && requiredPermissions.length > 0) {
        ..............
        return ActivityManager.BROADCAST_STICKY_CANT_HAVE_PERMISSION;
    }

    if (intent.getComponent() != null) {
        //粘性广播不能指定接收方
        ............
    }
    //当粘性广播是针对特定userId时,判断该粘性广播与系统保存的是否冲突
    if (userId != UserHandle.USER_ALL) {

        //取出发送给所有user的粘性广播
        ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(
                UserHandle.USER_ALL);
        if (stickies != null) {
            ArrayList<Intent> list = stickies.get(intent.getAction());
            if (list != null) {
                int N = list.size();
                int i;
                for (i=0; i<N; i++) {
                    //发送给特定user的粘性广播,与发送给所有user的粘性广播,action一致时,发生冲突
                    if (intent.filterEquals(list.get(i))) {
                        //抛出异常
                        .............
                    }
                }
            }
        }

        ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);
        if (stickies == null) {
            stickies = new ArrayMap<>();
            //按userId保存粘性广播
            //即一个user,可能有多个粘性广播
            mStickyBroadcasts.put(userId, stickies);
        }

        //按照Action保存粘性广播
        //即一个Action,可能对应中多个广播
        ArrayList<Intent> list = stickies.get(intent.getAction());
        if (list == null) {
            //list为null时,直接加入
            list = new ArrayList<>();
            stickies.put(intent.getAction(), list);
        }
        final int stickiesCount = list.size();
        int i;
        for (i = 0; i < stickiesCount; i++) {
            //新的粘性广播与之前的重复,则保留新的
            //即当发送多个相同的粘性广播时,系统仅会保留最新的
            if (intent.filterEquals(list.get(i))) {
                // This sticky already exists, replace it.
                list.set(i, new Intent(intent));
                break;
            }
        }
        if (i >= stickiesCount) {
            //不重复时,直接加入
            list.add(new Intent(intent));
        }
    }
}
...............

系统通过sticky描述intent所描述的广播是不是一个粘连性广播,如果是,它的值就等于true,此时AMS就需要将这个广播进行保存,后面注册的时候要接收这种类型的广播接受者可以获取这个广播。

所以action相同的粘连广播都保存在一个列表中,这些列表最终存在AMS类型的成员变量mStickyBroadcasts所描述的HashMap中,并且以他们的userId为关键字。

AMS会通过intent的Action来描述,因此通过Action得到能够得到粘连广播的list如果不存在则加入粘连广播列表。

part-3

.............
// Figure out who all will receive this broadcast.
//receivers主要用于保存匹配当前广播的静态注册的BroadcastReceiver
//若当前广播是有序广播时,还会插入动态注册的BroadcastReceiver
List receivers = null;

//registeredReceivers用于保存匹配当前广播的动态注册的BroadcastReceiver 
//BroadcastFilter中有对应的BroadcastReceiver的引用
List<BroadcastFilter> registeredReceivers = null;

// Need to resolve the intent to interested receivers...
// 若设置了FLAG_RECEIVER_REGISTERED_ONLY,那么只有此时完成了注册的BroadcastReceiver才会收到信息
// 简单讲就是,有FLAG_RECEIVER_REGISTERED_ONLY时,不通知静态注册的BroadcastReceiver

// 此处处理未设置该标记的场景
if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
    //利用PKMS的queryIntentReceivers接口,查询满足条件的静态BroadcastReceiver
    receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
}

//广播没有指定特定接收者时
if (intent.getComponent() == null) {
    //这里的要求比较特殊,针对所有user,且从shell发送的广播
    //即处理调试用的广播
    if (userId == UserHandle.USER_ALL && callingUid == Process.SHELL_UID) {
        // Query one target user at a time, excluding shell-restricted users
        for (int i = 0; i < users.length; i++) {
            //user不允许调试时,跳过
            if (mUserController.hasUserRestriction(
                    UserManager.DISALLOW_DEBUGGING_FEATURES, users[i])) {
                continue;
            }

            //得到当前user对应的满足Intent要求的BroadcastReceiver
            //mReceiverResolver中保存的都是动态注册的BroadcastReceiver对应的BroadcastFilter
            List<BroadcastFilter> registeredReceiversForUser =
                    mReceiverResolver.queryIntent(intent,
                            resolvedType, false, users[i]);

            if (registeredReceivers == null) {
                registeredReceivers = registeredReceiversForUser;
            } else if (registeredReceiversForUser != null) {
                registeredReceivers.addAll(registeredReceiversForUser);
            }
        }
    } else {
        //通常的处理流程
        registeredReceivers = mReceiverResolver.queryIntent(intent,
                resolvedType, false, userId);
    }
}

//检查广播中是否有REPLACE_PENDING标签
//如果设置了这个标签,那么新的广播可以替换掉AMS广播队列中,与之匹配的且还未被处理的旧有广播
//这么做的目的是:尽可能的减少重复广播的发送
final boolean replacePending =
        (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
.....................

//先处理动态注册的BroadcastReceiver对应的广播
int NR = registeredReceivers != null ? registeredReceivers.size() : 0;

//处理无序的广播,即普通广播
if (!ordered && NR > 0) {
    // If we are not serializing this broadcast, then send the
    // registered receivers separately so they don't wait for the
    // components to be launched.
    //根据Intent的Flag决定BroadcastQueue
    final BroadcastQueue queue = broadcastQueueForIntent(intent);

    //构造广播对应的BroadcastRecord
    //BroadcastRecord中包含了该广播的所有接收者
    BroadcastRecord r = new BroadcastRecord(........);
    ................
    //设置了REPLACE_PENDING标签,同时与旧有广播匹配时,才会进行替换
    //若能够替换,replaceParallelBroadcastLocked中就会将新的广播替换到队列中
    final boolean replaced = replacePending && queue.replaceParallelBroadcastLocked(r);

    if (!replaced) {
        //没有替换时,才需要将新的广播加入到队列中
        queue.enqueueParallelBroadcastLocked(r);

        //触发广播发送流程
        queue.scheduleBroadcastsLocked();
    }
    registeredReceivers = null;
    NR = 0;
}
.....................
List receivers = null;//静态广播
List<BroadcastFilter> registeredReceivers = null;//动态广播
  • 处理没有设置FLAG_RECEIVER_REGISTERED_ONLY这个标记的场景
  • 判断发送的组件不等于null
  • 根据intent得到广播注册者
  • 先处理动态注册的广播&处理无序广播
    - 根据Flag决定BroadcastQueue
    - 构造BroadcastRecord中包含了这个广播的所有接收者

这里我们可以看出,无序广播&动态广播先发出

小节:

通过第一部分和第二部分我们知道,先是处理粘连广播,将粘连广播保存起来。
然后处理广播匹配的静态和动态BroadcastReceiver,若当前带发送的广播是无序的,那么为动态注册的BroadcastReceiver木构造该广播对应的BraoadcastRecord加入到发送队列中,并出发广播发送流程。

part-4

.................
// Merge into one list.
int ir = 0;
if (receivers != null) {
    //处理特殊的Action,例如PACKAGE_ADDED,系统不希望有些应用一安装就能启动
    //APP安装后,PKMS将发送PACKAGE_ADDED广播
    //若没有这个限制,在刚安装的APP内部静态注册监听该消息的BroadcastReceiver,新安装的APP就能直接启动
    String skipPackages[] = null;
    if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
            || Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
            || Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
        Uri data = intent.getData();
        if (data != null) {
            String pkgName = data.getSchemeSpecificPart();
            if (pkgName != null) {
                skipPackages = new String[] { pkgName };
            }
        }
    } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
        skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
    }

    if (skipPackages != null && (skipPackages.length > 0)) {
        for (String skipPackage : skipPackages) {
            if (skipPackage != null) {
                int NT = receivers.size();
                for (int it=0; it<NT; it++) {
                    ResolveInfo curt = (ResolveInfo)receivers.get(it);
                    if (curt.activityInfo.packageName.equals(skipPackage)) {
                        //将skipPackages对应的BroadcastReceiver移出receivers
                        receivers.remove(it);
                        it--;
                        NT--;
                     }
                }
            }
        }
    }

    int NT = receivers != null ? receivers.size() : 0;
    int it = 0;
    ResolveInfo curt = null;
    BroadcastFilter curr = null;
    //NT对应的是静态BroadcastReceiver的数量
    //NR对应的是动态BroadcastReceiver的数量
    //若发送的是无序广播,此时NR为0
    //若是有序广播,才会进入下面两个while循环

    //下面两个while循环就是将静态注册的BroadcastReceiver和动态注册的BroadcastReceiver
    //按照优先级合并到一起(有序广播才会合并)
    while (it < NT && ir < NR) {
        if (curt == null) {
            curt = (ResolveInfo)receivers.get(it);
        }
        if (curr == null) {
            curr = registeredReceivers.get(ir);
        }

        //动态优先级大于静态时,将动态插入到receivers中
        if (curr.getPriority() >= curt.priority) {
            // Insert this broadcast record into the final list.
            receivers.add(it, curr);
            ir++;
            curr = null;
            it++;
            NT++;
        } else {
            // Skip to the next ResolveInfo in the final list.
            it++;
            curt = null;
        }
    }
}

while (ir < NR) {
    if (receivers == null) {
        receivers = new ArrayList();
    }
    //插入剩下的动态BroadcastReceiver
    receivers.add(registeredReceivers.get(ir));
    ir++;
}

if ((receivers != null && receivers.size() > 0)
        || resultTo != null) {
    BroadcastQueue queue = broadcastQueueForIntent(intent);
    //构造对应的BroadcastRecord
    BroadcastRecord r = new BroadcastRecord(........);
    ............
    //同样判断是否需要替换,这里是Ordered Queue
    boolean replaced = replacePending && queue.replaceOrderedBroadcastLocked(r);
    if (!replaced) {
        //没替换时,就加入Ordered Queue
        queue.enqueueOrderedBroadcastLocked(r);

        //触发发送流程
        queue.scheduleBroadcastsLocked();
    }
} else {
    // There was nobody interested in the broadcast, but we still want to record
    // that it happened.
    if (intent.getComponent() == null && intent.getPackage() == null
            && (intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
        // This was an implicit broadcast... let's record it for posterity.
        //没有处理的静态或有序广播,保存起来
        //感觉保存起来也没什么用啊
        addBroadcastStatLocked(intent.getAction(), callerPackage, 0, 0, 0);
    }
}
...............

上面意思是由于NR,NR是动态广播,动态广播无序的已经发送完成NR=0,如果是有序广播NR!=0,如果有静态广播&有有序动态广播,则将这两种广播进行合并,合并的结果都存入receivers列表中。

然后对receivers列表中所有广播都构造一个BroadcastRecord,然后触发发送流程。

从上面这些发送过程看,我们先是保存粘连广播,接着处理无序动态广播,接着处理有序动态广播和静态广播。

小节

1、处理粘性广播。
由于粘性广播的特性(BroadcastReceiver注册即可接收),系统必须首先保存粘性广播。

2、处理普通动态广播。
普通广播是并发的,系统优先为动态注册的BroadcastReceiver发送广播。
动态广播对应的BroadcastRecord加入到Parallel Queue中。

3、处理静态广播和有序广播。
这一步主要是为静态注册的BroadcastReceiver发送广播,对应的BroadcastRecord加入到Ordered Queue中。

此外,需要注意的是:
如果广播是有序的,那么第2步不会为动态注册的BroadcastReceiver发送广播,而是在第3步统一发送。
发送有序广播时,AMS将按照BroadcastReceiver的优先级,依次构造BroadcastRecord加入到Ordered Queue中。

BroadcastQueue.scheduleBroadcastsLocked()

public void scheduleBroadcastsLocked() {
    if (mBroadcastsScheduled) {
        return;
    }
    mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
    mBroadcastsScheduled = true;
}

其中注意mHandler是MainHandler即主线程哈

public void scheduleBroadcastsLocked() {
    ...........
    //避免短时间内重复发送BROADCAST_INTENT_MSG
    if (mBroadcastsScheduled) {
        return;
    }
    mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
    mBroadcastsScheduled = true;
}

这里通过一个变量进行表达,如果这个变量是true,则不进行发送这个广播了,那么什么时候是false呢,就在下面有展示。

最后调用到了processNextBroadcast()这个方法

BroadcastQueue.processNextBroadcast()

这个方法还是很长,我们就分部分解析

part-1

final void processNextBroadcast(boolean fromMsg) {
    synchronized(mService) {
        BroadcastRecord r;
        ..............
        //更新CPU的使用情况
        //处理静态广播时,可能需要拉起对应进程,因此在这里先记录一下CPU情况
        mService.updateCpuStats();

        if (fromMsg) {
            //处理BROADCAST_INTENT_MSG后,将mBroadcastsScheduled置为false
            //scheduleBroadcastsLocked就可以再次被调用了
            mBroadcastsScheduled = false;
        }

        // First, deliver any non-serialized broadcasts right away.
        //先处理“并发”发送的普通广播
        while (mParallelBroadcasts.size() > 0) {
            //依次取出BroadcastRecord
            r = mParallelBroadcasts.remove(0);

            //记录发送的时间
            r.dispatchTime = SystemClock.uptimeMillis();
            r.dispatchClockTime = System.currentTimeMillis();

            final int N = r.receivers.size();
            ................
            for (int i=0; i<N; i++) {
                //mParallelBroadcasts中的每个成员均为BroadcastFilter类型
                Object target = r.receivers.get(i);
                ............
                //为该BroadcastRecord对应的每个Receiver发送广播 
                deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
            }

            //将这里处理过的信息加入到历史记录中
            addBroadcastToHistoryLocked(r);
        }
        ........................
    }
}

在这里注意之前出现的两个变量,一个变量是mParallelBroadcasts(处理无序广播,并行),一个变量是mOrderedBroadcasts(处理有序广播)

  • 我们看见如果处理的是处理BROADCAST_INTENT_MSG后,将mBroadcastsScheduled置为false,目的是为了短时间内重复发送这个广播。
  • 然后通过一个循环进行发送广播
    • 从无序广播队列中获取发送的广播记录
    • 记录发送时间
    • 然后为这个BroadcastRecord对应的每一个Receiver发送广播
    • 将处理过后的广播记录加到历史列表中

我们稍后分析这个发送的方法是怎么一回事

part-2

if (mPendingBroadcast != null) {
    boolean isDead;
    synchronized (mService.mPidsSelfLocked) {
        ProcessRecord proc = mService.mPidsSelfLocked.get(mPendingBroadcast.curApp.pid);
        isDead = proc == null || proc.crashing;
    }
    if (!isDead) {
        return;
    } else {
        mPendingBroadcast.state = BroadcastRecord.IDLE;
        mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
        mPendingBroadcast = null;
    }
}

mPendingBroadcast表示处理静态&要启动进程的广播

当这个进程没有启动,则返回等待,这里提到等到是因为此函数外边也是一个循环。直到进程启动这个广播才能发送出去。

part-3

do {
    if (mOrderedBroadcasts.size() == 0) {
        mService.scheduleAppGcsLocked();
        if (looped) {
            mService.updateOomAdjLocked();
        }
        return;
    }

当所有有序广播处理完成则更新进程状态

    r = mOrderedBroadcasts.get(0);//获取第一个广播
    boolean forceReceive = false;
    //得到接收者的数量
    int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;

    if (mService.mProcessesReady && r.dispatchTime > 0) {
        long now = SystemClock.uptimeMillis();
        if ((numReceivers > 0) &&
                (now > r.dispatchTime + (2*mTimeoutPeriod*numReceivers))) {
            broadcastTimeoutLocked(false); // forcibly finish this broadcast
            forceReceive = true;
            r.state = BroadcastRecord.IDLE;//超时时候设置状态为IDLE
        }
    }

处理超时,超时时间注意里面乘以广播接收者的数量

    //如果当前广播没有完成,返回继续等待
    if (r.state != BroadcastRecord.IDLE) {
        return;
    }
    //如果当前广播没有接收者||是最后一个接收者
    if (r.receivers == null || r.nextReceiver >= numReceivers
            || r.resultAbort || forceReceive) {
        //发送最后带有结果的广播
        if (r.resultTo != null) {
            try {
                performReceiveLocked(r.callerApp, r.resultTo,
                    new Intent(r.intent), r.resultCode,
                    r.resultData, r.resultExtras, false, false, r.userId);
                r.resultTo = null;
            } catch (RemoteException e) {
                r.resultTo = null;
            }
        }

        cancelBroadcastTimeoutLocked();

        addBroadcastToHistoryLocked(r);
        if (r.intent.getComponent() == null && r.intent.getPackage() == null
                && (r.intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
            mService.addBroadcastStatLocked(r.intent.getAction(), r.callerPackage,
                    r.manifestCount, r.manifestSkipCount, r.finishTime-r.dispatchTime);
        }
        mOrderedBroadcasts.remove(0);
        r = null;
        looped = true;
        continue;
    }

处理最后一个广播接收者

} while (r == null);

这些处理如果都没发生,则正常的得到第一个有序广播的记录

part-4

int recIdx = r.nextReceiver++;//开始处理当前BroadcastRecord的下一个BroadcastReceiver下标
r.receiverTime = SystemClock.uptimeMillis();//记录单个广播的起始时间
if (recIdx == 0) {
    r.dispatchTime = r.receiverTime;//记录整个BroadcastRecord的起始时间
    r.dispatchClockTime = System.currentTimeMillis();
}
if (! mPendingBroadcastTimeoutMessage) {
    long timeoutTime = r.receiverTime + mTimeoutPeriod;
    setBroadcastTimeoutLocked(timeoutTime);//设置广播处理的超时时间为10s
}
final BroadcastOptions brOptions = r.options;
final Object nextReceiver = r.receivers.get(recIdx);

得到下一个广播Receiver

if (nextReceiver instanceof BroadcastFilter) {
    //动态注册的BroadcastReceiver,即处理的是有序广播
    BroadcastFilter filter = (BroadcastFilter)nextReceiver;
    deliverToRegisteredReceiverLocked(r, filter, r.ordered, recIdx);
    //当发送出现问题的时候为null
    if (r.receiver == null || !r.ordered) {
        //处理下一次广播,当前广播算是挂掉了
        r.state = BroadcastRecord.IDLE;
        scheduleBroadcastsLocked();
    } else {
        if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {
            scheduleTempWhitelistLocked(filter.owningUid,
                    brOptions.getTemporaryAppWhitelistDuration(), r);
        }
    }
    return;
}

处理的是动态BroadcastFilter,调用deliverToRegisteredReceiverLocked发送给对应receiver

由于已经处理了动态广播所以返回处理下一个广播

part-5

...................
// 开始处理静态广播
ResolveInfo info = (ResolveInfo)nextReceiver;
//得到静态广播对应的组件名
ComponentName component = new ComponentName(
        info.activityInfo.applicationInfo.packageName,
        info.activityInfo.name);

boolean skip = false;

//以下与deliverToRegisteredReceiverLocked中类似,进行发送广播前的检查工作

//判断发送方和接收方要求的权限,是否互相满足
//判断Intent是否满足AMS的IntentFirewall要求
//判断BroadcastReceiver是否是单例的
...................

//BroadcastReceiver要求SINGLE_USER
//那么必须申明INTERACT_ACROSS_USERS权限
if ((info.activityInfo.flags&ActivityInfo.FLAG_SINGLE_USER) != 0) {
    if (ActivityManager.checkUidPermission(
            android.Manifest.permission.INTERACT_ACROSS_USERS,
            info.activityInfo.applicationInfo.uid)
                    != PackageManager.PERMISSION_GRANTED) {
        ..............
        skip = true;
    }
}

if (!skip) {
    r.manifestCount++;
} else {
    r.manifestSkipCount++;
}

if (r.curApp != null && r.curApp.crashing) {
    .........
    skip = true;
}

if (!skip) {
    boolean isAvailable = false;
    try {
        isAvailable = AppGlobals.getPackageManager().isPackageAvailable(
                info.activityInfo.packageName,
                UserHandle.getUserId(info.activityInfo.applicationInfo.uid));
    } catch (Exception e) {
        ..........
    }
    if (!isAvailable) {
        .........
        skip = true;
    }
}
if (skip) {
    ..................
    r.delivery[recIdx] = BroadcastRecord.DELIVERY_SKIPPED;
    r.receiver = null;
    r.curFilter = null;
    r.state = BroadcastRecord.IDLE;
    //跳过该广播,发送下一个广播
    scheduleBroadcastsLocked();
    return;
}
```java
判断BroadcastReceiver对应进程是否允许后台启动
不允许也会skip
..............
r.delivery[recIdx] = BroadcastRecord.DELIVERY_DELIVERED;
r.state = BroadcastRecord.APP_RECEIVE;
r.curComponent = component;
r.curReceiver = info.activityInfo;
................
if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {
    //与处理有序普通广播一样,在此处理特殊的选项
    scheduleTempWhitelistLocked(receiverUid,
            brOptions.getTemporaryAppWhitelistDuration(), r);
}

// Broadcast is being executed, its package can't be stopped.
try {
    //发送静态广播前,修改BroadcastReceiver对应的Package状态
    AppGlobals.getPackageManager().setPackageStoppedState(
            r.curComponent.getPackageName(), false, UserHandle.getUserId(r.callingUid));
} catch (RemoteException e) {
} catch (IllegalArgumentException e) {
    ...............
}

如果静态广播对应的receiver的进存在执行下面逻辑

if (app != null && app.thread != null) {
    try {
        app.addPackage(info.activityInfo.packageName,
                info.activityInfo.applicationInfo.versionCode, mService.mProcessStats);
        //BroadcastReceiver对应进程启动时,调用ApplicationThread的scheduleReceiver
        processCurBroadcastLocked(r, app);

        //等待结果,故return
        return;
    } catch (RemoteException e) {
        //这可能是对应进程死亡,可以重新拉起进程发送
        ..........
    } catch (RuntimeException e) {
        .........
        //发送失败,结束本次发送
        finishReceiverLocked(r, r.resultCode, r.resultData,
        r.resultExtras, r.resultAbort, false);

        //继续发送后续的广播
        scheduleBroadcastsLocked();
        // We need to reset the state if we failed to start the receiver.
        r.state = BroadcastRecord.IDLE;
        return;
    }
}

进程不存在则处理下面逻辑

.............
//启动进程处理广播
if ((r.curApp=mService.startProcessLocked(targetProcess,
        info.activityInfo.applicationInfo, true,
        r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
        "broadcast", r.curComponent,
        (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false, false))
                == null) {
    //创建进程失败
    ...............
    //发送失败,结束本次发送
    finishReceiverLocked(r, r.resultCode, r.resultData,
    r.resultExtras, r.resultAbort, false);

    //继续发送后续的广播
    scheduleBroadcastsLocked();
    r.state = BroadcastRecord.IDLE;
    return;
}

//进程启动成功时,mPendingBroadcast保存当前的BroadcastRecord,及待发送广播的下标
//当进程启动后,将根据这两个值处理广播
mPendingBroadcast = r;
mPendingBroadcastRecvIndex = recIdx;
.............

除了检查是否满足发送条件外,主要进行了以下工作:

  1. 若BroadcastReceiver对应的进程已经启动,那么将直接调用进程对应ApplicationThread的scheduleReceiver发送广播;
  2. 若BroadcastReceiver对应的进程没有启动,那么AMS将启动对应的进程。

小节:

  1. 处理全部无序广播,遍历动态注册的接收者并通知
  2. 获取第一条有序广播
  3. 获取第一个接收者,设置超时
  4. 如果是动态注册的接收者,通知并return
  5. 如果是静态注册的接收者,校验权限
  6. 通知接收者

ApplicationThread.scheduleRegisteredReceiver()

我们上面提到使用scheduleBroadcastsLocked发送广播,下面看看这个方法的实现

public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
        int resultCode, String dataStr, Bundle extras, boolean ordered,
        boolean sticky, int sendingUser, int processState) throws RemoteException {
    updateProcessState(processState, false);
    receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
            sticky, sendingUser);
}

调用recriver的performReceive()

InnerReceiver.java

@Override
public void performReceive(Intent intent, int resultCode, String data,
        Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
    final LoadedApk.ReceiverDispatcher rd;
    if (intent == null) {
        rd = null;
    } else {
        rd = mDispatcher.get();
    }
    if (rd != null) {
        //调用ReceiverDispatcher的performReceive函数
        rd.performReceive(intent, resultCode, data, extras,
                ordered, sticky, sendingUser);
    } else {
        IActivityManager mgr = ActivityManagerNative.getDefault();
        try {
            if (extras != null) {
                extras.setAllowFds(false);
            }
            mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
}
public void performReceive(Intent intent, int resultCode, String data,
        Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
    //构造一个Args对象(runnable对象)
    final Args args = new Args(intent, resultCode, data, extras, ordered,sticky, sendingUser);
    if (intent == null || !mActivityThread.post(args)) {
        if (mRegistered && ordered) {
            IActivityManager mgr = ActivityManagerNative.getDefault();
            args.sendFinished(mgr);
        }
    }
}

其中Args继承于BroadcastReceiver.PendingResult,实现了接口Runnable; 其中mActivityThread是当前进程的主线程这里mActivityThread.post(args) 消息机制.
把消息放入MessageQueue,再调用Args的run()方法。

对应代码:

public final class LoadedApk {
  static final class ReceiverDispatcher {
    final class Args extends BroadcastReceiver.PendingResult implements Runnable {
        public void run() {
            final BroadcastReceiver receiver = mReceiver;
            final boolean ordered = mOrdered;

            final IActivityManager mgr = ActivityManagerNative.getDefault();
            final Intent intent = mCurIntent;
            mCurIntent = null;

            if (receiver == null || mForgotten) {
                if (mRegistered && ordered) {
                    sendFinished(mgr);
                }
                return;
            }

            try {
                //获取mReceiver的类加载器
                ClassLoader cl =  mReceiver.getClass().getClassLoader();
                intent.setExtrasClassLoader(cl);
                setExtrasClassLoader(cl);
                receiver.setPendingResult(this);
                //回调广播onReceive方法
                receiver.onReceive(mContext, intent);
            } catch (Exception e) {
                ...
            }

            if (receiver.getPendingResult() != null) {
                finish();
            }
        }
      }
    }

PendingResult.finish()

public final void finish() {
    //对于动态广播而言,type为TYPE_REGISTERED或TYPE_UNREGISTERED
    if (mType == TYPE_COMPONENT) {
        ................
    //有序广播才返回结果
    } else if (mOrderedHint && mType != TYPE_UNREGISTERED){
        ................
        final IActivityManager mgr = ActivityManagerNative.getDefault();
        //Binder通信,调用AMS的finishReceiver函数
        sendFinished(mgr);
    }
}

此图是引用gityuan的

send_broadcast.jpg
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 简介 广播作为Android系统四大组件之一,起得作用是相当大,安卓系统进程之间通信是相当频繁,而且解耦工作是重中...
    我叫王菜鸟阅读 6,312评论 0 2
  • 主目录见:Android高级进阶知识(这是总目录索引)  上一篇文章注册广播接收者的源码分析我们已经讲了注册的过程...
    ZJ_Rocky阅读 844评论 0 2
  • 前言 本来想写一下广播的,发现查阅后有整理的不错的,只好转载图个简便,日后好复习转载:http://www.cnb...
    提升即效率阅读 1,404评论 0 10
  • 诸多无奈,最近在改一个项目的bug的时候,脑子老是一片空白,可能是最近脑子不够用,总之,好多东西忘了,阅读一些别人...
    狗子王1948阅读 7,742评论 6 53
  • 广播接收器 是Android的四大组件之一,可见广播在Android中的重要性; 1. 什么是广播? 广播(Bro...
    Lost_Robot阅读 1,978评论 2 10