轉自:http://blog.csdn.net/luoshengyang/article/details/6744448
有時間要好好研究一下
前面我們分析了Android應用程序註冊廣播接收器的過程,這個過程只完成了萬里長征的第一步,接下來它還要等待ActivityManagerService將廣播分發過來。ActivityManagerService是如何得到廣播並把它分發出去的呢?這就是本文要介紹的廣播發送過程了。
廣播的發送過程比廣播接收器的註冊過程要複雜得多了,不過這個過程仍然是以ActivityManagerService爲中心。廣播的發送者將廣播發送到ActivityManagerService,ActivityManagerService接收到這個廣播以後,就會在自己的註冊中心查看有哪些廣播接收器訂閱了該廣播,然後把這個廣播逐一發送到這些廣播接收器中,但是ActivityManagerService並不等待廣播接收器處理這些廣播就返回了,因此,廣播的發送和處理是異步的。概括來說,廣播的發送路徑就是從發送者到ActivityManagerService,再從ActivityManagerService到接收者,這中間的兩個過程都是通過Binder進程間通信機制來完成的,因此,希望讀者在繼續閱讀本文之前,對Android系統的Binder進程間通信機制有所瞭解,具體可以參考Android進程間通信(IPC)機制Binder簡要介紹和學習計劃一文。
本文繼續以Android系統中的廣播(Broadcast)機制簡要介紹和學習計劃一文中所開發的應用程序爲例子,並且結合上文Android應用程序註冊廣播接收器(registerReceiver)的過程分析的內容,一起來分析Android應用程序發送廣播的過程。
回顧一下Android系統中的廣播(Broadcast)機制簡要介紹和學習計劃一文中所開發的應用程序的組織架構,MainActivity向ActivityManagerService註冊了一個CounterService.BROADCAST_COUNTER_ACTION類型的計數器服務廣播接收器,計數器服務CounterService在後臺線程中啓動了一個異步任務(AsyncTask),這個異步任務負責不斷地增加計數,並且不斷地將當前計數值通過廣播的形式發送出去,以便MainActivity可以將當前計數值在應用程序的界面線程中顯示出來。
計數器服務CounterService發送廣播的代碼如下所示:
- public class CounterService extends Service implements ICounterService {
- ......
- public void startCounter(int initVal) {
- AsyncTask<Integer, Integer, Integer> task = new AsyncTask<Integer, Integer, Integer>() {
- @Override
- protected Integer doInBackground(Integer... vals) {
- ......
- }
- @Override
- protected void onProgressUpdate(Integer... values) {
- super.onProgressUpdate(values);
- int counter = values[0];
- Intent intent = new Intent(BROADCAST_COUNTER_ACTION);
- intent.putExtra(COUNTER_VALUE, counter);
- sendBroadcast(intent);
- }
- @Override
- protected void onPostExecute(Integer val) {
- ......
- }
- };
- task.execute(0);
- }
- ......
- }
在繼承分析廣播的發送過程前,我們先來看一下廣播發送過程的序列圖,然後按照這個序圖中的步驟來一步一步分析整個過程。
Step 1. ContextWrapper.sendBroadcast
這個函數定義在frameworks/base/core/java/android/content/ContextWrapper.java文件中:
- public class ContextWrapper extends Context {
- Context mBase;
- ......
- @Override
- public void sendBroadcast(Intent intent) {
- mBase.sendBroadcast(intent);
- }
- ......
- }
Step 2. ContextImpl.sendBroadcast
這個函數定義在frameworks/base/core/java/android/app/ContextImpl.java文件中:
- class ContextImpl extends Context {
- ......
- @Override
- public void sendBroadcast(Intent intent) {
- String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
- try {
- ActivityManagerNative.getDefault().broadcastIntent(
- mMainThread.getApplicationThread(), intent, resolvedType, null,
- Activity.RESULT_OK, null, null, null, false, false);
- } catch (RemoteException e) {
- }
- }
- ......
- }
Step 3. ActivityManagerProxy.broadcastIntent
這個函數定義在frameworks/base/core/java/android/app/ActivityManagerNative.java文件中:
- class ActivityManagerProxy implements IActivityManager
- {
- ......
- public int broadcastIntent(IApplicationThread caller,
- Intent intent, String resolvedType, IIntentReceiver resultTo,
- int resultCode, String resultData, Bundle map,
- String requiredPermission, boolean serialized,
- boolean sticky) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(caller != null ? caller.asBinder() : null);
- intent.writeToParcel(data, 0);
- data.writeString(resolvedType);
- data.writeStrongBinder(resultTo != null ? resultTo.asBinder() : null);
- data.writeInt(resultCode);
- data.writeString(resultData);
- data.writeBundle(map);
- data.writeString(requiredPermission);
- data.writeInt(serialized ? 1 : 0);
- data.writeInt(sticky ? 1 : 0);
- mRemote.transact(BROADCAST_INTENT_TRANSACTION, data, reply, 0);
- reply.readException();
- int res = reply.readInt();
- reply.recycle();
- data.recycle();
- return res;
- }
- ......
- }
Step 4. ctivityManagerService.broadcastIntent
這個函數定義在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:
- public final class ActivityManagerService extends ActivityManagerNative
- implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
- ......
- public final int broadcastIntent(IApplicationThread caller,
- Intent intent, String resolvedType, IIntentReceiver resultTo,
- int resultCode, String resultData, Bundle map,
- String requiredPermission, boolean serialized, boolean sticky) {
- synchronized(this) {
- intent = verifyBroadcastLocked(intent);
- final ProcessRecord callerApp = getRecordForAppLocked(caller);
- final int callingPid = Binder.getCallingPid();
- final int callingUid = Binder.getCallingUid();
- final long origId = Binder.clearCallingIdentity();
- int res = broadcastIntentLocked(callerApp,
- callerApp != null ? callerApp.info.packageName : null,
- intent, resolvedType, resultTo,
- resultCode, resultData, map, requiredPermission, serialized,
- sticky, callingPid, callingUid);
- Binder.restoreCallingIdentity(origId);
- return res;
- }
- }
- ......
- }
Step 5. ActivityManagerService.broadcastIntentLocked
這個函數定義在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:
- public final class ActivityManagerService extends ActivityManagerNative
- implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
- ......
- private final int broadcastIntentLocked(ProcessRecord callerApp,
- String callerPackage, Intent intent, String resolvedType,
- IIntentReceiver resultTo, int resultCode, String resultData,
- Bundle map, String requiredPermission,
- boolean ordered, boolean sticky, int callingPid, int callingUid) {
- intent = new Intent(intent);
- ......
- // Figure out who all will receive this broadcast.
- List receivers = null;
- List<BroadcastFilter> registeredReceivers = null;
- try {
- if (intent.getComponent() != null) {
- ......
- } else {
- ......
- registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
- }
- } catch (RemoteException ex) {
- ......
- }
- final boolean replacePending =
- (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
- int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
- if (!ordered && NR > 0) {
- // If we are not serializing this broadcast, then send the
- // registered receivers separately so they don't wait for the
- // components to be launched.
- BroadcastRecord r = new BroadcastRecord(intent, callerApp,
- callerPackage, callingPid, callingUid, requiredPermission,
- registeredReceivers, resultTo, resultCode, resultData, map,
- ordered, sticky, false);
- ......
- boolean replaced = false;
- if (replacePending) {
- for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
- if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
- ......
- mParallelBroadcasts.set(i, r);
- replaced = true;
- break;
- }
- }
- }
- if (!replaced) {
- mParallelBroadcasts.add(r);
- scheduleBroadcastsLocked();
- }
- registeredReceivers = null;
- NR = 0;
- }
- ......
- }
- ......
- }
- // Figure out who all will receive this broadcast.
- List receivers = null;
- List<BroadcastFilter> registeredReceivers = null;
- try {
- if (intent.getComponent() != null) {
- ......
- } else {
- ......
- registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
- }
- } catch (RemoteException ex) {
- ......
- }
繼續往下看:
- final boolean replacePending =
- (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
再接着往下看:
- int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
- if (!ordered && NR > 0) {
- // If we are not serializing this broadcast, then send the
- // registered receivers separately so they don't wait for the
- // components to be launched.
- BroadcastRecord r = new BroadcastRecord(intent, callerApp,
- callerPackage, callingPid, callingUid, requiredPermission,
- registeredReceivers, resultTo, resultCode, resultData, map,
- ordered, sticky, false);
- ......
- boolean replaced = false;
- if (replacePending) {
- for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
- if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
- ......
- mParallelBroadcasts.set(i, r);
- replaced = true;
- break;
- }
- }
- }
- if (!replaced) {
- mParallelBroadcasts.add(r);
- scheduleBroadcastsLocked();
- }
- registeredReceivers = null;
- NR = 0;
- }
這樣,這裏得到的replaced變量的值也爲false,於是,就會把這個廣播記錄塊r放在ActivityManagerService的成員變量mParcelBroadcasts中,等待進一步處理;進一步處理的操作由函數scheduleBroadcastsLocked進行。
Step 6. ActivityManagerService.scheduleBroadcastsLocked
這個函數定義在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:
- public final class ActivityManagerService extends ActivityManagerNative
- implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
- ......
- private final void scheduleBroadcastsLocked() {
- ......
- if (mBroadcastsScheduled) {
- return;
- }
- mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
- mBroadcastsScheduled = true;
- }
- ......
- }
注意這裏處理廣播的方式,它是通過消息循環來處理,每當ActivityManagerService接收到一個廣播時,它就把這個廣播放進自己的消息隊列去就完事了,根本不管這個廣播後續是處理的,因此,這裏我們可以看出廣播的發送和處理是異步的。
這裏的成員變量mHandler是一個在ActivityManagerService內部定義的Handler類變量,通過它的sendEmptyMessage函數把一個類型爲BROADCAST_INTENT_MSG的空消息放進ActivityManagerService的消息隊列中去。這裏的空消息是指這個消息除了有類型信息之外,沒有任何其它額外的信息,因爲前面已經把要處理的廣播信息都保存在mParcelBroadcasts中了,等處理這個消息時,從mParcelBroadcasts就可以讀回相關的廣播信息了,因此,這裏不需要把廣播信息再放在消息內容中。
Step 7. Handler.sendEmptyMessage
這個自定義的Handler類實現在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中,它是ActivityManagerService的內部類,調用了它的sendEmptyMessage函數來把一個消息放到消息隊列後,一會就會調用它的handleMessage函數來真正處理這個消息:
- public final class ActivityManagerService extends ActivityManagerNative
- implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
- ......
- final Handler mHandler = new Handler() {
- public void handleMessage(Message msg) {
- switch (msg.what) {
- ......
- case BROADCAST_INTENT_MSG: {
- ......
- processNextBroadcast(true);
- } break;
- ......
- }
- }
- }
- ......
- }
Step 8. ActivityManagerService.processNextBroadcast
這個函數定義在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:
- public final class ActivityManagerService extends ActivityManagerNative
- implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
- ......
- private final void processNextBroadcast(boolean fromMsg) {
- synchronized(this) {
- BroadcastRecord r;
- ......
- if (fromMsg) {
- mBroadcastsScheduled = false;
- }
- // First, deliver any non-serialized broadcasts right away.
- 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);
- ......
- deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
- }
- addBroadcastToHistoryLocked(r);
- ......
- }
- ......
- }
- }
- ......
- }
Step 9. ActivityManagerService.deliverToRegisteredReceiverLocked
這個函數定義在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:
- public final class ActivityManagerService extends ActivityManagerNative
- implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
- ......
- private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
- BroadcastFilter filter, boolean ordered) {
- boolean skip = false;
- if (filter.requiredPermission != null) {
- ......
- }
- if (r.requiredPermission != null) {
- ......
- }
- if (!skip) {
- // If this is not being sent as an ordered broadcast, then we
- // don't want to touch the fields that keep track of the current
- // state of ordered broadcasts.
- if (ordered) {
- ......
- }
- try {
- ......
- performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
- new Intent(r.intent), r.resultCode,
- r.resultData, r.resultExtras, r.ordered, r.initialSticky);
- ......
- } catch (RemoteException e) {
- ......
- }
- }
- }
- ......
- }
Step 10. ActivityManagerService.performReceiveLocked
這個函數定義在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:
- public final class ActivityManagerService extends ActivityManagerNative
- implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
- ......
- static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
- Intent intent, int resultCode, String data, Bundle extras,
- boolean ordered, boolean sticky) throws RemoteException {
- // Send the intent to the receiver asynchronously using one-way binder calls.
- if (app != null && app.thread != null) {
- // If we have an app thread, do the call through that so it is
- // correctly ordered with other one-way calls.
- app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
- data, extras, ordered, sticky);
- } else {
- ......
- }
- }
- ......
- }
MainActivity在註冊廣播接收器時,已經把自己的ProcessRecord記錄下來了,所以這裏的參數app和app.thread均不爲null,於是,ActivityManagerService就調用app.thread.scheduleRegisteredReceiver函數來把這個廣播分發給MainActivity了。這裏的app.thread是一個Binder遠程對象,它的類型是ApplicationThreadProxy,我們在前面介紹應用程序的Activity啓動過程時,已經多次看到了,具體可以參考主題Android應用程序的Activity啓動過程簡要介紹和學習計劃。
Step 11. ApplicationThreadProxy.scheduleRegisteredReceiver
這個函數定義在frameworks/base/core/java/android/app/ApplicationThreadNative.java文件中:
- class ApplicationThreadProxy implements IApplicationThread {
- ......
- public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
- int resultCode, String dataStr, Bundle extras, boolean ordered, boolean sticky)
- throws RemoteException {
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken(IApplicationThread.descriptor);
- data.writeStrongBinder(receiver.asBinder());
- intent.writeToParcel(data, 0);
- data.writeInt(resultCode);
- data.writeString(dataStr);
- data.writeBundle(extras);
- data.writeInt(ordered ? 1 : 0);
- data.writeInt(sticky ? 1 : 0);
- mRemote.transact(SCHEDULE_REGISTERED_RECEIVER_TRANSACTION, data, null,
- IBinder.FLAG_ONEWAY);
- data.recycle();
- }
- ......
- }
Step 12. ApplicaitonThread.scheduleRegisteredReceiver
這個函數定義在frameworks/base/core/java/android/app/ActivityThread.java文件中:
- public final class ActivityThread {
- ......
- private final class ApplicationThread extends ApplicationThreadNative {
- ......
- // 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) throws RemoteException {
- receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky);
- }
- ......
- }
- ......
- }
Step 13. InnerReceiver.performReceive
這個函數定義在frameworks/base/core/java/android/app/LoadedApk.java文件中:
- final class LoadedApk {
- ......
- static final class ReceiverDispatcher {
- final static class InnerReceiver extends IIntentReceiver.Stub {
- ......
- public void performReceive(Intent intent, int resultCode,
- String data, Bundle extras, boolean ordered, boolean sticky) {
- LoadedApk.ReceiverDispatcher rd = mDispatcher.get();
- ......
- if (rd != null) {
- rd.performReceive(intent, resultCode, data, extras,
- ordered, sticky);
- } else {
- ......
- }
- }
- }
- ......
- }
- ......
- }
Step 14. ReceiverDispatcher.performReceive
這個函數定義在frameworks/base/core/java/android/app/LoadedApk.java文件中:
- final class LoadedApk {
- ......
- static final class ReceiverDispatcher {
- ......
- public void performReceive(Intent intent, int resultCode,
- String data, Bundle extras, boolean ordered, boolean sticky) {
- ......
- Args args = new Args();
- args.mCurIntent = intent;
- args.mCurCode = resultCode;
- args.mCurData = data;
- args.mCurMap = extras;
- args.mCurOrdered = ordered;
- args.mCurSticky = sticky;
- if (!mActivityThread.post(args)) {
- ......
- }
- }
- ......
- }
- ......
- }
注意這裏處理消息的方式是通過Handler.post函數進行的,post函數的參數是Runnable類型的,這個消息最終會調用這個這個參數的run成員函數來處理。這裏的Args類是LoadedApk類的內部類ReceiverDispatcher的一個內部類,它繼承於Runnable類,因此,可以作爲mActivityThread.post的參數傳進去,代表這個廣播的intent也保存在這個Args實例中。
Step 15. Hanlder.post
這個函數定義在frameworks/base/core/java/android/os/Handler.java文件中,這個函數我們就不看了,有興趣的讀者可以自己研究一下,它的作用就是把消息放在消息隊列中,然後就返回了,這個消息最終會在傳進來的Runnable類型的參數的run成員函數中進行處理。
Step 16. Args.run
這個函數定義在frameworks/base/core/java/android/app/LoadedApk.java文件中:
- final class LoadedApk {
- ......
- static final class ReceiverDispatcher {
- ......
- final class Args implements Runnable {
- ......
- public void run() {
- BroadcastReceiver receiver = mReceiver;
- ......
- Intent intent = mCurIntent;
- ......
- try {
- ClassLoader cl = mReceiver.getClass().getClassLoader();
- intent.setExtrasClassLoader(cl);
- if (mCurMap != null) {
- mCurMap.setClassLoader(cl);
- }
- receiver.setOrderedHint(true);
- receiver.setResult(mCurCode, mCurData, mCurMap);
- receiver.clearAbortBroadcast();
- receiver.setOrderedHint(mCurOrdered);
- receiver.setInitialStickyHint(mCurSticky);
- receiver.onReceive(mContext, intent);
- } catch (Exception e) {
- ......
- }
- ......
- }
- ......
- }
- ......
- }
- ......
- }
有了這個ReceiverDispatcher實例之後,就可以調用它的onReceive函數把這個廣播分發給它處理了。
Step 17. BroadcastReceiver.onReceive
這個函數定義Android系統中的廣播(Broadcast)機制簡要介紹和學習計劃一文中所介紹的Android應用程序Broadcast的工程目錄下的src/shy/luo/broadcast/MainActivity.java文件中:
- public class MainActivity extends Activity implements OnClickListener {
- ......
- private BroadcastReceiver counterActionReceiver = new BroadcastReceiver(){
- public void onReceive(Context context, Intent intent) {
- int counter = intent.getIntExtra(CounterService.COUNTER_VALUE, 0);
- String text = String.valueOf(counter);
- counterText.setText(text);
- Log.i(LOG_TAG, "Receive counter event");
- }
- }
- ......
- }
至此,Android應用程序發送廣播的過程就分析完成了,結合前面這篇分析廣播接收器註冊過程的文章Android應用程序註冊廣播接收器(registerReceiver)的過程分析,就會對Android系統的廣播機制且個更深刻的認識和理解了。
最後,我們總結一下這個Android應用程序發送廣播的過程:
1. Step 1 - Step 7,計數器服務CounterService通過sendBroadcast把一個廣播通過Binder進程間通信機制發送給ActivityManagerService,ActivityManagerService根據這個廣播的Action類型找到相應的廣播接收器,然後把這個廣播放進自己的消息隊列中去,就完成第一階段對這個廣播的異步分發了;
2. Step 8 - Step 15,ActivityManagerService在消息循環中處理這個廣播,並通過Binder進程間通信機制把這個廣播分發給註冊的廣播接收分發器ReceiverDispatcher,ReceiverDispatcher把這個廣播放進MainActivity所在的線程的消息隊列中去,就完成第二階段對這個廣播的異步分發了;
3. Step 16 - Step 17, ReceiverDispatcher的內部類Args在MainActivity所在的線程消息循環中處理這個廣播,最終是將這個廣播分發給所註冊的BroadcastReceiver實例的onReceive函數進行處理。
這樣,Android系統廣播機制就學習完成了,希望對讀者有所幫助。重新學習Android系統的廣播機制,請回到Android系統中的廣播(Broadcast)機制簡要介紹和學習計劃一文中。