这一节将分析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所示。
:-: ![](http://img.blog.csdn.net/20150803131511362?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
图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所示。
:-: ![](http://img.blog.csdn.net/20150803131528312?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
图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所示。
:-: ![](http://img.blog.csdn.net/20150803131545395?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
图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所示。
:-: ![](http://img.blog.csdn.net/20150803131604163?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
图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 本章小结