前面文章介绍了Android注册广播的过程,这篇介绍下广播的发送过程。
广播的发送过程比广播的注册过程复杂的多,主要有以下几个步骤:
1.广播的发送者将一个特定类型的广播发送给ActivityManagerService。
2.AMS接收到这个广播后,首先找到与这个广播对应的广播接收者,然后将它们添加到一个广播调度队列中,再将这个调度队列传递给BroadcastQueue,最后向BroadcastQueue的消息队列发送一个类型为BROADCAST_INTENT_MSG的消息,此时对于广播发送者来说,一个广播的发送就完成了。
3.当消息队列中的BROADCAST_INTENT_MSG消息被处理时,BroadcastQueue就会从广播调度队列中找对需要接收广播的接收者,并且将对应的广播发送给它们所运行在的应用程序进程。
4.广播接收者所运行在的应用程序进程接收到广播后,并不是直接将接收到的广播分发给各个广播接收者来处理,而是将接收到的广播封装成一个消息,并且发送到主线程的消息队列中。当这个消息被处理时,应用程序进程才会将它所描述的广播发送给相应的广播接收者处理。
惯例先看时序图,由于发送广播的过程有点复杂,所以时序图分开画的。sendBroadcast、sendOrderedBroadcast和sendStickyBroadcast方法在调用broadcastIntent方法之前的流程是一样的,这里只画出sendBroadcast方法的时序图:
说明:一个广播是使用一个Intent对象来描述的,而这个Intent对象的action名称就是用来描述它所对应的广播类型。
广播的发送也是从ContextWrapper类开始的:
@Override
public void sendBroadcast(Intent intent) {
mBase.sendBroadcast(intent);
}
ContextImpl类的sendBroadcast方法:
@Override
public void sendBroadcast(Intent intent) {
// 如果调用者是系统进程的话打印log
warnIfCallingFromSystemProcess();
// Intent的MIME数据类型,没有设置则为null
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
// 准备离开应用程序进程,进入AMS进程
intent.prepareToLeaveProcess();
// 调用ActivityManagerProxy类的broadcastIntent方法来实现广播的发送
// ActivityManagerProxy是一个Binder对象的远程接口,而这个Binder对象就是ActivityManagerService
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);
}
}
ActivityManagerService类的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);
// 通过ApplicationThread对象从成员变量mLruProcesses列表中查找调用者的ProcessRecord对象
final ProcessRecord callerApp = getRecordForAppLocked(caller);
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
// 调用broadcastIntentLocked方法处理 intent 所描述的广播
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方法中主要是用来查找目标广播接收者的:
/**
* State of all active sticky broadcasts per user. Keys are the action of the
* sticky Intent, values are an ArrayList of all broadcasted intents with
* that action (which should usually be one). The SparseArray is keyed
* by the user ID the sticky is for, and can include UserHandle.USER_ALL
* for stickies that are sent to all users.
*/
final SparseArray<ArrayMap<String, ArrayList<Intent>>> mStickyBroadcasts =
new SparseArray<ArrayMap<String, ArrayList<Intent>>>();
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) {
intent = new Intent(intent);
// By default broadcasts do not go to stopped apps.
// 设置这个flag后,intent将不会去匹配这个package中当前停止运行的组件。
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
// If we have not finished booting, don't allow this to launch new processes.
// FLAG_RECEIVER_BOOT_UPGRADE标志是广播用于系统升级的,如果设置了该标记,允许系统在启动完成前发送广播
if (!mProcessesReady && (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) {
// 追加FLAG_RECEIVER_REGISTERED_ONLY标志后,只有动态注册的广播接收者能收到广播
// 这是因为在系统启动过程中,PackageManagerService可能还未启动,此时AMS是无法获得静态注册的广播接收者的
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
}
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
(sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
+ " ordered=" + ordered + " userid=" + userId);
if ((resultTo != null) && !ordered) {
Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
}
// 处理调用者uid
userId = handleIncomingUser(callingPid, callingUid, userId,
true, ALLOW_NON_FULL, "broadcast", callerPackage);
// Make sure that the user who is receiving this broadcast is running.
// If not, we will just skip it. Make an exception for shutdown broadcasts
// and upgrade steps.
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())) {
Slog.w(TAG, "Skipping broadcast of " + intent
+ ": user " + userId + " is stopped");
return ActivityManager.BROADCAST_FAILED_USER_STOPPED;
}
}
BroadcastOptions brOptions = null;
if (options != null) {
brOptions = new BroadcastOptions(options);
if (brOptions.getTemporaryAppWhitelistDuration() > 0) {
// See if the caller is allowed to do this. Note we are checking against
// the actual real caller (not whoever provided the operation as say a
// PendingIntent), because that who is actually supplied the arguments.
if (checkComponentPermission(
android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
Binder.getCallingPid(), Binder.getCallingUid(), -1, true)
!= PackageManager.PERMISSION_GRANTED) {
String msg = "Permission Denial: " + intent.getAction()
+ " broadcast from " + callerPackage + " (pid=" + callingPid
+ ", uid=" + callingUid + ")"
+ " requires "
+ android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST;
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
}
}
/*
* Prevent non-system code (defined here to be non-persistent
* processes) from sending protected broadcasts.
* 防止非系统代码(这里定义为非持久性进程)发送受保护的广播
*/
int callingAppId = UserHandle.getAppId(callingUid);
if (callingAppId == Process.SYSTEM_UID || callingAppId == Process.PHONE_UID
|| callingAppId == Process.SHELL_UID || callingAppId == Process.BLUETOOTH_UID
|| callingAppId == Process.NFC_UID || callingUid == 0) {
// Always okay.
} else if (callerApp == null || !callerApp.persistent) {// 调用者为null或者调用者不是持久性进程
try {
// 非系统应用不能发送受保护的广播
if (AppGlobals.getPackageManager().isProtectedBroadcast(
intent.getAction())) {
String msg = "Permission Denial: not allowed to send broadcast "
+ intent.getAction() + " from pid="
+ callingPid + ", uid=" + callingUid;
Slog.w(TAG, msg);
throw new SecurityException(msg);
} else if (AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(intent.getAction())) {
// Special case for compatibility(兼容性): we don't want apps to send this,
// but historically it has not been protected and apps may be using it
// to poke(干涉) their own app widget. So, instead of making it protected,
// just limit it to the caller.
if (callerApp == null) {
String msg = "Permission Denial: not allowed to send broadcast "
+ intent.getAction() + " from unknown caller.";
Slog.w(TAG, msg);
throw new SecurityException(msg);
// 接收目标组件不为null
} else if (intent.getComponent() != null) {
// They are good enough to send to an explicit component... verify
// it is being sent to the calling app.
if (!intent.getComponent().getPackageName().equals(
callerApp.info.packageName)) {
String msg = "Permission Denial: not allowed to send broadcast "
+ intent.getAction() + " to "
+ intent.getComponent().getPackageName() + " from "
+ callerApp.info.packageName;
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
} else {
// 发送者不为null,接收者组件为null时,设置接收者只能是发送者
// Limit broadcast to their own package.
intent.setPackage(callerApp.info.packageName);
}
}
} catch (RemoteException e) {
Slog.w(TAG, "Remote exception", e);
return ActivityManager.BROADCAST_SUCCESS;
}
}
final String action = intent.getAction();
if (action != null) {
// 特殊的Action有不同的处理方式
switch (action) {
case Intent.ACTION_UID_REMOVED:
case Intent.ACTION_PACKAGE_REMOVED:
case Intent.ACTION_PACKAGE_CHANGED:
case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:
// Handle special intents: if this broadcast is from the package
// manager about a package being removed, we need to remove all of
// its activities from the history stack.
if (checkComponentPermission(
android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
callingPid, callingUid, -1, true)
!= PackageManager.PERMISSION_GRANTED) {
String msg = "Permission Denial: " + intent.getAction()
+ " broadcast from " + callerPackage + " (pid=" + callingPid
+ ", uid=" + callingUid + ")"
+ " requires "
+ android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
switch (action) {
case Intent.ACTION_UID_REMOVED:
final Bundle intentExtras = intent.getExtras();
final int uid = intentExtras != null
? intentExtras.getInt(Intent.EXTRA_UID) : -1;
if (uid >= 0) {
mBatteryStatsService.removeUid(uid);
mAppOpsService.uidRemoved(uid);
}
break;
// app正在移动到SD卡中,发出的广播
case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
// If resources are unavailable just force stop all those packages
// and flush the attribute cache as well.
String list[] =
intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
if (list != null && list.length > 0) {
for (int i = 0; i < list.length; i++) {
forceStopPackageLocked(list[i], -1, false, true, true,
false, false, userId, "storage unmount");
}
// 清空app的任务栈
mRecentTasks.cleanupLocked(UserHandle.USER_ALL);
// 发送app不可用的广播
sendPackageBroadcastLocked(
IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list,
userId);
}
break;
// app完成移动到SD的操作,发出的广播
case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:
mRecentTasks.cleanupLocked(UserHandle.USER_ALL);
break;
case Intent.ACTION_PACKAGE_REMOVED:
case Intent.ACTION_PACKAGE_CHANGED:
Uri data = intent.getData();
String ssp;
if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
boolean removed = Intent.ACTION_PACKAGE_REMOVED.equals(action);
boolean fullUninstall = removed &&
!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
final boolean killProcess =
!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false);
if (killProcess) {
forceStopPackageLocked(ssp, UserHandle.getAppId(
intent.getIntExtra(Intent.EXTRA_UID, -1)),
false, true, true, false, fullUninstall, userId,
removed ? "pkg removed" : "pkg changed");
}
if (removed) {
sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
new String[] {ssp}, userId);
if (fullUninstall) {
mAppOpsService.packageRemoved(
intent.getIntExtra(Intent.EXTRA_UID, -1), ssp);
// Remove all permissions granted from/to this package
removeUriPermissionsForPackageLocked(ssp, userId, true);
removeTasksByPackageNameLocked(ssp, userId);
mBatteryStatsService.notePackageUninstalled(ssp);
}
} else {
cleanupDisabledPackageComponentsLocked(ssp, userId, killProcess,
intent.getStringArrayExtra(
Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST));
}
}
break;
}
break;
case Intent.ACTION_PACKAGE_ADDED:
// Special case for adding a package: by default turn on compatibility mode.
Uri data = intent.getData();
String ssp;
if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
final boolean replacing =
intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
mCompatModePackages.handlePackageAddedLocked(ssp, replacing);
try {
ApplicationInfo ai = AppGlobals.getPackageManager().
getApplicationInfo(ssp, 0, 0);
mBatteryStatsService.notePackageInstalled(ssp,
ai != null ? ai.versionCode : 0);
} catch (RemoteException e) {
}
}
break;
case Intent.ACTION_TIMEZONE_CHANGED:
// If this is the time zone changed action, queue up a message that will reset
// the timezone of all currently running processes. This message will get
// queued up before the broadcast happens.
mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
break;
case Intent.ACTION_TIME_CHANGED:
// If the user set the time, let all running processes know.
final int is24Hour =
intent.getBooleanExtra(Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT, false) ? 1
: 0;
mHandler.sendMessage(mHandler.obtainMessage(UPDATE_TIME, is24Hour, 0));
BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
synchronized (stats) {
stats.noteCurrentTimeChangedLocked();
}
break;
case Intent.ACTION_CLEAR_DNS_CACHE:
mHandler.sendEmptyMessage(CLEAR_DNS_CACHE_MSG);
break;
case Proxy.PROXY_CHANGE_ACTION:
ProxyInfo proxy = intent.getParcelableExtra(Proxy.EXTRA_PROXY_INFO);
mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY_MSG, proxy));
break;
}
}
//SmartContainer modified begin
if (!SmartContainerConfig.WITH_OUT_VIRTUAL_BOX){
if (mAMSFunc.processSpecialIntent(intent,callingUid, userId) != 0)
return ActivityManager.BROADCAST_SUCCESS;
}
//SmartContainer modified end
// Add to the sticky list if requested.
if (sticky) {
// 粘性广播要加BROADCAST_STICKY权限
if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
callingPid, callingUid)
!= PackageManager.PERMISSION_GRANTED) {
String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
+ callingPid + ", uid=" + callingUid
+ " requires " + android.Manifest.permission.BROADCAST_STICKY;
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
// 发送粘性广播不能有其他权限
if (requiredPermissions != null && requiredPermissions.length > 0) {
Slog.w(TAG, "Can't broadcast sticky intent " + intent
+ " and enforce permissions " + Arrays.toString(requiredPermissions));
return ActivityManager.BROADCAST_STICKY_CANT_HAVE_PERMISSION;
}
// 粘性广播不能发给指定的接收组件
if (intent.getComponent() != null) {
throw new SecurityException(
"Sticky broadcasts can't target a specific component");
}
// We use userId directly here, since the "all" target is maintained
// as a separate set of sticky broadcasts.
if (userId != UserHandle.USER_ALL) {
// But first, if this is not a broadcast to all users, then
// make sure it doesn't conflict with an existing broadcast to
// all users.
// 如果广播不是发给所有用户的,则确认对所有用户它不会跟当前存在的广播冲突
ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(
UserHandle.USER_ALL);
if (stickies != null) {
// 根据Action获取action相同的Intent列表
ArrayList<Intent> list = stickies.get(intent.getAction());
if (list != null) {
int N = list.size();
int i;
for (i=0; i<N; i++) {
// 粘性广播发送后是会保存下来的,故如果已经存在则不需要重新发送
if (intent.filterEquals(list.get(i))) {
throw new IllegalArgumentException(
"Sticky broadcast " + intent + " for user "
+ userId + " conflicts with existing global broadcast");
}
}
}
}
}
// 在mStickyBroadcasts中根据参数userId查找以Action、广播列表为键值对的stickies,
// 如果不存在,则创建并添加
ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);
if (stickies == null) {
stickies = new ArrayMap<>();
mStickyBroadcasts.put(userId, stickies);
}
// 在stickies中查找是否存在与参数intent的Action名称对应的一个粘性广播列表list,
// 如果不存在,则创建并添加
ArrayList<Intent> list = stickies.get(intent.getAction());
if (list == null) {
list = new ArrayList<>();
stickies.put(intent.getAction(), list);
}
final int stickiesCount = list.size();
int i;
// 遍历检查在粘性广播列表list中是否存在一个与参数intent一致的广播
for (i = 0; i < stickiesCount; i++) {
// 如果存在则用intent参数所描述的广播来替换它
if (intent.filterEquals(list.get(i))) {
// This sticky already exists, replace it.
list.set(i, new Intent(intent));
break;
}
}
// 说明list列表中不存在与intent参数一致的广播
if (i >= stickiesCount) {
// 则把该intent所描述的广播添加到list列表中
list.add(new Intent(intent));
}
}
int[] users;
if (userId == UserHandle.USER_ALL) {
// Caller wants broadcast to go to all started users.
users = mStartedUserArray;
} else {
// Caller wants broadcast to go to one specific user.
users = new int[] {userId};
}
//SmartContainer Modified begin
int alternativeBoxId = userId;
Set<Integer> boxesToReceive = new HashSet<Integer>();
boxesToReceive.add(userId);
//SmartContainer Modified end
// Figure out who all will receive this broadcast.
List receivers = null;// 静态广播接收器列表
List<BroadcastFilter> registeredReceivers = null;// 动态广播接收器列表
// Need to resolve the intent to interested receivers...
if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
== 0) {
// 之前讲解注册广播时,静态注册的广播都保存在PMS中的mReceivers中了,
// 现在到PMS中找到所有静态注册的目标广播接收者,并保存在列表receivers中
receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
}
//SmartContainer modified begin
if (!SmartContainerConfig.WITH_OUT_VIRTUAL_BOX){
if (receivers != null && receivers.size() > 0 && callerPackage!= null){
mAMSFunc.processReceiverComponents(boxesToReceive, receivers, callerPackage, userId);
}
}
//SmartContainer modified end
// 没有指定接收者组件名
if (intent.getComponent() == null) {
if (userId == UserHandle.USER_ALL && callingUid == Process.SHELL_UID) {
// Query one target user at a time, excluding shell-restricted users
UserManagerService ums = getUserManagerLocked();
for (int i = 0; i < users.length; i++) {
if (ums.hasUserRestriction(
UserManager.DISALLOW_DEBUGGING_FEATURES, users[i])) {
continue;
}
List<BroadcastFilter> registeredReceiversForUser =
mReceiverResolver.queryIntent(intent,
resolvedType, false, users[i]);
if (registeredReceivers == null) {
registeredReceivers = registeredReceiversForUser;
} else if (registeredReceiversForUser != null) {
registeredReceivers.addAll(registeredReceiversForUser);
}
}
} else {
// 之前讲解注册广播时,动态注册的广播都存放在AMS的mReceiverResolver中了,
// 这里就在里面找到动态注册的目标广播接收者,并保存在registeredReceivers列表中
registeredReceivers = mReceiverResolver.queryIntent(intent,
resolvedType, false, userId);
//SmartContainer modified begin
if (userId != UserHandle.USER_ALL && !SmartContainerConfig.WITH_OUT_VIRTUAL_BOX &&
(registeredReceivers == null || registeredReceivers.size() == 0)) {
alternativeBoxId = mAMSFunc.processRegisterReceivers(registeredReceivers,
boxesToReceive, intent, resolvedType, userId, alternativeBoxId, callingUid);
}
//SmartContainer modified end
}
}
// 查看intent的flag有没有设置FLAG_RECEIVER_REPLACE_PENDING,如果设置的话,
// AMS就会在当前的系统中查看有没有相同的intent还未处理,如果有的话,就用当前这个新的intent
// 来替换旧的intent。
final boolean replacePending =
(intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueing broadcast: " + intent.getAction()
+ " replacePending=" + replacePending);
int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
// 参数ordered标记当前发送的广播是否是有序广播,如果不是,并且存在动态注册的目标广播接收者
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.
// broadcastQueueForIntent方法判断要发送的广播是前台广播还是后台广播,如果是前台广播则返回前台广播队列,
// 不同队列处理超时的时间不一样:前台10秒、后台60秒
final BroadcastQueue queue = broadcastQueueForIntent(intent);
//SmartContainer modified begin
if( SmartContainerConfig.WITH_OUT_APP_CLONE || boxesToReceive.size() == 1
|| userId == UserHandle.USER_ALL ){
// 将intent所描述的广播,以及动态注册的目标广播接收者封装成一个BroadcastRecord对象r,
// 用来描述AMS要执行的一个广播转发任务
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
callerPackage, callingPid, callingUid, resolvedType, requiredPermissions,
appOp, brOptions, registeredReceivers, resultTo, resultCode, resultData,
resultExtras, ordered, sticky, false, alternativeBoxId);
Slog.v(TAG_BROADCAST, "Enqueueing parallel broadcast " + r + " intent " + intent);
// replaceParallelBroadcastLocked方法根据r到queue中的无序调度队列中查找是否存在与intent描述一致的广播,存在则替换并返回true
final boolean replaced = replacePending && queue.replaceParallelBroadcastLocked(r);
// 如果replaced为true,说明不需要在无序广播调度队列中增加新的广播转发任务
if (!replaced) {
// 否者就把r所描述的广播转发任务放在BroadcastQueue类中的mParallelBroadcasts无序调度队列中
queue.enqueueParallelBroadcastLocked(r);
// 重新调度这个队列中的广播转发任务,从这里可以看出动态注册的广播接收者
// 比静态注册的广播接收者优先接收到无序广播
queue.scheduleBroadcastsLocked();
}
} else {
List<BroadcastFilter> broadcastFilterList = new ArrayList<BroadcastFilter>();
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
callerPackage, callingPid, callingUid, resolvedType, requiredPermissions,
appOp, brOptions, broadcastFilterList, resultTo, resultCode, resultData,
resultExtras, ordered, sticky, false, -1);
mAMSFunc.queueNOrderedRegisteredBroadcastForClone(registeredReceivers, r, boxesToReceive, intent, replacePending);
}
//SmartContainer modified end
// 到这里,对于无序广播来说,AMS就相当于已经将参数intent描述的广播发给那些动态注册的目标广播接收者了。
// 故,这里就将列表registeredReceivers设置为null,将标记动态注册的目标广播接收者个数的变量NR设置为0
registeredReceivers = null;
NR = 0;
}
// 执行到这里,无论AMS当前接收到的是一个无序广播还是有序广播,都会将该广播及其目标广播接收者封装成一个广播转发任务,
// 并添加到一个有序广播调度队列中。但对于无序广播来说,当它们被真正转发时,并不会按照有序广播来转发。
// 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.
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) {
// 特殊广播查看ssp有没有指定包名,有则赋值给skipPackages
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);
// 如果静态注册的广播接收者应用的包名和skipPackage一致,则从receivers移除
if (curt.activityInfo.packageName.equals(skipPackage)) {
receivers.remove(it);
it--;
NT--;
}
}
}
}
}
int NT = receivers != null ? receivers.size() : 0;
int it = 0;
ResolveInfo curt = null;
BroadcastFilter curr = null;
// 这里动态注册广播合并的是有序的,因为无序动态广播处理中NR最后被赋值为0了
while (it < NT && ir < NR) {
if (curt == null) {
// 静态注册的广播是ResolveInfo类型
curt = (ResolveInfo)receivers.get(it);
}
if (curr == null) {
// 动态注册的广播是BroadcastFilter类型,后面会根据类型判断广播是动态注册还是静态注册的
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;
}
}
}
// 把优先级低于所有静态注册广播接收者的动态广播接收者都追加到receivers列表中的末尾
while (ir < NR) {
if (receivers == null) {
receivers = new ArrayList();
}
receivers.add(registeredReceivers.get(ir));
ir++;
}
// 到这里,对于无序广播来说,静态注册的目标广播接收者就全部保存在列表receivers中了;
// 而对于有序广播来说,静态注册和动态注册的目标广播接收者也全部保存在列表receivers中了。
if ((receivers != null && receivers.size() > 0)
|| resultTo != null) {
//SmartContainer Modified begin
if ( SmartContainerConfig.WITH_OUT_VIRTUAL_BOX || userId == UserHandle.USER_ALL
|| receivers == null || receivers.size() == 0) {
BroadcastQueue queue = broadcastQueueForIntent(intent);
// 将intent所描述的广播,以及剩余的其他目标广播接收者封装成另外一个BroadcastRecord对象r,
// 用来描述AMS要执行的另一个广播转发任务,并且添加到有序广播调度队列中。
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
callerPackage, callingPid, callingUid, resolvedType,
requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
resultData, resultExtras, ordered, sticky, false, userId);
Slog.v(TAG_BROADCAST, "Enqueueing ordered broadcast " + r
+ ": prev had " + queue.mOrderedBroadcasts.size());
Slog.i(TAG_BROADCAST,
"Enqueueing broadcast " + r.intent.getAction());
// replaceOrderedBroadcastLocked方法根据r到queue中的有序调度队列中查找是否存在与intent描述一致的广播,存在则替换并返回true
boolean replaced = replacePending && queue.replaceOrderedBroadcastLocked(r);
// 如果replaced为true,说明不需要在有序广播调度队列中增加新的广播转发任务
if (!replaced) {
// 否者把r所描述的广播转发任务放在BroadcastQueue类中的mOrderedBroadcasts有序广播调度队列中
queue.enqueueOrderedBroadcastLocked(r);
// 重新调度这个队列中的广播转发任务
queue.scheduleBroadcastsLocked();
}
} else {
List receiverList = new ArrayList();
BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
callerPackage, callingPid, callingUid, resolvedType,
requiredPermissions, appOp, brOptions, receiverList, resultTo, resultCode,
resultData, resultExtras, ordered, sticky, false, -1);
mAMSFunc.queueFinalBroadcastForClone(receivers, r, boxesToReceive, intent, userId, replacePending);
}
//SmartContainer Modified end
}
return ActivityManager.BROADCAST_SUCCESS;
}
至此,AMS就找到参数intent所描述广播的目标广播接收者了,并且分别将它们保存在了BroadcastRecord类的无序广播调度队列mParallelBroadcasts(包括动态注册的无序广播接收者)中和有序广播调度队列mOrderedBroadcasts(包括动态注册的有序广播接收者和所有静态注册的广播接收者)中。
接下来,AMS就会调用BroadcastQueue类中的scheduleBroadcastsLocked方法将intent所描述的广播转发给目标广播接收者处理:
public void scheduleBroadcastsLocked() {
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Schedule broadcasts ["
+ mQueueName + "]: current="
+ mBroadcastsScheduled);
if (mBroadcastsScheduled) {
return;
}
mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
mBroadcastsScheduled = true;
}
上面mBroadcastsScheduled参数是用来标记是否已经向消息队列发送了一个类型为BROADCAST_INTENT_MSG消息。BroadcastQueue就是通过这个消息来调度保存在无序广播调度队列和有序广播调度队列中的广播转发任务的。
这里,虽然还没有将广播转发给各目标广播接收者,但是当它执行完成这一步之后,广播发送者就会认为这个广播已经发送成功了。从这里就可以看出,广播的发送和接收是异步的。
mHandler是BroadcastQueue类的内部类BroadcastHandler的实例,在BroadcastQueue类的构造方法中赋初值。
下面看下它的handleMessage方法:
final BroadcastHandler mHandler;
private final class BroadcastHandler extends Handler {
public BroadcastHandler(Looper looper) {
super(looper, null, true);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case BROADCAST_INTENT_MSG: {
if (DEBUG_BROADCAST) Slog.v(
TAG_BROADCAST, "Received BROADCAST_INTENT_MSG");
// 处理广播的转发任务
processNextBroadcast(true);
} break;
case BROADCAST_TIMEOUT_MSG: {
synchronized (mService) {
// 处理广播超时的操作,报ANR异常
broadcastTimeoutLocked(true);
}
} break;
case SCHEDULE_TEMP_WHITELIST_MSG: {
DeviceIdleController.LocalService dic = mService.mLocalDeviceIdleController;
if (dic != null) {
dic.addPowerSaveTempWhitelistAppDirect(UserHandle.getAppId(msg.arg1),
msg.arg2, true, (String)msg.obj);
}
} break;
}
}
};
processNextBroadcast方法主要是用来将广播转发给各目标广播接收者处理:
final void processNextBroadcast(boolean fromMsg) {
/*可以在这里获取允许自启动的名单*/
synchronized(mService) {
BroadcastRecord r;
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "processNextBroadcast ["
+ mQueueName + "]: "
+ mParallelBroadcasts.size() + " broadcasts, "
+ mOrderedBroadcasts.size() + " ordered broadcasts");
mService.updateCpuStats();
// fromMsg字段标记是否是从handleMessage中调用的该方法
if (fromMsg) {
// 设置该参数为false,表示前面发送到消息队列中的BROADCAST_INTENT_MSG消息已经被处理了
mBroadcastsScheduled = false;
}
// First, deliver any non-serialized broadcasts right away.
// 循环处理保存在无序广播调度队列mParallelBroadcasts中的广播转发任务,
// 即:将保存在无序广播调度队列中的广播发送给它的目标广播接收者(动态无序)处理
while (mParallelBroadcasts.size() > 0) {
// 得到mParallelBroadcasts中保存的第一个广播转发任务r
r = mParallelBroadcasts.remove(0);
r.dispatchTime = SystemClock.uptimeMillis();
r.dispatchClockTime = System.currentTimeMillis();
final int N = r.receivers.size();
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing parallel broadcast ["
+ mQueueName + "] " + r);
for (int i=0; i<N; i++) {
Object target = r.receivers.get(i);
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Delivering non-ordered on [" + mQueueName + "] to registered "
+ target + ": " + r);
// 遍历循环将无序广播发送给每一个目标广播接收者(动态注册的)
deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
}
// 添加r到历史队列中
addBroadcastToHistoryLocked(r);
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["
+ mQueueName + "] " + r);
}
// Now take care of the next serialized one...
// 接下来,继续处理保存在有序广播调度队列mOrderedBroadcasts中的广播转发任务。
// 前面讲到有序广播调度队列mOrderedBroadcasts中描述的广播的目标接收者有可能是静态注册的,
// 而这些静态注册的目标广播接收者可能还没有被启动起来,因此,将一个广播发送给它们处理时,先要
// 将它们启动起来。事实上,只需要将它们所运行在的应用程序进程启动起来就可以了,因为当这些应用程序
// 进程接收到广播时,就会主动将目标广播接收者启动起来。
// 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.
// 该参数是用来描述一个正在等待静态注册的目标广播接收者启动起来的广播转发任务的
if (mPendingBroadcast != null) {
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
"processNextBroadcast [" + mQueueName + "]: waiting for "
+ mPendingBroadcast.curApp);
boolean isDead;
// 检查这个静态注册的目标广播接收者所运行在的应用程序进程是否已经启动起来
synchronized (mService.mPidsSelfLocked) {
ProcessRecord proc = mService.mPidsSelfLocked.get(mPendingBroadcast.curApp.pid);
isDead = proc == null || proc.crashing;
}
// 如果这个应用程序进程没有死亡,就会继续等待
if (!isDead) {
// It's still alive, so keep waiting
return;
} else {
Slog.w(TAG, "pending app ["
+ mQueueName + "]" + mPendingBroadcast.curApp
+ " died before responding to broadcast");
mPendingBroadcast.state = BroadcastRecord.IDLE;
mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
mPendingBroadcast = null;
}
}
boolean looped = false;
// 循环在有序广播调度队列mOrderedBroadcasts(动态有序、所有静态)中找到下一个需要处理的广播转发任务
do {
// 判断有序广播调度队列中的广播转发任务是否已经处理完了
if (mOrderedBroadcasts.size() == 0) {
// No more broadcasts pending, so all done!
mService.scheduleAppGcsLocked();
if (looped) {
// If we had finished the last ordered broadcast, then
// make sure all processes have correct oom and sched
// adjustments.
mService.updateOomAdjLocked();
}
return;
}
// 取出第一个广播转发任务r
r = mOrderedBroadcasts.get(0);
/* 这里可以统计广播转发任务r中是否包含操作widget的Action:ACTION_APPWIDGET_ENABLED和
* ACTION_APPWIDGET_DISABLED的包名r.targetComp.getPackageName()和
* 类名r.targetComp.getClassName()以便于后面增加控制自启动的过滤操作*/
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.
// 获取到r所描述的广播转发任务的目标广播接收者的个数
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))) {
Slog.w(TAG, "Hung broadcast ["
+ mQueueName + "] discarded after timeout failure:"
+ " now=" + now
+ " dispatchTime=" + r.dispatchTime
+ " startTime=" + r.receiverTime
+ " intent=" + r.intent
+ " numReceivers=" + numReceivers
+ " nextReceiver=" + r.nextReceiver
+ " state=" + r.state);
// 如果目标广播接收者不能按时处理完广播,就强制结束这个广播转发任务
broadcastTimeoutLocked(false); // forcibly(强制) finish this broadcast
// 下面两个参数的设置表示要继续处理有序广播调度队列中的下一个广播转发任务
forceReceive = true;
r.state = BroadcastRecord.IDLE;
}
}
// 检查r所描述的广播转发任务是否正在处理中,即:正在将一个有序广播转发给它的前一个目标广播接收者处理
if (r.state != BroadcastRecord.IDLE) {
if (DEBUG_BROADCAST) Slog.d(TAG_BROADCAST,
"processNextBroadcast("
+ mQueueName + ") called when not idle (state="
+ r.state + ")");
// 如果正在将r所描述的广播转发给它的前一个目标接收者处理,则需要等待这个目标广播接收者处理完
// 该有序广播,然后再转发给下一个目标接收者处理。故这里直接返回
return;
}
// 检查r所描述的广播转发任务是否已经处理完成或者已经被强制结束了
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 {
if (DEBUG_BROADCAST) Slog.i(TAG_BROADCAST,
"Finishing broadcast [" + mQueueName + "] "
+ r.intent.getAction() + " app=" + r.callerApp);
// 执行广播的发送操作
performReceiveLocked(r.callerApp, r.resultTo,
new Intent(r.intent), r.resultCode,
r.resultData, r.resultExtras, false, false, r.userId);
// Set this to null so that the reference
// (local and remote) isn't kept in the mBroadcastHistory.
r.resultTo = null;
} catch (RemoteException e) {
r.resultTo = null;
Slog.w(TAG, "Failure ["
+ mQueueName + "] sending broadcast result of "
+ r.intent, e);
}
}
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Cancelling BROADCAST_TIMEOUT_MSG");
// remove掉前面给mHandler发送的BROADCAST_TIMEOUT_MSG消息,
// 表示r所描述的广播转发任务已经在规定时间内处理完了
cancelBroadcastTimeoutLocked();
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
"Finished with ordered broadcast " + r);
// ... and on to the next...
addBroadcastToHistoryLocked(r);
// 将r所描述的广播转发任务从有序广播队列中删除
mOrderedBroadcasts.remove(0);
// 这里将r设为null以便继续执行while循环来找到下一个需要处理的广播转发任务
r = null;
looped = true;
continue;
}
} while (r == null);
// 上面循环执行完后,下一个需要处理的广播转发任务就保存在r中了
// r所描述的广播转发任务的目标广播接收者保存在它的成员变量receivers列表中,
// 而下一个目标广播接收者就保存在它的成员变量nextReceiver中,这里得到的是
// r所描述的广播转发任务的下一个目标广播接收者在其目标广播接收者列表中的位置
// Get the next receiver...
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();
// 如果recIdx为0说明广播转发任务刚开始被处理
if (recIdx == 0) {
// 广播刚被处理,保存当前时间到r.dispatchTime变量中
r.dispatchTime = r.receiverTime;
r.dispatchClockTime = System.currentTimeMillis();
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing ordered broadcast ["
+ mQueueName + "] " + r);
}
// 检查是否已经向消息队列发送了BROADCAST_TIMEOUT_MSG消息
if (! mPendingBroadcastTimeoutMessage) {
long timeoutTime = r.receiverTime + mTimeoutPeriod;
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Submitting BROADCAST_TIMEOUT_MSG ["
+ mQueueName + "] for " + r + " at " + timeoutTime);
// 如果还没有发送,则向消息队列发送该消息,并且指定它在timeoutTime时间后处理
setBroadcastTimeoutLocked(timeoutTime);
}
final BroadcastOptions brOptions = r.options;
// 取出r所描述的广播转发任务的下一个目标广播接收者
final Object nextReceiver = r.receivers.get(recIdx);
// 前面说过动态注册广播接收者是BroadcastFilter类型的,这里处理动态有序广播接收者
if (nextReceiver instanceof BroadcastFilter) {
// Simple case: this is a registered receiver who gets
// a direct call.
BroadcastFilter filter = (BroadcastFilter)nextReceiver;
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Delivering ordered ["
+ mQueueName + "] to registered "
+ filter + ": " + r);
// 这里直接向动态注册的广播接收者发送广播,因为动态注册的广播接收者肯定是已经启动起来的
deliverToRegisteredReceiverLocked(r, filter, r.ordered);
// 判断r所描述的广播转发任务是否是用来转发无序广播的
if (r.receiver == null || !r.ordered) {
// The receiver has already finished, so schedule to
// process the next one.
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Quick finishing ["
+ mQueueName + "]: ordered="
+ r.ordered + " receiver=" + r.receiver);
// 如果是则将 r.state设置为IDLE,表示不需要等待它的前一个目标广播接收者处理完成一个广播,
// 就可以将该广播继续发送给它的下一个目标广播接收者处理
r.state = BroadcastRecord.IDLE;
// 为了将广播继续发送给r所描述的广播转发任务的下一个目标广播接收者处理,
// 方法中实现发送BROADCAST_INTENT_MSG消息给消息队列以便继续处理
scheduleBroadcastsLocked();
} else {
if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {
scheduleTempWhitelistLocked(filter.owningUid,
brOptions.getTemporaryAppWhitelistDuration(), r);
}
}
return;
}
// 如果r所描述的广播转发任务的下一个目标广播接收者不是BroadcastFilter类型的,那就说明这
// 是一个静态注册的广播接收者,这种情况略复杂,因为静态注册的广播接收者可能还没有被启动起来
// Hard case: need to instantiate the receiver, possibly
// starting its application process to host it.
// 前面说过,静态注册的广播接收者是ResolveInfo类型的,这里直接强转
ResolveInfo info =
(ResolveInfo)nextReceiver;
ComponentName component = new ComponentName(
info.activityInfo.applicationInfo.packageName,
info.activityInfo.name);
// 下面主要是根据是否得到权限来决定是否跳过本次广播的发送
boolean skip = false;
// 根据目标广播接收者所需要的权限检查发送者的Pid和Uid是否符合要求
int perm = mService.checkComponentPermission(info.activityInfo.permission,
r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid,
info.activityInfo.exported);
// 如果发送者不符合要求,则直接跳过本次转发
if (perm != PackageManager.PERMISSION_GRANTED) {
if (!info.activityInfo.exported) {
Slog.w(TAG, "Permission Denial: broadcasting "
+ r.intent.toString()
+ " from " + r.callerPackage + " (pid=" + r.callingPid
+ ", uid=" + r.callingUid + ")"
+ " is not exported from uid " + info.activityInfo.applicationInfo.uid
+ " due to receiver " + component.flattenToShortString());
} else {
Slog.w(TAG, "Permission Denial: broadcasting "
+ r.intent.toString()
+ " from " + r.callerPackage + " (pid=" + r.callingPid
+ ", uid=" + r.callingUid + ")"
+ " requires " + info.activityInfo.permission
+ " due to receiver " + component.flattenToShortString());
}
skip = true;
// 如果发送者符合要求,就检查发送者申请的权限是否被用户拒绝,拒绝的话也直接跳过本次转发
} else if (info.activityInfo.permission != null) {
final int opCode = AppOpsManager.permissionToOpCode(info.activityInfo.permission);
if (opCode != AppOpsManager.OP_NONE
&& mService.mAppOpsService.noteOperation(opCode, r.callingUid,
r.callerPackage) != AppOpsManager.MODE_ALLOWED) {
Slog.w(TAG, "Appop Denial: broadcasting "
+ r.intent.toString()
+ " from " + r.callerPackage + " (pid="
+ r.callingPid + ", uid=" + r.callingUid + ")"
+ " requires appop " + AppOpsManager.permissionToOp(
info.activityInfo.permission)
+ " due to registered receiver "
+ component.flattenToShortString());
skip = true;
}
}
/*可以添加关联唤醒的判断逻辑:如根据目标广播接收者的包名/类名前缀判断是否属于第三方push平台,如果是则设置skip为true*/
// 检查接收者权限
if (!skip && info.activityInfo.applicationInfo.uid != Process.SYSTEM_UID &&
r.requiredPermissions != null && r.requiredPermissions.length > 0) {
// 循环根据发送者所需的权限检查所有的目标广播接收者的Pid和Uid是否符合要求,一项不符合就直接跳过
// 符合要求,就检查接收者申请的权限是否被用户拒绝,拒绝的话也直接跳过
for (int i = 0; i < r.requiredPermissions.length; i++) {
String requiredPermission = r.requiredPermissions[i];
try {
perm = AppGlobals.getPackageManager().
checkPermission(requiredPermission,
info.activityInfo.applicationInfo.packageName,
UserHandle
.getUserId(info.activityInfo.applicationInfo.uid));
} catch (RemoteException e) {
perm = PackageManager.PERMISSION_DENIED;
}
if (perm != PackageManager.PERMISSION_GRANTED) {
Slog.w(TAG, "Permission Denial: receiving "
+ r.intent + " to "
+ component.flattenToShortString()
+ " requires " + requiredPermission
+ " due to sender " + r.callerPackage
+ " (uid " + r.callingUid + ")");
skip = true;
break;
}
int appOp = AppOpsManager.permissionToOpCode(requiredPermission);
if (appOp != AppOpsManager.OP_NONE && appOp != r.appOp
&& mService.mAppOpsService.noteOperation(appOp,
info.activityInfo.applicationInfo.uid, info.activityInfo.packageName)
!= AppOpsManager.MODE_ALLOWED) {
Slog.w(TAG, "Appop Denial: receiving "
+ r.intent + " to "
+ component.flattenToShortString()
+ " requires appop " + AppOpsManager.permissionToOp(
requiredPermission)
+ " due to sender " + r.callerPackage
+ " (uid " + r.callingUid + ")");
skip = true;
break;
}
}
}
if (!skip && r.appOp != AppOpsManager.OP_NONE
&& mService.mAppOpsService.noteOperation(r.appOp,
info.activityInfo.applicationInfo.uid, info.activityInfo.packageName)
!= AppOpsManager.MODE_ALLOWED) {
Slog.w(TAG, "Appop Denial: receiving "
+ r.intent + " to "
+ component.flattenToShortString()
+ " requires appop " + AppOpsManager.opToName(r.appOp)
+ " due to sender " + r.callerPackage
+ " (uid " + r.callingUid + ")");
skip = true;
}
if (!skip) {
skip = !mService.mIntentFirewall.checkBroadcast(r.intent, r.callingUid,
r.callingPid, r.resolvedType, info.activityInfo.applicationInfo.uid);
}
boolean isSingleton = false;
try {
isSingleton = mService.isSingleton(info.activityInfo.processName,
info.activityInfo.applicationInfo,
info.activityInfo.name, info.activityInfo.flags);
} catch (SecurityException e) {
Slog.w(TAG, e.getMessage());
skip = true;
}
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) {
Slog.w(TAG, "Permission Denial: Receiver " + component.flattenToShortString()
+ " requests FLAG_SINGLE_USER, but app does not hold "
+ android.Manifest.permission.INTERACT_ACROSS_USERS);
skip = true;
}
}
if (r.curApp != null && r.curApp.crashing) {
// If the target process is crashing, just skip it.
Slog.w(TAG, "Skipping deliver ordered [" + mQueueName + "] " + r
+ " to " + r.curApp + ": process 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) {
// all such failures mean we skip this receiver
Slog.w(TAG, "Exception getting recipient info for "
+ info.activityInfo.packageName, e);
}
if (!isAvailable) {
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Skipping delivery to " + info.activityInfo.packageName + " / "
+ info.activityInfo.applicationInfo.uid
+ " : package no longer available");
skip = true;
}
}
if (skip) {
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Skipping delivery of ordered [" + mQueueName + "] "
+ r + " for whatever reason");
r.receiver = null;
r.curFilter = null;
r.state = BroadcastRecord.IDLE;
// 如果跳过,直接继续发送给r所描述的广播转发任务的下一个目标广播接收者处理
scheduleBroadcastsLocked();
return;
}
r.state = BroadcastRecord.APP_RECEIVE;
// 得到静态注册的广播接收者的android:process属性值,即它需要运行在的应用程序进程的名字
String targetProcess = info.activityInfo.processName;
r.curComponent = component;
final int receiverUid = info.activityInfo.applicationInfo.uid;
// If it's a singleton, it needs to be the same app or a special app
if (r.callingUid != Process.SYSTEM_UID && isSingleton
&& mService.isValidSingletonCall(r.callingUid, receiverUid)) {
info.activityInfo = mService.getActivityInfoForUser(info.activityInfo, 0);
}
r.curReceiver = info.activityInfo;
if (DEBUG_MU && r.callingUid > UserHandle.PER_USER_RANGE) {
Slog.v(TAG_MU, "Updated broadcast record activity info for secondary user, "
+ info.activityInfo + ", callingUid = " + r.callingUid + ", uid = "
+ info.activityInfo.applicationInfo.uid);
}
if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {
scheduleTempWhitelistLocked(receiverUid,
brOptions.getTemporaryAppWhitelistDuration(), r);
}
// Broadcast is being executed, its package can't be stopped.
try {
AppGlobals.getPackageManager().setPackageStoppedState(
r.curComponent.getPackageName(), false, UserHandle.getUserId(r.callingUid));
} catch (RemoteException e) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
+ r.curComponent.getPackageName() + ": " + e);
}
// Is this receiver's application already running?
ProcessRecord app = mService.getProcessRecordLocked(targetProcess,
info.activityInfo.applicationInfo.uid, false);
// 判断静态注册的广播接收者所运行在的应用程序进程是否已经启动起来
if (app != null && app.thread != null) {
try {
app.addPackage(info.activityInfo.packageName,
info.activityInfo.applicationInfo.versionCode, mService.mProcessStats);
// 如果已经启动,则直接将广播发送给它处理
processCurBroadcastLocked(r, app);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when sending broadcast to "
+ r.curComponent, e);
} catch (RuntimeException e) {
Slog.wtf(TAG, "Failed sending broadcast to "
+ r.curComponent + " with " + r.intent, e);
// If some unexpected exception happened, just skip
// this broadcast. At this point we are not in the call
// from a client, so throwing an exception out from here
// will crash the entire system instead of just whoever
// sent the broadcast.
logBroadcastReceiverDiscardLocked(r);
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 a dead object exception was thrown -- fall through to
// restart the application.
}
// Not running -- get it started, to be executed when the app comes up.
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Need to start app ["
+ mQueueName + "] " + targetProcess + " for broadcast " + r);
/*因为下面要开始启动进程了,故这里可以增加禁止自启动判断:如果要启动进程的包名在黑名单中或者不是默认允许启动的,则直接执行启动失败的逻辑*/
// 调用startProcessLocked方法启动这个应用程序进程
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) {
// Ah, this recipient is unavailable. Finish it if necessary,
// and mark the broadcast record as ready for the next.
Slog.w(TAG, "Unable to launch app "
+ info.activityInfo.applicationInfo.packageName + "/"
+ info.activityInfo.applicationInfo.uid + " for broadcast "
+ r.intent + ": process is bad");
logBroadcastReceiverDiscardLocked(r);
finishReceiverLocked(r, r.resultCode, r.resultData,
r.resultExtras, r.resultAbort, false);
// 如果进程启动失败,继续发送给r所描述的广播转发任务的下一个目标广播接收者处理
scheduleBroadcastsLocked();
r.state = BroadcastRecord.IDLE;
return;
}
// 如果成功启动进程,则保存r和recIdx,表示正在等待r所描述的广播转发任务的
// 下一个目标广播接收者所在的应用程序进程启动起来
mPendingBroadcast = r;
mPendingBroadcastRecvIndex = recIdx;
}
}
假设r所描述的广播转发任务的下一个目标广播接收者是一个动态注册的广播接收者,那么执行完上面步骤后,接下来就会调用BroadcastQueue类的deliverToRegisteredReceiverLocked方法将一个广播转发给它处理:
private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
BroadcastFilter filter, boolean ordered) {
boolean skip = false;
// BroadcastQueue将一个广播转发给一个目标广播接收者之前,需要检查这个广播的发送者和接收者的权限。
// 目标广播接收者所需权限不为null
if (filter.requiredPermission != null) {
// 根据目标广播接收者所需的权限检验广播的发送者的Pid和Uid是否符合要求
int perm = mService.checkComponentPermission(filter.requiredPermission,
r.callingPid, r.callingUid, -1, true);
// 如果发送者不符合要求,则直接跳过本次转发
if (perm != PackageManager.PERMISSION_GRANTED) {
Slog.w(TAG, "Permission Denial: broadcasting "
+ r.intent.toString()
+ " from " + r.callerPackage + " (pid="
+ r.callingPid + ", uid=" + r.callingUid + ")"
+ " requires " + filter.requiredPermission
+ " due to registered receiver " + filter);
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) {
Slog.w(TAG, "Appop Denial: broadcasting "
+ r.intent.toString()
+ " from " + r.callerPackage + " (pid="
+ r.callingPid + ", uid=" + r.callingUid + ")"
+ " requires appop " + AppOpsManager.permissionToOp(
filter.requiredPermission)
+ " due to registered receiver " + filter);
skip = true;
}
}
}
// 发送者所需权限不为null
if (!skip && r.requiredPermissions != null && r.requiredPermissions.length > 0) {
// 循环根据发送者所需的权限检验所有的目标广播接收者的Pid和Uid是否符合要求,一项不符合就直接跳过
// 符合要求,就检查接收者申请的权限是否被用户拒绝,拒绝的话也直接跳过本次转发
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) {
Slog.w(TAG, "Permission Denial: receiving "
+ r.intent.toString()
+ " to " + filter.receiverList.app
+ " (pid=" + filter.receiverList.pid
+ ", uid=" + filter.receiverList.uid + ")"
+ " requires " + requiredPermission
+ " due to sender " + r.callerPackage
+ " (uid " + r.callingUid + ")");
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) {
Slog.w(TAG, "Appop Denial: receiving "
+ r.intent.toString()
+ " to " + filter.receiverList.app
+ " (pid=" + filter.receiverList.pid
+ ", uid=" + filter.receiverList.uid + ")"
+ " requires appop " + AppOpsManager.permissionToOp(
requiredPermission)
+ " due to sender " + r.callerPackage
+ " (uid " + r.callingUid + ")");
skip = true;
break;
}
}
}
// 如果发送者不需要权限,则检查目标广播接收者的Pid和Uid是否符合要求
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) {
Slog.w(TAG, "Permission Denial: security check failed when receiving "
+ r.intent.toString()
+ " to " + filter.receiverList.app
+ " (pid=" + filter.receiverList.pid
+ ", uid=" + filter.receiverList.uid + ")"
+ " due to sender " + r.callerPackage
+ " (uid " + r.callingUid + ")");
skip = true;
}
}
if (!skip && r.appOp != AppOpsManager.OP_NONE
&& mService.mAppOpsService.noteOperation(r.appOp,
filter.receiverList.uid, filter.packageName)
!= AppOpsManager.MODE_ALLOWED) {
Slog.w(TAG, "Appop Denial: receiving "
+ r.intent.toString()
+ " to " + filter.receiverList.app
+ " (pid=" + filter.receiverList.pid
+ ", uid=" + filter.receiverList.uid + ")"
+ " requires appop " + AppOpsManager.opToName(r.appOp)
+ " due to sender " + r.callerPackage
+ " (uid " + r.callingUid + ")");
skip = true;
}
if (!mService.mIntentFirewall.checkBroadcast(r.intent, r.callingUid,
r.callingPid, r.resolvedType, filter.receiverList.uid)) {
return;
}
if (filter.receiverList.app == null || filter.receiverList.app.crashing) {
Slog.w(TAG, "Skipping deliver [" + mQueueName + "] " + r
+ " to " + filter.receiverList + ": process crashing");
skip = true;
}
if (!skip) {
// 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) {
r.receiver = filter.receiverList.receiver.asBinder();
r.curFilter = filter;
filter.receiverList.curBroadcast = r;
r.state = BroadcastRecord.CALL_IN_RECEIVE;
if (filter.receiverList.app != null) {
// Bump hosting application to no longer be in background
// scheduling class. Note that we can't do that if there
// isn't an app... but we can only be in that case for
// things that directly call the IActivityManager API, which
// are already core system stuff so don't matter for this.
r.curApp = filter.receiverList.app;
filter.receiverList.app.curReceiver = r;
mService.updateOomAdjLocked(r.curApp);
}
}
try {
if (DEBUG_BROADCAST_LIGHT) Slog.i(TAG_BROADCAST,
"Delivering to " + filter + " : " + r);
// 将r所描述的广播转发给filter所描述的目标广播接收者处理
performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
new Intent(r.intent), r.resultCode, r.resultData,
r.resultExtras, r.ordered, r.initialSticky, r.userId);
if (ordered) {
r.state = BroadcastRecord.CALL_DONE_RECEIVE;
}
} catch (RemoteException e) {
Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
if (ordered) {
r.receiver = null;
r.curFilter = null;
filter.receiverList.curBroadcast = null;
if (filter.receiverList.app != null) {
filter.receiverList.app.curReceiver = null;
}
}
}
}
}
private static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Intent intent, int resultCode, String data, Bundle extras,
boolean ordered, boolean sticky, int sendingUser) throws RemoteException {
// 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.
// 调用运行在该应用程序进程中的一个ApplicationThread对象的Binder代理对象的
// scheduleRegisteredReceiver方法来向它发送这个广播
app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
data, extras, ordered, sticky, sendingUser, app.repProcState);
} else {
// Application has died. Receiver doesn't exist.
throw new RemoteException("app.thread must not be null");
}
} else {
// 否者直接调用与它关联的一个IIntentReceiver对象的Binder代理对象的performReceive方法
// 来向它发送这个广播
receiver.performReceive(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
}
}
上面performReceiveLocked方法中的参数app指向一个ProcessRecord对象,用来描述目标广播接收者所运行在的应用程序进程;参数receiver指向了一个实现了IIntentReceiver接口的Binder代理对象,用来描述目标广播接收者;参数intent用来描述即将要发送给目标广播接收者的一个广播。
下面看ActivityThread的内部类ApplicationThread的scheduleRegisteredReceiver方法:
// This function exists to make sure all receiver dispatching is
// correctly ordered, since these are one-way calls and the binder driver
// applies transaction ordering per object for such calls.
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);
}
参数receiver指向了一个IIntentReceiver对象,前面讲过每一个IIntentReceiver对象在内部都封装了一个广播接收者,并且代替它所封装的广播接收者注册到AMS中。这样当AMS将一个广播发送给一个目标广播接收者时,实际上是将这个广播发送给了与目标广播接收者相关联的一个IIntentReceiver对象,而这个IIntentReceiver对象是通过它的performReceive方法来接收这个广播的。
来看LoadedApk类中的内部类ReceiverDispatcher中的performReceive方法:
static final class ReceiverDispatcher {
final static class InnerReceiver extends IIntentReceiver.Stub {
final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
final LoadedApk.ReceiverDispatcher mStrongRef;
InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
mStrongRef = strong ? rd : null;
}
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
LoadedApk.ReceiverDispatcher rd = mDispatcher.get();
if (ActivityThread.DEBUG_BROADCAST) {
int seq = intent.getIntExtra("seq", -1);
Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction() + " seq=" + seq
+ " to " + (rd != null ? rd.mReceiver : null));
}
if (rd != null) {
// 调用ReceiverDispatcher的performReceive方法来接收intent所描述的广播
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.
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing broadcast to unregistered receiver");
IActivityManager mgr = ActivityManagerNative.getDefault();
try {
if (extras != null) {
extras.setAllowFds(false);
}
mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
} catch (RemoteException e) {
Slog.w(ActivityThread.TAG, "Couldn't finish broadcast to unregistered receiver");
}
}
}
}
final IIntentReceiver.Stub mIIntentReceiver;
// 目标广播接收者
final BroadcastReceiver mReceiver;
final Context mContext;
final Handler mActivityThread;
final Instrumentation mInstrumentation;
// 目标广播接收者是否已经注册到AMS中
final boolean mRegistered;
final IntentReceiverLeaked mLocation;
RuntimeException mUnregisterLocation;
boolean mForgotten;
final class Args extends BroadcastReceiver.PendingResult implements Runnable {
private Intent mCurIntent;
private final boolean mOrdered;
public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras,
boolean ordered, boolean sticky, int sendingUser) {
super(resultCode, resultData, resultExtras,
mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, ordered,
sticky, mIIntentReceiver.asBinder(), sendingUser, intent.getFlags());
// 要接收的广播
mCurIntent = intent;
// 描述该广播是否是有序广播
mOrdered = ordered;
}
public void run() {
// 目标广播接收者
final BroadcastReceiver receiver = mReceiver;
final boolean ordered = mOrdered;
if (ActivityThread.DEBUG_BROADCAST) {
int seq = mCurIntent.getIntExtra("seq", -1);
Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction()
+ " seq=" + seq + " to " + mReceiver);
Slog.i(ActivityThread.TAG, " mRegistered=" + mRegistered
+ " mOrderedHint=" + ordered);
}
final IActivityManager mgr = ActivityManagerNative.getDefault();
final Intent intent = mCurIntent;
mCurIntent = null;
if (receiver == null || mForgotten) {
if (mRegistered && ordered) {
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing null broadcast to " + mReceiver);
sendFinished(mgr);
}
return;
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");
try {
ClassLoader cl = mReceiver.getClass().getClassLoader();
intent.setExtrasClassLoader(cl);
setExtrasClassLoader(cl);
receiver.setPendingResult(this);
// 回调目标广播接收者的onReceive方法来接收这个广播
receiver.onReceive(mContext, intent);
} catch (Exception e) {
if (mRegistered && ordered) {
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing failed broadcast to " + mReceiver);
sendFinished(mgr);
}
if (mInstrumentation == null ||
!mInstrumentation.onException(mReceiver, e)) {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
throw new RuntimeException(
"Error receiving broadcast " + intent
+ " in " + mReceiver, e);
}
}
if (receiver.getPendingResult() != null) {
finish();
}
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}
ReceiverDispatcher(BroadcastReceiver receiver, Context context,
Handler activityThread, Instrumentation instrumentation,
boolean registered) {
if (activityThread == null) {
throw new NullPointerException("Handler must not be null");
}
mIIntentReceiver = new InnerReceiver(this, !registered);
mReceiver = receiver;
mContext = context;
mActivityThread = activityThread;
mInstrumentation = instrumentation;
mRegistered = registered;
mLocation = new IntentReceiverLeaked(null);
mLocation.fillInStackTrace();
}
. . .
RuntimeException getUnregisterLocation() {
return mUnregisterLocation;
}
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
if (ActivityThread.DEBUG_BROADCAST) {
int seq = intent.getIntExtra("seq", -1);
Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction() + " seq=" + seq
+ " to " + mReceiver);
}
// 将参数intent所描述的广播封装成一个Args对象
Args args = new Args(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
// 将Args对象封装成一个消息发送到目标广播接收者所运行在的应用程序进程的消息队列中,
// 这个消息最终在Args类的run方法中处理
if (!mActivityThread.post(args)) {
if (mRegistered && ordered) {
IActivityManager mgr = ActivityManagerNative.getDefault();
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing sync broadcast to " + mReceiver);
// 由于这里已经把广播发给接收者处理了,故现在通知AMS继续给下一个目标广播接收者发送广播了
args.sendFinished(mgr);
}
}
}
}
说到这里,我们分析了动态注册的广播接收者处理有序广播和无序广播的过程,下面说下静态广播的处理过程,看BroadcastQueue类中的processCurBroadcastLocked方法:
private final void processCurBroadcastLocked(BroadcastRecord r,
ProcessRecord app) throws RemoteException {
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Process cur broadcast " + r + " for app " + app);
// 如果目标广播接收者所运行在的应用程序进程没有启动起来,则抛异常
if (app.thread == null) {
throw new RemoteException();
}
r.receiver = app.thread.asBinder();
r.curApp = app;
app.curReceiver = r;
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
mService.updateLruProcessLocked(app, false, null);
mService.updateOomAdjLocked();
// Tell the application to launch this receiver.
r.intent.setComponent(r.curComponent);
boolean started = false;
try {
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
"Delivering to component " + r.curComponent
+ ": " + r);
mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
// 调用运行在该应用程序进程中的一个ApplicationThread对象的Binder代理对象的
// scheduleReceiver方法来向它发送这个广播
app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
mService.compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
r.resultCode, r.resultData, r.resultExtras, r.ordered, r.userId,
app.repProcState);
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Process cur broadcast " + r + " DELIVERED for app " + app);
started = true;
} finally {
if (!started) {
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Process cur broadcast " + r + ": NOT STARTED!");
r.receiver = null;
r.curApp = null;
app.curReceiver = null;
}
}
}
下面看ActivityThread的内部类ApplicationThread的scheduleReceiver方法:
public final void scheduleReceiver(Intent intent, ActivityInfo info,
CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,
boolean sync, int sendingUser, int processState) {
updateProcessState(processState, false);
// 将参数封装成一个ReceiverData对象,通过sendMessage方法向应用程序主线程消息队列中发送一个RECEIVER消息
ReceiverData r = new ReceiverData(intent, resultCode, data, extras,
sync, false, mAppThread.asBinder(), sendingUser);
r.info = info;
r.compatInfo = compatInfo;
sendMessage(H.RECEIVER, r);
}
private class H extends Handler {
. . .
public static final int RECEIVER = 113;
public void handleMessage(Message msg) {
switch (msg.what) {
. . .
case RECEIVER:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveComp");
handleReceiver((ReceiverData)msg.obj);
maybeSnapshot();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
}
}
}
private void handleReceiver(ReceiverData data) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
// 目标广播接收者类名
String component = data.intent.getComponent().getClassName();
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
IActivityManager mgr = ActivityManagerNative.getDefault();
BroadcastReceiver receiver;
try {
java.lang.ClassLoader cl = packageInfo.getClassLoader();
data.intent.setExtrasClassLoader(cl);
data.intent.prepareToEnterProcess();
data.setExtrasClassLoader(cl);
// 根据目标广播接收者类名实例化一个接收对象
receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();
} catch (Exception e) {
if (DEBUG_BROADCAST) Slog.i(TAG,
"Finishing failed broadcast to " + data.intent.getComponent());
data.sendFinished(mgr);
throw new RuntimeException(
"Unable to instantiate receiver " + component
+ ": " + e.toString(), e);
}
try {
Application app = packageInfo.makeApplication(false, mInstrumentation);
if (localLOGV) Slog.v(
TAG, "Performing receive of " + data.intent
+ ": app=" + app
+ ", appName=" + app.getPackageName()
+ ", pkg=" + packageInfo.getPackageName()
+ ", comp=" + data.intent.getComponent().toShortString()
+ ", dir=" + packageInfo.getAppDir());
ContextImpl context = (ContextImpl)app.getBaseContext();
sCurrentBroadcastIntent.set(data.intent);
receiver.setPendingResult(data);
// 回调目标广播接收者的onReceive方法来接收这个广播
receiver.onReceive(context.getReceiverRestrictedContext(),
data.intent);
} catch (Exception e) {
if (DEBUG_BROADCAST) Slog.i(TAG,
"Finishing failed broadcast to " + data.intent.getComponent());
data.sendFinished(mgr);
if (!mInstrumentation.onException(receiver, e)) {
throw new RuntimeException(
"Unable to start receiver " + component
+ ": " + e.toString(), e);
}
} finally {
sCurrentBroadcastIntent.set(null);
}
if (receiver.getPendingResult() != null) {
// 处理完本次接收后通知AMS继续给下一个目标广播接收者发送广播
data.finish();
}
}
到这里,广播的发送流程就终于分析完了。
内容有理解错误或偏差之处请包涵指正,谢谢!