動態(tài)注冊過程
ContextWrapper#registerReceiver(以下代碼基于API26)
動態(tài)注冊的過程從ContextWrapper的registerReceiver方法開始
@Override
public Intent registerReceiver(
BroadcastReceiver receiver, IntentFilter filter) {
return mBase.registerReceiver(receiver, filter);
}
和Activity、Service一樣,ContextWrapper沒有做任何操作,而是把任務(wù)交給了ContextImpl(mBase的實(shí)現(xiàn)類型是ContextImpl)來完成。接著看ContextImpl的registerReceiver方法。
ContextImpl#registerReceiver
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
return registerReceiver(receiver, filter, null, null);
}
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
String broadcastPermission, Handler scheduler) {
return registerReceiverInternal(receiver, getUserId(),
filter, broadcastPermission, scheduler, getOuterContext(), 0);
}
又調(diào)用自己的registerReceiverInternal方法
ContextImpl#registerReceiverInternal
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
IntentFilter filter, String broadcastPermission,
Handler scheduler, Context context, int flags) {
IIntentReceiver rd = null;
//廣播接收器不為空時,獲取IIntentReceiver對象(IIntentReceiver是一個Binder接口)
if (receiver != null) {
if (mPackageInfo != null && context != null) {
//...
rd = mPackageInfo.getReceiverDispatcher(
receiver, context, scheduler,
mMainThread.getInstrumentation(), true);
} else {
//...
rd = new LoadedApk.ReceiverDispatcher(
receiver, context, scheduler, null, true).getIIntentReceiver();
}
}
try {
//通過AMS的registerReceiver方法注冊廣播
final Intent intent = ActivityManager.getService().registerReceiver(
mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
broadcastPermission, userId, flags);
//...
return intent;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
為什么需要先將BroadcastReceiver轉(zhuǎn)化為IIntentReceiver?
因?yàn)閺V播的注冊過程是一個進(jìn)程間通信的進(jìn)程,而BroadcastReceiver是Android的一個組件,不能直接跨進(jìn)程傳遞,而IIntentReceiver是一個Binder接口,可以跨進(jìn)程,所以需要先將BroadcastReceiver轉(zhuǎn)化為IIntentReceiver。
下面看一下IIntentReceiver的獲取,無論是哪種情況,最后都是調(diào)用LoadedApk.ReceiverDispatcher的getIIntentReceiver方法
LoadedApk.ReceiverDispatcher#getIIntentReceiver
IIntentReceiver getIIntentReceiver() {
return mIIntentReceiver;
}
其中mIIntentReceiver是一個IIntentReceiver.Stub對象
final IIntentReceiver.Stub mIIntentReceiver;
mIIntentReceiver是在ReceiverDispatcher的構(gòu)造方法中初始化的
ReceiverDispatcher(BroadcastReceiver receiver, Context context,
Handler activityThread, Instrumentation instrumentation,
boolean registered) {
//...
mIIntentReceiver = new InnerReceiver(this, !registered);
//...
}
可以看到,最終IIntentReceiver的實(shí)現(xiàn)類是LoadedApk.ReceiverDispatcher.InnerReceiver
繼續(xù)看回注冊過程:
//ActivityManager.getService()返回的是ActivityManagerService對象
final Intent intent = ActivityManager.getService().registerReceiver(
mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
broadcastPermission, userId, flags);
//...
return intent;
可以看到,注冊過程的真正實(shí)現(xiàn)是AMS的registerReceiver方法
ActivityManagerService#registerReceiver
public Intent registerReceiver(IApplicationThread caller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
int flags) {
//...
synchronized (this) {
//...
//獲取該receiver(IIntentReceiver對象)對應(yīng)的ReceiverList
//ReceiverList繼承于ArrayList<BroadcastFilter>,是一個存儲BroadcastFilter的集合
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
//若rl為空,則根據(jù)receiver創(chuàng)建對應(yīng)的ReceiverList,并使兩者建立映射關(guān)系存入HashMap中
if (rl == null) {
rl = new ReceiverList(this, callerApp, callingPid, callingUid,
userId, receiver);
//...
mRegisteredReceivers.put(receiver.asBinder(), rl);
}
//...
//BroadcastFilter繼承于IntentFilter
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
permission, callingUid, userId, instantApp, visibleToInstantApps);
//將該BroadcastFilter添加進(jìn)ReceiverList中
rl.add(bf);
mReceiverResolver.addFilter(bf);
//...
}
}
其中mRegisteredReceivers的定義如下:
/**
* Keeps track of all IIntentReceivers that have been registered for broadcasts.
* Hash keys are the receiver IBinder, hash value is a ReceiverList.
*/
final HashMap<IBinder, ReceiverList> mRegisteredReceivers = new HashMap<>();
可以看到,一個IIntentReceiver對應(yīng)著一個ReceiverList
最終,通過HashMap把IIntentReceiver與對應(yīng)的ReceiverList保存起來;而ReceiverList又把可以啟動該BroadcastReceiver的IntentFilter保存起來。
發(fā)送、接收普通廣播
以下是一個發(fā)送普通廣播的例子:
Intent intent = new Intent();
intent.setAction("FIRST_RECEIVER");
sendBroadcast(intent); //發(fā)送廣播
仍然是從ContextWrapper開始,調(diào)用其sendBroadcast方法
ContextWrapper#sendBroadcast
@Override
public void sendBroadcast(Intent intent) {
mBase.sendBroadcast(intent);
}
依然是交給ContextImpl來處理,調(diào)用其sendBroadcast方法
ContextImpl#sendBroadcast
@Override
public void sendBroadcast(Intent intent) {
//...
try {
intent.prepareToLeaveProcess(this);
//調(diào)用AMS的broadcastIntent方法
ActivityManager.getService().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
getUserId());
} //...
}
ContextImpl也沒做什么,它直接調(diào)用AMS的broadcastIntent方法
ActivityManagerService#broadcastIntent
public final int broadcastIntent(IApplicationThread caller,
Intent intent, String resolvedType, IIntentReceiver resultTo,
int resultCode, String resultData, Bundle resultExtras,
String[] requiredPermissions, int appOp, Bundle bOptions,
boolean serialized, boolean sticky, int userId) {
//...
synchronized(this) {
//...
int res = broadcastIntentLocked(callerApp,
callerApp != null ? callerApp.info.packageName : null,
intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
requiredPermissions, appOp, bOptions, serialized, sticky,
callingPid, callingUid, userId);
//...
return res;
}
}
繼續(xù)調(diào)用broadcastIntentLocked方法
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) {
//...
//添加這個標(biāo)志后,廣播不會發(fā)送給已經(jīng)停止的應(yīng)用
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
//...
//判斷是否有添加FLAG_RECEIVER_REPLACE_PENDING標(biāo)記位
//這個flag將會將之前的Intent替代掉。加了這個flag,在發(fā)送一系列的這樣的Intent之后, //中間有些Intent有可能在你還沒有來得及處理的時候,就被替代掉了。
final boolean replacePending =
(intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
//...
if ((receivers != null && receivers.size() > 0)
|| resultTo != null) {
//獲取AMS的廣播隊(duì)列
BroadcastQueue queue = broadcastQueueForIntent(intent);
//先將匹配的廣播接收器封裝成一個BroadcastRecord對象r
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
resultData, resultExtras, ordered, sticky, false, userId);
//...
final BroadcastRecord oldRecord =
replacePending ? queue.replaceOrderedBroadcastLocked(r) : null;
if (oldRecord != null) {
// Replaced, fire the result-to receiver.
//...
} else {
//將BroadcastRecord對象r插入廣播隊(duì)列queue中
queue.enqueueOrderedBroadcastLocked(r);
//在BroadcastRecord中發(fā)送廣播
queue.scheduleBroadcastsLocked();
}
} //...
return ActivityManager.BROADCAST_SUCCESS;
}
該方法最終將滿足條件的廣播接收器封裝到BroadcastRecord中,并添加到廣播隊(duì)列BroadcastQueue中,通過BroadcastQueue的scheduleBroadcastsLocked方法發(fā)送給相應(yīng)的廣播接收器。接下來看一下BroadcastQueue的scheduleBroadcastsLocked方法。
BroadcastQueue#scheduleBroadcastsLocked
public void scheduleBroadcastsLocked() {
//...
//mBroadcastsScheduled是一個布爾變量,表明是否發(fā)送過BROADCAST_INTENT_MSG消息
if (mBroadcastsScheduled) {
return;
}
//發(fā)送BROADCAST_INTENT_MSG消息
mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
mBroadcastsScheduled = true;
}
對BROADCAST_INTENT_MSG消息的處理是
case BROADCAST_INTENT_MSG: {
//...
processNextBroadcast(true);
} break;
可以看到,收到BROADCAST_INTENT_MSG消息后,執(zhí)行processNextBroadcast方法
BroadcastQueue#processNextBroadcast
final void processNextBroadcast(boolean fromMsg) {
synchronized(mService) {
BroadcastRecord r;
//...
//如果是從BROADCAST_INTENT_MSG消息而來,重置mBroadcastsScheduled
if (fromMsg) {
mBroadcastsScheduled = false;
}
//發(fā)送無序廣播,無序廣播存儲在mParallelBroadcasts中
while (mParallelBroadcasts.size() > 0) {
r = mParallelBroadcasts.remove(0);
//...
final int N = r.receivers.size();
for (int i=0; i<N; i++) {
Object target = r.receivers.get(i);
//該方法負(fù)責(zé)將廣播發(fā)送給特定的接收器
deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
}
addBroadcastToHistoryLocked(r);
}
}
可以看到,將廣播發(fā)送到對應(yīng)接收器的過程是通過deliverToRegisteredReceiverLocked方法實(shí)現(xiàn)的
BroadcastQueue#deliverToRegisteredReceiverLocked
private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
BroadcastFilter filter, boolean ordered, int index) {
//...
try {
if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {
//...
} else {
//通過該方法完成具體的發(fā)送過程
performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
new Intent(r.intent), r.resultCode, r.resultData,
r.resultExtras, r.ordered, r.initialSticky, r.userId);
}
//...
} //...
}
繼續(xù)看performReceiveLocked方法
BroadcastQueue#performReceiveLocked
void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Intent intent, int resultCode, String data, Bundle extras,
boolean ordered, boolean sticky, int sendingUser) throws RemoteException {
if (app != null) {
if (app.thread != null) {
try {
//app.thread的實(shí)現(xiàn)是ActivityThread.ApplicationThread
app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
data, extras, ordered, sticky, sendingUser, app.repProcState);
} //...
} //...
} //...
}
接著調(diào)用ApplicationThread的scheduleRegisteredReceiver方法
ActivityThread.ApplicationThread#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);
//調(diào)用InnerReceiver的performReceive方法
receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
sticky, sendingUser);
}
ReceiverDispatcher.InnerReceiver
final static class InnerReceiver extends IIntentReceiver.Stub {
final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
final LoadedApk.ReceiverDispatcher mStrongRef;
InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
mStrongRef = strong ? rd : null;
}
@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) {
rd = null;
} else {
rd = mDispatcher.get();
}
//...
if (rd != null) {
//調(diào)用LoadedApk.ReceiverDispatcher的performReceive方法
rd.performReceive(intent, resultCode, data, extras,
ordered, sticky, sendingUser);
} //...
}
}
繼續(xù)調(diào)用LoadedApk.ReceiverDispatcher的performReceive方法
LoadedApk.ReceiverDispatcher#performReceive
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
//Args是LoadedApk.ReceiverDispatcher的內(nèi)部類
final Args args = new Args(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
//...
//mActivityThread是一個Handler對象,指向ActivityThread中的handler對象
if (intent == null || !mActivityThread.post(args.getRunnable())) {
//...
}
}
在post里面執(zhí)行了Args的getRunnable方法,其實(shí)現(xiàn)如下
LoadedApk.ReceiverDispatcher.Args#getRunnable
public final Runnable getRunnable() {
return () -> {
final BroadcastReceiver receiver = mReceiver;
//...
try {
//...
//回調(diào)了BoradcastReceiver的onReceive方法
receiver.onReceive(mContext, intent);
} //...
};
}
可以看到,最終在Args拋出的一個Runnable的run方法中回調(diào)了BoradcastReceiver的onReceive方法,并且是在廣播接收器的主線程中執(zhí)行的。
至此,普通廣播的發(fā)送及接收過程分析完畢。
參考
- 《Android開發(fā)藝術(shù)探索》
- BroadcastReceiver源碼解析(二)