Zygote是什么?有什么作用?
Android系統(tǒng)底層基于Linux Kernel, 當(dāng)Kernel啟動(dòng)過程會(huì)創(chuàng)建init進(jìn)程, 該進(jìn)程是所有用戶空間的鼻祖, init進(jìn)程會(huì)啟動(dòng)ServiceManager(Binder服務(wù)管家)、 Zygote進(jìn)程(Java進(jìn)程的鼻祖)。Zygote進(jìn)程會(huì)創(chuàng)建 system_server進(jìn)程以及各種App進(jìn)程。
Zygote進(jìn)程:是Android系統(tǒng)的首個(gè)Java進(jìn)程,Zygote是所有Java進(jìn)程的父進(jìn)程,包括 system_server進(jìn)程以及所有的App進(jìn)程都是Zygote的子進(jìn)程,注意這里說的是子進(jìn)程,而非子線程。
我們都知道,每一個(gè)App其實(shí)都是
- 一個(gè)單獨(dú)的Dalvik虛擬機(jī)
- 一個(gè)單獨(dú)的進(jìn)程
所以當(dāng)系統(tǒng)里面的第一個(gè)Zygote進(jìn)程運(yùn)行之后,在這之后再開啟App,就相當(dāng)于開啟一個(gè)新的進(jìn)程。而為了實(shí)現(xiàn)資源共用和更快的啟動(dòng)速度,Android系統(tǒng)開啟新進(jìn)程的方式,是通過fork第一個(gè)Zygote進(jìn)程實(shí)現(xiàn)的。所以說,除了第一個(gè)Zygote進(jìn)程,其他應(yīng)用所在的進(jìn)程都是Zygote的子進(jìn)程,這下你明白為什么這個(gè)進(jìn)程叫“受精卵”了吧?因?yàn)榫拖袷且粋€(gè)受精卵一樣,它能快速的分裂,并且產(chǎn)生遺傳物質(zhì)一樣的細(xì)胞!
SystemServer是什么?有什么作用?它與zygote的關(guān)系是什么?
首先我要告訴你的是,SystemServer也是一個(gè)進(jìn)程,而且是由zygote進(jìn)程fork出來的。
知道了SystemServer的本質(zhì),我們對(duì)它就不算太陌生了,這個(gè)進(jìn)程是Android Framework里面兩大非常重要的進(jìn)程之一—另外一個(gè)進(jìn)程就是上面的zygote進(jìn)程。
為什么說SystemServer非常重要呢?因?yàn)橄到y(tǒng)里面重要的服務(wù)都是在這個(gè)進(jìn)程里面開啟的,比如
ActivityManagerService、PackageManagerService、WindowManagerService等等,看著是不是都挺眼熟的?
那么這些系統(tǒng)服務(wù)是怎么開啟起來的呢?
在zygote開啟的時(shí)候,會(huì)調(diào)用ZygoteInit.main()進(jìn)行初始化
public static void main(String argv[]) {
...ignore some code...
//在加載首個(gè)zygote的時(shí)候,會(huì)傳入初始化參數(shù),使得startSystemServer = true
boolean startSystemServer = false;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
} else if (argv[i].startsWith(ABI_LIST_ARG)) {
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
socketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}
...ignore some code...
//開始fork我們的SystemServer進(jìn)程
if (startSystemServer) {
startSystemServer(abiList, socketName);
}
...ignore some code...
}
ActivityManagerService是什么?什么時(shí)候初始化的?有什么作用?
ActivityManagerService,簡稱AMS,服務(wù)端對(duì)象,負(fù)責(zé)系統(tǒng)中所有Activity的生命周期。
ActivityManagerService進(jìn)行初始化的時(shí)機(jī)很明確,就是在SystemServer進(jìn)程開啟的時(shí)候,就會(huì)初始化ActivityManagerService。從下面的代碼中可以看到
public final class SystemServer {
//zygote的主入口
public static void main(String[] args) {
new SystemServer().run();
}
public SystemServer() {
// Check for factory test mode.
mFactoryTestMode = FactoryTest.getMode();
}
private void run() {
...ignore some code...
//加載本地系統(tǒng)服務(wù)庫,并進(jìn)行初始化
System.loadLibrary("android_servers");
nativeInit();
// 創(chuàng)建系統(tǒng)上下文
createSystemContext();
//初始化SystemServiceManager對(duì)象,下面的系統(tǒng)服務(wù)開啟都需要調(diào)用SystemServiceManager.startService(Class<T>),這個(gè)方法通過反射來啟動(dòng)對(duì)應(yīng)的服務(wù)
mSystemServiceManager = new SystemServiceManager(mSystemContext);
//開啟服務(wù)
try {
startBootstrapServices();
startCoreServices();
startOtherServices();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
}
...ignore some code...
}
//初始化系統(tǒng)上下文對(duì)象mSystemContext,并設(shè)置默認(rèn)的主題,mSystemContext實(shí)際上是一個(gè)ContextImpl對(duì)象。調(diào)用ActivityThread.systemMain()的時(shí)候,會(huì)調(diào)用ActivityThread.attach(true),而在attach()里面,則創(chuàng)建了Application對(duì)象,并調(diào)用了Application.onCreate()。
private void createSystemContext() {
ActivityThread activityThread = ActivityThread.systemMain();
mSystemContext = activityThread.getSystemContext();
mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
}
//在這里開啟了幾個(gè)核心的服務(wù),因?yàn)檫@些服務(wù)之間相互依賴,所以都放在了這個(gè)方法里面。
private void startBootstrapServices() {
...ignore some code...
//初始化ActivityManagerService
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService();
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
//初始化PowerManagerService,因?yàn)槠渌?wù)需要依賴這個(gè)Service,因此需要盡快的初始化
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
// 現(xiàn)在電源管理已經(jīng)開啟,ActivityManagerService負(fù)責(zé)電源管理功能
mActivityManagerService.initPowerManagement();
// 初始化DisplayManagerService
mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
//初始化PackageManagerService
mPackageManagerService = PackageManagerService.main(mSystemContext, mInstaller,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
...ignore some code...
}
}
經(jīng)過上面這些步驟,我們的ActivityManagerService對(duì)象已經(jīng)創(chuàng)建好了,并且完成了成員變量初始化。而且在這之前,調(diào)用createSystemContext()創(chuàng)建系統(tǒng)上下文的時(shí)候,也已經(jīng)完成了mSystemContext和ActivityThread的創(chuàng)建。注意,這是系統(tǒng)進(jìn)程開啟時(shí)的流程,在這之后,會(huì)開啟系統(tǒng)的Launcher程序,完成系統(tǒng)界面的加載與顯示。
你是否會(huì)好奇,我為什么說AMS是服務(wù)端對(duì)象?下面我給你介紹下Android系統(tǒng)里面的服務(wù)器和客戶端的概念。
其實(shí)服務(wù)器客戶端的概念不僅僅存在于Web開發(fā)中,在Android的框架設(shè)計(jì)中,使用的也是這一種模式。服務(wù)器端指的就是所有App共用的系統(tǒng)服務(wù),比如我們這里提到的ActivityManagerService,和前面提到的PackageManagerService、WindowManagerService等等,這些基礎(chǔ)的系統(tǒng)服務(wù)是被所有的App公用的,當(dāng)某個(gè)App想實(shí)現(xiàn)某個(gè)操作的時(shí)候,要告訴這些系統(tǒng)服務(wù),比如你想打開一個(gè)App,那么我們知道了包名和MainActivity類名之后就可以打開
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
ComponentName cn = new ComponentName(packageName, className);
intent.setComponent(cn);
startActivity(intent);
但是,我們的App通過調(diào)用startActivity()并不能直接打開另外一個(gè)App,這個(gè)方法會(huì)通過一系列的調(diào)用,最后還是告訴AMS說:“我要打開這個(gè)App,我知道他的住址和名字,你幫我打開吧!”所以是AMS來通知zygote進(jìn)程來fork一個(gè)新進(jìn)程,來開啟我們的目標(biāo)App的。這就像是瀏覽器想要打開一個(gè)超鏈接一樣,瀏覽器把網(wǎng)頁地址發(fā)送給服務(wù)器,然后還是服務(wù)器把需要的資源文件發(fā)送給客戶端的。
知道了Android Framework的客戶端服務(wù)器架構(gòu)之后,我們還需要了解一件事情,那就是我們的App和AMS(SystemServer進(jìn)程)還有zygote進(jìn)程分屬于三個(gè)獨(dú)立的進(jìn)程,他們之間如何通信呢?
App與AMS通過Binder進(jìn)行IPC通信,AMS(SystemServer進(jìn)程)與zygote通過Socket進(jìn)行IPC通信。
那么AMS有什么用呢?在前面我們知道了,如果想打開一個(gè)App的話,需要AMS去通知zygote進(jìn)程,除此之外,其實(shí)所有的Activity的開啟、暫停、關(guān)閉都需要AMS來控制,所以我們說,AMS負(fù)責(zé)系統(tǒng)中所有Activity的生命周期。
在Android系統(tǒng)中,任何一個(gè)Activity的啟動(dòng)都是由AMS和應(yīng)用程序進(jìn)程(主要是ActivityThread)相互配合來完成的。AMS服務(wù)統(tǒng)一調(diào)度系統(tǒng)中所有進(jìn)程的Activity啟動(dòng),而每個(gè)Activity的啟動(dòng)過程則由其所屬的進(jìn)程具體來完成。
這樣說你可能還是覺得比較抽象,沒關(guān)系,下面有一部分是專門來介紹AMS與ActivityThread如何一起合作控制Activity的生命周期的。
Launcher是什么?什么時(shí)候啟動(dòng)的?
當(dāng)我們點(diǎn)擊手機(jī)桌面上的圖標(biāo)的時(shí)候,App就由Launcher開始啟動(dòng)了。但是,你有沒有思考過Launcher到底是一個(gè)什么東西?
Launcher本質(zhì)上也是一個(gè)應(yīng)用程序,和我們的App一樣,也是繼承自Activity
packages/apps/Launcher2/src/com/android/launcher2/Launcher.java
public final class Launcher extends Activity
implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks,
View.OnTouchListener {
}1234
Launcher實(shí)現(xiàn)了點(diǎn)擊、長按等回調(diào)接口,來接收用戶的輸入。既然是普通的App,那么我們的開發(fā)經(jīng)驗(yàn)在這里就仍然適用,比如,我們點(diǎn)擊圖標(biāo)的時(shí)候,是怎么開啟的應(yīng)用呢?如果讓你,你怎么做這個(gè)功能呢?捕捉圖標(biāo)點(diǎn)擊事件,然后startActivity()發(fā)送對(duì)應(yīng)的Intent請(qǐng)求唄!是的,Launcher也是這么做的,就是這么easy!
那么到底是處理的哪個(gè)對(duì)象的點(diǎn)擊事件呢?既然Launcher是App,并且有界面,那么肯定有布局文件呀,是的,我找到了布局文件launcher.xml
為了方便查看,我刪除了很多代碼,從上面這些我們應(yīng)該可以看出一些東西來:Launcher大量使用標(biāo)簽來實(shí)現(xiàn)界面的復(fù)用,而且定義了很多的自定義控件實(shí)現(xiàn)界面效果,dock_divider從布局的參數(shù)聲明上可以猜出,是底部操作欄和上面圖標(biāo)布局的分割線,而paged_view_indicator則是頁面指示器,和App首次進(jìn)入的引導(dǎo)頁下面的界面引導(dǎo)是一樣的道理。當(dāng)然,我們最關(guān)心的是Workspace這個(gè)布局,因?yàn)樽⑨尷锩嬲f在這里面包含了5個(gè)屏幕的單元格,想必你也猜到了,這個(gè)就是在首頁存放我們圖標(biāo)的那五個(gè)界面(不同的ROM會(huì)做不同的DIY,數(shù)量不固定)。
CellLayout確實(shí)是繼承自ViewGroup。在CellLayout里面,只放了一個(gè)子View,那就是ShortcutAndWidgetContainer。從名字也可以看出來,ShortcutAndWidgetContainer這個(gè)類就是用來存放快捷圖標(biāo)和Widget小部件的,那么里面放的是什么對(duì)象呢?
在桌面上的圖標(biāo),使用的是BubbleTextView對(duì)象,這個(gè)對(duì)象在TextView的基礎(chǔ)之上,添加了一些特效,比如你長按移動(dòng)圖標(biāo)的時(shí)候,圖標(biāo)位置會(huì)出現(xiàn)一個(gè)背景(不同版本的效果不同),所以我們找到BubbleTextView對(duì)象的點(diǎn)擊事件,就可以找到Launcher如何開啟一個(gè)App了。
除了在桌面上有圖標(biāo)之外,在程序列表中點(diǎn)擊圖標(biāo),也可以開啟對(duì)應(yīng)的程序。這里的圖標(biāo)使用的不是BubbleTextView對(duì)象,而是PagedViewIcon對(duì)象,我們?nèi)绻业剿狞c(diǎn)擊事件,就也可以找到Launcher如何開啟一個(gè)App。
其實(shí)說這么多,和今天的主題隔著十萬八千里,上面這些東西,你有興趣就看,沒興趣就直接跳過,不知道不影響這篇文章閱讀。
BubbleTextView的點(diǎn)擊事件在哪里呢?我來告訴你:在Launcher.onClick(View v)里面。
public void onClick(View v) {
...ignore some code...
Object tag = v.getTag();
if (tag instanceof ShortcutInfo) {
// Open shortcut
final Intent intent = ((ShortcutInfo) tag).intent;
int[] pos = new int[2];
v.getLocationOnScreen(pos);
intent.setSourceBounds(new Rect(pos[0], pos[1],
pos[0] + v.getWidth(), pos[1] + v.getHeight()));
//開始開啟Activity咯~
boolean success = startActivitySafely(v, intent, tag);
if (success && v instanceof BubbleTextView) {
mWaitingForResume = (BubbleTextView) v;
mWaitingForResume.setStayPressed(true);
}
} else if (tag instanceof FolderInfo) {
//如果點(diǎn)擊的是圖標(biāo)文件夾,就打開文件夾
if (v instanceof FolderIcon) {
FolderIcon fi = (FolderIcon) v;
handleFolderClick(fi);
}
} else if (v == mAllAppsButton) {
...ignore some code...
}
}
從上面的代碼我們可以看到,在桌面上點(diǎn)擊快捷圖標(biāo)的時(shí)候,會(huì)調(diào)用
startActivitySafely(v, intent, tag);
那么從程序列表界面,點(diǎn)擊圖標(biāo)的時(shí)候會(huì)發(fā)生什么呢?實(shí)際上,程序列表界面使用的是AppsCustomizePagedView對(duì)象,所以我在這個(gè)類里面找到了onClick(View v)。
public class AppsCustomizePagedView extends PagedViewWithDraggableItems implements
View.OnClickListener,View.OnKeyListener,DragSource,PagedViewIcon.PressedCallback,
PagedViewWidget.ShortPressListener, LauncherTransitionable {
@Override
public void onClick(View v) {
...
if (v instanceof PagedViewIcon) {
mLauncher.updateWallpaperVisibility(true);
mLauncher.startActivitySafely(v, appInfo.intent, appInfo);
} else if (v instanceof PagedViewWidget) {
...ignore some code..
}
}
}
可以看到,調(diào)用的是
mLauncher.startActivitySafely(v, appInfo.intent, appInfo);
和上面一樣!這叫什么?這叫殊途同歸!
所以咱們現(xiàn)在又明白了一件事情:不管從哪里點(diǎn)擊圖標(biāo),調(diào)用的都是Launcher.startActivitySafely()。
- 下面我們就可以一步步的來看一下Launcher.startActivitySafely()到底做了什么事情。
boolean startActivitySafely(View v, Intent intent, Object tag) {
boolean success = false;
try {
success = startActivity(v, intent, tag);
} catch (ActivityNotFoundException e) {
Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
}
return success;
}
調(diào)用了startActivity(v, intent, tag)
boolean startActivity(View v, Intent intent, Object tag) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
boolean useLaunchAnimation = (v != null) &&
!intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);
if (useLaunchAnimation) {
if (user == null || user.equals(android.os.Process.myUserHandle())) {
startActivity(intent, opts.toBundle());
} else {
launcherApps.startMainActivity(intent.getComponent(), user,
intent.getSourceBounds(),
opts.toBundle());
}
} else {
if (user == null || user.equals(android.os.Process.myUserHandle())) {
startActivity(intent);
} else {
launcherApps.startMainActivity(intent.getComponent(), user,
intent.getSourceBounds(), null);
}
}
return true;
} catch (SecurityException e) {
...
}
return false;
}
這里會(huì)調(diào)用Activity.startActivity(intent, opts.toBundle()),這個(gè)方法熟悉嗎?這就是我們經(jīng)常用到的Activity.startActivity(Intent)的重載函數(shù)。而且由于設(shè)置了
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
所以這個(gè)Activity會(huì)添加到一個(gè)新的Task棧中,而且,startActivity()調(diào)用的其實(shí)是startActivityForResult()這個(gè)方法。
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
// Note we want to go through this call for compatibility with
// applications that may have overridden the method.
startActivityForResult(intent, -1);
}
}
所以我們現(xiàn)在明確了,Launcher中開啟一個(gè)App,其實(shí)和我們?cè)贏ctivity中直接startActivity()基本一樣,都是調(diào)用了Activity.startActivityForResult()。
Instrumentation是什么?和ActivityThread是什么關(guān)系?
還記得前面說過的Instrumentation對(duì)象嗎?每個(gè)Activity都持有Instrumentation對(duì)象的一個(gè)引用,但是整個(gè)進(jìn)程只會(huì)存在一個(gè)Instrumentation對(duì)象。當(dāng)startActivityForResult()調(diào)用之后,實(shí)際上還是調(diào)用了mInstrumentation.execStartActivity()
public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
if (mParent == null) {
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
...ignore some code...
} else {
if (options != null) {
//當(dāng)現(xiàn)在的Activity有父Activity的時(shí)候會(huì)調(diào)用,但是在startActivityFromChild()內(nèi)部實(shí)際還是調(diào)用的mInstrumentation.execStartActivity()
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
mParent.startActivityFromChild(this, intent, requestCode);
}
}
...ignore some code...
}
下面是mInstrumentation.execStartActivity()
的實(shí)現(xiàn)
public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
...ignore some code...
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess();
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
}
return null;
}
所以當(dāng)我們?cè)诔绦蛑姓{(diào)用startActivity()的 時(shí)候,實(shí)際上調(diào)用的是Instrumentation的相關(guān)的方法。
Instrumentation意為“儀器”,我們先看一下這個(gè)類里面包含哪些方法吧
我們可以看到,這個(gè)類里面的方法大多數(shù)和Application和Activity有關(guān),是的,這個(gè)類就是完成對(duì)Application和Activity初始化和生命周期的工具類。比如說,我單獨(dú)挑一個(gè)callActivityOnCreate()
讓你看看
public void callActivityOnCreate(Activity activity, Bundle icicle) {
prePerformCreate(activity);
activity.performCreate(icicle);
postPerformCreate(activity);
}
對(duì)activity.performCreate(icicle);這一行代碼熟悉嗎?這一行里面就調(diào)用了傳說中的Activity的入口函數(shù)onCreate(),不信?接著往下看Activity.performCreate()
final void performCreate(Bundle icicle) {
onCreate(icicle);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}
沒騙你吧,onCreate在這里調(diào)用了吧。但是有一件事情必須說清楚,那就是這個(gè)Instrumentation類這么重要,為啥我在開發(fā)的過程中,沒有發(fā)現(xiàn)他的蹤跡呢?
是的,Instrumentation這個(gè)類很重要,對(duì)Activity生命周期方法的調(diào)用根本就離不開他,他可以說是一個(gè)大管家,但是,這個(gè)大管家比較害羞,是一個(gè)女的,管內(nèi)不管外,是老板娘~
那么你可能要問了,老板是誰呀?
老板當(dāng)然是大名鼎鼎的ActivityThread了!
public final class ActivityThread {//沒有繼承或者實(shí)現(xiàn)其他類。
final ApplicationThread mAppThread = new ApplicationThread();
public ApplicationThread getApplicationThread(){
return mAppThread;
}
//ActivityThread的內(nèi)部類ApplicationThread
private class ApplicationThread extends ApplicationThreadNative {
......
}
}
ApplicationThreadNative
就是相當(dāng)于AIDL通訊中的Stub,也就是服務(wù)端,ApplicationThreadProxy
即AIDL通訊中的Proxy,也就是客戶端。所以ApplicationThread
是通訊的具體實(shí)現(xiàn)類。
ActivityThread你都沒聽說過?那你肯定聽說過傳說中的UI線程吧?是的,這就是UI線程。我們前面說過,App和AMS是通過Binder傳遞信息的,那么ActivityThread就是專門與AMS的外交工作的。
AMS說:“ActivityThread,你給我暫停一個(gè)Activity!”
ActivityThread就說:“沒問題!”然后轉(zhuǎn)身和Instrumentation說:“老婆,AMS讓暫停一個(gè)Activity,我這里忙著呢,你快去幫我把這事辦了把~”
于是,Instrumentation就去把事兒搞定了。
所以說,AMS是董事會(huì),負(fù)責(zé)指揮和調(diào)度的,ActivityThread是老板,雖然說家里的事自己說了算,但是需要聽從AMS的指揮,而Instrumentation則是老板娘,負(fù)責(zé)家里的大事小事,但是一般不拋頭露面,聽一家之主ActivityThread的安排。
如何理解AMS和ActivityThread之間的Binder通信?
前面我們說到,在調(diào)用startActivity()的時(shí)候,實(shí)際上調(diào)用的是
mInstrumentation.execStartActivity()
但是到這里還沒完呢!里面又調(diào)用了下面的方法
ActivityManagerNative.getDefault().startActivity()
這里的ActivityManagerNative.getDefault
返回的就是ActivityManagerService
的遠(yuǎn)程接口,即ActivityManagerProxy
。
怎么知道的呢?往下看
public abstract class ActivityManagerNative extends Binder implements IActivityManager{
//從類聲明上,可以看到ActivityManagerNative是Binder的一個(gè)子類,而且實(shí)現(xiàn)了IActivityManager接口
static public IActivityManager getDefault() {
return gDefault.get();
}
//通過單例模式獲取一個(gè)IActivityManager對(duì)象,這個(gè)對(duì)象通過asInterface(b)獲得
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");
IActivityManager am = asInterface(b);
return am;
}
};
//最終返回的還是一個(gè)ActivityManagerProxy對(duì)象
static public IActivityManager asInterface(IBinder obj) {
if (obj == null) {
return null;
}
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
//這里面的Binder類型的obj參數(shù)會(huì)作為ActivityManagerProxy的成員變量保存為mRemote成員變量,負(fù)責(zé)進(jìn)行IPC通信
return new ActivityManagerProxy(obj);
}
}
public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
data.writeString(callingPackage);
intent.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeStrongBinder(resultTo);
data.writeString(resultWho);
data.writeInt(requestCode);
data.writeInt(startFlags);
if (profilerInfo != null) {
data.writeInt(1);
profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
data.writeInt(0);
}
if (options != null) {
data.writeInt(1);
options.writeToParcel(data, 0);
} else {
data.writeInt(0);
}
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
reply.readException();
int result = reply.readInt();
reply.recycle();
data.recycle();
return result;
}
再看ActivityManagerProxy.startActivity()
,在這里面做的事情就是IPC通信,利用Binder對(duì)象,調(diào)用transact(),把所有需要的參數(shù)封裝成Parcel對(duì)象,向AMS發(fā)送數(shù)據(jù)進(jìn)行通信。
ActivityManagerProxy經(jīng)過Binder IPC,進(jìn)入ActivityManagerNative。接下來程序進(jìn)入了system_servr進(jìn)程,開始繼續(xù)執(zhí)行。接下來程序進(jìn)入了system_servr進(jìn)程,開始繼續(xù)執(zhí)行。
transact
方法是一個(gè)本地方法;它的實(shí)現(xiàn)在native層,具體來說在frameworks/base/core/jni/android_util_Binder.cpp
文件,里面進(jìn)行了一系列的函數(shù)調(diào)用它最終調(diào)用到了talkWithDriver
函數(shù);看這個(gè)函數(shù)的名字就知道,通信過程要交給驅(qū)動(dòng)完成了;這個(gè)函數(shù)最后通過ioctl
系統(tǒng)調(diào)用,Client進(jìn)程陷入內(nèi)核態(tài),Client調(diào)用add
方法的線程掛起等待返回;驅(qū)動(dòng)完成一系列的操作之后喚醒Server進(jìn)程,調(diào)用了Server進(jìn)程本地對(duì)象的onTransact
函數(shù)(實(shí)際上由Server端線程池完成)。Binder本地對(duì)象的onTransact
方法(這里就是Stub
類里面的此方法)
ActivityManagerService本質(zhì)就是一個(gè)Binder,并且實(shí)體在服務(wù)端。AMS在遠(yuǎn)端操作著Activity的生命周期。這個(gè)進(jìn)程由SystemServer進(jìn)程fork出來。
ActivityThread。大家都知道ActivityThread就是應(yīng)用的UI線程,main方法就是整個(gè)應(yīng)用的入口。ActivityThread本質(zhì)并不是一個(gè)線程,他只是依附著主線程存在。ActivityThread通過和AMS進(jìn)行IPC通信來共同管理Activity的生命周期。在后面我準(zhǔn)備寫一篇關(guān)于Handle的續(xù)篇,里面還會(huì)提到他,因?yàn)橹骶€程里面的Looper就是在這里init的。
ApplicationThread。它是ActivityThread的內(nèi)部類,本質(zhì)上ActivityThread是通過它來進(jìn)行和AMS的IPC通信的。它的本質(zhì)也是一個(gè)Binder!只不過這次他的實(shí)體放在客戶端,AMS通過他的代理類ApplicationThreadProxy來和ApplicationThread通信。
Instrumentation。這個(gè)類我在看完第一遍書的時(shí)候感覺操作調(diào)用鏈里面的最外層。因?yàn)樽詈笠徊紸ctivity實(shí)例對(duì)象的生成和onCreat()方法的調(diào)用最終是來自這個(gè)類的。其實(shí)這個(gè)類是ActivityThread想要進(jìn)行的操作的具體操作類。這個(gè)類是全局的,并且每個(gè)Acitivity里面都擁有一個(gè)它的引用。
對(duì)Binder的理解
Binder本質(zhì)上只是一種底層通信方式,和具體服務(wù)沒有關(guān)系。為了提供具體服務(wù),Server必須提供一套接口函數(shù)以便Client通過遠(yuǎn)程訪問使用各種服務(wù)。這時(shí)通常采用Proxy設(shè)計(jì)模式:將接口函數(shù)定義在一個(gè)抽象類中,Server和Client都會(huì)以該抽象類為基類實(shí)現(xiàn)所有接口函數(shù),所不同的是Server端是真正的功能實(shí)現(xiàn),而Client端是對(duì)這些函數(shù)遠(yuǎn)程調(diào)用請(qǐng)求的包裝。
為了更方便的說明客戶端和服務(wù)器之間的Binder通信,下面以ActivityManagerServices和他在客戶端的代理類ActivityManagerProxy為例。
ActivityManagerServices和ActivityManagerProxy都實(shí)現(xiàn)了同一個(gè)接口——IActivityManager。
ActivityManagerNative.getDefault()就是ActivityManagerService的代理類!AMS和代理類本質(zhì)上都是IActivityManager的實(shí)現(xiàn)類。
class ActivityManagerProxy implements IActivityManager{}
public final class ActivityManagerService extends ActivityManagerNative{}
public abstract class ActivityManagerNative extends Binder implements IActivityManager{}
雖然都實(shí)現(xiàn)了同一個(gè)接口,但是代理對(duì)象ActivityManagerProxy并不會(huì)對(duì)這些方法進(jìn)行真正地實(shí)現(xiàn),ActivityManagerProxy只是通過這種方式對(duì)方法的參數(shù)進(jìn)行打包(因?yàn)槎紝?shí)現(xiàn)了相同接口,所以可以保證同一個(gè)方法有相同的參數(shù),即對(duì)要傳輸給服務(wù)器的數(shù)據(jù)進(jìn)行打包),真正實(shí)現(xiàn)的是ActivityManagerService。
但是這個(gè)地方并**不是直接由客戶端傳遞給服務(wù)器,而是通過Binder驅(qū)動(dòng)進(jìn)行中轉(zhuǎn)。其實(shí)我對(duì)Binder驅(qū)動(dòng)并不熟悉,我們就把他當(dāng)做一個(gè)中轉(zhuǎn)站就OK,客戶端調(diào)用ActivityManagerProxy接口里面的方法,把數(shù)據(jù)傳送給Binder驅(qū)動(dòng),然后Binder驅(qū)動(dòng)就會(huì)把這些東西轉(zhuǎn)發(fā)給服務(wù)器的ActivityManagerServices,由ActivityManagerServices去真正的實(shí)施具體的操作。
但是Binder只能傳遞數(shù)據(jù),并不知道是要調(diào)用ActivityManagerServices的哪個(gè)方法,所以在數(shù)據(jù)中會(huì)添加方法的唯一標(biāo)識(shí)碼,比如前面的startActivity()方法:
public int startActivity() throws RemoteException {
...
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
}
上面的START_ACTIVITY_TRANSACTION就是方法標(biāo)示,data是要傳輸給Binder驅(qū)動(dòng)的數(shù)據(jù),reply則接受操作的返回值。
客戶端:ActivityManagerProxy =====>Binder驅(qū)動(dòng)=====> ActivityManagerService:服務(wù)器
而且由于繼承了同樣的公共接口類,ActivityManagerProxy提供了與ActivityManagerService一樣的函數(shù)原型,使用戶感覺不出Server是運(yùn)行在本地還是遠(yuǎn)端,從而可以更加方便的調(diào)用這些重要的系統(tǒng)服務(wù)。
但是!這里Binder通信是單方向的,即從ActivityManagerProxy指向ActivityManagerService的,如果AMS想要通知ActivityThread做一些事情,應(yīng)該咋辦呢?
還是通過Binder通信,不過是換了另外一對(duì),換成了ApplicationThread和ApplicationThreadProxy。
客戶端:ApplicationThread <=====Binder驅(qū)動(dòng)<===== ApplicationThreadProxy:服務(wù)器
他們也都實(shí)現(xiàn)了相同的接口IApplicationThread
private class ApplicationThread extends ApplicationThreadNative {}
public abstract class ApplicationThreadNative extends Binder implements IApplicationThread{}
class ApplicationThreadProxy implements IApplicationThread {}12345
AMS接收到客戶端的請(qǐng)求之后,會(huì)如何開啟一個(gè)Activity?
ActivityStack(AMS中)。很好懂,一個(gè)Activity棧。但是這個(gè)ActivityStack是有兩種類型的,一種叫系統(tǒng)ActivityStack(HomeTask),這一類的ActivityStack包含著Launcher(或者有其他我不知道的),還有一種是普通應(yīng)用的ActivityStack(安卓中Task這個(gè)概念的具體實(shí)現(xiàn)形式),其實(shí)就是一個(gè)Task(任務(wù)棧)。這個(gè)類是由AMS來管理,AMS通過這個(gè)數(shù)據(jù)結(jié)構(gòu)來得知Activity的狀態(tài)。
ActivityStackSuperisor(AMS中)。加了一個(gè)單詞,就是Activity棧的管理者。這個(gè)類的作用就是管理?xiàng)#⑶彝ㄟ^ActivityStack來獲得要啟動(dòng)的activity的信息。
ActivityRecord。這個(gè)就是上面說的服務(wù)端的Actiivty信息的載體類。并且也是服務(wù)端的類~這個(gè)類相當(dāng)?shù)闹匾允贾两K都貫穿在調(diào)用鏈里面,在安卓ActivityStack里面存儲(chǔ)的并不是activity實(shí)例,其實(shí)就是這個(gè)ActivityRecord的實(shí)例。
ActivityClientRecord。這個(gè)和上面區(qū)別就是這個(gè)類是客戶端activity信息的載體類。
TaskRecord。同樣,這個(gè)類就是ActivityTask的信息記錄類而已。
至此,點(diǎn)擊桌面圖標(biāo)調(diào)用startActivity(),終于把數(shù)據(jù)和要開啟Activity的請(qǐng)求發(fā)送到了AMS了。說了這么多,其實(shí)這些都在一瞬間完成了,下面咱們研究下AMS到底做了什么。
AMS收到startActivity的請(qǐng)求之后,會(huì)按照如下的方法鏈進(jìn)行調(diào)用
注意,從這里開始,調(diào)用鏈會(huì)變得很復(fù)雜
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options) {
//調(diào)用了startActivityAsUser,caller是我們的ApplicaitonThread
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, options,
UserHandle.getCallingUserId());
}
繼續(xù)看這個(gè)startActivityAsUser()方法:
@Override
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
enforceNotIsolatedCaller("startActivity");
userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,false, ALLOW_FULL_ONLY, "startActivity", null);
// TODO: Switch to user app stacks here. caller是我們的ApplicaitonThread
return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, options, userId, null, null);
}
startActivityAsUser()方法中調(diào)用了ActivityStackSupervisor的startActivityMayWait()方法。這里的目的就是想去通過棧的管理者來通過傳進(jìn)來的數(shù)據(jù)去改變棧,并且拿到被啟動(dòng)Activity的ActivityRecord實(shí)例。
在startActivityMayWait()里面,主要做了ActivityStack、ActivityInfo、 LaunchMode等等各種信息的初始化工作,然后就又調(diào)用了startActivityLocked()方法, 這個(gè)方法里面又做了一系列的變量初始化,初始啟動(dòng)的錯(cuò)誤判斷, UID檢查之后,又調(diào)用了startActivityUncheckedLocked()方法。這個(gè)方法里面根據(jù)前面一系列的工作,確定了最終的LanuchMode,這個(gè)LaunchMode會(huì)在后面的函數(shù)被拿來進(jìn)行判斷,構(gòu)建了一個(gè)新的Intent、ActivityInfo、ActivityTask。
ActivityStarter
startActivityMayWait方法根據(jù)Intent在系統(tǒng)中找到合適的應(yīng)用的Activity,如果有多個(gè)Activity可選擇,
則會(huì)彈出ResolverActivity讓用戶選擇合適的應(yīng)用。再調(diào)用startActivityLocked方法在startActivityLocked方法里,對(duì)傳過來的參數(shù)做一些校驗(yàn),然后創(chuàng)建ActivityRecord對(duì)象,再調(diào)用startActivityUnchecked方法啟動(dòng)Activity。
startActivityUnchecked方法負(fù)責(zé)調(diào)度ActivityRecord和Task,理解該方法是理解Actvity啟動(dòng)模式的關(guān)鍵。
startActivityUnchecked方法調(diào)度Task的算法非常復(fù)雜,和當(dāng)前回退棧,要啟動(dòng)的acitivity的啟動(dòng)模式以及taskAffinity屬性,啟動(dòng)activity時(shí)設(shè)置的intent的flag等諸多要素相關(guān),intent的flag就有很多種情況,故此算法非常復(fù)雜,需要閱讀源碼并結(jié)合特定啟動(dòng)情況才能理解。
ActivityStarter的startActivityUnchecked() 方法調(diào)用ActivityStack的startActivityLocked()
//同時(shí)調(diào)用WindowManager準(zhǔn)備App切換相關(guān)的工作
//ActivityStarter
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask){
//ActivityStack的startActivityLocked,同時(shí)調(diào)用WindowManager準(zhǔn)備App切換相關(guān)的工作
mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
if (mDoResume) {
final ActivityRecord topTaskActivity =mStartActivity.task.topRunningActivityLocked();
if (!mTargetStack.isFocusable()|| (topTaskActivity != null && topTaskActivity.mTaskOverlay&& mStartActivity != topTaskActivity)) {
...
} else {
//最終調(diào)用ActivityStackSupervisor的resumeFocusedStackTopActivityLocked
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions);
}
}
}
ActivityStack
接下來調(diào)用ActivityStack的startActivityLocked將ActivityRecord加入到回退棧里。最終調(diào)用ActivityStackSupervisor
的resumeFocusedStackTopActivityLocked()
方法。
待啟動(dòng)Activity對(duì)應(yīng)的Task為前臺(tái)Task時(shí),調(diào)用該Task對(duì)應(yīng)ActivityStack的resumeTopActivityUncheckedLocked函數(shù)。
接著跟進(jìn)ActivityStack
//ActivityStack
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
...
result = resumeTopActivityInnerLocked(prev, options);
return result;
}
private boolean resumeTopActivityInnerLocked(ActivityRecord prev,ActivityOptions options){
//mResumedActivity指向上一次啟動(dòng)的Activity(Launcher)
if (mResumedActivity != null) {
...
//通知Launcher進(jìn)入pause狀態(tài)
pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
}
if (pausing) {//Launcher已經(jīng)暫停了
...
if (next.app != null && next.app.thread != null) {
//如果app已經(jīng)啟動(dòng)過
//調(diào)用淘寶(待啟動(dòng))Activity所在進(jìn)程的優(yōu)先級(jí),保證其不被kill
mService.updateLruProcessLocked(next.app, true, null);
}
}
...
if (next.app != null && next.app.thread != null) {
//如果Intent不為空,調(diào)用NewIntent方法傳入Intent
next.app.thread.scheduleNewIntent(next.newIntents, next.appToken, false);
//若淘寶已經(jīng)啟動(dòng),點(diǎn)擊Home鍵返回到Launcher,再次從Launcher啟動(dòng)淘寶(或者第三方啟動(dòng)已開啟的App)
next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
mService.isNextTransitionForward(), resumeAnimOptions);
} else {
//創(chuàng)建進(jìn)程,冷啟動(dòng)Activity。或者已啟動(dòng)App,重新啟動(dòng)Activity
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
return true;
}
繼續(xù)看resumeTopActivityInnerLocked(prev, options);這個(gè)方法太長了,我分析了一整天,終于所有體會(huì)吧。這個(gè)方法最終的作用是將啟動(dòng)者Activity的生命周期變成paused,這樣之后被啟動(dòng)的Activity的實(shí)例創(chuàng)建了之后才能順利的resumed。
resumeTopActivityInnerLocked函數(shù)非常繁瑣,但整體來講應(yīng)該只有兩個(gè)比較關(guān)鍵的地方:
- 判斷是否已有Activity(mResumedActivity)啟動(dòng)(即Launcher,通過Launcher啟動(dòng)淘寶的),有則暫停該Activity
- 判斷是否需要重新啟動(dòng)目標(biāo)Activity,即Activity是否已經(jīng)啟動(dòng)過。(例如保存在后臺(tái),應(yīng)用切換)
2.AMS記錄要啟動(dòng)的Activity信息,并且通知Launcher進(jìn)入pause狀態(tài)。
3.Launcher進(jìn)入pause狀態(tài)后,通知AMS已經(jīng)paused了,可以啟動(dòng)淘寶了。
最終在函數(shù)的末尾會(huì)又調(diào)用ActivityStackSupervisor的startSpecificActivityLocked(next, true, true);方法。
創(chuàng)建進(jìn)程
接下來的操作就比較重要了,創(chuàng)建進(jìn)程,啟動(dòng)Activity。
//ActivityStackSupervisor
void startSpecificActivityLocked(ActivityRecord r,boolean andResume, boolean checkConfig){
// Is this activity's application already running?
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
if (app != null && app.thread != null) {
try {
if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
|| !"android".equals(r.info.packageName)) {
app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
mService.mProcessStats);
}
//目標(biāo)Activity的App已經(jīng)啟動(dòng)(存在ActivityThread),則重啟Activity
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
...
}
}
//如果進(jìn)程不存在,則通過zygote創(chuàng)建應(yīng)用進(jìn)程。
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
從上面代碼可以了解到startSpecificActivityLocked
為啟動(dòng)Activity的兩種不同情況
- 例如從Launcher冷啟動(dòng)淘寶,則需要?jiǎng)?chuàng)建新進(jìn)程,通過AMS調(diào)用Zygote(孕育天地)孵化應(yīng)用進(jìn)程。
- 如果淘寶App已經(jīng)啟動(dòng),例如從MainActivity跳轉(zhuǎn)到LoginActivity,則通過
realStartActivityLocked
啟動(dòng)。
因?yàn)槲覀冮_頭以Launcher啟動(dòng)淘寶為例子,所以我們硬著頭皮繼續(xù)分析AMS創(chuàng)建進(jìn)程以及Activity的綁定過程。
上面分析到mService.startProcessLocked
,到了這里我們直接看啟動(dòng)線程的方法,中間的過程實(shí)在是略復(fù)雜。
4.淘寶App未開啟過,所以AMS啟動(dòng)新的進(jìn)程,并且在新進(jìn)程中創(chuàng)建ActivityThread對(duì)象,執(zhí)行其中的main函數(shù)方法。
Zygote進(jìn)程孵化出新的應(yīng)用進(jìn)程后,通過反射執(zhí)行ActivityThread類的main方法。在該方法里會(huì)先準(zhǔn)備好Looper和消息隊(duì)列,然后調(diào)用attach方法將應(yīng)用進(jìn)程綁定到AMS,然后進(jìn)入loop循環(huán),不斷地讀取消息隊(duì)列里的消息,并分發(fā)消息。
至此,進(jìn)程創(chuàng)建完畢,并且也有了主線程,剩下的便是啟動(dòng)Activity和關(guān)聯(lián)Context等初始化操作了。
淘寶app主線程啟動(dòng)完畢后通知AMS,并傳入applicationThread以便通訊。
//ActivityThread
public static void main(String[] args) {
...
//準(zhǔn)備主線程的Looper,下篇博文分析Handler,Looper
Looper.prepareMainLooper();
//創(chuàng)建當(dāng)前進(jìn)程的ActivityThread
ActivityThread thread = new ActivityThread();
//將該進(jìn)程綁定到AMS
thread.attach(false);
if (sMainThreadHandler == null) {
//保存進(jìn)程對(duì)應(yīng)的主線程Handler
sMainThreadHandler = thread.getHandler();
}
...
//進(jìn)入主線程的消息循環(huán)
Looper.loop();
...
}
//上面說過,ApplicationThread是ActivityThread用來與AMS通訊的中介
final ApplicationThread mAppThread = new ApplicationThread();
private void attach(boolean system) {
if (!system) {
final IActivityManager mgr = ActivityManagerNative.getDefault();
//調(diào)用AMS的attachApplication方法,將ApplicationThread對(duì)象綁定至ActivityManagerService
//這樣AMS就可以通過ApplicationThread代理對(duì)象控制應(yīng)用進(jìn)程
mgr.attachApplication(mAppThread);
} else {
...
}
}
AMS啟動(dòng)Activity小結(jié)
至此通過下圖總結(jié)一下在AMS
啟動(dòng)Activity
的大致流程,各個(gè)方法函數(shù)像一臺(tái)機(jī)器上的不同零件,各盡其責(zé),分工明確。
雖然錯(cuò)綜復(fù)雜,但是耦合性低,比如說啟動(dòng)模式需要優(yōu)化,重新完善startActivityUnchecked
方法函數(shù)即可。
AMS.attachApplicationLocked() 關(guān)聯(lián)Activity
在這個(gè)時(shí)候,雖然有了App進(jìn)程和主線程,但是仍是一副空殼。
沒有Activity信息,沒有關(guān)聯(lián)上下文,這時(shí)候就要請(qǐng)出AMS
來進(jìn)行指揮。
因?yàn)橹骶€程main入口通過attach
方法將 ApplicationThread
發(fā)送給 AMS
,所以通過applicationThread
這個(gè)橋梁來通知ActivityThread
創(chuàng)建/關(guān)聯(lián)和啟動(dòng)Activity。
//AMS
@Override
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
//獲取applicationThread的進(jìn)程id(也就是淘寶應(yīng)用進(jìn)程)
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}
通過Binder獲取proxy(ApplicationThread )方的進(jìn)程id,也就是獲取目標(biāo)(淘寶)進(jìn)程的Pid。
//Binder
public static final native int getCallingPid();
接下來重點(diǎn)分析attachApplicationLocked
方法
//AMS
private final boolean attachApplicationLocked(IApplicationThread thread,int pid) {
ProcessRecord app;
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
app = mPidsSelfLocked.get(pid);
}
} else {
app = null;
}
//因?yàn)檫M(jìn)程由AMS啟動(dòng),所以在AMS中一定會(huì)有ProcessRecord(進(jìn)程記錄)
//如果沒有ProcessRecord,則需要?dú)⑺涝撨M(jìn)程并退出
if (app == null) {
...
return false;
}
// If this application record is still attached to a previous
// process, clean it up now.
if (app.thread != null) {
//如果從ProcessRecord中獲取的IApplicationThread不為空,則需要處理該IApplicationThread
//因?yàn)橛锌赡艽薖id為復(fù)用,舊應(yīng)用進(jìn)程剛釋放,內(nèi)部IApplicationThread尚未清空,
//同時(shí)新進(jìn)程又剛好使用了此Pid
handleAppDiedLocked(app, true, true);
}
//創(chuàng)建死亡代理(進(jìn)程kill后通知AMS)
AppDeathRecipient adr = new AppDeathRecipient(app, pid, thread);
//進(jìn)程注冊(cè)成功,移除超時(shí)通知
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
...
try {
//綁定Application
thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
app.instrumentationUiAutomationConnection, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(mConfiguration), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked());
updateLruProcessLocked(app, false, null);
} catch (Exception e) {
...
//bindApplication失敗后,重啟進(jìn)程
startProcessLocked(app, "bind fail", processName);
return false;
}
try {
//啟動(dòng)Activity(啟動(dòng)淘寶MainActivity)
if (mStackSupervisor.attachApplicationLocked(app)) {
didSomething = true;//didSomething表示是否有啟動(dòng)四大組件
}
} catch (Exception e) {
badApp = true;
}
...
//綁定service和Broadcast的Application
if (badApp) {
//如果以上組件啟動(dòng)出錯(cuò),則需要?dú)⑺肋M(jìn)程并移除記錄
app.kill("error during init", true);
handleAppDiedLocked(app, false, true);
return false;
}
//如果以上沒有啟動(dòng)任何組件,那么didSomething為false
if (!didSomething) {
//調(diào)整進(jìn)程的oom_adj值, oom_adj相當(dāng)于一種優(yōu)先級(jí)
//如果應(yīng)用進(jìn)程沒有運(yùn)行任何組件,那么當(dāng)內(nèi)存出現(xiàn)不足時(shí),該進(jìn)程是最先被系統(tǒng)“殺死”
updateOomAdjLocked();
}
return true;
}
在attachApplicationLocked
中有兩個(gè)比較重要的方法函數(shù):
-
thread.bindApplication(…)
: 綁定Application到ActivityThread -
mStackSupervisor.attachApplicationLocked(app
) : 啟動(dòng)Activity(Android 7.0前為mMainStack.realStartActivityLocked()
)
ApplicationThread.bindApplication綁定Application到ActivityThread
在上面我們說道,ActivityThread
通過ApplicationThread
與AMS進(jìn)行通訊,所以上面的thread.bindApplication(...)
方法,就應(yīng)該是通過ApplicationThread
進(jìn)行傳達(dá)。
在ActivityThread
的內(nèi)部類ApplicationThread
中,我們找到bindApplication
方法
//ActivityThread
//內(nèi)部類ApplicationThread
private class ApplicationThread extends ApplicationThreadNative {
public final void bindApplication(...一大堆參數(shù)...) {
AppBindData data = new AppBindData();
//給data設(shè)置參數(shù)...
...
sendMessage(H.BIND_APPLICATION, data);
}
}
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
Message msg = Message.obtain();
//給msg設(shè)置參數(shù)
...
mH.sendMessage(msg);
}
發(fā)送消息是通過H
的Handler
類來完成的。
private class H extends Handler {
public static final int LAUNCH_ACTIVITY = 100;
public static final int PAUSE_ACTIVITY = 101;
...
public static final int RESUME_ACTIVITY = 107;
public static final int DESTROY_ACTIVITY = 109;
public static final int BIND_APPLICATION = 110;
public static final int EXIT_APPLICATION = 111;
...
public void handleMessage(Message msg) {
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
...
//綁定application
case BIND_APPLICATION:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
}
}
}
可以看出,這個(gè)H
類相當(dāng)于ActivityThread
和ApplicationThread
的中介人,也就是拉皮條的。
ActivityThread
通過ApplicationThread
與AMS通訊。
ApplicationThread
通過H
與ActivityThread
通訊,處理Activity事務(wù)。
那么既然H
、ApplicationThread
都在ActivityThread
類里,為何ApplicationThread
還要通過Handler
來發(fā)送消息?
- 便于集中管理,方便打印Log日志等,
H
就是這其中的大管家。 -
ActivityThread
通過ApplicationThread
和AMS進(jìn)行進(jìn)程間通信,AMS以進(jìn)程通訊的方式來完成ActivityThread
的請(qǐng)求后調(diào)用ApplicationThread
中的Binder方法,然后ApplicationThread
會(huì)向H
發(fā)送消息,H
收到消息后會(huì)將ApplicationThread
中的邏輯切換到ActivityThread
中去執(zhí)行,即切換到主線程中去執(zhí)行,這個(gè)過程就是主線程的消息循環(huán)模型。
而且有一點(diǎn)要注意的是,這個(gè)ActivityThread
并不是一個(gè)線程Thread,它是final類并且無繼承或者實(shí)現(xiàn)其它類,它的作用就是在main
方法內(nèi)消息循環(huán),處理主線程事務(wù)。(還需了解Looper及消息機(jī)制)
言歸正傳,上面ApplicationThread
給H
發(fā)送BIND_APPLICATION
標(biāo)識(shí),在H
中,通過handleBindApplication
處理Application的綁定事務(wù)。
//ActivityThread
private void handleBindApplication(AppBindData data) {
...
//根據(jù)傳遞過來的ApplicationInfo創(chuàng)建一個(gè)對(duì)應(yīng)的LoadedApk對(duì)象
data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);//獲取LoadedApk
//禁止在主線程使用網(wǎng)絡(luò)操作
if (data.appInfo.targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB) {
StrictMode.enableDeathOnNetwork();
}
//7.0引入Fileprovide
if (data.appInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
StrictMode.enableDeathOnFileUriExposure();
}
...
//創(chuàng)建進(jìn)程對(duì)應(yīng)的Android運(yùn)行環(huán)境ContextImpl
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
if ((InstrumentationInfo)ii != null) {
...
} else {
//注意Activity的所有生命周期方法都會(huì)被Instrumentation對(duì)象所監(jiān)控,
//也就說執(zhí)行Activity的生命周期方法前后一定會(huì)調(diào)用Instrumentation對(duì)象的相關(guān)方法
mInstrumentation = new Instrumentation();
}
try {
...
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;
//加載進(jìn)程對(duì)應(yīng)Package中攜帶的ContentProvider
installContentProviders(app, data.providers);
...
mInstrumentation.onCreate(data.instrumentationArgs);
try {
//這里會(huì)調(diào)用Application的onCreate方法
//故此Applcation對(duì)象的onCreate方法會(huì)比ActivityThread的main方法后調(diào)用
//但是會(huì)比這個(gè)應(yīng)用的所有activity先調(diào)用
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
...
}
} finally {
StrictMode.setThreadPolicy(savedPolicy);
}
}
如上文所述,handleBindApplication
的目的是讓一個(gè)Java進(jìn)程融入到Android體系中。
因此,該函數(shù)中的代碼主要進(jìn)行以下工作:
- 按照Android的要求,完成對(duì)進(jìn)程基本參數(shù)的設(shè)置置,包括設(shè)置進(jìn)程名、時(shí)區(qū)、資源及兼容性配置;
同時(shí)也添加了一些限制,例如主線程不能訪問網(wǎng)絡(luò)等。 - 創(chuàng)建進(jìn)程對(duì)應(yīng)的ContextImpl、LoadedApk、Application等對(duì)象,同時(shí)加載Application中的ContentProvider,并初始化Application。
- 使用
Instrumentation
監(jiān)控Activity的生命周期。(一個(gè)進(jìn)程對(duì)應(yīng)一個(gè)Instrumentation
實(shí)例)
當(dāng)完成上述工作后,新建的進(jìn)程終于加入到了Android體系。
AMS通知淘寶綁定Application并啟動(dòng)MainActivity。
ActivityStackSupervisor.attachApplicationLocked啟動(dòng)Activity
在上述代碼AMS的attachApplicationLocked
方法中,我們說道:
在
attachApplicationLocked
中有兩個(gè)比較重要的方法函數(shù),分析到這里我們的文章也要進(jìn)入尾聲了。
- thread.bindApplication(…) : 綁定Application到ActivityThread
- mStackSupervisor.attachApplicationLocked(app) : 啟動(dòng)Activity
綁定了Application之后,我們就可以啟動(dòng)Activity(淘寶MainActivity)。
//ActivityStackSupervisor
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
final String processName = app.processName;
boolean didSomething = false;
//ActivityStackSupervisor維護(hù)著終端中所有ActivityStack
//此處通過輪詢,找出前臺(tái)棧頂端的待啟動(dòng)Activity
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
if (!isFocusedStack(stack)) {
continue;
}
ActivityRecord hr = stack.topRunningActivityLocked();
if (hr != null) {
//前臺(tái)待啟動(dòng)的Activity與當(dāng)前新建的進(jìn)程一致時(shí),啟動(dòng)這個(gè)Activity
if (hr.app == null && app.uid == hr.info.applicationInfo.uid && processName.equals(hr.processName)) {
try {
//realStartActivityLocked進(jìn)行實(shí)際的啟動(dòng)工作
if (realStartActivityLocked(hr, app, true, true)) {
didSomething = true;
}
} catch (RemoteException e) {
}
}
}
}
}
return didSomething;
}
大概系統(tǒng)工程師也覺得這個(gè)啟動(dòng)過程賊雞兒繞了,最終啟動(dòng)的方法命名為realStartActivityLocked
,意味著告訴你,大伙兒不要搞暈了,這個(gè)就是最后啟動(dòng)Activity的方法了。realStartActivityLocked()方法
通過ApplicaitonThread的scheduleLaunchActivity()
調(diào)用客戶端Binder實(shí)體的方法,最后我們直搗黃龍,在ActivityStackSupervisor
方法中,我們找到如下代碼
//ActivityStackSupervisor
//通過ApplicaitonThread調(diào)用客戶端Binder實(shí)體的方法。
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage,
task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
public final void scheduleResumeActivity(IBinder token, int processState,
boolean isForward, Bundle resumeArgs) {
updateProcessState(processState, false);
sendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0);
}
看到這里想必大伙兒都明白了,AMS最后通過ApplicationThread
通知ActivityThread
啟動(dòng)Activity
,感覺這一切的通訊都像發(fā)電報(bào)一樣,鬼斧神工出神入化,皆出架構(gòu)師之目營心匠。
那么到這里我們就能推算出接下來的老套路了
ApplicationThread—> H—> ActivityThread—> 最終啟動(dòng)Activity的方法。
ActivityThread
//ActivityThread
//內(nèi)部類ApplicationThread
private class ApplicationThread extends ApplicationThreadNative {
@Override
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
CompatibilityInfo compatInfo, String referrer,
IVoiceInteractor voiceInteractor,
int procState, Bundle state, PersistableBundle persistentState,
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
updateProcessState(procState, false);
ActivityClientRecord r = new ActivityClientRecord();
//設(shè)置參數(shù)
...
//從LAUNCH_ACTIVITY這個(gè)標(biāo)識(shí)我們就可以知道,它就是用來啟動(dòng)Activity
sendMessage(H.LAUNCH_ACTIVITY, r);
}
}
private class H extends Handler {
...
//用Handler發(fā)送了一個(gè)Message。Handler的處理會(huì)最終調(diào)用handlerLaunchActivity方法
public void handleMessage(Message msg) {
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
//利用ApplicationInfo等信息得到對(duì)應(yīng)的LoadedApk,保存到ActivityClientRecord
//ActivityClientRecord包含Activity相關(guān)的信息
r.packageInfo = getPackageInfoNoCheck(r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
...
}
}
}
}
//ActivityThread
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
...
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
...
}
...
}
handleLaunchActivity
方法里有有兩個(gè)重要的函數(shù)調(diào)用:
- performLaunchActivity : 會(huì)調(diào)用Activity的onCreate、onStart、onResotreInstanceState方法
- handleResumeActivity : 會(huì)調(diào)用Activity的onResume方法
從上面的源碼可以看出,
performLaunchActivity
方法最終完成了Activity對(duì)象的創(chuàng)建和啟動(dòng)過程,并且ActivityThread通過handleResumeActivity
方法來調(diào)用被啟動(dòng)Activity的onResume這一生命周期方法。
performLaunchActivity
performLaunchActivity
這個(gè)方法主要完成了如下幾件事:
1、從ActivityClientRecord中獲取待啟動(dòng)的Activity的組件信息。
//ActivityThread的performLaunchActivity方法
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
ComponentName component = r.intent.getComponent();
if (component == null) {
component = r.intent.resolveActivity(
mInitialApplication.getPackageManager());
r.intent.setComponent(component);
}
if (r.activityInfo.targetActivity != null) {
component = new ComponentName(r.activityInfo.packageName,
r.activityInfo.targetActivity);
}
2、通過Instrumentation
的newActivity方法使用類加載器創(chuàng)建Activity對(duì)象。
//ActivityThread的performLaunchActivity方法
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
...
}
3、通過LoadedApk的makeApplication
方法來創(chuàng)建Application對(duì)象。
//ActivityThread的performLaunchActivity方法
Application app = r.packageInfo.makeApplication(false, mInstrumentation);//r.packageInfo為LoadedApk對(duì)象
其實(shí)在我們上面的bindApplication中,我們就有介紹到通過LoadedApk
創(chuàng)建Application,并且創(chuàng)建完畢后,通過Instrumentation
的callApplicationOnCreate
來調(diào)用Application的onCreate
方法
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
...
mInstrumentation.callApplicationOnCreate(app);
所以第三步是為了判斷Application是否為空,而且我們從makeApplication
方法中也能看出如果Application已經(jīng)被創(chuàng)建過了,那么就不會(huì)再重復(fù)創(chuàng)建了。
4、創(chuàng)建ContextImpl對(duì)象,并通過Activity的attach方法來完成一些重要數(shù)據(jù)的初始化。
Context appContext = createBaseContextForActivity(r, activity);//創(chuàng)建ContextImpl對(duì)象
Window window = null;
if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
window = r.mPendingRemoveWindow;
r.mPendingRemoveWindow = null;
r.mPendingRemoveWindowManager = null;
}
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window);
ContextImpl是一個(gè)很重要的數(shù)據(jù)結(jié)構(gòu),它是Context的具體實(shí)現(xiàn),Context中的大部分邏輯都是由ContextImpl來完成的。ContextImpl來完成的。ContextImpl是通過Activity的attach方法來和Activity建立關(guān)聯(lián)的,除此之外,在attach方法中Activity還會(huì)完成Window的創(chuàng)建并建立自己和Window的關(guān)聯(lián),這樣當(dāng)Window接收到外部輸入事件后就可以將事件傳遞給Activity。
5、調(diào)用Activity的onCreate方法
mInstrumentation.callActivityOnCreate(activity, r.state);
由于Activity的onCreate已經(jīng)被調(diào)用,這也意味著Activity已經(jīng)完成了整個(gè)啟動(dòng)過程。
6、調(diào)用Activity的onStart、onResotreInstanceState方法
mInstrumentation.callActivityOnCreate(activity, r.state);
...
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
public void callActivityOnCreate(Activity activity, Bundle icicle) {
prePerformCreate(activity);
activity.performCreate(icicle);
postPerformCreate(activity);
}
對(duì)activity.performCreate(icicle);
這一行代碼熟悉嗎?這一行里面就調(diào)用了傳說中的Activity的入口函數(shù)onCreate()
,不信?接著往下看Activity.performCreate()
final void performCreate(Bundle icicle) {
onCreate(icicle);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}
沒騙你吧,onCreate在這里調(diào)用了吧。
參考文章
【凱子哥帶你學(xué)Framework】Activity啟動(dòng)過程全解析