动态

详情 返回 返回

Android系統Launcher啓動流程 - 动态 详情

本文基於android13-release源碼閲讀整理

系統源碼地址:init.h - Android Code Search

前言

以往我們開發Android應用都在系統桌面點擊打開,但桌面Launcher進程是如何加載並展示應用窗口未能深入瞭解,由此去窺探Android系統整體啓動流程以加深對Android開發體系的理解

1.Android系統啓動核心流程

  • 當開機鍵按下時Boot Rom激活並加載引導程序BootLoader到RAM
  • 啓動kernal swapper進程(idle)pid=0
  • 初始化進程管理,內存管理
  • 加載Binder\Display\Camera Driver
  • 創建kthreadd進程(pid=2),初始化內核工作線程kworkder,中斷線程ksoftirad,內核守護進程thermal
  • 創建init進程

2.init進程源碼解析

2.1 init進程

功能如下:

  • 解析init.rc配置文件,首先開啓ServiceManager和MediaServer等關鍵進程
  • init進程fork啓動Zygote服務進程
  • 處理子進程的終止(signal方式)
  • 提供屬性服務的功能

源碼文件路徑 : system/core/init/main.cpp)

int main(int argc, char** argv) {
    ...
    //設置進程和用户的進程執行優先級
    setpriority(PRIO_PROCESS, 0, -20);
    //init進程創建ueventd子進程處理設備節點文件,通過ColdBoot.Run()方法冷啓動
    //具體細節位置:/system/core/init/ueventd.cpp
    if (!strcmp(basename(argv[0]), "ueventd")) {
        return ueventd_main(argc, argv);
    }
    if (argc > 1) {
        if (!strcmp(argv[1], "subcontext")) {
        //內核日誌初始化,文件位置:/system/libbase/logging.cpp
        //[logging.cpp - Android Code Search](https://cs.android.com/android/platform/superproject/+/android13-release:system/libbase/logging.cpp;drc=715a186b5d8903d30c25299ed0ecff0e2e9fbb9c;bpv=1;bpt=1;l=337?hl=zh-cn)
            android::base::InitLogging(argv, &android::base::KernelLogger);
            //文件位置:/system/core/init/builtins.cpp,獲取內核函數傳遞給“subcontext”
            const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();
            //subcontext進程
            return SubcontextMain(argc, argv, &function_map);
        }
        if (!strcmp(argv[1], "selinux_setup")) {
            return SetupSelinux(argv);
        }
        if (!strcmp(argv[1], "second_stage")) {
            return SecondStageMain(argc, argv);
        }
    }
    return FirstStageMain(argc, argv);
}

2.2 進程優先級

setpriority(PRIO_PROCESS, 0, -20);

設置進程和用户的進程執行優先級,源碼位置 : bionic/libc/include/sys/resource.h

int getpriority(int __which, id_t __who);
int setpriority(int __which, id_t __who, int __priority);
  • int __which : 三個類別可選,PRIO_PROCESS(標記具體進程)、PRIO_PGRP(標記進程組)、PRIO_USER(標記用户進程,通過user id區分)
  • id_t __who : 與which類別一一對應,分別標記上述類別id
  • int __priority : 優先級範圍 -20~19,值越小優先級越高

運行adb shell 查看進程nice值

adb shell top

image.png

2.3 FirstStageMain

代碼位置:system/core/init/first_stage_init.cpp,主要是創建掛載相關文件目錄

int FirstStageMain(int argc, char** argv) {
    //初始化重啓系統的處理信號,通過sigaction註冊新號並監聽,源碼位置:system/core/init/reboot_utils.cpp
    if (REBOOT_BOOTLOADER_ON_PANIC) {
        InstallRebootSignalHandlers();
    }
    //系統時鐘
    boot_clock::time_point start_time = boot_clock::now();
    ...
    //一系列文件操作,linux下socket也是特殊文件,0755標記用户具有讀/寫/執行 權限,具體可查看相關命令
    CHECKCALL(mkdir("/dev/socket", 0755));
    //CMD命令行
    CHECKCALL(chmod("/proc/cmdline", 0440));
    std::string cmdline;
    android::base::ReadFileToString("/proc/cmdline", &cmdline);
    //讀取bootconfig
    chmod("/proc/bootconfig", 0440);
    std::string bootconfig;
    android::base::ReadFileToString("/proc/bootconfig", &bootconfig);
    ...
    SetStdioToDevNull(argv);
    //-------------- SetStdioToDevNull 源碼如下注釋如下 ---------------------------------
    最後,在第一階段初始化中簡單地調用 SetStdioToDevNull() 是不夠的,因為首先
    stage init 仍然在內核上下文中運行,未來的子進程將無權
    訪問它打開的任何 FDS,包括下面為 /dev/null 打開的 FDS。因此
    SetStdioToDevNull() 必須在第二階段 init 中再次調用。
    void SetStdioToDevNull(char** argv) {
        // Make stdin/stdout/stderr all point to /dev/null.
        int fd = open("/dev/null", O_RDWR);  // NOLINT(android-cloexec-open)
        if (fd == -1) {
            int saved_errno = errno;
            android::base::InitLogging(argv, &android::base::KernelLogger, InitAborter);
            errno = saved_errno;
            PLOG(FATAL) << "Couldn't open /dev/null";
        }
        dup2(fd, STDIN_FILENO);
        dup2(fd, STDOUT_FILENO);
        dup2(fd, STDERR_FILENO);
        if (fd > STDERR_FILENO) close(fd);
    }
    //-------------- SetStdioToDevNull() ---------------------------------
    //初始化內核日誌打印
    InitKernelLogging(argv);
    ...
    //unique_ptr智能指針主動釋放內存
    auto old_root_dir = std::unique_ptr<DIR, decltype(&closedir)>{opendir("/"), closedir};
    struct stat old_root_info;
    if (stat("/", &old_root_info) != 0) {
        PLOG(ERROR) << "Could not stat(\"/\"), not freeing ramdisk";
        //無法釋放時直接重啓
        old_root_dir.reset();重啓方法定義文件位置:/external/libcxx/include/memory
    }
    //FirstStageConsole
    auto want_console = ALLOW_FIRST_STAGE_CONSOLE ? FirstStageConsole(cmdline, bootconfig) : 0;
    auto want_parallel =
            bootconfig.find("androidboot.load_modules_parallel = \"true\"") != std::string::npos;
    ...
    //在恢復模式(Recovery)下驗證AVB原數據,驗證成功設置INIT_AVB_VERSION
    SetInitAvbVersionInRecovery();
    //寫入環境變量
    setenv(kEnvFirstStageStartedAt, std::to_string(start_time.time_since_epoch().count()).c_str(),
           1);

    const char* path = "/system/bin/init";
    const char* args[] = {path, "selinux_setup", nullptr};
    auto fd = open("/dev/kmsg", O_WRONLY | O_CLOEXEC);
    dup2(fd, STDOUT_FILENO);
    dup2(fd, STDERR_FILENO);
    close(fd);
    //啓動新進程運行“selinux_setup”函數下一個階段,執行流程回到 main.cpp
    execv(path, const_cast<char**>(args));
    // execv() only returns if an error happened, in which case we
    // panic and never fall through this conditional.
    PLOG(FATAL) << "execv(\"" << path << "\") failed";
    return 1;
}

2.4 SetupSelinux.cpp

設置安全策略
文件位置:/system/core/init/selinux.cpp

int SetupSelinux(char** argv) {
    //參考3.3中同函數描述
    SetStdioToDevNull(argv);
    //初始化內核日誌
    InitKernelLogging(argv);
    if (REBOOT_BOOTLOADER_ON_PANIC) {
        //參考3.3中同函數描述
        InstallRebootSignalHandlers();
    }
    //系統啓動時間
    boot_clock::time_point start_time = boot_clock::now();
    //R 上掛載system_ext,system,product 源碼位置:/system/core/init/selinux.cpp
    MountMissingSystemPartitions();
    //寫入kmsg selinux日誌
    SelinuxSetupKernelLogging();
    //預編譯安全策略
    PrepareApexSepolicy();
    // Read the policy before potentially killing snapuserd.
    std::string policy;
    //讀取policy
    ReadPolicy(&policy);
    //清理預編譯緩存
    CleanupApexSepolicy();
    ...
    //加載安全策略
    LoadSelinuxPolicy(policy);
    ...
    //強制執行安全策略
    SelinuxSetEnforcement();
    ...
    //設置env環境
    setenv(kEnvSelinuxStartedAt, std::to_string(start_time.time_since_epoch().count()).c_str(), 1);

    const char* path = "/system/bin/init";
    const char* args[] = {path, "second_stage", nullptr};
    //啓動新進程運行“second_stage”函數下一個階段,執行流程回到 main.cpp
    execv(path, const_cast<char**>(args));

    // execv() only returns if an error happened, in which case we
    // panic and never return from this function.
    PLOG(FATAL) << "execv(\"" << path << "\") failed";
    return 1;
}

2.5 SecondStageMain.cpp

第二階段啓動,文件位置:/system/core/init/init.cpp

