本文基于Andorid 11。
一、registerReceiver
registerReceiver(new MyRecevier(), new IntentFilter("com.example.broadcast"));
- 动态注册广播接收器,参数:BroadcastReceiver, IntentFilter。
xml
<receiver android:name=".MyReceiver">
<intent-filter>
<action android:name="com.test.broadcast"/>
</intent-filter>
</receiver>
- 静态注册广播,安卓8以后除几个特殊的广播外,静态注册方式只能接收显示广播。
查看动态注册广播流程:
1.2 ContextImpl.registerReceiverInternal
java
// ContextImpl.java
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
IntentFilter filter, String broadcastPermission,
Handler scheduler, Context context, int flags) {
IIntentReceiver rd = null;
if (receiver != null) {
if (mPackageInfo != null && context != null) {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
rd = mPackageInfo.getReceiverDispatcher(
receiver, context, scheduler,
mMainThread.getInstrumentation(), true);
} else {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
rd = new LoadedApk.ReceiverDispatcher(
receiver, context, scheduler, null, true).getIIntentReceiver();
}
}
try {
final Intent intent = ActivityManager.getService().registerReceiverWithFeature(
mMainThread.getApplicationThread(), mBasePackageName, getAttributionTag(), rd,
filter, broadcastPermission, userId, flags);
if (intent != null) {
intent.setExtrasClassLoader(getClassLoader());
intent.prepareToEnterProcess();
}
return intent;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
传入IIntentReceiver对象作为参数,调用AMS.registerReceiverWithFeature方法注册。
1.3 AMS.registerReceiverWithFeature
java
// ActivityManagerService.java
public Intent registerReceiverWithFeature(IApplicationThread caller, String callerPackage,
String callerFeatureId, IIntentReceiver receiver, IntentFilter filter,
String permission, int userId, int flags) {
enforceNotIsolatedCaller("registerReceiver");
ArrayList<Intent> stickyIntents = null;
ProcessRecord callerApp = null;
final boolean visibleToInstantApps
= (flags & Context.RECEIVER_VISIBLE_TO_INSTANT_APPS) != 0;
// 1. 获取Uid, Pid, isInstantApp, actions
int callingUid;
int callingPid;
boolean instantApp;
synchronized(this) {
if (caller != null) {
callerApp = getRecordForAppLocked(caller);
if (callerApp == null) {
throw new SecurityException(
"Unable to find app for caller " + caller
+ " (pid=" + Binder.getCallingPid()
+ ") when registering receiver " + receiver);
}
if (callerApp.info.uid != SYSTEM_UID &&
!callerApp.pkgList.containsKey(callerPackage) &&
!"android".equals(callerPackage)) {
throw new SecurityException("Given caller package " + callerPackage
+ " is not running in process " + callerApp);
}
callingUid = callerApp.info.uid;
callingPid = callerApp.pid;
} else {
callerPackage = null;
callingUid = Binder.getCallingUid();
callingPid = Binder.getCallingPid();
}
instantApp = isInstantApp(callerApp, callerPackage, callingUid);
userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true,
ALLOW_FULL_ONLY, "registerReceiver", callerPackage);
Iterator<String> actions = filter.actionsIterator();
if (actions == null) {
ArrayList<String> noAction = new ArrayList<String>(1);
noAction.add(null);
actions = noAction.iterator();
}
// 2. 收集当前用户下的粘性广播
// Collect stickies of users
int[] userIds = { UserHandle.USER_ALL, UserHandle.getUserId(callingUid) };
while (actions.hasNext()) {
String action = actions.next();
for (int id : userIds) {
ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(id);
if (stickies != null) {
ArrayList<Intent> intents = stickies.get(action);
if (intents != null) {
if (stickyIntents == null) {
stickyIntents = new ArrayList<Intent>();
}
stickyIntents.addAll(intents);
}
}
}
}
}
ArrayList<Intent> allSticky = null;
if (stickyIntents != null) {
final ContentResolver resolver = mContext.getContentResolver();
// Look for any matching sticky broadcasts...
for (int i = 0, N = stickyIntents.size(); i < N; i++) {
Intent intent = stickyIntents.get(i);
// Don't provided intents that aren't available to instant apps.
if (instantApp &&
(intent.getFlags() & Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS) == 0) {
continue;
}
// If intent has scheme "content", it will need to acccess
// provider that needs to lock mProviderMap in ActivityThread
// and also it may need to wait application response, so we
// cannot lock ActivityManagerService here.
if (filter.match(resolver, intent, true, TAG) >= 0) {
if (allSticky == null) {
allSticky = new ArrayList<Intent>();
}
allSticky.add(intent);
}
}
}
// The first sticky in the list is returned directly back to the client.
Intent sticky = allSticky != null ? allSticky.get(0) : null;
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Register receiver " + filter + ": " + sticky);
if (receiver == null) {
return sticky;
}
// 3. 创建ReceiverList,BroadcastFilter对象,添加到AMS类变量mRegisteredReceivers, mReceiverResolver中维护。
synchronized (this) {
if (callerApp != null && (callerApp.thread == null
|| callerApp.thread.asBinder() != caller.asBinder())) {
// Original caller already died
return null;
}
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
if (rl == null) {
rl = new ReceiverList(this, callerApp, callingPid, callingUid,
userId, receiver);
if (rl.app != null) {
final int totalReceiversForApp = rl.app.receivers.size();
if (totalReceiversForApp >= MAX_RECEIVERS_ALLOWED_PER_APP) {
throw new IllegalStateException("Too many receivers, total of "
+ totalReceiversForApp + ", registered for pid: "
+ rl.pid + ", callerPackage: " + callerPackage);
}
rl.app.receivers.add(rl);
} else {
try {
receiver.asBinder().linkToDeath(rl, 0);
} catch (RemoteException e) {
return sticky;
}
rl.linkedToDeath = true;
}
mRegisteredReceivers.put(receiver.asBinder(), rl);
} else if (rl.uid != callingUid) {
throw new IllegalArgumentException(
"Receiver requested to register for uid " + callingUid
+ " was previously registered for uid " + rl.uid
+ " callerPackage is " + callerPackage);
} else if (rl.pid != callingPid) {
throw new IllegalArgumentException(
"Receiver requested to register for pid " + callingPid
+ " was previously registered for pid " + rl.pid
+ " callerPackage is " + callerPackage);
} else if (rl.userId != userId) {
throw new IllegalArgumentException(
"Receiver requested to register for user " + userId
+ " was previously registered for user " + rl.userId
+ " callerPackage is " + callerPackage);
}
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, callerFeatureId,
permission, callingUid, userId, instantApp, visibleToInstantApps);
if (rl.containsFilter(filter)) {
Slog.w(TAG, "Receiver with filter " + filter
+ " already registered for pid " + rl.pid
+ ", callerPackage is " + callerPackage);
} else {
rl.add(bf);
mReceiverResolver.addFilter(bf);
}
// Enqueue broadcasts for all existing stickies that match
// this filter.
if (allSticky != null) {
ArrayList receivers = new ArrayList();
receivers.add(bf);
final int stickyCount = allSticky.size();
for (int i = 0; i < stickyCount; i++) {
Intent intent = allSticky.get(i);
BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, null,
null, null, -1, -1, false, null, null, OP_NONE, null, receivers,
null, 0, null, null, false, true, true, -1, false,
false /* only PRE_BOOT_COMPLETED should be exempt, no stickies */);
queue.enqueueParallelBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
}
}
return sticky;
}
}
- 获取Uid, Pid, userId, isInstantApp, actions,做一些校验工作
- 收集当前用户下的粘性广播
- 创建ReceiverList,BroadcastFilter对象,添加到AMS类变量mRegisteredReceivers, mReceiverResolver中维护。
java
final HashMap<IBinder, ReceiverList> mRegisteredReceivers = new HashMap<>();
final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
= new IntentResolver<BroadcastFilter, BroadcastFilter>()
mRegisteredReceivers保存了每个IIntentReceiver注册的广播列表,IIntentReceiver对象在1.2小节被contextImple传入,对应一个BroadcastReceiver对象,BroadcastReceiver可能监听多个广播(添加了多个IntentFilter),ReceiverList代表其监听的广播。
ReceiverList类继承ArrayList<BroadcastFilter>,BroadcastFilter类继承IntentFilter,关注一下BroadcastFilter的构造方法:
java
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, callerFeatureId,
permission, callingUid, userId, instantApp, visibleToInstantApps);
应用程序调用registerReceiver()方法时注册广播接收器传递的IntentFilter参数filter
被传递给BroadcastFilter对象,通过此参数指明感兴趣的广播;创建的BroadcastFilter对象被添加到ReceiverList中:rl.add(bf);
;添加到mReceiverResolver中:mReceiverResolver.addFilter(bf);
,mReceiverResolver是一个IntentResolver对象,从命名就可以看出来IntentResolver负责Intent的处理解析工作,Intent在安卓各个组件中传递消息,IntentResolver负责将消息交给对应的组件。
IntentResolver维护几个Filter对象处理Intent解析工作:
java
// All of the MIME types that have been registered, such as "image/jpeg",
private final ArrayMap<String, F[]> mTypeToFilter = new ArrayMap<String, F[]>();
java
// All of the URI schemes (such as http) that have been registered.
private final ArrayMap<String, F[]> mSchemeToFilter = new ArrayMap<String, F[]>();
java
// All of the actions that have been registered, but only those that did not specify data.
private final ArrayMap<String, F[]> mActionToFilter = new ArrayMap<String, F[]>();
这里负责广播Intent解析工作的就是mActionToFilter
,mActionToFilter
使用ArrayMap<String, F[]>()数据结构保存action和IntentFilter[]的对应关系,发送广播时便从mActionToFilter
对象维护的ArrayMap中找到对应的IntentFilter,将信息封装成ResolveInfo对象就好了。
二、sendBroadcast
2.1 AMS.broadcastIntentLocked
java
// ActivityManagerService.java
@GuardedBy("this")
final int broadcastIntentLocked(ProcessRecord callerApp, String callerPackage,
@Nullable String callerFeatureId, Intent intent, String resolvedType,
IIntentReceiver resultTo, int resultCode, String resultData,
Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
boolean ordered, boolean sticky, int callingPid, int callingUid, int realCallingUid,
int realCallingPid, int userId, boolean allowBackgroundActivityStarts,
@Nullable int[] broadcastWhitelist) {
intent = new Intent(intent);
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
// 1. 处理安全问题,ProtectedBroadcast
final String action = intent.getAction();
final boolean isProtectedBroadcast;
isProtectedBroadcast = AppGlobals.getPackageManager().isProtectedBroadcast(action);
final boolean isCallerSystem;
switch (UserHandle.getAppId(callingUid)) {
case ROOT_UID:
case SYSTEM_UID:
case PHONE_UID:
case BLUETOOTH_UID:
case NFC_UID:
case SE_UID:
case NETWORK_STACK_UID:
isCallerSystem = true;
break;
default:
isCallerSystem = (callerApp != null) && callerApp.isPersistent();
break;
}
if (!isCallerSystem) {
if (isProtectedBroadcast) {
throw new SecurityException(msg);
} else if (AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(action)
|| AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {
//...
}
}
// 2. 粘性广播,安卓5.0后被弃用,不关注。
if (sticky) {
}
// 3. 计算广播接收者
List receivers = null;
List<BroadcastFilter> registeredReceivers = null;
// 3.1 FLAG_RECEIVER_REGISTERED_ONLY指定必须动态注册广播接收器才能接收,如果未指定,通过PMS通过Intent参数的component或者package查找接收器
if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
receivers = collectReceiverComponents(
intent, resolvedType, callingUid, users, broadcastWhitelist);
}
// 3.2 隐式广播,查找动态注册广播接收器,mReceiverResolver维护了在应用程序调用registerReceiver()添加的对应接收器
if (intent.getComponent() == null) {
if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) {
// ...
} else {
registeredReceivers = mReceiverResolver.queryIntent(intent,
resolvedType, false /*defaultOnly*/, userId);
}
}
final boolean replacePending =
(intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
// 4. 获取BroadcastQueue, 创建BroadcastRecord对象,添加到mParallelBroadcasts发送。
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.
final BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage,
callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType,
requiredPermissions, appOp, brOptions, registeredReceivers, resultTo,
resultCode, resultData, resultExtras, ordered, sticky, false, userId,
allowBackgroundActivityStarts, timeoutExempt);
final boolean replaced = replacePending
&& (queue.replaceParallelBroadcastLocked(r) != null);
// Note: We assume resultTo is null for non-ordered broadcasts.
if (!replaced) {
queue.enqueueParallelBroadcastLocked(r);// 添加到mParallelBroadcasts队列。
queue.scheduleBroadcastsLocked(); // 发送mParallelBroadcasts队列中的平行广播。
}
registeredReceivers = null;
NR = 0; // 将registeredReceivers和NR变量重置,避免后续合并到receivers中。
}
// 5. 合并receivers(静态注册),registeredReceivers(动态注册)到receivers变量中。
if (receivers != null) {
int NT = receivers != null ? receivers.size() : 0;
int it = 0;
ResolveInfo curt = null;
BroadcastFilter curr = null;
while (it < NT && ir < NR) { // 动态注册无序广播 NR == 0。
if (curt == null) {
curt = (ResolveInfo)receivers.get(it);
}
if (curr == null) {
curr = registeredReceivers.get(ir);
}
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();
}
receivers.add(registeredReceivers.get(ir));
ir++;
}
// 6. 将合并的静态注册广播根据优先级,添加到mOrderedBroadcasts发送。
if ((receivers != null && receivers.size() > 0)
|| resultTo != null) {
BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage,
callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType,
requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
resultData, resultExtras, ordered, sticky, false, userId,
allowBackgroundActivityStarts, timeoutExempt);
final BroadcastRecord oldRecord =
replacePending ? queue.replaceOrderedBroadcastLocked(r) : null;
if (oldRecord != null) {
if (oldRecord.resultTo != null) {
final BroadcastQueue oldQueue = broadcastQueueForIntent(oldRecord.intent);
oldQueue.performReceiveLocked(oldRecord.callerApp, oldRecord.resultTo,
oldRecord.intent,
Activity.RESULT_CANCELED, null, null,
false, false, oldRecord.userId);
}
} else {
queue.enqueueOrderedBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
}
}
}
发送广播:
-
检查是否protected广播,system app发送隐式广播需要是protected的,否则抛出wtf异常,发送显示广播没有这个限制;非system app没有权限发送protected广播,否则crash。
-
粘性广播处理,安卓5.0后被弃用,不关注。
-
查找计算广播接收者,注册广播接收有静态和动态两种方式。
- 没有指定Intent.FLAG_RECEIVER_REGISTERED_ONLY,可以发送给静态注册的接收器,collectReceiverComponents计算静态广播接收器,保存到receivers变量。
- 隐式广播,查找动态注册广播接收器,从1.3小节中可以看到,mReceiverResolver变量维护了在应用程序调用registerReceiver()添加的对应接收器。
-
发送动态注册的无序广播,静态注册的广播都认为是有序广播,所以这里处理的是动态注册的广播接收器,获取BroadcastQueue, 创建BroadcastRecord对象,添加到mParallelBroadcasts,开始广播发送工作。将registeredReceivers和NR变量重置,避免后续合并到receivers中。
BroadcastQueue分为前台广播队列,后台广播队列,指定了
Intent.FLAG_RECEIVER_FOREGROUND
被添加到前台广播队列,否则为后台队列。- 前台广播:前台广播数量较少,广播超时时间10S。
- 后台广播:默认为后台广播,广播数量较多,超时时间60S,后台广播在当前用户后台启动服务超过阈值时会暂停广播,等待服务启动完成再开始发送。
-
合并receivers(静态注册),registeredReceivers(动态注册的有序广播)到receivers变量中。
-
将合并的静态注册广播根据优先级,添加到mOrderedBroadcasts发送。从4、5、6三个步骤可以看出,动态注册的无序广播优先级更高,优先处理接收工作,动态注册有序广播和静态注册广播优点级较低,在动态注册的无序广播(平行广播)处理完之后开始处理。
2.2 collectReceiverComponents
java
// ActivityManagerService.java
private List<ResolveInfo> collectReceiverComponents(Intent intent, String resolvedType,
int callingUid, int[] users, int[] broadcastWhitelist) {
List<ResolveInfo> newReceivers = AppGlobals.getPackageManager()
.queryIntentReceivers(intent, resolvedType, pmFlags, user).getList();
}
java
// PackageManagerService.java
@Override
public @NonNull ParceledListSlice<ResolveInfo> queryIntentReceivers(Intent intent,
String resolvedType, int flags, int userId) {
return new ParceledListSlice<>(
queryIntentReceiversInternal(intent, resolvedType, flags, userId,
false /*allowDynamicSplits*/));
}
private @NonNull List<ResolveInfo> queryIntentReceiversInternal(Intent intent,
String resolvedType, int flags, int userId, boolean allowDynamicSplits) {
ComponentName comp = intent.getComponent();
// 1. 显式广播,指定接收者ComponentName
if (comp != null) {
final List<ResolveInfo> list = new ArrayList<>(1);
final ActivityInfo ai = getReceiverInfo(comp, flags, userId);
ResolveInfo ri = new ResolveInfo();
ri.activityInfo = ai;
list.add(ri);
return applyPostResolutionFilter(
list, instantAppPkgName, allowDynamicSplits, callingUid, false, userId,
intent);
}
// 2. 隐式广播,只能通过ComponentResolver查找接收者。
synchronized (mLock) {
String pkgName = intent.getPackage();
if (pkgName == null) {
final List<ResolveInfo> result =
mComponentResolver.queryReceivers(intent, resolvedType, flags, userId);
return applyPostResolutionFilter(
result, instantAppPkgName, allowDynamicSplits, callingUid, false, userId,
intent);
}
final AndroidPackage pkg = mPackages.get(pkgName);
if (pkg != null) {
final List<ResolveInfo> result = mComponentResolver.queryReceivers(
intent, resolvedType, flags, pkg.getReceivers(), userId);
return applyPostResolutionFilter(
result, instantAppPkgName, allowDynamicSplits, callingUid, false, userId,
intent);
}
return Collections.emptyList();
}
}
收集广播接收者:
- 显示广播,Intent setComponent()方法指定接收者。
- 隐式广播,需要PMS通过IntentResolver查找广播接受者。
看下IntentResolver的处理过程:
2.2.1 queryIntent
java
// IntentResolver.java
public List<R> queryIntent(Intent intent, String resolvedType, boolean defaultOnly,
int userId) {
String scheme = intent.getScheme();
ArrayList<R> finalList = new ArrayList<R>();
F[] firstTypeCut = null;
F[] secondTypeCut = null;
F[] thirdTypeCut = null;
F[] schemeCut = null;
// 1.处理MIME type,资源类型包括文本、图片、音视频等等。// Intent.setType("image/*");
// If the intent includes a MIME type, then we want to collect all of
// the filters that match that MIME type.
if (resolvedType != null) {
int slashpos = resolvedType.indexOf('/');
if (slashpos > 0) {
final String baseType = resolvedType.substring(0, slashpos);
if (!baseType.equals("*")) {
if (resolvedType.length() != slashpos+2
|| resolvedType.charAt(slashpos+1) != '*') {
// Not a wild card, so we can just look for all filters that
// completely match or wildcards whose base type matches.
firstTypeCut = mTypeToFilter.get(resolvedType);
secondTypeCut = mWildTypeToFilter.get(baseType);
} else {
// We can match anything with our base type.
firstTypeCut = mBaseTypeToFilter.get(baseType);
secondTypeCut = mWildTypeToFilter.get(baseType);
}
// Any */* types always apply, but we only need to do this
// if the intent type was not already */*.
thirdTypeCut = mWildTypeToFilter.get("*");
} else if (intent.getAction() != null) {
// The intent specified any type ({@literal *}/*). This
// can be a whole heck of a lot of things, so as a first
// cut let's use the action instead.
firstTypeCut = mTypedActionToFilter.get(intent.getAction());
}
}
}
// 2.处理scheme, 指定特定的模式,例如:content,http。// Intent.setData(Uri.fromFile(new File("/sdcard/test.3gp")));
// If the intent includes a data URI, then we want to collect all of
// the filters that match its scheme (we will further refine matches
// on the authority and path by directly matching each resulting filter).
if (scheme != null) {
schemeCut = mSchemeToFilter.get(scheme);
}
// 3.没有指定任何数据,通过action查找。// Intent.setAction("com.test.broadcast");
// If the intent does not specify any data -- either a MIME type or
// a URI -- then we will only be looking for matches against empty
// data.
if (resolvedType == null && scheme == null && intent.getAction() != null) {
firstTypeCut = mActionToFilter.get(intent.getAction());
}
// 4.处理category,category代表类别,定义了Activity的类别,Activity可以设置一个或者多个category标签。DEFAULT,HOME,LAUNCHER
FastImmutableArraySet<String> categories = getFastIntentCategories(intent);
if (firstTypeCut != null) {
buildResolveList(intent, categories, debug, defaultOnly, resolvedType,
scheme, firstTypeCut, finalList, userId);
}
if (secondTypeCut != null) {
buildResolveList(intent, categories, debug, defaultOnly, resolvedType,
scheme, secondTypeCut, finalList, userId);
}
if (thirdTypeCut != null) {
buildResolveList(intent, categories, debug, defaultOnly, resolvedType,
scheme, thirdTypeCut, finalList, userId);
}
if (schemeCut != null) {
buildResolveList(intent, categories, debug, defaultOnly, resolvedType,
scheme, schemeCut, finalList, userId);
}
filterResults(finalList);
sortResults(finalList);
return finalList;
}
总结一下:对Intent的处理主要分为4个部分:MIME,scheme,action,category。
- 处理MIME type,资源类型包括文本、图片、音视频等等。
// Intent.setType("image/*");
- 处理scheme, 指定特定的模式,例如:content,http。
// Intent.setData(Uri.fromFile(new File("/sdcard/test.3gp")));
- 处理action,没有指定任何数据,通过action查找。
// Intent.setAction("com.test.broadcast");
- 处理category,category代表了Activity的类别,Activity可以设置一个或者多个category标签。DEFAULT,HOME,LAUNCHER。
// Intent.addCategory(Intent.CATEGORY_LAUNCHER);
隐式广播在这个过程中找到之前已经注册的广播接收器。
2.3 processNextBroadcastLocked
整理好广播接收者后,BroadcastQueue.scheduleBroadcastsLocked()执行广播发送。
java
// BroadcastQueue.java
final void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj) {
BroadcastRecord r;
// 1. mParallelBroadcasts,并行广播立即执行,不需要等待上个广播接收完成,目前只针对动态注册的广播接受者。
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, i);
}
}
// 2.mPendingBroadcast,如果存在mPendingBroadcast,且进程正在启动过程中,return等待进程启动完成接收广播,完成接收后使mPendingBroadcast=null。
if (mPendingBroadcast != null) {
boolean isDead;
if (mPendingBroadcast.curApp.pid > 0) {
synchronized (mService.mPidsSelfLocked) {
ProcessRecord proc = mService.mPidsSelfLocked.get(
mPendingBroadcast.curApp.pid);
isDead = proc == null || proc.isCrashing();
}
} else {
final ProcessRecord proc = mService.mProcessList.mProcessNames.get(
mPendingBroadcast.curApp.processName, mPendingBroadcast.curApp.uid);
isDead = proc == null || !proc.pendingStart;
}
if (!isDead) {
// It's still alive, so keep waiting
return;
} else {
mPendingBroadcast.state = BroadcastRecord.IDLE;
mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
mPendingBroadcast = null;
}
}
// 3. 从mOrderedBroadcasts获取下一个BroadcastRecord对象
do {
final long now = SystemClock.uptimeMillis();
r = mDispatcher.getNextBroadcastLocked(now);
} while (r == null);
// 4.发送广播
ResolveInfo info =
(ResolveInfo)nextReceiver;
ComponentName component = new ComponentName(
info.activityInfo.applicationInfo.packageName,
info.activityInfo.name);
final int receiverUid = info.activityInfo.applicationInfo.uid;
String targetProcess = info.activityInfo.processName;
ProcessRecord app = mService.getProcessRecordLocked(targetProcess,
info.activityInfo.applicationInfo.uid, false);
r.manifestCount++;
r.delivery[recIdx] = BroadcastRecord.DELIVERY_DELIVERED;
r.state = BroadcastRecord.APP_RECEIVE;
r.curComponent = component;
r.curReceiver = info.activityInfo;
// 4.1 广播接收进程已启动,processCurBroadcastLocked
if (app != null && app.thread != null && !app.killed) {
app.addPackage(info.activityInfo.packageName,
info.activityInfo.applicationInfo.longVersionCode, mService.mProcessStats);
maybeAddAllowBackgroundActivityStartsToken(app, r);
processCurBroadcastLocked(r, app, skipOomAdj);
return;
}
// 4.2 广播接收进程未启动,startProcessLocked,mPendingBroadcast = r;
if ((r.curApp=mService.startProcessLocked(targetProcess,
info.activityInfo.applicationInfo, true,
r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
new HostingRecord("broadcast", r.curComponent),
isActivityCapable ? ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE : ZYGOTE_POLICY_FLAG_EMPTY,
(r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false, false))
== null) {
// 启动失败
}
// 赋值mPendingBroadcast
mPendingBroadcast = r;
}
- 处理动态注册的广播接收者mParallelBroadcasts,并行广播立即执行,不需要等待上个广播接收完成,目前只针对动态注册的广播接收者,因为动态注册说明这个接收者的应用进程已经启动了。
- 处理mPendingBroadcast,如果存在mPendingBroadcast,且进程正在启动过程中,return等待进程启动完成接收广播,一些静态注册的广播接收者在广播发送后可能应用进程还未启动,所以先拉起应用进程,在应用进程启动后再执行广播接收,完成接收后使mPendingBroadcast=null。
- 从mOrderedBroadcasts获取下一个BroadcastRecord对象。
- 发送广播,发送广播分为两种情况:a.接受者应用进程已经启动(常见于动态注册);b.接收者进程未启动(常见于静态注册),如果进程未启动,需要先拉起应用进程,将广播赋值给mPendingBroadcast变量记录下来,然后回到上面说的第2种情况。应用进程启动后会调用AMS的attachApplicationLocked方法通知应用启动完成,然后调用sendPendingBroadcastsLocked处理待接收的广播,同样Activity和Service也是这样处理,处理顺序是Activity->Service->Broadcast。
2.4 processCurBroadcastLocked
java
// BroadcastQueue.java
private final void processCurBroadcastLocked(BroadcastRecord r,
ProcessRecord app, boolean skipOomAdj) throws RemoteException {
r.receiver = app.thread.asBinder();
r.curApp = app;
app.curReceivers.add(r);
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
mService.mProcessList.updateLruProcessLocked(app, false, null);
// Tell the application to launch this receiver.
r.intent.setComponent(r.curComponent);
mService.notifyPackageUse(r.intent.getComponent().getPackageName(),
PackageManager.NOTIFY_PACKAGE_USE_BROADCAST_RECEIVER);
app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
mService.compatibilityInfoForPackage(r.curReceiver.applicationInfo),
r.resultCode, r.resultData, r.resultExtras, r.ordered, r.userId,
app.getReportedProcState());
}
更新AMS和PMS中的一些进程状态:ProcessState,Lru,PackageUsage等。
2.4.1 handleReceiver
app.thread.scheduleReceiver()通知应用进程回调onReceive()方法。
java
// ActivityThread.java
private void handleReceiver(ReceiverData data) {
Application app;
BroadcastReceiver receiver;
ContextImpl context;
app = packageInfo.makeApplication(false, mInstrumentation);
context = (ContextImpl) app.getBaseContext();
java.lang.ClassLoader cl = context.getClassLoader();
data.intent.setExtrasClassLoader(cl);
data.intent.prepareToEnterProcess();
data.setExtrasClassLoader(cl);
receiver = packageInfo.getAppFactory()
.instantiateReceiver(cl, data.info.name, data.intent);
receiver.setPendingResult(data);
receiver.onReceive(context.getReceiverRestrictedContext(),
data.intent);
}