下面说广播发送过程
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;
.............
除了检查是否满足发送条件外,主要进行了以下工作:
- 若BroadcastReceiver对应的进程已经启动,那么将直接调用进程对应ApplicationThread的scheduleReceiver发送广播;
- 若BroadcastReceiver对应的进程没有启动,那么AMS将启动对应的进程。
小节:
- 处理全部无序广播,遍历动态注册的接收者并通知
- 获取第一条有序广播
- 获取第一个接收者,设置超时
- 如果是动态注册的接收者,通知并return
- 如果是静态注册的接收者,校验权限
- 通知接收者
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的