int SecondStageMain(int argc, char** argv) {
    ...
    ...
    // 當設備解鎖時允許adb root加載調試信息
    const char* force_debuggable_env = getenv("INIT_FORCE_DEBUGGABLE");
    bool load_debug_prop = false;
    if (force_debuggable_env && AvbHandle::IsDeviceUnlocked()) {
        load_debug_prop = "true"s == force_debuggable_env;
    }
    ...
    //屬性初始化,源碼位置:/system/core/init/property_service.cpp
    //創建屬性信息並存儲在/dev/__properties__/property_info中,同時處理
    //ProcessKernelDt();
    //ProcessKernelCmdline();
    //ProcessBootconfig();
    //ExportKernelBootProps();
    //PropertyLoadBootDefaults();
    PropertyInit();
    // Umount second stage resources after property service has read the .prop files.
    UmountSecondStageRes();
    // Umount the debug ramdisk after property service has read the .prop files when it means to.
    if (load_debug_prop) {
        UmountDebugRamdisk();
    }
    // Mount extra filesystems required during second stage init
    MountExtraFilesystems();
    // Now set up SELinux for second stage.
    SelabelInitialize();
    SelinuxRestoreContext();
    Epoll epoll;
    if (auto result = epoll.Open(); !result.ok()) {
        PLOG(FATAL) << result.error();
    }
    // We always reap children before responding to the other pending functions. This is to
    // prevent a race where other daemons see that a service has exited and ask init to
    // start it again via ctl.start before init has reaped it.
    epoll.SetFirstCallback(ReapAnyOutstandingChildren);
    //設置監聽處理子進程退出信號
    InstallSignalFdHandler(&epoll);
    //喚醒init進程
    InstallInitNotifier(&epoll);
    //創建property_service,property_set_fd sockets,property service 線程,通過sokcet與init進程通信
    //源碼位置:/system/core/init/property_service.cpp
    StartPropertyService(&property_fd);
    // Make the time that init stages started available for bootstat to log.
    RecordStageBoottimes(start_time);
    // Set libavb version for Framework-only OTA match in Treble build.
    if (const char* avb_version = getenv("INIT_AVB_VERSION"); avb_version != nullptr) {
        SetProperty("ro.boot.avb_version", avb_version);
    }
    ...
    //初始化subcontext
    InitializeSubcontext();
    //創建ActionManager、ServiceList
    ActionManager& am = ActionManager::GetInstance();
    ServiceList& sm = ServiceList::GetInstance();
    //加載rc文件
    LoadBootScripts(am, sm);
    //觸發 early-init 語句
    am.QueueEventTrigger("early-init");
    ...
    //觸發 init 語句
    am.QueueEventTrigger("init");
    ...
    //插入要執行的 Action
    am.QueueBuiltinAction(InitBinder, "InitBinder");
    ...
    //設置action,等待event_queue執行函數
    am.QueueBuiltinAction(SetupCgroupsAction, "SetupCgroups");
    ...
    std::string bootmode = GetProperty("ro.bootmode", "");
    if (bootmode == "charger") {
        //觸發 charger 語句
        am.QueueEventTrigger("charger");
    } else {
        //觸發 late-init 語句
        am.QueueEventTrigger("late-init");
    }
    ...
    ...
    while (true) {
        // By default, sleep until something happens. Do not convert far_future into
        // std::chrono::milliseconds because that would trigger an overflow. The unit of boot_clock
        // is 1ns.
        const boot_clock::time_point far_future = boot_clock::time_point::max();
        boot_clock::time_point next_action_time = far_future;
        auto shutdown_command = shutdown_state.CheckShutdown();
        //關機命令
        if (shutdown_command) {
            LOG(INFO) << "Got shutdown_command '" << *shutdown_command
                      << "' Calling HandlePowerctlMessage()";
            HandlePowerctlMessage(*shutdown_command);
        }
        //執行action
        if (!(prop_waiter_state.MightBeWaiting() || Service::is_exec_service_running())) {
            am.ExecuteOneCommand();
            // If there's more work to do, wake up again immediately.
            if (am.HasMoreCommands()) {
                next_action_time = boot_clock::now();
            }
        }
        ...
        if (!IsShuttingDown()) {
            //處理屬性的control命令,關聯ctl.開頭的屬性
            HandleControlMessages();
            //設置usb屬性
            SetUsbController();
        }
    }
    return 0;
}

exec 函數族有多個變種的形式:execl、execle、execv,具體描述可閲讀該文檔
https://zhuanlan.zhihu.com/p/363510745

2.6 SubcontextMain-subcontext進程

源碼位置 : system/core/init/subcontext.cpp

首先執行adb shell 查看context CMD命令

adb shell ps -Af
root 572 1 0 17:40:12 ? 00:00:21 init subcontext u:r:vendor_init:s0 12
root 573 1 0 17:40:12 ? 00:00:04 init subcontext u:r:vendor_init:s0 13
  • system context : u:r:init:s0
  • vendor context : u:r:vendor_init:s0

核心調用方法,通過socket與init進程通信

//初始化subcontext
void InitializeSubcontext() {  
    ...
    //使用u:r:vendor_init:s0 context來執行命令
    if (SelinuxGetVendorAndroidVersion() >= __ANDROID_API_P__) {
        subcontext.reset(
                new Subcontext(std::vector<std::string>{"/vendor", "/odm"}, kVendorContext));
    }
}
//Fork子進程
void Subcontext::Fork()
//init.cpp main()初始化
int SubcontextMain(int argc, char** argv, const BuiltinFunctionMap* function_map) { 
    auto context = std::string(argv[2]);
    auto init_fd = std::atoi(argv[3]);
    ...
    auto subcontext_process = SubcontextProcess(function_map, context, init_fd);
    // Restore prio before main loop
    setpriority(PRIO_PROCESS, 0, 0);
    //MainLoop死循環,對socket進行監聽/讀取/解析/執行CMD/SendMessage init
    subcontext_process.MainLoop();
    return 0;
}
void SubcontextProcess::MainLoop()

2.7 第二階段LoadBootScripts方法

static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {
    //創建解析器
    Parser parser = CreateParser(action_manager, service_list);
    //獲取.init_rc屬性
    std::string bootscript = GetProperty("ro.boot.init_rc", "");
    if (bootscript.empty()) {
        //解析init.rc
        parser.ParseConfig("/system/etc/init/hw/init.rc");
        if (!parser.ParseConfig("/system/etc/init")) {
            late_import_paths.emplace_back("/system/etc/init");
        }
        // late_import is available only in Q and earlier release. As we don't
        // have system_ext in those versions, skip late_import for system_ext.
        //通用系統組件
        parser.ParseConfig("/system_ext/etc/init");
        //“vendor” 廠商對系統的定製
        if (!parser.ParseConfig("/vendor/etc/init")) {
            late_import_paths.emplace_back("/vendor/etc/init");
        }
        //“odm” 廠商對系統定製的可選分區
        if (!parser.ParseConfig("/odm/etc/init")) {
            late_import_paths.emplace_back("/odm/etc/init");
        }
        //“product” 特定的產品模塊,對系統的定製化
        if (!parser.ParseConfig("/product/etc/init")) {
            late_import_paths.emplace_back("/product/etc/init");
        }
    } else {
        parser.ParseConfig(bootscript);
    }
}

解析器有Parser,包含Action,Command,ActionManager,Service,Option,ServiceList等對象,整個解析過程是面向對象

Parser CreateParser(ActionManager& action_manager, ServiceList& service_list) {
    //以section塊為單位,包含service,on,import語句
    Parser parser;
    //ServiceParser解析器
    parser.AddSectionParser("service", std::make_unique<ServiceParser>(
    &service_list, GetSubcontext(), std::nullopt));
    //ActionParser解析器
    parser.AddSectionParser("on", std::make_unique<ActionParser>(&action_manager, GetSubcontext()));
    //ImportParser解析器
    parser.AddSectionParser("import", std::make_unique<ImportParser>(&parser));
    return parser;
}

解析器都繼承於SectionParser,文件位置:/system/core/init/parser.h,每個parser從上往下解析, 對應步驟如下(具體可以看文件源碼):

  • 分析開始(ParseSection)
  • 每一行分析(ParseLineSection)
  • 結束分析(EndSection/EndFile)

不同解析器處理不同section塊,以上面三種解析器為例:

  • ServiceParser : 解析service section,構建Service對象,記錄可執行文件路徑和參數,最後交由ServiceList(std::vector<Service*>)管理
  • ActionParser : 解析action section,構建action對象,包含所有command,最後交由ActionManager管理
  • ImportParser : 解析導入的rc文件名

瞭解解析器後,我們繼續看init.rc具體腳本內容,文件位置:/system/core/rootdir/init.rc
腳本源碼內容基本1000+行,所以拆分出主流程,詳細的可閲讀源碼瞭解

//am.QueueEventTrigger("early-init")
on early-init
    //一個守護進程,負責處理 uevent 消息
    start ueventd
    //apex 服務於系統模塊安裝
    exec_start apexd-bootstrap

//觸發所有 action
//am.QueueEventTrigger("init");
on init
    //創建 stdio 標準輸入輸出鏈接
    symlink /proc/self/fd/0 /dev/stdin
    //設置sdcard權限
    chmod 0770 /config/sdcardfs
    //啓動servicemanager
    start servicemanager
    //啓動硬件服務
    start hwservicemanager
    //供應商服務
    start vndservicemanager
    
//am.QueueEventTrigger("charger");
//屬性 - 充電模式 trigger late-init
on property:sys.boot_from_charger_mode=1
    class_stop charger
    trigger late-init
    
//掛載文件系統,啓動系統核心服務
//am.QueueEventTrigger("late-init")
on late-init
    //觸發 fs:外部存儲
    trigger early-fs
    //觸發zygote進程,文件位置:system/core/rootdir/init.zygote32.rc
    trigger zygote-start
    //boot
    trigger early-boot
    trigger boot

on boot
    //啓動HAL硬件服務
    class_start hal
    //啓動核心類服務
    class_start core

2.8 解析zygote.rc腳本文件

文件位置:

  • /system/core/rootdir/init.zygote32.rc,
  • system/core/rootdir/init.zygote64.rc,
  • system/core/rootdir/init.zygote64_32.rc
  • system/core/rootdir/init.no_zygote.rc

    service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
      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 exec_background - system system -- /system/bin/vdc volume abort_fuse
      onrestart write /sys/power/state on
      # NOTE: If the wakelock name here is changed, then also
      # update it in SystemSuspend.cpp
      onrestart write /sys/power/wake_lock zygote_kwl
      onrestart restart audioserver
      onrestart restart cameraserver
      onrestart restart media
      onrestart restart media.tuner
      onrestart restart netd
      onrestart restart wificond
      task_profiles ProcessCapacityHigh
      critical window=${zygote.critical_window.minute:-off} target=zygote-fatal
  • service zygote 定義zygote服務,init進程通過該名稱fork子進程
  • /system/bin/app_process 執行系統下app_process並傳入後面參數
  • -Xzygote 參數作為虛擬機入參
  • /system/bin 虛擬機所在文件位置
  • --zygote 指定虛擬機執行入口函數:ZygoteInit.java main()
  • --start-system-server 啓動zygote系統服務

3. Zygote進程

基於init.rc腳本配置,通過解析器及服務相關配置,此時已經進入native framework層準備進入啓動入口,通過AppRuntime main() 調用AndroidRuntime start()最終啓動,AppRuntime 繼承於AndroidRuntime,main()會解析啓動zygote服務傳遞的參數,然後根據指定參數啓動是ZygoteInit 還是RuntimeInit;下面我看下AppRuntime app_process 源碼定義

源碼位置:/frameworks/base/cmds/app_process/app_main.cpp

#if defined(__LP64__)
static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist64";
static const char ZYGOTE_NICE_NAME[] = "zygote64";
#else
static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist32";
static const char ZYGOTE_NICE_NAME[] = "zygote";
#endif

