3,发送广播
对应不同的广播,发送方法如下:
public void sendBroadcast(Intent intent, String receiverPermission)
public void sendOrderedBroadcast(Intent intent, String receiverPermission)
public void sendStickyBroadcast(Intent intent)
ContextImpl的sendBroadcast调用流程图如下,
sendBroadcast方法如下,
public void sendBroadcast(Intent intent) {
warnIfCallingFromSystemProcess();
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.prepareToLeaveProcess();
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 new RuntimeException("Failure from system", e);
}
}
当应用apk发起一个广播时,最后都会通过跨进程调用到AMS的broadcastIntent方法,只是有些标志(是否是顺序广播)不一样而已。
broadcastIntent方法如下,
public final int broadcastIntent(IApplicationThread caller,
Intent intent, String resolvedType, IIntentReceiver resultTo,
int resultCode, String resultData, Bundle resultExtras,
String[] requiredPermissions, int appOp, Bundle options,
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, null, serialized, sticky,
callingPid, callingUid, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
}
broadcastIntentLocked方法又臭又长,其他的就不多说了,看主要的,
private final int broadcastIntentLocked(){
List receivers = null; // 记录静态广播
List<BroadcastFilter> registeredReceivers = null; // 记录动态广播
// 根据intent 获取匹配的静态广播
receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
// 根据intent 获取匹配的动态广播
registeredReceivers = mReceiverResolver.queryIntent(intent,
resolvedType, false, userId);
if (!ordered && NR > 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);
final boolean replaced = replacePending && queue.replaceParallelBroadcastLocked(r);
if (!replaced) {
queue.enqueueParallelBroadcastLocked(r);
queue.scheduleBroadcastsLocked(); // 发送动态广播
}
registeredReceivers = null;
NR = 0;
}
if ((receivers != null && receivers.size() > 0)|| resultTo != null) {
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);
boolean replaced = replacePending && queue.replaceOrderedBroadcastLocked(r);
if (!replaced) {
queue.enqueueOrderedBroadcastLocked(r);
queue.scheduleBroadcastsLocked(); // 发送静态广播
}
}
}
由于广播分为动态广播和静态广播,所以在该函数中,分别定义了2个list来查询并保存匹配的静态和动态广播,最后分别插入广播队列进行处理。
3.1 查询
3.1.1静态广播的匹配查询
collectReceiverComponents方法如下,
private List<ResolveInfo> collectReceiverComponents(Intent intent, String resolvedType,
int callingUid, int[] users) {
List<ResolveInfo> receivers = null;
try {
HashSet<ComponentName> singleUserReceivers = null;
boolean scannedFirstReceivers = false;
for (int user : users) {
// Skip users that have Shell restrictions
if (callingUid == Process.SHELL_UID
&& getUserManagerLocked().hasUserRestriction(
UserManager.DISALLOW_DEBUGGING_FEATURES, user)) {
continue;
}
List<ResolveInfo> newReceivers = AppGlobals.getPackageManager()
.queryIntentReceivers(intent, resolvedType, STOCK_PM_FLAGS, user);
if (user != UserHandle.USER_OWNER && newReceivers != null) {
•••
for (int i=0; i<newReceivers.size(); i++) {
ResolveInfo ri = newReceivers.get(i);
if ((ri.activityInfo.flags&ActivityInfo.FLAG_SINGLE_USER) != 0) {
ComponentName cn = new ComponentName(
ri.activityInfo.packageName, ri.activityInfo.name);
if (singleUserReceivers == null) {
singleUserReceivers = new HashSet<ComponentName>();
}
if (!singleUserReceivers.contains(cn)) {
singleUserReceivers.add(cn);
receivers.add(ri);
}
} else {
receivers.add(ri);
}
}
}
}
} catch (RemoteException ex) {
// pm is in same process, this will never happen.
}
return receivers;
}
AppGlobals.getPackageManager()方法最后会得到PMS,直接看queryIntentReceivers方法,
public List<ResolveInfo> queryIntentReceivers(Intent intent, String resolvedType, int
flags, int userId) {
if (!sUserManager.exists(userId)) return Collections.emptyList();
ComponentName comp = intent.getComponent();
if (comp == null) {
if (intent.getSelector() != null) {
intent = intent.getSelector();
comp = intent.getComponent();
}
}
if (comp != null) {
List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
ActivityInfo ai = getReceiverInfo(comp, flags, userId);
if (ai != null) {
ResolveInfo ri = new ResolveInfo();
ri.activityInfo = ai;
list.add(ri);
}
return list;
}
// reader
synchronized (mPackages) {
String pkgName = intent.getPackage();
if (pkgName == null) {
return mReceivers.queryIntent(intent, resolvedType, flags, userId);
}
final PackageParser.Package pkg = mPackages.get(pkgName);
if (pkg != null) {
return mReceivers.queryIntentForPackage(intent, resolvedType, flags,
pkg.receivers, userId);
}
return null;
}
}
一般广播都是动态广播,而有序广播两种状态都有,有序广播保存receivers 序列中。首先查询符合条件的静态广播
receivers =collectReceiverComponents(intent,
AppGlobals.getPackageManager().queryIntentReceivers(intent
然后将receivers 和registeredReceivers根据数据的大小(优先级)合并到receivers中,最后插入队列并发起实际的广播调度。
queue.enqueueOrderedBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
结构图如下:
3.1.2动态广播的匹配查询
查询到符合条件的动态广播之后,根据BroadcastFilter创建一个BroadcastRecord节点,插入BroadcastQueue内的并行处理队列,
最后发起实际的广播调度。
结构图如下:
3.2 一般广播执行流程
3.2.1流程图
3.2.1 关键代码解析
一般广播里面的所有广播同时全部执行,最后调用onReceive函数,通过finishReceiver反馈结果。在processNextBroadcast函数中,
可以看到同时调用,
while (mParallelBroadcasts.size() > 0)
{
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++)
{
Object target = r.receivers.get(i);
. . . . . .
deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
}
. . . . . .
}
3.3 有序广播
3.3.1流程图
3.3.1 关键代码分析
在processNextBroadcast函数中,首先判断该app是否为空,说明该进程还没有起来,那就先调用processCurBroadcastLocked启动app,
最后都会调用processCurBroadcastLocked执行,调用onReceive处理广播。
因为是有序广播,是一个一个安装顺序执行,在反馈的结果BroadcastReceive中,会根据相关信息调用processNextBroadcast函数接着
执行下一个广播。
广播完成之后和AMS还有一个交互,其实有序广播就比一般广播多了一个重复的过程,相当于多条广播逐条执行。