Android Framework 之 启动流程

Android 系统的启动流程

Android 系统的启动流程可以分为以下几个主要步骤:

  1. 引导加载器(Bootloader)启动:当你打开一个 Android 设备时,首先启动的是引导加载器。引导加载器负责启动 Android 的核心操作系统。

  2. Linux 内核启动:引导加载器加载并启动 Linux 内核。Linux 内核负责启动系统的底层硬件,并启动 init 进程。

  3. Init 进程启动:init 进程是 Linux 系统中的第一个进程(PID = 1)。在 Android 系统中,init 进程负责启动一些重要的守护进程和服务,例如 Zygote 进程。

  4. Zygote 进程启动:Zygote 是 Android 中的一个特殊进程,负责孵化(Fork)出所有其他的应用进程。Zygote 进程在启动时会预加载大量的系统类和资源,以此来提高应用启动的速度。

  5. SystemServer 进程启动:Zygote 进程会 fork 出一个新的进程来启动 SystemServer。SystemServer 是 Android 系统中的核心服务,它管理并提供了许多系统级别的服务,例如窗口管理服务、活动管理服务等。

  6. 系统服务启动:在 SystemServer 进程中,会启动各种系统服务。这些服务在系统启动完成后,将一直运行,为应用程序提供各种服务。

  7. 启动 Launcher 应用:系统服务启动完毕后,Activity Manager Service 会启动设备的 Launcher 应用,此时,用户可以开始与设备进行交互。

这就是 Android 系统启动的整个过程。请注意,这个过程可能会因设备制造商的定制和 Android 版本的不同而有所不同,但大体流程是相同的。

Launcher的启动流程

Launcher 的启动过程更具体的说明如下:

  1. 当 Android 系统启动完成,并且所有的系统服务都已经启动后,ActivityManagerService (AMS)会开始处理用户的交互。AMS 是 Android 中负责管理所有活动的系统服务。

  2. AMS 会发送一个包含 ACTION_MAIN 和 CATEGORY_HOME 的 Intent。这个 Intent 的目的是寻找并启动设备上配置为主屏幕(HOME)的应用,通常这就是 Launcher 应用。

  3. 这个 Intent 会通过 Android 的 Intent 解析系统,寻找所有能够响应这个 Intent 的应用。由于 Launcher 在其清单文件(AndroidManifest.xml)中声明了相应的 ,因此它会被选中来响应这个 Intent。

  4. 一旦 Launcher 被选中,AMS 就会请求 Launcher 启动。如果这是设备第一次启动,或者 Launcher 进程尚未启动,那么 AMS 会请求 Zygote 启动一个新的进程来托管 Launcher。如果 Launcher 进程已经存在,AMS 就会在该进程中启动新的 Launcher 活动实例。

  5. 当 Launcher 启动后,它会创建并显示用户的主屏幕。这个屏幕上会显示应用的图标、小部件等,用户可以通过这个界面启动和切换应用。

startActivity 详细说明

  1. 发送 Intent:源应用程序(App1)调用 startActivity 方法,传递一个 Intent。该 Intent 包含要启动的目标应用程序(App2)的 Activity 的信息。

  2. 验证权限和 Intent:在 ActivityManagerService (AMS) 中,startActivity 方法会对 Intent 进行检查和验证。这包括验证调用者的权限,查找 Intent 对应的 Activity,处理各种启动模式等。

  3. 判断目标应用程序进程状态:接着,AMS 会判断目标应用程序 App2 的进程是否已经存在。如果已经存在,AMS 会使用已经存在的进程;如果不存在,AMS 会向 Zygote 发送请求,要求它创建一个新的进程。

  4. 创建新的应用程序进程:Zygote 在收到 AMS 的请求后,会创建一个新的应用程序进程,然后在这个进程中创建一个 Application 对象,并执行其 onCreate 方法。

  5. 创建 ActivityRecord:与此同时,AMS 会创建一个新的 ActivityRecord 对象,来代表要启动的 Activity。

  6. 调度启动 Activity:然后,AMS 会通过 Binder IPC 向新的应用程序进程发送一个 LAUNCH_ACTIVITY 消息。

  7. 接收 LAUNCH_ACTIVITY 消息:新的应用程序进程在接收到 LAUNCH_ACTIVITY 消息后,会创建目标 Activity 的实例,然后调用其 onCreate、onStart 和 onResume 方法。

ActivityManagerService 启动

