Android 应用启动全流程深度剖析(1)

1. 前言

从用户手指点击桌面上的应用图标到屏幕上显示出应用主 Activity 界面而完成应用启动,快的话往往都不需要一秒钟,但是这整个过程却是十分复杂的,其中涉及了 Android 系统的几乎所有核心知识点。同时应用的启动速度也绝对是系统的核心用户体验指标之一,多少年来,无论是谷歌或是手机系统厂商们还是各个 Android 应用开发者,都在为实现应用打开速度更快一点的目标而不断努力

但是要想真正做好应用启动速度优化这件事情,我想是必须要对应用启动的整个流程有充分的认识和理解的,所以无论作为 Android 系统或应用开发者,都有必要好好的学习和了解一下这个过程的。网上有很多介绍应用启动流程源码的文章,但是总感觉大多数都不太全面,很多只是介绍了应用启动过程中的部分流程,而没有总体清晰的认识应用启动过程的总体脉络与系统架构设计思想

所以本文将结合笔者多年来的工作经历,结合 Systrace 分析工具,基于最新 Android R AOSP 源码完整的分析一下这个从用户手指触控点击屏幕应用图标到应用界面展示到屏幕上的整个应用启动过程,也是对之前所做所学的一个总结与归纳

2. 大纲

· Android 触控事件处理机制
· Zygote 进程启动和应用进程创建流程
· Handler 消息机制
· AMS 的 Activity 组件管理
· 应用 Application 和 Activity 组件创建与初始化
· 应用 UI 布局与绘制
· RenderThread 渲染
· SurfaceFlinger 合成显示

3. Input 触控事件处理流程

3.1 系统机制分析

Android 系统是由事件驱动的,而 input 是最常见的事件之一,用户的点击、滑动、长按等操作,都属于 input 事件驱动,其中的核心就是 InputReader 和 InputDispatcher。

InputReader 和 InputDispatcher 是跑在 SystemServer 进程中的两个 native 循环线程,负责读取和分发 Input 事件。整个处理过程大致流程如下:

  1. InputReader 负责从 EventHub 里面把 Input 事件读取出来,然后交给 InputDispatcher 进行事件分发;
  2. InputDispatcher 在拿到 InputReader 获取的事件之后,对事件进行包装后,寻找并分发到目标窗口;
  3. InboundQueue 队列(“iq”)中放着 InputDispatcher 从 InputReader 中拿到的 input 事件;
  4. OutboundQueue(“oq”)队列里面放的是即将要被派发给各个目标窗口 App 的事件;
  5. WaitQueue 队列里面记录的是已经派发给 App(“wq”),但是 App 还在处理没有返回处理成功的事件;
  6. PendingInputEventQueue 队列(“aq”)中记录的是应用需要处理的 Input 事件,这里可以看到 input 事件已经传递到了应用进程;
  7. deliverInputEvent 标识 App UI Thread 被 Input 事件唤醒;
  8. InputResponse 标识 Input 事件区域,这里可以看到一个 Input_Down 事件 + 若干个 Input_Move 事件 + 一个 Input_Up 事件的处理阶段都被算到了这里;
  9. App 响应处理 Input 事件,内部会在其界面 View 树中传递处理
    用一张图描述整个过程大致如下:
    input流程
    3.2 结合 Systrace 分析
    从桌面点击应用图标启动应用,system_server 的 native 线程 InputReader 首先负责从 EventHub 中利用 linux 的 epolle 机制监听并从屏幕驱动读取上报的触控事件,然后唤醒另外一条 native 线程 InputDispatcher 负责进行进一步事件分发。InputDispatcher 中会先将事件放到 InboundQueue 也就是 “iq” 队列中,然后寻找具体处理 input 事件的目标应用窗口,并将事件放入对应的目标窗口 OutboundQueue 也就是 “oq” 队列中等待通过 SocketPair 双工信道发送到应用目标窗口中。最后当事件发送给具体的应用目标窗口后,会将事件移动到 WaitQueue 也就是 “wq” 中等待目标应用处理事件完成,并开启倒计时,如果目标应用窗口在 5S 内没有处理完成此次触控事件,就会向 system_server 报应用 ANR 异常事件。以上整个过程在 Android 系统源码中都加有相应的 systrace tag,如下 systrace 截图所示:
    input 事件处理 1

接着上面的流程继续往下分析:当 input 触控事件传递到桌面应用进程后,Input 事件到来后先通过 enqueueInputEvent 函数放入 “aq” 本地待处理队列中,并唤醒应用的 UI 线程在 deliverInputEvent 的流程中进行 input 事件的具体分发与处理。具体会先交给在应用界面 Window 创建时的 ViewRootImpl#setView 流程中创建的多个不同类型的 InputUsage 中依次进行处理(比如对输入法处理逻辑的封装 ImeInputUsage),整个处理流程是按照责任链的设计模式进行。最后会交给 ViewpostImeInputUsage 中具体进行处理,这里面会从 View 布局树的根节点 DecorView 开始遍历整个 View 树上的每一个子 View 或 ViewGroup 界面进行事件的分发、拦截、处理的逻辑。最后触控事件处理完成后会调用 finishInputEvent 结束应用对触控事件处理逻辑,这里面会通过 JNI 调用到 native 层 InputConsumer 的 sendFinishedSignal 函数通知 InputDispatcher 事件处理完成,从触发从 “wq” 队列中及时移除待处理事件以免报 ANR 异常。
input 事件处理 2

桌面应用界面 View 中在连续处理一个 ACTION_DOWN 的 TouchEvent 触控事件和多个 ACTION_MOVE,直到最后出现一个 ACTION_UP 的 TouchEvent 事件后,判断属于 onClick 点击事件,然后透过 ActivityManager Binder 调用 AMS 的 startActivity 服务接口触发启动应用的逻辑。从 systrace 上看如下图所示:
input 事件处理 3

  • 27
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值