Android启动过程-万字长文(Android14)

计算机启动过程Linux内核Kernel启动过程介绍了计算机启动和内核加载,本篇文章主要介绍Android系统是如何启动的。

一、Android启动流程

Android系统的启动流程与Linux接近:
sequenceDiagram participant Bootloader as 引导加载程序 participant Kernel as 内核 participant Init as init 进程 participant Zygote as Zygote 进程 participant SystemServices as 系统服务 participant Launcher as 应用程序(桌面) Bootloader->>Kernel: 加载内核 Kernel->>Kernel: 初始化 Kernel->>Init: 启动 init 进程 Init->>Init: 读取系统配置文件 Init->>Zygote: 启动 Zygote 进程 Zygote->>Zygote: 预加载常用的 Java 类和资源 Zygote->>SystemServices: 启动系统服务 SystemServices->>Launcher: 启动桌面程序

  • 1.引导加载程序(Bootloader)启动: 当设备上电或者重启时,首先会由引导加载程序负责启动。引导加载程序通常存储在设备的固件中,它的主要任务是初始化硬件,并加载并启动操作系统内核。引导加载程序会首先运行自身的初始化代码,然后加载操作系统内核到内存中。
  • 2.内核加载: 引导加载程序会根据预定义的配置从设备存储中加载操作系统内核。在Android设备中,通常使用的是Linux内核。引导加载程序将内核加载到内存中的指定位置。
  • 3.内核初始化: 一旦内核加载到内存中,引导加载程序会将控制权转交给内核。内核开始执行初始化过程,包括对硬件进行初始化、建立虚拟文件系统、创建进程和线程等。
  • 4.启动 init 进程: 内核初始化完成后,会启动名为init的用户空间进程。init进程是Android系统的第一个用户空间进程,它负责系统的进一步初始化和启动。init进程会读取系统配置文件(例如 init.rc),并根据其中的指令启动系统服务和应用程序。
  • 5.启动 Zygote 进程: 在init进程启动后,会启动名为Zygote的进程。Zygote进程是Android应用程序的孵化器,它会预加载常用的Java类和资源,以加速应用程序的启动。
  • 6.启动系统服务: 在Zygote进程启动后,还会启动一系列系统服务,例如SurfaceFlinger、ActivityManager、PackageManager等。这些系统服务负责管理系统的各个方面,包括显示、应用程序生命周期、包管理等。
  • 7.启动桌面程序: 一旦系统服务启动完成,Android系统就处于可用状态。就会启动桌面程序,用户可以开始启动应用程序并使用设备进行各种操作了。

计算机启动过程Linux内核Kernel启动过程已经介绍了计算机启动和内核加载,所以本篇文章从Zygote进程开始介绍。

二、Zygote进程(孵化器进程)

1.Zygote简介

  • Zygote进程是一个用户进程,由init进程(1号进程)fork而来。
  • Zygote进程的主要任务是加载系统的核心类库(如Java核心库和Android核心库)和安卓系统服务(SystemService),然后进入一个循环,等待请求来创建新的 Android 应用程序进程。
  • Zygote进程通过fork的方式创建新的应用程序进程。

2.Zygote进程的创建

Zygote进程在系统启动时由init进程创建。init进程是Linux系统中的第一个用户空间进程,它通过解析init.rc文件来启动各种服务和进程,包括Zygote。具体流程如下:

2.1 启动init进程:

  • 系统启动后,内核会加载并运行init进程
  • init进程读取并解析init.rc配置文件。

init进程的启动可参考Linux内核Kernel启动过程

2.2 init.rc脚本:

init.rc文件中包含启动Zygote的指令脚本的主要代码:

c 复制代码
// 创建zygote服务
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
// 创建zygote socket,与系统和应用程序做通信
socket zygote stream 660 root system
// 定义了zygote服务重启时的一些操作
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server:

  • service zygote: 定义一个名为zygote的服务
  • /system/bin/app_process :这是启动Zygote进程的可执行文件,64位系统为app_process64
  • -Xzygote:标志表明这是一个Zygote进程启动的特殊模式。
  • /system/bin:指定进程的工作目录。
  • --zygote:告诉app_process以Zygote模式启动。
  • --start-system-server:Zygote启动时还要启动System Server进程,这是Android系统中管理关键系统服务的核心进程。