**ActivityManagerService (AMS) **是 Android 中最为关键的系统服务之一,它负责管理系统中的进程,以及四大组件(Activity、Service、BroadcastReceiver 和 ContentProvider)的生命周期。这里将详细解释 AMS 的内部启动流程和工作流程:

AMS的启动流程:

实例化:AMS 是在 SystemServer 中被实例化的。SystemServer 会首先创建一个 ContextImpl 对象,然后利用这个 ContextImpl 创建 AMS。

服务初始化:接下来,调用 AMS 的 init 方法进行初始化,这个方法会创建和初始化一些需要的数据结构和服务,比如 BroadcastQueue、IntentFirewall 和 ActivityStackSupervisor 等。

准备完成:完成初始化后,调用 systemReady 方法来通知 AMS 系统准备就绪。在这个方法中,AMS 会完成一些后期初始化的工作,例如启动系统的 Home Activity。

AMS的工作流程:

AMS 主要的工作就是管理系统中的四大组件和进程。以下是它们分别的工作流程:

Activity的管理:AMS 使用 ActivityStackSupervisor 来管理系统中所有的 Activity。当应用程序调用 startActivity 方法时,会通过 Binder IPC 机制调用 AMS 中的 startActivity 方法。AMS 会根据 Intent 解析出需要启动的 Activity,创建一个 ActivityRecord 对象并添加到 ActivityStack 中。然后,AMS 会向应用程序发送 LAUNCH_ACTIVITY 消息,告诉应用程序启动新的 Activity。

Service的管理:当应用程序调用 startService 或 bindService 方法时,AMS 会创建一个 ServiceRecord 对象来保存 Service 的状态。然后,AMS 会向应用程序发送 CREATE_SERVICE 或 BIND_SERVICE 消息,告诉应用程序创建或绑定 Service。

BroadcastReceiver的管理:当应用程序调用 sendBroadcast 方法时,AMS 会创建一个 BroadcastRecord 对象,保存广播的信息。然后,AMS 会将 BroadcastRecord 添加到 BroadcastQueue 中,等待处理。

ContentProvider的管理:当应用程序调用 getContentResolver().query() 或其他方法时,AMS 会查找对应的 ContentProviderRecord,然后通过 Binder IPC 机制向目标 ContentProvider 发送请求。

进程的管理:AMS 使用 ProcessList 和 ProcessRecord 来管理系统中的进程。当需要创建新的进程时,AMS 会向 Zygote 发送请求,然后由 Zygote 创建新的进程。同时,AMS 也负责进程的调度和回收。

主要信息

startProcessLocked

在 Android 中,startProcessLocked() 方法主要是在 ActivityManagerService 中,用于启动新的应用进程。这个方法会被系统在需要启动新的应用进程时调用,例如,当用户启动一个新的应用或者服务需要在新的进程中运行时。以下是一些主要的步骤和操作:

检查是否已经存在相同的进程:首先,系统会检查是否已经存在一个相同名字的进程。如果已经存在,则不会再创建新的进程。

检查系统资源限制:系统会检查当前的系统资源,如内存使用情况等,来决定是否有足够的资源启动新的进程。

创建进程记录:如果可以启动新的进程,系统会创建一个新的 ProcessRecord 对象来保存新进程的信息。

启动新进程:使用 Zygote 启动新进程。Zygote 是 Android 中的一个特殊进程,它预加载了大量的系统资源和常用库,新的应用进程会通过 fork Zygote 进程的方式启动,这样可以提高进程启动的速度。

设置进程的参数:系统会设置新进程的各种参数,例如进程的优先级、所属用户等。

更新系统状态:系统会更新当前的系统状态,例如更新当前运行的进程列表等。

runOnce

**runOnce()**方法在Android的Zygote进程中非常关键,它是处理进程启动请求的主要逻辑。

在Android系统中,新的应用进程是通过fork Zygote 进程来创建的。具体来说,当需要启动新的应用进程时,系统会通过一个特殊的socketZygote 进程进行通信,向Zygote 进程发送一个包含新进程需要的信息的请求,Zygote进程在接收到请求后,会执行**runOnce()**方法来处理这个请求。

以下是runOnce()方法的主要步骤:

读取请求参数runOnce()方法首先会从Zygote socket中读取请求参数,这些参数包括新进程的一些信息,例如应用的包名、启动类名等。

fork新进程 :读取完请求参数后,runOnce()方法会调用 forkAndSpecialize() forkSystemServer()方法来fork 一个新的进程。这两个方法的主要区别在于,forkAndSpecialize()方法是用于创建普通的应用进程,而 forkSystemServer()方法是用于创建System Server进程。