//AppRuntime構造函數調用父類方法初始化Skia引擎
AndroidRuntime::AndroidRuntime(char* argBlockStart, const size_t argBlockLength) :
        mExitWithoutCleanup(false),
        mArgBlockStart(argBlockStart),
        mArgBlockLength(argBlockLength){
    init_android_graphics();
    ...
}
//入口方法
int main(int argc, char* const argv[]){
    //構建AppRuntime
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    // Process command line arguments
    // ignore argv[0]
    argc--;
    argv++;
    //解析init.rc 啓動zygote service參數
    // Parse runtime arguments.  Stop at first unrecognized option.
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;
    String8 className;
    ++i;  // Skip unused "parent dir" argument.
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) {
            //ztgote設置為true
            zygote = true;
            //32位名稱為zygote,64位為zygote64
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
            //是否啓動system-server
            startSystemServer = true;
        } else if (strcmp(arg, "--application") == 0) {
            //獨立應用
            application = true;
        } else if (strncmp(arg, "--nice-name=", 12) == 0) {
            //進程別名,區分abi
            niceName.setTo(arg + 12);
        } else if (strncmp(arg, "--", 2) != 0) {
            className.setTo(arg);
            break;
        } else {
            --i;
            break;
        }
    }
    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);
        ...
    } else {
        // We're in zygote mode. 進入zygote模式,創建dalvik緩存目錄,data/dalivk-cache
        maybeCreateDalvikCache();
        //加入"start-system-server"參數
        if (startSystemServer) {
            args.add(String8("start-system-server"));
        }
        //處理abi相關
        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);
        // In zygote mode, pass all remaining arguments to the zygote
        // main() method.
        for (; i < argc; ++i) {
            args.add(String8(argv[i]));
        }
    }
    //設置process名稱 -  由app_process 改為 niceName變量值
    if (!niceName.isEmpty()) {
        runtime.setArgv0(niceName.string(), true /* setProcName */);
    }
    //如果是zygote啓動模式,加載com.android.internal.os.ZygoteInit.java
    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        //如果是application模式,加載RuntimeInit.java
        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.");
    }
}

基於AppRuntime繼承AndroidRuntime,我們繼續看下runtime.start真正執行的代碼段

源碼位置:/frameworks/base/core/jni/AndroidRuntime.cpp

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote){
    /* start the virtual machine */
    JniInvocation jni_invocation;
    //加載libart.so
    jni_invocation.Init(NULL);
    JNIEnv* env;
    //啓動Java虛擬機
    if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
        return;
    }
    //回調子類重寫方法
    onVmCreated(env);
    //註冊Android JNI方法,為後面查找ZygoteInit.java類準備
    /*
     * Register android functions.
     */
    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.
     */
    jclass stringClass;
    jobjectArray strArray;
    jstring classNameStr;
    //查找zygote初始化類,
    //runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    stringClass = env->FindClass("java/lang/String");
    assert(stringClass != NULL);
    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
    assert(strArray != NULL);
    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);
    }
    /*
     * Start VM.  This thread becomes the main thread of the VM, and will
     * not return until the VM exits.
     */
    //JNI中的類名規則:將Java類名中的"."替換成"/"
    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.java 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 {
            //已找到main方法,通過JNI調用Java方法,最終啓動zygote init初始化相關
            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");
}

通過AndroidRuntime源碼我們可以看到它做了以下幾點

  • jni_invocation.Init 加載libart.so
  • startVm 啓動Java虛擬機
  • startReg 註冊Android JNI方法
  • FindClass 查找zygote初始化類
  • CallStaticVoidMethod 調用ZygoteInit.java main()

3.1 啓動JVM :JniInvocation初始化

JniInvocation實際是頭文件代理類,最終調用實現為JniInvocationImpl,通過構造函數初始化impl,接着調用init方法,最終都轉向JniInvocationImpl.c中方法調用

JniInvocation.h 源碼位置:
/libnativehelper/include_platform/nativehelper/JniInvocation.h

JniInvocationImpl.c 源碼位置:
/libnativehelper/include_platform/nativehelper/JniInvocation.h

static const char* kDefaultJniInvocationLibrary = "libart.so";

bool JniInvocationInit(struct JniInvocationImpl* instance, const char* library_name) {
  ...
  //非debug模式返回kDefaultJniInvocationLibrary參數
  library_name = JniInvocationGetLibrary(library_name, buffer);
  //打開"libart.so"
  DlLibrary library = DlOpenLibrary(library_name);
  if (library == NULL) {
    //加載失敗返回false
    if (strcmp(library_name, kDefaultJniInvocationLibrary) == 0) {
      // Nothing else to try.
      ALOGE("Failed to dlopen %s: %s", library_name, DlGetError());
      return false;
    }
    ...
  }
  //從當前"libart.so"獲取以下3個JNI函數指針
  DlSymbol JNI_GetDefaultJavaVMInitArgs_ = FindSymbol(library, "JNI_GetDefaultJavaVMInitArgs");
  //獲取虛擬機默認初始化參數
  if (JNI_GetDefaultJavaVMInitArgs_ == NULL) {
    return false;
  }
  DlSymbol JNI_CreateJavaVM_ = FindSymbol(library, "JNI_CreateJavaVM");
  //創建虛擬機
  if (JNI_CreateJavaVM_ == NULL) {
    return false;
  }
  DlSymbol JNI_GetCreatedJavaVMs_ = FindSymbol(library, "JNI_GetCreatedJavaVMs");
  //獲取創建的實例
  if (JNI_GetCreatedJavaVMs_ == NULL) {
    return false;
  }
  ...
  return true;
}

3.2 啓動JVM :startVM()

該方法主要處理以下內容

  • 配置虛擬機參數和選項
  • 調用JNI_CreateJavaVM()創建並初始化,該方法原始位置:/art/runtime/jni/java_vm_ext.cc

3.3 startReg 註冊Android JNI方法

/*
 * Register android native functions with the VM.
 */
/*static*/ int AndroidRuntime::startReg(JNIEnv* env){
    ATRACE_NAME("RegisterAndroidNatives");
    /*
     * This hook causes all future threads created in this process to be
     * attached to the JavaVM.  (This needs to go away in favor of JNI
     * Attach calls.)
     */
     //根據源碼註釋,此處調用javaCreateThreadEtc創建的線程會attached jvm,這樣C++、Java代碼都能執行
    androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);
    /*
     * Every "register" function calls one or more things that return
     * a local reference (e.g. FindClass).  Because we haven't really
     * started the VM yet, they're all getting stored in the base frame
     * and never released.  Use Push/Pop to manage the storage.
     */
     //jni局部引用 - 入棧
    env->PushLocalFrame(200);
    //註冊jni方法
    if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
        env->PopLocalFrame(NULL);
        return -1;
    }
    //jni局部引用 - 出棧
    env->PopLocalFrame(NULL);
    //createJavaThread("fubar", quickTest, (void*) "hello");
    return 0;
}
//JNI函數數組
static const RegJNIRec gRegJNI[] = {
    REG_JNI(register_com_android_internal_os_RuntimeInit),
    REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit),
    ...
    ...
}
//循環調用gRegJNI數組中所有的函數
static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env){
    for (size_t i = 0; i < count; i++) {
        if (array[i].mProc(env) < 0) {
            ...
            return -1;
        }
    }
    return 0;
}
//gRegJNI函數數組實例,JNI函數相關調用
int register_com_android_internal_os_RuntimeInit(JNIEnv* env){
    const JNINativeMethod methods[] = {
            {"nativeFinishInit", "()V",
             (void*)com_android_internal_os_RuntimeInit_nativeFinishInit},
            {"nativeSetExitWithoutCleanup", "(Z)V",
             (void*)com_android_internal_os_RuntimeInit_nativeSetExitWithoutCleanup},
    };
    return jniRegisterNativeMethods(env, "com/android/internal/os/RuntimeInit",
        methods, NELEM(methods));
}
int register_com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env){
    const JNINativeMethod methods[] = {
        { "nativeZygoteInit", "()V",
            (void*) com_android_internal_os_ZygoteInit_nativeZygoteInit },
    };
    return jniRegisterNativeMethods(env, "com/android/internal/os/ZygoteInit",
        methods, NELEM(methods));
}

通過以上JVM虛擬機配置/創建,JNI引用註冊/函數查找,以及對ZygoteInit main()調用,我們可以進入ZygoteInit.java代碼了,一起看看Java層是如何實現

4. ZygoteInit.java類

源碼路徑:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

下面先看看main()源碼定義,然後再繼續分析

public static void main(String[] argv) {
    ZygoteServer zygoteServer = null;
    // Mark zygote start. This ensures that thread creation will throw
    // an error.
    ZygoteHooks.startZygoteNoThreadCreation();
    // Zygote goes into its own process group.
    try {
        Os.setpgid(0, 0);
    } catch(ErrnoException ex) {
        throw new RuntimeException("Failed to setpgid(0,0)", ex);
    }
    Runnable caller;
    try {
        // Store now for StatsLogging later.
        final long startTime = SystemClock.elapsedRealtime();
        final boolean isRuntimeRestarted = "1".equals(SystemProperties.get("sys.boot_completed"));

        String bootTimeTag = Process.is64Bit() ? "Zygote64Timing": "Zygote32Timing";
        TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag, Trace.TRACE_TAG_DALVIK);
        bootTimingsTraceLog.traceBegin("ZygoteInit");
        RuntimeInit.preForkInit();
        //設置startSystemServer,abiList,argvs參數,sokcet name等
        boolean startSystemServer = false;
        String zygoteSocketName = "zygote";
        String abiList = null;
        boolean enableLazyPreload = false;
        for (int i = 1; i < argv.length; i++) {
            if ("start-system-server".equals(argv[i])) {
                startSystemServer = true;
            } else if ("--enable-lazy-preload".equals(argv[i])) {
                enableLazyPreload = true;
            } else if (argv[i].startsWith(ABI_LIST_ARG)) {
                abiList = argv[i].substring(ABI_LIST_ARG.length());
            } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
                zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
            } else {
                throw new RuntimeException("Unknown command line argument: " + argv[i]);
            }
        }
        final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);
        if (!isRuntimeRestarted) {
            if (isPrimaryZygote) {
                FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED, BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__ZYGOTE_INIT_START, startTime);
            } else if (zygoteSocketName.equals(Zygote.SECONDARY_SOCKET_NAME)) {
                FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED, BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__SECONDARY_ZYGOTE_INIT_START, startTime);
            }
        }
        if (abiList == null) {
            throw new 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
        }
        // Do an initial gc to clean up after startup
        bootTimingsTraceLog.traceBegin("PostZygoteInitGC");
        gcAndFinalize();
        bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC
        bootTimingsTraceLog.traceEnd(); // ZygoteInit
        Zygote.initNativeState(isPrimaryZygote);
        ZygoteHooks.stopZygoteNoThreadCreation();
        zygoteServer = new ZygoteServer(isPrimaryZygote);
        if (startSystemServer) {
            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;
            }
        }
        Log.i(TAG, "Accepting command socket connections");
        // 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 fatal exception", ex);
        throw ex;
    } finally {
        if (zygoteServer != null) {
            zygoteServer.closeServerSocket();
        }
    }
    // We're in the child process and have exited the select loop. Proceed to execute the
    // command.
    if (caller != null) {
        caller.run();
    }
}

