上一篇分析了Android系統(tǒng)中廣播的注冊和注銷,這一篇我們繼續(xù)分析發(fā)送廣播的源碼流程,廣播的發(fā)送相對來說比較復(fù)雜,所以需要比較長的時(shí)間來看,如果你看懂了流程相對來說再研究流程中的細(xì)節(jié)就比較簡單了。
先看一張時(shí)序圖,因?yàn)槔锩嫔婕暗窖h(huán)過程,代碼中會提到,但是時(shí)序圖沒有繪制,所以需要注意一下。

0、ContextImpl.sendBroadcast
/**
* 發(fā)送廣播
* 步驟:
* 1.廣播發(fā)送者,即一個(gè)Activity組件或者一個(gè)Service組件,將一個(gè)特定類型的廣播發(fā)送給AMS
* <p>
* 2.AMS接收到一個(gè)廣播后,首先找到與這個(gè)廣播對應(yīng)的廣播接收者,然后將它們添加到一個(gè)廣播調(diào)度隊(duì)列中,
* 最后向AMS所運(yùn)行在的先從的消息隊(duì)列發(fā)送一個(gè)類型為BROADCAST_INTENT_MSG的消息,這時(shí)候?qū)V播發(fā)送
* 者來說,一個(gè)廣播就發(fā)送完了。
* <p>
* 3.當(dāng)發(fā)送到AMS所運(yùn)行在的線程的消息隊(duì)列中的BROADCAST_INTENT_MSG消息被處理時(shí),AMS就會從廣播調(diào)
* 度隊(duì)列中知道需要接受廣播的接收者,并且將對應(yīng)的廣播發(fā)送給它們所運(yùn)行在的應(yīng)用進(jìn)程。
* <p>
* 4.廣播接收者所運(yùn)行的應(yīng)用程序接收到AMS發(fā)送過來的廣播后,并不是直接將接收到的廣播發(fā)送給廣播接收
* 者來處理,而是將接收到的廣播封裝成一個(gè)消息,并且發(fā)送到主線程的消息隊(duì)列中。當(dāng)找個(gè)消息被處理時(shí),
* 應(yīng)用程序進(jìn)程才會將它所描述的廣播發(fā)給相應(yīng)的廣播接收者處理
* <p>
* 參考:
* http://blog.csdn.net/houliang120/article/details/51607170
* http://gityuan.com/2016/06/04/broadcast-receiver/
* http://blog.csdn.net/windskier/article/details/7251742
*
* @param intent The Intent to broadcast; all receivers matching this
* Intent will receive the broadcast.
*/
@Override
public void sendBroadcast(Intent intent) {
...
try {
...
// 調(diào)用ActivityManagerProxy中的broadcastIntent,然后通過Binder調(diào)用ActivityManagerService
// 中的broadcastIntent
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE,
null, false, false, getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
之前我們講過調(diào)用ActivityManagerProxy的broadcastIntent方法,然后通過Binder調(diào)用ActivityManagerService中的對應(yīng)方法。
1、ActivityManagerProxy.broadcastIntent
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 {
...
// 通過Binder對象mRemote向AMS發(fā)送一個(gè)類型為BROADCAST_INTENT_TRANSACTION的進(jìn)程間通信請求
mRemote.transact(BROADCAST_INTENT_TRANSACTION, data, reply, 0);
...
return res;
}
2、ActivityManagerService.broadcastIntent
// 發(fā)送廣播
public final int broadcastIntent(IApplicationThread caller,
Intent intent, String resolvedType, IIntentReceiver resultTo,
int resultCode, String resultData, Bundle resultExtras,
String[] requiredPermissions, int appOp, Bundle bOptions,
boolean serialized, boolean sticky, int userId) {
enforceNotIsolatedCaller("broadcastIntent");
synchronized (this) {
// 驗(yàn)證廣播的Intent是否合法,如果這個(gè)時(shí)候系統(tǒng)正在啟動,還會驗(yàn)證intent所描述的廣播是否只發(fā)送
// 給動態(tài)注冊的廣播接收者。在系統(tǒng)的啟動過程中,PMS可能還未啟動,這種情況下,AMS是無法獲取靜態(tài)
// 注冊廣播接收者的,因此,就禁止發(fā)送廣播給靜態(tài)注冊的廣播接收者
intent = verifyBroadcastLocked(intent);
// 根據(jù)caller從緩存mLruProcesses中獲取進(jìn)程對象ProcessRecord
final ProcessRecord callerApp = getRecordForAppLocked(caller);
...
int res = broadcastIntentLocked(callerApp,
callerApp != null ? callerApp.info.packageName : null,
intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
requiredPermissions, appOp, bOptions, serialized, sticky,
callingPid, callingUid, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
}
3、ActivityManagerService.broadcastIntentLocked
final int broadcastIntentLocked(ProcessRecord callerApp,
String callerPackage, Intent intent, String resolvedType,
IIntentReceiver resultTo, int resultCode, String resultData,
Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) {
intent = new Intent(intent);
// By default broadcasts do not go to stopped apps.
// 增加下面flag,默認(rèn)不發(fā)送廣播到已經(jīng)停止的app
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
// If we have not finished booting, don't allow this to launch new processes.
// 如果該進(jìn)程還沒有完成啟動,并且不是發(fā)送給啟動升級的廣播,則添只發(fā)送給已注冊的廣播接收者標(biāo)簽
if (!mProcessesReady && (intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) {
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);// 只發(fā)給注冊的receiver
}
...
// 獲取當(dāng)前發(fā)送廣播應(yīng)用所在用戶的userId
// 解釋:
// 7.1.1系統(tǒng)有多用戶登錄,就像電腦上的主用戶和訪客模式一樣,可以設(shè)置多個(gè)用戶,每個(gè)用戶有一個(gè)id,
// 有些廣播需要多個(gè)用戶都要接收,比如時(shí)區(qū)變化這些,是同步的,每個(gè)用戶都要變化。這里一般是我們
// 當(dāng)前登錄的用戶id
userId = mUserController.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 && !mUserController.isUserRunningLocked(userId, 0)) {
return ActivityManager.BROADCAST_FAILED_USER_STOPPED;
}
}
...
// Verify that protected broadcasts are only being sent by system code,
// and that system code is only sending protected broadcasts.
final String action = intent.getAction();
final boolean isProtectedBroadcast;
try {
// 驗(yàn)證是不是受保護(hù)的廣播(是不是系統(tǒng)廣播)
isProtectedBroadcast = AppGlobals.getPackageManager().isProtectedBroadcast(action);
} catch (RemoteException e) {
...
return ActivityManager.BROADCAST_SUCCESS;
}
// 檢查是不是系統(tǒng)調(diào)用
final boolean isCallerSystem;
switch (UserHandle.getAppId(callingUid)) {
case Process.ROOT_UID:
case Process.SYSTEM_UID:
case Process.PHONE_UID:
case Process.BLUETOOTH_UID:
case Process.NFC_UID:
isCallerSystem = true;
break;
default:
isCallerSystem = (callerApp != null) && callerApp.persistent;
break;
}
// First line security check before anything else: stop non-system apps from
// sending protected broadcasts.
if (!isCallerSystem) {// 不是系統(tǒng)發(fā)送的廣播
if (isProtectedBroadcast) {// 非系統(tǒng)進(jìn)程發(fā)送受保護(hù)廣播拋出異常
throw new SecurityException(msg);
} else if (AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(action)
|| AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {
// 如果是配置小部件或者升級小部件的廣播
// 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 (callerPackage == null) {
throw new SecurityException(msg);
} 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(
callerPackage)) {
throw new SecurityException(msg);
}
} else {
// Limit broadcast to their own package.
// 限制發(fā)送廣播給自己包里
intent.setPackage(callerPackage);
}
}
}
// 下面主要是針對系統(tǒng)廣播的處理
if (action != null) {
switch (action) {
case Intent.ACTION_UID_REMOVED:// 移除uid
case Intent.ACTION_PACKAGE_REMOVED:// 卸載應(yīng)用
case Intent.ACTION_PACKAGE_CHANGED:// 應(yīng)用更改,比如:停用,啟動等
case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:// 外部應(yīng)用不可用,比如安裝到sd卡的應(yīng)用,卸載了sd卡
case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:// 外部應(yīng)用可用
case Intent.ACTION_PACKAGES_SUSPENDED:// 暫停應(yīng)用
case Intent.ACTION_PACKAGES_UNSUSPENDED:// 應(yīng)用可用
switch (action) {
case Intent.ACTION_UID_REMOVED:// 移除系統(tǒng)userId(刪除一個(gè)用戶)
...
break;
case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:// 外部應(yīng)用不可用,一般是卸載SD卡
...
break;
case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:// 外部應(yīng)用可用,一般是插入SD卡
...
break;
case Intent.ACTION_PACKAGE_REMOVED:// 卸載
case Intent.ACTION_PACKAGE_CHANGED:// 更新
...
break;
case Intent.ACTION_PACKAGES_SUSPENDED:
case Intent.ACTION_PACKAGES_UNSUSPENDED:
...
break;
}
break;
case Intent.ACTION_PACKAGE_REPLACED: {// 升級應(yīng)用
...
break;
}
case Intent.ACTION_PACKAGE_ADDED: {// 安裝應(yīng)用
...
break;
}
case Intent.ACTION_PACKAGE_DATA_CLEARED: {// 清理應(yīng)用數(shù)據(jù)
...
break;
}
case Intent.ACTION_TIMEZONE_CHANGED:// 時(shí)區(qū)改變
...
break;
case Intent.ACTION_TIME_CHANGED:// 時(shí)間改變
...
break;
case Intent.ACTION_CLEAR_DNS_CACHE:// 清理DNS緩存
...
break;
case Proxy.PROXY_CHANGE_ACTION:// 代理改變
...
break;
case android.hardware.Camera.ACTION_NEW_PICTURE:// 新照片
case android.hardware.Camera.ACTION_NEW_VIDEO:// 新視頻
...
return ActivityManager.BROADCAST_SUCCESS;
}
}
// Add to the sticky list if requested.
if (sticky) {// 判斷是否是粘性廣播,如果是,AMS就需要保存這個(gè)廣播,以便后面注冊要接收此類型廣播的接收者可以獲得這個(gè)廣播
// 檢查粘性廣播是否申請了權(quán)限
...
if (requiredPermissions != null && requiredPermissions.length > 0) {
...
return ActivityManager.BROADCAST_STICKY_CANT_HAVE_PERMISSION;
}
// sticky廣播不能指定目標(biāo)組件
...
// We use userId directly here, since the "all" target is maintained(維護(hù))
// as a separate set of sticky broadcasts.
if (userId != UserHandle.USER_ALL) {// 不是發(fā)送給所有用戶的廣播
// 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);
...// 檢查是否和存在的發(fā)給所有用戶的粘性廣播一樣的廣播
}
// 在AMS中所有的粘性廣播都保存在一個(gè)列表中,這些列表最終保存在AMS的成員變量mStickyBroadcasts
// 所描述的一個(gè)HashMap中,并且以它們的廣播類型為關(guān)鍵字
// 首先檢查mStickyBroadcasts是否有改用戶的粘性廣播列表
ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);
// 該廣播列表中沒有該用戶的stick廣播列表
if (stickies == null) {
stickies = new ArrayMap<>();
mStickyBroadcasts.put(userId, stickies);
}
// 獲取注冊廣播的Action對應(yīng)的粘性廣播的Intent列表
ArrayList<Intent> list = stickies.get(intent.getAction());
if (list == null) {// 如果為空
list = new ArrayList<>();// 創(chuàng)建一個(gè)列表
stickies.put(intent.getAction(), list);// 以action為鍵保存該列表
}
// 獲取該action對應(yīng)粘性廣播Intent列表的個(gè)數(shù)
final int stickiesCount = list.size();
int i;
// 檢查在粘性廣播列表中是否保存了一個(gè)與參數(shù)Intent一致的廣播。如果存在直接替換,否則將參數(shù)
// Intent描述的廣播添加到粘性廣播列表list中
for (i = 0; i < stickiesCount; i++) {
if (intent.filterEquals(list.get(i))) {
// This sticky already exists, replace it.
list.set(i, new Intent(intent));
break;
}
}
if (i >= stickiesCount) {// 如果該列表中不存在該粘性廣播的Intent加入進(jìn)去
list.add(new Intent(intent));
// 我們看到粘性廣播放在了list中,而list以action為鍵放置在了stickies中,而stickies
// 又以userId為鍵放在了mStickyBroadcasts中,因此mStickyBroadcasts保存了設(shè)備中所有
// 用戶粘性廣播的Intent
}
}
int[] users;
if (userId == UserHandle.USER_ALL) {// 發(fā)送廣播給全部用戶
// Caller wants broadcast to go to all started users.
// 獲取所有已啟動用戶的列表
users = mUserController.getStartedUserArrayLocked();
} else {// 發(fā)送廣播給指定用戶
// Caller wants broadcast to go to one specific user.
users = new int[]{userId};
}
// Figure out who all will receive this broadcast.
List receivers = null;// 靜態(tài)注冊接收者
List<BroadcastFilter> registeredReceivers = null;// 動態(tài)注冊接收者
// Need to resolve the intent to interested receivers...
if ((intent.getFlags() & Intent.FLAG_RECEIVER_REGISTERED_ONLY)
== 0) {// 如果當(dāng)前的廣播Intent沒有指定FLAG_RECEIVER_REGISTERED_ONLY標(biāo)記,也就是允許靜態(tài)注冊
// 允許靜態(tài)注冊的Intent,需要從PMS中去查詢對應(yīng)的廣播接收者
receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
}
// 如果參數(shù)intent沒有指定廣播接收者的組件名,說明是發(fā)送給所有已注冊并且要接收該廣播的接收者的
if (intent.getComponent() == null) {
if (userId == UserHandle.USER_ALL && callingUid == Process.SHELL_UID) {
// Query one target user at a time, excluding shell-restricted users
// 查找每一個(gè)用戶的廣播注冊者
for (int i = 0; i < users.length; i++) {
if (mUserController.hasUserRestriction(
UserManager.DISALLOW_DEBUGGING_FEATURES, users[i])) {
continue;
}
// registeredReceiver快結(jié)束前將注冊的BroadcastFilter放入mReceiverResolver中
// 里面包含了對應(yīng)的動態(tài)注冊的廣播接收者
List<BroadcastFilter> registeredReceiversForUser =
mReceiverResolver.queryIntent(intent,
resolvedType, false, users[i]);
if (registeredReceivers == null) {
registeredReceivers = registeredReceiversForUser;
} else if (registeredReceiversForUser != null) {
registeredReceivers.addAll(registeredReceiversForUser);
}
}
} else {// 查找當(dāng)前用戶的所有廣播接收者
// 查詢所有動態(tài)注冊廣播接收者
registeredReceivers = mReceiverResolver.queryIntent(intent,
resolvedType, false, userId);
}
}
// 由于AMS是通過消息機(jī)制將接收到的廣播發(fā)送給目標(biāo)廣播接收者的,因此可能會出現(xiàn)一種情況:上次接收
// 的廣播還沒有來得及發(fā)送給廣播接收者,又馬上接收到一個(gè)同樣的廣播,在這種情況下,如果現(xiàn)在接收的
// 廣播標(biāo)志位FLAG_RECEIVER_REPLACE_PENDING等于1,那么AMS就會用新的廣播代替舊的廣播。
final boolean replacePending =
(intent.getFlags() & Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
// 動態(tài)廣播接收者個(gè)數(shù)
int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
// 處理無序廣播并且存在動態(tài)接收者,首先將當(dāng)前發(fā)送的廣播,即參數(shù)Intent所描述的對象轉(zhuǎn)發(fā)給這些動態(tài)
// 注冊的目標(biāo)廣播接收者,然后轉(zhuǎn)發(fā)給靜態(tài)廣播接收者
if (!ordered && NR > 0) {
...
// 根據(jù)intent查找對應(yīng)的廣播隊(duì)列(前臺優(yōu)先級隊(duì)列還是后臺優(yōu)先級隊(duì)列),創(chuàng)建BroadcastRecord
final BroadcastQueue queue = broadcastQueueForIntent(intent);
// 將參數(shù)intent所描述的廣播以及動態(tài)注冊的目標(biāo)廣播接收者封裝成一個(gè)BroadcastRecord對象r,
// 用來描述AMS要執(zhí)行的一個(gè)廣播轉(zhuǎn)發(fā)任務(wù)
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
callerPackage, callingPid, callingUid, resolvedType, requiredPermissions,
appOp, brOptions, registeredReceivers, resultTo, resultCode, resultData,
resultExtras, ordered, sticky, false, userId);
...
// 在BroadcastQueue中等待發(fā)送廣播中搜索是否有相同的BroadcastRecord并且是否替換
final boolean replaced = replacePending && queue.replaceParallelBroadcastLocked(r);
if (!replaced) {
// 如果不需要替換則插入到BroadcastQueue中,并推動一次廣播發(fā)送
// ------------------!!!重要!!!-------------這里如果是非有序廣播,那就都是動態(tài)廣播接收者
// 也就是說動態(tài)廣播接收者都放在了BroadcastQueue的mParallelBroadcasts中
queue.enqueueParallelBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
}
registeredReceivers = null;
NR = 0;
}
// Merge into one list.動態(tài)廣播registeredReceivers和靜態(tài)廣播receivers合并
// 如果是order廣播,動態(tài)接收者和靜態(tài)的接收者合并到一個(gè)隊(duì)列里面進(jìn)行處理,也就是說order廣播下,
// 所有的接收者(靜態(tài)和動態(tài))處理方式都是一樣的(后面會分析到,都是串行化處理的)。
// 還有就是對于靜態(tài)的接收者而言,始終是和order廣播的處理方式是一樣的,也就是說靜態(tài)的接收者
// 只有order模式(串行化接收)。
// 在合并過程中,如果一個(gè)動態(tài)注冊的廣播接收者和一個(gè)靜態(tài)注冊的目標(biāo)廣播接收者的優(yōu)先級相同,那么
// 動態(tài)注冊的目標(biāo)接收者會排在靜態(tài)注冊的目標(biāo)廣播接收者前面,即動態(tài)注冊的目標(biāo)廣播接收者會優(yōu)先于
// 靜態(tài)注冊的廣播接收者接受有序廣播
int ir = 0;
if (receivers != null) {// order廣播(靜態(tài)廣播)
// 對于ACTION_PACKAGE_ADDED廣播而言,如果是自己被add了,那么這個(gè)廣播只能別人收到,
// 自己即使注冊了這個(gè)靜態(tài)廣播也接收不到,注釋上說是擔(dān)心有些應(yīng)用一安裝就接收自己的PACKAGE_ADDED
// 廣播,然后就啟動了。簡言之,應(yīng)用永遠(yuǎn)接收不到自己的PACKAGE_ADDED廣播。
String skipPackages[] = null;// 需要跳過的廣播
...
// 合并中...
// 下面這一段代碼是典型的有序鏈表的合并操作,合并的依據(jù)是接收者的priority值,這里需要注意的一點(diǎn)
// 是動態(tài)廣播接收器注冊的時(shí)候一般都沒有指定priority,默認(rèn)值是0,具體實(shí)現(xiàn)好像有點(diǎn)像歸并排序的意思,
// 而且是從后向前進(jìn)行的歸并,因此priority越小,在鏈表中的位置就越靠前,后面處理的時(shí)候也就越先處理。
// 走完這里所有的靜態(tài)接收者和order模式下的動態(tài)接收者都已經(jīng)被合并到了receivers鏈表里面。
// 合并以后在receivers鏈表里面靜態(tài)接收者對應(yīng)ResolveInfo對象,order模式下的動態(tài)接收者對應(yīng)的
// 是BroadcastFilter對象。
int NT = receivers != null ? receivers.size() : 0;// 靜態(tài)注冊廣播接收者
int it = 0;
ResolveInfo curt = null;// 靜態(tài)接收者
BroadcastFilter curr = null;// 動態(tài)接收者
...
}
// 對于無序廣播來說,靜態(tài)注冊的廣播接收者全部保存在列表receivers中,而對于有序廣播來說,靜態(tài)
// 注冊和動態(tài)注冊的目標(biāo)廣播接收者全部保存在receivers列表中
// 合并中...
...
// 可以看出,是在合并入receiver后統(tǒng)一發(fā)送BroadcastQueue.scheduleBroadcastsLocked
if ((receivers != null && receivers.size() > 0)
|| resultTo != null) {
BroadcastQueue queue = broadcastQueueForIntent(intent);
// 將剩余的其他目標(biāo)廣播接收者封裝成另外的一個(gè)BroadcastRecord對象,用來描述AMS要執(zhí)行的另
// 一個(gè)廣播轉(zhuǎn)發(fā)任務(wù),兵器添加到AMS內(nèi)部的有序廣播調(diào)用隊(duì)列中
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
callerPackage, callingPid, callingUid, resolvedType,
requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
resultData, resultExtras, ordered, sticky, false, userId);
// 在BroadcastQueue中等待發(fā)送廣播中搜索是否有相同的BroadcastRecord并且是否替換
boolean replaced = replacePending && queue.replaceOrderedBroadcastLocked(r);
if (!replaced) {// 存在需要AMS的有序廣播調(diào)用隊(duì)列中增加新的額廣播任務(wù)
// ---------!!!重要!!!----------包含動態(tài)和靜態(tài)接收者
// 也就是說靜態(tài)廣播都放在BroadcastQueue的mOrderedBroadcasts中,這里也有orderd動態(tài)廣播
queue.enqueueOrderedBroadcastLocked(r);
// 執(zhí)行發(fā)送廣播
queue.scheduleBroadcastsLocked();
}
} else {
// There was nobody interested in the broadcast, but we still want to record
// that it happened.
if (intent.getComponent() == null && intent.getPackage() == null
&& (intent.getFlags() & Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
// This was an implicit broadcast... let's record it for posterity.
addBroadcastStatLocked(intent.getAction(), callerPackage, 0, 0, 0);
}
}
return ActivityManager.BROADCAST_SUCCESS;
}
這里代碼比較多,簡單解釋一下,首先是判斷是不是系統(tǒng)廣播,也就是switch語句中的部分,這部分的廣播是系統(tǒng)發(fā)出的,根據(jù)不同廣播做出不同的處理,系統(tǒng)廣播我們可以接收但是不能發(fā)送,只能由系統(tǒng)發(fā)出,詳細(xì)的不再解釋,自己可以看看;然后是sticky廣播的處理;然后是靜態(tài)廣播和動態(tài)廣播的處理,在動態(tài)廣播和靜態(tài)廣播處理中,先處理動態(tài)廣播接收者,再處理靜態(tài)廣播接收者,因此動態(tài)廣播接收者先收到廣播,然后是靜態(tài)廣播接收者,動態(tài)廣播和靜態(tài)廣播接收者都會通過調(diào)用BroadcastQueue.scheduleBroadcastsLocked方法來發(fā)送廣播,在看這個(gè)代碼之前先看一下時(shí)序圖中的第四步。
4、AMS.broadcastQueueForIntent
// 根據(jù)Intent所帶標(biāo)簽判斷接收者是以前臺優(yōu)先級還是后臺優(yōu)先級運(yùn)行,前臺接收者優(yōu)先級超時(shí)時(shí)間較短
// 正常是后臺優(yōu)先級運(yùn)行,并且不會被提升到前臺優(yōu)先級
BroadcastQueue broadcastQueueForIntent(Intent intent) {
final boolean isFg = (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0;
return (isFg) ? mFgBroadcastQueue : mBgBroadcastQueue;
}
這個(gè)方法主要是根據(jù)Intent中的標(biāo)簽在判斷是接收者是后臺優(yōu)先級還是前臺優(yōu)先級,關(guān)于這兩個(gè)概念看上面代碼中注釋的內(nèi)容。
5、BroadcastQueue.scheduleBroadcastsLocked
// 驅(qū)動廣播,所有廣播都應(yīng)該從這里走,然后會到processNextBroadcast
public void scheduleBroadcastsLocked() {
...
// mBroadcastsScheduled用來描述AMS是否已經(jīng)向它所運(yùn)行在的線程的消息隊(duì)列發(fā)送了一個(gè)類型為
// BROADCAST_INTENT_MSG的消息。AMS就是通過這個(gè)BROADCAST_INTENT_MSG消息類調(diào)度保存在無
// 序廣播調(diào)度隊(duì)列mParallelBroadcasts和有序廣播調(diào)度隊(duì)列mOrderedBroadcasts中的廣播轉(zhuǎn)發(fā)任務(wù)的
if (mBroadcastsScheduled) {// 如果true說明消息隊(duì)列已經(jīng)存在一個(gè)類型為BROADCAST_INTENT_MSG的消息了
return;
}
// 雖然這里只發(fā)送了發(fā)送廣播的消息,但是這一步執(zhí)行完之后就已經(jīng)標(biāo)記廣播發(fā)送了,因此可以看出廣播發(fā)送和接
// 受是異步的,即廣播發(fā)送者將一個(gè)廣播發(fā)送給AMS后,不會等待AMS將這個(gè)廣播轉(zhuǎn)發(fā)給廣播接收者處理
mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
mBroadcastsScheduled = true;
}
廣播中大多數(shù)內(nèi)容的處理是在BroadcastQueue類中,上面有個(gè)mBroadcastsScheduled參數(shù),如果為ture則阻止繼續(xù)執(zhí)行,那么我們看到下面發(fā)完消息后會將其設(shè)置為true,我們接著看哪里將其執(zhí)行為false的,
6、BroadcastQueue.processNextBroadcast
// 廣播的核心部分,參數(shù)fromMsg是用來描述AMS類的成員函數(shù)processNextBroadcast是否是用來處理類型為
// BROADCAST_INTENT_MSG的消息的
final void processNextBroadcast(boolean fromMsg) {
synchronized (mService) {
BroadcastRecord r;
...
if (fromMsg) {// 從msg過來的時(shí)候?yàn)閠rue
// 前面說到,如果消息隊(duì)列里面有BROADCAST_INTENT_MSG消息,該標(biāo)記為true,
// 阻止新的消息加入隊(duì)列,這里開始處理這個(gè)消息的時(shí)候,將mBroadcastsScheduled變量設(shè)置為false,
// 開始允許新的消息加入。
mBroadcastsScheduled = false;
}
// 無序廣播之間不存在相互等待,這里處理的是所有非order的動態(tài)廣播
// 處理保存在無序廣播調(diào)度隊(duì)列mParallelBroadcasts中的廣播發(fā)送任務(wù),即把保存在無序廣播調(diào)度
// 隊(duì)列mParallelBroadcasts中的廣播發(fā)送給它的目標(biāo)廣播接收者處理
while (mParallelBroadcasts.size() > 0) {
// 首先保存無序廣播調(diào)度隊(duì)列mParallelBroadcasts中的每一個(gè)BroadcastRecord對象
r = mParallelBroadcasts.remove(0);
r.dispatchTime = SystemClock.uptimeMillis();
r.dispatchClockTime = System.currentTimeMillis();
// 調(diào)用deliverToRegisteredReceiverLocked向所有的receivers發(fā)送廣播
final int N = r.receivers.size();
// 將它所描述的每一個(gè)無序廣播發(fā)送給每一個(gè)廣播接收者
for (int i = 0; i < N; i++) {
Object target = r.receivers.get(i);
deliverToRegisteredReceiverLocked(r, (BroadcastFilter) target, false, i);
}
addBroadcastToHistoryLocked(r);
}
...
// 接下來處理保存在有序廣播調(diào)度隊(duì)列mPendingBroadcast中的廣播轉(zhuǎn)發(fā)任務(wù)。有前面可知,有序廣播
// 調(diào)度隊(duì)列mOrderedBroadcast描述的目標(biāo)廣播接收者有可能是靜態(tài)注冊的,而這些靜態(tài)注冊的目標(biāo)廣
// 播接收者可能還沒有啟動起來,因此AMS將一個(gè)廣播發(fā)送給它們處理時(shí),首先將它們啟動起來。事實(shí)上,
// AMS只需要將他們所運(yùn)行在的進(jìn)程啟動起來就可以了,因?yàn)楫?dāng)這些進(jìn)程接收到AMS發(fā)送的廣播后,就會
// 主動將目標(biāo)廣播接收者啟動起來
// mPendingBroadcast對象是用來描述一個(gè)正在等待靜態(tài)注冊的目標(biāo)廣播接收者啟動起來的廣播轉(zhuǎn)發(fā)任務(wù)的
if (mPendingBroadcast != null) {
boolean isDead;
synchronized (mService.mPidsSelfLocked) {
// 檢查目標(biāo)廣播接收者所在進(jìn)程是否已經(jīng)啟動
ProcessRecord proc = mService.mPidsSelfLocked.get(mPendingBroadcast.curApp.pid);
isDead = proc == null || proc.crashing;
}
if (!isDead) {// 如果正在啟動,等待
// It's still alive, so keep waiting
return;
} else {// 已經(jīng)啟動準(zhǔn)備發(fā)送廣播
...
}
}
boolean looped = false;
// 逐條處理有序廣播列表mOrderedBroadcasts中的BroadcastRecord
do {
// 判斷有序廣播調(diào)度隊(duì)列mOrderedBroadcasts是否還有需要處理的廣播
if (mOrderedBroadcasts.size() == 0) {// 沒有,說明調(diào)度隊(duì)列中的廣播已經(jīng)處理完成
...
return;
}
// 如果沒有處理完成,取出下一個(gè)馬上要處理的廣播BroadcastRecord
r = mOrderedBroadcasts.get(0);
boolean forceReceive = false;
// 獲取廣播轉(zhuǎn)發(fā)任務(wù)的目標(biāo)廣播接收者的個(gè)數(shù)
int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
// 檢查前一個(gè)目標(biāo)廣播接收者是否在規(guī)定的時(shí)間內(nèi)處理完成AMS給它發(fā)送的一個(gè)有序廣播。AMS處理
// BroadcastRecord對象r所描述的一個(gè)廣播轉(zhuǎn)發(fā)任務(wù)時(shí),會將當(dāng)前時(shí)間記錄在這個(gè)BroadcastRecord
// 對象中,如果這個(gè)廣播任務(wù)不能在(2*BROADCAST_TIMEOUT*numReceivers)毫秒內(nèi)完成,即它的目
// 標(biāo)廣播接收者不能在(2*BROADCAST_TIMEOUT*numReceivers)毫秒內(nèi)完成AMS給它們發(fā)送的一個(gè)有
// 序廣播,那么會調(diào)用broadcastTimeoutLocked函數(shù)來強(qiáng)制結(jié)束這個(gè)廣播轉(zhuǎn)發(fā)任務(wù),
if (mService.mProcessesReady && r.dispatchTime > 0) {
long now = SystemClock.uptimeMillis();
if ((numReceivers > 0) &&
(now > r.dispatchTime + (2 * mTimeoutPeriod * numReceivers))) {
...
// 出現(xiàn)超時(shí),強(qiáng)制結(jié)束
broadcastTimeoutLocked(false); // forcibly finish this broadcast
// 重置參數(shù),繼續(xù)處理有序廣播調(diào)度隊(duì)列mOrderedBroadcasts的下一個(gè)廣播轉(zhuǎn)發(fā)任務(wù)
forceReceive = true;
r.state = BroadcastRecord.IDLE;
}
}
// 檢測廣播轉(zhuǎn)發(fā)任務(wù)是否正在處理中,即AMS正在將一個(gè)有序廣播轉(zhuǎn)發(fā)給它的前一個(gè)目標(biāo)廣播接收處理者,
// 如果是,AMS就會等待這個(gè)目標(biāo)廣播接收者處理完該有序廣播,然后再轉(zhuǎn)發(fā)給下一個(gè)廣播接收者處理
...
// 表示廣播已經(jīng)向所有的receiver發(fā)送結(jié)束或者中途被取消, 如果r.resultAbort為true,會停止處理
// 當(dāng)前正在發(fā)送的BroadcastRecord,這樣優(yōu)先級比較低的接收者也就收不到這個(gè)廣播了
// 檢查BroadcastRecord對象r所描述的廣播轉(zhuǎn)發(fā)任務(wù)是否已經(jīng)處理完成,或者是否已經(jīng)被強(qiáng)制結(jié)束了。
// 如果是,那么調(diào)用函數(shù)cancelBroadcastTimeoutLocked來刪除前面發(fā)送到AMS所運(yùn)行在的線程的消息
// 隊(duì)列中的一個(gè)BROADCAST_TIMEOUT_MSG消息,表示BroadcastRecord對象r所描述的廣播轉(zhuǎn)發(fā)任務(wù)已經(jīng)
// 在規(guī)定時(shí)間內(nèi)處理完成了。接下來就講改廣播BroadcastRecord對象從隊(duì)列中刪除,然后賦值為null
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 {
...
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) {
...
}
}
...
// ... and on to the next...
...
// BroadcastRecord處理完移除
mOrderedBroadcasts.remove(0);
r = null;
looped = true;
continue;
}
} while (r == null);// 如果第一次取出的r不為空,則退出循環(huán)
// Get the next receiver...(獲取下一個(gè)將要處理的廣播接收者在其列表中的位置)
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.
// 保存當(dāng)前時(shí)間,
r.receiverTime = SystemClock.uptimeMillis();
if (recIdx == 0) {// 表示第一個(gè)開始處理的接收者,也就是BroadcastRecord對象r所描述的廣播任務(wù)剛被處理
// 接收者開始處理的時(shí)間戳,也就是這個(gè)接收者開始處理了,要記錄開始時(shí)間來計(jì)算是否超過超時(shí)時(shí)間
// 也就是說這是BroadcastRecord中第一個(gè)接收者開始被處理的時(shí)間戳,也就是上面BroadcastRecord
// 超時(shí)的起點(diǎn),可以看到上面超時(shí)比較的時(shí)候用的就是r.dispatchTime
r.dispatchTime = r.receiverTime;
r.dispatchClockTime = System.currentTimeMillis();
...
}
// 檢查AMS是否已經(jīng)向它所在的線程的消息隊(duì)列發(fā)送了類型為BROADCAST_TIMEOUT_MSG的消息,如果沒有發(fā)送,
// 那么會調(diào)用setBroadcastTimeoutLocked函數(shù)向這個(gè)線程發(fā)送一個(gè)類型為setBroadcastTimeoutLocked
// 的消息,并且制定在timeoutTime毫秒后處理。上面指定了r.receiverTime為當(dāng)前時(shí)間表示AMS將一個(gè)有序
// 廣播發(fā)送給BroadcastRecord對象r所描述的廣播轉(zhuǎn)發(fā)任務(wù)的下一個(gè)目標(biāo)廣播接收者處理的時(shí)間。如果這個(gè)
// 廣播接收者不能再timeoutTime之內(nèi)完成這個(gè)有序廣播,AMS就會任務(wù)它超時(shí)。
if (!mPendingBroadcastTimeoutMessage) {
long timeoutTime = r.receiverTime + mTimeoutPeriod;
...
// 設(shè)置超時(shí),傳入?yún)?shù)是r.receiverTime + mTimeoutPeriod,也就是開始時(shí)間加上超時(shí)時(shí)間
// mTimeoutPeriod,mTimeoutPeriod初始化是在BroadcastQueue初始化的時(shí)候傳入的,
// 也就是在AMS(AMS構(gòu)造函數(shù)中)中初始化mFgBroadcastQueue和mBgBroadcastQueue時(shí)傳入的
// BROADCAST_FG_TIMEOUT = 10 * 1000和BROADCAST_BG_TIMEOUT = 60 * 1000,
// 這里開始埋了ANR的雷
setBroadcastTimeoutLocked(timeoutTime);
}
// 上面分析的時(shí)候?qū)τ贐roadcastRecord.receivers里面包含兩種receiver接收者:order廣播下的
// 動態(tài)注冊接收者和靜態(tài)接收者,這兩種receiver處理的方式是不一樣的,對于order廣播下的動態(tài)注冊
// receiver而言,接收者進(jìn)程一定是已經(jīng)啟動的,但是對于靜態(tài)接收者receiver而言,當(dāng)前的receiver進(jìn)程
// 可能還沒有啟動,因此動態(tài)和靜態(tài)的receiver處理的邏輯不一樣,需要分開處理,而靜態(tài)接收者又分為進(jìn)程
// 已經(jīng)啟動和尚未啟動兩種情況。
final BroadcastOptions brOptions = r.options;
// 得到下一個(gè)廣播接收者
final Object nextReceiver = r.receivers.get(recIdx);
// 如果當(dāng)前nextReceiver是一個(gè)BroadcastFilter類型,說名是一個(gè)動態(tài)注冊接收者,不需要啟動一個(gè)進(jìn)程,
// 直接調(diào)用deliverToRegisteredReceiverLocked函數(shù)發(fā)送廣播
if (nextReceiver instanceof BroadcastFilter) {
// Simple case: this is a registered receiver who gets
// a direct call.
BroadcastFilter filter = (BroadcastFilter) nextReceiver;
...
// 上面已經(jīng)分析
deliverToRegisteredReceiverLocked(r, filter, r.ordered, recIdx);
// 檢查BroadcastRecord對象r所描述的廣播轉(zhuǎn)發(fā)任務(wù)是否用來轉(zhuǎn)發(fā)無序廣播的。
if (r.receiver == null || !r.ordered) {// 如果是
...
// 設(shè)置IDLE狀態(tài),表示AMS不需要等待它的前一個(gè)目標(biāo)廣播接收者處理完成一個(gè)廣播就可以將該廣播
// 繼續(xù)發(fā)送給它的下一個(gè)目標(biāo)廣播接收者處理
r.state = BroadcastRecord.IDLE;
// 調(diào)用下面函數(shù)就是為了將一個(gè)廣播繼續(xù)發(fā)送給BroadcastRecord對象r所描述的廣播轉(zhuǎn)發(fā)任務(wù)的
// 下一個(gè)目標(biāo)廣播接收者處理的
scheduleBroadcastsLocked();
} else {
...
}
return;
}
// Hard case: need to instantiate the receiver, possibly
// starting its application process to host it.
// 如果不是動態(tài)的說明是一個(gè)靜態(tài)注冊接收者(如果動態(tài)的上面if中處理并進(jìn)行攔截),此時(shí)進(jìn)程可能沒有啟動
ResolveInfo info =
(ResolveInfo) nextReceiver;
ComponentName component = new ComponentName(
info.activityInfo.applicationInfo.packageName,
info.activityInfo.name);
// 是否跳過該廣播接收者不處理
boolean skip = false;
...
// 得到ResolveInfo對象info所描述的廣播接收者的android:process屬性值,即它需要運(yùn)行在的應(yīng)用程序
// 進(jìn)程的名稱,并且保存在變量targetProcess中
String targetProcess = info.activityInfo.processName;
// 獲取當(dāng)前廣播接收者的進(jìn)程記錄,也就是該靜態(tài)廣播接收者是否已經(jīng)運(yùn)行
ProcessRecord app = mService.getProcessRecordLocked(targetProcess,
info.activityInfo.applicationInfo.uid, false);
...
// 跳過,恢復(fù)初始狀態(tài),開始下一個(gè)廣播接收者的處理
if (skip) {
...
return;
}
r.delivery[recIdx] = BroadcastRecord.DELIVERY_DELIVERED;
r.state = BroadcastRecord.APP_RECEIVE;
r.curComponent = component;
r.curReceiver = info.activityInfo;
...
if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {
scheduleTempWhitelistLocked(receiverUid,
brOptions.getTemporaryAppWhitelistDuration(), r);
}
// Broadcast is being executed, its package can't be stopped.
try {
AppGlobals.getPackageManager().setPackageStoppedState(
r.curComponent.getPackageName(), false, UserHandle.getUserId(r.callingUid));
} catch (RemoteException e) {
} catch (IllegalArgumentException e) {
...
}
// Is this receiver's application already running?
// 如果當(dāng)前進(jìn)程已經(jīng)運(yùn)行,則直接發(fā)給該進(jìn)程,然后返回
if (app != null && app.thread != null) {
try {
app.addPackage(info.activityInfo.packageName,
info.activityInfo.applicationInfo.versionCode, mService.mProcessStats);
// 將廣播發(fā)送給該進(jìn)程處理
processCurBroadcastLocked(r, app);
// order廣播是一種同步處理方式,因此處理完可以直接return
return;
} catch (RemoteException e) {
...
} catch (RuntimeException e) {
...
return;
}
// If a dead object exception was thrown -- fall through to
// restart the application.
}
...
// 靜態(tài)接收者進(jìn)程尚未啟動,調(diào)用AMS的startProcessLocked函數(shù)啟動該接收者進(jìn)程,并將當(dāng)前正在等待進(jìn)程
// 啟動的BroadcastRecord存儲到mPendingBroadcast里面,這個(gè)就是靜態(tài)廣播拉起應(yīng)用的原理,如果應(yīng)用
// 沒有啟動,注冊一個(gè)靜態(tài)廣播(一般廠商會修改只能啟動自己的應(yīng)用)。到這里又開始進(jìn)入等待進(jìn)程啟動的
// 過程,進(jìn)程啟動完成后才能處理廣播
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) {// 如果啟動失敗
...
logBroadcastReceiverDiscardLocked(r);
// 結(jié)束廣播發(fā)送任務(wù)
finishReceiverLocked(r, r.resultCode, r.resultData,
r.resultExtras, r.resultAbort, false);
scheduleBroadcastsLocked();
r.state = BroadcastRecord.IDLE;
return;
}
// 正在啟動接收者進(jìn)程,將正在啟動的BroadcastRecord記錄存儲到mPendingBroadcast中,同時(shí)將當(dāng)前正在
// 啟動的接收者進(jìn)程在所有接收者中的索引存儲到mPendingBroadcastRecvIndex,如果當(dāng)前廣播接收者處理
// 完,需要繼續(xù)從mPendingBroadcastRecvIndex計(jì)算到下一個(gè)接收者發(fā)送當(dāng)前廣播
mPendingBroadcast = r;
mPendingBroadcastRecvIndex = recIdx;
}
}
我們根據(jù)第五步的發(fā)送消息類型可以跟蹤到,消息執(zhí)行是在BroadcastHandler的handleMessage方法中調(diào)用的,這里出入一個(gè)參數(shù)fromMsg,也就是該廣播是不是通過Handler發(fā)送消息的方式傳遞的,那么我們上面知道我們這就是通過這種方式執(zhí)行的,所以在代碼中會將mBroadcastsScheduled參數(shù)設(shè)置為false,也就是這個(gè)消息開始執(zhí)行了則開始運(yùn)行下一個(gè)消息發(fā)送。還有就是通過直接調(diào)用的方式來執(zhí)行的,那么就不會改變這個(gè)參數(shù)。
接著看,先執(zhí)行無序廣播,無序廣播接收者不需要等待,所以直接for循環(huán)執(zhí)行,調(diào)用deliverToRegisteredReceiverLocked方法發(fā)送廣播。
7、deliverToRegisteredReceiverLocked
// AMS將一個(gè)廣播發(fā)給一個(gè)目標(biāo)廣播接收者之前,有可能需要檢查這個(gè)廣播的發(fā)送者和接收者的權(quán)限。這個(gè)權(quán)限檢查是
// 雙向的,即需要檢查一個(gè)廣播發(fā)送者是否有權(quán)限向一個(gè)目標(biāo)廣播接收者發(fā)送廣播,以及一個(gè)目標(biāo)廣播接收者是否有權(quán)限
// 接收一個(gè)廣播發(fā)送者發(fā)過來的一個(gè)廣播。這兩個(gè)權(quán)限主要是調(diào)用AMS的成員函數(shù)checkComponentPermission來檢查
// 對方的PID以及UID是否符合要求
private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
BroadcastFilter filter, boolean ordered, int index) {
// 標(biāo)記是否要跳過該廣播接收者
boolean skip = false;
// 需要檢查廣播發(fā)送者的權(quán)限
...
// r.requiredPermissions != null為true表示需要檢查廣播接收者的權(quán)限
...
// 如果要跳過,則設(shè)置該廣播結(jié)束
if (skip) {
r.delivery[index] = BroadcastRecord.DELIVERY_SKIPPED;
return;
}
...
// order廣播,所有的接收者需要依次以一種同步的方式發(fā)送廣播,
// 可以看到order廣播在BroadcastRecord保存了幾個(gè)狀態(tài)
if (ordered) {
// IBinder類型,代表當(dāng)前的接收者
r.receiver = filter.receiverList.receiver.asBinder();
// 當(dāng)前正在處理的BroadcastFilter,和上面的receiver是對應(yīng)好的
r.curFilter = filter;
filter.receiverList.curBroadcast = r;
r.state = BroadcastRecord.CALL_IN_RECEIVE;
if (filter.receiverList.app != null) {
r.curApp = filter.receiverList.app;
filter.receiverList.app.curReceiver = r;
mService.updateOomAdjLocked(r.curApp);
}
}
try {
if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {
// 如果正在備份或者恢復(fù)備份跳過,
// 如果是一個(gè)有序廣播,則執(zhí)行下一個(gè)廣播
if (ordered) {
skipReceiverLocked(r);
}
} else {
// 如果不需要進(jìn)行權(quán)限檢查或者通過權(quán)限檢查,調(diào)用performReceiveLocked發(fā)送廣播
performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
new Intent(r.intent), r.resultCode, r.resultData,
r.resultExtras, r.ordered, r.initialSticky, r.userId);
}
...
} catch (RemoteException e) {
...
}
}
我們這里不是有序廣播,正常也不會備份,所以會走else里面的方法performReceiveLocked。如果是有序廣播我們后面再分析
8、performReceiveLocked
/**
* 由前面可知,當(dāng)一個(gè)Activity或者一個(gè)Service將一個(gè)廣播接收者注冊到AMS中時(shí),它所在的應(yīng)用程序進(jìn)程會先將
* 這個(gè)廣播接收者封裝成一個(gè)類型為InnerReceiver的Binder本地對象,然后再注冊到AMS中。因此當(dāng)AMS要將一個(gè)
* 廣播發(fā)給一個(gè)目標(biāo)廣播接收者處理時(shí),實(shí)際上是將這個(gè)廣播轉(zhuǎn)發(fā)給封裝了這個(gè)目標(biāo)廣播接收者的一個(gè)InnerReceiver
* 對象來處理
* <p>
* AMS向一個(gè)應(yīng)用程序進(jìn)程發(fā)送一個(gè)廣播時(shí),采用的是異步進(jìn)程間通信方式。前面提到,發(fā)送給一個(gè)Binder實(shí)體對象
* 的所有異步事物都是保存在一個(gè)異步事物隊(duì)列中的。由于保存在一個(gè)異步事物隊(duì)列中的異步事物在同一時(shí)刻只有一
* 個(gè)會得到處理,即只有隊(duì)列頭部的異步事物才會得到處理,因此AMS就可以保證它發(fā)送給同一個(gè)應(yīng)用程序的所有廣
* 播都是按照這個(gè)發(fā)送順序來串行的被接受和處理
*/
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.
// app不為空,表示進(jìn)程已經(jīng)啟動,調(diào)用ActivityThread.scheduleRegisteredReceiver發(fā)送當(dāng)前廣播
if (app != null) {
if (app.thread != null) {// 因?yàn)槭莿討B(tài)注冊廣播,所以一般不為空
try {
// 這里scheduleRegisteredReceiver函數(shù)是一個(gè)Binder調(diào)用,注釋上面說的很清楚,
// 要用one-way calls像動態(tài)的注冊進(jìn)程發(fā)起B(yǎng)inder調(diào)用,意思就是在Binder調(diào)用里面會
// 加上IBinder.FLAG_ONEWAY標(biāo)記,Binder客戶端(動態(tài)注冊進(jìn)程)只要一收到Binder調(diào)用的
// 命令和數(shù)據(jù),立馬返回到Binder服務(wù)端(AMS進(jìn)程),是一個(gè)異步的調(diào)用方式。
// 大致流程是:
// 1) ApplicationThreadNative.ApplicationThreadProxy. scheduleRegisteredReceiver(system_server)
// 2) Binder驅(qū)動 (Binder驅(qū)動進(jìn)程,ONEWAY)
// 3)ApplicationThreadNative. scheduleRegisteredReceiver(應(yīng)用進(jìn)程,Binder線程向主線程發(fā)送消息)
// 4)Binder驅(qū)動返回 (Binder驅(qū)動進(jìn)程)
// 5)ActivityThread. scheduleRegisteredReceiver(應(yīng)用進(jìn)程,處理消息)
// 調(diào)用ApplicationThread對象的Binder代理對象的函數(shù)來向它發(fā)送廣播
app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
data, extras, ordered, sticky, sendingUser, app.repProcState);
...
} catch (RemoteException ex) {
...
}
} else {
...
}
} else {
// 直接調(diào)用與它關(guān)聯(lián)的一個(gè)InnerReceiver對象的Binder代理對象的成員函數(shù)performReceive來向它發(fā)送廣播
receiver.performReceive(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
}
}
如果進(jìn)程存在,則執(zhí)行ActivityThread.scheduleRegisteredReceiver方法,否則直接調(diào)用receiver.performReceive方法發(fā)送廣播。因?yàn)槲覀儎討B(tài)注冊的所以會執(zhí)行第一種情況。
9、ActivityThread.scheduleRegisteredReceiver
// 處理非串行化動態(tài)廣播,非串化ordered是false,這里的receiver對應(yīng)的是
// LoadedApk.ReceiverDispatcher.InnerReceiver對象
// 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);
// 調(diào)用LoadedApk.ReceiverDispatcher.InnerReceiver.performReceive函數(shù)
receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
sticky, sendingUser);
}
這里我們看到和上面一樣最終還是執(zhí)行receiver.performReceive方法來發(fā)送廣播。
10、LoadedApk.ReceiverDispatcher.InnerReceiver.performReceive
@Override
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
final LoadedApk.ReceiverDispatcher rd;
...
rd = mDispatcher.get();
...
if (rd != null) {
rd.performReceive(intent, resultCode, data, extras,
ordered, sticky, sendingUser);
} else {
...
try {
...
mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
} catch (RemoteException e) {
...
}
}
}
}
我們上一章注冊廣播是講過LoadedApk.ReceiverDispatcher對象封裝了廣播接收者,如果該廣播接收者注冊了,那么該對象就會存在,則會調(diào)用LodedApk.ReceiverDispatcher.performReceive,否則調(diào)用AMS.finishReceiver方法,我們先看有廣播的情況。
11、LodedApk.ReceiverDispatcher.performReceive
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
// 首先將參數(shù)Intent所描述的一個(gè)廣播封裝成一個(gè)Args對象,然后將這個(gè)Args對象封裝成一個(gè)消息對象,
// 然后將這個(gè)消息對象發(fā)送到應(yīng)用程序主線程的消息隊(duì)列中。
final Args args = new Args(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
// 將當(dāng)前廣播信息放到主線程的Handler中進(jìn)行處理,作為一個(gè)Runnable調(diào)度而不是在handleMessage中處理,
// 而是在Handler內(nèi)部機(jī)制中,處理的時(shí)候會對應(yīng)run函數(shù),因此這里不久后會調(diào)用Args.run函數(shù)
..
// 上面將廣播的參數(shù)封裝在一個(gè)Args對象里面,然后通過post到主線程的消息隊(duì)列里面
if (intent == null || !mActivityThread.post(args)) {
if (mRegistered && ordered) {
...
args.sendFinished(mgr);
}
}
}
上面初始化了一個(gè)Args對象,該對象實(shí)現(xiàn)了Runnable接口,在if語句中調(diào)用post方法,會調(diào)用Args中的run方法。
13、Args.run
public void run() {
// mReceiver指向一個(gè)廣播接收者
final BroadcastReceiver receiver = mReceiver;
...
// 這里處理的是動態(tài)廣播接收者,默認(rèn)認(rèn)為接收者BroadcastReceiver已經(jīng)存在
try {
...
// 接受廣播
receiver.onReceive(mContext, intent);
// 然后調(diào)用BroadcastReceiver.PendingResult.finish函數(shù),也就是下面的finish函數(shù)
} catch (Exception e) {
// 檢查當(dāng)前廣播是否是有序廣播,并且廣播接收者是否已經(jīng)注冊到AMS中
if (mRegistered && ordered) {
// 通知AMS,它前面轉(zhuǎn)發(fā)過來的有序廣播已經(jīng)處理完了,這時(shí)AMS就可以繼續(xù)將這個(gè)有序廣播
// 轉(zhuǎn)發(fā)給下一個(gè)目標(biāo)廣播接收者了
sendFinished(mgr);
}
...
}
...
}
在這里調(diào)用BroadcastReceiver.onReceive方法,這樣就會執(zhí)行完一次無需廣播發(fā)送過程。我們再回到第10步,如果對象接收者不存在則調(diào)用AMS.finishReceiver
15、AMS.finishReceiver
public void finishReceiver(IBinder who, int resultCode, String resultData,
Bundle resultExtras, boolean resultAbort, int flags) {
...
try {
boolean doNext = false;
BroadcastRecord r;
// 首先辨別出當(dāng)前receiver所在的BroadcastRecord屬于前臺廣播還是后臺廣播,然后在對應(yīng)的
// BroadcastQueue中找出對應(yīng)的BroadcastRecord,里面的finishReceiverLocked函數(shù)在前面介紹過,
// 主要是重新設(shè)置BroadcastRecord里面一些狀態(tài)變量,以便于BroadcastRecord將廣播發(fā)送給下一個(gè)
// 接收者。尤其的,如果前面的mAbortBroadcast設(shè)置為true,那么BroadcastRecord的成員resultAbort
// 會設(shè)置成true
synchronized (this) {
BroadcastQueue queue = (flags & Intent.FLAG_RECEIVER_FOREGROUND) != 0
? mFgBroadcastQueue : mBgBroadcastQueue;
r = queue.getMatchingOrderedReceiver(who);
// 結(jié)束當(dāng)前正在發(fā)送的廣播
if (r != null) {
doNext = r.queue.finishReceiverLocked(r, resultCode,
resultData, resultExtras, resultAbort, true);
}
}
// 立馬調(diào)度一次發(fā)送廣播,發(fā)送下一次廣播,但是processNextBroadcast是一個(gè)同步函數(shù),
// 一次只能處理一個(gè)請求
if (doNext) {
r.queue.processNextBroadcast(false);
}
...
} finally {
...
}
}
這里是如果發(fā)送廣播時(shí)接收者不存在,那么要完成該次廣播,并且判斷是否執(zhí)行發(fā)送給下一個(gè)廣播接收者,如果需要發(fā)送給下個(gè)廣播接收者要再次調(diào)用BroadcastQueue.processNextBroadcast方法。這樣就又回到了前面第六步。我們再往前看BroadcastQueue.processNextBroadcast方法,執(zhí)行完無序廣播后開始執(zhí)行有序廣播,因?yàn)橛行驈V播是一個(gè)執(zhí)行完再執(zhí)行下一個(gè)所以必須設(shè)置超時(shí),并且如果超時(shí)要立即接受廣播,
17、broadcastTimeoutLocked
/**
* AMS在處理order模式廣播接收者時(shí),會為每一個(gè)order模式廣播處理設(shè)置超時(shí)時(shí)間,并且超時(shí)時(shí)間是各個(gè)接收者之間
* 相互獨(dú)立,前面分析超時(shí)通過setBroadcastTimeoutLocked函數(shù)建立超時(shí)時(shí)間點(diǎn)消息的,本以為每次處理完以后,
* 調(diào)用cancelBroadcastTimeoutLocked函數(shù)取消當(dāng)前接收者的超時(shí)消息,但是實(shí)際上用了一種更加高效的方法處理了
* 超時(shí)機(jī)制,在每個(gè)order模式receiver開始處理的時(shí)候設(shè)置超時(shí)消息,BroadcastRecord.receiverTime記錄了
* 當(dāng)前receiver開始處理的時(shí)間點(diǎn)
* <p>
* BroadcastRecord超時(shí):注意這里的超時(shí)和我們常說的廣播超時(shí)ANR不是一個(gè)概念,這個(gè)BroadcastRecord超時(shí)是針
* 對當(dāng)前BroadcastRecord. receivers里面剩余的所有的成員而言的,比如說當(dāng)前receivers里面剩余4個(gè)廣播接收者,
* 那么這個(gè)超時(shí)的時(shí)間: 2*(4*mTimeoutPeriod) 至于這個(gè)mTimeoutPeriod,對于前臺廣播mFgBroadcastQueue
* 和mBgBroadcastQueue后臺廣播時(shí)間:BROADCAST_FG_TIMEOUT = 10 * 1000
* 和BROADCAST_BG_TIMEOUT = 60 * 1000(AMS中),也就是對于有4個(gè)成員的receivers 后臺廣播的
* BroadcastRecord而言超時(shí)的時(shí)間為:2*(4*10*1000)=80 000ms=80s,當(dāng)出現(xiàn)這種超時(shí)的時(shí)候,當(dāng)前正在處理的
* 廣播接收者會出現(xiàn)ANR,并且導(dǎo)致后面尚未接收到廣播的收不到當(dāng)前的廣播。broadcastTimeoutLocked函數(shù)會將
* mOrderedBroadcasts中下標(biāo)為0的應(yīng)用進(jìn)程ANR,下面forceReceive設(shè)置為true,走到下面的if判斷里面會將當(dāng)前
* 正在處理的BroadcastRecord從mOrderedBroadcasts中remove掉,導(dǎo)致receivers后面的成員沒有收到廣播,
* 并且將r設(shè)置為null,接著就處理broadcastTimeoutLocked里面的下一個(gè)廣播記錄BroadcastRecord。例如,
* receivers里面包含4個(gè)成員,但是第1個(gè)接收者在80s內(nèi)都沒有處理完,那么這個(gè)接收者進(jìn)程會收到ANR,
* 并且后面的3個(gè)廣播接收者都收不到當(dāng)前的廣播。
* <p>
* 注釋來自于:http://blog.csdn.net/houliang120/article/details/51607170
*
* @param fromMsg
*/
final void broadcastTimeoutLocked(boolean fromMsg) {
...
long now = SystemClock.uptimeMillis();
BroadcastRecord r = mOrderedBroadcasts.get(0);
if (fromMsg) {
if (mService.mDidDexOpt) {
...
long timeoutTime = SystemClock.uptimeMillis() + mTimeoutPeriod;
setBroadcastTimeoutLocked(timeoutTime);
return;
}
...
long timeoutTime = r.receiverTime + mTimeoutPeriod;
// 舉個(gè)例子:
// 假設(shè)receiverA在100s的時(shí)候開始處理,超時(shí)時(shí)間為10s,那么receiverA的超時(shí)時(shí)間點(diǎn)就是110s,
// 但是receiverA在105s的時(shí)候已經(jīng)處理完了,于是在105s的時(shí)候開始receiverB,但是并沒有取消
// receiverA的超時(shí)消息,也就是在110s的時(shí)候仍然會走到這里的broadcastTimeoutLocked函數(shù),
// receiverB開始處理,這時(shí)候r.receiverTime就是105s,對于receiverB而言超時(shí)時(shí)間應(yīng)該是115s,
// 假設(shè)receiverB需要在112s才能處理完,在110s的時(shí)候broadcastTimeoutLocked函數(shù)處理的時(shí)候
// timeoutTime=115s,now=110s,這時(shí)候不會進(jìn)行實(shí)際的超時(shí)處理,因?yàn)檫€沒有到真實(shí)的超時(shí)時(shí)間,
// 所以重新設(shè)置超時(shí)時(shí)間點(diǎn)在115s。就這樣根據(jù)當(dāng)前BroadcastRecord.receiverTime的時(shí)間反復(fù)調(diào)整。
if (timeoutTime > now) {// 判斷超時(shí)時(shí)間點(diǎn)和現(xiàn)在時(shí)間的關(guān)系,此處還沒有超時(shí)
// We can observe premature timeouts because we do not cancel and reset the
// broadcast timeout message after each receiver finishes. Instead, we set up
// an initial timeout then kick it down the road a little further as needed
// when it expires.
// 因?yàn)闆]有在每個(gè)廣播處理完之后取消或者重置超時(shí)時(shí)間,從而導(dǎo)致提前檢測到超時(shí)消息。取而代之,
// 設(shè)置一個(gè)初始超時(shí)時(shí)間點(diǎn),然后每次出現(xiàn)超時(shí)事件的時(shí)候根據(jù)需要進(jìn)行處理或者調(diào)整超時(shí)機(jī)制。
...
setBroadcastTimeoutLocked(timeoutTime);
return;
}
}
BroadcastRecord br = mOrderedBroadcasts.get(0);
if (br.state == BroadcastRecord.WAITING_SERVICES) {
...
processNextBroadcast(false);
return;
}
...
}
這里主要是超時(shí)的處理,因?yàn)樽⑨屢呀?jīng)非常詳細(xì),所以不再解釋,所以我們在寫廣播接收到消息是最后采用Handler或者啟動服務(wù)將消息處理的過程放到Handler中或者服務(wù)中,而不是直接在廣播接收者中完成。
18、setBroadcastTimeoutLocked
// 設(shè)置超時(shí)時(shí)間
final void setBroadcastTimeoutLocked(long timeoutTime) {
if (!mPendingBroadcastTimeoutMessage) {
Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG, this);
mHandler.sendMessageAtTime(msg, timeoutTime);
mPendingBroadcastTimeoutMessage = true;
}
}
如果廣播還沒有超時(shí)就執(zhí)行完了就從新設(shè)置下一個(gè)廣播的起始時(shí)間,方便計(jì)算下一個(gè)廣播的超時(shí)。這個(gè)消息處理就不分析了,自己看一下。再回到第六步BroadcastQueue.processNextBroadcast方法中,如果廣播發(fā)送完成,或者被中斷或者取消,則判斷是否發(fā)送最后的廣播,如果要發(fā)送,則執(zhí)行performReceiveLocked方法,這個(gè)方法在第八步講了,這里就不再重復(fù)分析。我們知道廣播有靜態(tài)廣播接收者和動態(tài)廣播接收者,動態(tài)廣播接收者進(jìn)程都是啟動的,但是靜態(tài)的就不一定了,可能進(jìn)程還沒有啟動,就想第六步中代碼注釋分析的一樣,我們上面處理的都是動態(tài)注冊的,不需要判斷進(jìn)程是否已經(jīng)啟動,但是靜態(tài)廣播就需要判斷該進(jìn)程是否已經(jīng)啟動了。這里的ResolveInfo表示靜態(tài)廣播接收者對象。找到對象后判斷是否要跳過該廣播,如果跳過則通過執(zhí)行scheduleBroadcastsLocked方法發(fā)送消息執(zhí)行下一個(gè)廣播。如果不需要跳過該廣播時(shí),判斷該進(jìn)程是否存在,如果該靜態(tài)廣播的進(jìn)程已經(jīng)存在了則執(zhí)行processCurBroadcastLocked,將廣播發(fā)送給該進(jìn)程處理,如果不存在則啟動進(jìn)程,并且將廣播對象BroadcastRecord放入等待廣播列表中,如果啟動失敗則接受該廣播并判斷是否執(zhí)行下一個(gè)廣播,我們先將一下進(jìn)程存在時(shí)廣播的處理,最后再分析進(jìn)程啟動時(shí)的廣播處理。
21、processCurBroadcastLocked
// 這里只是將廣播發(fā)送到接收者進(jìn)程,需要一直等待接收者進(jìn)程處理完廣播后返回,AMS才能處理當(dāng)前BroadcastRecord
// 里面的下一個(gè)receiver,所以直接返回就行了,反正需要等待的。
private final void processCurBroadcastLocked(BroadcastRecord r,
ProcessRecord app) throws RemoteException {
...
// 將進(jìn)程的相關(guān)信息寫入當(dāng)前BroadcastRecord中相關(guān)的接收者
...
boolean started = false;
try {
...
// 處理廣播,等待接收進(jìn)程的返回
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);
...
} finally {
...
}
}
調(diào)用scheduleReceiver方法處理廣播。
22、ApplicationThread.scheduleReceiver
// 處理應(yīng)用進(jìn)程中接收到的靜態(tài)廣播消息,實(shí)際處理該廣播的是ActivityThread.handleReceiver函數(shù)
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 r = new ReceiverData(intent, resultCode, data, extras,
sync, false, mAppThread.asBinder(), sendingUser);
..
sendMessage(H.RECEIVER, r);
}
通過Handler消息處理機(jī)制調(diào)用handleReceiver方法處理該靜態(tài)廣播
23、ApplicationThread.handleReceiver
// 主要包括三步:
// 1) 創(chuàng)建BroadcastReceiver對象
// 2) 執(zhí)行onReceive函數(shù)
// 3) 向AMS發(fā)送處理結(jié)束消息
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();
// 1) 創(chuàng)建BroadcastReceiver對象
// 這里處理的是靜態(tài)廣播接收者,默認(rèn)認(rèn)為接收者BroadcastReceiver對象不存在
// 每次接受都會創(chuàng)建一個(gè)新的BroadcastReceiver對象
String component = data.intent.getComponent().getClassName();
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
IActivityManager mgr = ActivityManagerNative.getDefault();
BroadcastReceiver receiver;
try {
// 首先從AMS傳遞的intent中獲取當(dāng)前處理該廣播的組件名稱,然后通過反射創(chuàng)建一個(gè)BroadcastReceiver
// 對象,從這里可以看出來,靜態(tài)廣播處理的時(shí)候,每次都會創(chuàng)建一個(gè)新的BroadcastReceiver對象;
...
receiver = (BroadcastReceiver) cl.loadClass(component).newInstance();
} catch (Exception e) {
...
}
// 2) 執(zhí)行onReceive函數(shù)
try {
// 創(chuàng)建Application對象,如果進(jìn)程已經(jīng)啟動,Application對象已經(jīng)創(chuàng)建
Application app = packageInfo.makeApplication(false, mInstrumentation);
...
// 調(diào)用接收者的onReceive方法,這里還調(diào)用了setPendingResult方法,詳細(xì)內(nèi)容請看
// BroadcastReceiver.goAsync方法。
receiver.setPendingResult(data);
receiver.onReceive(context.getReceiverRestrictedContext(),
data.intent);
} catch (Exception e) {
...
} finally {
sCurrentBroadcastIntent.set(null);
}
// 3) 向AMS發(fā)送處理結(jié)束消息
if (receiver.getPendingResult() != null) {
data.finish();
}
}
上面最開始注釋寫了這里分為三步,創(chuàng)建BroadcastReceiver對象,執(zhí)行onReceive函數(shù),結(jié)束。這樣進(jìn)程存在時(shí)靜態(tài)廣播就發(fā)送完成了。最后我們分析需要啟動進(jìn)程時(shí)發(fā)送廣播的流程,我們先看一張時(shí)序圖。

