做爲一名 Android 程序員,你有沒有想過:那麼複雜的 Android 系統,它是怎樣運行起來的,咱們的 App 又是怎樣被 Android 系統加載後呈如今屏幕上的呢?Android 系統的啓動是一個比較複雜的過程,涉及到了一些咱們沒有接觸過的知識,本文將基於 Android Nougat 最新的代碼上講述 Android 系統的啓動流程。html
當按下電源鍵(加電)或者系統重啓(復位)的時候,引導芯片會從 ROM(這裏通常指 Flash ROM,即閃存)中預約義的位置將 Bootloader 載入到 RAM 中,接着,Bootloader 將會把 Linux 內核載入到 RAM 中並啓動。java
Bootloader 是在系統內核運行以前運行的一段小程序,也是系統運行的第一個程序,它的主要做用是:linux
Linux 內核啓動過程當中會建立 init 進程,init 進程是用戶空間的第一個進程(pid=1),對應的可執行程序的源文件文件爲 /system/core/init/Init.cpp,它的 main 方法以下:android
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);
// 建立文件並掛載
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));
// 初始化屬性相關資源
property_init();
process_kernel_dt();
process_kernel_cmdline();
export_kernel_boot_props();
}
...
// 啓動屬性服務
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 進程的職責主要有四個:ios
這裏重點看第一點,init.rc 是一個配置文件,它由 Android 初始化語言編寫,zygote 進程和 servicemanager 進程都是由 init 進程解析 init.rc 中特定的語句啓動的,好比,啓動 zygote 進程的代碼格式以下:c++
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
class main
priority -20
user root
group root readproc
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
onrestart restart wificond
writepid /dev/cpuset/foreground/tasks
複製代碼
事實上,在 system/core/rootdir 目錄下,有多個 init.rc 文件,在不一樣的硬件環境下,相應的 init.rc 文件會被導入,好比在 64 位操做系統中,上面啓動 zygote 進程的代碼是從 init.zygote64.rc 文件中導入的。git
我在文章藉助 AIDL 理解 Android Binder 機制——Binder 前因後果中講到「Binder 通訊模型和通訊過程」的時候提到過 ServerManager,它是 Binder IPC 的核心,是上下文的管理者,Binder 服務端必須先向 ServerManager 註冊纔可以爲客戶端提供服務,Binder 客戶端在與服務端通訊以前須要從 ServerManager 中查找並獲取 Binder 服務端的引用。然而 ServerManager 在向 Binder 驅動申請成爲上下文管理者的時候又涉及到了 Binder IPC 過程,這時候應該怎麼處理呢?程序員
servicemanager 進程是由 init 進程經過解析 init.rc 文件來啓動的,對應的代碼以下:小程序
service servicemanager /system/bin/servicemanager
class core
user system
group system
critical
onrestart restart healthd
onrestart restart zygote
onrestart restart media
onrestart restart surfaceflinger
onrestart restart drm
複製代碼
servicemanager 進程對應可執行程序的源文件爲 framework/native/cmds/servicemanager/service_manager.c,簡化後的代碼以下:數組
int main(int argc, char **argv) {
struct binder_state *bs;
// 打開binder驅動,申請 128k 字節大小的內存空間
bs = binder_open(128*1024);
...
// 成爲上下文管理者
if (binder_become_context_manager(bs)) {
return -1;
}
// 驗證 selinux 權限,判斷進程是否有權註冊或查看指定服務
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();
}
}
...
// 進入無限循環,處理 client 端發來的請求
binder_loop(bs, svcmgr_handler);
return 0;
}
複製代碼
這裏重點關注兩點,首先,在申請了一塊大小爲 128k 的內存空間並驗證 selinux 權限後,接着調用 framework/native/cmds/servicemanager/binder.c 中的 binder_become_context_manager 方法:
int binder_become_context_manager(struct binder_state *bs) {
// 經過ioctl,發送 BINDER_SET_CONTEXT_MGR 指令
return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}
複製代碼
而後,調用 binder_loop 方法進入循環來處理 client 發來的請求,注意第二個參數是一個方法體,用於處理各類狀態回調:
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:
// 獲取服務名
s = bio_get_string16(msg, &len);
// 根據名稱查找相應服務
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:
// 獲取服務名
s = bio_get_string16(msg, &len);
handle = bio_get_ref(msg);
allow_isolated = bio_get_uint32(msg) ? 1 : 0;
// 註冊指定服務
if (do_add_service(bs, s, len, handle, txn->sender_euid,
allow_isolated, txn->sender_pid))
return -1;
break;
}
}
複製代碼
servicemanager 進程在啓動過程的工做內容以下:
經過解析 init.rc 文件, zygote 進程對應的可執行程序的源文件爲 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) {
// 調用 AppRuntime 父類 AndroidRuntime 的 start 方法建立 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;
}
}
複製代碼
調用 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);
// 建立數組
strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
assert(strArray != NULL);
// 從 app_main 的 main 函數得知 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 函數
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 調用 ZygoteInit 的 main 函數
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);
...
// 預加載類和資源
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);
// 建立 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 啓動參數
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);
// 調用 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();
// 調用 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 出來的子線程中執行
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 方法中建立的服務端 Socket
fds.add(sServerSocket.getFileDescriptor());
peers.add(null);
// 循環讀取狀態
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) {
// 讀取的狀態不是客戶端鏈接或者數據請求時,進入下一次循環
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 發送過來的請求
// runOnce 方法建立一個新的應用程序進程
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 客戶端發送過來的參數列表
args = readArgumentList();
descriptors = mSocket.getAncillaryFileDescriptors();
} catch (IOException ex) {
// EOF reached.
closeSocket();
return true;
}
...
try {
// 將 socket 客戶端傳遞過來的參數,解析成 Arguments 對象格式
parsedArgs = new Arguments(args);
...
// 一樣調用 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) {
// 子進程執行
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
// 進入子進程流程
handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
return true;
} else {
// 父進程執行
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
}
} finally {
IoUtils.closeQuietly(childPipeFd);
IoUtils.closeQuietly(serverPipeFd);
}
}
複製代碼
從 App_main 開始,zygote 啓動過程的時序圖以下:
能夠看到,這個過程當中 zygote 首先啓動了 AndroidRuntime 並經過它反射調用了 ZygoteInit.main() 方法,由此進入了 Java 的世界,所以 zygote 是 Java 層的第一個進程,也是其餘 Java 進程的始祖,其餘 Java 進程的建立必須依賴 zygote。
zygote 進程的任務分別是:
接下來分別講解 system_server 進程的啓動過程和 system_server 進程的執行過程。
在上一小節中咱們已經知道,zygote 進程在啓動的過程當中會經過 startSystemServer 方法 fock 出了一個叫 system_server 的進程,而後再該方法內執行了 handleSystemServerProcess 方法:
private static void handleSystemServerProcess( ZygoteConnection.Arguments parsedArgs) throws ZygoteInit.MethodAndArgsCaller {
/** 因爲 fock 出來的 system_server 進程會複製 zygote 進程的地址空間,所以它也獲得了 zygote 進程中的 Socket,這個 Socket 對它來講並沒有用處,這裏將其關閉 **/
closeServerSocket();
...
if (parsedArgs.invokeWith != null) {
...
} else {
ClassLoader cl = null;
if (systemServerClasspath != null) {
cl = createSystemServerClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);
Thread.currentThread().setContextClassLoader(cl);
}
// 出現新的類 RuntimeInit,調用了它的 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 方法最終調用 app_main.cpp 的 onZygoteInit 方法 啓動 Binder 線程池, 使 system_server 進程可使用 Binder 與其餘進程通訊 **/
nativeZygoteInit();
// 繼續往下調用
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 類中並做爲異常拋出 捕獲異常的地方在上一小節中 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 對象後調用它的 run 方法
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
複製代碼
ZygoteInit 的 MethodAndArgsCaller 類是一個 Exception 類,同時也實現了 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 {
// 調用傳遞過來的 mMethod
mMethod.invoke(null, new Object[] { mArgs });
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InvocationTargetException ex) {
...
}
}
}
複製代碼
這樣,system_server 進程便啓動起來並進入了 SystemServer.java 的 main 方法。
這裏須要思考一下,爲何須要拋出異常到 ZygoteInit 中執行?官方解釋就是拋出異常的時候 Android 虛擬機會清空該進程堆內存中的棧幀,所以前面一系列啓動 system_server 進程的過程當中方法調用過程就被清除了,節省了堆棧的空間,使 ZygoteInit.java 的 main 方法處於全部 Java 進程的方法棧中的棧頂。另外,從最新 Android Pie 的代碼中看,這個過程已經變成在每一步中將包裝好的 MethodAndArgsCaller 對象做爲返回值返回,最後在 ZygoteInit 執行對象的 call 方法,這樣每一個方法都執行了返回過程,天然在堆棧中對應的棧幀也被彈出棧了。
查看 frameworks/base/services/java/com/android/server/SystemServer.java 的源碼:
/** * The main entry point from zygote. */
public static void main(String[] args) {
// 調用 run 方法
new SystemServer().run();
}
複製代碼
private void run() {
...
// 加載 libandroid_servers.so
System.loadLibrary("android_servers");
...
// 建立 SystemServiceManager
mSystemServiceManager = new SystemServiceManager(mSystemContext);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
...
try {
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices");
// 啓動引導服務
startBootstrapServices();
// 啓動核心服務
startCoreServices();
// 啓動其餘服務
startOtherServices();
} catch (Throwable ex) {
...
} finally {
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
...
}
複製代碼
能夠看到,在 run 方法中,主要執行了啓動引導服務、核心服務和其餘服務的任務,這些服務加起來一共有 80 多個,它們對應這個各類不一樣的功能,部分服務以下:
引導服務 | 做用 |
---|---|
Installer | 系統安裝apk時的一個服務類,啓動完成Installer服務以後才能啓動其餘的系統服務 |
ActivityManagerService | 負責四大組件的啓動、切換、調度。 |
PowerManagerService | 計算系統中和Power相關的計算,而後決策系統應該如何反應 |
LightsService | 管理和顯示背光LED |
DisplayManagerService | 用來管理全部顯示設備 |
UserManagerService | 多用戶模式管理 |
SensorService | 爲系統提供各類感應器服務 |
PackageManagerService | 用來對apk進行安裝、解析、刪除、卸載等等操做 |
核心服務 | 做用 |
---|---|
BatteryService | 管理電池相關的服務 |
UsageStatsService | 收集用戶使用每個APP的頻率、使用時常 |
WebViewUpdateService | WebView更新服務 |
其餘服務 | 做用 |
---|---|
CameraService | 攝像頭相關服務 |
AlarmManagerService | 全局定時器管理服務 |
InputManagerService | 管理輸入事件 |
WindowManagerService | 窗口管理服務 |
VrManagerService | VR模式管理服務 |
BluetoothService | 藍牙管理服務 |
NotificationManagerService | 通知管理服務 |
DeviceStorageMonitorService | 存儲相關管理服務 |
LocationManagerService | 定位管理服務 |
AudioService | 音頻相關管理服務 |
... | ... |
system_server 進程在啓動過程當中完成的工做分別是:
在上一節 frameworks/base/services/java/com/android/server/SystemServer.java 的 main 方法中,有一句:
private void startOtherServices() {
...
// 調用 AMS 的 systemReady 方法
mActivityManagerService.systemReady(new Runnable() {
@Override
public void run() {
...
}
}
...
}
複製代碼
繼續跟蹤: frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java:
public void systemReady(final Runnable goingCallback) {
...
synchronized (this) {
...
// 調用 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)) {
// 調用 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();
}
// 調用 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,這裏再也不詳細跟蹤
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 標籤的 Activity,而帶有 Intent.CATEGORY_HOME 標籤的 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 啓動後會將全部已安裝的應用圖標展現在一個網格佈局的 RecyclerView 裏面,這時候用戶就能夠經過點擊這些圖標來啓動相應的 app 了。
整個過程的時序圖以下:
關於 Launcher 如何將 App 圖標顯示出來等更多工做細節,能夠參考Android M Launcher3主流程源碼淺析 和 Android系統啓動流程(四)Launcher啓動過程與系統啓動流程這兩篇文章。
最後,從總體上來看 Android 系統的啓動流程:
原來,一個複雜的 Android 系統就這麼被運行起來了,礙於本人有限的水平,描述這個過程其實也還簡化了不少操做,下面這個圖比較全面地總結了這個流程:
系列文章
按下電源鍵後居然發生了這一幕 —— Android 系統啓動流程分析(本文)
App 居然是這樣跑起來的 —— Android App/Activity 啓動流程分析
屏幕上內容到底是怎樣畫出來的 —— Android View 工做原理詳解
參考文章
若是你對文章內容有疑問或者有不一樣的意見,歡迎留言,咱們一同探討。