main方法主要處理以下內容:

  1. ZygoteHooks.startZygoteNoThreadCreation() 標記zygote啓動,單線程模式

    Java層調用native方法,源碼:art/runtime/native/dalvik_system_ZygoteHooks.cc

    static void ZygoteHooks_startZygoteNoThreadCreation(JNIEnv* env ATTRIBUTE_UNUSED,jclass klass ATTRIBUTE_UNUSED) {
      Runtime::Current()->SetZygoteNoThreadSection(true);
    }
    static void ZygoteHooks_stopZygoteNoThreadCreation(JNIEnv* env ATTRIBUTE_UNUSED,jclass klass ATTRIBUTE_UNUSED) {
      Runtime::Current()->SetZygoteNoThreadSection(false);
    }
    //調用上面2個方法設置zygote_no_threads_參數值,源碼:/art/runtime/runtime.h
    void SetZygoteNoThreadSection(bool val) {
        zygote_no_threads_ = val;
    }
  2. android.system.Os.setpgid(0, 0) 設置進程組id為0
  3. RuntimeInit.preForkInit() Zygote Init預初始化,開啓DDMS,設置MimeMap
  4. preload(bootTimingsTraceLog) 開始預加載resources,class,tff

    static void preload(TimingsTraceLog bootTimingsTraceLog) {
        //開始
        beginPreload();
        //加載pre class,文件位置:frameworks/base/boot/preloaded-classes frameworks/base/config/preloaded-classes
        preloadClasses();
        //加載無法放入Boot classpath的文件,/system/framework/android.hidl.base-V1.0-java.jar /system/framework/android.test.base.jar
        cacheNonBootClasspathClassLoaders();
        //加載drawables、colors
        preloadResources();
        //加載hal 硬件
        nativePreloadAppProcessHALs();
        //調用OpenGL/Vulkan加載圖形驅動程序
        maybePreloadGraphicsDriver();
        //加載共享庫,System.loadLibrary("android")(“jnigraphics”)(“compiler_rt”)
        preloadSharedLibraries();
        //初始化TextView
        preloadTextResources();
        //初始化WebView
        WebViewFactory.prepareWebViewInZygote();
        //結束
        endPreload();
        warmUpJcaProviders();
        sPreloadComplete = true;
    }
  5. gcAndFinalize() 在fork之前主動調用Java gc
  6. Zygote.initNativeState(isPrimaryZygote) [1]從環境中獲取套接字FD [2]初始化安全屬性 [3]適當地卸載存儲 [4]加載必要的性能配置文件信息
  7. ZygoteHooks.stopZygoteNoThreadCreation() 標記zygote停止維護單線程模式,可創建子線程
  8. zygoteServer = new ZygoteServer 初始化ZygoteServer - socket

    調用Zygote.createManagedSocketFromInitSocket方法實例化LocalServerSocketImpl對象

    //源碼位置:/frameworks/base/core/java/android/net/LocalServerSocket.java
    //        /frameworks/base/core/java/android/net/LocalSocketImpl.java
    public LocalServerSocket(String name) throws IOException {
        //實例化
        impl = new LocalSocketImpl();
        //創建socket流
        impl.create(LocalSocket.SOCKET_STREAM);
        //建立本地通信地址
        localAddress = new LocalSocketAddress(name);
        //綁定該地址
        impl.bind(localAddress);
        //Linux函數listen 開啓監聽
        impl.listen(LISTEN_BACKLOG);
    }
  9. Runnable r = forkSystemServer : fork出SystemServer,對應com.android.server.SystemServer
  10. caller = zygoteServer.runSelectLoop 一直循環接收socket消息
    在runSelectLoop死循環中,會先創建StructPollfd數組並通過Os.poll函數轉換為struct pollfd數組,如果是ZygoteServer socket對應的fd,則調用ZygoteConnection newPeer = acceptCommandPeer(abiList)建立socket連接,源碼如下:

    //acceptCommandPeer
    private ZygoteConnection acceptCommandPeer(String abiList) {
        try {
            return createNewConnection(mZygoteSocket.accept(), abiList);
        } catch(IOException ex) {
            throw new RuntimeException("IOException during accept()", ex);
        }
    }
    //調用LocalSocketImpl的accept方法接受socket
    public LocalSocket accept() throws IOException {
        LocalSocketImpl acceptedImpl = new LocalSocketImpl();
        impl.accept(acceptedImpl);
        //把LocalSocketImpl包裝成LocalSocket對象
        return LocalSocket.createLocalSocketForAccept(acceptedImpl);
    }
    //然後將LocalSocket包裝成ZygoteConnection socket連接
    ZygoteConnection(LocalSocket socket, String abiList) throws IOException {
        mSocket = socket;
        this.abiList = abiList;
        //開啓寫入流,準備寫入數據
        mSocketOutStream = new DataOutputStream(socket.getOutputStream());
        mSocket.setSoTimeout(CONNECTION_TIMEOUT_MILLIS);
        try {
            peer = mSocket.getPeerCredentials();
        } catch(IOException ex) {
            Log.e(TAG, "Cannot read peer credentials", ex);
            throw ex;
        }
        isEof = false;
    }

    循環繼續往下走,調用connection.processOneCommand執行socket命令,通過Zygote.readArgumentList讀取socket傳遞參數,ZygoteArguments對象處理參數,一系列參數校驗完成,開始調用Zygote.forkAndSpecialize創建子進程

    static int forkAndSpecialize(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, boolean isTopApp, String[] pkgDataInfoList, String[] allowlistedDataInfoList, boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs) {
        //1.預先fork時會停止zygote創建的4個守護進程,釋放資源
            //HeapTaskDaemon.INSTANCE.stop();           Java堆任務線程
            //ReferenceQueueDaemon.INSTANCE.stop();     引用隊列線程
            //FinalizerDaemon.INSTANCE.stop();          析構線程
            //FinalizerWatchdogDaemon.INSTANCE.stop();  析構監控線程
        //2.調用native方法完成gc heap初始化
        //3.等待所有子線程結束
        ZygoteHooks.preFork();
        //調用native方法
        int pid = nativeForkAndSpecialize(uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose, fdsToIgnore, startChildZygote, instructionSet, appDataDir, isTopApp, pkgDataInfoList, allowlistedDataInfoList, bindMountAppDataDirs, bindMountAppStorageDirs);
        if (pid == 0) {
            //監控handleChildProc處理,直到子進程fork完畢
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
            // If no GIDs were specified, don't make any permissions changes based on groups.
            if (gids != null && gids.length > 0) {
                NetworkUtilsInternal.setAllowNetworkingForProcess(containsInetGid(gids));
            }
        }
        // Set the Java Language thread priority to the default value for new apps.
        Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
        //fork結束後恢復其它線程
        ZygoteHooks.postForkCommon();
        return pid;
    }
    
    //nativeFork方法,源碼位置:frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
    private static native int nativeForkAndSpecialize(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, boolean isTopApp, String[] pkgDataInfoList, String[] allowlistedDataInfoList, boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs);

    我們繼續往下查看handleChildProc子進程處理,

    private Runnable handleChildProc(ZygoteArguments parsedArgs, FileDescriptor pipeFd, boolean isZygote) {
        //進程創建完畢關閉socket
        closeSocket();
        //設置進程名稱
        Zygote.setAppProcessName(parsedArgs, TAG);
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        //這個地方mInvokeWith未找到調用源
        if (parsedArgs.mInvokeWith != null) {
            WrapperInit.execApplication(parsedArgs.mInvokeWith, parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion, VMRuntime.getCurrentInstructionSet(), pipeFd, parsedArgs.mRemainingArgs);
            throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned");
        } else {
            if (!isZygote) {
                return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion, parsedArgs.mDisabledCompatChanges, parsedArgs.mRemainingArgs, null);
            } else {
                return ZygoteInit.childZygoteInit(parsedArgs.mRemainingArgs);
            }
        }
    }
    //ZygoteInit.zygoteInit 源碼位置:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
    public static Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges, String[] argv, ClassLoader classLoader) {
        ...
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
        //重定向log流
        RuntimeInit.redirectLogStreams();
        //log、thread、AndroidConfig初始化
        RuntimeInit.commonInit();
        //最終調用AndroidRuntime-AppRuntime-onZygoteInit(),初始化binder
        ZygoteInit.nativeZygoteInit();
        //應用初始化
        return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv, classLoader);
    }
    
    //源碼位置:frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
    protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges, String[] argv, ClassLoader classLoader) {
        //如果應用程序調用System.exit(),則終止進程立即運行,而不運行hooks;不可能優雅地關閉Android應用程序。
        //除其他外Android運行時關閉掛鈎關閉Binder驅動程序,這可能導致剩餘的運行線程在進程實際退出之前崩潰
        nativeSetExitWithoutCleanup(true);
        //設置targetVersion\disabledCompatChanges參數
        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
        VMRuntime.getRuntime().setDisabledCompatChanges(disabledCompatChanges);
        //解析參數
        final Arguments args = new Arguments(argv);
        // The end of of the RuntimeInit event (see #zygoteInit).
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        //解析參數,調用startClass對應的main方法,此處class為:android.app.ActivityThread
        //通過反射查找main方法並創建MethodAndArgsCaller runnable執行對象
        //通過調用ZygoteInit.runSelectLoop返回runnable caller,如果不為空caller.run
        return findStaticMain(args.startClass, args.startArgs, classLoader);
    }
  11. zygoteServer.closeServerSocket() 關閉接收socket消息

5.SystemServer.java

Zygote的forkSystemServer方法最終會走到nativeForkSystemServer進行處理,
對應源碼位置:frameworks/base/core/jni/com_android_internal_os_Zygote.cpp

String[] args = {
    "--setuid=1000",
    "--setgid=1000",
    "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023," + "1024,1032,1065,3001,3002,3003,3005,3006,3007,3009,3010,3011,3012",
    "--capabilities=" + capabilities + "," + capabilities,
    "--nice-name=system_server",
    "--runtime-args",
    "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
    "com.android.server.SystemServer",
};

調用方法傳參時定義了 "com.android.server.SystemServer",由此後續在調用ZygoteInit.zygoteInit、RuntimeInit.applicationInit、findStaticMain等方法後,最終會調用com.android.server.SystemServer main()方法,省略以上過程我們直接進入主入口源碼

