這篇文章主要是接著上面兩篇文章的:
1.注冊廣播接收者的源碼分析;
2.廣播發(fā)送過程源碼解析
到這里這篇,廣播也就完成了,下一篇我們會來說說ContentProvider的相關(guān)源碼,然后四大組件的源碼分析也就完成了,接著我們會來分析資源的加載,類的加載過程等,這些插件化必需的知識,最后我們會來剖析一個插件化的框架,大家敬請期待哈。
一.源碼解析
緊接著上一篇講到BroadcastQueue#processNextBroadcast()
方法,我們就從這里開始出發(fā)。這個方法很長,我們一步一步來看。
1.處理并行廣播
// First, deliver any non-serialized broadcasts right away.
//馬上處理掉所有的并行廣播
while (mParallelBroadcasts.size() > 0) {
r = mParallelBroadcasts.remove(0);
r.dispatchTime = SystemClock.uptimeMillis();
r.dispatchClockTime = System.currentTimeMillis();
//并行廣播的receivers中是BroadcastFilter類型對象
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);
//這是發(fā)送廣播,這里的target是BroadcastFilter類型
deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
}
addBroadcastToHistoryLocked(r);
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["
+ mQueueName + "] " + r);
}
之前的文章我們知道,我們的動態(tài)注冊的廣播都是放在并行隊列里面,所以程序這里會取出所有的并行隊列中的BrocastRecord
類型對象,然后取出對象里面的receivers,這里是一個BroadcastFilter
集合對象。然后一一發(fā)送。這里我們具體來看下deliverToRegisteredReceiverLocked()
方法的具體處理流程。
2.動態(tài)注冊廣播發(fā)送
private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
BroadcastFilter filter, boolean ordered, int index) {
boolean skip = false;
//這里省略了權(quán)限檢查代碼。如果設(shè)置了權(quán)限的話,這里就會檢查發(fā)送者是否有權(quán)限,有的話,就會判斷接收者是否有發(fā)送者的權(quán)限,
//沒有的話就會skip設(shè)置為true,如果有的話會調(diào)用noteOperation判斷是否權(quán)限被禁止了
.........
//有序廣播處理邏輯,因為我們這里是無序廣播,所以不會進(jìn)入這個操作
if (ordered) {
//這里的filter.receiverList.receiver.asBinder()得到的就是客戶端ReceiverDispatcher中的InnerReceiver這個Binder實體
r.receiver = filter.receiverList.receiver.asBinder();
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) {
......
} else {
//我們程序會走到這里,這里就是處理廣播的地方
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) {
.......
}
}
如果對上面的權(quán)限判斷不是很了解,這里推薦一篇Android權(quán)限管理原理,這篇文章還是非常不錯的,講的很清楚。我們看到我們無序廣播處理的地方是performReceiveLocked()
方法,里面filter.receiverList.receiver
就是對應(yīng)的客戶端ReceiverDispatcher
中的InnerReceiver
這個Binder實體。
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) {//判斷app.thread(這里是ActivityThread的ApplicationThreadProxy)是否不為空
try {
//實際就是調(diào)用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 {
receiver.performReceive(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
}
}
我們看到這個方法會調(diào)用到ActivityThread
中間的scheduleRegisteredReceiver()
方法:
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
int resultCode, String dataStr, Bundle extras, boolean ordered,
boolean sticky, int sendingUser, int processState) throws RemoteException {
updateProcessState(processState, false);
receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
sticky, sendingUser);
}
這里的receiver
我們在注冊廣播接收者的源碼分析這篇文章中可以知道,receiver是LoadedApk#ReceiverDispatcher#InnerReceiver
對象。所以這里會調(diào)用到InnerReceiver
的performReceive()
方法:
@Override
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
final LoadedApk.ReceiverDispatcher rd;
if (intent == null) {
Log.wtf(TAG, "Null intent received");
rd = null;
} else {
rd = mDispatcher.get();
}
if (ActivityThread.DEBUG_BROADCAST) {
int seq = intent.getIntExtra("seq", -1);
}
if (rd != null) {
rd.performReceive(intent, resultCode, data, extras,
ordered, sticky, sendingUser);
} else {
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();
}
}
}
這里看到我們這個方法內(nèi)部會調(diào)用ReceiverDispatcher
的performReceive()
方法,所以我們繼續(xù)往下跟:
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);
}
}
//這里處理消息的方式是通過Handler.post函數(shù)進(jìn)行的,post函數(shù)的參數(shù)是Runnable類型的,這個消息最終會調(diào)用這個這個參數(shù)的run成員函數(shù)來處理
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ā)送完成本次廣播處理,用來進(jìn)行下次的廣播處理
args.sendFinished(mgr);
}
}
}
我們看到這個方法里面會調(diào)用mActivityThread
即一個Handler
的post方法,post方法里面的參數(shù)是一個Runnable
對象,所以我們知道會調(diào)用這個Runnable
對象的run方法:
public void run() {
final BroadcastReceiver receiver = mReceiver;
final boolean ordered = mOrdered;
.....
final IActivityManager mgr = ActivityManagerNative.getDefault();
final Intent intent = mCurIntent;
if (intent == null) {
Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched);
}
mCurIntent = null;
mDispatched = true;
if (receiver == null || intent == null || mForgotten) {
if (mRegistered && ordered) {
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing null broadcast to " + mReceiver);
sendFinished(mgr);
}
return;
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");
try {
ClassLoader cl = mReceiver.getClass().getClassLoader();
intent.setExtrasClassLoader(cl);
intent.prepareToEnterProcess();
setExtrasClassLoader(cl);
receiver.setPendingResult(this);
receiver.onReceive(mContext, intent);
} catch (Exception e) {
.......
}
if (receiver.getPendingResult() != null) {
finish();
}
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
這里的mReceiver
就是ReceiverDispatcher
對象的成員變量,它是一個BroadcastReceiver
類型,這里它就是Activity注冊廣播接收器時創(chuàng)建的BroadcastReceiver
實例了。有了ReceiverDispatcher
就可以回調(diào)他的onReceive
方法了。這樣的話,到這里動態(tài)注冊廣播的處理也就完成了。這樣的話我們繼續(xù)來看processNextBroadcast()
方法。
3.處理pending廣播
//目標(biāo)進(jìn)程如果不存在,那么會啟動進(jìn)程,因為啟動進(jìn)程是耗時的工作,則會先把廣播放在mPendingBroadcast中
if (mPendingBroadcast != null) {
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
"processNextBroadcast [" + mQueueName + "]: waiting for "
+ mPendingBroadcast.curApp);
boolean isDead;
synchronized (mService.mPidsSelfLocked) {
// 檢查這個靜態(tài)注冊的目標(biāo)廣播接收者所運(yùn)行在的應(yīng)用程序進(jìn)程是否已經(jīng)啟動起來
ProcessRecord proc = mService.mPidsSelfLocked.get(mPendingBroadcast.curApp.pid);
isDead = proc == null || proc.crashing;
}
// 如果這個應(yīng)用程序進(jìn)程還活著,就會繼續(xù)等待,否則就不等了
if (!isDead) {
// It's still alive, so keep waiting
return;
} else {
mPendingBroadcast.state = BroadcastRecord.IDLE;
mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
mPendingBroadcast = null;
}
}
boolean looped = false;
目標(biāo)進(jìn)程如果不存在,那么會啟動進(jìn)程,因為啟動進(jìn)程是耗時的工作,則會先把廣播放在mPendingBroadcast
中。
4.有序廣播處理
do {
//是否存在有序廣播
if (mOrderedBroadcasts.size() == 0) {
// No more broadcasts pending, so all done!
mService.scheduleAppGcsLocked();
if (looped) {
//這是AMS的內(nèi)存回收方法
mService.updateOomAdjLocked();
}
return;
}
//這里是獲取一個有序廣播,在循環(huán)的最后會remove,也就是說這里是從mOrderedBroadcasts
//中循環(huán)取出有序廣播
r = mOrderedBroadcasts.get(0);
boolean forceReceive = false;
int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
//這里是超時的處理機(jī)制
if (mService.mProcessesReady && r.dispatchTime > 0) {
long now = SystemClock.uptimeMillis();
//dispatchTime為廣播發(fā)送的起始時間+mTimeoutPeriod這是由BroadcastQueue
//類型決定的,為10秒和60秒*2*有序廣播數(shù)量(也就是說只要整體的廣播發(fā)送事件不超過這個事件
//就不會報ANR)
if ((numReceivers > 0) &&
(now > r.dispatchTime + (2*mTimeoutPeriod*numReceivers))) {
Slog.w(TAG, "Hung broadcast ["
+ mQueueName + "] discarded after timeout failure:"
+ " now=" + now
+ " dispatchTime=" + r.dispatchTime
+ " startTime=" + r.receiverTime
+ " intent=" + r.intent
+ " numReceivers=" + numReceivers
+ " nextReceiver=" + r.nextReceiver
+ " state=" + r.state);
//廣播超時,則廣播
broadcastTimeoutLocked(false); // forcibly finish this broadcast
forceReceive = true;
r.state = BroadcastRecord.IDLE;
}
}
if (r.state != BroadcastRecord.IDLE) {
if (DEBUG_BROADCAST) Slog.d(TAG_BROADCAST,
"processNextBroadcast("
+ mQueueName + ") called when not idle (state="
+ r.state + ")");
return;
}
//沒有廣播接收者了,或者廣播被攔截或者被強(qiáng)制結(jié)束則進(jìn)入這個處理
if (r.receivers == null || r.nextReceiver >= numReceivers
|| r.resultAbort || forceReceive) {
// No more receivers for this broadcast! Send the final
// result if requested...
//如果沒有更多的廣播,那么久發(fā)送最后一條
if (r.resultTo != null) {
try {
////處理廣播消息消息,調(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) {
.......
}
}
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Cancelling BROADCAST_TIMEOUT_MSG");
//如果前面發(fā)送的廣播已經(jīng)完成了,那么需要remove掉前面發(fā)送的超時消息
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);
}
mOrderedBroadcasts.remove(0);
r = null;
looped = true;
//進(jìn)入下一次循環(huán)
continue;
}
} while (r == null);
我們看到這個方法主要是判斷是否超時了,如果這些條件都沒有的話,就會返回r取到隊列中的一個有序廣播,然后就會進(jìn)入處理程序內(nèi)容。
5.動態(tài)廣播處理
// Get the next receiver...
//獲取下一個廣播
int recIdx = r.nextReceiver++;
// Keep track of when this receiver started, and make sure there
// is a timeout message pending to kill it if need be.
r.receiverTime = SystemClock.uptimeMillis();
if (recIdx == 0) {//沒有下一個廣播則設(shè)置開始時間
r.dispatchTime = r.receiverTime;
r.dispatchClockTime = System.currentTimeMillis();
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing ordered broadcast ["
+ mQueueName + "] " + r);
}
if (! mPendingBroadcastTimeoutMessage) {//如果已經(jīng)超時則關(guān)閉廣播
long timeoutTime = r.receiverTime + mTimeoutPeriod;
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Submitting BROADCAST_TIMEOUT_MSG ["
+ mQueueName + "] for " + r + " at " + timeoutTime);
setBroadcastTimeoutLocked(timeoutTime);
}
final BroadcastOptions brOptions = r.options;
final Object nextReceiver = r.receivers.get(recIdx);
if (nextReceiver instanceof BroadcastFilter) {//判斷是動態(tài)注冊還是靜態(tài)注冊廣播
// Simple case: this is a registered receiver who gets
// a direct call.
BroadcastFilter filter = (BroadcastFilter)nextReceiver;
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Delivering ordered ["
+ mQueueName + "] to registered "
+ filter + ": " + r);
//如果是動態(tài)注冊廣播則調(diào)用deliverToRegisteredReceiverLocked發(fā)送
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 = BroadcastRecord.IDLE;
//則直接執(zhí)行下一個廣播,不需要等待前一個廣播完成
scheduleBroadcastsLocked();
} else {
if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {
scheduleTempWhitelistLocked(filter.owningUid,
brOptions.getTemporaryAppWhitelistDuration(), r);
}
}
return;
}
我們看到這個方法里面會取出下一個廣播,然后判斷是不是動態(tài)注冊廣播,如果是的話就會直接調(diào)用deliverToRegisteredReceiverLocked
方法發(fā)送,這個方法前面2.動態(tài)注冊廣播發(fā)送已經(jīng)講過了。
6.靜態(tài)廣播處理
//因為前面的動態(tài)廣播處理都完成了,剩下的就是靜態(tài)廣播了
ResolveInfo info =
(ResolveInfo)nextReceiver;
ComponentName component = new ComponentName(
info.activityInfo.applicationInfo.packageName,
info.activityInfo.name);
boolean skip = false;
//省略了很多skip標(biāo)志位重設(shè)的判斷
.......
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;
//如果要跳過的話那么就直接執(zhí)行下一個廣播
r.state = BroadcastRecord.IDLE;
scheduleBroadcastsLocked();
return;
}
......
// Is this receiver's application already running?
if (app != null && app.thread != null) {
try {
app.addPackage(info.activityInfo.packageName,
info.activityInfo.applicationInfo.versionCode, mService.mProcessStats);
//如果接收者的應(yīng)用存在且在運(yùn)行的話那么就調(diào)用這個方法處理這個靜態(tài)廣播
processCurBroadcastLocked(r, app);
return;
} catch (RemoteException e) {
......
} catch (RuntimeException e) {
......
}
// If a dead object exception was thrown -- fall through to
// restart the application.
}
// Not running -- get it started, to be executed when the app comes up.
//接收者進(jìn)程沒有啟動那么就啟動進(jìn)程,當(dāng)然之后進(jìn)程啟動完畢還是會調(diào)用processCurBroadcastLocked來啟動
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);
finishReceiverLocked(r, r.resultCode, r.resultData,
r.resultExtras, r.resultAbort, false);
//執(zhí)行下一個廣播
scheduleBroadcastsLocked();
r.state = BroadcastRecord.IDLE;
return;
}
mPendingBroadcast = r;
mPendingBroadcastRecvIndex = recIdx;
}
我們看到靜態(tài)廣播處理會調(diào)用processCurBroadcastLocked()
方法進(jìn)行發(fā)送,所以我們來看看這個方法。
8.靜態(tài)廣播發(fā)送
private final void processCurBroadcastLocked(BroadcastRecord r,
ProcessRecord app) throws RemoteException {
.....
r.receiver = app.thread.asBinder();
r.curApp = app;
app.curReceiver = r;
//更新進(jìn)程狀態(tài)為PROCESS_STATE_RECEIVER
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
//AMS更新內(nèi)存
mService.updateLruProcessLocked(app, false, null);
//該方法的作用是告訴OOMKiller指定進(jìn)程的優(yōu)先級,值越小越重要,該函數(shù)的返回值是boolean類型,
//如果底層linux包含OOMKiller則返回true,否則返回false
//也就是提升優(yōu)先級
mService.updateOomAdjLocked();
// Tell the application to launch this receiver.
r.intent.setComponent(r.curComponent);
boolean started = false;
try {
mService.notifyPackageUse(r.intent.getComponent().getPackageName(),
PackageManager.NOTIFY_PACKAGE_USE_BROADCAST_RECEIVER);
//這里同上面的2.動態(tài)廣播發(fā)送有點(diǎ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);
started = true;
} finally {
if (!started) {
r.receiver = null;
r.curApp = null;
app.curReceiver = null;
}
}
}
這里我們看到最終靜態(tài)廣播發(fā)送也會發(fā)送到ActivityThread
的scheduleReceiver()
方法中,具體流程與動態(tài)注冊廣播類似,這里就不贅述了。到這里動態(tài)廣播與靜態(tài)廣播發(fā)送處理都完成了。
總結(jié):廣播的發(fā)送和處理還是比較繁瑣的,里面的一些東西也有我理解比較淺顯的,希望大家體諒,如果大家有更好的理解可以教教我,希望大家共同進(jìn)步哈。