本篇文章的目錄
1谆趾、廣播數(shù)據(jù)結構分析
2、線程的切換
3袍睡、processNextBroadcast分析
- 3.1、處理并行廣播
- 3.2肋僧、處理Pending廣播
- 3.3斑胜、處理有序廣播
- 3.4、獲取下一條廣播
- 3.5嫌吠、檢查是否是動態(tài)廣播
- 3.6止潘、檢查是否是靜態(tài)廣播
- 3.7、啟動進程辫诅,處理未發(fā)送的靜態(tài)廣播
4凭戴、動態(tài)廣播receiver處理
5、靜態(tài)廣播receiver處理
先了解一下廣播的數(shù)據(jù)結構炕矮,然后在分析廣播的處理過程么夫。建議看本文,需要先看前面兩篇文章
Android源碼解析---廣播的注冊過程
Android源碼解析---廣播的處理過程
1肤视、廣播數(shù)據(jù)結構分析
final class BroadcastRecord extends Binder {
final Intent intent; // the original intent that generated us
final ComponentName targetComp; // original component name set on the intent
final ProcessRecord callerApp; // 廣播調(diào)用者進程
final String[] requiredPermissions; // 調(diào)用者需要的權限
final List receivers; //存儲廣播接收者档痪, 包含 BroadcastFilter 和 ResolveInfo
IIntentReceiver resultTo; // who receives final result if non-null
long enqueueClockTime; // 加入隊列的時間
long dispatchTime; // 分發(fā)時間
long dispatchClockTime; //分發(fā)時間
long receiverTime; // 接收時間.
long finishTime; ////廣播完成時間
int nextReceiver; // 下一個廣播接收者
IBinder receiver; //當前廣播接收者
int state;
int anrCount; //廣播ANR次數(shù)
ProcessRecord curApp; // hosting application of current receiver.
ComponentName curComponent; // the receiver class that is currently running.
ActivityInfo curReceiver; // info about the receiver that is currently running.
}
比較重要的數(shù)據(jù)成員有receivers,存儲的都是廣播接收器邢滑,callerApp是廣播調(diào)用者進程腐螟,還要注意四個時間點,有入隊列殊鞭,分發(fā)遭垛,接收,完成操灿,另外動態(tài)廣播節(jié)點用BroadcastFilter描述锯仪,靜態(tài)的用ResolveInfo描述。
ReceiverDispatcher: 客戶端廣播分發(fā)者對象趾盐,第一篇講的很清楚了庶喜,ReceiverDispatcher的內(nèi)部類InnerReceiver為binder對象小腊,用于與AMS的傳遞與通信。
ReceiverList: 繼承自ArrayList久窟,存放了Receiver的binder對象以及其注冊的BroadcastFilter列表秩冈。AMS中定義了
final HashMap<IBinder, ReceiverList> mRegisteredReceivers = new HashMap<>();key為InnerReceiver的binder對象,值為ReceiverList斥扛,ReceiverList內(nèi)部記錄的是動態(tài)注冊的廣播接收者入问,mRegisteredReceivers只有動態(tài)注冊的時候才會有內(nèi)容。BroadcastFilter: 封裝了IntentFilter稀颁,描述動態(tài)廣播芬失,是動態(tài)廣播節(jié)點。
ResolveInfo:Parcelable子類匾灶,描述靜態(tài)廣播棱烂,是靜態(tài)廣播節(jié)點。
IntentResolver: 解析Intent阶女,在addFilter時即進行解析颊糜。其內(nèi)部有mSchemeToFilter,mActionToFilter秃踩,mTypedActionToFilter三個map對象衬鱼。key為對應的action(scheme或者type),value為Filter吞瞪。
BroadcastRecord:描述一個廣播馁启, 將intent等一堆信息驾孔,封裝成BroadcastRecord芍秆,交給BroadcastQueue進行處理。
BroadcastQueue: BroadcastQueue為Broadcast處理隊列翠勉,分為前臺隊列mFgBroadcastQueue和后臺隊列mBgBroadcastQueue妖啥,mFgBroadcastQueue會有更高的權限,被優(yōu)先處理对碌。mFgBroadcastQueue和mBgBroadcastQueue兩個隊列中都含有mOrderedBroadcasts和mParallelBroadcasts兩個列表用來表示有序廣播列表和無序廣播列表荆虱。
2、線程的切換
上篇說到不管是有序廣播朽们、無序廣播還是粘性廣播最終都是調(diào)用scheduleBroadcastsLocked處理的怀读。那么scheduleBroadcastsLocked做了什么?
public void scheduleBroadcastsLocked() {
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Schedule broadcasts ["
+ mQueueName + "]: current="
+ mBroadcastsScheduled);
//mBroadcastsScheduled參數(shù)是用來標記是否已經(jīng)向消息隊列發(fā)送了一個類型為BROADCAST_INTENT_MSG消息
if (mBroadcastsScheduled) {
return;
}
//發(fā)送一個BROADCAST_INTENT_MSG消息
mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
mBroadcastsScheduled = true;
}
mHandler是BroadcastQueue的成員變量骑脱,定義如下
final BroadcastHandler mHandler;
它在BroadcastQueue構造函數(shù)中初始化
BroadcastQueue(ActivityManagerService service, Handler handler,
String name, long timeoutPeriod, boolean allowDelayBehindServices) {
mService = service;
mHandler = new BroadcastHandler(handler.getLooper());
mQueueName = name;
mTimeoutPeriod = timeoutPeriod;
mDelayBehindServices = allowDelayBehindServices;
}
參數(shù)中的handler是AMS中的MainHandler菜枷,所以BroadcastHandler采用的是ActivityManager線程的Looper,所以通過上面發(fā)送一個BROADCAST_INTENT_MSG消息叁丧,現(xiàn)在由system_server的binder線程切換到system_server的ActivityManager線程中啤誊。
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) {
//超時的時候走這里
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;
}
}
}
所以現(xiàn)在重點分析processNextBroadcast方法岳瞭。
3、processNextBroadcast分析
processNextBroadcast方法的代碼跟broadcastIntentLocked方法一樣蚊锹,也是很長瞳筏,所以分段來分析。
3.1牡昆、處理并行廣播
mService.updateCpuStats();
//fromMsg字段標記是否是從handleMessage中調(diào)用的該方法
if (fromMsg) {
//設置該參數(shù)為false姚炕,表示前面發(fā)送到消息隊列中的BROADCAST_INTENT_MSG消息已經(jīng)被處理了
mBroadcastsScheduled = false;
}
//并行廣播在這里循環(huán)一次性處理掉
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發(fā)送出去的,此時r.receivers里面的都是BroadcastFilter
deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
}
addBroadcastToHistoryLocked(r);
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["
+ mQueueName + "] " + r);
}
3.2丢烘、處理Pending廣播
如果一個廣播在發(fā)送的時候钻心,進程還沒有啟動起來,那么會將它存在mPendingBroadcast中铅协。由于動態(tài)廣播是不會保證一定能夠收到的捷沸,所以mPendingBroadcast是用來描述一個正在等待靜態(tài)注冊的目標廣播接收者啟動的廣播。
// Now take care of the next serialized one...
// 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;
// 檢查這個靜態(tài)注冊的目標廣播接收者所運行在的應用程序進程是否已經(jīng)啟動起來
synchronized (mService.mPidsSelfLocked) {
ProcessRecord proc = mService.mPidsSelfLocked.get(mPendingBroadcast.curApp.pid);
isDead = proc == null || proc.crashing;
}
如果這個應用程序進程還活著狐史,就會繼續(xù)等待痒给,否則就不等了
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;
3.3、處理有序廣播
有序廣播是一個接著一個處理的骏全,并且還可以攔截苍柏,
do {
//有序廣播隊列為0,不用處理姜贡,返回
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.
//更改一下OOM
mService.updateOomAdjLocked();
}
return;
}
//獲取一個有序廣播(最頂部的BroadcastRecord)
r = mOrderedBroadcasts.get(0);
boolean forceReceive = false;
//廣播超時處理试吁,這個會在下一節(jié)具體分析
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;
//恢復初始狀態(tài)楼咳。
r.state = BroadcastRecord.IDLE;
}
}
if (r.state != BroadcastRecord.IDLE) {
if (DEBUG_BROADCAST) Slog.d(TAG_BROADCAST,
"processNextBroadcast("
+ mQueueName + ") called when not idle (state="
+ r.state + ")");
return;
}
// 進入下面的條件有以下集中可能熄捍,一:廣播沒有接收者了,二:默認第一次r.nextReceiver = 0,但是它每次都會++母怜,等待最后一個處理完了余耽,再++就會得到一個不存在的nextReceiver,此時r.nextReceiver >= numReceivers苹熏,條件成立碟贾,三:
廣播是否已經(jīng)被攔截了,四:廣播是否已經(jīng)被強制結束了
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);
//處理廣播消息消息轨域,調(diào)用到onReceive()
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");
//r所描述的廣播轉發(fā)任務已經(jīng)在規(guī)定時間內(nèi)處理完了袱耽,需要remove掉前面給mHandler發(fā)送的BROADCAST_TIMEOUT_MSG消息。
cancelBroadcastTimeoutLocked();
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
"Finished with ordered broadcast " + r);
// ... and on to the next...
addBroadcastToHistoryLocked(r);
if (r.intent.getComponent() == null && r.intent.getPackage() == null
&& (r.intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
// This was an implicit broadcast... let's record it for posterity.
mService.addBroadcastStatLocked(r.intent.getAction(), r.callerPackage,
r.manifestCount, r.manifestSkipCount, r.finishTime-r.dispatchTime);
}
// 將r所描述的廣播轉發(fā)任務從有序廣播隊列中刪除
mOrderedBroadcasts.remove(0);
//賦值為null干发,進入下一次循環(huán)
r = null;
looped = true;
continue;
}
} while (r == null);
3.4朱巨、獲取下一條廣播
//通過上面的循環(huán),r就有值了铐然,獲取下一條廣播
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();
if (recIdx == 0) {
r.dispatchTime = r.receiverTime;
r.dispatchClockTime = System.currentTimeMillis();
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing ordered broadcast ["
+ mQueueName + "] " + r);
}
if (! mPendingBroadcastTimeoutMessage) {
long timeoutTime = r.receiverTime + mTimeoutPeriod;
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Submitting BROADCAST_TIMEOUT_MSG ["
+ mQueueName + "] for " + r + " at " + timeoutTime);
setBroadcastTimeoutLocked(timeoutTime);
}ComponentName component
final BroadcastOptions brOptions = r.options;
final Object nextReceiver = r.receivers.get(recIdx);
3.5蔬崩、檢查是否是動態(tài)廣播
//檢查是否是動態(tài)廣播
if (nextReceiver instanceof BroadcastFilter) {
BroadcastFilter filter = (BroadcastFilter)nextReceiver;
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Delivering ordered ["
+ mQueueName + "] to registered "
+ filter + ": " + r);
//動態(tài)注冊的廣播給deliverToRegisteredReceiverLocked處理
deliverToRegisteredReceiverLocked(r, filter, r.ordered, recIdx);
//判斷是否是無序廣播
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恶座,表示不需要等待它的前一個目標廣播接收者處理完成一個廣播,
// 就可以將該廣播繼續(xù)發(fā)送給它的下一個目標廣播接收者處理
r.state = BroadcastRecord.IDLE;
//執(zhí)行下一個廣播沥阳,內(nèi)部也是發(fā)送消息
scheduleBroadcastsLocked();
} else {
....
}
//有序廣播一次只處理一個跨琳,直接返回就行
return;
}
3.6、檢查是否是靜態(tài)廣播
//如果上面沒有return,那么肯定是靜態(tài)注冊的廣播桐罕,靜態(tài)注冊注冊的廣播節(jié)點是ResolveInfo
ResolveInfo info = (ResolveInfo)nextReceiver;
//這個ComponentName會一直傳遞到ActivityThread脉让,用來反射new廣播接收者對象的
ComponentName component = new ComponentName(
info.activityInfo.applicationInfo.packageName,
info.activityInfo.name);
//很多的條件判斷,skip不滿足就為true
boolean skip = false;
.......
String targetProcess = info.activityInfo.processName;
ProcessRecord app = mService.getProcessRecordLocked(targetProcess,
info.activityInfo.applicationInfo.uid, false);
if (skip) {
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Skipping delivery of ordered [" + mQueueName + "] "
+ r + " for whatever reason");
r.delivery[recIdx] = BroadcastRecord.DELIVERY_SKIPPED;
r.receiver = null;
r.curFilter = null;
//變成初始狀態(tài)
r.state = BroadcastRecord.IDLE;
//執(zhí)行下個廣播
scheduleBroadcastsLocked();
return;
}
.......
//如果當前進程存在功炮,調(diào)用processCurBroadcastLocked處理溅潜,靜態(tài)廣播都是走processCurBroadcastLocked處理的
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.
}
//程序走到這里薪伏,說明進程不存在滚澜,那么調(diào)用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);
//啟動失敗就執(zhí)行下一個
scheduleBroadcastsLocked();
r.state = BroadcastRecord.IDLE;
return;
}
//把當前的r存下來嫁怀,方便下一次處理
mPendingBroadcast = r;
//設置當前的receiver的索引,用來表示將要啟動的设捐。
mPendingBroadcastRecvIndex = recIdx;
3.7、啟動進程塘淑,處理未發(fā)送的靜態(tài)廣播
當進程啟動完成之后萝招,會回調(diào)AMS的attachApplication,然后走到attachApplicationLocked存捺。
// 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;
}
}
// 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;
}
public boolean sendPendingBroadcastsLocked(ProcessRecord app) {
boolean didSomething = false;
final BroadcastRecord br = mPendingBroadcast;
if (br != null && br.curApp.pid == app.pid) {
if (br.curApp != app) {
Slog.e(TAG, "App mismatch when sending pending broadcast to "
+ app.processName + ", intended target is " + br.curApp.processName);
return false;
}
try {
//目標進程已經(jīng)成功啟動了槐沼,那么mPendingBroadcast就可以賦值為null了
mPendingBroadcast = null;
//調(diào)用processCurBroadcastLocked處理廣播
processCurBroadcastLocked(br, app);
didSomething = true;
} catch (Exception e) {
Slog.w(TAG, "Exception in new application when starting receiver "
+ br.curComponent.flattenToShortString(), e);
logBroadcastReceiverDiscardLocked(br);
finishReceiverLocked(br, br.resultCode, br.resultData,
br.resultExtras, br.resultAbort, false);
scheduleBroadcastsLocked();
// We need to reset the state if we failed to start the receiver.
br.state = BroadcastRecord.IDLE;
throw new RuntimeException(e.getMessage());
}
}
return didSomething;
}
看完上面的三個小節(jié),到這里總結一下 processNextBroadcast()的代碼邏輯:
- 如果是動態(tài)廣播接收者(無序)捌治,會調(diào)用deliverToRegisteredReceiverLocked一次性處理岗钩,即遍歷并行列表(mParallelBroadcasts)的每一個BroadcastRecord以及其中的receivers列表,是一個雙重循環(huán)具滴。
- 如果是靜態(tài)廣播接收者(有序)凹嘲,且對應進程已經(jīng)創(chuàng)建,會調(diào)用processCurBroadcastLocked繼續(xù)處理构韵;
- 如果是靜態(tài)廣播接收者(有序),且對應進程尚未創(chuàng)建趋艘,會調(diào)用startProcessLocked創(chuàng)建進程疲恢,之后仍然會調(diào)用processCurBroadcastLocked繼續(xù)處理。
4瓷胧、動態(tài)廣播receiver處理
上面主要分析了動態(tài)廣播接收者和靜態(tài)廣播接收者該如何處理显拳,現(xiàn)在先看動態(tài)廣播是如何處理的。就是分析deliverToRegisteredReceiverLocked方法實現(xiàn)搓萧。
private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
BroadcastFilter filter, boolean ordered, int index) {
boolean skip = false;
//權限判斷杂数, 檢查發(fā)送者是否有權限宛畦,檢查接收者是否有發(fā)送者所需的權限等等,
//此處省略揍移,不符合的skip==true,下面就return次和。
....
if (skip) {
r.delivery[index] = BroadcastRecord.DELIVERY_SKIPPED;
return;
}
....
//只有有序廣播才會進入這個分支
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);
if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {
// Skip delivery if full backup in progress
// If it's an ordered broadcast, we need to continue to the next receiver.
if (ordered) {
skipReceiverLocked(r);
}
} else {
//處理廣播,filter.receiverList.receiver對應的是客戶端ReceiverDispatcher的Binder實體——InnerReceiver
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) {
....
}
}
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) {
try {
//終于走到ActivityThread里面了
app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
data, extras, ordered, sticky, sendingUser, app.repProcState);
} catch (RemoteException ex) {
.....
}
} else {
// Application has died. Receiver doesn't exist.
throw new RemoteException("app.thread must not be null");
}
} else {
//調(diào)用者進程不存在那伐,則執(zhí)行該分支
receiver.performReceive(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
}
}
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);
//走到ReceiverDispatcher中的performReceive實際是InnerReceiver內(nèi)部類當中的方法
receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
sticky, sendingUser);
}
終于走到客戶端的ReceiverDispatcher(廣播分發(fā)者)了踏施,ReceiverDispatcher知道我們這個廣播要分發(fā)給誰。此時正式由SystemServer進程回到客戶端進程了罕邀。
@Override
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
final LoadedApk.ReceiverDispatcher rd;
......
if (rd != null) {
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) {
throw e.rethrowFromSystemServer();
}
}
}
可以看到我們調(diào)用ReceiverDispatcher中InnerReceiver的performReceive之后畅形,緊接著在內(nèi)部調(diào)用了ReceiverDispatcher的performReceive方法,再看ReceiverDispatcher的performReceive方法诉探。
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
final Args args = new Args(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
if (intent == null) {
Log.wtf(TAG, "Null intent received");
} else {
if (ActivityThread.DEBUG_BROADCAST) {
int seq = intent.getIntExtra("seq", -1);
Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction()
+ " seq=" + seq + " to " + mReceiver);
}
}
//post了一個消息給主線程
if (intent == null || !mActivityThread.post(args)) {
if (mRegistered && ordered) {
IActivityManager mgr = ActivityManagerNative.getDefault();
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing sync broadcast to " + mReceiver);
///發(fā)送完成本次廣播處理日熬,用來進行下次的廣播處理。
args.sendFinished(mgr);
}
}
}
上面的mActivityThread在第一篇文章說過肾胯,代表主線程碍遍,所以現(xiàn)在會執(zhí)行args的run方法。
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;
if (intent == null) {
Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched);
}
......
try {
ClassLoader cl = mReceiver.getClass().getClassLoader();
intent.setExtrasClassLoader(cl);
intent.prepareToEnterProcess();
setExtrasClassLoader(cl);
receiver.setPendingResult(this);
//onReceive方法回調(diào)
receiver.onReceive(mContext, intent);
} catch (Exception e) {
.....
}
到此阳液,deliverToRegisteredReceiverLocked是怎么處理動態(tài)廣播就分析完畢了怕敬。總結一下主要流程
------|-BroadcastQueue.performReceiveLocked()
------|-------|-ActivityThread.ApplicationThread.scheduleRegisteredReceiver()
------|-------|-------|- ReceiverDispatcher.InnerReceiver.performReceive()
------|-------|-------|-------|-Handler.post(args)
------|-------|-------|-------|-------|-Args.run()
------|-------|-------|-------|-------|-------|-BroadcastReceiver.onReceive()
5帘皿、靜態(tài)廣播receiver處理
剛剛說了靜態(tài)廣播是processCurBroadcastLocked處理的
private final void processCurBroadcastLocked(BroadcastRecord r,
ProcessRecord app) throws RemoteException {
.....
r.receiver = app.thread.asBinder();
r.curApp = app;
app.curReceiver = r;
//更新進程狀態(tài)
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
//更新內(nèi)存
mService.updateLruProcessLocked(app, false, null);
//更新adj
mService.updateOomAdjLocked();
// Tell the application to launch this receiver.告訴客戶端啟動這個receiver
r.intent.setComponent(r.curComponent);
boolean started = false;
try {
.....
//走到了ActivityThread中的ApplicationThread中對應的方法东跪。
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 {
.....
}
}
}
此時正式由SystemServer進程進入了客戶端進程了
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);
r.info = info;
r.compatInfo = compatInfo;
sendMessage(H.RECEIVER, r);
}
一樣的套路,發(fā)送一個消息給主線程鹰溜,進入對應的case,執(zhí)行 handleReceiver((ReceiverData)msg.obj)虽填;
private void handleReceiver(ReceiverData data) {
// 這個最初就是在processNextBroadcast處理靜態(tài)注冊的ResolveInfo時,new的ComponentName曹动。
String component = data.intent.getComponent().getClassName();
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
IActivityManager mgr = ActivityManagerNative.getDefault();
BroadcastReceiver receiver;
try {
//反射出BroadcastReceiver
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);
//這個和動態(tài)的不一樣斋日,靜態(tài)的廣播onReceive方法中的context是RestrictedContext
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) {
data.finish();
}
}
到這總結一下靜態(tài)廣播接收者的處理流程,如下:
如果應用程序已經(jīng)啟動(app.thread != null)
------|-ActivityThread.ApplicationThread.scheduleReceiver()
------|------|- ActivityThread.handleReceiver()
------|-------|-------|- BroadcastReceiver.onReceive()
否則
------|-LoadedApk.ReceiverDispatcher.IntentReceiver.performReceive()
------|-------|-LoadedApk.ReceiverDispatcher.performReceiver()
------|-------|-------|- LoadedApk.ReceiverDispatcher.Args.run()
------|-------|-------|-------|-BroadcastReceiver.onReceive()
至此廣播的處理過程就結束了墓陈,下篇寫一下廣播細節(jié)恶守,加深理解,比如廣播有序是怎么保證的贡必?怎么實現(xiàn)廣播攔截處理的?廣播超時是怎么處理的?onReceive方法中可以在發(fā)送廣播嗎?registerReceiver方法發(fā)返回值有什么用?粘性廣播等等