//源碼路徑:frameworks/base/services/java/com/android/server/SystemServer.java
public static void main(String[] args) {
    new SystemServer().run();
}
public SystemServer() {
    // Check for factory test mode.
    mFactoryTestMode = FactoryTest.getMode();
    //記錄進程啓動信息
    mStartCount = SystemProperties.getInt(SYSPROP_START_COUNT, 0) + 1;
    //設置時間
    mRuntimeStartElapsedTime = SystemClock.elapsedRealtime();
    mRuntimeStartUptime = SystemClock.uptimeMillis();
    Process.setStartTimes(mRuntimeStartElapsedTime, mRuntimeStartUptime, mRuntimeStartElapsedTime, mRuntimeStartUptime);
    //記錄是運行時重啓還是重新啓動
    mRuntimeRestart = "1".equals(SystemProperties.get("sys.boot_completed"));
}
//run
private void run() {
    TimingsTraceAndSlog t = new TimingsTraceAndSlog();
    try {
        //監控開始
        t.traceBegin("InitBeforeStartServices");
        //進程系統屬性信息
        SystemProperties.set(SYSPROP_START_COUNT, String.valueOf(mStartCount));
        SystemProperties.set(SYSPROP_START_ELAPSED, String.valueOf(mRuntimeStartElapsedTime));
        SystemProperties.set(SYSPROP_START_UPTIME, String.valueOf(mRuntimeStartUptime));
        EventLog.writeEvent(EventLogTags.SYSTEM_SERVER_START, mStartCount, mRuntimeStartUptime, mRuntimeStartElapsedTime);
        //設置時區
        String timezoneProperty = SystemProperties.get("persist.sys.timezone");
        if (!isValidTimeZoneId(timezoneProperty)) {
            Slog.w(TAG, "persist.sys.timezone is not valid (" + timezoneProperty + "); 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();
            SystemProperties.set("persist.sys.locale", languageTag);
            SystemProperties.set("persist.sys.language", "");
            SystemProperties.set("persist.sys.country", "");
            SystemProperties.set("persist.sys.localevar", "");
        }
        // 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
        SQLiteCompatibilityWalFlags.init(null);
        // Here we go!
        Slog.i(TAG, "Entered the Android system server!");
        final long uptimeMillis = SystemClock.elapsedRealtime();
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, uptimeMillis);
        if (!mRuntimeRestart) {
            FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED, FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__SYSTEM_SERVER_INIT_START, uptimeMillis);
        }
        // In case the runtime switched since last boot (such as when
        // the old runtime was removed in an OTA), set the system
        // property so that it is in sync. We can't do this in
        // libnativehelper's JniInvocation::Init code where we already
        // had to fallback to a different runtime because it is
        // running as root and we need to be the system user to set
        // the property. http://b/11463182
        //設置虛擬機屬性
        SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());
        //清理內存
        VMRuntime.getRuntime().clearGrowthLimit();
        // 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.
        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.prepareMainLooper();
        SystemServiceRegistry.sEnableServiceNotFoundWtf = true;
        // Initialize native services.
        System.loadLibrary("android_servers");
        // Allow heap / perf profiling.
        initZygoteChildHeapProfiling();
        // Debug builds - spawn a thread to monitor for fd leaks.
        if (Build.IS_DEBUGGABLE) {
            spawnFdLeakCheckThread();
        }
        // Check whether we failed to shut down last time we tried.
        // This call may not return.
        performPendingShutdown();
        // Initialize the system context.
        createSystemContext();
        // Call per-process mainline module initialization.
        ActivityThread.initializeMainlineModules();
        // Sets the dumper service
        ServiceManager.addService("system_server_dumper", mDumper);
        mDumper.addDumpable(this);
        // Create the system service manager.
        mSystemServiceManager = new SystemServiceManager(mSystemContext);
        mSystemServiceManager.setStartInfo(mRuntimeRestart, mRuntimeStartElapsedTime, mRuntimeStartUptime);
        mDumper.addDumpable(mSystemServiceManager);
        LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
        // Prepare the thread pool for init tasks that can be parallelized
        SystemServerInitThreadPool tp = SystemServerInitThreadPool.start();
        mDumper.addDumpable(tp);
        // Load preinstalled system fonts for system server, so that WindowManagerService, etc
        // can start using Typeface. Note that fonts are required not only for text rendering,
        // but also for some text operations (e.g. TextUtils.makeSafeForPresentation()).
        if (Typeface.ENABLE_LAZY_TYPEFACE_INITIALIZATION) {
            Typeface.loadPreinstalledSystemFontMap();
        }
        // Attach JVMTI agent if this is a debuggable build and the system property is set.
        if (Build.IS_DEBUGGABLE) {
            // Property is of the form "library_path=parameters".
            String jvmtiAgent = SystemProperties.get("persist.sys.dalvik.jvmtiagent");
            if (!jvmtiAgent.isEmpty()) {
                int equalIndex = jvmtiAgent.indexOf('=');
                String libraryPath = jvmtiAgent.substring(0, equalIndex);
                String parameterList = jvmtiAgent.substring(equalIndex + 1, jvmtiAgent.length());
                // Attach the agent.
                try {
                    Debug.attachJvmtiAgent(libraryPath, parameterList, null);
                } catch(Exception e) {
                    Slog.e("System", "*************************************************");
                    Slog.e("System", "********** Failed to load jvmti plugin: " + jvmtiAgent);
                }
            }
        }
    } finally {
        t.traceEnd(); // InitBeforeStartServices
    }
    // Setup the default WTF handler
    RuntimeInit.setDefaultApplicationWtfHandler(SystemServer: :handleEarlySystemWtf);
    // Start services.
    try {
        t.traceBegin("StartServices");
        //引導服務[Watchdog][FileIntegrityService][Installer][AMS][PMS]...
        startBootstrapServices(t);
        //啓動核心服務[Battery][SystemConfig][LooperState][GpuService]...
        startCoreServices(t);
        //其它服務[Network][Vpn][WMS][IMS][TelephonyRegistry]...
        startOtherServices(t);
        //Android Q APEX格式文件
        startApexServices(t);
    } catch(Throwable ex) {
        Slog.e("System", "******************************************");
        Slog.e("System", "************ Failure starting system services", ex);
        throw ex;
    } finally {
        t.traceEnd(); // StartServices
    }
    //初始化虛擬機StrictMode
    StrictMode.initVmDefaults(null);
    //非運行時重啓或者首次啓動或更新
    if (!mRuntimeRestart && !isFirstBootOrUpgrade()) {
        final long uptimeMillis = SystemClock.elapsedRealtime();        FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED, FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__SYSTEM_SERVER_READY, uptimeMillis);
        final long maxUptimeMillis = 60 * 1000;
        if (uptimeMillis > maxUptimeMillis) {
            Slog.wtf(SYSTEM_SERVER_TIMING_TAG, "SystemServer init took too long. uptimeMillis=" + uptimeMillis);
        }
    }
    // Loop forever.
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}

以上run方法源碼原始英文註釋非常詳細,流程執行也很清晰,核心步驟如下

  • 調用SystemServerInitThreadPool初始化線程池
  • 創建SystemServiceManager服務管理對象
  • 調用startBootstrapServices啓動引導服務
  • 調用startCoreServices啓動核心服務
  • 調用startOtherServices啓動其它服務
  • 調用startApexServices啓動APEX文件服務

6. ActivityManagerService

ActivityManagerService主要管理系統中所有的應用進程和四大組件服務,
LifeCycle.getService()返回ActivityTaskManagerService對象(Lifecycle繼承於SystemService),mSystemServiceManager.startService通過反射查找class並最終startService,我們接着看ActivityManagerService的構造函數

public ActivityManagerService(Context systemContext,
                                ActivityTaskManagerService atm) {
    LockGuard.installLock(this, LockGuard.INDEX_ACTIVITY);
    // 初始化Injector對象
    mInjector = new Injector(systemContext);
    mContext = systemContext;
    mFactoryTest = FactoryTest.getMode();
    //獲取SystemServer.createSystemContext函數中初始化的ActivityThread
    mSystemThread = ActivityThread.currentActivityThread();
    mUiContext = mSystemThread.getSystemUiContext();
    //TAG線程名,默認TAG_AM即ActivityManager前台線程,獲取mHandler
    mHandlerThread = new ServiceThread(TAG, THREAD_PRIORITY_FOREGROUND, false/*allowIo*/);
    mHandlerThread.start();
    //創建MainHandler,與mHandlerThread關聯
    mHandler = new MainHandler(mHandlerThread.getLooper());
    //初始化UiHandler對象,繼承於Handler
    mUiHandler = mInjector.getUiHandler(this);
    //新建mProcStartHandlerThread線程並於創建handle關聯
    mProcStartHandlerThread = new ServiceThread(TAG + ":procStart", THREAD_PRIORITY_FOREGROUND, false
    /* allowIo */
    );
    mProcStartHandlerThread.start();
    mProcStartHandler = new ProcStartHandler(this, mProcStartHandlerThread.getLooper());
    //ActivityManager常量管理
    mConstants = new ActivityManagerConstants(mContext, this, mHandler);
    final ActiveUids activeUids = new ActiveUids(this, true
    /* postChangesToAtm */
    );
    mPlatformCompat = (PlatformCompat) ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE);
    mProcessList = mInjector.getProcessList(this);
    mProcessList.init(this, activeUids, mPlatformCompat);
    //profiler,低內存監控
    mAppProfiler = new AppProfiler(this, BackgroundThread.getHandler().getLooper(), new LowMemDetector(this));
    mPhantomProcessList = new PhantomProcessList(this);
    //OOM監控
    mOomAdjuster = new OomAdjuster(this, mProcessList, activeUids);
    //監聽BROADCAST_BG_CONSTANTS廣播相關
    // Broadcast policy parameters
    final BroadcastConstants foreConstants = new BroadcastConstants(Settings.Global.BROADCAST_FG_CONSTANTS);
    foreConstants.TIMEOUT = BROADCAST_FG_TIMEOUT;

    final BroadcastConstants backConstants = new BroadcastConstants(Settings.Global.BROADCAST_BG_CONSTANTS);
    backConstants.TIMEOUT = BROADCAST_BG_TIMEOUT;
    final BroadcastConstants offloadConstants = new BroadcastConstants(Settings.Global.BROADCAST_OFFLOAD_CONSTANTS);
    offloadConstants.TIMEOUT = BROADCAST_BG_TIMEOUT;
    // by default, no "slow" policy in this queue
    offloadConstants.SLOW_TIME = Integer.MAX_VALUE;

    mEnableOffloadQueue = SystemProperties.getBoolean("persist.device_config.activity_manager_native_boot.offload_queue_enabled", true);
    //初始化廣播隊列
    mFgBroadcastQueue = new BroadcastQueue(this, mHandler, "foreground", foreConstants, false);
    mBgBroadcastQueue = new BroadcastQueue(this, mHandler, "background", backConstants, true);
    mBgOffloadBroadcastQueue = new BroadcastQueue(this, mHandler, "offload_bg", offloadConstants, true);
    mFgOffloadBroadcastQueue = new BroadcastQueue(this, mHandler, "offload_fg", foreConstants, true);
    mBroadcastQueues[0] = mFgBroadcastQueue;
    mBroadcastQueues[1] = mBgBroadcastQueue;
    mBroadcastQueues[2] = mBgOffloadBroadcastQueue;
    mBroadcastQueues[3] = mFgOffloadBroadcastQueue;
    //初始化後台服務管理對象
    mServices = new ActiveServices(this);
    //ContentProvider helper
    mCpHelper = new ContentProviderHelper(this, true);
    //監控系統運行狀況
    mPackageWatchdog = PackageWatchdog.getInstance(mUiContext);
    //處理錯誤信息
    mAppErrors = new AppErrors(mUiContext, this, mPackageWatchdog);
    mUidObserverController = new UidObserverController(mUiHandler);
    //初始化/data/system目錄
    final File systemDir = SystemServiceManager.ensureSystemDir();
    //BatteryStatsService
    mBatteryStatsService = new BatteryStatsService(systemContext, systemDir, BackgroundThread.get().getHandler());
    mBatteryStatsService.getActiveStatistics().readLocked();
    mBatteryStatsService.scheduleWriteToDisk();
    mOnBattery = DEBUG_POWER ? true: mBatteryStatsService.getActiveStatistics().getIsOnBattery();
    mBatteryStatsService.getActiveStatistics().setCallback(this);
    mOomAdjProfiler.batteryPowerChanged(mOnBattery);
    //創建進程統計服務
    mProcessStats = new ProcessStatsService(this, new File(systemDir, "procstats"));
    //AppOpsService
    mAppOpsService = mInjector.getAppOpsService(new File(systemDir, "appops.xml"), mHandler);
    mUgmInternal = LocalServices.getService(UriGrantsManagerInternal.class);
    //UserController管理多用户進程
    mUserController = new UserController(this);
    //PendingIntent管理
    mPendingIntentController = new PendingIntentController(mHandlerThread.getLooper(), mUserController, mConstants);
    ...
    //初始化ActivityTaskManagerService配置
    mActivityTaskManager = atm;
    mActivityTaskManager.initialize(mIntentFirewall, mPendingIntentController, DisplayThread.get().getLooper());
    //獲取LocalService對象,繼承於ActivityTaskManagerInternal
    mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
    mHiddenApiBlacklist = new HiddenApiSettings(mHandler, mContext);
    mSdkSandboxSettings = new SdkSandboxSettings(mContext);
    //初始化監控
    Watchdog.getInstance().addMonitor(this);
    //監控線程是否死鎖
    Watchdog.getInstance().addThread(mHandler);
    // bind background threads to little cores
    // this is expected to fail inside of framework tests because apps can't touch cpusets directly
    // make sure we've already adjusted system_server's internal view of itself first
    updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_NONE);
    try {
        Process.setThreadGroupAndCpuset(BackgroundThread.get().getThreadId(), Process.THREAD_GROUP_SYSTEM);
        Process.setThreadGroupAndCpuset(mOomAdjuster.mCachedAppOptimizer.mCachedAppOptimizerThread.getThreadId(), Process.THREAD_GROUP_SYSTEM);
    } catch(Exception e) {
        Slog.w(TAG, "Setting background thread cpuset failed");
    }
    mInternal = new LocalService();
    mPendingStartActivityUids = new PendingStartActivityUids();
    mTraceErrorLogger = new TraceErrorLogger();
    mComponentAliasResolver = new ComponentAliasResolver(this);
}