class main:

  • 将Zygote服务归类为main类别。
  • Android系统在启动过程中会启动所有"main"类别的服务。

socket zygote stream 660 root system :

创建了一个名为zygote的UNIX域Socket套接字,用于其他进程与Zygote进程通信。

onrestart write /sys/android_power/request_state wake

当zygote服务重启时,系统应该将"/sys/android_power/request_state"文件的内容设置为"wake",以唤醒设备。

onrestart write /sys/power/state on

当zygote服务重启时,系统应该将"/sys/power/state"文件的内容设置为 "on",以打开电源。

onrestart restart media

当zygote服务重启时,系统应该重启媒体服务(如音频、视频等),以恢复媒体功能。

onrestart restart netd

当zygote服务重启时,系统应该重启网络守护进程(netd),以恢复网络功能。

2.3 app_process文件

/system/bin/app_process是Android中的一个关键可执行文件,负责启动Zygote进程和应用进程。

Android14的app_process源码地址

2.3.1 main方法

app_process主入口点是main方法,它是整个进程启动流程的起点。以下是其主要代码和解释:

以下是关键代码说明:

c 复制代码
int main(int argc, char* const argv[])
{
    // 创建并初始化AppRuntime对象runtime
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    
    // 初始化参数zygote,startSystemServer,application,niceName,className
    // 代码见源码,此处略
    
    // 解析命令行参数
    // 代码见源码,此处略

    // 构建传递给 Java 初始化类的参数列表
    // 代码见源码,此处略
    
    if (zygote) {
        // 调用AppRuntime的start方法,开始加载ZygoteInit类
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (!className.isEmpty()) {
        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.");
    }
}

2.3.2 AppRuntime类(AndroidRuntime)

AppRuntime 继承自AndroidRuntime(ART),是Android中的一个关键类,负责管理和启动 Android 应用程序或系统服务的 Java 虚拟机 (JVM)。

Android14的AndroidRuntime源码地址

2.3.2.1 AndroidRuntime类的start方法

app_process的main方法调用了AppRuntime的start方法,也就是AppRuntime的父类AndroidRuntime的start方法

c 复制代码
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    // 初始化Java Native Interface (JNI)。JNI是Java和C/C++之间的接口,它允许Java代码和C/C++代码相互调用
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    
    JNIEnv* env;  // JNIEnv环境指针
    // 初始化虚拟机
    if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
        return;
    }

    // 注册JNI方法
    if (startReg(env) < 0) {
        return;
    }

    /*
     * 以下代码执行后,当前线程(即运行 AndroidRuntime::start 方法的线程)将成为Java虚拟机(JVM)的主线程,并且在调用env->CallStaticVoidMethod启动指定的Java类的 main 方法后,这个方法不会返回,直到 JVM 退出为止。(官方文档说明)
     */
    
    // 将"com.android.internal.os.ZygoteInit"转换为"com/android/internal/os/ZygoteInit"
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        // 没有找到ZygoteInit.main()方法
    } else {
        // 通过JNI调用ZygoteInit.main()方法
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
    }
}
  • 创建虚拟机
  • 注册JNI方法
  • 通过JNI调用ZygoteInit.main()

3.Zygote进程

AndroidRuntimestart方法,通过JNI调用ZygoteInit.main(),系统第一次进入Java层(ZygoteInit是系统运行的第一个Java类),当前线程也正式成为Java虚拟机(JVM)的主线程。

Android14的ZygoteInit源码地址

3.1 ZygoteInit.main()

通过main方法完成资源预加载、启动系统服务等功能,为Launcher桌面程序做准备。

java 复制代码
public static void main(String[] argv) {
    // 创建ZygoteServer
    ZygoteServer zygoteServer = null;
    ...
    // 预加载资源
    preload(bootTimingsTraceLog);
    ...
    // 初始化ZygoteServer
    zygoteServer = new ZygoteServer(isPrimaryZygote);
    ...
    // 通过fork的形式初始化SystemServer
    Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
    if (r != null) {
        r.run();
        return;
    }
    ...
    // 启动Loop,监听消息
    caller = zygoteServer.runSelectLoop(abiList);
    ...
}

