安卓系统应用启动流程分析

随着移动开发的兴起,安卓系统的重要性愈加突显。本文简要介绍安卓系统上应用启动流程,对于应用开发、系统定制以及性能优化人员来说,熟悉应用启动流程会使得在今后的工作中更加得心应手,做到知其然,知其所以然。本文主要面向开发人员,假定读者已有一定的安卓基础。

本文以安卓P版本为基础,不同安卓版本上应用启动流程略有差异,但核心逻辑仍然一致。

安卓上应用启动的几种形式

冷启动

这种方式应用需要完成完整的启动过程,即创建进程、初始化资源及显示应用界面,相比于另外两种启动模式,应用冷启动耗时最长。

热启动

这种方式下应用进程已经启动,通常只需将要显示的activity带到前台即可,所以在该模式下应用可以较快速启动。

温启动

这种方式需要完成部分冷启动过程,比如进程已经创建,但要重新执行activity的onCreate()来创建要显示的activity,这种模式下的启动时间介于以上两种之间。

本文主要介绍冷启动的执行流程。

应用启动相关的一些基本概念

zygote

该进程是安卓上所有应用进程的父进程,在开机过程中由系统启动并保持运行状态。由于现在的安卓平台大部分同时支持32位和64位应用,zygote也分为32位和64位两个版本,其原理相同,在本文中不做区分。

system_server

安卓上的系统服务进程,绝大部分主要系统服务都驻留在该进程内,包括下文中介绍的AMS、WMS、PMS等。system_server由zygote在启动进程中分裂而来(即也是zygote的子进程),然后持续运行。

AMS

Activity Manager Service,是安卓上的一个核心服务,负责管理应用各个组件,所有应用在其生命周期内均需和AMS打交道。该服务驻留在system_server进程内。 

WMS

Window Manager Service,是安卓上的窗口管理服务,负责处理应用的界面显示相关的请求。该服务驻留在system_server进程内。

PMS

Package Manager Service,是安卓上的包管理服务,负责处理应用的安装、缷载等。该服务驻留在system_server进程内。

应用冷启动的任务序列

在冷启动时,系统首先有三个任务:

1. 在AMS端分配应用资源;

2. 显示应用的空白启动窗口;

3. 创建应用进程;

在应用进程启动后,应用进程会负责启动的后续阶段:

1. 创建应用对象;

2. 启动主线程;

3. 创建主activity并完成绘制及显示;

应用进程完成第一帧绘制后,系统会将空白窗口替换为应用的画面,此时,用户可以开始使用应用。

典型的冷启动场景及流程

接下来,我们以一个典型场景,即从桌面点击应用图标启动应用这一过程,来介绍应用启动流程。其它应用启动场景,比如从命令行启动,或者从A应用启动B应用,与本场景大同小异,本文中不再另做说明。

先看下简要的流程图:

如上图所示,当用户点击桌面上应用图标后,Launcher进程会将应用信息发送给AMS,由于这时应用进程还没有启动,所以需要先创建应用进程,AMS收到请求后会发送命令给zygote进程要求创建目标应用进程,当目标进程启动后,会将自身的远程handle注册给AMS,这样AMS就可以控制应用进程去执行接下来的一系列启动操作。

接下来,我们对这一过程做下详细说明。

1. 用户点击应用图标后,launcher进程向system_server进程发消息请求启动应用进程,即launcher通过startActivity()向AMS发送请求启动对应的activity,核心代码如下:

frameworks/base/core/java/android/app/Activity.java

其中,参数intent包含了要启动的目标应用的信息。

以上代码最终会调用AMS内部的startActivity(),由于Launcher和AMS分属不同进程,这一过程通过binder通信。

2. system_server进程收到请求后,通过其内部逻辑,即AMS收到startActivity()调用后,会进行必要的权限检查,创建activity的内部表示即ActivityRecord对象,并显示一个空白的窗口。

核心代码如下:

frameworks/base/services/core/java/com/android/server/am/ActivityRecord.java

由于应用冷启动时进程不存在,AMS会通过zygote创建应用进程。

核心代码如下:

frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

具体流程如下:

在非冷启动的情况,即如果应用进程已经启动完成,则可以直接进入启动activity的逻辑,代码如下:

在冷启动的startProcessLocked()调用过程中,有一个参数需要特别注意,即 ”entryPoint”,这个参数表示zygote分裂出的应用进程的入口,其定义为:

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

也就是说,ActivityThread是应用程序的入口。

3. 当应用进程启动后,会进入ActivityThread的main()方法执行应用端逻辑;