結合AMS的構造函數,大致處理以下內容

  • 創建ServiceThread消息循環線程,並於MainHandler關聯
  • 創建一些服務以及/data/system系統目錄創建
  • 初始化Watchdog並監控系統、線程運行狀況
  • 初始化廣播隊列
  • 其它初始化內容

ActivityManagerService.start() 啓動方法,主要將服務註冊到ServiceManager和LocalServices中供後續調用

private void start() {
    //註冊服務到LocalService
    //LocalServices.addService(BatteryStatsInternal.class, new LocalService());
    //ServiceManager.addService(BatteryStats.SERVICE_NAME, asBinder());
    mBatteryStatsService.publish();
    //系統操作
    //ServiceManager.addService(Context.APP_OPS_SERVICE, asBinder());
    //LocalServices.addService(AppOpsManagerInternal.class, mAppOpsManagerInternal);
    mAppOpsService.publish();
    //應用進程信息
    //LocalServices.addService(ProcessStatsInternal.class, new LocalService());
    mProcessStats.publish();
    //添加本地系統服務接口
    //mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
    //mUgmInternal = LocalServices.getService(UriGrantsManagerInternal.class);
    LocalServices.addService(ActivityManagerInternal.class, mInternal);
    LocalManagerRegistry.addManager(ActivityManagerLocal.class, (ActivityManagerLocal) mInternal);
    //LocalServices註冊完成後,在ActivityTaskManagerService獲取該對象
    mActivityTaskManager.onActivityManagerInternalAdded();
    //LocalServices註冊完成後,在PendingIntentController獲取該對象
    mPendingIntentController.onActivityManagerInternalAdded();
    //AppProfiler獲取
    mAppProfiler.onActivityManagerInternalAdded();
    //初始化最近關鍵事件日誌
    CriticalEventLog.init();
}

6.1 startBootstrapServices

bootstrap源碼內容

private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
    //初始化Watchdog
    final Watchdog watchdog = Watchdog.getInstance();
    watchdog.start();
    //加入dumper集合
    mDumper.addDumpable(watchdog);
    //提交系統配置初始化任務到線程池
    final String TAG_SYSTEM_CONFIG = "ReadingSystemConfig";
    SystemServerInitThreadPool.submit(SystemConfig: :getInstance, TAG_SYSTEM_CONFIG);
    // Platform compat service is used by ActivityManagerService, PackageManagerService, and
    // possibly others in the future. b/135010838.
    //系統內部api變更
    PlatformCompat platformCompat = new PlatformCompat(mSystemContext);
    ServiceManager.addService(Context.PLATFORM_COMPAT_SERVICE, platformCompat);
    ServiceManager.addService(Context.PLATFORM_COMPAT_NATIVE_SERVICE, new PlatformCompatNative(platformCompat));
    AppCompatCallbacks.install(new long[0]);
    //啓動文件完整性操作服務
    mSystemServiceManager.startService(FileIntegrityService.class);
    // 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繼承於SystemSerivce,等待系統服務安裝完成再初始化其它服務
    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.
    //在ActivityManager啓動前註冊設備標識符(序列號)
    mSystemServiceManager.startService(DeviceIdentifiersPolicyService.class);
    // Uri Grants Manager.
    //管理Uri Permission
    mSystemServiceManager.startService(UriGrantsManagerService.Lifecycle.class);
    // Tracks rail data to be used for power statistics.
    //啓動系統服務電量使用統計服務,WI-FI、GPS、顯示器,提供數據監聽回調
    mSystemServiceManager.startService(PowerStatsService.class);
    //native方法,啓動跨進程通信服務
    //startStatsHidlService();
    //startStatsAidlService();
    startIStatsService();
    // Start MemtrackProxyService before ActivityManager, so that early calls
    // to Memtrack::getMemory() don't fail.
    //內存監控代理服務
    startMemtrackProxyService();
    // Activity manager runs the show.
    // TODO: Might need to move after migration to WM.
    //獲取ActivityManager
    ActivityTaskManagerService atm = mSystemServiceManager.startService(ActivityTaskManagerService.Lifecycle.class).getService();
    mActivityManagerService = ActivityManagerService.Lifecycle.startService(mSystemServiceManager, atm);
    mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
    mActivityManagerService.setInstaller(installer);
    mWindowManagerGlobalLock = atm.getGlobalLock();

    // Data loader manager service needs to be started before package manager
    //SystemService數據加載管理器
    mDataLoaderManagerService = mSystemServiceManager.startService(DataLoaderManagerService.class);

    // Incremental service needs to be started before package manager
    t.traceBegin("StartIncrementalService");
    mIncrementalServiceHandle = startIncrementalService();
    t.traceEnd();

    // Power manager needs to be started early because other services need it.
    // Native daemons may be watching for it to be registered so it must be ready
    // to handle incoming binder calls immediately (including being able to verify
    // the permissions for those calls).
    //啓動電源管理服務
    mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
    //啓動hal監聽事件服務
    mSystemServiceManager.startService(ThermalManagerService.class);
    mSystemServiceManager.startService(HintManagerService.class);
    t.traceEnd();

    // Now that the power manager has been started, let the activity manager
    // initialize power management features.
    //前面已啓動電源管理服務,現在通過ActivityManager初始化電源管理
    mActivityManagerService.initPowerManagement();
    // Bring up recovery system in case a rescue party needs a reboot
    //恢復模式
    mSystemServiceManager.startService(RecoverySystemService.Lifecycle.class);
    // Now that we have the bare essentials of the OS up and running, take
    // note that we just booted, which might send out a rescue party if
    // we're stuck in a runtime restart loop.
    //已啓動完基本配置服務,註冊系統情況監聽
    RescueParty.registerHealthObserver(mSystemContext);
    PackageWatchdog.getInstance(mSystemContext).noteBoot();

    // Manages LEDs and display backlight so we need it to bring up the display.
    //啓動顯示器服務
    mSystemServiceManager.startService(LightsService.class);
    // Package manager isn't started yet; need to use SysProp not hardware feature
    if (SystemProperties.getBoolean("config.enable_display_offload", false)) {
        mSystemServiceManager.startService(WEAR_DISPLAYOFFLOAD_SERVICE_CLASS);
    }
    // Package manager isn't started yet; need to use SysProp not hardware feature
    if (SystemProperties.getBoolean("config.enable_sidekick_graphics", false)) {
        mSystemServiceManager.startService(WEAR_SIDEKICK_SERVICE_CLASS);
    }
    // Display manager is needed to provide display metrics before package manager
    // starts up.
    //啓動顯示窗口服務
    mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
    // We need the default display before we can initialize the package manager.
    mSystemServiceManager.startBootPhase(t, SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
    // Only run "core" apps if we're encrypting the device.
    String cryptState = VoldProperties.decrypt().orElse("");
    if (ENCRYPTING_STATE.equals(cryptState)) {
        Slog.w(TAG, "Detected encryption in progress - only parsing core apps");
        mOnlyCore = true;
    } else if (ENCRYPTED_STATE.equals(cryptState)) {
        Slog.w(TAG, "Device encrypted - only parsing core apps");
        mOnlyCore = true;
    }
    // Start the package manager.
    if (!mRuntimeRestart) {
        FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED, FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__PACKAGE_MANAGER_INIT_START, SystemClock.elapsedRealtime());
    }
    //啓動域名驗證服務
    DomainVerificationService domainVerificationService = new DomainVerificationService(mSystemContext, SystemConfig.getInstance(), platformCompat);
    mSystemServiceManager.startService(domainVerificationService);
    //包管理器
    IPackageManager iPackageManager;
    t.traceBegin("StartPackageManagerService");
    try {
        Watchdog.getInstance().pauseWatchingCurrentThread("packagemanagermain");
        Pair < PackageManagerService,
        IPackageManager > pmsPair = PackageManagerService.main(mSystemContext, installer, domainVerificationService, mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
        mPackageManagerService = pmsPair.first;
        iPackageManager = pmsPair.second;
    } finally {
        Watchdog.getInstance().resumeWatchingCurrentThread("packagemanagermain");
    }
    // Now that the package manager has started, register the dex load reporter to capture any
    // dex files loaded by system server.
    // These dex files will be optimized by the BackgroundDexOptService.
    SystemServerDexLoadReporter.configureSystemServerDexReporter(iPackageManager);
    mFirstBoot = mPackageManagerService.isFirstBoot();
    mPackageManager = mSystemContext.getPackageManager(); 
    if (!mRuntimeRestart && !isFirstBootOrUpgrade()) {
        FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED, FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__PACKAGE_MANAGER_INIT_READY, SystemClock.elapsedRealtime());
    }
    // Manages A/B OTA dexopting. This is a bootstrap service as we need it to rename
    // A/B artifacts after boot, before anything else might touch/need them.
    // Note: this isn't needed during decryption (we don't have /data anyways).
    if (!mOnlyCore) {
        boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt", false);
        if (!disableOtaDexopt) {
            t.traceBegin("StartOtaDexOptService");
            try {
                Watchdog.getInstance().pauseWatchingCurrentThread("moveab");
                OtaDexoptService.main(mSystemContext, mPackageManagerService);
            } catch(Throwable e) {
                reportWtf("starting OtaDexOptService", e);
            } finally {
                Watchdog.getInstance().resumeWatchingCurrentThread("moveab");
                t.traceEnd();
            }
        }
    }
    //啓動用户管理服務
    mSystemServiceManager.startService(UserManagerService.LifeCycle.class);
    //初始化系統屬性資源
    // Initialize attribute cache used to cache resources from packages.
    AttributeCache.init(mSystemContext);
    // Set up the Application instance for the system process and get started.
    //1.添加meminfo\dbinfo\permission\processinfo\cacheinfo服務
    //2.啓動線程安裝ApplicationInfo
    //3.同步監控並鎖定ApplicationInfo 進程,緩存監控,OOM監控
    //4.監控應用程序操作
    mActivityManagerService.setSystemProcess();
    // The package receiver depends on the activity service in order to get registered.
    platformCompat.registerPackageReceiver(mSystemContext);
    // Complete the watchdog setup with an ActivityManager instance and listen for reboots
    // Do this only after the ActivityManagerService is properly started as a system process
    //初始化watchdog
    watchdog.init(mSystemContext, mActivityManagerService);
    // DisplayManagerService needs to setup android.display scheduling related policies
    // since setSystemProcess() would have overridden policies due to setProcessGroup
    //設置DMS調度策略
    mDisplayManagerService.setupSchedulerPolicies();
    // Manages Overlay packages
    //啓動Overlay資源管理服務
    mSystemServiceManager.startService(new OverlayManagerService(mSystemContext));
    // Manages Resources packages
    ResourcesManagerService resourcesService = new ResourcesManagerService(mSystemContext);
    resourcesService.setActivityManagerService(mActivityManagerService);
    mSystemServiceManager.startService(resourcesService);
    //傳感器
    mSystemServiceManager.startService(new SensorPrivacyService(mSystemContext));
    if (SystemProperties.getInt("persist.sys.displayinset.top", 0) > 0) {
        // DisplayManager needs the overlay immediately.
        mActivityManagerService.updateSystemUiContext();
        LocalServices.getService(DisplayManagerInternal.class).onOverlayChanged();
    }
    // The sensor service needs access to package manager service, app op
    // service, and permissions service, therefore we start it after them.
    t.traceBegin("StartSensorService");
    mSystemServiceManager.startService(SensorService.class);
    t.traceEnd();
    t.traceEnd(); // startBootstrapServices completed
}

