Android AOSP 6.0.1 sendBroadcast发送广播流程分析
上一节中分析了广播注册流程,那么 sendBroadcast 又经过了那些步骤?
在 DemoService 的 onStartCommand 调用 sendBroadcast,发送之前携带了一个 String 类型的字符串。
package com.demo.framework
import android.app.Service
import android.content.Intent
import android.os.IBinder
import android.util.Log
class DemoService : Service() {
companion object {
const val TAG = "DemoService"
}
override fun onBind(intent: Intent): IBinder? {
Log.d(TAG, "onBind")
return null
}
override fun onCreate() {
Log.d(TAG, "onCreate")
super.onCreate()
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.d(TAG, "onStartCommand flags=$flags,startId=$startId")
val intent = Intent(MainActivity.ACTION)
intent.putExtra(MainActivity.VALUE_KEY, "DemoService Hello!")
sendBroadcast(intent)
return super.onStartCommand(intent, flags, startId)
}
override fun onDestroy() {
Log.d(TAG, "onDestroy")
super.onDestroy()
}
}
sendBroadcast 方法来自 ContextWrapper 类,最终调用了 ContextImpl 类中的 sendBroadcast 方法。
frameworks/base/core/java/android/content/ContextWrapper.java
public class ContextWrapper extends Context {
......
@Override
public void sendBroadcast(Intent intent) {
mBase.sendBroadcast(intent);
}
......
}
ContextImpl 类 sendBroadcast 方法中拿到 ActivityManagerProxy 对象,然后调用其 broadcastIntent 方法。mMainThread.getApplicationThread() 返回 ApplicationThread 对象。
frameworks/base/core/java/android/app/ContextImpl.java
class ContextImpl extends Context {
......
@Override
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);
}
}
......
}
ActivityManagerProxy 的 broadcastIntent 方法最终是调用其内部的一个 Binder 代理对象 mRemote 向 ActivityManagerService 发送一个类型为 BROADCAST_INTENT_TRANSACTION 的进程间通信请求。
frameworks/base/core/java/android/app/ActivityManagerNative.java
class ActivityManagerProxy implements IActivityManager
{
......
public int broadcastIntent(IApplicationThread caller,
Intent intent, String resolvedType, IIntentReceiver resultTo,
int resultCode, String resultData, Bundle map,
String[] requiredPermissions, int appOp, Bundle options, boolean serialized,
boolean sticky, int userId) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
intent.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeStrongBinder(resultTo != null ? resultTo.asBinder() : null);
data.writeInt(resultCode);
data.writeString(resultData);
data.writeBundle(map);
data.writeStringArray(requiredPermissions);
data.writeInt(appOp);
data.writeBundle(options);
data.writeInt(serialized ? 1 : 0);
data.writeInt(sticky ? 1 : 0);
data.writeInt(userId);
mRemote.transact(BROADCAST_INTENT_TRANSACTION, data, reply, 0);
reply.readException();
int res = reply.readInt();
reply.recycle();
data.recycle();
return res;
}
......
}
此函数接着调用 broadcastIntentLocked 方法。
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
......
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 方法。
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
......
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);
// 默认情况下,广播不会转到已停止的应用程序
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
// 如果还没有完成启动,不能允许启动新的进程
if (!mProcessesReady && (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) {
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
}
userId = handleIncomingUser(callingPid, callingUid, userId,
true, ALLOW_NON_FULL, "broadcast", callerPackage);
// 确保正在接收此广播的用户正在运行。 如果没有,我们将跳过它。
if (userId != UserHandle.USER_ALL && !isUserRunningLocked(userId, false)) {
if ((callingUid != Process.SYSTEM_UID
|| (intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0)
&& !Intent.ACTION_SHUTDOWN.equals(intent.getAction())) {
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) {
// 检查是否允许调用者这样做。注意,我们正在检查实际的真实调用者,因为实际上是谁提供了参数。
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);
}
}
}
/*
* 防止非系统代码(此处定义为非持久性进程)发送受保护的广播。
*/
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) {
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())) {
// 兼容性的特殊情况:我们不希望应用程序发送这个,
// 但从历史上看,它没有受到保护,因此,与其让它受保护,不如从调用者做限制。
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);
} else if (intent.getComponent() != null) {
// 它们足够好,可以发送到显式组件...验证它是否已发送到调用应用程序。
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 {
// 限制广播到自己的包中。
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) {
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:
// 处理特殊意图:如果此广播是从程序包管理器发出的有关删除程序包的信息,
// 则我们需要从历史记录栈中删除其所有 Activity。
// 权限不满足,抛出 SecurityException 异常
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;
case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
// 如果资源不可用,则强制停止所有这些包并刷新属性缓存。
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");
}
mRecentTasks.cleanupLocked(UserHandle.USER_ALL);
sendPackageBroadcastLocked(
IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list,
userId);
}
break;
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);
// 删除给此包授予的所有权限
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:
// 添加软件包的特殊情况:默认情况下,打开兼容模式。
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:
// 如果这是更改时区的操作,请排队一条消息,以重置当前所有正在运行的进程的时区。 该消息将在广播发生之前排队。
mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
break;
case Intent.ACTION_TIME_CHANGED:
// 如果用户设置了时间,则让所有正在运行的进程知道。
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;
}
}
// 如果需要,添加到粘性列表。
if (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");
}
// 我们在这里直接使用 userId,因为“all”目标被维护为一组单独的粘性广播。
if (userId != UserHandle.USER_ALL) {
// 但是首先,如果这不是对所有用户的广播,那么要确保它与现有的对所有用户的广播不冲突
ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(
UserHandle.USER_ALL);
if (stickies != null) {
ArrayList<Intent> list = stickies.get(intent.getAction());
if (list != null) {
int N = list.size();
int i;
for (i=0; i<N; i++) {
if (intent.filterEquals(list.get(i))) {
throw new IllegalArgumentException(
"Sticky broadcast " + intent + " for user "
+ userId + " conflicts with existing global broadcast");
}
}
}
}
}
ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);
if (stickies == null) {
stickies = new ArrayMap<>();
mStickyBroadcasts.put(userId, stickies);
}
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;
for (i = 0; i < stickiesCount; i++) {
if (intent.filterEquals(list.get(i))) {
// 这个粘性已经存在,替换它。
list.set(i, new Intent(intent));
break;
}
}
if (i >= stickiesCount) {
list.add(new Intent(intent));
}
}
int[] users;
if (userId == UserHandle.USER_ALL) {
// 调用者希望广播到所有已启动的用户。
users = mStartedUserArray;
} else {
// 调用者希望广播到一个特定的用户。
users = new int[] {userId};
}
// 找出谁都将收到此广播。
List receivers = null;
List<BroadcastFilter> registeredReceivers = null;
// 需要解决的意图感兴趣接收者…
if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
== 0) {
receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
}
if (intent.getComponent() == null) {
if (userId == UserHandle.USER_ALL && callingUid == Process.SHELL_UID) {
// 一次查询一个目标用户,不包括受 shell 限制的用户
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 {
registeredReceivers = mReceiverResolver.queryIntent(intent,
resolvedType, false, userId);
}
}
// 这个flag 将会将之前的 Intent 替代掉。
// 加了这个 flag,在发送一系列的这样的 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;
if (!ordered && NR > 0) {
// 如果我们不序列化这个广播,那么将它向注册的接收者单独发送,这样就不会等待组件被启动。
// 获取广播队列,我们保留两个广播队列和相关的簿记,一个队列处于前台优先级,一个队列用于正常(背景优先级)广播。
final BroadcastQueue queue = broadcastQueueForIntent(intent);
// 构建 BroadcastRecord 对象,其内部记录了广播的很多信息
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
callerPackage, callingPid, callingUid, resolvedType, requiredPermissions,
appOp, brOptions, registeredReceivers, resultTo, resultCode, resultData,
resultExtras, ordered, sticky, false, userId);
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing parallel broadcast " + r);
// replaceParallelBroadcastLocked 函数检查 queue 中是否包含具有相同意图的 BroadcastRecord,这里 replaced 为 false
final boolean replaced = replacePending && queue.replaceParallelBroadcastLocked(r);
if (!replaced) {
queue.enqueueParallelBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
}
registeredReceivers = null;
NR = 0;
}
// 合并到一个列表中。
int ir = 0;
if (receivers != null) {
// PACKAGE_ADDED 的特殊情况:不允许添加的包看到此广播。
// 这可以防止它们将此作为后门,以便在安装后立即运行。
// 也许将来我们想要为应用程序提供一个特殊的安装广播或类似的东西,但是我们想要慎重地做出这个决定。
String skipPackages[] = null;
if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
|| Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
|| Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
Uri data = intent.getData();
if (data != null) {
String pkgName = data.getSchemeSpecificPart();
if (pkgName != null) {
skipPackages = new String[] { pkgName };
}
}
} else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
}
if (skipPackages != null && (skipPackages.length > 0)) {
for (String skipPackage : skipPackages) {
if (skipPackage != null) {
int NT = receivers.size();
for (int it=0; it<NT; it++) {
ResolveInfo curt = (ResolveInfo)receivers.get(it);
if (curt.activityInfo.packageName.equals(skipPackage)) {
receivers.remove(it);
it--;
NT--;
}
}
}
}
}
int NT = receivers != null ? receivers.size() : 0;
int it = 0;
ResolveInfo curt = null;
BroadcastFilter curr = null;
while (it < NT && ir < NR) {
if (curt == null) {
curt = (ResolveInfo)receivers.get(it);
}
if (curr == null) {
curr = registeredReceivers.get(ir);
}
if (curr.getPriority() >= curt.priority) {
// 将此广播记录插入最终列表。
receivers.add(it, curr);
ir++;
curr = null;
it++;
NT++;
} else {
// 跳到最终列表中的下一个 ResolveInfo。
it++;
curt = null;
}
}
}
while (ir < NR) {
if (receivers == null) {
receivers = new ArrayList();
}
receivers.add(registeredReceivers.get(ir));
ir++;
}
// 处理静态广播接收者
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);
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing ordered broadcast " + r
+ ": prev had " + queue.mOrderedBroadcasts.size());
if (DEBUG_BROADCAST) Slog.i(TAG_BROADCAST,
"Enqueueing broadcast " + r.intent.getAction());
boolean replaced = replacePending && queue.replaceOrderedBroadcastLocked(r);
if (!replaced) {
queue.enqueueOrderedBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
}
}
return ActivityManager.BROADCAST_SUCCESS;
}
......
}
- receivers 是对这个广播感兴趣的静态 BroadcastReceiver 列表;collectReceiverComponents 通过 PackageManager 获取了与这个广播匹配的静态 BroadcastReceiver 信息;
- mReceiverResolver 存储了动态注册的 BroadcastReceiver 的信息。
由于在我们的代码中,使用动态注册的方式,所以 receivers 为 null,接下来调用了下面两个函数:
queue.enqueueParallelBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
第一个函数是将 BroadcastRecord 入队;第二个函数调度发送广播。queue 是一个 BroadcastQueue 类型对象,我们保留两个广播队列和相关的簿记,一个用于前台优先级,另一个用于普通的(后台优先级)广播。
frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java
public final class BroadcastQueue {
......
public void enqueueParallelBroadcastLocked(BroadcastRecord r) {
mParallelBroadcasts.add(r);
r.enqueueClockTime = System.currentTimeMillis();
}
......
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;
}
.....
}
enqueueParallelBroadcastLocked 函数非常简单,只是将 BroadcastRecord 对象 r 添加到 mParallelBroadcasts,mParallelBroadcasts 代表将立即执行的所有活动广播的列表(无需等待另一个广播完成)。目前,它只包含对已注册的接收者的广播,后台优先级广播和前台优先级广播分别排队。
scheduleBroadcastsLocked 只是通过 mHandler 发送了一个 BROADCAST_INTENT_MSG 类型的消息。mBroadcastsScheduled 标志代表我们当前有一个 BROADCAST_INTENT_MSG 消息在处理。
frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java
public final class BroadcastQueue {
......
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;
......
}
}
};
.....
}
BROADCAST_INTENT_MSG 类型消息最后会在 BroadcastHandler 类中 handleMessage 方法处理,下一步调用 processNextBroadcast 方法。
frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java
public final class BroadcastQueue {
......
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 为 true,这里把 mBroadcastsScheduled 置为了 false,以便 scheduleBroadcastsLocked 方法中不再 return,可以继续下一步
if (fromMsg) {
mBroadcastsScheduled = false;
}
// 首先,立即传送任何非序列化广播。
while (mParallelBroadcasts.size() > 0) {
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);
}
addBroadcastToHistoryLocked(r);
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["
+ mQueueName + "] " + r);
}
......
}
}
.....
}
r.receivers 是一个 List 对象,对其中的每个 BroadcastFilter 对象都执行 deliverToRegisteredReceiverLocked 方法。
frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java
public final class BroadcastQueue {
......
private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
BroadcastFilter filter, boolean ordered) {
boolean skip = false;
......
if (!skip) {
// 如果这不是作为一个有序广播发送的,那么我们就不希望触及跟踪有序广播当前状态的字段。
if (ordered) {
......
}
try {
if (DEBUG_BROADCAST_LIGHT) Slog.i(TAG_BROADCAST,
"Delivering to " + filter + " : " + r);
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);
......
}
}
}
......
}
下一步进入 performReceiveLocked 方法。
frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java
public final class BroadcastQueue {
......
private static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Intent intent, int resultCode, String data, Bundle extras,
boolean ordered, boolean sticky, int sendingUser) throws RemoteException {
// 使用 one-way binder 调用将意图异步发送给接收者。
if (app != null) {
if (app.thread != null) {
// 如果我们有一个应用程序线程,通过它来执行调用,以便它与其他 one-way 调用一起被正确排序。
app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
data, extras, ordered, sticky, sendingUser, app.repProcState);
} else {
// 应用程序已经死亡。接收方不存在。
throw new RemoteException("app.thread must not be null");
}
} else {
receiver.performReceive(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
}
}
......
}
app.thread 最终指向的是一个 ApplicationThreadProxy 对象,然后调用其 scheduleRegisteredReceiver 方法。
frameworks/base/core/java/android/app/ApplicationThreadNative.java
class ApplicationThreadProxy implements IApplicationThread {
......
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
int resultCode, String dataStr, Bundle extras, boolean ordered,
boolean sticky, int sendingUser, int processState) throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeStrongBinder(receiver.asBinder());
intent.writeToParcel(data, 0);
data.writeInt(resultCode);
data.writeString(dataStr);
data.writeBundle(extras);
data.writeInt(ordered ? 1 : 0);
data.writeInt(sticky ? 1 : 0);
data.writeInt(sendingUser);
data.writeInt(processState);
mRemote.transact(SCHEDULE_REGISTERED_RECEIVER_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
}
......
}
ApplicationThreadProxy 中的 scheduleRegisteredReceiver 方法,最终远程调用 ApplicationThread 中的 scheduleRegisteredReceiver 方法。
frameworks/base/core/java/android/app/ActivityThread.java
private class ApplicationThread extends ApplicationThreadNative {
......
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);
}
......
}
先来研究一下 IIntentReceiver 接口,它在 AIDL 文件中定义,我们都知道 AIDL 是用来跨进程通信的。
frameworks/base/core/java/android/content/IIntentReceiver.aidl
package android.content;
import android.content.Intent;
import android.os.Bundle;
/**
* 用于发送 Intent 广播的系统私有 API。这是作为注册 Intent 广播的一部分提供给 activity 管理器的,并在它接收到 Intent 时调用。
*
* {@hide}
*/
oneway interface IIntentReceiver {
void performReceive(in Intent intent, int resultCode, String data,
in Bundle extras, boolean ordered, boolean sticky, int sendingUser);
}
以下是编译此 AIDL 后的 java 代码,需要重点研究一下 asInterface 方法中调用的 queryLocalInterface 方法,它的作用是尝试为此 Binder 对象检索接口的本地实现。 如果返回 null,则需要实例化代理类以通过 transact() 方法远程调用。
package android.content;
public interface IIntentReceiver extends android.os.IInterface {
public void performReceive(android.content.Intent intent, int resultCode, java.lang.String data, android.os.Bundle extras, boolean ordered, boolean sticky, int sendingUser) throws android.os.RemoteException;
/**
* 本地端 IPC 实现存根类。
*/
public static abstract class Stub extends android.os.Binder implements android.content.IIntentReceiver {
static final int TRANSACTION_performReceive = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
private static final java.lang.String DESCRIPTOR = "android.content.IIntentReceiver";
/**
* 构造 Stub 对象,并将其附加到接口
*/
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* 将 IBinder 对象强制转换为 android.content.IIntentReceiver 接口,在需要时生成代理。
*/
public static android.content.IIntentReceiver asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof android.content.IIntentReceiver))) {
return ((android.content.IIntentReceiver) iin);
}
return new android.content.IIntentReceiver.Stub.Proxy(obj);
}
@Override
public android.os.IBinder asBinder() {
return this;
}
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
java.lang.String descriptor = DESCRIPTOR;
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(descriptor);
return true;
}
case TRANSACTION_performReceive: {
data.enforceInterface(descriptor);
android.content.Intent _arg0;
if ((0 != data.readInt())) {
_arg0 = android.content.Intent.CREATOR.createFromParcel(data);
} else {
_arg0 = null;
}
int _arg1;
_arg1 = data.readInt();
java.lang.String _arg2;
_arg2 = data.readString();
android.os.Bundle _arg3;
if ((0 != data.readInt())) {
_arg3 = android.os.Bundle.CREATOR.createFromParcel(data);
} else {
_arg3 = null;
}
boolean _arg4;
_arg4 = (0 != data.readInt());
boolean _arg5;
_arg5 = (0 != data.readInt());
int _arg6;
_arg6 = data.readInt();
this.performReceive(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6);
return true;
}
default: {
return super.onTransact(code, data, reply, flags);
}
}
}
private static class Proxy implements android.content.IIntentReceiver {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
@Override
public android.os.IBinder asBinder() {
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
@Override
public void performReceive(android.content.Intent intent, int resultCode, java.lang.String data, android.os.Bundle extras, boolean ordered, boolean sticky, int sendingUser) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((intent != null)) {
_data.writeInt(1);
intent.writeToParcel(_data, 0);
} else {
_data.writeInt(0);
}
_data.writeInt(resultCode);
_data.writeString(data);
if ((extras != null)) {
_data.writeInt(1);
extras.writeToParcel(_data, 0);
} else {
_data.writeInt(0);
}
_data.writeInt(((ordered) ? (1) : (0)));
_data.writeInt(((sticky) ? (1) : (0)));
_data.writeInt(sendingUser);
mRemote.transact(Stub.TRANSACTION_performReceive, _data, null, android.os.IBinder.FLAG_ONEWAY);
} finally {
_data.recycle();
}
}
}
}
}
那么调用实现 IIntentReceiver 接口对象的 performReceive 方法,实际上是一个继承自 IIntentReceiver.Stub 抽象类。我们在动态注册广播一节已经知道,我们注册的时候实际上获取的是一个 InnerReceiver 对象,它继承自 IIntentReceiver.Stub。所以最后一定执行的是其 performReceive 方法。
frameworks/base/core/java/android/app/LoadedApk.java
public final class LoadedApk {
......
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) {
rd.performReceive(intent, resultCode, data, extras,
ordered, sticky, sendingUser);
} else {
// activity 管理器在此过程中将广播分发到已注册的接收者,但是在发送广播之前,接收者尚未注册。
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");
}
}
}
}
......
}
......
}
在 InnerReceiver performReceive 方法中,先从弱引用中获取 LoadedApk.ReceiverDispatcher 对象,然后调用其 performReceive 方法。
frameworks/base/core/java/android/app/LoadedApk.java
public final class LoadedApk {
......
static final class ReceiverDispatcher {
......
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);
}
Args args = new Args(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
if (!mActivityThread.post(args)) {
if (mRegistered && ordered) {
IActivityManager mgr = ActivityManagerNative.getDefault();
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing sync broadcast to " + mReceiver);
args.sendFinished(mgr);
}
}
}
}
......
}
首先创建一个 Args 对象,然后使用 Handler post 此对象,它实现了 run 方法,接着就会执行它的 run 方法。由于我们发送的是一个普通广播,因此是非顺序的,ordered = false,内部 if 分支不再进入。
frameworks/base/core/java/android/app/LoadedApk.java
public final class LoadedApk {
......
static final class ReceiverDispatcher {
......
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 Intent intent = mCurIntent;
mCurIntent = null;
......
try {
ClassLoader cl = mReceiver.getClass().getClassLoader();
intent.setExtrasClassLoader(cl);
setExtrasClassLoader(cl);
receiver.setPendingResult(this);
receiver.onReceive(mContext, intent);
} catch (Exception e) {
......
}
......
}
}
......
}
......
}
run 方法中的 BroadcastReceiver 对象是我们注册的时候传入的,最后就会执行我们自定义的 Receiver(MainActivityBroadcastReceiver)中的 onReceive 方法。
接下来打印 Log 跟踪一下以上调用过程。
07-16 05:23:41.244 2323-2323/com.demo.framework D/lhw: ContextWrapper sendBroadcast intent=Intent { act=com.demo.framework.ACTION (has extras) }
07-16 05:23:41.244 2323-2323/com.demo.framework D/lhw: ContextImpl sendBroadcast intent=Intent { act=com.demo.framework.ACTION (has extras) }
07-16 05:23:41.245 2323-2323/com.demo.framework V/lhw: ActivityManagerProxy broadcastIntent aaa@qq.com,intent=Intent { act=com.demo.framework.ACTION (has extras) },resolvedType=null,resultTo=null,resultCode=-1,resultData=null,map=null,appOp=-1,options=null,serialized=false,sticky=false,userId=0
07-16 05:23:41.245 770-1644/system_process V/lhw: ActivityManagerService broadcastIntent aaa@qq.com,intent=Intent { act=com.demo.framework.ACTION (has extras) },resolvedType=null,resultTo=null,resultCode=-1,resultData=null,resultExtras=null,appOp=-1,options=null,serialized=false,sticky=false,userId=0
07-16 05:23:41.245 770-1644/system_process V/lhw: ActivityManagerService broadcastIntentLocked callerApp=ProcessRecord{a649f5e 2323:com.demo.framework/u0a124},callerPackage=com.demo.framework,intent=Intent { act=com.demo.framework.ACTION (has extras) },resolvedType=null,resultTo=null,resultCode=-1,resultData=null,resultExtras=null,appOp=-1,options=null,ordered=false,sticky=false,callingPid=2323,callingUid=10124,userId=0
07-16 05:23:41.245 770-1644/system_process V/lhw: ActivityManagerService broadcastIntentLocked replaced=false
07-16 05:23:41.245 770-1644/system_process V/lhw: BroadcastQueue enqueueParallelBroadcastLocked r=BroadcastRecord{61aaf3f u0 com.demo.framework.ACTION}
07-16 05:23:41.245 770-1644/system_process V/lhw: BroadcastQueue scheduleBroadcastsLocked
07-16 05:23:41.245 770-803/system_process V/lhw: BroadcastHandler handleMessage BROADCAST_INTENT_MSG
07-16 05:23:41.245 770-803/system_process V/lhw: BroadcastQueue processNextBroadcast fromMsg=true
07-16 05:23:41.245 770-803/system_process V/lhw: BroadcastQueue deliverToRegisteredReceiverLocked r=BroadcastRecord{61aaf3f u0 com.demo.framework.ACTION},filter=BroadcastFilter{5c0e7dc u0 ReceiverList{c66144f 2323 com.demo.framework/10124/u0 remote:4792eae}},ordered=false
07-16 05:23:41.245 770-803/system_process V/lhw: BroadcastQueue performReceiveLocked app=ProcessRecord{a649f5e 2323:com.demo.framework/u0a124},aaa@qq.com,intent=Intent { act=com.demo.framework.ACTION flg=0x10 (has extras) },resultCode=-1,data=null,extras=null,ordered=false,sticky=false,sendingUser=0
07-16 05:23:41.245 770-803/system_process V/lhw: ApplicationThreadProxy scheduleRegisteredReceiver aaa@qq.com,intent=Intent { act=com.demo.framework.ACTION flg=0x10 (has extras) },resultCode=-1,dataStr=null,extras=null,ordered=false,sticky=false,sendingUser=0,processState=2
07-16 05:23:41.245 2323-2341/com.demo.framework V/lhw: ApplicationThread scheduleRegisteredReceiver aaa@qq.com9e5a36a,intent=Intent { act=com.demo.framework.ACTION flg=0x10 (has extras) },resultCode=-1,dataStr=null,extras=null,ordered=false,sticky=false,sendingUser=0,processState=2
07-16 05:23:41.246 2323-2341/com.demo.framework V/lhw: InnerReceiver performReceive intent=Intent { act=com.demo.framework.ACTION flg=0x10 (has extras) },resultCode=-1,datanull,extras=null,ordered=false,sticky=false,sendingUser=0
07-16 05:23:41.246 2323-2341/com.demo.framework V/lhw: ReceiverDispatcher performReceive intent=Intent { act=com.demo.framework.ACTION flg=0x10 (has extras) },resultCode=-1,datanull,extras=null,ordered=false,sticky=false,sendingUser=0
07-16 05:23:41.248 2323-2323/com.demo.framework V/lhw: Args run ordered=false,aaa@qq.com,intent=Intent { act=com.demo.framework.ACTION flg=0x10 (has extras) }
07-16 05:23:41.252 2323-2323/com.demo.framework D/MainActivity: MainActivityBroadcastReceiver onReceive str=DemoService Hello!
最后画一张时序图作为总结。