核心代码如下:

frameworks/base/core/java/android/app/ActivityThread.java

创建ActivityThread对象时,会同时创建应用进程的表示对象,即该应用的handle,代码如下:

frameworks/base/core/java/android/app/ActivityThread.java

同时要特别注意应用进程的“attach”操作,这一操作会将应用进程自身的远程handle即mAppThread注册给AMS,这样AMS就可以和应用通信,通知应用执行后续的操作,启动相应的activity;

核心代码如下:

frameworks/base/core/java/android/app/ActivityThread.java

4. 现在应用进程已经启动,并且已与AMS建立关联,AMS会继续执行启动应用的第一个activity的逻辑;

核心代码如下:

frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

其中,realStartActivityLocked()会通知应用启动相应activity,逻辑如下:

5. 应用进程收到 ”launch”及”resume” 命令后,就会创建相应的activity对象以及关联的窗口对象等资源,并调用activity的生命周期回调函数完成activity的显示;到此,应用进程的第一个activity就创建完成了;

核心代码如下:

frameworks/base/core/java/android/app/ActivityThread.java

初始化图形资源及与WMS的连接:

创建activity对象:

初始化activity实例:

调用activity的onCreate()函数:

接下来会继续activity的其它生命周期回调函数并将activity显示出来,至此,一个应用的首个activity即完成了启动。

总结

本文简要说明了安卓平台上应用启动的流程,通过本篇介绍,希望读者能理清应用启动的大致脉络,对应用启动过程有一个基本的理解。

参考资料

[1]http://androidxref.com/

[2]https://developer.android.com/topic/performance/vitals/launch-time

推荐阅读:

专辑|Linux文章汇总

专辑|程序人生

专辑|C语言

嵌入式Linux

微信扫描二维码,关注我的公众号

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/467556.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

bootstrap 居中 表格中_使用Twitter Bootstrap在表格单元格中垂直居中

Tom Sarduy..156FOR BOOTSTRAP 3.X:Bootstrap现在具有表格单元格的以下样式:.table tbody > tr > td{vertical-align: top;}要做的就是添加自己的类,为前一个选择器添加更多特异性:.table tbody > tr > td.vert-aligned {vertical-align: middle;}然后将类添加到您…

撞车咋办

出门行车,最怕的就是遇到事故,老司机倒还好,这新手司机以及咱们的女司机遇到事故第一反应肯定是傻眼了。那么真要遇到事故了怎么办呢? 今天小编就来给大家讲讲遇到事故应该如何理智应对! 一、单方事故 就是你没碰到人或…

物联网通信协议全解析

随着物联网设备数量的持续增加,这些设备之间的通信或连接已成为一个重要的思考课题。通信对物联网来说十分常用且关键,无论是近距离无线传输技术还是移动通信技术,都影响着物联网的发展。而在通信中,通信协议尤其重要,…

【长沙集训】2017.10.10

Adore 1.1 问题描述 小 w 偶然间遇到了一个 DAG。 这个 DAG 有 m 层&#xff0c;第一层只有1个源点&#xff0c;最后一层只有1个汇点&#xff0c;剩下的每一层都有 k 个 节点。 现在小 w 每次可以取反第 i(1 < i < n − 1) 层和第 i 1 层之间的连边。也就是把原本从 (i,…

elasticsearch mongodb mysql_Elasticsearch 与 Mongodb 数据同步问题

1、mongo-connector工具首先安装python环境wget http://www.python.org/ftp/python/3.0.1/Python-3.0.1.tgztar -zxvf Python-3.0.1.tgzcd Python-3.0.1./configuremake allmake install看来新装的版本生效了&#xff0c;做个软连接应该就OK。ln -s /usr/local/bin/python3.0 /…

Linux中断子系统之Workqueue

背景说明Kernel版本&#xff1a;4.14ARM64处理器&#xff0c;Contex-A53&#xff0c;双核使用工具&#xff1a;Source Insight 3.5&#xff0c; Visio1. 概述Workqueue工作队列是利用内核线程来异步执行工作任务的通用机制&#xff1b;Workqueue工作队列可以用作中断处理的Bott…

python3一个简单的网页抓取

python3一个简单的网页抓取 都是学PYTHON。怎么学都是学&#xff0c;按照基础学也好&#xff0c;按照例子增加印象也好&#xff0c;反正都是学 import urllib import urllib.requestdata{} data[word]baker95935url_valuesurllib.parse.urlencode(data) url"http://www.ba…

给你准备的Linux启动流程