初始化新进程fork新进程后,**runOnce()**方法会对新进程进行一些初始化操作,例如设置新进程的环境变量、加载应用的dex文件等。

启动新进程的主类 :初始化完成后,runOnce()方法会调用 RuntimeInit.zygoteInit()方法来启动新进程的主类。对于普通的应用进程,主类通常是应用的Application 类;对于System Server 进程,主类是com.android.server.SystemServer类。

返回新进程的PID:最后,**runOnce()**方法会将新进程的PID返回给系统。这个PID是新进程的唯一标识,系统可以使用这个PID来管理新进程。

ActivityThread的main函数

ActivityThread 是 Android 中的一个非常重要的类,它是每个 Android 应用程序主线程的入口点,也就是应用程序的主线程("main" thread)。在 ActivityThread 的 main 方法中,执行了一系列的初始化操作来启动和设置应用程序。

以下是 ActivityThread 的 main 方法主要做了哪些事情:

设置 Thread 属性:主线程的名称会被设置为** "main"**。

创建 Looper :在 Android 中,主线程需要一个 Looper 对象来处理消息队列。Looper.prepareMainLooper() 方法会创建一个绑定到主线程的 Looper 对象。

创建 ActivityThread 对象 :创建 ActivityThread 实例并调用其 attach 方法,这个方法会完成一些重要的初始化工作,包括设置应用的上下文,创建应用的 Instrumentation 对象等。

设置 Android 默认的异常处理器:如果应用抛出未捕获的异常,这个处理器将会被调用。

开始循环 :通过调用 Looper.loop() 来开始主线程的消息循环。

在应用进程启动后,需要向 ActivityManagerService (AMS) 报告是因为 AMS 是 Android 系统中管理所有应用程序生命周期的关键组件。当一个新的应用程序进程被创建时,它需要告诉 AMS 它已经启动并且准备好接收指令。此外,这也是一个错误检查机制:如果 AMS 启动了一个进程,但是这个进程在一段时间内没有报告回来,那么 AMS 会认为这个进程启动失败,会采取相应的操作,如重新启动这个进程或者报告一个错误。

启动binder机制

Binder 机制主要在应用程序启动时进行初始化,并在其进程生命周期内保持活动状态,用于处理进程间通信(IPC )的请求。关于 Binder 机制的启动,这主要发生在应用程序的主线程(ActivityThread)初始化过程中。

以下是 Binder 机制的启动过程:

创建应用的主线程 :每个** Android** 应用都有一个主线程,它是应用程序的入口点。当新的应用程序进程创建时,Zygote 会复制其内存空间,并在新的进程空间中启动应用的主线程。主线程的入口函数是 ActivityThread.main()

初始化 Looper :在 ActivityThread.main() 函数中,会调用 Looper.prepareMainLooper() 来为主线程创建一个 LooperLooper 是一个用于处理消息队列的工具,是实现事件驱动编程的关键组件。

创建 ActivityThread 对象 :接下来,会创建一个 ActivityThread 对象,并调用其 attach() 方法来进行一些必要的初始化工作。在这个过程中,会创建应用的 ContextInstrumentation 对象等。

创建 Binder 线程池 :在 ActivityThreadattach() 方法中,会调用 BinderInternal.addGcWatcher()BinderInternal.createBinderThreadPool() 来为当前进程创建 Binder 线程池。

addGcWatcher() 方法会添加一个 GC (垃圾回收)监听器,该监听器会在每次完成 Binder 事务后执行一次 GC ,以防止 Binder 事务造成的内存泄漏。

createBinderThreadPool() 方法会创建一个 Binder 线程池。这个线程池会在后台运行,用于处理来自其他进程的 Binder 请求。

启动消息循环 :最后,主线程的 Looper 对象会调用其 loop() 方法来启动消息循环。在这个消息循环中,主线程会不断地从消息队列中取出消息并处理,包括处理来自 Binder 线程池的消息。

Binder Native 层

打开 Binder 驱动 :在 Android 系统启动的过程中,会加载 Binder 驱动。在每个进程创建的过程中,会打开 /dev/binder 设备,这样,该进程就可以使用 Binder 驱动进行 IPC 通信了。

映射内存 :当进程打开 /dev/binder 设备后,会通过 mmap 系统调用映射一块内存空间作为进程和 Binder 驱动之间的通信区域。这样,进程和 Binder 驱动就可以通过这块共享内存进行数据交换,提高了通信效率。