在Android系統(tǒng)源碼分析--Process啟動過程一章我們分析了進(jìn)程啟動過程,在最后會調(diào)用ActivityThread.mian方法,我們從這個(gè)方法開始看:
0、ActivityThread.mian
/**
* 啟動新的進(jìn)程時(shí)調(diào)用Process的start方法會最終調(diào)用改函數(shù)
* 啟動新的進(jìn)程主要做了兩件事:
* 1.在進(jìn)程中創(chuàng)建了一個(gè)ActivityThread對象,并調(diào)用了它的成員函數(shù)attach向AMS發(fā)送一個(gè)啟動完成的通知
* 2.調(diào)用Looper類的靜態(tài)成員函數(shù)prepareMainLooper創(chuàng)建一個(gè)消息循環(huán),并且在向AMS發(fā)送啟動完成通知后,
* 使得當(dāng)前進(jìn)程進(jìn)入到這個(gè)消息循環(huán)中
*
* @param args
*/
public static void main(String[] args) {
...
ActivityThread thread = new ActivityThread();
thread.attach(false);
...
}
這里會初始化一個(gè)ActivityThread對象,然后調(diào)用該對象的attach方法,傳入?yún)?shù)false。
1、ActivityThread.attach
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
...
// 獲取AMS的代理對象,下面會調(diào)用它的成員函數(shù)attachApplication向AMS發(fā)送一個(gè)進(jìn)程間通信請求,并且
// 將前面所創(chuàng)建的ApplicationThread(mAppThread)對象傳遞給AMS
final IActivityManager mgr = ActivityManagerNative.getDefault();
try {
// 這里向ActivityManagerService注冊Client端的binder對象,它是一個(gè)binder線程
// ActivityManagerService中有關(guān)Activity聲明周期的消息都會發(fā)送到ActivityThread中的
// 主線程mH處理
// mAppThread是一個(gè)Binder本地對象,AMS是通過它來和應(yīng)用進(jìn)程通訊的。(AMS的代理對象類型為
// ActivityManagerProxy,因此,接下來會調(diào)用ActivityManagerProxy類的成員函數(shù)向AMS發(fā)送一個(gè)
// 進(jìn)程間通信請求)
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
...
} else {// system thread
...
}
...
}
我們上面接受了傳入?yún)?shù)是false,則會走if中的代碼,也就是會執(zhí)行mgr.attachApplication方法,通過注釋我們知道會調(diào)用ActivityManagerProxy.attachApplication方法,然后傳遞到ActivityManagerService.attachApplication方法。
2、ActivityManagerProxy.attachApplication
public void attachApplication(IApplicationThread app) throws RemoteException {
...
// 通過mRemote(Binder)向AMS發(fā)送一個(gè)類型為ATTACH_APPLICATION_TRANSACTION的進(jìn)程間通信請求
mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0);
...
}
3、ActivityManagerService.attachApplication
// 用來處理ActivityMangerProxy傳遞過來的類型為ATTACH_APPLICATION_TRANSACTION的進(jìn)程間通信請求
@Override
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
...
attachApplicationLocked(thread, callingPid);
...
}
}
這里調(diào)用attachApplicationLocked方法:
4、attachApplicationLocked
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
...
// Check if a next-broadcast receiver is in this process...
if (!badApp && isPendingBroadcastProcessLocked(pid)) {
try {
didSomething |= sendPendingBroadcastsLocked(app);
} catch (Exception e) {
// If the app died trying to launch the receiver we declare it 'bad'
Slog.wtf(TAG, "Exception thrown dispatching broadcasts in " + app, e);
badApp = true;
}
}
...
}
因?yàn)槲覀冞@里分析發(fā)送廣播,所以我們只關(guān)心廣播的相關(guān)處理,所以上面只保留了廣播的內(nèi)容,if語句中判斷當(dāng)前應(yīng)用沒有問題,并且有等待的廣播,才會調(diào)用sendPendingBroadcastsLocked方法,前面我們知道靜態(tài)廣播有一種是進(jìn)程不存在的,所以這個(gè)廣播就要放到等待廣播中,這里就開始處理等待廣播的情況。
5、sendPendingBroadcastsLocked
// The app just attached; send any pending broadcasts that it should receive
boolean sendPendingBroadcastsLocked(ProcessRecord app) {
boolean didSomething = false;
for (BroadcastQueue queue : mBroadcastQueues) {
didSomething |= queue.sendPendingBroadcastsLocked(app);
}
return didSomething;
}
mBroadcastQueues是包含前臺優(yōu)先級和后臺優(yōu)先級的廣播隊(duì)列,這里分別調(diào)用前臺和后臺優(yōu)先級廣播的BroadcastQueue.sendPendingBroadcastsLocked方法。
6、BroadcastQueue.sendPendingBroadcastsLocked
// 未啟動進(jìn)程的廣播接收者需要先啟動進(jìn)程,最后到達(dá)這個(gè)函數(shù)
public boolean sendPendingBroadcastsLocked(ProcessRecord app) {
boolean didSomething = false;
// 前面分析mPendingBroadcast用于存儲當(dāng)前正在等待進(jìn)程啟動的BroadcastRecord
final BroadcastRecord br = mPendingBroadcast;
if (br != null && br.curApp.pid == app.pid) {
...
try {
// 啟動完成設(shè)置為null
mPendingBroadcast = null;
processCurBroadcastLocked(br, app);
didSomething = true;
} catch (Exception e) {
...
}
}
return didSomething;
}
這里是找到等待處理的廣播并且判斷是否為空,并且是否和當(dāng)前進(jìn)程的pid相同,也就是是不是找個(gè)進(jìn)程的等待廣播,如果是就調(diào)用processCurBroadcastLocked方法進(jìn)行處理,這個(gè)方法在上面第21步中已經(jīng)講過,所以又回到了進(jìn)程存在的情況下廣播的處理。這樣整個(gè)廣播的處理就分析完了,代碼量很大,但是邏輯很清楚,只需要對著注釋多看看看就明白了。下一篇我們開始講Activity啟動的源碼分析。

為了方便記憶,這里添加一個(gè)發(fā)送廣播的流程圖,這樣對照著上面的代碼流程再看就會好理解很多。
注
首發(fā)地址:http://www.codemx.cn
Android開發(fā)群:192508518
微信公眾賬號:Code-MX
注:本文原創(chuàng),轉(zhuǎn)載請注明出處,多謝。