读者朋友提问&#xff1a; 昨天在后台看到一个读者朋友跟我说&#xff0c;发哥&#xff0c;你能不能讲一下嵌入式Linux的开机流程&#xff0c;然后我看了下&#xff0c;我是没有写过这方面的文章&#xff0c;所以&#xff0c;就有了这篇文章。回答&#xff1a;我们都知道pc指针…

[linux]服务器apache配置vhost

官网示例&#xff1a; http://httpd.apache.org/docs/current/vhosts/examples.html转载于:https://www.cnblogs.com/oDoraemon/p/7650748.html

java dao 单元测试_Spring Service、Dao进行Junit单元测试

pring对Controller、Service、Dao进行Junit单元测试总结​ 所有用Junit进行单元测试&#xff0c;都需要下面的配置RunWith(SpringJUnit4ClassRunner.class)ContextConfiguration(locations {"classpath:applicationContext.xml"})​ applicationContext.xml 是整个项…

Linus Torvalds:我们都老了,但Linux维护者真的很难找

Linux 之父Linus Torvalds非常担忧没人继续维护内核「真的很难找到维护者&#xff01;」在本周召开的Linux开源峰会与嵌入式大会上&#xff0c; VMware的首席开放源代码官Dirk Hohndel和Linux的创建者Linus Torvalds再次就Linux开发展开了远程对话讨论。左&#xff1a;Dirk Ho…

判断线程结束

判断线程结束 使用ExecutorService.isTerminated方式 public void executor() throws InterruptedException{ExecutorService executorService Executors.newFixedThreadPool(threadNum);List<Callable<Object>> calls new ArrayList<>();for (int i 0; …

java map扩容机制_java中ConcurrentHashMap的扩容机制是怎样的?详细解析

大家都知道java中有很多的基础知识&#xff0c;需要大家花费一定的时间去消化。关于java中ConcurrentHashMap的扩容机制不知道大家是否了解过&#xff0c;其实内容也是很好理解的&#xff0c;一起来看看吧。首先&#xff0c;我们需要知道的是&#xff1a;1. 计算每个线程可以处…

看printk引发的一点思考

在源码位置kernel/printk/函数原型asmlinkage __visible int printk(const char *fmt, ...) {printk_func_t vprintk_func;va_list args;int r;va_start(args, fmt);/** If a caller overrides the per_cpu printk_func, then it needs* to disable preemption when calling pr…

寄语

寄语&#xff1a; 前面漆黑一片&#xff0c;什么都看不到。 也不是&#xff0c;天亮后就会很美的。转载于:https://www.cnblogs.com/doudou-taste/p/7660997.html

我毕业时候写的简历

写简历这个事情&#xff0c;一直是一个非常让人头疼的&#xff0c;在我看来&#xff0c;写简历并不是一件简单的事情&#xff0c;所以&#xff0c;现在是晚上一点钟&#xff0c;我倒腾了一个晚上&#xff0c;才有了这篇文章。我认为写简历有几个需要注意的地方&#xff0c;不啰…

idea java 非法字符_解决IDEA显示非法字符 \ufeff 的问题

一、问题在txt文本中复制代码进入IDEA报错Error:(1, 1) java: 非法字符: ‘\ufeffError:(1, 10) java: 需要class, interface或enum二、解决办法用IDEA转换&#xff0c;先转换为GBK&#xff0c;再转回UTF-8()补充知识&#xff1a;Eurake问题Failed to bind properties under eu…

css 单行/多行文字垂直居中问题

例子可以直接看这里 http://www.zhangxinxu.com/study/200911/line-height-text-v-center.html 这篇文章中有一点点解释 http://blog.csdn.net/hdchangchang/article/details/47086565 这一篇提出了一个新想法 http://caibaojian.com/css-vertical-middle.html 总的来说&#x…

Linux 内核完成接口

Linux 内核里面有一个函数wait_for_completion&#xff0c;这是一个内核同步机制的函数&#xff0c;同步机制如果是早期的读者应该看过我发的文章&#xff0c;如果没有看过的可以看看Linux 专辑文章里面找找。既然是同步机制&#xff0c;主要的工作就是调用了这个函数&#xff…

java 换行符 常量_6.java常量

Java中常量的分类&#xff1a;整数常量 &#xff1a; 所有整数小数常量 &#xff1a; 所有小数布尔常量 &#xff1a; 只有true和false字符常量 &#xff1a;使用’’引起来的单个字符字符串常量 &#xff1a;使用“”引起来的字符序列&#xff0c;“” 、“a” 、” ”null常…