在SDK中同樣定義了好幾個函數用于發送廣播。不過,根據之前的經驗,最終和AMS交互的函數可能通過一個接口就能完成。來看最簡單的廣播發送函數sendBroadcast,其代碼如下:
**ContextImpl.java::sendBroadcast**
~~~
public void sendBroadcast(Intent intent) {
StringresolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.setAllowFds(false);
//調用AMS的brodcastIntent,在SDK中定義的廣播發送函數最終都會調用它
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, null, false, false);
}......
}
~~~
AMS的broadcastIntent函數的主要工作將交由AMS的broadcastIntentLocked來完成,故此處直接分析broadcastIntentLocked。
1. broadcastIntentLocked分析
我們分階段來分析broadcastIntentLocked的工作,先來看第一階段工作。
(1) broadcastIntentLocked分析之一
**ActivityManagerService.java::broadcastIntentLocked**
~~~
private final int broadcastIntentLocked(ProcessRecordcallerApp,
StringcallerPackage, Intent intent, String resolvedType,
IIntentReceiver resultTo, int resultCode, String resultData,
Bundlemap, String requiredPermission,
boolean ordered, boolean sticky, int callingPid, int callingUid) {
intent =new Intent(intent);
//為Intent增加FLAG_EXCLUDE_STOPPED_PACKAGES標志,表示該廣播不會傳遞給被STOPPED
//的Package
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
//處理一些特殊的廣播,包括UID_REMOVED,PACKAGE_REMOVED和PACKAGE_ADDED等
finalboolean uidRemoved = Intent.ACTION_UID_REMOVED.equals(
intent.getAction());
......//處理特殊的廣播,主要和PACKAGE相關,例如接收到PACKAGE_REMOVED廣播后,AMS
//需將該Package的組件從相關成員中刪除,相關代碼可自行閱讀
//處理TIME_ZONE變化廣播
if(intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction()))
mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
//處理CLEAR_DNS_CACHE廣播
if(intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction()))
mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
//處理PROXY_CHANGE廣播
if(Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
ProxyProperties proxy = intent.getParcelableExtra("proxy");
mHandler.sendMessage(mHandler.obtainMessage(
UPDATE_HTTP_PROXY,proxy));
}
~~~
從以上代碼可知,broadcastIntentLocked第一階段的工作主要是處理一些特殊的廣播消息。
下面來看broadcastIntentLocked第二階段的工作。
(2) broadcastIntentLocked分析之二
**ActivityManagerService.java::broadcastIntentLocked**
~~~
//處理發送sticky廣播的情況
if(sticky) {
......//檢查發送進程是否有BROADCAST_STICKY權限
if(requiredPermission != null) {
//在發送Sticky廣播的時候,不能攜帶權限信息
returnBROADCAST_STICKY_CANT_HAVE_PERMISSION;
}
//在發送Stikcy廣播的時候,也不能指定特定的接收對象
if(intent.getComponent() != null) ......//拋異常
//將這個Sticky的Intent保存到mStickyBroadcasts中
ArrayList<Intent> list =mStickyBroadcasts.get(intent.getAction());
if (list== null) {
list= new ArrayList<Intent>();
mStickyBroadcasts.put(intent.getAction(), list);
}
......//如果list中已經有該intent,則直接用新的intent替換舊的intent
//否則將該intent加入到list中保存
if (i >= N) list.add(new Intent(intent));
}
//定義兩個變量,其中receivers用于保存匹配該Intent的所有廣播接收者,包括靜態或動態
//注冊的廣播接收者,registeredReceivers用于保存符合該Intent的所有動態注冊者
Listreceivers = null;
List<BroadcastFilter>registeredReceivers = null;
try {
if(intent.getComponent() != null) {
......//如果指定了接收者,則從PKMS中查詢它的信息
}else {
//FLAG_RECEIVER_REGISTERED_ONLY標簽表明該廣播只能發給動態注冊者
if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)== 0) {
//如果沒有設置前面的標簽,則需要查詢PKMS,獲得那些在AndroidManifest.xml
//中聲明的廣播接收者,即靜態廣播接收者的信息,并保存到receivers中
receivers =
AppGlobals.getPackageManager().queryIntentReceivers(
intent, resolvedType,STOCK_PM_FLAGS);
}
//再從AMS的mReceiverResolver中查詢符合條件的動態廣播接收者
registeredReceivers =mReceiverResolver.queryIntent(intent,
resolvedType, false);
}
}......
/*
判斷該廣播是否設置了REPLACE_PENDING標簽。如果設置了該標簽,并且之前的那個Intent還
沒有被處理,則可以用新的Intent替換舊的Intent。這么做的目的是為了減少不必要的廣播發送,
但筆者感覺,這個標簽的作用并不靠譜,因為只有舊的Intent沒被處理的時候,它才能被替換。
因為舊Intent被處理的時間不能確定,所以不能保證廣播發送者的一番好意能夠實現。因此,
在發送廣播時,千萬不要以為設置了該標志就一定能節約不必要的廣播發送。
*/
final boolean replacePending =
(intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
//先處理動態注冊的接收者
int NR =registeredReceivers != null ? registeredReceivers.size() : 0;
//如果此次廣播為非串行化發送,并且符合條件的動態注冊接收者個數不為零
if(!ordered && NR > 0) {
//創建一個BroadcastRecord對象即可,注意,一個BroadcastRecord對象可包括所有的
//接收者(可參考圖6-19)
BroadcastRecord r = new BroadcastRecord(intent, callerApp,
callerPackage, callingPid, callingUid, requiredPermission,
registeredReceivers, resultTo, resultCode, resultData, map,
ordered, sticky, false);
boolean replaced = false;
if (replacePending) {
......//從mParalledBroadcasts中查找是否有舊的Intent,如果有就替代它,并設置
//replaced為true
}
if(!replaced) {//如果沒有被替換,則保存到mParallelBroadcasts中
mParallelBroadcasts.add(r);
scheduleBroadcastsLocked();//調度一次廣播發送
}
//至此,動態注冊的廣播接收者已處理完畢,設置registeredReceivers為null
registeredReceivers = null;//
NR =0;
}
~~~
broadcastIntentLocked第二階段的工作有兩項:
- 查詢滿足條件的動態廣播接收者及靜態廣播接收者。
- 當本次廣播不為ordered時,需要盡快發送該廣播。另外,非ordered的廣播都被AMS保存在mParallelBroadcasts中。
(3) broadcastIntentLocked分析之三
下面來看broadcastIntentLocked最后一階段的工作,其代碼如下:
**ActivityManagerService.java::broadcastIntentLocked**
~~~
int ir = 0;
if(receivers != null) {
StringskipPackages[] = null;
......//處理PACKAGE_ADDED的Intent,系統不希望有些應用程序一安裝就啟動。
//這類程序的工作原理是什么呢?即在該程序內部監聽PACKAGE_ADDED廣播。如果系統
//沒有這一招防備,則PKMS安裝完程序后所發送的PAKCAGE_ADDED消息將觸發該應用的啟動
......//處理ACTION_EXTERNAL_APPLICATIONS_AVAILABLE廣播
......//將動態注冊的接收者registeredReceivers的元素合并到receivers中去
//處理完畢后,所有的接收者(無論動態還是靜態注冊的)都存儲到receivers變量中了
if((receivers != null && receivers.size() > 0) || resultTo != null) {
//創建一個BroadcastRecord對象,注意它的receivers中包括所有的接收者
BroadcastRecord r = new BroadcastRecord(intent, callerApp,
callerPackage, callingPid, callingUid, requiredPermission,
receivers, resultTo, resultCode, resultData, map, ordered,
sticky, false);
booleanreplaced = false;
if (replacePending) {
......//替換mOrderedBroadcasts中舊的Intent
}//
if(!replaced) {//如果沒有替換,則添加該條廣播記錄到mOrderedBroadcasts中
mOrderedBroadcasts.add(r);
scheduleBroadcastsLocked();//調度AMS進行廣播發送工作
}
}
returnBROADCAST_SUCCESS;
}
~~~
由以上代碼可知,AMS將動態注冊者和靜態注冊者都合并到receivers中去了。注意,如果本次廣播不是ordered,那么表明動態注冊者就已經在第二階段工作中被處理了。因此在合并時,將不會有動態注冊者被加到receivers中。最終所創建的廣播記錄存儲在mOrderedBroadcasts中,也就是說,不管是否串行化發送,靜態接收者對應的廣播記錄都將保存在mOrderedBroadcasts中。
為什么不將它們保存在mParallelBroadcasts中呢?
結合代碼會發現,保存在mParallelBroadcasts中的BroadcastRecord所包含的都是動態注冊的廣播接收者信息,這是因為動態接收者所在的進程是已經存在的(如果該進程不存在,如何去注冊動態接收者呢?),而靜態廣播接收者就不能保證它已經和一個進程綁定在一起了(靜態廣播接收者此時可能還僅僅是在AndroidManifest.xml中聲明的一個信息,相應的進程并未創建和啟動)。根據前一節所分析的Activity啟動流程,AMS還需要進行創建應用進程,初始化Android運行環境等一系列復雜的操作。讀到后面內容時會發現,AMS將在一個循環中逐條處理mParallelBroadcasts中的成員(即派發給接收者)。如果將靜態廣播接收者也保存到mParallelBroadcasts中,會有什么后果呢?假設這些靜態接收者所對應的進程全部未創建和啟動,那么AMS將在那個循環中創建多個進程!結果讓人震驚,系統壓力一下就上去了。所以,對于靜態注冊者,它們對應的廣播記錄都被放到mOrderedBroadcasts中保存。AMS在處理這類廣播信息時,一個進程一個進程地處理,只有處理完一個接收者,才繼續下一個接收者。這種做法的好處是,避免了驚群效應的出現,壞處則是延時較長。
下面進入AMS的BROADCAST_INTENT_MSG消息處理函數,看看情況是否如上所說。
- 前言
- 第1章 搭建Android源碼工作環境
- 1.1 Android系統架構
- 1.2 搭建開發環境
- 1.2.1 下載源碼
- 1.2.2 編譯源碼
- 1.2.3 利用Eclipse調試system_process
- 1.3 本章小結
- 第2章 深入理解Java Binder和MessageQueue
- 2.1 概述
- 2.2 Java層中的Binder架構分析
- 2.2.1 Binder架構總覽
- 2.2.2 初始化Java層Binder框架
- 2.2.3 addService實例分析
- 2.2.4 Java層Binder架構總結
- 2.3 心系兩界的MessageQueue
- 2.3.1 MessageQueue的創建
- 2.3.2 提取消息
- 2.3.3 nativePollOnce函數分析
- 2.3.4 MessageQueue總結
- 2.4 本章小結
- 第3章 深入理解SystemServer
- 3.1 概述
- 3.2 SystemServer分析
- 3.2.1 main函數分析
- 3.2.2 Service群英會
- 3.3 EntropyService分析
- 3.4 DropBoxManagerService分析
- 3.4.1 DBMS構造函數分析
- 3.4.2 dropbox日志文件的添加
- 3.4.3 DBMS和settings數據庫
- 3.5 DiskStatsService和DeviceStorageMonitorService分析
- 3.5.1 DiskStatsService分析
- 3.5.2 DeviceStorageManagerService分析
- 3.6 SamplingProfilerService分析
- 3.6.1 SamplingProfilerService構造函數分析
- 3.6.2 SamplingProfilerIntegration分析
- 3.7 ClipboardService分析
- 3.7.1 復制數據到剪貼板
- 3.7.2 從剪切板粘貼數據
- 3.7.3 CBS中的權限管理
- 3.8 本章小結
- 第4章 深入理解PackageManagerService
- 4.1 概述
- 4.2 初識PackageManagerService
- 4.3 PKMS的main函數分析
- 4.3.1 構造函數分析之前期準備工作
- 4.3.2 構造函數分析之掃描Package
- 4.3.3 構造函數分析之掃尾工作
- 4.3.4 PKMS構造函數總結
- 4.4 APK Installation分析
- 4.4.1 adb install分析
- 4.4.2 pm分析
- 4.4.3 installPackageWithVerification函數分析
- 4.4.4 APK 安裝流程總結
- 4.4.5 Verification介紹
- 4.5 queryIntentActivities分析
- 4.5.1 Intent及IntentFilter介紹
- 4.5.2 Activity信息的管理
- 4.5.3 Intent 匹配查詢分析
- 4.5.4 queryIntentActivities總結
- 4.6 installd及UserManager介紹
- 4.6.1 installd介紹
- 4.6.2 UserManager介紹
- 4.7 本章學習指導
- 4.8 本章小結
- 第5章 深入理解PowerManagerService
- 5.1 概述
- 5.2 初識PowerManagerService
- 5.2.1 PMS構造函數分析
- 5.2.2 init分析
- 5.2.3 systemReady分析
- 5.2.4 BootComplete處理
- 5.2.5 初識PowerManagerService總結
- 5.3 PMS WakeLock分析
- 5.3.1 WakeLock客戶端分析
- 5.3.2 PMS acquireWakeLock分析
- 5.3.3 Power類及LightService類介紹
- 5.3.4 WakeLock總結
- 5.4 userActivity及Power按鍵處理分析
- 5.4.1 userActivity分析
- 5.4.2 Power按鍵處理分析
- 5.5 BatteryService及BatteryStatsService分析
- 5.5.1 BatteryService分析
- 5.5.2 BatteryStatsService分析
- 5.5.3 BatteryService及BatteryStatsService總結
- 5.6 本章學習指導
- 5.7 本章小結
- 第6章 深入理解ActivityManagerService
- 6.1 概述
- 6.2 初識ActivityManagerService
- 6.2.1 ActivityManagerService的main函數分析
- 6.2.2 AMS的 setSystemProcess分析
- 6.2.3 AMS的 installSystemProviders函數分析
- 6.2.4 AMS的 systemReady分析
- 6.2.5 初識ActivityManagerService總結
- 6.3 startActivity分析
- 6.3.1 從am說起
- 6.3.2 AMS的startActivityAndWait函數分析
- 6.3.3 startActivityLocked分析
- 6.4 Broadcast和BroadcastReceiver分析
- 6.4.1 registerReceiver流程分析
- 6.4.2 sendBroadcast流程分析
- 6.4.3 BROADCAST_INTENT_MSG消息處理函數
- 6.4.4 應用進程處理廣播分析
- 6.4.5 廣播處理總結
- 6.5 startService之按圖索驥
- 6.5.1 Service知識介紹
- 6.5.2 startService流程圖
- 6.6 AMS中的進程管理
- 6.6.1 Linux進程管理介紹
- 6.6.2 關于Android中的進程管理的介紹
- 6.6.3 AMS進程管理函數分析
- 6.6.4 AMS進程管理總結
- 6.7 App的 Crash處理
- 6.7.1 應用進程的Crash處理
- 6.7.2 AMS的handleApplicationCrash分析
- 6.7.3 AppDeathRecipient binderDied分析
- 6.7.4 App的Crash處理總結
- 6.8 本章學習指導
- 6.9 本章小結
- 第7章 深入理解ContentProvider
- 7.1 概述
- 7.2 MediaProvider的啟動及創建
- 7.2.1 Context的getContentResolver函數分析
- 7.2.2 MediaStore.Image.Media的query函數分析
- 7.2.3 MediaProvider的啟動及創建總結
- 7.3 SQLite創建數據庫分析
- 7.3.1 SQLite及SQLiteDatabase家族
- 7.3.2 MediaProvider創建數據庫分析
- 7.3.3 SQLiteDatabase創建數據庫的分析總結
- 7.4 Cursor 的query函數的實現分析
- 7.4.1 提取query關鍵點
- 7.4.2 MediaProvider 的query分析
- 7.4.3 query關鍵點分析
- 7.4.4 Cursor query實現分析總結
- 7.5 Cursor close函數實現分析
- 7.5.1 客戶端close的分析
- 7.5.2 服務端close的分析
- 7.5.3 finalize函數分析
- 7.5.4 Cursor close函數總結
- 7.6 ContentResolver openAssetFileDescriptor函數分析
- 7.6.1 openAssetFileDescriptor之客戶端調用分析
- 7.6.2 ContentProvider的 openTypedAssetFile函數分析
- 7.6.3 跨進程傳遞文件描述符的探討
- 7.6.4 openAssetFileDescriptor函數分析總結
- 7.7 本章學習指導
- 7.8 本章小結
- 第8章 深入理解ContentService和AccountManagerService
- 8.1 概述
- 8.2 數據更新通知機制分析
- 8.2.1 初識ContentService
- 8.2.2 ContentResovler 的registerContentObserver分析
- 8.2.3 ContentResolver的 notifyChange分析
- 8.2.4 數據更新通知機制總結和深入探討
- 8.3 AccountManagerService分析
- 8.3.1 初識AccountManagerService
- 8.3.2 AccountManager addAccount分析
- 8.3.3 AccountManagerService的分析總結
- 8.4 數據同步管理SyncManager分析
- 8.4.1 初識SyncManager
- 8.4.2 ContentResolver 的requestSync分析
- 8.4.3 數據同步管理SyncManager分析總結
- 8.5 本章學習指導
- 8.6 本章小結