Android
系統是基於Linux
定製的一款開源的而移動端作業系統,由於其開源的特性,各大手機廠商可以針對其原始碼進行深度定製,對於開發者來說,有如此龐大且優秀的開源os
提供參考,尤其是對移動端的開發者來說,閱讀Android
系統原始碼可以幫助我們更好地理解其中的各種機制,平時束手無策的問題也可以在原始碼中尋找答案。當然光8.0的原始碼就20多個g,像全部讀完幾乎是不可能的事,我們主要以framework
為主線,以系統執行機制為分支,層層閱讀,剝開Android
系統的神祕面紗。
Android 系統架構
首先來一張google
經典的Android
系統架構圖:可以看到,從上到下主要分為4層:應用層,framework
層,系統庫和執行時,Linux
核心層。
#Android 啟動流程
這裡再上一張Android系統啟動的流程圖,可以看到系統從啟動開始是按照一個流程:Loader
->kernel
->framework
->Application
來進行的。
Loader層:
Boot Rom
:當手機處於關機狀態時,長按開機鍵開機,會引導晶片開始從固化在Rom裡預設的程式碼開始執行,然後載入載入程式到Ram
Boot Loader
:啟動Android系統之前的載入程式,主要是檢查Ram
,初始化引數等
Kernel層
Kernel
層指的就是Android核心層,這裡一般開機剛剛結束進入Android系統,Kernel
層的啟動流程如下:
- 啟動
swapper
程式(pid=0),這是系統初始化過程kernel建立的第一個程式,用於初始化程式管理、記憶體管理、載入Display
、Camera
、Binder
等驅動相關工作 - 啟動
kthreadd
程式,這是Linux
系統的核心程式,會建立核心工作執行緒kworkder
、軟中斷執行緒ksoftirqd
和thermal
等核心守護程式。kthreadd
是所有核心程式的鼻祖。
Native層
這裡的native
層主要包括由init
程式孵化的使用者空間的守護程式,bootanim
開機動畫和hal
層等。Init
是Linux
系統的守護程式,是所有使用者空間程式的鼻祖。
init
程式會孵化出ueventd
、logd
、healthd
、installd
、adbd
、lm這裡寫程式碼片
kd等使用者守護程式;init
程式還會啟動ServiceManager
(Binder服務管家)、bootanim
(開機動畫)等重要服務。init
程式孵化出Zygote
程式,Zygote
程式是Android系統第一個Java程式(虛擬機器程式),Zygote
程式是所有Java程式的父程式。
Framework層
framework
層有native
層和java
層共同組成,協調系統平穩有序的工作。framework
層主要包括以下內容:
Media Server
程式,是由init
程式fork
而來,負責啟動和管理整個C++ framework
,包含AudioFlinger
,Camera Service
等服務。Zygote
程式,由Init
程式通過解析init.rc
檔案生成,Zygote
是Android系統的第一個Java程式,是所有Java程式的父程式。System Server
程式,由Zygote
程式fork
而來,是Zygote
程式孵化的第一個子程式,負責啟動和管理整個Java Framework
,包括Ams
、Pms
等。
App層
Zygote
程式孵化的第一個App
程式是Launcher
程式,也就是我們的桌面程式,也就是我們開啟手機看到的使用者介面。因為在前面的framework
生成了各種守護程式和管理程式,對於Launcher
也就有對應的點選、長按、滑動、解除安裝等監聽。Zygote
程式也會建立Browser
、Phone
、Email
等App程式。也就是說所有的App程式都是由Zygote
程式fork
生成的。而且上層的程式全部由下層的程式進行管理,包括但不限於介面的註冊、跳轉,訊息的傳遞。
Zygote程式的啟動
瞭解了Android
系統從按下開機鍵到桌面完整執行在使用者眼前的整個流程,我們就可以針對系統的各個過程進行分析。由於是移動開發,平時最多打交道的是應用層,也是就上面的App
層,跟我們打交道最多的就是framework
層,我們主要關注framework
層是如何啟動並排程各應用程式協調工作的。從ZygoteInit
的main
方法開始,我們先看framework
啟動流程的時序圖(省略了一些步驟)大體如下:
1.ZygoteInit.main
public static void main(String argv[]) {
ZygoteServer zygoteServer = new ZygoteServer();
// Mark zygote start. This ensures that thread creation will throw
// an error.
ZygoteHooks.startZygoteNoThreadCreation();
...
try {
// Report Zygote start time to tron unless it is a runtime restart
if (!"1".equals(SystemProperties.get("sys.boot_completed"))) {
MetricsLogger.histogram(null, "boot_zygote_init",
(int) SystemClock.elapsedRealtime());
}
...
// 1.載入首個Zygote程式的時候,載入引數有start-system-server,即startSystemServer=true
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
} else if ("--enable-lazy-preload".equals(argv[i])) {
enableLazyPreload = 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]);
}
}
if (abiList == null) {
throw new RuntimeException("No ABI list supplied.");
}
// 2. 註冊zygote服務端localserversocket
zygoteServer.registerServerSocket(socketName);
...
// 3.在這裡開啟了SystemServer,也就是Ams,Pms,Wms...等一系列系統服務
if (startSystemServer) {
startSystemServer(abiList, socketName, zygoteServer);
}
Log.i(TAG, "Accepting command socket connections");
// 4.while(true) 死迴圈,除非丟擲異常系統中斷
zygoteServer.runSelectLoop(abiList);
zygoteServer.closeServerSocket();
} catch (Zygote.MethodAndArgsCaller caller) {
caller.run();
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
zygoteServer.closeServerSocket();
throw ex;
}
}
複製程式碼
ZygoteInit.main()
由native
層傳入初始化引數呼叫,這裡不再贅述,這邊主要沿Java的framework
層來分析系統的呼叫,結合上圖和程式碼註釋可以看到,載入引數有start-system-server,即startSystemServer=true賦值,緊接著下面會呼叫ZygoteServer.registerServerSocket()
,也就是這裡和ZygoteServer
的通訊用到的是LocalSocket
,我們知道跨程式呼叫最常見的呼叫方式就是LocalSocket
和aidl
,在framework
裡也有很多這樣通訊的。接下來就開啟了SystemServer
,後面是一個runSelectLoop()
,這裡其實是一個死迴圈,當丟擲異常終止則會呼叫zygoteServer.closeServerSocket()
來關閉socket
連線。我們繼續跟進startSystemServer
看具體是如何開啟系統服務的。
2.startSystemServer
/**
* Prepare the arguments and fork for the system server process.
*/
private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)
throws Zygote.MethodAndArgsCaller, RuntimeException {
...
/* Hardcoded command line to start the system server */
String args[] = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
//傳入準備引數,注意上面引數最後的"com.android.server.SystemServer"
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
/* Request to fork the system server process */
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
// pid = 0 說明建立子程式成功,SystemServer此時擁有獨立程式,可以獨立在自己的程式內操作了
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
zygoteServer.closeServerSocket();
// 處理SystemServer程式
handleSystemServerProcess(parsedArgs);
}
return true;
}
複製程式碼
這個方法不是很長,看註釋可以知道,主要是用來準備SystemServer
程式的引數和forkSystemServer
程式。前面一堆引數不用看,注意我新增中文註釋的地方,傳入的引數有一個內容為"com.android.server.SystemServer"
,這是SystemServer
類的全限定名,接下來呼叫Zygote.forkSystemSeerver()
,最後當pid=0
時,也就是說明子程式建立成功,如果這時候有兩個Zygote
程式則等待第二個Zygote
程式連線,關閉掉第一個Zygote
程式和ZygoteServer
的socket
連線。最後呼叫handleSystemServerProcess()
來處理SystemServer
程式。這裡的Zygote.forkSystemServer()
實際上是呼叫了native
層的forkSystemServer()
來fork子程式。這裡主要跟進handleSystemServerProcess()
看看是如何完成新fork的SystemServer
程式的剩餘工作的。
3.handleSystemServerProcess
/**
* Finish remaining work for the newly forked system server process.
*/
private static void handleSystemServerProcess(
ZygoteConnection.Arguments parsedArgs)
throws Zygote.MethodAndArgsCaller {
...
// 預設為null,走Zygote.init()流程
if (parsedArgs.invokeWith != null) {
...
} else {
ClassLoader cl = null;
if (systemServerClasspath != null) {
// 建立類載入器,並賦予當前執行緒
cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);
Thread.currentThread().setContextClassLoader(cl);
}
/*
* Pass the remaining arguments to SystemServer.
*/
ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
}
/* should never reach here */
}
複製程式碼
parsedArgs.invokeWith
預設是為null的,也就是走else
流程,可以看到先建立了一個類載入器並賦予了當前執行緒,然後進入了ZygoteInit.zygoteInit()
。
4.ZygoteInit.zygoteInit()
/**
* The main function called when started through the zygote process. This
* could be unified with main(), if the native code in nativeFinishInit()
* were rationalized with Zygote startup.<p>
*
* Current recognized args:
* <ul>
* <li> <code> [--] <start class name> <args>
* </ul>
*
* @param targetSdkVersion target SDK version
* @param argv arg strings
*/
public static final void zygoteInit(int targetSdkVersion, String[] argv,
ClassLoader classLoader) throws Zygote.MethodAndArgsCaller {
if (RuntimeInit.DEBUG) {
Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
RuntimeInit.redirectLogStreams();
RuntimeInit.commonInit();
// Zygote初始化
ZygoteInit.nativeZygoteInit();
// 應用初始化
RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
複製程式碼
這個方法不是很長,主要工作是Zygote
的初始化和Runtime
的初始化。Zygote
的初始化呼叫了native
方法,裡面的大致工作是開啟/dev/binder
驅動裝置,建立一個新的binder
執行緒,呼叫talkWithDriver()
不斷地跟驅動互動。
進入RuntimeInit.applicationInit()
檢視具體應用初始化流程。
5.RuntimeInit.applicationInit
protected static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws Zygote.MethodAndArgsCaller {
// If the application calls System.exit(), terminate the process
// immediately without running any shutdown hooks. It is not possible to
// shutdown an Android application gracefully. Among other things, the
// Android runtime shutdown hooks close the Binder driver, which can cause
// leftover running threads to crash before the process actually exits.
nativeSetExitWithoutCleanup(true);
// We want to be fairly aggressive about heap utilization, to avoid
// holding on to a lot of memory that isn't needed.
VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
final Arguments args;
try {
// 解析引數
args = new Arguments(argv);
} catch (IllegalArgumentException ex) {
Slog.e(TAG, ex.getMessage());
// let the process exit
return;
}
// The end of of the RuntimeInit event (see #zygoteInit).
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
// Remaining arguments are passed to the start class's static main
invokeStaticMain(args.startClass, args.startArgs, classLoader);
}
複製程式碼
這個方法也不是很長,前面的一些配置略過,主要看解析引數和invokeStaticMain()
,顧名思義,這裡的目的是通過反射呼叫靜態的main方法,那麼呼叫的是哪個類的main
方法,我們看傳入的引數是args.startClass
,我們追溯引數的傳遞過程,發現之前提到的一系列args
被封裝進ZygoteConnection.Arguments
類中,這一系列引數原本是
String args[] = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
"com.android.server.SystemServer",
};
複製程式碼
可以看到,唯一的類的全限定名是com.android.server.SystemServer
,追述args = new Arguments(argv)
的原始碼也可以找到答案:
Arguments(String args[]) throws IllegalArgumentException {
parseArgs(args);
}
private void parseArgs(String args[])
throws IllegalArgumentException {
int curArg = 0;
for (; curArg < args.length; curArg++) {
String arg = args[curArg];
if (arg.equals("--")) {
curArg++;
break;
} else if (!arg.startsWith("--")) {
break;
}
}
if (curArg == args.length) {
throw new IllegalArgumentException("Missing classname argument to RuntimeInit!");
}
// startClass 為args的最後一個引數
startClass = args[curArg++];
startArgs = new String[args.length - curArg];
System.arraycopy(args, curArg, startArgs, 0, startArgs.length);
}
}
複製程式碼
6.RuntimeInit.invokeStaticMain
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
throws Zygote.MethodAndArgsCaller {
Class<?> cl;
try {
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}
Method m;
try {
m = cl.getMethod("main", new Class[] { String[].class });
} catch (NoSuchMethodException ex) {
throw new RuntimeException(
"Missing static main on " + className, ex);
} catch (SecurityException ex) {
throw new RuntimeException(
"Problem getting static main on " + className, ex);
}
int modifiers = m.getModifiers();
if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
throw new RuntimeException(
"Main method is not public and static on " + className);
}
/*
* This throw gets caught in ZygoteInit.main(), which responds
* by invoking the exception's run() method. This arrangement
* clears up all the stack frames that were required in setting
* up the process.
*/
throw new Zygote.MethodAndArgsCaller(m, argv);
}
複製程式碼
可以看到,這邊走的就是正常的一個反射流程,會對main
方法的引數、修飾符等校驗,有問題丟擲RuntimeException
執行時異常,沒問題就丟擲一個Zygote.MethodAndArgsCaller
,這一步的處理可以說是非常奇怪了,既然執行完畢為什麼不直接invoke而是丟擲異常呢,我們可以看到英文註釋的大概解釋,這個異常丟擲在ZygoteInit.main()
方法,執行了異常的run方法,其目的是清除設定中的所有堆疊幀,既然如此我們回到ZygoteInit.main()
方法,果然:
try{
...
}catch (Zygote.MethodAndArgsCaller caller) {
caller.run();
}
複製程式碼
丟擲該異常呼叫了caller.run()
方法,那我們看這裡做了什麼:
public static class MethodAndArgsCaller extends Exception
implements Runnable {
/** method to call */
private final Method mMethod;
/** argument array */
private final String[] mArgs;
public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;
mArgs = args;
}
public void run() {
try {
mMethod.invoke(null, new Object[] { mArgs });
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InvocationTargetException ex) {
Throwable cause = ex.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
} else if (cause instanceof Error) {
throw (Error) cause;
}
throw new RuntimeException(ex);
}
}
}
複製程式碼
可以看到,這裡呼叫了mMethod.invoke(null, new Object[] { mArgs })
,也就是執行了SystemServer
的main
方法。
7.SystemServer.main
public static void main(String[] args) {
new SystemServer().run();
}
複製程式碼
try {
...
//主執行緒在當前程式
Looper.prepareMainLooper();
...
// 初始化系統上下文
createSystemContext();
// 1.建立SystemServiceManager
mSystemServiceManager = new SystemServiceManager(mSystemContext);
mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
// Prepare the thread pool for init tasks that can be parallelized
SystemServerInitThreadPool.get();
} finally {
traceEnd();
}
...
try {
traceBeginAndSlog("StartServices");
//2.開啟一些重要的系統服務
startBootstrapServices();
startCoreServices();
startOtherServices();
SystemServerInitThreadPool.shutdown();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
} finally {
traceEnd();
}
...
// Loop forever.
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
複製程式碼
可以看到,這邊主要的工作,建立主執行緒Looper
迴圈器,初始化系統上下文,最關鍵的還是後面的開啟一系列的服務,這些服務就包括了系統服務,跟進sartBootstrapService()
看看是如何初始化系統服務的。
8.SystemServer.startBootstrapServices
...
SystemServerInitThreadPool.get().submit(SystemConfig::getInstance, TAG_SYSTEM_CONFIG);
// 阻塞等待與installd建立socket通道
Installer installer = mSystemServiceManager.startService(Installer.class);
// 1. 在這裡開啟了Ams
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService();
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
mActivityManagerService.setInstaller(installer);
...
// 2.在這裡開啟了PowerManagerService
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
// 3.Ams 初始化PowerManager
mActivityManagerService.initPowerManagement();
// Bring up recovery system in case a rescue party needs a reboot
if (!SystemProperties.getBoolean("config.disable_noncore", false)) {
traceBeginAndSlog("StartRecoverySystemService");
//
mSystemServiceManager.startService(RecoverySystemService.class);
traceEnd();
}
mSystemServiceManager.startService(LightsService.class);
mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
mFirstBoot = mPackageManagerService.isFirstBoot();
mPackageManager = mSystemContext.getPackageManager();
mSystemServiceManager.startService(UserManagerService.LifeCycle.class);
mSystemServiceManager.startService(new OverlayManagerService(mSystemContext, installer));
複製程式碼
可以看見啟動了很多的系統服務,其中很多的服務目前也不是很瞭解,主要的是ActivityMangerService
和PackageManagerService
等主要管理系統的一些服務。自此,Android系統的SystemServer
已經啟動,並且其相關的各種系統服務已經啟動,Ams
等重要系統服務也均已開啟。Ams
是貫穿Android系統的核心服務,負責系統四大元件的啟動、切換及其生命週期管理和排程等工作,各個應用程式App作為獨立程式需要通過Binder
與Ams
進行通訊,而Ams
在SystemServer
中通過LocalSocket
與Zygote
進行通訊。不管是對於系統執行的原理,還是各元件的排程過程,理解Ams
的工作原理十分重要,接下來將以此為主線,分別分析Ams
、四大元件等的啟動流程和生命週期的管理等。
參考資料
Android 8.0.1原始碼