1. binderDied函數分析
**ActvityManagerService.java::AppDeathRecipientbinderDied**
~~~
public void binderDied() {
//注意,該函數也是通過Binder線程調用的,所以此處要加鎖
synchronized(ActivityManagerService.this) {
appDiedLocked(mApp, mPid, mAppThread);
}
}
~~~
最終的處理函數是appDiedLocked,其中所傳遞的3個參數保存了對應死亡進程的信息。來看appDiedLocked的代碼::
**ActvityManagerService.java::appDiedLocked**
~~~
final void appDiedLocked(ProcessRecord app, intpid,
IApplicationThread thread) {
......
if(app.pid == pid && app.thread != null &&
app.thread.asBinder() == thread.asBinder()) {
//當內存低到水位線時,LMK模塊也會殺死進程。對AMS來說,需要區分進程死亡是LMK導致的
//還是其他原因導致的。App instrumentationClass一般都為空,故此處doLowMem為true
booleandoLowMem = app.instrumentationClass == null;
//①下面這個函數非常重要
handleAppDiedLocked(app, false, true);
if(doLowMem) {
boolean haveBg = false;
//如果系統中還存在oom_adj大于HIDDEN_APP_MIN_ADJ的進程,就表明不是LMK模塊因
//內存不夠而導致進程死亡的
for(int i=mLruProcesses.size()-1; i>=0; i--) {
ProcessRecord rec = mLruProcesses.get(i);
if (rec.thread != null && rec.setAdj >=
ProcessList.HIDDEN_APP_MIN_ADJ){
haveBg = true;//還有后臺進程,故可確定系統內存尚未吃緊
break;
}
}//for循環結束
//如果沒有后臺進程,表明系統內存已吃緊
if(!haveBg) {
long now = SystemClock.uptimeMillis();
for(int i=mLruProcesses.size()-1; i>=0; i--) {
.....//將這些進程按一定規則加到mProcessesToGc中,盡量保證
//heavy/important/visible/foreground的進程位于mProcessesToGc數組
//的前端
}//for循環結束
/*
發送GC_BACKGROUND_PROCESSES_MSG消息給mHandler,該消息的處理過程就是:
調用應用進程的scheduleLowMemory或processInBackground函數。其中,
scheduleLowMemory將觸發onLowMemory回調被調用,而processInBackground將
觸發應用進程進行一次垃圾回收
讀者可自行閱讀該消息的處理函數performAppGcsIfAppropriateLocked
*/
scheduleAppGcsLocked();
}// if(!haveBg)判斷結束
}//if(doLowMem)判斷結束
}
~~~
以上代碼中有一個關鍵函數handleAppDiedLocked,下面來看它的處理過程。
2. handleAppDiedLocked函數分析
**ActivityManagerService.java::handleAppDiedLocked**
~~~
private final voidhandleAppDiedLocked(ProcessRecord app,
boolean restarting, boolean allowRestart) {
//①在本例中,傳入的參數為restarting=false, allowRestart=true
cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1);
if(!restarting) {
mLruProcesses.remove(app);
}
......//下面還有一部分代碼處理和Activity相關的收尾工作,讀者可自行閱讀
}
~~~
重點看上邊代碼中的cleanUpApplicationRecordLocked函數,該函數的主要功能就是處理Service、ContentProvider及BroadcastReceiver相關的收尾工作。先來看Service方面的工作。
(1) cleanUpApplicationRecordLocked之處理Service
**ActivityManagerService.java::cleanUpApplicationRecordLocked**
~~~
privatefinal void cleanUpApplicationRecordLocked(ProcessRecord app,
boolean restarting, boolean allowRestart, int index) {
if (index>= 0) mLruProcesses.remove(index);
mProcessesToGc.remove(app);
//如果該Crash進程有對應打開的對話框,則關閉它們,這些對話框包括crash、anr和wait等
if(app.crashDialog != null) {
app.crashDialog.dismiss();
app.crashDialog = null;
}
......//處理anrDialog、waitDialog
//清理app的一些參數
app.crashing = false;
app.notResponding = false;
......
//處理該進程中所駐留的Service或它和別的進程中的Service建立的Connection關系
//該函數是AMS Service處理流程中很重要的一環,讀者要仔細閱讀
killServicesLocked(app,allowRestart);
~~~
cleanUpApplicationRecordLocked函數首先處理幾個對話框(dialog),然后調用killServicesLocked函數做相關處理。作為Service流程的一部分,讀者需要深入研究。
(2) cleanUpApplicationRecordLocked之處理ContentProvider
再來看cleanUpApplicationRecordLocked下一階段的工作,主要和ContentProvider有關。
**ActivityManagerService.java::cleanUpApplicationRecordLocked**
~~~
booleanrestart = false;
int NL = mLaunchingProviders.size();
if(!app.pubProviders.isEmpty()) {
//得到該進程中發布的ContentProvider信息
Iterator<ContentProviderRecord> it =
app.pubProviders.values().iterator();
while(it.hasNext()) {
ContentProviderRecord cpr = it.next();
cpr.provider = null;
cpr.proc = null;
int i = 0;
if(!app.bad && allowRestart) {
for (; i<NL; i++) {
/*
如果有客戶端進程在等待這個已經死亡的ContentProvider,則系統會
嘗試重新啟動它,即設置restart變量為true
*/
if (mLaunchingProviders.get(i) == cpr) {
restart = true;
break;
}
}//for循環結束
} else i = NL;
if(i >= NL) {
/*
如果沒有客戶端進程等待這個ContentProvider,則調用下面這個函數處理它,我們
在卷I的第10章曾提過一個問題,即ContentProvider進程被殺死
后,系統該如何處理那些使用了該ContentProvider的客戶端進程。例如,Music和
MediaProvider之間有交互,如果殺死了MediaProvider,Music會怎樣呢?
答案是系統會殺死Music,證據就在removeDyingProviderLocked函數
中,讀者可自行閱讀其內部處理流程
*/
removeDyingProviderLocked(app, cpr);
NL = mLaunchingProviders.size();
}
}// while(it.hasNext())循環結束
app.pubProviders.clear();
}
//下面這個函數的功能是檢查本進程中的ContentProvider是否存在于
// mLaunchingProviders中,如果存在,則表明有客戶端在等待,故需考慮是否重啟本進程或者
//殺死客戶端(當死亡進程變成bad process的時,需要殺死客戶端)
if(checkAppInLaunchingProvidersLocked(app, false)) restart = true;
......
~~~
從以上的描述中可知,ContentProvider所在進程和其客戶端進程實際上有著非常緊密而隱晦(之所以說其隱晦,是因為SDK中沒有任何說明)的關系。在目前軟件開發追求模塊間盡量保持松耦合關系的大趨勢下,Android中的ContentProvider和其客戶端這種緊耦合的設計思路似乎不夠明智。不過,這種設計是否是不得已而為之呢?讀者不妨探討一下,如果有更合適的解決方案,期待能一起分享。
(3) cleanUpApplicationRecordLocked之處理BroadcastReceiver
**ActivityManagerService.java::cleanUpApplicationRecordLocked**
~~~
skipCurrentReceiverLocked(app);
//從AMS中去除接收者
if(app.receivers.size() > 0) {
Iterator<ReceiverList> it = app.receivers.iterator();
while(it.hasNext()) {
removeReceiverLocked(it.next());
}
app.receivers.clear();
}
if(mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
//處理Backup信息
}
mHandler.obtainMessage(DISPATCH_PROCESS_DIED, app.pid,
app.info.uid,null).sendToTarget();
//注意該變量名為restarting,前面設置為restart.
if(restarting) return;
if(!app.persistent) {
mProcessNames.remove(app.processName, app.info.uid);
if(mHeavyWeightProcess == app) {
......//處理HeavyWeightProcess
}
} elseif (!app.removed) {
if(mPersistentStartingProcesses.indexOf(app) < 0) {
mPersistentStartingProcesses.add(app);
restart = true;
}
}
mProcessesOnHold.remove(app);
if (app== mHomeProcess) mHomeProcess = null;
if(restart) {//如果需要重啟,則調用startProcessLocked處理它
mProcessNames.put(app.processName, app.info.uid, app);
startProcessLocked(app, "restart", app.processName);
} elseif (app.pid > 0 && app.pid != MY_PID) {
synchronized (mPidsSelfLocked) {
mPidsSelfLocked.remove(app.pid);
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
}
app.setPid(0);
}
}
~~~
在這段代碼中,除了處理BrodcastReceiver方面的工作外,還包括其他方面的收尾工作。最后,如果要重啟該應用,則需調用startProcessLocked函數進行處理。這部分代碼不再詳述,讀者可自行閱讀。
- 前言
- 第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 本章小結