6.2 startCoreServices

啓動的核心服務BatteryLooperStateUsageStatsService等,具體細節可看源碼

6.3 startOtherServices

啓動其它服務為運行應用準備,該方法源碼特別長,大致啓動服務NetworkWMS[TelephonyRegistry]如有需要可進入源碼閲讀,我們繼續看主要節點

mActivityManagerService.systemReady(() - >{
    //系統service已經準備完成
    mSystemServiceManager.startBootPhase(t, SystemService.PHASE_ACTIVITY_MANAGER_READY);
    //監控native crashs
    try {
        mActivityManagerService.startObservingNativeCrashes();
    } catch(Throwable e) {
        reportWtf("observing native crashes", e);
    }
    ...
    // No dependency on Webview preparation in system server. But this should
    // be completed before allowing 3rd party
    //在webView準備好後,第三方apk可以調用
    final String WEBVIEW_PREPARATION = "WebViewFactoryPreparation";
    Future < ?>webviewPrep = null;
    if (!mOnlyCore && mWebViewUpdateService != null) {
        webviewPrep = SystemServerInitThreadPool.submit(() - >{
            Slog.i(TAG, WEBVIEW_PREPARATION);
            TimingsTraceAndSlog traceLog = TimingsTraceAndSlog.newAsyncLog();
            traceLog.traceBegin(WEBVIEW_PREPARATION);
            ConcurrentUtils.waitForFutureNoInterrupt(mZygotePreload, "Zygote preload");
            mZygotePreload = null;
            mWebViewUpdateService.prepareWebViewInSystemServer();
            traceLog.traceEnd();
        },WEBVIEW_PREPARATION);
    }
    //一系列系統組件準備完成
    ...
    networkManagementF.systemReady();
    networkPolicyF.networkScoreAndNetworkManagementServiceReady();
    connectivityF.systemReady();
    vpnManagerF.systemReady();
    vcnManagementF.systemReady();
    networkPolicyF.systemReady(networkPolicyInitReadySignal);
    ...
    //等待所有app數據預加載
    mPackageManagerService.waitForAppDataPrepared();
    // It is now okay to let the various system services start their
    // third party code...
    // confirm webview completion before starting 3rd party
    //等待WebView準備完成
    if (webviewPrep != null) {
        ConcurrentUtils.waitForFutureNoInterrupt(webviewPrep, WEBVIEW_PREPARATION);
    }
    //三方app可以啓動
    mSystemServiceManager.startBootPhase(t, SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
    //啓動在單獨模塊中運行的網絡堆棧通信服務
    try {
        // Note : the network stack is creating on-demand objects that need to send
        // broadcasts, which means it currently depends on being started after
        // ActivityManagerService.mSystemReady and ActivityManagerService.mProcessesReady
        // are set to true. Be careful if moving this to a different place in the
        // startup sequence.
        NetworkStackClient.getInstance().start();
    } catch(Throwable e) {
        reportWtf("starting Network Stack", e);
    }
    //一系列組件已經準備好並運行
    ...
    countryDetectorF.systemRunning();
    networkTimeUpdaterF.systemRunning();
    inputManagerF.systemRunning();
    telephonyRegistryF.systemRunning();
    mediaRouterF.systemRunning();
    ...
    incident.systemRunning();
    ...
},t);
//啓動SystemUI,快接近Launcher啓動
try {
    startSystemUi(context, windowManagerF);
} catch(Throwable e) {
    reportWtf("starting System UI", e);
}
//startSystemUi
private static void startSystemUi(Context context, WindowManagerService windowManager) {
    //獲取本地包管理服務
    PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
    //設置啓動intent
    Intent intent = new Intent();
    intent.setComponent(pm.getSystemUiServiceComponent());
    intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
    //對陣系統用户啓動服務
    context.startServiceAsUser(intent, UserHandle.SYSTEM);
    //systemUI啓動後調用
    windowManager.onSystemUiStarted();
}
//onSystemUiStarted實際調用最終指向PhoneWindowManager.java
private void bindKeyguard() {
    synchronized(mLock) {
        if (mKeyguardBound) {
            return;
        }
        mKeyguardBound = true;
    }
    //綁定keyguardService服務
    mKeyguardDelegate.bindService(mContext);
}

7.AMS.systemReady方法

//通過以上所有ready\running工作,現在正式進入AMS.systemReady方法
public void systemReady(final Runnable goingCallback, @NonNull TimingsTraceAndSlog t) {
    //ActivityManager準備完成
    mSystemServiceManager.preSystemReady();
    //鎖定並執行上述所有ready\running服務
    synchronized(this) {
        if (mSystemReady) {
            // If we're done calling all the receivers, run the next "boot phase" passed in
            // by the SystemServer
            if (goingCallback != null) {
                goingCallback.run();
            }
            return;
        }
        //所有工作準備就緒
        mLocalDeviceIdleController = LocalServices.getService(DeviceIdleInternal.class);
        mActivityTaskManager.onSystemReady();
        // Make sure we have the current profile info, since it is needed for security checks.
        mUserController.onSystemReady();
        mAppOpsService.systemReady();
        mProcessList.onSystemReady();
        mAppRestrictionController.onSystemReady();
        //設置準備完成標記
        mSystemReady = true;
    }

    try {
        sTheRealBuildSerial = IDeviceIdentifiersPolicyService.Stub.asInterface(ServiceManager.getService(Context.DEVICE_IDENTIFIERS_SERVICE)).getSerial();
    } catch(RemoteException e) {}
    //清理進程
    ArrayList < ProcessRecord > procsToKill = null;
    synchronized(mPidsSelfLocked) {
        for (int i = mPidsSelfLocked.size() - 1; i >= 0; i--) {
            ProcessRecord proc = mPidsSelfLocked.valueAt(i);
            if (!isAllowedWhileBooting(proc.info)) {
                if (procsToKill == null) {
                    procsToKill = new ArrayList < ProcessRecord > ();
                }
                procsToKill.add(proc);
            }
        }
    }
    synchronized(this) {
        if (procsToKill != null) {
            for (int i = procsToKill.size() - 1; i >= 0; i--) {
                ProcessRecord proc = procsToKill.get(i);
                Slog.i(TAG, "Removing system update proc: " + proc);
                mProcessList.removeProcessLocked(proc, true, false, ApplicationExitInfo.REASON_OTHER, ApplicationExitInfo.SUBREASON_SYSTEM_UPDATE_DONE, "system update done");
            }
        }

        // Now that we have cleaned up any update processes, we
        // are ready to start launching real processes and know that
        // we won't trample on them any more.
        mProcessesReady = true;
    }
    ...
    ...
    //如果systemReady = true 未標記完成,執行此處ready\running服務
    if (goingCallback != null) goingCallback.run();
    ...
    ...
    //給BatteryStatsService發送狀態
    mBatteryStatsService.onSystemReady();
    mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_USER_RUNNING_START, Integer.toString(currentUserId), currentUserId);
    mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_START, Integer.toString(currentUserId), currentUserId);
    ...
    ...
    synchronized(this) {
        // Only start up encryption-aware persistent apps; once user is
        // unlocked we'll come back around and start unaware apps
        t.traceBegin("startPersistentApps");
        //啓動startPersistentApps
        startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);
        ...
        boolean isBootingSystemUser = currentUserId == UserHandle.USER_SYSTEM;
        // Some systems - like automotive - will explicitly unlock system user then switch
        // to a secondary user.
        // TODO(b/242195409): this workaround shouldn't be necessary once we move
        // the headless-user start logic to UserManager-land.
        if (isBootingSystemUser && !UserManager.isHeadlessSystemUserMode()) {
            //啓動Launcher進程,回調給RootWindowContainer.startHomeOnAllDisplays,
            mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady");
        }
        ...
        t.traceBegin("resumeTopActivities");
        mAtmInternal.resumeTopActivities(false
        ...
    }
}
//startHomeOnAllDisplays最終調用 - RootWindowContainer.java
public boolean startHomeOnTaskDisplayArea(int userId, String reason, TaskDisplayArea taskDisplayArea, boolean allowInstrumenting, boolean fromHomeKey) {
    ...
    ...
    //獲取homeIntent
    Intent homeIntent = null;
    //查詢ActivityInfo
    ActivityInfo aInfo = null;
    if (taskDisplayArea == getDefaultTaskDisplayArea()) {
        //通過ActivityTaskManagerService獲取intent
        homeIntent = mService.getHomeIntent();
        //通過PackageManagerService解析intent
        aInfo = resolveHomeActivity(userId, homeIntent);
    } else if (shouldPlaceSecondaryHomeOnDisplayArea(taskDisplayArea)) {
        Pair < ActivityInfo,
        Intent > info = resolveSecondaryHomeActivity(userId, taskDisplayArea);
        aInfo = info.first;
        homeIntent = info.second;
    }
    ...
    ...
    // Updates the home component of the intent.
    //更新設置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);
        if (mWindowManager.getRecentsAnimationController() != null) {
            mWindowManager.getRecentsAnimationController().cancelAnimationForHomeStart();
        }
    }
    homeIntent.putExtra(WindowManagerPolicy.EXTRA_START_REASON, reason);
    // 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) + ":" + taskDisplayArea.getDisplayId();
    //通過獲取到的intent、aInfo調用startHomeActivity啓動launcher
    mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason, taskDisplayArea);
    return true;
}
//startHomeActivity方法 - ActivityStartController.java
void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason, TaskDisplayArea taskDisplayArea) {
    //ActivityOptions一系列參數
    final ActivityOptions options = ActivityOptions.makeBasic();
    options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
    if (!ActivityRecord.isResolverActivity(aInfo.name)) {
        options.setLaunchActivityType(ACTIVITY_TYPE_HOME);
    }
    final int displayId = taskDisplayArea.getDisplayId();
    options.setLaunchDisplayId(displayId);
    options.setLaunchTaskDisplayArea(taskDisplayArea.mRemoteToken.toWindowContainerToken());
    //執行啓動executeRequest - execute()在ActivityStarter.java中
    mLastHomeActivityStartResult = obtainStarter(intent, "startHomeActivity: " + reason).setOutActivity(tmpOutRecord).setCallingUid(0).setActivityInfo(aInfo).setActivityOptions(options.toBundle()).execute();
    ...
}
  1. execute()方法處理Activity啓動請求,進入到
  2. executeRequest(mRequest);執行執行一系列權限檢查,進入到
  3. startActivityUnchecked()校驗初步權限檢查是否完成,進入到
  4. startActivityInner()啓動 Activity,並確定是否將activity添加到棧頂,進入到
  5. startActivityLocked()判斷當前activity是否可見以及是否需要為其新建Task,並將ActivityRecord加入到Task棧頂中,進入到
  6. resumeFocusedTasksTopActivities() - RootWindowContainer.java ,主要判斷targetRootTask是否處於棧頂,同時判斷task是否處於暫停狀態,進入到
  7. resumeTopActivityUncheckedLocked() - Task.java,遞歸調用該方法並查找棧頂可顯示activity以及狀態是否暫停,進入到
  8. resumeTopActivityInnerLocked() - Task.java,該方法主要處理ActivityRecord、設置resume狀態、準備啓動activity,進入到
  9. resumeTopActivity() - TaskFragment.java,查找棧頂activity是否處於running,檢查所有暫停操作是否完成,進入到
  10. startSpecificActivity() - ActivityTaskSupervisor.java,如果activity已運行則直接啓動,未運行則啓動目標Activity,開啓啓動新進程,進入到
  11. startProcessAsync() - ActivityTaskManagerService.java,通過handle發送消息給AMS啓動進程,ATMS不持有該鎖,回到AMS中,進入到
  12. startProcessLocked() - ActivityManagerService.java,繼續調用
  13. ProcessList.startProcessLocked() - ProcessList.java,最終調用startProcess(),定義

    final String entryPoint = "android.app.ActivityThread";
    final Process.ProcessStartResult startResult = startProcess(hostingRecord, entryPoint, app, uid, gids, runtimeFlags, zygotePolicyFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith, startUptime);

    以上調用鏈最終進入startProcess() - ProcessList.java,根據參數類型啓動進程

    final Process.ProcessStartResult startResult;
    boolean regularZygote = false;
    if (hostingRecord.usesWebviewZygote()) {
     startResult = startWebView(entryPoint, app.processName, uid, uid, gids, runtimeFlags, mountExternal, app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.dataDir, null, app.info.packageName, app.getDisabledCompatChanges(), new String[] {
         PROC_START_SEQ_IDENT + app.getStartSeq()
     });
    } else if (hostingRecord.usesAppZygote()) {
     final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);
     // We can't isolate app data and storage data as parent zygote already did that.
     startResult = appZygote.getProcess().start(entryPoint, app.processName, uid, uid, gids, runtimeFlags, mountExternal, app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.dataDir, null, app.info.packageName,
     /*zygotePolicyFlags=*/
     ZYGOTE_POLICY_FLAG_EMPTY, isTopApp, app.getDisabledCompatChanges(), pkgDataInfoMap, allowlistedAppDataInfoMap, false, false, new String[] {
         PROC_START_SEQ_IDENT + app.getStartSeq()
     });
    } else {
     regularZygote = true;
     startResult = Process.start(entryPoint, app.processName, uid, uid, gids, runtimeFlags, mountExternal, app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.dataDir, invokeWith, app.info.packageName, zygotePolicyFlags, isTopApp, app.getDisabledCompatChanges(), pkgDataInfoMap, allowlistedAppDataInfoMap, bindMountAppsData, bindMountAppStorageDirs, new String[] {
         PROC_START_SEQ_IDENT + app.getStartSeq()
     });
    }

    regularZygote表示常規的zygote32/zygote64,此處最終調用Process.start()創建進程,通過zygoteWriter發送給zygote進程,通知zygote開始fork進程,在前文ZygoteServer中
    【5. ZygoteInit.java類 - 8小節】,此處會循環接收來自AMS發送的消息,且entryPoint攜帶標記 "android.app.ActivityThread",此時子進程入口即為:ActivityThread的main(),
    基於此launcher進程已經啓動,ActivityThread.main()最後調用Looper.loop()進入循環等待,子進程啓動完成後AMS接着完成activity啓動操作