创建 Binder 线程池 :每个进程都需要创建一个 Binder 线程池来处理来自其他进程的 Binder 请求。Binder 线程池是一个由多个线程组成的线程池,每个线程都会使用 ioctl 系统调用进入到 Binder 驱动的等待队列,等待来自其他进程的 Binder 请求。

当一个进程通过 Binder 机制向另一个进程发送请求时,Binder 驱动会唤醒等待队列中的一个线程来处理这个请求。这个线程会读取共享内存中的数据,处理请求,并将结果写回到共享内存中。然后,这个线程会再次进入到 Binder 驱动的等待队列,等待下一次的请求。

冷启动 App 全流程

  1. 点击桌面图标后,Launcher 应用会构建一个 intent 并发送给 AMS,通知 AMS 启动 App;
  2. AMS 收到 intent 消息后,首先做一些校验,然后判断 App 对应的进程是否启动,如果没有启动,则通知 Zygote 进程启动 App;
  3. AMS 通过 socket 与 Zygote 进程通信,将必要的启动参数传递过去,Zygote 进程收到后,通过 fork 调用创建新的进程,并且在主进程中将子进程的 pid 返回给 AMS 所在的进程;
  4. fork 出来的进程也就是 App 进程,进程启动后首先会初始化 Binder 机制,具体为打开 Binder 驱动、通过 mmap 映射内存缓存,启动 binder 线程池;
  5. App 进程在 Binder 启动后会创建一个 ApplicationThread 的 Binder 实体,通过ServerManager 获取 AMS 的 Binder 代理,将 ApplicationThread 这个 Binder 传递给 AMS;
  6. AMS 收到 attach 后,保存 ApplicationThread 对象的 Binder 代理对象,以方便后续与 App 进程进行通信。AMS 发送 attachApplication 请求,该请求最后会在 App 所在进程的 Binder 线程被执行,然后构建一个 Message 对象发送给主线程执行 Application 对象的初始化;
  7. App 的主线程收到消息后,构建 LoadedApk 对象,该对象存储 App 的一些基本信息,紧接着创建 ContentImpl 对象,并且通过反射创建 Application 对象,接着调用其 attach 方法,传入 ContentImpl 对象,最后调用其 onCreate 方法;
  8. 再回到 AMS 刚刚通知 App 创建 Application 的位置,AMS 在执行完该事后,会立马通知 App 启动 launch类型的 Activity 以及一些 service、广播等
  9. App 在收到启动首页 Activity 事件后,通过反射创建 Activity 对象,并且同时创建一个 ContentImpl 对象,接着执行 Activity 的 onCreate 方法,设置布局文件;
  10. 接下来 onResume 方法中,通过 WMS 的 addView 方法,将 ViewRoot 中的视图添加到 WMS 中,并且视图树会执行 attachToWindow 回调;
  11. ViewRootImpl 会通过 Choreographer 注册 vsyn 信息,在下一个 vsyn 信号到来之后,会执行 msasure、layout、draw ,在 draw 方法执行完之后,其内部通过 canvas 的 api 调用绘制指令,这些指令会被记录下来,最后通过 RenderThread 线程进行计算执行,最终通过 GPU进行渲染;
  12. 渲染的数据会放到 Surface 缓冲区中,SufaceFlinger 将所有的窗口对象的 Surface 数据区域进行合成,并发送到屏幕的后缓冲区域;
  13. 下一个 vsync 信号到来之后,后缓冲区的图像就会显示到屏幕上;
相关推荐
雨白10 小时前
Android 快捷方式实战指南:静态、动态与固定快捷方式详解
android
hqk10 小时前
鸿蒙项目实战:手把手带你实现 WanAndroid 布局与交互
android·前端·harmonyos
LING11 小时前
RN容器启动优化实践
android·react native
恋猫de小郭13 小时前
Flutter 发布官方 Skills ,Flutter 在 AI 领域再添一助力
android·前端·flutter
Kapaseker19 小时前
一杯美式搞懂 Any、Unit、Nothing
android·kotlin
黄林晴19 小时前
你的 Android App 还没接 AI?Gemini API 接入全攻略
android
恋猫de小郭1 天前
2026 Flutter VS React Native ,同时在 AI 时代 VS Native 开发,你没见过的版本
android·前端·flutter
冬奇Lab1 天前
PowerManagerService(上):电源状态与WakeLock管理
android·源码阅读
BoomHe1 天前
Now in Android 架构模式全面分析
android·android jetpack
二流小码农2 天前
鸿蒙开发:上传一张参考图片便可实现页面功能
android·ios·harmonyos