作為一名 Android 程序員,你有沒有想過:那么復(fù)雜的 Android 系統(tǒng),它是怎樣運行起來的,我們的 App 又是怎樣被 Android 系統(tǒng)加載后呈現(xiàn)在屏幕上的呢?Android 系統(tǒng)的啟動是一個比較復(fù)雜的過程,涉及到了一些我們沒有接觸過的知識,本文將基于 Android Nougat 最新的代碼上講述 Android 系統(tǒng)的啟動流程。
Bootloader —— 第一個程序
當(dāng)按下電源鍵(加電)或者系統(tǒng)重啟(復(fù)位)的時候,引導(dǎo)芯片會從 ROM(這里一般指 Flash ROM,即閃存)中預(yù)定義的位置將 Bootloader 載入到 RAM 中,接著,Bootloader 將會把 Linux 內(nèi)核載入到 RAM 中并啟動。
Bootloader 是在系統(tǒng)內(nèi)核運行之前運行的一段小程序,也是系統(tǒng)運行的第一個程序,它的主要作用是:
- 初始化 RAM(一般指內(nèi)存)
- 初始化硬件設(shè)備
- 加載內(nèi)核和內(nèi)存空間影像圖
- 跳轉(zhuǎn)到內(nèi)核
init 進程 —— 1 號進程
Linux 內(nèi)核啟動過程中會創(chuàng)建 init 進程,init 進程是用戶空間的第一個進程(pid=1),對應(yīng)的可執(zhí)行程序的源文件文件為 /system/core/init/Init.cpp,它的 main 方法如下:
int main(int argc, char** argv) {
if (!strcmp(basename(argv[0]), "ueventd")) {
return ueventd_main(argc, argv);
}
if (!strcmp(basename(argv[0]), "watchdogd")) {
return watchdogd_main(argc, argv);
}
umask(0);
add_environment("PATH", _PATH_DEFPATH);
bool is_first_stage = (argc == 1) || (strcmp(argv[1], "--second-stage") != 0);
// 創(chuàng)建文件并掛載
if (is_first_stage) {
mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
mkdir("/dev/pts", 0755);
mkdir("/dev/socket", 0755);
mount("devpts", "/dev/pts", "devpts", 0, NULL);
#define MAKE_STR(x) __STRING(x)
mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC));
mount("sysfs", "/sys", "sysfs", 0, NULL);
}
open_devnull_stdio();
klog_init();
klog_set_level(KLOG_NOTICE_LEVEL);
NOTICE("init %s started!\n", is_first_stage ? "first stage" : "second stage");
if (!is_first_stage) {
// Indicate that booting is in progress to background fw loaders, etc.
close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));
// 初始化屬性相關(guān)資源
property_init();
process_kernel_dt();
process_kernel_cmdline();
export_kernel_boot_props();
}
...
// 啟動屬性服務(wù)
start_property_service();
const BuiltinFunctionMap function_map;
Action::set_function_map(&function_map);
Parser& parser = Parser::GetInstance();
parser.AddSectionParser("service",std::make_unique<ServiceParser>());
parser.AddSectionParser("on", std::make_unique<ActionParser>());
parser.AddSectionParser("import", std::make_unique<ImportParser>());
// 解析init.rc配置文件
parser.ParseConfig("/init.rc");
...
while (true) {
if (!waiting_for_exec) {
am.ExecuteOneCommand();
restart_processes();
}
int timeout = -1;
if (process_needs_restart) {
timeout = (process_needs_restart - gettime()) * 1000;
if (timeout < 0)
timeout = 0;
}
if (am.HasMoreCommands()) {
timeout = 0;
}
bootchart_sample(&timeout);
epoll_event ev;
int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, timeout));
if (nr == -1) {
ERROR("epoll_wait failed: %s\n", strerror(errno));
} else if (nr == 1) {
((void (*)()) ev.data.ptr)();
}
}
return 0;
}
init 進程的職責(zé)主要有四個:
- 解析和運行所有 init.rc 文件
- 生成設(shè)備驅(qū)動節(jié)點
- 處理子進程的終結(jié)
- 提供屬性服務(wù)
這里重點看第一點,init.rc 是一個配置文件,內(nèi)容大概如下:
import /init.environ.rc
import /init.usb.rc
import /init.${ro.hardware}.rc
import /init.usb.configfs.rc
import /init.${ro.zygote}.rc
on early-init
# Set init and its forked children's oom_adj.
write /proc/1/oom_score_adj -1000
# Disable sysrq from keyboard
write /proc/sys/kernel/sysrq 0
# Set the security context of /adb_keys if present.
restorecon /adb_keys
# Shouldn't be necessary, but sdcard won't start without it. http://b/22568628.
mkdir /mnt 0775 root system
# Set the security context of /postinstall if present.
restorecon /postinstall
start ueventd
...(省略)...
service flash_recovery /system/bin/install-recovery.sh
class main
oneshot
rc 文件由 Android 初始化語言編寫,rc 文件主要包含 Action、Service、Command、Options 等,這些操作都由特殊的命令組成。
在開頭幾行代碼中,import 導(dǎo)入了幾個 rc 文件,事實上,在 system/core/rootdir 目錄下,有多個 init.XXX.rc 文件,在不同的硬件環(huán)境下,相應(yīng)的 init.XXX.rc 文件會被導(dǎo)入,比如在 64 位操作系統(tǒng)中,init.zygote64.rc 文件將會被導(dǎo)入,它的內(nèi)容如下:
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
這幾行代碼表示啟動一個名字為 zygote、 執(zhí)行文件路徑為 /system/bin/app_process64、參數(shù)為 -Xzygote /system/bin --zygote --start-system-server 的進程。
除了 zygote 進程,還有許多關(guān)鍵進程都是由 init 進程通過讀取相應(yīng)的 rc 文件進行啟動的,如 servicemanager、surfaceflinger 和 mediaserver 進程等等,這些進程都是保證系統(tǒng)運行必不可少的。限于篇幅,下面只列舉出比較關(guān)鍵的部分。
servicemanager 進程 —— Binder 服務(wù)的總管
我在文章借助 AIDL 理解 Android Binder 機制——Binder 來龍去脈中講到“Binder 通信模型和通信過程”的時候提到過 ServerManager,它是 Binder IPC 的核心,是上下文的管理者,Binder 服務(wù)端必須先向 ServerManager 注冊才能夠為客戶端提供服務(wù),Binder 客戶端在與服務(wù)端通信之前需要從 ServerManager 中查找并獲取 Binder 服務(wù)端的引用。然而 ServerManager 在向 Binder 驅(qū)動申請成為上下文管理者的時候又涉及到了 Binder IPC 過程,這時候應(yīng)該怎么處理呢?答案在后文講解。
servicemanager 進程是通過解析 servicemanager.rc 文件來啟動的,對應(yīng)的代碼如下:
service servicemanager /system/bin/servicemanager
class core
user system
group system readproc
critical
onrestart restart healthd
onrestart restart zygote
onrestart restart audioserver
onrestart restart media
onrestart restart surfaceflinger
onrestart restart inputflinger
onrestart restart drm
onrestart restart cameraserver
writepid /dev/cpuset/system-background/tasks
servicemanager 進程對應(yīng)可執(zhí)行程序的源文件為 framework/native/cmds/servicemanager/service_manager.c,簡化后的代碼如下:
int main(int argc, char **argv) {
struct binder_state *bs;
// 打開binder驅(qū)動,申請 128k 字節(jié)大小的內(nèi)存空間
bs = binder_open(128*1024);
...
// 成為上下文管理者
if (binder_become_context_manager(bs)) {
return -1;
}
// 驗證 selinux 權(quán)限,判斷進程是否有權(quán)注冊或查看指定服務(wù)
selinux_enabled = is_selinux_enabled();
sehandle = selinux_android_service_context_handle();
selinux_status_open(true);
if (selinux_enabled > 0) {
if (sehandle == NULL) {
abort();
}
if (getcon(&service_manager_context) != 0) {
abort();
}
}
...
// 進入無限循環(huán),處理 client 端發(fā)來的請求
binder_loop(bs, svcmgr_handler);
return 0;
}
這里重點關(guān)注兩點,首先,在申請了一塊大小為 128k 的內(nèi)存空間并驗證 selinux 權(quán)限后,接著調(diào)用 framework/native/cmds/servicemanager/binder.c 中的 binder_become_context_manager 方法:
int binder_become_context_manager(struct binder_state *bs) {
// 通過ioctl,發(fā)送 BINDER_SET_CONTEXT_MGR 指令
return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}
然后,調(diào)用 binder_loop 方法進入循環(huán)來處理 client 發(fā)來的請求,注意第二個參數(shù)是一個方法體,用于處理各種狀態(tài)回調(diào):
int svcmgr_handler(struct binder_state *bs,
struct binder_transaction_data *txn,
struct binder_io *msg,
struct binder_io *reply)
{
struct svcinfo *si;
uint16_t *s;
size_t len;
uint32_t handle;
uint32_t strict_policy;
int allow_isolated;
...
strict_policy = bio_get_uint32(msg);
s = bio_get_string16(msg, &len);
...
switch(txn->code) {
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE:
// 獲取服務(wù)名
s = bio_get_string16(msg, &len);
// 根據(jù)名稱查找相應(yīng)服務(wù)
handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid);
bio_put_ref(reply, handle);
return 0;
case SVC_MGR_ADD_SERVICE:
// 獲取服務(wù)名
s = bio_get_string16(msg, &len);
handle = bio_get_ref(msg);
allow_isolated = bio_get_uint32(msg) ? 1 : 0;
// 注冊指定服務(wù)
if (do_add_service(bs, s, len, handle, txn->sender_euid,
allow_isolated, txn->sender_pid))
return -1;
break;
}
}
servicemanager 進程在啟動過程的工作內(nèi)容如下:
- 調(diào)用 binder_open 方法打開 Binder 驅(qū)動,并申請分配一塊 128k 的內(nèi)存空間
- 調(diào)用 binder_become_context_manager 方法發(fā)送 BINDER_SET_CONTEXT_MGR 給 Binder 驅(qū)動,使自己成為上下文管理者
- 驗證 selinux 權(quán)限,判斷進程是否有注冊或查看指定服務(wù)的權(quán)限
- 調(diào)用 binder_loop 方法進入循環(huán)狀態(tài),等待 Client 請求
- 根據(jù)服務(wù)名稱注冊服務(wù)·
- 接收 Binder 死亡通知
zygote 進程 —— Java 進程的始祖
通過解析 init.rc 文件,
zygote 進程對應(yīng)的可執(zhí)行程序的源文件為 frameworks/base/cmds/app_process/App_main.cpp,它的 main 方法如下:
int main(int argc, char* const argv[])
{
...
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
...
Vector<String8> args;
if (!className.isEmpty()) {
args.add(application ? String8("application") : String8("tool"));
runtime.setClassNameAndArgs(className, argc - i, argv + i);
} else {
maybeCreateDalvikCache();
if (startSystemServer) {
args.add(String8("start-system-server"));
}
char prop[PROP_VALUE_MAX];
if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
ABI_LIST_PROPERTY);
return 11;
}
String8 abiFlag("--abi-list=");
abiFlag.append(prop);
args.add(abiFlag);
for (; i < argc; ++i) {
args.add(String8(argv[i]));
}
}
if (!niceName.isEmpty()) {
runtime.setArgv0(niceName.string());
set_process_name(niceName.string());
}
if (zygote) {
// 調(diào)用 AppRuntime 父類 AndroidRuntime 的 start 方法創(chuàng)建 zygote 進程
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
return 10;
}
}
調(diào)用 frameworks/base/core/jni/AndroidRuntime.cpp 的 start 方法:
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
...
/* start the virtual machine */
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
// 啟動 DVM
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
onVmCreated(env);
// 注冊 JNI 方法
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
stringClass = env->FindClass("java/lang/String");
assert(stringClass != NULL);
// 創(chuàng)建數(shù)組
strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
assert(strArray != NULL);
// 從 app_main 的 main 函數(shù)得知 className 為 com.android.internal.os.ZygoteInit
classNameStr = env->NewStringUTF(className);
assert(classNameStr != NULL);
env->SetObjectArrayElement(strArray, 0, classNameStr);
for (size_t i = 0; i < options.size(); ++i) {
jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
assert(optionsStr != NULL);
env->SetObjectArrayElement(strArray, i + 1, optionsStr);
}
char* slashClassName = toSlashClassName(className);
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
// 找到 ZygoteInit 的 main 函數(shù)
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
// 通過 JNI 調(diào)用 ZygoteInit 的 main 函數(shù)
env->CallStaticVoidMethod(startClass, startMeth, strArray);
if (env->ExceptionCheck())
threadExitUncaughtException(env);
}
}
...
}
通過 JNI 的方式進入 frameworks/base/core/java/com/android/internal/os/ZygoteInit.java:
public static void main(String argv[]) {
...
try {
...
// 注冊Zygote用的Socket
registerZygoteSocket(socketName);
...
// 預(yù)加載類和資源
preload();//2
...
if (startSystemServer) {
// 啟動SystemServer進程
startSystemServer(abiList, socketName);
}
Log.i(TAG, "Accepting command socket connections");
// 等待客戶端請求
runSelectLoop(abiList);
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
ZygoteInit.java 的 registerZygoteSocket 方法:
private static void registerZygoteSocket(String socketName) {
if (sServerSocket == null) {
int fileDesc;
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
try {
String env = System.getenv(fullSocketName);
fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) {
throw new RuntimeException(fullSocketName + " unset or invalid", ex);
}
try {
FileDescriptor fd = new FileDescriptor();
fd.setInt$(fileDesc);
// 創(chuàng)建 Socket 客戶端
sServerSocket = new LocalServerSocket(fd);
} catch (IOException ex) {
throw new RuntimeException(
"Error binding to local socket '" + fileDesc + "'", ex);
}
}
}
ZygoteInit.java 的 startSystemServer 方法:
private static boolean startSystemServer(String abiList, String socketName)
throws MethodAndArgsCaller, RuntimeException {
...
/* Hardcoded command line to start the system server */
// SystemServer 啟動參數(shù)
String args[] = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,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 {
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
// 調(diào)用 Zygote.java fock 出新線程,名字叫 system_server
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
// pid 為 0 則為 fock 出來的子線程
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
// 啟動 SystemServer 進程
handleSystemServerProcess(parsedArgs);
}
return true;
}
frameworks/base/core/java/com/android/internal/os/Zygote.java 的 forkAndSpecialize 方法:
public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
String instructionSet, String appDataDir) {
VM_HOOKS.preFork();
// 調(diào)用 Native 層的方法 fock 出子線程
int pid = nativeForkAndSpecialize(uid, gid, gids, debugFlags, rlimits,
mountExternal, seInfo, niceName, fdsToClose, instructionSet, appDataDir);
// Enable tracing as soon as possible for the child process.
if (pid == 0) {// fock 出來的子線程中執(zhí)行
Trace.setTracingEnabled(true);
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
}
VM_HOOKS.postForkCommon();
return pid;
}
ZygoteInit.java 的 runSelectLoop 方法:
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
// sServerSocket 對象就是剛才在 registerZygoteSocket 方法中創(chuàng)建的服務(wù)端 Socket
fds.add(sServerSocket.getFileDescriptor());
peers.add(null);
// 循環(huán)讀取狀態(tài)
while (true) {
StructPollfd[] pollFds = new StructPollfd[fds.size()];
for (int i = 0; i < pollFds.length; ++i) {
pollFds[i] = new StructPollfd();
pollFds[i].fd = fds.get(i);
pollFds[i].events = (short) POLLIN;
}
try {
Os.poll(pollFds, -1);
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}
for (int i = pollFds.length - 1; i >= 0; --i) {
// 讀取的狀態(tài)不是客戶端連接或者數(shù)據(jù)請求時,進入下一次循環(huán)
if ((pollFds[i].revents & POLLIN) == 0) {
continue;
}
if (i == 0) {// i = 0 表示跟客戶端 Socket 連接上了
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {// i > 0 表示接收到客戶端 Socket 發(fā)送過來的請求
// runOnce 方法創(chuàng)建一個新的應(yīng)用程序進程
boolean done = peers.get(i).runOnce();
if (done) {
peers.remove(i);
fds.remove(i);
}
}
}
}
}
frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java 的 runOnce 方法:
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
String args[];
Arguments parsedArgs = null;
FileDescriptor[] descriptors;
try {
// 讀取 socket 客戶端發(fā)送過來的參數(shù)列表
args = readArgumentList();
descriptors = mSocket.getAncillaryFileDescriptors();
} catch (IOException ex) {
// EOF reached.
closeSocket();
return true;
}
...
try {
// 將 socket 客戶端傳遞過來的參數(shù),解析成 Arguments 對象格式
parsedArgs = new Arguments(args);
...
// 同樣調(diào)用 Zygote.java 的 forkAndSpecialize 方法 fock 出子進程
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
parsedArgs.appDataDir);
} catch (Exception e) {
...
}
try {
if (pid == 0) {
// 子進程執(zhí)行
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
// 進入子進程流程
handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
return true;
} else {
// 父進程執(zhí)行
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
}
} finally {
IoUtils.closeQuietly(childPipeFd);
IoUtils.closeQuietly(serverPipeFd);
}
}
從 App_main 開始,zygote 啟動過程的時序圖如下:
可以看到,這個過程中 zygote 首先啟動了 AndroidRuntime 并通過它反射調(diào)用了 ZygoteInit.main() 方法,由此進入了 Java 的世界,因此 zygote 是 Java 層的第一個進程,也是其他 Java 進程的始祖,其他 Java 進程的創(chuàng)建必須依賴 zygote。
zygote 進程的任務(wù)分別是:
- 創(chuàng)建 AppRuntime(繼承自 AndroidRuntime), 并調(diào)用它的 start 方法
- 調(diào)用 AndroidRuntime 的 startVM() 方法創(chuàng)建 DVM(Dalvik Virtual Machine),并調(diào)用 startReg() 方法為 DVM 注冊 JNI
- 通過 JNI 調(diào)用 ZygoteInit.main() 方法,第一次進入 Java 的世界
- 調(diào)用 registerZygoteSocket() 函數(shù)建立 Socket 通道,使 zygote 進程成為 Socket 服務(wù)端,并通過 runSelectLoop() 函數(shù)等待 ActivityManagerService 發(fā)送請求創(chuàng)建新的應(yīng)用程序進程
- 調(diào)用 startSystemServer() 函數(shù) fock 出 system_server 進程
system_server 進程 —— 承載 framework 層核心業(yè)務(wù)
接下來分別講解 system_server 進程的啟動過程和 system_server 進程的執(zhí)行過程。
1.system_server 進程的啟動過程
在上一小節(jié)中我們已經(jīng)知道,zygote 進程在啟動的過程中會通過 startSystemServer 方法 fock 出了一個叫 system_server 的進程,然后再該方法內(nèi)執(zhí)行了 handleSystemServerProcess 方法:
private static void handleSystemServerProcess(
ZygoteConnection.Arguments parsedArgs)
throws ZygoteInit.MethodAndArgsCaller {
/** 由于 fock 出來的 system_server 進程會復(fù)制 zygote 進程的地址空間,因此它也得到了 zygote
進程中的 Socket,這個 Socket 對它來說并無用處,這里將其關(guān)閉 **/
closeServerSocket();
...
if (parsedArgs.invokeWith != null) {
...
} else {
ClassLoader cl = null;
if (systemServerClasspath != null) {
cl = createSystemServerClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);
Thread.currentThread().setContextClassLoader(cl);
}
// 出現(xiàn)新的類 RuntimeInit,調(diào)用了它的 zygoteInit 方法
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
}
}
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java 的 zygoteInit 方法:
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");
redirectLogStreams();
commonInit();
/** 通過 Native 層中 AndroidRuntime.cpp 的 JNI 方法最終調(diào)用 app_main.cpp 的 onZygoteInit 方法
啟動 Binder 線程池, 使 system_server 進程可以使用 Binder 與其他進程通信 **/
nativeZygoteInit();
// 繼續(xù)往下調(diào)用
applicationInit(targetSdkVersion, argv, classLoader);
}
RuntimeInit 的 applicationInit 方法:
private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
...
invokeStaticMain(args.startClass, args.startArgs, classLoader);
}
RuntimeInit 的 invokeStaticMain 方法:
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
Class<?> cl;
try {
/** className 為 ZygoteInit.java 中 startSystemServer 方法
傳遞過來的 "com.android.server.SystemServer",這里通過反射得到 SystemServer 類 **/
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className, ex);
}
Method m;
try {
// 找到 SystemServer 類的 main 方法
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);
}
/** 將 main 方法包裝在 ZygoteInit.MethodAndArgsCaller 類中并作為異常拋出
捕獲異常的地方在上一小節(jié)中 ZygoteInit.java 的 main 方法 **/
throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java 的 main 方法:
public static void main(String argv[]) {
...
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
// 接收到 caller 對象后調(diào)用它的 run 方法
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
ZygoteInit 的 MethodAndArgsCaller 類是一個 Exception 類,同時也實現(xiàn)了 Runnable 接口:
public static class MethodAndArgsCaller extends Exception
implements Runnable {
private final Method mMethod;
private final String[] mArgs;
public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;
mArgs = args;
}
public void run() {
try {
// 調(diào)用傳遞過來的 mMethod
mMethod.invoke(null, new Object[] { mArgs });
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InvocationTargetException ex) {
...
}
}
}
這樣,system_server 進程便啟動起來并進入了 SystemServer.java 的 main 方法。
這里需要思考一下,為什么需要拋出異常到 ZygoteInit 中執(zhí)行?官方解釋就是拋出異常的時候 Android 虛擬機會清空該進程堆內(nèi)存中的棧幀,因此前面一系列啟動 system_server 進程的過程中方法調(diào)用過程就被清除了,節(jié)省了堆棧的空間,使 ZygoteInit.java 的 main 方法處于所有 Java 進程的方法棧中的棧頂。另外,從最新 Android Pie 的代碼中看,這個過程已經(jīng)變成在每一步中將包裝好的 MethodAndArgsCaller 對象作為返回值返回,最后在 ZygoteInit 執(zhí)行對象的 call 方法,這樣每個方法都執(zhí)行了返回過程,自然在堆棧中對應(yīng)的棧幀也被彈出棧了。
2.system_server 進程的執(zhí)行過程
查看 frameworks/base/services/java/com/android/server/SystemServer.java 的源碼:
/**
* The main entry point from zygote.
*/
public static void main(String[] args) {
// 調(diào)用 run 方法
new SystemServer().run();
}
private void run() {
...
// 加載 libandroid_servers.so
System.loadLibrary("android_servers");
...
// 創(chuàng)建 SystemServiceManager
mSystemServiceManager = new SystemServiceManager(mSystemContext);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
...
try {
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices");
// 啟動引導(dǎo)服務(wù)
startBootstrapServices();
// 啟動核心服務(wù)
startCoreServices();
// 啟動其他服務(wù)
startOtherServices();
} catch (Throwable ex) {
...
} finally {
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
...
}
可以看到,在 run 方法中,主要執(zhí)行了啟動引導(dǎo)服務(wù)、核心服務(wù)和其他服務(wù)的任務(wù),這些服務(wù)加起來一共有 80 多個,它們對應(yīng)這個各種不同的功能,部分服務(wù)如下:
引導(dǎo)服務(wù) | 作用 |
---|---|
Installer | 系統(tǒng)安裝apk時的一個服務(wù)類,啟動完成Installer服務(wù)之后才能啟動其他的系統(tǒng)服務(wù) |
ActivityManagerService | 負(fù)責(zé)四大組件的啟動、切換、調(diào)度。 |
PowerManagerService | 計算系統(tǒng)中和Power相關(guān)的計算,然后決策系統(tǒng)應(yīng)該如何反應(yīng) |
LightsService | 管理和顯示背光LED |
DisplayManagerService | 用來管理所有顯示設(shè)備 |
UserManagerService | 多用戶模式管理 |
SensorService | 為系統(tǒng)提供各種感應(yīng)器服務(wù) |
PackageManagerService | 用來對apk進行安裝、解析、刪除、卸載等等操作 |
核心服務(wù) | 作用 |
---|---|
BatteryService | 管理電池相關(guān)的服務(wù) |
UsageStatsService | 收集用戶使用每一個APP的頻率、使用時常 |
WebViewUpdateService | WebView更新服務(wù) |
其他服務(wù) | 作用 |
---|---|
CameraService | 攝像頭相關(guān)服務(wù) |
AlarmManagerService | 全局定時器管理服務(wù) |
InputManagerService | 管理輸入事件 |
WindowManagerService | 窗口管理服務(wù) |
VrManagerService | VR模式管理服務(wù) |
BluetoothService | 藍牙管理服務(wù) |
NotificationManagerService | 通知管理服務(wù) |
DeviceStorageMonitorService | 存儲相關(guān)管理服務(wù) |
LocationManagerService | 定位管理服務(wù) |
AudioService | 音頻相關(guān)管理服務(wù) |
... | ... |
小結(jié)
system_server 進程在啟動過程中完成的工作分別是:
- 啟動 Binder 線程池,使進程可以通過 Binder 與其他進程進程通信
- 創(chuàng)建 SystemServiceManager
- 使用 SystemServiceManager 對各種系統(tǒng)服務(wù)進行創(chuàng)建、啟動和生命周期管理
Launcher —— Android 系統(tǒng)的“桌面”
在上一節(jié) frameworks/base/services/java/com/android/server/SystemServer.java 的 main 方法中,有一句:
private void startOtherServices() {
...
// 調(diào)用 AMS 的 systemReady 方法
mActivityManagerService.systemReady(new Runnable() {
@Override
public void run() {
...
}
}
...
}
繼續(xù)跟蹤:
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java:
public void systemReady(final Runnable goingCallback) {
...
synchronized (this) {
...
// 調(diào)用 ActivityStackSupervisor 的 resumeFocusedStackTopActivityLocked 方法
mStackSupervisor.resumeFocusedStackTopActivityLocked();
mUserController.sendUserSwitchBroadcastsLocked(-1, currentUserId);
}
}
frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java:
boolean resumeFocusedStackTopActivityLocked(ActivityStack targetStack, ActivityRecord target,
ActivityOptions targetOptions) {
if (targetStack != null && isFocusedStack(targetStack)) {
// 調(diào)用 ActivityStack 的 resumeTopActivityUncheckedLocked 方法
return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
if (r == null || r.state != RESUMED) {
mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
}
return false;
}
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
if (mStackSupervisor.inResumeTopActivity) {
return false;
}
boolean result = false;
try {
// Protect against recursion.
mStackSupervisor.inResumeTopActivity = true;
if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) {
mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN;
mService.updateSleepIfNeededLocked();
}
// 調(diào)用 resumeTopActivityInnerLocked 方法
result = resumeTopActivityInnerLocked(prev, options);
} finally {
mStackSupervisor.inResumeTopActivity = false;
}
return result;
}
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
...
// 回到 ActivityStackSupervisor 的 resumeHomeStackTask 方法
return isOnHomeDisplay() && mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, "prevFinished");
...
}
frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java:
boolean resumeHomeStackTask(int homeStackTaskType, ActivityRecord prev, String reason) {
...
if (r != null && !r.finishing) {
mService.setFocusedActivityLocked(r, myReason);
return resumeFocusedStackTopActivityLocked(mHomeStack, prev, null);
}
// 再次回到 AMS 的 startHomeActivityLocked 方法
return mService.startHomeActivityLocked(mCurrentUser, myReason);
}
boolean startHomeActivityLocked(int userId, String reason) {
if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
&& mTopAction == null) {
return false;
}
// 獲取 Intent
Intent intent = getHomeIntent();
ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
if (aInfo != null) {
intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
aInfo = new ActivityInfo(aInfo);
aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
ProcessRecord app = getProcessRecordLocked(aInfo.processName,
aInfo.applicationInfo.uid, true);
if (app == null || app.instrumentationClass == null) {
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
// 使用 mActivityStarter 啟動 app,這里不再詳細(xì)跟蹤
mActivityStarter.startHomeActivityLocked(intent, aInfo, reason);
}
} else {
Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());
}
return true;
}
getHomeIntent 方法:
Intent getHomeIntent() {
Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
intent.setComponent(mTopComponent);
intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
// 添加 android.intent.category.HOME
intent.addCategory(Intent.CATEGORY_HOME);
}
return intent;
}
可以看到,最后通過一個隱式 Intent 使用 Intent.FLAG_ACTIVITY_NEW_TASK 模式啟動了一個帶 Intent.CATEGORY_HOME 標(biāo)簽的 Activity,而帶有 Intent.CATEGORY_HOME 標(biāo)簽的 Activity 正是 Launcher App,它的 AndroidManifest 文件如下:
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.launcher3">
<uses-sdk android:targetSdkVersion="23" android:minSdkVersion="16"/>
...
<application
android:allowBackup="@bool/enable_backup"
android:backupAgent="com.android.launcher3.LauncherBackupAgentHelper"
android:hardwareAccelerated="true"
android:icon="@mipmap/ic_launcher_home"
android:label="@string/app_name"
android:largeHeap="@bool/config_largeHeap"
android:restoreAnyVersion="true"
android:supportsRtl="true" >
<activity
android:name="com.android.launcher3.Launcher"
android:launchMode="singleTask"
android:clearTaskOnLaunch="true"
android:stateNotNeeded="true"
android:theme="@style/Theme"
android:windowSoftInputMode="adjustPan"
android:screenOrientation="nosensor"
android:configChanges="keyboard|keyboardHidden|navigation"
android:resumeWhilePausing="true"
android:taskAffinity=""
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.MONKEY"/>
</intent-filter>
</activity>
...
</application>
</manifest>
Launcher 啟動后會將所有已安裝的應(yīng)用圖標(biāo)展示在一個網(wǎng)格布局的 RecyclerView 里面,這時候用戶就可以通過點擊這些圖標(biāo)來啟動相應(yīng)的 app 了。
整個過程的時序圖如下:
關(guān)于 Launcher 如何將 App 圖標(biāo)顯示出來等更多工作細(xì)節(jié),可以參考Android M Launcher3主流程源碼淺析 和 Android系統(tǒng)啟動流程(四)Launcher啟動過程與系統(tǒng)啟動流程這兩篇文章。
總結(jié)
最后,從整體上來看 Android 系統(tǒng)的啟動流程:
- 按下電源,固化在 ROM 中預(yù)定位置的 Bootloader 將會被加載到內(nèi)存中
- Bootloader 初始化完軟硬件環(huán)境后將 Linux 內(nèi)核啟動起來
- Linux 內(nèi)核啟動時會做設(shè)置緩存、被保護存儲器、計劃列表和加載驅(qū)動等一些列操作,內(nèi)核啟動完成后會啟動 init 進程
- init 進程會初始化并啟動屬性服務(wù),并且解析并執(zhí)行所有 init.rc 文件
- init 通過執(zhí)行特定的 init.rc 文件啟動 servermanager 進程,servermanager 被啟動后會向 Binder 驅(qū)動發(fā)送命令讓自己成為守護進程并管理所有上下文
- init 通過解析 init.rc 文件啟動 zygote 進程
- zygote 進程啟動的過程會創(chuàng)建 DVM 并為其注冊 JNI 函數(shù),然后創(chuàng)建服務(wù)端 Socket、啟動 system_server 進程
- 啟動 system_server 進程的過程會創(chuàng)建 Binder 線程池使其具有 IPC 能力,然后啟動 AMS 等各種系統(tǒng)服務(wù)
- AMS 啟動 Launcher,Launcher 被啟動后會將已安裝應(yīng)用的圖標(biāo)顯示在界面上
原來,一個復(fù)雜的 Android 系統(tǒng)就這么被運行起來了,礙于本人有限的水平,描述這個過程其實也還簡化了很多操作,下面這個圖比較全面地總結(jié)了這個流程:
系列文章
按下電源鍵后竟然發(fā)生了這一幕 —— Android 系統(tǒng)啟動流程分析(本文)
App 竟然是這樣跑起來的 —— Android App/Activity 啟動流程分析
屏幕上內(nèi)容究竟是怎樣畫出來的 —— Android View 工作原理詳解
參考文章
嵌入式系統(tǒng) Boot Loader 技術(shù)內(nèi)幕
如果你對文章內(nèi)容有疑問或者有不同的意見,歡迎留言,我們一同探討。