8.啓動Activity

經過上一節繁雜的的調用鏈,最終來到應用啓動入口

public static void main(String[] args) {
    //安裝選擇性系統調用攔截
    AndroidOs.install();
    //關閉CloseGuard
    CloseGuard.setEnabled(false);
    //初始化user environment
    Environment.initForCurrentUser();
    ...
    // Call per-process mainline module initialization.
    initializeMainlineModules();
    //設置進程args
    Process.setArgV0("<pre-initialized>");
    Looper.prepareMainLooper();
    // Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.
    // It will be in the format "seq=114"
    long startSeq = 0;
    if (args != null) {
        for (int i = args.length - 1; i >= 0; --i) {
            if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
                startSeq = Long.parseLong(args[i].substring(PROC_START_SEQ_IDENT.length()));
            }
        }
    }
    //初始化ActivityThread
    ActivityThread thread = new ActivityThread();
    thread.attach(false, startSeq);
    //獲取MainThreadHandler
    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }
    if (false) {
        Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread"));
    }
    //進入循環等待
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}
//繼續看下thread.attach()
private void attach(boolean system, long startSeq) {
    sCurrentActivityThread = this;
    mConfigurationController = new ConfigurationController(this);
    mSystemThread = system;
    if (!system) {
        android.ddm.DdmHandleAppName.setAppName("<pre-initialized>", UserHandle.myUserId());
        //RuntimeInit設置launcher binder服務:ApplicationThread
        RuntimeInit.setApplicationObject(mAppThread.asBinder());
        //獲取ActivityManagerService,由IActivityManager代理
        final IActivityManager mgr = ActivityManager.getService();
        try {
            //通過IApplicationThread跨進程通知launcher進程開始綁定
            mgr.attachApplication(mAppThread, startSeq);
        } catch(RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
        ...
    } else {
        ...
    }
    ...
}
@Override
public final void attachApplication(IApplicationThread thread, long startSeq) {
    synchronized (this) {
        //通過binder獲取進程id
        int callingPid = Binder.getCallingPid();
        //獲取user id
        final int callingUid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        //啓動正在等待的activity
        attachApplicationLocked(thread, callingPid, callingUid, startSeq);
        Binder.restoreCallingIdentity(origId);
    }
}

再往下就是創建Application對象,回調attachBaseContext(),初始化ContentProvider,回調onCreate(),繼續回調Application onCreate(),
此後就是Activity創建,調用attach(),執行onCreate方法,回調Activity各個生命週期方法,至此Launcher整體啓動完成,AMS啓動activity涉及多次跨進程通信
,與zygote通信判斷進程是否存在,不存在則fork新進程,並回調AMS執行其初始化方法,最後執行ActivityThread.main(),整體調用鏈非常繁雜,但各個模塊各司其職,
我們在應用層進行組件工程基礎模型分割時也可參考其內部的架構方式

9.文檔説明

由於源碼流程較長,整體調用鏈非常繁雜,可能存在錯漏的地方,歡迎在閲讀時提出問題和不足

參考文檔:

Android Code Search

/ - OpenGrok cross reference for / (aospxref.com)

torvalds/linux: Linux kernel source tree (github.com)

首頁 - 內核技術中文網 - 構建全國最權威的內核技術交流分享論壇 (0voice.com)

ActivityManagerService啓動過程 - Gityuan博客 | 袁輝輝的技術博客

init進程 – personal blog (liujunyang.site)

user avatar king_wenzhinan 头像 kanjianliao 头像 journey_64224c9377fd5 头像 u_13529088 头像 xuxueli 头像 u_16769727 头像 u_15878077 头像 werbenhu 头像 chuanghongdengdeqingwa_eoxet2 头像 jkdataapi 头像 manshenjiroudexiangjiao_bogavh 头像 lenve 头像
点赞 26 用户, 点赞了这篇动态!
点赞

Add a new 评论

Some HTML is okay.