std::vector<std::pair<std::string, int>> errors; #define CHECKCALL(x) \ if (x != 0) errors.emplace_back(#x " failed", errno); // Clear the umask. umask(0);
CHECKCALL(clearenv()); CHECKCALL(setenv("PATH", _PATH_DEFPATH, 1)); // Get the basic filesystem setup we need put together in the initramdisk // on / and then we'll let the rc file figure out the rest. CHECKCALL(mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755")); CHECKCALL(mkdir("/dev/pts", 0755)); CHECKCALL(mkdir("/dev/socket", 0755)); CHECKCALL(mount("devpts", "/dev/pts", "devpts", 0, NULL)); #define MAKE_STR(x) __STRING(x) CHECKCALL(mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC))); #undef MAKE_STR // Don't expose the raw commandline to unprivileged processes. CHECKCALL(chmod("/proc/cmdline", 0440)); gid_t groups[] = {AID_READPROC}; CHECKCALL(setgroups(arraysize(groups), groups)); CHECKCALL(mount("sysfs", "/sys", "sysfs", 0, NULL)); CHECKCALL(mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL));
// This is needed for log wrapper, which gets called before ueventd runs. CHECKCALL(mknod("/dev/ptmx", S_IFCHR | 0666, makedev(5, 2))); CHECKCALL(mknod("/dev/null", S_IFCHR | 0666, makedev(1, 3)));
CHECKCALL(mount("tmpfs", "/mnt", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV, "mode=0755,uid=0,gid=1000")); // /mnt/vendor is used to mount vendor-specific partitions that can not be // part of the vendor partition, e.g. because they are mounted read-write. CHECKCALL(mkdir("/mnt/vendor", 0755)); // /mnt/product is used to mount product-specific partitions that can not be // part of the product partition, e.g. because they are mounted read-write. CHECKCALL(mkdir("/mnt/product", 0755));
// /apex is used to mount APEXes CHECKCALL(mount("tmpfs", "/apex", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV, "mode=0755,uid=0,gid=0"));
// /debug_ramdisk is used to preserve additional files from the debug ramdisk CHECKCALL(mount("tmpfs", "/debug_ramdisk", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV, "mode=0755,uid=0,gid=0")); #undef CHECKCALL
SetStdioToDevNull(argv); // Now that tmpfs is mounted on /dev and we have /dev/kmsg, we can actually // talk to the outside world... InitKernelLogging(argv);
if (!errors.empty()) { for (constauto& [error_string, error_errno] : errors) { LOG(ERROR) << error_string << " " << strerror(error_errno); } LOG(FATAL) << "Init encountered errors starting first stage, aborting"; }
LOG(INFO) << "init first stage started!";
auto old_root_dir = std::unique_ptr<DIR, decltype(&closedir)>{opendir("/"), closedir}; if (!old_root_dir) { PLOG(ERROR) << "Could not opendir(\"/\"), not freeing ramdisk"; }
structstatold_root_info; if (stat("/", &old_root_info) != 0) { PLOG(ERROR) << "Could not stat(\"/\"), not freeing ramdisk"; old_root_dir.reset(); }
if (ForceNormalBoot()) { mkdir("/first_stage_ramdisk", 0755); // SwitchRoot() must be called with a mount point as the target, so we bind mount the // target directory to itself here. if (mount("/first_stage_ramdisk", "/first_stage_ramdisk", nullptr, MS_BIND, nullptr) != 0) { LOG(FATAL) << "Could not bind mount /first_stage_ramdisk to itself"; } SwitchRoot("/first_stage_ramdisk"); }
// If this file is present, the second-stage init will use a userdebug sepolicy // and load adb_debug.prop to allow adb root, if the device is unlocked. if (access("/force_debuggable", F_OK) == 0) { std::error_code ec; // to invoke the overloaded copy_file() that won't throw. if (!fs::copy_file("/adb_debug.prop", kDebugRamdiskProp, ec) || !fs::copy_file("/userdebug_plat_sepolicy.cil", kDebugRamdiskSEPolicy, ec)) { LOG(ERROR) << "Failed to setup debug ramdisk"; } else { // setenv for second-stage init to read above kDebugRamdisk* files. setenv("INIT_FORCE_DEBUGGABLE", "true", 1); } }
if (!DoFirstStageMount()) { LOG(FATAL) << "Failed to mount required partitions early ..."; }
structstatnew_root_info; if (stat("/", &new_root_info) != 0) { PLOG(ERROR) << "Could not stat(\"/\"), not freeing ramdisk"; old_root_dir.reset(); }
if (old_root_dir && old_root_info.st_dev != new_root_info.st_dev) { FreeRamdisk(old_root_dir.get(), old_root_info.st_dev); }
// execv() only returns if an error happened, in which case we // panic and never fall through this conditional. PLOG(FATAL) << "execv(\"" << path << "\") failed"; return1; }
// This function initializes SELinux then execs init to run in the init SELinux context. intSetupSelinux(char** argv){ InitKernelLogging(argv);
if (REBOOT_BOOTLOADER_ON_PANIC) { InstallRebootSignalHandlers(); }
// Set up SELinux, loading the SELinux policy. SelinuxSetupKernelLogging(); SelinuxInitialize();
// We're in the kernel domain and want to transition to the init domain. File systems that // store SELabels in their xattrs, such as ext4 do not need an explicit restorecon here, // but other file systems do. In particular, this is needed for ramdisks such as the // recovery image for A/B devices. if (selinux_android_restorecon("/system/bin/init", 0) == -1) { PLOG(FATAL) << "restorecon failed of /system/bin/init failed"; }
// execv() only returns if an error happened, in which case we // panic and never return from this function. PLOG(FATAL) << "execv(\"" << path << "\") failed"; return1; }
intSecondStageMain(int argc, char** argv){ if (REBOOT_BOOTLOADER_ON_PANIC) { InstallRebootSignalHandlers(); }
SetStdioToDevNull(argv); InitKernelLogging(argv); LOG(INFO) << "init second stage started!";
// Set init and its forked children's oom_adj. if (auto result = WriteFile("/proc/1/oom_score_adj", "-1000"); !result) { LOG(ERROR) << "Unable to write -1000 to /proc/1/oom_score_adj: " << result.error(); }
// Enable seccomp if global boot option was passed (otherwise it is enabled in zygote). GlobalSeccomp();
// Set up a session keyring that all processes will have access to. It // will hold things like FBE encryption keys. No process should override // its session keyring. keyctl_get_keyring_ID(KEY_SPEC_SESSION_KEYRING, 1);
// Indicate that booting is in progress to background fw loaders, etc. close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));
// 初始化属性相关资源 property_init();
// If arguments are passed both on the command line and in DT, // properties set in DT always have priority over the command-line ones. process_kernel_dt(); process_kernel_cmdline();
// Propagate the kernel variables to internal variables // used by init as well as the current required properties. export_kernel_boot_props();
// Make the time that init started available for bootstat to log. property_set("ro.boottime.init", getenv("INIT_STARTED_AT")); property_set("ro.boottime.init.selinux", getenv("INIT_SELINUX_TOOK"));
// Set libavb version for Framework-only OTA match in Treble build. constchar* avb_version = getenv("INIT_AVB_VERSION"); if (avb_version) property_set("ro.boot.avb_version", avb_version);
// See if need to load debug props to allow adb root, when the device is unlocked. constchar* force_debuggable_env = getenv("INIT_FORCE_DEBUGGABLE"); if (force_debuggable_env && AvbHandle::IsDeviceUnlocked()) { load_debug_prop = "true"s == force_debuggable_env; }
// Clean up our environment. unsetenv("INIT_STARTED_AT"); unsetenv("INIT_SELINUX_TOOK"); unsetenv("INIT_AVB_VERSION"); unsetenv("INIT_FORCE_DEBUGGABLE");
// Now set up SELinux for second stage. SelinuxSetupKernelLogging(); SelabelInitialize(); SelinuxRestoreContext();
Epoll epoll; if (auto result = epoll.Open(); !result) { PLOG(FATAL) << result.error(); }
if (!SetupMountNamespaces()) { PLOG(FATAL) << "SetupMountNamespaces failed"; }
subcontexts = InitializeSubcontexts();
ActionManager& am = ActionManager::GetInstance(); ServiceList& sm = ServiceList::GetInstance(); //加载引导脚本 LoadBootScripts(am, sm);
// Turning this on and letting the INFO logging be discarded adds 0.2s to // Nexus 9 boot time, so it's disabled by default. if (false) DumpState();
// Make the GSI status available before scripts start running. if (android::gsi::IsGsiRunning()) { property_set("ro.gsid.image_running", "1"); } else { property_set("ro.gsid.image_running", "0"); }
// Queue an action that waits for coldboot done so we know ueventd has set up all of /dev... am.QueueBuiltinAction(wait_for_coldboot_done_action, "wait_for_coldboot_done"); // ... so that we can start queuing up actions that require stuff from /dev. am.QueueBuiltinAction(MixHwrngIntoLinuxRngAction, "MixHwrngIntoLinuxRng"); am.QueueBuiltinAction(SetMmapRndBitsAction, "SetMmapRndBits"); am.QueueBuiltinAction(SetKptrRestrictAction, "SetKptrRestrict"); Keychords keychords; am.QueueBuiltinAction( [&epoll, &keychords](const BuiltinArguments& args) -> Result<Success> { for (constauto& svc : ServiceList::GetInstance()) { keychords.Register(svc->keycodes()); } keychords.Start(&epoll, HandleKeychord); return Success(); }, "KeychordInit"); am.QueueBuiltinAction(console_init_action, "console_init");
// Trigger all the boot actions to get us started. am.QueueEventTrigger("init");
// Starting the BoringSSL self test, for NIAP certification compliance. am.QueueBuiltinAction(StartBoringSslSelfTest, "StartBoringSslSelfTest");
// Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random // wasn't ready immediately after wait_for_coldboot_done am.QueueBuiltinAction(MixHwrngIntoLinuxRngAction, "MixHwrngIntoLinuxRng");
// Initialize binder before bringing up other system services am.QueueBuiltinAction(InitBinder, "InitBinder");
// Don't mount filesystems or start core system services in charger mode. std::string bootmode = GetProperty("ro.bootmode", ""); if (bootmode == "charger") { am.QueueEventTrigger("charger"); } else { am.QueueEventTrigger("late-init"); }
// Run all property triggers based on current state of the properties. am.QueueBuiltinAction(queue_property_triggers_action, "queue_property_triggers");
while (true) { // By default, sleep until something happens. auto epoll_timeout = std::optional<std::chrono::milliseconds>{};
if (do_shutdown && !shutting_down) { do_shutdown = false; if (HandlePowerctlMessage(shutdown_command)) { shutting_down = true; } }
if (!(waiting_for_prop || Service::is_exec_service_running())) { //内部会执行每个action中携带的command对应的执行函数 am.ExecuteOneCommand(); } if (!(waiting_for_prop || Service::is_exec_service_running())) { if (!shutting_down) { auto next_process_action_time = HandleProcessActions();
// If there's a process that needs restarting, wake up in time for that. if (next_process_action_time) { epoll_timeout = std::chrono::ceil<std::chrono::milliseconds>( *next_process_action_time - boot_clock::now()); if (*epoll_timeout < 0ms) epoll_timeout = 0ms; } }
// If there's more work to do, wake up again immediately. if (am.HasMoreCommands()) epoll_timeout = 0ms; }
if (auto result = epoll.Wait(epoll_timeout); !result) { LOG(ERROR) << result.error(); } }
service zygote /system/bin/app_process32 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote class main priority -20 user root group root readproc reserved_disk socket zygote stream 660 root system socket usap_pool_primary 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
service zygote_secondary /system/bin/app_process64 -Xzygote /system/bin --zygote --socket-name=zygote_secondary class main priority -20 user root group root readproc reserved_disk socket zygote_secondary stream 660 root system socket usap_pool_secondary stream 660 root system onrestart restart zygote writepid /dev/cpuset/foreground/tasks
static Result<Success> do_class_start(const BuiltinArguments& args) { // Starting a class does not start services which are explicitly disabled. // They must be started individually. for (const auto& service : ServiceList::GetInstance()) { if (service->classnames().count(args[1])) { // 2 if (auto result = service->StartIfNotDisabled(); !result) { LOG(ERROR) << "Could not start service'" << service->name() << "' as part of class '" << args[1] << "': " << result.error(); } } } return Success(); }
intmain(int argc, char* const argv[]) { ... //创建了AppRuntime对象,AppRuntime类继承自AndroidRuntime AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv)); // Process command line arguments // ignore argv[0] argc--; argv++; //从命令行参数中找到虚拟机相关的参数,添加到runtime对象 constchar* spaced_commands[] = { "-cp", "-classpath" }; // Allow "spaced commands" to be succeeded by exactly 1 argument (regardless of -s). bool known_command = false;
int i; for (i = 0; i < argc; i++) { if (known_command == true) { runtime.addOption(strdup(argv[i])); // The static analyzer gets upset that we don't ever free the above // string. Since the allocation is from main, leaking it doesn't seem // problematic. NOLINTNEXTLINE ALOGV("app_process main add known option '%s'", argv[i]); known_command = false; continue; }
for (int j = 0; j < static_cast<int>(sizeof(spaced_commands) / sizeof(spaced_commands[0])); ++j) { if (strcmp(argv[i], spaced_commands[j]) == 0) { known_command = true; ALOGV("app_process main found known command '%s'", argv[i]); } }
runtime.addOption(strdup(argv[i])); // The static analyzer gets upset that we don't ever free the above // string. Since the allocation is from main, leaking it doesn't seem // problematic. NOLINTNEXTLINE ALOGV("app_process main add option '%s'", argv[i]); } // Parse runtime arguments. Stop at first unrecognized option. // 解析runtime参数 bool zygote = false; bool startSystemServer = false; bool application = false; String8 niceName; String8 className;
++i; // Skip unused "parent dir" argument. while (i < argc) { constchar* arg = argv[i++]; if (strcmp(arg, "--zygote") == 0) { zygote = true; niceName = ZYGOTE_NICE_NAME; } elseif (strcmp(arg, "--start-system-server") == 0) { startSystemServer = true; } elseif (strcmp(arg, "--application") == 0) { application = true; } elseif (strncmp(arg, "--nice-name=", 12) == 0) { niceName.setTo(arg + 12); } elseif (strncmp(arg, "--", 2) != 0) { className.setTo(arg); break; } else { --i; break; } } //准备启动ZygoteInit类或者RuntimeInit类,根据类名是否存在为空,来区别是非zyoget模式和zyoget模式. Vector<String8> args; if (!className.isEmpty()) { // We're not in zygote mode, the only argument we need to pass // to RuntimeInit is the application argument. // The Remainder of args get passed to startup class main(). Make // copies of them before we overwrite them with the process name. args.add(application ? String8("application") : String8("tool")); runtime.setClassNameAndArgs(className, argc - i, argv + i);
if (!LOG_NDEBUG) { String8 restOfArgs; char* const* argv_new = argv + i; int argc_new = argc - i; for (int k = 0; k < argc_new; ++k) { restOfArgs.append("\""); restOfArgs.append(argv_new[k]); restOfArgs.append("\" "); } ALOGV("Class name = %s, args = %s", className.string(), restOfArgs.string()); } } else { // We're in zygote mode. 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); return11; }
/* * Start the Android runtime. This involves starting the virtual machine * and calling the "static void main(String[] args)" method in the class * named by "className". */ voidAndroidRuntime::start(constchar* className, const Vector<String8>& options, bool zygote) { ... //获取系统目录 constchar* rootDir = getenv("ANDROID_ROOT"); if (rootDir == NULL) { rootDir = "/system"; if (!hasDir("/system")) { LOG_FATAL("No root directory specified, and /system does not exist."); return; } setenv("ANDROID_ROOT", rootDir, 1); }
constchar* runtimeRootDir = getenv("ANDROID_RUNTIME_ROOT"); if (runtimeRootDir == NULL) { LOG_FATAL("No runtime directory specified with ANDROID_RUNTIME_ROOT environment variable."); return; }
constchar* tzdataRootDir = getenv("ANDROID_TZDATA_ROOT"); if (tzdataRootDir == NULL) { LOG_FATAL("No tz data directory specified with ANDROID_TZDATA_ROOT environment variable."); return; }
/* * Register android functions. */ //注册系统的JNI函数 if (startReg(env) < 0) { ALOGE("Unable to register all android natives\n"); return; }
/* * We want to call main() with a String array with arguments in it. * At present we have two arguments, the class name and an option string. * Create an array to hold them. */ //为启动Java类的main函数做准备 jclass stringClass; jobjectArray strArray; jstring 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); }
/* * Start VM. This thread becomes the main thread of the VM, and will * not return until the VM exits. */ //调用Zygoteinit类或RuntimeInit类的main()函数 char* slashClassName = toSlashClassName(className != NULL ? className : ""); jclass startClass = env->FindClass(slashClassName); if (startClass == NULL) { ALOGE("JavaVM unable to locate class '%s'\n", slashClassName); /* keep going */ } else { // 找到 ZygoteInit/RuntimeInit 的 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/RuntimeInit 的 main 函数 env->CallStaticVoidMethod(startClass, startMeth, strArray);
#if 0 if (env->ExceptionCheck()) threadExitUncaughtException(env); #endif } } free(slashClassName);
ALOGD("Shutting down VM\n"); if (mJavaVM->DetachCurrentThread() != JNI_OK) ALOGW("Warning: unable to detach main thread\n"); if (mJavaVM->DestroyJavaVM() != 0) ALOGW("Warning: VM did not shut down cleanly\n"); }
// Mark zygote start. This ensures that thread creation will throw // an error. //这里其实只是设置一个标志位,为创建Java线程时做判断处理,如果是zygote进程,则不需要开启线程 ZygoteHooks.startZygoteNoThreadCreation();
// Zygote goes into its own process group. try { //设置进程组ID Os.setpgid(0, 0); } catch (ErrnoException ex) { thrownew RuntimeException("Failed to setpgid(0,0)", ex); }
Runnable caller; 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()); } //判断当前进程是64位程序还是32位程序,并设置标记 String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing"; TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag, Trace.TRACE_TAG_DALVIK); bootTimingsTraceLog.traceBegin("ZygoteInit"); RuntimeInit.enableDdms();// 启用 DDMS
if (abiList == null) { thrownew RuntimeException("No ABI list supplied."); }
// In some configurations, we avoid preloading resources and classes eagerly. // In such cases, we will preload things prior to our first fork. if (!enableLazyPreload) { bootTimingsTraceLog.traceBegin("ZygotePreload"); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, SystemClock.uptimeMillis()); preload(bootTimingsTraceLog); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, SystemClock.uptimeMillis()); bootTimingsTraceLog.traceEnd(); // ZygotePreload } else { Zygote.resetNicePriority(); }
// Do an initial gc to clean up after startup bootTimingsTraceLog.traceBegin("PostZygoteInitGC"); gcAndFinalize();//调用ZygoteHooks.gcAndFinalize()进行垃圾回收 bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC
bootTimingsTraceLog.traceEnd(); // ZygoteInit // Disable tracing so that forked processes do not inherit stale tracing tags from // Zygote. Trace.setTracingEnabled(false, 0);
Zygote.initNativeState(isPrimaryZygote);
ZygoteHooks.stopZygoteNoThreadCreation(); //创建zygoteServer,为其他进程初始化创建时与mZygoteSocket通信做准备 zygoteServer = new ZygoteServer(isPrimaryZygote);
if (startSystemServer) { //启动SystemServer进程,通过fork的方式开启zygote的子进程systemServer,并返回一个Runnale对象 Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the child (system_server) process. if (r != null) { r.run(); return; } }
// The select loop returns early in the child process after a fork and // loops forever in the zygote. //循环等待处理客户端请求,来获取子进程发送的消息 caller = zygoteServer.runSelectLoop(abiList); } catch (Throwable ex) { Log.e(TAG, "System zygote died with exception", ex); throw ex; } finally { if (zygoteServer != null) { zygoteServer.closeServerSocket();// 关闭并释放 socket 连接 } }
// We're in the child process and have exited the select loop. Proceed to execute the // command. if (caller != null) { caller.run(); } }
> ZygoteHooks.java publicstaticvoidgcAndFinalize(){ final VMRuntime runtime = VMRuntime.getRuntime();
/* runFinalizationSync() lets finalizers be called in Zygote, * which doesn't have a HeapWorker thread. */ System.gc(); runtime.runFinalizationSync(); System.gc(); }
ZygoteInit.zygoteServer
1 2 3
... zygoteServer = new ZygoteServer(isPrimaryZygote); ...
publicstaticintforkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir, int targetSdkVersion){ //在fork新进程之前,停止Zygote的4个Daemon子线程的运行 ZygoteHooks.preFork(); // Resets nice priority for zygote process. resetNicePriority(); //调用native方法fork子进程 int pid = nativeForkAndSpecialize( uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose, fdsToIgnore, startChildZygote, instructionSet, appDataDir); // Enable tracing as soon as possible for the child process. if (pid == 0) { Zygote.disableExecuteOnly(targetSdkVersion); Trace.setTracingEnabled(true, runtimeFlags);
// Note that this event ends at the end of handleChildProc, Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork"); } //fork之后启动4个Deamon子线程 ZygoteHooks.postForkCommon(); return pid; }
privatestaticnativeintnativeForkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir);
int res = android.system.Os.poll(fds, remainingSleepTime); long endTime = System.nanoTime(); int elapsedTimeMs = (int)((endTime - startTime) / 1000000l); remainingSleepTime = WRAPPED_PID_TIMEOUT_MILLIS - elapsedTimeMs; ... if (dataIndex == data.length) { DataInputStream is = new DataInputStream(new ByteArrayInputStream(data)); innerPid = is.readInt(); } } catch (Exception ex) { Log.w(TAG, "Error reading pid from wrapped process, child may have died", ex); }
// Ensure that the pid reported by the wrapped process is either the // child process that we forked, or a descendant of it. if (innerPid > 0) { int parentPid = innerPid; while (parentPid > 0 && parentPid != pid) { parentPid = Process.getParentPid(parentPid); } if (parentPid > 0) { Log.i(TAG, "Wrapped process has pid " + innerPid); pid = innerPid; usingWrapper = true; } else { Log.w(TAG, "Wrapped process reported a pid that is not a child of " + "the process that we forked: childPid=" + pid + " innerPid=" + innerPid); } } } // 将创建的应用进程id返回给system_server进程 try { mSocketOutStream.writeInt(pid); mSocketOutStream.writeBoolean(usingWrapper); } catch (IOException ex) { thrownew IllegalStateException("Error writing to command socket", ex); } }
publicstaticintforkSystemServer(int uid, int gid, int[] gids, int runtimeFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities){ //在fork新进程之前,停止Zygote的4个Daemon子线程的运行,等待并确保Zygote的单线程(用于fork效率) //并等待这些线程的停止,初始化gc堆的工作 ZygoteHooks.preFork(); // Resets nice priority for zygote process. resetNicePriority(); int pid = nativeForkSystemServer( uid, gid, gids, runtimeFlags, rlimits, permittedCapabilities, effectiveCapabilities); // Enable tracing as soon as we enter the system_server. if (pid == 0) { Trace.setTracingEnabled(true, runtimeFlags); } //在fork新进程之后,启动Zygote的4个Deamon线程,Java堆整理,引用队列,以及析构线程。 ZygoteHooks.postForkCommon(); return pid; }
privatestaticnativeintnativeForkSystemServer(int uid, int gid, int[] gids, int runtimeFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);
if (gUsapPoolEventFD != -1) { fds_to_close.push_back(gUsapPoolEventFD); fds_to_ignore.push_back(gUsapPoolEventFD); } //fork 子进程 pid_t pid = ForkCommon(env, true, fds_to_close, fds_to_ignore); if (pid == 0) { SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, permitted_capabilities, effective_capabilities, MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true, false, nullptr, nullptr); } elseif (pid > 0) { // The zygote process checks whether the child process has died or not. ALOGI("System server process %d has been created", pid); gSystemServerPid = pid; // There is a slight window that the system server process has crashed // but it went unnoticed because we haven't published its pid yet. So // we recheck here just to make sure that all is well. int status; if (waitpid(pid, &status, WNOHANG) == pid) { ALOGE("System server process %d has died. Restarting Zygote!", pid); RuntimeAbort(env, __LINE__, "System server process has died. Restarting Zygote!"); }
if (UsePerAppMemcg()) { // Assign system_server to the correct memory cgroup. // Not all devices mount memcg so check if it is mounted first // to avoid unnecessarily printing errors and denials in the logs. if (!SetTaskProfiles(pid, std::vector<std::string>{"SystemMemoryProcess"})) { ALOGE("couldn't add process %d into system memcg group", pid); } } } return pid; }
/* For child process */ //pid == 0 表示子进程即system_server进程,继续剩余工作 if(pid == 0){ if (hasSecondZygote(abiList)) { waitForSecondaryZygote(socketName); } zygoteServer.closeServerSocket(); return handleSystemServerProcess(parsedArgs); } //父进程 (zygote) 会返回 null returnnull;
回到 ZygoteInit.main() 中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
if (startSystemServer) { Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the // child (system_server) process. // r == null 说明是在 zygote 进程 // r != null 说明是在 system_server 进程 if (r != null) { r.run(); return; } } // 循环等待处理客户端请求 caller = zygoteServer.runSelectLoop(abiList);
privatestatic Runnable handleSystemServerProcess(ZygoteArguments parsedArgs){ // set umask to 0077 so new files and directories will default to owner-only permissions. // 通过umask设置创建文件的默认权限 Os.umask(S_IRWXG | S_IRWXO); // 设置当前进程名为 "system_server" if (parsedArgs.mNiceName != null) { Process.setArgV0(parsedArgs.mNiceName); } // 获取环境变量SYSTEMSERVERCLASSPATH,环境变量位于init.environ.rc中 final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH"); if (systemServerClasspath != null) { // 对环境变量SYSTEMSERVERCLASSPATH中的jar包进行dex优化 if (performSystemServerDexOpt(systemServerClasspath)) { sCachedSystemServerClassLoader = null; } // prevents it. boolean profileSystemServer = SystemProperties.getBoolean( "dalvik.vm.profilesystemserver", false); if (profileSystemServer && (Build.IS_USERDEBUG || Build.IS_ENG)) { try { prepareSystemServerProfile(systemServerClasspath); } catch (Exception e) { Log.wtf(TAG, "Failed to set up system server profile", e); } } } //启动参数未包含"--invoke-with",invokeWith 一般为空,直接走else if (parsedArgs.mInvokeWith != null) { String[] args = parsedArgs.mRemainingArgs; // If we have a non-null system server class path, we'll have to duplicate the // existing arguments and append the classpath to it. ART will handle the classpath // correctly when we exec a new process. if (systemServerClasspath != null) { String[] amendedArgs = new String[args.length + 2]; amendedArgs[0] = "-cp"; amendedArgs[1] = systemServerClasspath; System.arraycopy(args, 0, amendedArgs, 2, args.length); args = amendedArgs; }
protectedstatic Runnable applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader){ // 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. //true 代表应用程序退出时,不调用AppRuntime.onExit(),否则会在退出前调用 nativeSetExitWithoutCleanup(true);
// We want to be fairly aggressive about heap utilization, to avoid // holding on to a lot of memory that isn't needed. // 设置虚拟机的内存利用率数值为0.75 VMRuntime.getRuntime().setTargetHeapUtilization(0.75f); VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion); // 解析参数 final Arguments args = new Arguments(argv);
// 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 //寻找 startClass 的静态main() 方法。这里的 startClass 是 com.android.server.SystemServer return findStaticMain(args.startClass, args.startArgs, classLoader); }
try { //找到指定的className类 cl = Class.forName(className, true, classLoader); } catch (ClassNotFoundException ex) { thrownew RuntimeException( "Missing class when invoking static main " + className, ex); }
Method m; try { //找到className类的main()方法 m = cl.getMethod("main", new Class[] { String[].class }); } catch (NoSuchMethodException ex) { thrownew RuntimeException( "Missing static main on " + className, ex); } catch (SecurityException ex) { thrownew RuntimeException( "Problem getting static main on " + className, ex); }
int modifiers = m.getModifiers(); if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) { thrownew 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. */ //返回一个 Runnable,在 Zygote 的 main() 方法中执行 run() 方法 //之前的版本是抛出一个异常,在 main() 方法中捕获,这样做的好处是清空栈帧,提高栈帧利用率 returnnew MethodAndArgsCaller(m, argv); }
publicstaticvoidmain(String[] args){ new SystemServer().run(); //调用 run 方法 }
publicSystemServer(){ // Check for factory test mode. mFactoryTestMode = FactoryTest.getMode(); //记录进程开始信息 // one for the password screen, second for the actual boot. mStartCount = SystemProperties.getInt(SYSPROP_START_COUNT, 0) + 1; mRuntimeStartElapsedTime = SystemClock.elapsedRealtime(); mRuntimeStartUptime = SystemClock.uptimeMillis(); mRuntimeRestart = "1".equals(SystemProperties.get("sys.boot_completed")); }
// Record the process start information in sys props. //在sys props中记录进程启动信息。 SystemProperties.set(SYSPROP_START_COUNT, String.valueOf(mStartCount)); SystemProperties.set(SYSPROP_START_ELAPSED, String.valueOf(mRuntimeStartElapsedTime)); SystemProperties.set(SYSPROP_START_UPTIME, String.valueOf(mRuntimeStartUptime));
// 计算时间 如果当前系统时间比1970年更早,就设置当前系统时间为1970年 if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) { Slog.w(TAG, "System clock is before 1970; setting to 1970."); SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME); } // Default the timezone property to GMT if not set. //如果未设置时区属性,则将其默认为GMT。 String timezoneProperty = SystemProperties.get("persist.sys.timezone"); if (timezoneProperty == null || timezoneProperty.isEmpty()) { Slog.w(TAG, "Timezone not set; setting to GMT."); SystemProperties.set("persist.sys.timezone", "GMT"); } // NOTE: Most changes made here will need an equivalent change to // core/jni/AndroidRuntime.cpp // 如果没有设置 语言,则设置当地的语言 if (!SystemProperties.get("persist.sys.language").isEmpty()) { final String languageTag = Locale.getDefault().toLanguageTag();
// The system server should never make non-oneway calls //设置系统服务器不应进行非单向调用 Binder.setWarnOnBlocking(true); // The system server should always load safe labels //系统服务器应始终加载安全标签 PackageItemInfo.forceSafeLabels();
// Default to FULL within the system server. SQLiteGlobal.sDefaultSyncMode = SQLiteGlobal.SYNC_MODE_FULL;
// Deactivate SQLiteCompatibilityWalFlags until settings provider is initialized //在初始化设置provider之前,停用SQLiteCompatibilityWalFlags SQLiteCompatibilityWalFlags.init(null);
// Here we go! Slog.i(TAG, "Entered the Android system server!"); int uptimeMillis = (int) SystemClock.elapsedRealtime(); EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, uptimeMillis); if (!mRuntimeRestart) { MetricsLogger.histogram(null, "boot_system_server_init", uptimeMillis); }
// Mmmmmm... more memory! // 清除VM内存增长上限,由于启动过程需要较多的虚拟机内存空间 VMRuntime.getRuntime().clearGrowthLimit();
// The system server has to run all of the time, so it needs to be // as efficient as possible with its memory usage. // 设置内存可能有效使用率为0.8 VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
// Some devices rely on runtime fingerprint generation, so make sure // we've defined it before booting further. // 针对部分设备依赖运行时就产生指纹信息,因此需要在开机完成前已经定义 Build.ensureFingerprintProperty();
// Within the system server, it is an error to access Environment paths without // explicitly specifying a user. // 设置访问环境变量的条件,即需要明确指定用户 Environment.setUserRequired(true);
// Within the system server, any incoming Bundles should be defused // to avoid throwing BadParcelableException. BaseBundle.setShouldDefuse(true);
// Within the system server, when parceling exceptions, include the stack trace Parcel.setStackTraceParceling(true);
// Ensure binder calls into the system always run at foreground priority. //确保当前系统进程的binder调用,总是运行在前台优先级(foreground) BinderInternal.disableBackgroundScheduling(true);
// Increase the number of binder threads in system_server BinderInternal.setMaxThreads(sMaxBinderThreads);
// Prepare the main looper thread (this thread). android.os.Process.setThreadPriority( android.os.Process.THREAD_PRIORITY_FOREGROUND); android.os.Process.setCanSelfBackground(false); //创建主线程Looper,就在当前线程运行 Looper.prepareMainLooper(); Looper.getMainLooper().setSlowLogThresholdMs( SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);
// Check whether we failed to shut down last time we tried. // This call may not return. //检查上次关键是否失败了,可能没有返回值 performPendingShutdown();
// Initialize the system context. // 初始化系统上下文 createSystemContext();
// Create the system service manager. // 创建SystemServiceManager 用于后面的binder机制 mSystemServiceManager = new SystemServiceManager(mSystemContext); mSystemServiceManager.setStartInfo(mRuntimeRestart, mRuntimeStartElapsedTime, mRuntimeStartUptime); //添加注册到LocalServices LocalServices.addService(SystemServiceManager.class, mSystemServiceManager); // Prepare the thread pool for init tasks that can be parallelized //为初始化任务准备线程池 SystemServerInitThreadPool.get(); } finally { traceEnd(); // InitBeforeStartServices }
privatevoidstartBootstrapServices(){ ... // Wait for installd to finish starting up so that it has a chance to // create critical directories such as /data/user with the appropriate // permissions. We need this to complete before we initialize other services. Installer installer = mSystemServiceManager.startService(Installer.class); // In some cases after launching an app we need to access device identifiers, // therefore register the device identifier policy before the activity manager. mSystemServiceManager.startService(DeviceIdentifiersPolicyService.class); // Uri Grants Manager. mSystemServiceManager.startService(UriGrantsManagerService.Lifecycle.class); // Activity manager runs the show. // 创建启动ATMS(ActivityTaskManagerService) //是通过"ssm"反射创建"atm"的静态内部类Lifecycle对象,并通过该对象的getService()获取到"atm"实例对象 ActivityTaskManagerService atm = mSystemServiceManager.startService( ActivityTaskManagerService.Lifecycle.class).getService(); // 创建启动AMS(ActivityManagerService) //调用"ams"的静态内部类Lifecycle的静态方法"startService"函数,把"ssm"和"atm"传递过去 mActivityManagerService = ActivityManagerService.Lifecycle.startService( mSystemServiceManager, atm);//内部还是使用"ssm"来创建的"ams" mActivityManagerService.setSystemServiceManager(mSystemServiceManager); mActivityManagerService.setInstaller(installer); mWindowManagerGlobalLock = atm.getGlobalLock(); // Power manager needs to be started early because other services need it. mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class); ... }
privatevoidstartCoreServices(){ // Tracks the battery level. Requires LightService. mSystemServiceManager.startService(BatteryService.class);
// Tracks application usage stats. mSystemServiceManager.startService(UsageStatsService.class); mActivityManagerService.setUsageStatsManager( LocalServices.getService(UsageStatsManagerInternal.class)); // Tracks whether the updatable WebView is in a ready state and watches for update installs. if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_WEBVIEW)) { traceBeginAndSlog("StartWebViewUpdateService"); mWebViewUpdateService = mSystemServiceManager.startService(WebViewUpdateService.class); traceEnd(); } ... }
ServiceManager.addService("sec_key_att_app_id_provider", new KeyAttestationApplicationIdProviderService(context)); mSystemServiceManager.startService(KeyChainSystemService.class); ServiceManager.addService("scheduling_policy", new SchedulingPolicyService()); ... }
//启动HomeActivity booleanstartHomeOnDisplay(int userId, String reason, int displayId, boolean allowInstrumenting, boolean fromHomeKey){ // Fallback to top focused display if the displayId is invalid. if (displayId == INVALID_DISPLAY) { displayId = getTopDisplayFocusedStack().mDisplayId; }
if (!canStartHomeOnDisplay(aInfo, displayId, allowInstrumenting)) { returnfalse; }
// Updates the home component of the intent. homeIntent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name)); homeIntent.setFlags(homeIntent.getFlags() | FLAG_ACTIVITY_NEW_TASK); // Updates the extra information of the intent. if (fromHomeKey) { homeIntent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, true); } // Update the reason for ANR debugging to verify if the user activity is the one that // actually launched. final String myReason = reason + ":" + userId + ":" + UserHandle.getUserId( aInfo.applicationInfo.uid) + ":" + displayId; // 启动桌面 Activity mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason, displayId); returntrue; }
voidstartHomeActivity(Intent intent, ActivityInfo aInfo, String reason, int displayId){ final ActivityOptions options = ActivityOptions.makeBasic(); options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN); if (!ActivityRecord.isResolverActivity(aInfo.name)) { // The resolver activity shouldn't be put in home stack because when the foreground is // standard type activity, the resolver activity should be put on the top of current // foreground instead of bring home stack to front. options.setLaunchActivityType(ACTIVITY_TYPE_HOME); } options.setLaunchDisplayId(displayId); mLastHomeActivityStartResult = obtainStarter(intent, "startHomeActivity: " + reason) .setOutActivity(tmpOutRecord) .setCallingUid(0) .setActivityInfo(aInfo) .setActivityOptions(options.toBundle()) .execute(); mLastHomeActivityStartRecord = tmpOutRecord[0]; final ActivityDisplay display = mService.mRootActivityContainer.getActivityDisplay(displayId); final ActivityStack homeStack = display != null ? display.getHomeStack() : null; if (homeStack != null && homeStack.mInResumeTopActivity) { // If we are in resume section already, home activity will be initialized, but not // resumed (to avoid recursive resume) and will stay that way until something pokes it // again. We need to schedule another resume. mSupervisor.scheduleResumeTopActivities(); } }