3.2 ZygoteInit.preload()预加载

通过preload方法预加载系统常用的类、资源和库,能够显著减少应用启动时的延迟,并通过共享这些预加载的内容来降低内存使用,提高系统性能。

java 复制代码
static void preload(TimingsTraceLog bootTimingsTraceLog) {
    preloadClasses(); //加载常用的Java类
    preloadResources(); //加载常用的资源(如布局、图片等)
    preloadOpenGL(); //加载OpenGL库
    preloadSharedLibraries(); //加载常用的本地共享库
    preloadTextResources(); //加载常用的文本资源
    ...
}

3.2.1 常用类

  • Android框架中的基础类,如Activity、Service、BroadcastReceiver等。
  • 常用的UI组件类,如TextView、Button、ImageView等。

3.2.2 常用资源

常用布局文件(layout)。

常用图片资源(drawable)。

常用字符串(strings.xml)。

3.2.3 常用库

标准C库(libc.so)。

图形处理库(libskia.so)。

OpenGL ES库(libGLESv2.so)。

3.3 启动System Server

System Server是Android系统中的关键进程,负责启动和管理核心系统服务。

启动过程的核心代码:

java 复制代码
public static void main(String argv[]) {
    // 初始化ZygoteServer
    ZygoteServer zygoteServer = new ZygoteServer();
    // 启动System Server
    if (startSystemServer) {
        startSystemServer(abiList, socketName, zygoteServer);
    }
    // 进入Zygote的主循环,等待新进程的启动请求
    zygoteServer.runSelectLoop();
}

private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer) {
    /* 调用native方法fork系统服务器 */
    int pid = Zygote.forkSystemServer(...);
    if (pid == 0) {
        // 在子进程中执行System Server的main方法
        handleSystemServerProcess(parsedArgs);
    }
}

private static void handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) {
    // 通过反射调用SystemServer的main方法
    ClassLoader cl = ClassLoader.getSystemClassLoader();
    Class<?> clz = cl.loadClass("com.android.server.SystemServer");
    Method m = clz.getMethod("main", new Class[] { String[].class });
    m.invoke(null, new Object[] { parsedArgs.remainingArgs });
}
  • ZygoteServer是一个Socket,Zygote进程通过这个Socket和SystemService及其他应用程序进程做通信
  • 通过fork创建的SystemServer进程是一个独立运行的进程,避免SystemServer进程受到其他进程的影响。
  • 关于SystemServer,后面还会更详细的介绍

三、系统服务 System Server

Zygote中通过Zygote.forkSystemServer方法创建了System Server进程,然后通过Java的反射机制调用com.android.server.SystemServermain方法来启动System Server。

Android14的System Server源码地址

3.1 SystemServer.java

SystemServer.javamain方法调用了自身的run方法,在run方法中启动了具体的系统服务,代码如下:

java 复制代码
public static void main(String[] args) {
    new SystemServer().run();
}

private void run() {
    // 初始化系统属性,时区、语言、环境等,代码略
    ...
    // 加载本地服务
    System.loadLibrary("android_servers");
    ...
    // 初始化系统上下文
    createSystemContext();
    // 初始化主线模块
    ActivityThread.initializeMainlineModules();
    ...
    // 创建系统服务管理器
    mSystemServiceManager = new SystemServiceManager(mSystemContext);
    ...

    /* 启动系统服务 */
    // 启动引导服务
    startBootstrapServices(t);
    // 启动核心服务
    startCoreServices(t);
    // 启动其他服务
    startOtherServices(t);
    // 启动 APEX 服务
    startApexServices(t);
    ...
}

3.2 System Server启动的主要服务

以下为System Server启动的主要服务列表,具体实现可在源码中查看。

