Android 7.0 ActivityManagerService(5) 广播(Broadcast)相关流程分析(2)
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Android 7.0 ActivityManagerService(5) 广播(Broadcast)相关流程分析(2)
4 broadcastIntentLocked函数Part IV
.................
// Merge into one list.
int ir = 0;
if (receivers != null) {
// A special case for PACKAGE_ADDED: do not allow the package
// being added to see this broadcast. This prevents them from
// using this as a back door to get run as soon as they are
// installed. Maybe in the future we want to have a special install
// broadcast or such for apps, but we'd like to deliberately make
// this decision.
//处理特殊的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_DA TA_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_A V AILABLE.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_ONL Y) == 0) { // This was an implicit broadcast... let's record it for posterity.
//没有处理的静态或有序广播,保存起来
//感觉保存起来也没什么用啊
addBroadcastStatLocked(intent.getAction(), callerPackage, 0, 0, 0);
}
}
...............
简单来说,broadcastIntentLocked的第四部分工作就是为有序广播和静态广播,构造对应的BroadcastRecord(按优先级顺序),
然后将BroadcastRecord加入到Ordered Queue中,并触发广播发送流程。
至此,整个broadcastIntentLocked函数分析完毕,除去一些条件判断的细节外,整个工作流
程如下图所示:
1、处理粘性广播。
由于粘性广播的特性(BroadcastReceiver注册即可接收),系统必须首先保存粘性广播。
2、处理普通动态广播。
普通广播是并发的,系统优先为动态注册的BroadcastReceiver发送广播。
动态广播对应的BroadcastRecord加入到Parallel Queue中。
3、处理静态广播和有序广播。
这一步主要是为静态注册的BroadcastReceiver发送广播,对应的BroadcastRecord加入到Ordered Queue中。
此外,需要注意的是:
如果广播是有序的,那么第2步不会为动态注册的BroadcastReceiver发送广播,而是在第3步统一发送。
发送有序广播时,AMS将按照BroadcastReceiver的优先级,依次构造BroadcastRecord加入到Ordered Queue中。
四、BroadcastQueue的scheduleBroadcastsLocked函数流程分析
从上面的代码,我们知道广播发送方调用sendBroadcast后,AMS会构造对应的BroadcastRecord加入到BroadcastQueue中,
然后调用BroadcastQueue的scheduleBroadcastsLocked函数。
现在,我们就来看一下scheduleBroadcastsLocked相关的流程。
public void scheduleBroadcastsLocked() {
...........
//避免短时间内重复发送BROADCAST_INTENT_MSG
if (mBroadcastsScheduled) {
return;
}
mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
mBroadcastsScheduled = true;
}
上面的代码将发送BROADCAST_INTENT_MSG,触发BroadcastQueue调用processNextBroadcast进行处理。
processNextBroadcast函数同样非常的长,大概有500多行。
我们还是分段进行分析。
1 processNextBroadcast函数Part I
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);
}
........................
}
}
从上面的代码可以看出,processNextBroadcast函数的第一部分主要是为动态注册的BroadcastReceiver发送普通广播。
发送普通广播的函数为deliverToRegisteredReceiverLocked:
private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
BroadcastFilter filter, boolean ordered, int index) {
boolean skip = false;
//检查广播发送方是否有BroadcastReceiver指定的权限
if (filter.requiredPermission != null) {
int perm = mService.checkComponentPermission(filter.requiredPermission,
r.callingPid, r.callingUid, -1, true);
if (perm != PackageManager.PERMISSION_GRANTED) {
............
skip = true;
} else {
//进一步检查权限的合理性
final int opCode = AppOpsManager.permissionToOpCode(filter.requiredPermission);
if (opCode != AppOpsManager.OP_NONE
&& mService.mAppOpsService.noteOperation(opCode, r.callingUid,
r.callerPackage) != AppOpsManager.MODE_ALLOWED) { ............
skip = true;
}
}
}
//检查BroadcastReceiver是否有Broadcast要求的权限
if (!skip && r.requiredPermissions != null && r.requiredPermissions.length > 0) { for (int i = 0; i < r.requiredPermissions.length; i++) {
String requiredPermission = r.requiredPermissions[i];
int perm = mService.checkComponentPermission(requiredPermission,
filter.receiverList.pid, filter.receiverList.uid, -1, true);
if (perm != PackageManager.PERMISSION_GRANTED) {
.................
//只要一条权限不满足,就结束
skip = true;
break;
}
//进一步检查权限的合理性
int appOp = AppOpsManager.permissionToOpCode(requiredPermission);
if (appOp != AppOpsManager.OP_NONE && appOp != r.appOp
&& mService.mAppOpsService.noteOperation(appOp,
filter.receiverList.uid, filter.packageName)
!= AppOpsManager.MODE_ALLOWED) {
...........
skip = true;
break;
}
}
}
//这段代码我看的有些懵逼,发送方没要求权限,还检查啥?
if (!skip && (r.requiredPermissions == null || r.requiredPermissions.length == 0)) { int perm = mService.checkComponentPermission(null,
filter.receiverList.pid, filter.receiverList.uid, -1, true);
if (perm != PackageManager.PERMISSION_GRANTED) {
............
skip = true;
}
}
//还有一些其它的检查,不再分析代码了。
//包括是否允许以background的方式发送、IntentFirewall是否允许广播中的Intent发送...............................
if (skip) {
//不满足发送条件的话,标记一下,结束发送
r.delivery[index] = BroadcastRecord.DELIVERY_SKIPPED;
return;
}
// If permissions need a review before any of the app components can run, we drop
// the broadcast and if the calling app is in the foreground and the broadcast is
// explicit we launch the review UI passing it a pending intent to send the skipped
// broadcast.
//特殊情况,还需要再次检查权限,中断广播发送
//再次满足发送条件后,会重新进入到后续的发送流程
if (Build.PERMISSIONS_REVIEW_REQUIRED) {
if (!requestStartTargetPermissionsReviewIfNeededLocked(r, filter.packageName,
filter.owningUserId)) {
r.delivery[index] = BroadcastRecord.DELIVERY_SKIPPED;
return;
}
}
//可以发送了,标记一下
r.delivery[index] = BroadcastRecord.DELIVERY_DELIVERED;
// If this is not being sent as an ordered broadcast, then we
// don't want to touch the fields that keep track of the current
// state of ordered broadcasts.
if (ordered) {
//如果发送的是有序广播,则记录一些状态信息等,不涉及广播发送的过程
.............
}
try {
..............
//若BroadcastReceiver对应的进程处于fullBackup状态(备份和恢复),则不发送广播
if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {
if (ordered) {
//有序广播必须处理完一个,才能处理下一个,因此这里主动触发一下
skipReceiverLocked(r);
}
} else {
//执行发送工作
performReceiveLocked(.............);
}
if (ordered) {
r.state = BroadcastRecord.CALL_DONE_RECEIVE;
}
} catch (RemoteException e) {
.............
}
}
deliverToRegisteredReceiverLocked看起来很长,但大部分内容都是进行权限检查等操作,实际的发送工作交给了performReceiveLocked函数。
广播是一种可以携带数据的跨进程、跨APP通信机制,为了避免安全泄露的问题,Android 才在此处使用了大量的篇幅进行权限检查的工作。
在这一部分的最后,我们跟进一下performReceiveLocked函数:
void performReceiveLocked(.........) {
// Send the intent to the receiver asynchronously using one-way binder calls.
if (app != null) {
if (app.thread != null) {
// If we have an app thread, do the call through that so it is
// correctly ordered with other one-way calls.
try {
//通过Binder通信,将广播信息发往BroadcastReceiver处在的进程
app.thread.scheduleRegisteredReceiver(.......);
} catch (RemoteException ex) {
// Failed to call into the process. It's either dying or wedged. Kill it gently.
.......
app.scheduleCrash("can't deliver broadcast");
}
throw ex;
} else {
// Application has died. Receiver doesn't exist.
throw new RemoteException("app.thread must not be null");
}
} else {
//直接通过Binder通信,将消息发往BroadcastReceiver的IIntentReceiver接口
receiver.performReceive(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
}
}
对于动态注册的BroadcastReceiver而言,发送广播的流程应该进入到上述代码的If分支。
进程的ApplicationThread调用scheduleRegisteredReceiver函数的流程,我们放在后面单独分析。
这一部分整体的流程如下图所示:
2 processNextBroadcast函数Part II
至此,processNextBroadcast函数已经发送完所有的动态普通广播,我们看看该函数后续的流程:
..........
// Now take care of the next serialized one...
// If we are waiting for a process to come up to handle the next
// broadcast, then do nothing at this point. Just in case, we
// check that the process we're waiting for still exists.
// 对于有序或静态广播而言,需要依次向每个BroadcastReceiver发送广播,前一个处理完毕后才能发送下一个广播
// 如果BroadcastReceiver对应的进程还未启动,则需要等待
// mPendingBroadcast就是用于保存,因为对应进程还未启动,而处于等待状态的BroadcastRecord
if (mPendingBroadcast != null) {
................
boolean isDead;
synchronized (mService.mPidsSelfLocked) {
//通过AMS得到对应进程的信息
//BroadRecord对应多个BroadcastReceiver,即对应多个进程
//此处curApp保存当前正在等待的进程
ProcessRecord proc = mService.mPidsSelfLocked.get(mPendingBroadcast.curApp.pid);
isDead = proc == null || proc.crashing;
}
if (!isDead) {
// It's still alive, so keep waiting
// 注意到有序和静态广播必须依次处理
// 因此,若前一个BroadcastRecord对应的某个进程启动较慢,不仅会影响该BroadcastRecord中后续进程接收广播
// 还会影响到后续所有BroadcastRecord对应进程接收广播
return;
} else {
............
mPendingBroadcast.state = BroadcastRecord.IDLE;
mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
mPendingBroadcast = null;
}
}
boolean looped = false;
//处理之前发送BroadcastRecord的状态
do {
if (mOrderedBroadcasts.size() == 0) {
// No more broadcasts pending, so all done!
mService.scheduleAppGcsLocked();
//当至少一个BroadcastRecord被处理完毕后,looped才会被置变为true
if (looped) {
// If we had finished the last ordered broadcast, then
// make sure all processes have correct oom and sched
// adjustments.
// 因为静态广播和有序广播,可能拉起进程
// 因此这些广播处理完毕后,AMS需要释放掉一些不需要的进程
mService.updateOomAdjLocked();
}
return;
}
//每次均处理当前的第一个
r = mOrderedBroadcasts.get(0);
boolean forceReceive = false;
// Ensure that even if something goes awry with the timeout
// detection, we catch "hung" broadcasts here, discard them,
// and continue to make progress.
//
// This is only done if the system is ready so that PRE_BOOT_COMPLETED
// receivers don't get executed with timeouts. They're intended for
// one time heavy lifting after system upgrades and can take
// significant amounts of time.
// 这里用于判断此广播是否处理超时
// 仅在系统启动完毕后,才进行该判断,因为PRE_BOOT_COMPLETED广播可能由于系统升级需要等待较长时间
int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
if (mService.mProcessesReady && r.dispatchTime > 0) {
long now = SystemClock.uptimeMillis();
if ((numReceivers > 0) &&
//单个广播处理的超时时间,定义为2 * 每个接收者处理的最长时间(10s)* 接收者的数量
(now > r.dispatchTime + (2*mTimeoutPeriod*numReceivers))) {
...............
//如果超时,则强制结束这条广播的处理
broadcastTimeoutLocked(false); // forcibly finish this broadcast
forceReceive = true;
r.state = BroadcastRecord.IDLE;
}
}
if (r.state != BroadcastRecord.IDLE) {
//BroadcastRecord还未处理或处理完毕后,状态为IDLE态
............
return;
}
//如果广播处理完毕,或中途被取消
if (r.receivers == null || r.nextReceiver >= numReceivers
|| r.resultAbort || forceReceive) {
// No more receivers for this broadcast! Send the final
// result if requested...
if (r.resultTo != null) {
try {
..........
//广播处理完毕,将该广播的处理结果发送给resultTo对应BroadcastReceiver
performReceiveLocked(r.callerApp, r.resultTo,
new Intent(r.intent), r.resultCode,
r.resultData, r.resultExtras, false, false, erId);
} catch (RemoteException e) {
.............
}
}
.................
cancelBroadcastTimeoutLocked();
addBroadcastToHistoryLocked(r);
//作一下记录
if (r.intent.getComponent() == null && r.intent.getPackage() == null
&& (r.intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONL Y) == 0) {
// This was an implicit broadcast... let's record it for posterity.
mService.addBroadcastStatLocked(r.intent.getAction(), r.callerPackage,
r.manifestCount, r.manifestSkipCount, r.finishTime-r.dispatchTime);
}
mOrderedBroadcasts.remove(0);
//一个BroadcastRecord处理完毕后,将r置为null
r = null;
//如果一个广播处理完毕,说明可能拉起过进程,于是looped置为true
looped = true;
continue;
}
//r == null时,可以处理下一个BroadcastRecord
//r != null, 继续处理当前BroadcastRecord的下一个BroadReceiver
} while (r == null);
....................
这一部分代码,乍一看有点摸不着头脑的感觉,其实主要做了两个工作:
1、判断是否有PendingBroadcast。
当存在PendingBroadcast,且当前正在等待启动的进程并没有死亡,那么不能处理下一个BroadcastRecord,必须等待PendingBroadcast处理完毕。
2、处理mOrderedBroadcasts中的BroadcastRecord
由于有序广播和静态广播,必须一个接一个的处理。
因此每发送完一个广播后,均会重新调用processNextBroadcast函数。
在发送新的BroadcastRecord时,需要先处理旧有BroadcastRecord的状态。
于是,这段代码后续部分,主要进行了以下操作:
若所有BroadcastRecord均处理完毕,利用AMS释放掉无用进程;
更新超时BroadcastRecord的状态,同时越过此BroadcastRecord;
当一个BroadcastRecord处理完毕后,将结果发送给指定BroadcastReceiver(指定了接收者,才进行此操作),
同时将该BroadcastRecord从mOrderedBroadcasts中移除。
这一系列动作的最终目的,就是选出下一个处理的BroadcastRecord,
然后就可以开始向该BroadcastRecord中下一个BroadcastReceiver发送广播了。
这一部分整体的判断逻辑大致上如下图所示:
3 processNextBroadcast函数Part III
..............
// Get the next receiver...
// 开始处理当前BroadcastRecord的下一个BroadcastReceiver
int recIdx = r.nextReceiver++;
// Keep track of when this receiver started, and make sure there
// is a timeout message pending to kill it if need be.
// 记录单个广播的起始时间
r.receiverTime = SystemClock.uptimeMillis();
if (recIdx == 0) {
//记录整个BroadcastRecord的起始时间
r.dispatchTime = r.receiverTime;
r.dispatchClockTime = System.currentTimeMillis();
................
}
if (! mPendingBroadcastTimeoutMessage) {
long timeoutTime = r.receiverTime + mTimeoutPeriod;
....................
//设置广播处理的超时时间为10s
setBroadcastTimeoutLocked(timeoutTime);
}
final BroadcastOptions brOptions = r.options;
//取出下一个广播接收者
final Object nextReceiver = r.receivers.get(recIdx);
if (nextReceiver instanceof BroadcastFilter) {
// Simple case: this is a registered receiver who gets
// a direct call.
//动态注册的BroadcastReceiver,即处理的是有序广播
BroadcastFilter filter = (BroadcastFilter)nextReceiver;
............
//与处理普通广播一样,调用deliverToRegisteredReceiverLocked
//将广播发送给BroadcastReceiver对应进程的ApplicationThread
deliverToRegisteredReceiverLocked(r, filter, r.ordered, recIdx);
//从代码流程来看,deliverToRegisteredReceiverLocked发送广播出现问题时,r.receiver 才可能是null
//代码运行到这个位置,加入到Ordered Queue的Broadcast一定是order的
if (r.receiver == null || !r.ordered) {
// The receiver has already finished, so schedule to
// process the next one.
...............
//因此这里应该是有序广播发送错误,因此重新发送BROADCAST_INTENT_MSG,触发下一次发送广播的流程
r.state = BroadcastRecord.IDLE;
scheduleBroadcastsLocked();
} else {
//处理特殊的选项
//向DeviceIdleController发送消息,赋予白名单内的应用,
//在Doze模式的激活窗口中,额外的可以访问网络和持锁的时间
if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) { scheduleTempWhitelistLocked(filter.owningUid,
brOptions.getTemporaryAppWhitelistDuration(), r);
}
}
//对于有序广播而言,已经通知了一个BroadcastReceiver,需要等待处理结果,因此返回
return;
}
.......................
processNextBroadcast的第3部分,主要是处理有序广播发往动态BroadcastReceiver的场景。
从代码可以看出,有序广播具体的方法流程与普通广播一致,均是调用deliverToRegisteredReceiverLocked函数。
唯一不同的是,有序广播发往一个BroadcastReceiver后,必须等待处理结果,才能进行下一次发送过程。
4 processNextBroadcast函数Part IV
...................
// Hard case: need to instantiate the receiver, possibly
// starting its application process to host it.
// 开始处理静态广播
ResolveInfo info = (ResolveInfo)nextReceiver;
//得到静态广播对应的组件名
ComponentName component = new ComponentName(
info.activityInfo.applicationInfo.packageName,
);
boolean skip = false;
//以下与deliverToRegisteredReceiverLocked中类似,进行发送广播前的检查工作
//判断发送方和接收方要求的权限,是否互相满足
//判断Intent是否满足AMS的IntentFirewall要求...................
boolean isSingleton = false;
//判断BroadcastReceiver是否是单例的
isSingleton = mService.isSingleton(info.activityInfo.processName,
info.activityInfo.applicationInfo,
, info.activityInfo.flags);
} catch (SecurityException e) {
.................
}
//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;
}
//判断BroadcastReceiver对应进程是否允许后台启动
//不允许也会skip
..............
if (skip) {
..................
r.delivery[recIdx] = BroadcastRecord.DELIVERY_SKIPPED;
r.receiver = null;
r.curFilter = null;
r.state = BroadcastRecord.IDLE;
//跳过该广播,发送下一个广播
scheduleBroadcastsLocked();
return;
}
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) {
...............
}
// Is this receiver's application already running?
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;
.............
processNextBroadcast第四部分主要是处理静态广播,除了检查是否满足发送条件外,主要进行了以下工作:
1、若BroadcastReceiver对应的进程已经启动,那么将直接调用进程对应ApplicationThread 的scheduleReceiver发送广播;
2、若BroadcastReceiver对应的进程没有启动,那么AMS将启动对应的进程。
当对应的进程启动,同时完成Android环境的创建后,AMS在attachApplicationLocked函数中重新处理等待发送的广播,对应代码如下:
...............
// Check if a next-broadcast receiver is in this process...
if (!badApp && isPendingBroadcastProcessLocked(pid)) {
try {
//发送因目标进程还未启动,而处于等待状态的广播
//sendPendingBroadcastsLocked将调用BroadcastQueue中的sendPendingBroadcastsLocked函数
//sendPendingBroadcastsLocked最后仍会调用进程对应ApplicationThread的scheduleReceiver函数
didSomething |= sendPendingBroadcastsLocked(app);
} catch (Exception e) {
// If the app died trying to launch the receiver we declare it 'bad'
Slog.wtf(TAG, "Exception thrown dispatching broadcasts in " + app, e);
badApp = true;
}
}
.............
这一部分整体的流程大致如下图所示:
五、应用进程处理广播分析
最后,我们看看应用进程收到广播处理请求后的流程。
1、动态广播的处理流程
AMS处理动态广播时,最后通过Binder通信调用的是进程对应ApplicationThread的scheduleRegisteredReceiver接口:
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
int resultCode, String dataStr, undle extras, boolean ordered,
boolean sticky, int sendingUser, int processState) throws RemoteException { ..............
//调用的是LoadedApk中ReceiverDispatcher的内部类InnerReceiver的接口
receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
sticky, sendingUser);
}
我们看看InnerReceiver的performReceive函数:
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 {
// The activity manager dispatched a broadcast to a registered
// receiver in this process, but before it could be delivered the
// receiver was unregistered. Acknowledge the broadcast on its
// behalf so that the system's broadcast sequence can continue.
// 处理特殊情况,在收到广播前,BroadcastReceiver已经unregister
IActivityManager mgr = ActivityManagerNative.getDefault();
try {
if (extras != null) {
extras.setAllowFds(false);
}
//通知AMS结果
mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
我们跟进一下ReceiverDispatcher的performReceive函数:
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);
..............
//mActivityThread是一个Handler对象
//若注册BroadcastReceiver时没有指定,则是ActivityThread主线程对应的Handler if (intent == null || !mActivityThread.post(args)) {
//出现问题时,若处理的是有序广播,则需要通知AMS
if (mRegistered && ordered) {
IActivityManager mgr = ActivityManagerNative.getDefault();
.............
args.sendFinished(mgr);
}
}
}
当Args对象被Handler对应线程处理时,对应的run函数将被调用:
public void run() {
final BroadcastReceiver receiver = mReceiver;
final boolean ordered = mOrdered;
...............
final IActivityManager mgr = ActivityManagerNative.getDefault();
final Intent intent = mCurIntent;
..............
mCurIntent = null;
mDispatched = true;
...........
try {
//此处并没有反射创建BroadcastReceiver
ClassLoader cl = mReceiver.getClass().getClassLoader();
intent.setExtrasClassLoader(cl);
intent.prepareToEnterProcess();
setExtrasClassLoader(cl);
//receiver设置pendingResult
receiver.setPendingResult(this);
receiver.onReceive(mContext, intent);
} catch (Exception e) {
if (mRegistered && ordered) {
................
sendFinished(mgr);
}
...........
}
//当调用BroadcastReceiver的goAsync时,会将pendingResult置为null //于是不会结束发送流程,直到调用pendingResult的finish函数
if (receiver.getPendingResult() != null) {
//Args继承PendingResult,此处也是调用PendingResult的finish函数
finish();
}
}
当BroadcastReceiver调用onReceive函数处理完广播后,调用PendingResult的finish函数结束处理流程:
/**
* Finish the broadcast. The current result will be sent and the
* next broadcast will proceed.
*/
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);
}
}
我们最后看看AMS的finishReceiver函数:
public void finishReceiver(IBinder who, int resultCode, String resultData,
Bundle resultExtras, boolean resultAbort, int flags) {
............
final long origId = Binder.clearCallingIdentity();
try {
boolean doNext = false;
BroadcastRecord r;
synchronized(this) {
BroadcastQueue queue = (flags & Intent.FLAG_RECEIVER_FOREGROUND) != 0
? mFgBroadcastQueue : mBgBroadcastQueue;
r = queue.getMatchingOrderedReceiver(who);
if (r != null) {
//判断是否还需要发送后续的广播
doNext = r.queue.finishReceiverLocked(r, resultCode,
resultData, resultExtras, resultAbort, true);
}
}
if (doNext) {
//处理下一个广播
r.queue.processNextBroadcast(false);
}
//释放不必要的进程
trimApplications();
} finally {
Binder.restoreCallingIdentity(origId);
}
}
2、静态广播的处理流程
AMS处理静态广播时,最后通过Binder通信调用的是进程对应ApplicationThread的scheduleReceiver接口:
public final void scheduleReceiver(Intent intent, ActivityInfo info,
CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,
boolean sync, int sendingUser, int processState) {
..............
ReceiverData r = new ReceiverData(intent, resultCode, data, extras,
sync, false, mAppThread.asBinder(), sendingUser);
= fo;
patInfo = compatInfo;
//发送消息触发ActivityThread调用handleReceiver函数
sendMessage(H.RECEIVER, r);。