在android手机上,当我们点击桌面上的按钮启动一个应用,就能打开应用的界面。这里我们所说的桌面其实就是android系统启动后的就已经帮我们运行的第一个程序,launcher程序。
launcher程序可以理解为作为其它应用app入口管理的一个系统自带的app,正常情况下,安装一个新的应用,就会在桌面(laucher)程序中显示一个相应的图标。
上述点击桌面上的图标打开应用的过程,本质上是通过lancher应用的提供的桌面图标启动另一个app的过程,并打开了新应用的首个Activity。
很显然,上述的过程是两个应用之间的一个交互,属于跨进程的通信。
针对于上述流程中,今天我们先搞清楚第一个问题:
Android手机系统启动的流程,都干了些什么?另外,从launcher程序中打开一个应用的流程,暂不分析。
说明:不会涉及太多的源码分析,尤其相对底层非java层源码,本篇主要分析Android系统启动、App启动的流程,部分涉及到的源码为Android10.0源码。
首先,我们来看一下android系统的启动架构图:
Android系统启动的过程是自下而上的一个过程,是由Boot Loader引导开机,然后依次进入:
Kernel->Native->FrameWork->App,从上图中也能看到在App层启动了我们的launcher应用。
板子上电后,芯片从固化在ROM里预设的代码(BOOT ROM)开始执行,BOOT ROM会加载BootLoader到RAM,然后把控制权交给BootLoader。
BootLoader并不属于Android系统,它的作用是初始化硬件设备,加载内核文件等,为Android系统内核启动搭建好所需的环境。
BootLoader是针对特定的主板和芯片的(与CPU以及电路板的配置情况有关),因此对于不同的设备制造商,他们的引导程序都是不同的。目前大多数系统都是是uboot来修改的。
BootLoader引导程序一般分两个阶段执行:
1.基本的硬件初始化,目的是为了下一个阶段的执行以及随后的kernel的执行准备好一些基本的硬件环境。这一阶段的代码通常是用汇编语言写的,以达到短小精焊的目的。
2.初始化Flash设备,设置网络、内存等等,将kernel映像和根文件系统映像从Flash上读到RAM空间中,然后启动内核。这段代码通常是用C语言来写的,以便于实现复杂的功能和取得更好的代码可读性和可移植性。
实际上BootLoader还需要根据misc分区的设置来决定是要正常启动系统内核还是要进入recovery进行系统升级,复位等工作。
Linux内核负责初始化各种软硬件环境,加载驱动程序,挂载根文件系统等。最重要的是内核启动完成后,它会在根文件系统中寻找”init“文件,然后启动init进程。
init进程是Linux系统中用户空间的第一个进程,进程号为1,我们可以说它是root进程或者是所有进程的父进程。
在init进程中,挂载虚拟文件系统、启动property服务、当然更重要的是包括了启动的各种系统服务:serviceManager、adbd、mediasever、zygote、bootanmation等。
zygote进程是Android系统最重要的进程之一。后续Android中的应用进程都是由zygote进程fork出来的。因此,zygote是Android系统所有应用进程的父进程。zygote进程实际执行文件并不是zygote,而是/system/bin/app_process。它会调用 frameworks/base/core/jni/AndroidRuntime.cpp 提供的接口启动 java 层的代码 frameworks/base/core/java/com/android/internal/os/ZygoteInit.java。
public static void main(String argv[]) {
.....
zygoteServer = new ZygoteServer(isPrimaryZygote);
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
.....
}
上面的ZygoteInit.java中的核心代码,ZygoteServer的构造函数:
/**
* 初始化一个带有server socket的ZygoteServer进程。
*/
ZygoteServer(boolean isPrimaryZygote) {
....
mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);
.....
}
”后续Android中的应用进程都是由zygote进程fork出来的“,上述zogoteInit的主要工作:
1、启动socket服务,监听socket,当有启动应用的请求到达的时候,fork生成app应用进程。
2、启动SystemServer进程。
SystemServer进程,被称为系统服务进程,属于Android framework层的源码实现,通过android studio打开SystemServer.java,能够看到其中声明了大量的android的系统服务。简单看一下SystemServer.java的源码实现:
/**
* zygote进程调用入口点
*/
public static void main(String[] args) {
// systemServer的实际创建,并run起来
new SystemServer().run();
}
private void run() {
// 初始化系统上下文.
createSystemContext();
// 创建service manager.
mSystemServiceManager = new SystemServiceManager(mSystemContext);
// Start services.(启动服务)
try {
traceBeginAndSlog("StartServices");
startBootstrapServices();//引导程序服务
startCoreServices();//核心服务
startOtherServices();//其它服务
SystemServerInitThreadPool.shutdown();
} catch (Throwable ex) {
...
}
}
SystemServer的主要作用就是启动各种系统的服务和管理它们,包含三大类服务:
上述systemServer进程中启动的ActivityManagerService,最后会调用systemReady
public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
...
//9.0源码,此处的api有区别,建议直接查看10.0源码
mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady");
...
}
上述代码,就是laucher程序的启动的入口函数,这里不做详细深入的launcher程序启动过多细节,Android10.0的源码和之前的源码有一些差别,主要是将很多职责交给了ActivityTaskManagerService来处理,需要追看源代码的可以从这里入手继续看。简单概括一下launcher程序的启动的流程:
2、3步骤,分析过Activity的启动过程源码的同学,一眼就能看出一致性。
Launcher启动完成之后,开机动画会进行出,这样给用户的体验就是开机后,就直接进入到桌面了。
本篇文章部分文字描述摘自其它网络资源,源码部分皆为自行查看和注释。
参考文章:http://gityuan.com/android/,https://qiushao.net/
及时获得最新文章更新,关注gongzhonghao:Hym4Android