服务名称 功能说明
Activity Manager Service (AMS) 管理应用程序的生命周期,包括启动和停止应用、管理任务和活动栈、处理广播等
Package Manager Service (PMS) 管理应用包的安装、卸载、更新、权限分配等
System Config Service 管理系统配置和资源
Power Manager Service 管理设备的电源状态和电源策略,如休眠、唤醒等
Display Manager Service 管理显示设备,如屏幕亮度、显示模式等
User Manager Service 管理用户账户和用户信息
Battery Service 监控和管理电池状态和电池使用情况
Vibrator Service 控制设备的振动功能
Sensor Service 管理设备的传感器,如加速度计、陀螺仪等
Window Manager Service (WMS) 管理窗口和显示内容,包括窗口的创建、删除、布局等
Input Manager Service 管理输入设备,如触摸屏、键盘等
Alarm Manager Service 提供定时任务调度功能
Connectivity Service 管理网络连接,如 Wi-Fi、移动数据等
Network Management Service 管理网络接口和网络连接
Telephony Registry 管理电话和短信服务
Input Method Manager Service (IMMS) 管理输入法框架
Accessibility Manager Service 管理无障碍服务,为有特殊需要的用户提供辅助功能
Mount Service 管理存储设备的挂载和卸载
Location Manager Service 管理位置服务,如 GPS 和网络定位
Search Manager Service 管理系统搜索功能
Clipboard Service 管理剪贴板功能
DevicePolicy Manager Service 管理设备的安全策略和企业管理功能
Status Bar Service 管理状态栏显示和操作
Wallpaper Manager Service 管理壁纸设置和操作
Media Router Service 管理媒体设备路由

在系统服务全部启动完成后,就开始启动系统桌面程序Launcher了。

四、桌面程序Launcher

sequenceDiagram participant SystemServer participant ActivityManagerService participant ActivityTaskManagerService participant RootWindowContainer participant ActivityStartController participant Home SystemServer->>ActivityManagerService: systemReady() ActivityManagerService->>ActivityTaskManagerService: startHomeOnAllDisplays ActivityTaskManagerService->>RootWindowContainer: startHomeOnAllDisplays RootWindowContainer->>ActivityStartController: startHomeActivity ActivityStartController->>Home: Home application (Launcher) is started

  • SystemServer 启动所有服务: SystemServer类在run方法中调用startOtherServices方法,启动其他系统服务,包括ActivityManagerService。
  • ActivityManagerService准备系统: ActivityManagerService 在systemReady方法中调用mAtmInternal.startHomeOnAllDisplays方法,开始在所有显示器上启动桌面程序。
  • ActivityTaskManagerService启动: Home Activity:ActivityTaskManagerService 调用RootWindowContainer的startHomeOnAllDisplays方法。
  • RootWindowContainer循环所有显示器: RootWindowContainer 遍历每个显示器,并调用startHomeOnDisplay方法。
  • 启动Home Activity: 在每个显示器上,通过TaskDisplayArea调用ActivityStartController的startHomeActivity方法,最终调用ActivityManagerService的startActivity方法启动Home Activity。
  • Home应用启动: ActivityManagerService处理启动请求,启动Home应用的Activity展示桌面界面。

核心代码流转:

4.1 SystemServer.java

Android14的System Server源码地址

java 复制代码
private void run() {
    ...
    // 启动其他服务
    startOtherServices(t);
    ...
}

private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
    ...
    // 启动ActivityManagerService
    mActivityManagerService = mSystemServiceManager.startService(
            ActivityManagerService.Lifecycle.class).getService();
    ...
    // 启动Launcher
    mActivityManagerService.systemReady(...)
    ...
}

4.2 桌面程序Launcher(Home)的启动流程

4.2.1 ActivityManagerService.java

Android14的ActivityManagerService源码地址

java 复制代码
public void systemReady(final Runnable goingCallback, TimingsTraceAndSlog t) {
    ...
    // 在所有显示器上启动Launcher
    mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady");
    ...
}
  • 此行代码最终会调用到ActivityTaskManagerService.javastartHomeOnAllDisplays方法

4.2.2 ActivityTaskManagerService.java

Android14的ActivityTaskManagerService源码地址

