這一節將分析AccountManagerService中的一個重要的函數,即addAccount,其功能是為某項賬戶添加一個用戶。下面以前面提及的Email為例來認識AAS的處理流程。
AccountManagerService是一個運行在SystemServer中的服務,客戶端進程必須借助AccountManager提供的API來使用AccountManagerService服務,所以,本例需從AccountManager的addAccount函數講起。
1. AccountManager的addAccount發起請求
AccountManager 的addAccount函數的參數和返回值較復雜,先看其函數原型:
~~~
public AccountManagerFuture<Bundle>addAccount(
finalString accountType,
finalString authTokenType,
finalString[] requiredFeatures,
finalBundle addAccountOptions,
finalActivity activity,
AccountManagerCallback<Bundle>callback,
Handlerhandler)
~~~
在以上代碼中:
- addAccount的返回值類型是AccountManagerFuture<Bundle>。其中,AccountManagerFuture是一個模板Interface,其真實類型只有在分析addAccount的實現時才能知道。現在可以告訴讀者的是,它和Java并發庫(concurrent庫)中的FutureTask有關,是對異步函數調用的一種封裝[^①]。調用者在后期只要調用它的getResult函數即可取得addAccount的調用結果。由于addAccount可能涉及網絡操作(例如,AAS需要把賬戶添加到網絡服務器上),所以這里采用了異步調用的方法以避免長時間的阻塞。這也是AccountManagerFuture的getResult不能在主線程中調用的原因。
- addAccount的第一個參數accountType代表賬戶類型。該參數不能為空。就本例而言,它的值為“com.android.email”。
- authTokenType、requiredFeatures和addAccountOptions與具體的AAS服務有關。如果想添加指定賬戶類型的Account,則須對其背后的AAS有所了解。
- activity:此參數和界面有關。例如有些AAS需要用戶輸入用戶名和密碼,故需啟動一Activity。在這種情況下,AAS會返回一個Intent,客戶端將通過這個activity啟動Intent所標示的Activity。讀者將通過下文的分析了解這一點。
- callback和handler:這兩個參數與如何獲取addAccount返回結果有關。如這兩個參數為空,客戶端則須單獨啟動一個線程去調用AccountManagerFuture的getResult函數。
addAccount的代碼如下:
**AccountManager.java::addAccount**
~~~
public AccountManagerFuture<Bundle>addAccount(final String accountType,
finalString authTokenType, final String[] requiredFeatures,
finalBundle addAccountOptions, final Activity activity,
AccountManagerCallback<Bundle> callback, Handler handler) {
if(accountType == null) //accountType不能為null
thrownew IllegalArgumentException("accountType is null");
finalBundle optionsIn = new Bundle();
if(addAccountOptions != null)//保存客戶端傳入的addAccountOptions
optionsIn.putAll(addAccountOptions);
optionsIn.putString(KEY_ANDROID_PACKAGE_NAME,
mContext.getPackageName());
//構造一個匿名類對象,該類繼承自AmsTask,并實現了doWork函數。addAccount返回前
//將調用該對象的start函數
returnnew AmsTask(activity, handler, callback) {
publicvoid doWork() throws RemoteException {
//mService用于和AccountManagerService通信
mService.addAcount(mResponse, accountType, authTokenType,
requiredFeatures, activity!= null, optionsIn);
}
}.start();
}
~~~
在以上代碼中,AccountManager的 addAccount函數將返回一個匿名類對象,該匿名類繼承自AmsTask類。那么,AmsTask又是什么呢?
(1) AmsTask介紹
先來看AmsTask的繼承關系,如圖8-7所示。
:-: 
圖8-7 AmsTask繼承關系
由圖8-7可知:
- AmsTask繼承自FutureTask,并實現了AccountManagerFuture接口。FutureTask是Java concurrent庫中一個常用的類。AmsTask定義了一個doWork虛函數,該函數必須由子類來實現。
- 一個AmsTask對象中有一個mResponse成員,該成員的類型是AmsTask中的內部類Response。從Response的派生關系可知,Response將參與Binder通信,并且它是Binder通信的Bn端。而AccountManagerService的addAccount將得到它的Bp端對象。當添加完賬戶后,AccountManagerService會通過這個Bp端對象的onResult或onError函數向Response通知處理結果。
(2) AmsTask匿名類處理分析
AccountManager的addAccount最終返回給客戶端的是一個AmsTask的子類,首先來了解它的構造函數,其代碼如下:
**AccountManager.java::AmsTask**
~~~
public AmsTask(Activity activity, Handler handler,
AccountManagerCallback<Bundle> callback){
......//調用基類構造函數
//保存客戶端傳遞的參數
mHandler= handler;
mCallback = callback;
mActivity = activity;
mResponse = new Response();//構造一個Response對象,并保存到mResponse中
}
~~~
下一步調用的是這個匿名類的start函數,代碼如下:
**AccountManager.java::AmsTask.start**
~~~
public final AccountManagerFuture<Bundle>start() {
try {
doWork(); //調用匿名類實現的doWork函數
}......
returnthis;
}
~~~
匿名類實現的doWork函數即下面這個函數:
**AccountManager.java::addAccount返回的匿名類**
~~~
public void doWork() throws RemoteException {
//調用AccountManagerService的addAccount函數,其第一個參數是mResponse
mService.addAcount(mResponse, accountType, authTokenType,
requiredFeatures, activity != null, optionsIn);
}
~~~
AccountManager的addAccount函數的實現比較新奇,它內部使用了Java的concurrent類。不熟悉Java并發編程的讀者有必要了解相關知識。
下面轉到AccountManagerService中去分析addAccount的實現。
2. AccountManagerService addAccount轉發請求
AccountManagerServiceaddAccount的代碼如下所示:
**AccountManagerService.java::addAccount**
~~~
public void addAcount(finalIAccountManagerResponse response,
finalString accountType, final String authTokenType,
final String[] requiredFeatures, final boolean expectActivityLaunch,
final Bundle optionsIn) {
......
//檢查客戶端進程是否有“android.permission.MANAGE_ACCOUNTS”的權限
checkManageAccountsPermission();
final intpid = Binder.getCallingPid();
final intuid = Binder.getCallingUid();
//構造一個Bundle類型的options變量,并保存傳入的optionsIn
finalBundle options = (optionsIn == null) ? new Bundle() : optionsIn;
options.putInt(AccountManager.KEY_CALLER_UID, uid);
options.putInt(AccountManager.KEY_CALLER_PID, pid);
longidentityToken = clearCallingIdentity();
try {
//創建一個匿名類對象,該匿名類派生自Session類。最后調用該匿名類的bind函數
new Session(response, accountType, expectActivityLaunch,true){
public void run() throws RemoteException {
mAuthenticator.addAccount(this, mAccountType,
authTokenType,requiredFeatures, options);
}
protected String toDebugString(longnow) {
......//實現toDebugString函數
}
}.bind();
}finally {
restoreCallingIdentity(identityToken);
}
}
~~~
由以上代碼可知,AccountManagerService的addAccount函數最后也創建了一個匿名類對象,該匿名類派生自Session。addAccount最后還調用了這個對象的bind函數。其中最重要的內容就是Session。那么,Session又是什么呢?
(1) Session介紹
Session家族成員如圖8-8所示。
:-: 
圖8-8 Session家族示意圖
由圖8-8可知:
- Session從IAccountAuthenticatorResponse.Stub派生,這表明它將參與Binder通信,并且它是Bn端。那么這個Binder通信的目標是誰呢?,它正是具體的AAS服務。AccountManagerService會將自己傳遞給AAS,這樣,AAS就得到IAccountAuthenticatorResponse的Bp端對象。當AAS完成了具體的賬戶添加工作后,會通過IAccountAuthenticatorResponse的Bp端對象向Seession返回處理結果。
- Session通過mResponse成員變量指向來自客戶端的IAccountManagerResponse接口,當Session收到AAS的返回結果后,又通過IAccountManagerResponse 的Bp端對象向客戶端返回處理結果。
- Session mAuthenticator變量的類型是IAccountAuthenticator,它用于和遠端的AAS通信。客戶端發起的請求將通過Session經由mAuthenticator調用對應AAS中的函數。
由圖8-7和圖8-8可知,AccountManagerService在addAccount流程中所起的是橋梁作用,具體如下:
- 客戶端將請求發送給AccountManagerService,然后AccountManagerService再轉發給對應的AAS。
- AAS處理完的結果先返回給AccountManagerService,再由AccountManagerService返回給客戶端。
由于圖8-7和圖8-8中定義的類名較相似,因此讀者閱讀時應仔細一些。
下面來看Session匿名類的處理。
(2) Session匿名類處理分析
首先調用Session的構造函數,代碼為:
**AccountManagerService.java::Session**
~~~
public Session(IAccountManagerResponse response,String accountType,
boolean expectActivityLaunch, boolean stripAuthTokenFromResult) {
super();
......
/*
注意其中的參數,expectActivityLaunch由客戶端傳來,如果用戶調用
AccountManager addAccount時傳入了activity參數,則該值為true,
stripAuthTokenFromResult的默認值為true
*/
mStripAuthTokenFromResult = stripAuthTokenFromResult;
mResponse = response;
mAccountType = accountType;
mExpectActivityLaunch = expectActivityLaunch;
mCreationTime = SystemClock.elapsedRealtime();
synchronized(mSessions) {
//將這個匿名類對象保存到AccountManagerService中的mSessions成員中
mSessions.put(toString(), this);
}
try{ //監聽客戶端死亡消息
response.asBinder().linkToDeath(this, 0);
} ......
}
~~~
獲得匿名類對象后,addAccount將調用其bind函數,該函數由AmsTask實現,代碼如下:
**AccountManagerService.java::Session:bind**
~~~
void bind() {
//綁定到mAccountType指定的AAS。在本例中,AAS的類型是“com.android.email”
if(!bindToAuthenticator(mAccountType)) {
onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION, "bindfailure");
}
}
~~~
bindToAuthenticator的代碼為:
**AccountManagerService.java::Session:bindToAuthenticator**
~~~
private boolean bindToAuthenticator(StringauthenticatorType) {
//從mAuthenticatorCache中查詢滿足指定類型的服務信息
AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription>
authenticatorInfo =
mAuthenticatorCache.getServiceInfo(
AuthenticatorDescription.newKey(authenticatorType));
......
Intentintent = new Intent();
intent.setAction(AccountManager.ACTION_AUTHENTICATOR_INTENT);
//設置目標服務的ComponentName
intent.setComponent(authenticatorInfo.componentName);
//通過bindService啟動指定的服務,成功與否將通過第二個參數傳遞的
//ServiceConnection接口返回
if(!mContext.bindService(intent, this, Context.BIND_AUTO_CREATE)) {
......
}
returntrue;
}
~~~
由以上代碼可知,Session的bind函數將啟動指定類型的Service,這是通過bindService函數完成的。如果服務啟動成功,Session的onServiceConnected函數將被調用,這部分代碼如下:
**AccountManagerService.java::Session:onServiceConnected**
~~~
public void onServiceConnected(ComponentName name,IBinder service) {
//得到遠端AAS返回的IAccountAuthenticator接口,這個接口用于
//AccountManagerService和該遠端AAS交互
mAuthenticator = IAccountAuthenticator.Stub.asInterface(service);
try {
run();//調用匿名類實現的run函數
} ......
}
~~~
匿名類實現的run函數非常簡單,代碼如下:
**AccountManagerService.java::addAccount返回的匿名類**
~~~
new Session(response, accountType,expectActivityLaunch,true) {
publicvoid run() throws RemoteException {
//調用遠端AAS實現的addAccount函數
mAuthenticator.addAccount(this, mAccountType,
authTokenType, requiredFeatures,options);
}
~~~
由以上代碼可知,AccountManagerService在addAccount最終將調用AAS實現的addAccount函數。
下面來看本例中滿足“com.android.email”類型的服務是如何處理addAccount的請求的。該服務就是Email應用中的EasAuthenticatorService,下面來分析它。
3. EasAuthenticatorService處理請求
EasAuthenticatorService的創建是AccountManagerService調用了bindService導致的,該函數會觸發EasAuthenticatorService的onBind函數被調用,這部分代碼如下:
**EasAuthenticatorService.java::onBind**
~~~
public IBinder onBind(Intent intent) {
if(AccountManager.ACTION_AUTHENTICATOR_INTENT.equals(
intent.getAction())){
//創建一個EasAuthenticator類型的對象,并調用其getIBinder函數
return new EasAuthenticator(this).getIBinder();
}else return null;
}
~~~
下面來分析EasAuthenticator。
(1) EasAuthenticator介紹
EasAuthenticator是EasAuthenticatorService定義的內部類,其家族關系如圖8-9所示。
:-: 
圖8-9 EasAuthenticator家族類圖
由圖8-9可知:
- EasAuthenticator從AbstractAccountAuthenticator類派生。AbstractAccountAuthenticator內部有一個mTransport的成員變量,其類型是AbstractAccountAuthenticator的內部類Transport。在前面的onBind函數中,EasAuthenticator的getIBinder函數返回的就是這個變量。
- Transport類繼承自Binder,故它將參與Binder通信,并且是IAccountAuthenticator的Bn端。Session匿名類通過onServiceConnected函數將得到一個IAccountAuthenticator的Bp端對象。
當由AccoutManagerService的addAccount創建的那個Session匿名類調用IAccountAuthenticator Bp端對象的addAccount時,將觸發位于Emai進程中的IAccountAuthenticatorBn端的addAccount。下面來分析Bn端的addAccount函數。
(2) EasAuthenticator的 addAccount函數分析
根據上文的描述可知,Emai 進程中首先被觸發的是IAccountAuthenticatorBn端的addAccount函數,其代碼如下:
**AbstractAccountAuthenticator.java::Transport:addAccount**
~~~
private class Transport extendsIAccountAuthenticator.Stub {
publicvoid addAccount(IAccountAuthenticatorResponse response,
String accountType, String authTokenType,
String[] features, Bundle options)
throws RemoteException {
//檢查權限
checkBinderPermission();
try {
//調用AbstractAccountAuthenticator子類實現的addAccount函數
final Bundle result =
AbstractAccountAuthenticator.this.addAccount(
new AccountAuthenticatorResponse(response),
accountType,authTokenType, features, options);
//如果返回的result不為空,則調用response的onResult返回結果。
//這個response是IAccountAuthenticatorResponse類型,它的onResult
//將觸發位于Session匿名類中mResponse變量的onResult函數被調用
if (result != null)
response.onResult(result);
}......
}
~~~
本例中AbstractAccountAuthenticator子類(即EasAuthenticator)實現的addAccount函數,代碼如下:
**EasAuthenticatorService.java::EasAuthenticator.addAccount**
~~~
public BundleaddAccount(AccountAuthenticatorResponse response,
String accountType, StringauthTokenType,
String[] requiredFeatures, Bundle options)
throws NetworkErrorException {
//EasAuthenticatoraddAccount的處理邏輯和Email應用有關。只做簡單了解即可
//如果用戶傳遞的賬戶信息保護了密碼和用戶名,則走if分支。注意,其中有一些參數名是
//通用的,例如OPTIONS_PASSWORD,OPTIONS_USERNAME等
if(options != null && options.containsKey(OPTIONS_PASSWORD)
&& options.containsKey(OPTIONS_USERNAME)) {
//創建一個Account對象,該對象僅包括兩個成員,一個是name,用于表示賬戶名;
//另一個是type,用于表示賬戶類型
finalAccount account = new
Account(options.getString(OPTIONS_USERNAME),
AccountManagerTypes.TYPE_EXCHANGE);
//調用AccountManager的addAccountExplicitly將account對象和password傳遞
//給AccountManagerService處理。讀者可自行研究這個函數,在其內部將這些信息寫入
//accounts.db的account表中
AccountManager.get(EasAuthenticatorService.this).
addAccountExplicitly(account,
options.getString(OPTIONS_PASSWORD), null);
//根據Email應用的規則,下面將判斷和該賬戶相關的數據是否需要設置自動數據同步
//首先判斷是否需要處理聯系人自動數據同步
booleansyncContacts = false;
if(options.containsKey(OPTIONS_CONTACTS_SYNC_ENABLED) &&
options.getBoolean(OPTIONS_CONTACTS_SYNC_ENABLED))
syncContacts = true;
ContentResolver.setIsSyncable(account,
ContactsContract.AUTHORITY,1);
ContentResolver.setSyncAutomatically(account,
ContactsContract.AUTHORITY,syncContacts);
booleansyncCalendar = false;
......//判斷是否需要設置Calendar自動數據同步
booleansyncEmail = false;
//如果選項中包含Email同步相關的功能,則需要設置Email數據同步的相關參數
if(options.containsKey(OPTIONS_EMAIL_SYNC_ENABLED) &&
options.getBoolean(OPTIONS_EMAIL_SYNC_ENABLED))
syncEmail = true;
/*
下面這兩個函數將和ContentService中的SyncManager交互。注意這
兩個函數:第一個函數setIsSyncable將設置Email對應的同步服務功能標志,
第二個函數setSyncAutomatically將設置是否自動同步Email。
數據同步的內容留待8.4節再詳細分析
*/
ContentResolver.setIsSyncable(account,EmailContent.AUTHORITY, 1);
ContentResolver.setSyncAutomatically(account,EmailContent.AUTHORITY,
syncEmail);
//構造返回結果,注意,下面這些參數名是Android統一定義的,如KEY_ACCOUNT_NAME等
Bundleb = new Bundle();
b.putString(AccountManager.KEY_ACCOUNT_NAME,
options.getString(OPTIONS_USERNAME));
b.putString(AccountManager.KEY_ACCOUNT_TYPE,
AccountManagerTypes.TYPE_EXCHANGE);
returnb;
} else {
//如果沒有傳遞password,則需要啟動一個Activity,該Activity對應的Intent
//由actionSetupExchangeIntent返回。注意下面幾個通用的參數,如
// KEY_ACCOUNT_AUTHENTICATOR_RESPONSE和KEY_INTENT
Bundle b = new Bundle();
Intent intent =AccountSetupBasics.actionSetupExchangeIntent(
EasAuthenticatorService.this);
intent.putExtra(
AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
b.putParcelable(AccountManager.KEY_INTENT,intent);
return b;
}
}
~~~
不同的AAS有自己特定的處理邏輯,以上代碼向讀者展示了EasAuthenticatorService的工作流程。雖然每個AAS的處理方式各有不同,但Android還是定義了一些通用的參數,例如OPTIONS_USERNAME用于表示用戶名,OPTIONS_PASSWORD用于表示密碼等。關于這方面內容,讀者可查閱SDK中AccountManager的文檔說明。
4. 返回值的處理流程
在EasAuthenticator的addAccount返回處理結果后,AbstractAuthenticator將通過IAccountAuthenticatorResponse的onResult將其返回給由AccountManagerService創建的Session匿名類對象。來看Session的onResult函數,其代碼如下:
**AccountManagerService.java::Session:onResult**
~~~
public void onResult(Bundle result) {
mNumResults++;
//從返回的result中取出相關信息,關于下面這個if分支處理和狀態欄中相關的邏輯,
//讀者可自行研究 if (result != null&&!TextUtils.isEmpty(
result.getString(AccountManager.KEY_AUTHTOKEN))) {
String accountName = result.getString(AccountManager.KEY_ACCOUNT_NAME);
String accountType =
result.getString(AccountManager.KEY_ACCOUNT_TYPE);
if(!TextUtils.isEmpty(accountName) &&
!TextUtils.isEmpty(accountType)){
Account account = new Account(accountName, accountType);
cancelNotification(
getSigninRequiredNotificationId(account));
}
}
IAccountManagerResponse response;
//如果客戶端傳遞了activity參數,則mExpectActivityLaunch為true。如果
//AAS返回的結果中包含KEY_INTENT,則表明需要彈出Activity以輸入賬戶和密碼
if(mExpectActivityLaunch && result != null
&& result.containsKey(AccountManager.KEY_INTENT)) {
response = mResponse;
} else {
/*
getResponseAndClose返回的也是mResponse,不過它會調用unBindService
斷開和AAS服務的連接。就整個流程而言,此時addAccount已經完成AAS和
AccountManagerService的工作,故無需再保留和AAS服務的連接。而由于上面的if
分支還需要輸入用戶密碼,因此以AAS和AccountManagerService之間的工作
還沒有真正完成
*/
response = getResponseAndClose();
}
if(response != null) {
try{
......
if (mStripAuthTokenFromResult)
result.remove(AccountManager.KEY_AUTHTOKEN);
//調用位于客戶端的IAccountManagerResponse的onResult函數
response.onResult(result);
} ......
}
}
~~~
客戶端的IAccountManagerResponse接口由AmsTask內部類Response實現,其代碼為:
**AccountManager.java::AmsTask::Response.onResult**
~~~
public void onResult(Bundle bundle) {
Intentintent = bundle.getParcelable(KEY_INTENT);
//如果需要彈出Activity,則要利用客戶端傳入的那個activity去啟動AAS指定的
//Activity。這個Activity由AAS返回的Intent來表示
if(intent != null && mActivity != null) {
mActivity.startActivity(intent);
} elseif (bundle.getBoolean("retry")) {
//如果需要重試,則再次調用doWork
try {
doWork();
}......
}else{
//將返回結果保存起來,當客戶端調用getResult時,就會得到相關結果
set(bundle);
}
}
~~~
5. AccountManager的addAccount分析總結
AccountManager的addAccount流程分析起來給人一種行云流水般的感覺。該流程涉及3個模塊,分別是客戶端、AccountManagerService和AAS。整體難度雖不算大,但架構卻比較巧妙。
總結起來addAccount相關流程如圖8-10所示。
:-: 
圖8-10 AccountManager的addAccount處理流程
為了讓讀者看得更清楚,圖8-10中略去了一些細枝末節的內容。另外,圖8-10中第10步的onServiceConnected函數應由位于SystemServer中的ActivityThread對象調用,為方便閱讀起見,這里沒有畫出ActivityThread的對象。
[^①]:從設計模式角度來說,這屬于ActiveObject模式。詳細內容可閱讀《Pattern.Oriented.Software.Architecture.Volume.2》的第2章“Concurrency Patterns”。
- 前言
- 第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 本章小結