java 复制代码
void startHomeOnAllDisplays(int userId, String reason) {
    synchronized (mGlobalLock) {
        // 在所有显示器上启动Launcher
        return mRootWindowContainer.startHomeOnAllDisplays(userId, reason);
    }
}
  • 此行代码最终会调用到RootWindowContainer.javastartHomeOnAllDisplays方法

4.2.3 RootWindowContainer.java

Android14的RootWindowContainer源码地址

java 复制代码
boolean startHomeOnAllDisplays(int userId, String reason) {
    boolean homeStarted = false;
    for (int i = getChildCount() - 1; i >= 0; i--) {
        final int displayId = getChildAt(i).mDisplayId;
        // 在每一个显示器上启动桌面程序
        homeStarted |= startHomeOnDisplay(userId, reason, displayId);
    }
    return homeStarted;
}

boolean startHomeOnDisplay(int userId, String reason, int displayId) {
    return startHomeOnDisplay(userId, reason, displayId, false, false);
}

boolean startHomeOnDisplay(int userId, String reason, int displayId, boolean allowInstrumenting, boolean fromHomeKey) {
    ...
    // 调用startHomeOnTaskDisplayArea
    return display.reduceOnAllTaskDisplayAreas((taskDisplayArea, result) ->
                    result | startHomeOnTaskDisplayArea(userId, reason, taskDisplayArea,
                            allowInstrumenting, fromHomeKey),false);
}

boolean startHomeOnTaskDisplayArea(int userId, String reason, TaskDisplayArea taskDisplayArea,
        boolean allowInstrumenting, boolean fromHomeKey) {
    ...
    Intent homeIntent = mService.getHomeIntent();
    mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason,
            taskDisplayArea);
    ...
    return true;
}
  • 最终通过Intent和startHomeActivity方法启动了桌面程序

五、总结

通过上述介绍,从用户按下电源键开始,经过Bootloader启动、内核启动、init进程启动、Zygote进程启动、SystemServer进程启动,以及系统应用的启动,最终进入桌面环境。

每个阶段都的核心工作:

  1. Bootloader启动:初始化硬件并加载内核。

  2. 内核启动:内核是操作系统的核心,负责管理系统资源和硬件设备。

  3. init进程启动:init进程通过解析init.rc文件来启动和配置系统服务。

  4. Zygote进程启动:Zygote是Android系统的独有设计,负责创建应用进程。通过预加载资源和共享内存,Zygote大大提高了应用启动的速度和系统资源的利用率。

  5. SystemServer进程启动:SystemServer进程启动了大量系统服务,如Activity Manager和Package Manager等,这些服务构成了Android系统的骨干,管理和协调应用的运行。

  6. 启动系统应用:Launcher应用的启动标志着系统启动的完成。用户进入桌面,可以开始正常使用设备。

通过深入理解Android的启动流程,可以更有效地进行系统开发和维护,从而提供更高性能和更稳定的用户体验。

如有任何疑问或建议,欢迎留言讨论。

相关推荐
Dnelic-1 小时前
【单元测试】【Android】JUnit 4 和 JUnit 5 的差异记录
android·junit·单元测试·android studio·自学笔记
Eastsea.Chen3 小时前
MTK Android12 user版本MtkLogger
android·framework
长亭外的少年10 小时前
Kotlin 编译失败问题及解决方案:从守护进程到 Gradle 配置
android·开发语言·kotlin
建群新人小猿13 小时前
会员等级经验问题
android·开发语言·前端·javascript·php
1024小神14 小时前
tauri2.0版本开发苹果ios和安卓android应用,环境搭建和最后编译为apk
android·ios·tauri
兰琛14 小时前
20241121 android中树结构列表(使用recyclerView实现)
android·gitee
Y多了个想法15 小时前
RK3568 android11 适配敦泰触摸屏 FocalTech-ft5526
android·rk3568·触摸屏·tp·敦泰·focaltech·ft5526
NotesChapter16 小时前
Android吸顶效果,并有着ViewPager左右切换
android
_祝你今天愉快17 小时前
分析android :The binary version of its metadata is 1.8.0, expected version is 1.5.
android
暮志未晚Webgl17 小时前
109. UE5 GAS RPG 实现检查点的存档功能
android·java·ue5