Android冷启动流程
1.input事件处理
input事件的重点在于 InputReader
和 InputDispatcher
,这两个都是SystemServer
进程中的两个 native
循环线程。
native
循环线程是指在 Android 系统中使用本地代码编写的循环线程,通常用于执行高性能或与硬件相关的任务
大概流程如下:
InputReader:从 EventHub 读取输入事件,并交给 InputDispatcher 处理。
InputDispatcher:接收事件后进行包装,寻找目标窗口并分发事件。
InboundQueue (IQ):存放从 InputReader 获取的输入事件。
OutboundQueue (OQ):存放即将分发给各个应用窗口的事件。
WaitQueue (WQ):记录已分发给应用但尚未处理完成的事件。
PendingInputEventQueue (AQ):存放应用需要处理的输入事件,表示事件已传递到应用进程。
deliverInputEvent (DIE):表示应用的 UI 线程被输入事件唤醒。
InputResponse (IR):表示输入事件的处理区域,包括一个 Input_Down 事件、多个 Input_Move 事件和一个 Input_Up 事件。
App 响应:应用内部在其界面视图树中处理输入事件。
疑问:
上图为input事件走向。
在放入aq队列之后,唤醒应用主线程,在deliverInputEvent流程中进行时间的分发和处理,先交给window创建时的多个不同类型的InputStage中一次进行处理。
InputStage可以理解为按照策略在View和窗口之间传递,比如输入法处理逻辑的封装(ImeInputStage)
InputStage是责任链设计模式
之后进行具体处理时,会从View布局树根节点遍历,进行分发拦截处理逻辑。
事件处理结束之后,调用finishInputEvent结束处理逻辑,并通知inputDishpatcher,从wq队列中移除事件,以免ANR。
判断为点击事件之后,通过ActivityManager Binder调用AMS的startActivity服务拉起应用启动逻辑(这里从systemserver能看到)
2.应用进程创建启动
2.1 Pause桌面
上面讲到SystemServer开始执行StartActivity,开始执行StartActivityInner操作
在StartActivityInner中,会检查当前的activity是否是resume状态,是否是需要打开的应用
如果不是,那就通知当前activity执行pause状态
接着当前activity执行完onPause生命周期后,binder通知系统完成操作
AMS收到后继续进行启动应用操作,判断要启动的应用进程是否存在
如果不存在,开始创建应用进程(Start proc: com.jio.myjio)
2.2 创建应用进程
安卓系统中的进程都是由Zygote进程fork出的,需要创建新进程时,AMS会通过socket链接并通知zygote开机时创建的socket服务端,之后fork。流程如下图:
这方面涉及到开机流程详细可以去搜索了解,或者之后的文章提及
上图先链接到zygote服务端,发送socket请求,请求中包含了创建进程时的一些参数等信息,返回值包含了进程的pid号。
应用进程初始化,主要做了一下一些事情:
设置默认的java异常处理机制。
JNI调用,启动了Binder线程池(自己创建的)。
通过反射调用main方法,下面看看main函数做了什么:
创建并启动主线程的Loop循环。
attach进程到AMS中(通过binder注册进程)。
主线程初始化完成之后,可以开始接收Messege由handler进行处理。
在注册进程到AMS阶段,attachapplication过程中会调用bindapplication初始化函数。
bindapplication会做如下事情:
根据将要打开的应用创建对应apk的LoadApk对象。
创建应用的Context(上下文)。
创建类加载器触发art虚拟机加载应用的Dex文件。
通过LoadApk加载应用的Resource资源。
创建应用Application对象。
调用oncreate开始执行生命周期。
2.3 Activity创建与初始化
2.3.1 ActivityStart
创建Activity的Context对象。
通过反射创建Activity对象。
执行Activity的attach,会创建应用窗口的phoneWindow对象并设置WindowsManager。
这一步可以理解为讲Activity与Application以及Context联系起来。
phoneWindow是Activity窗口容器,负责管理窗口视图层次结构以及各种界面元素。
WindowsManager是在phoneWindow中使用,用来管理和渲染应用的接口
执行Activity的oncreate生命周期函数,并在setContextView中创建窗口的DecorView。
DecorView(装饰视图) 是整个窗口的根视图
DecorView
内部的层次结构大致如下:最外层是
FrameLayout
,包含了ContentView
和其他装饰元素。ContentView
是实际显示应用UI的部分,由setContentView
传入的布局文件生成。
2.3.2 ActivityResume
执行应用Activiity的onResume生命周期函数。
执行刚才的windowManager.addView开启视图绘制逻辑。
创建Activity的ViewRootImpl对象。
它是
View
系统和Window
系统之间的桥梁每个
Activity
都有一个与之关联的ViewRootImpl
对象,用于处理窗口的绘制、输入事件的分发、以及窗口动画等。执行VewRootImpl的setView开启UI界面绘图动作。
2.3.3 应用UI布局与绘制
我们现提一下如Activity
、PhoneWindow
、DecorView
、ViewRootImpl
、WindowManager
它们之间的关系与职责。
Window:
抽象类,通过控制
DecorView
提供标准的 UI 方案,比如背景、标题、虚拟按键等。PhoneWindow 是
Window
的唯一实现类,Activity
创建时生成。应用的内容会装载到其内部的mDecor
(即DecorView
)中。
DecorView:
是整个界面布局
View
树的根节点,负责承载和管理所有界面元素。
WindowManager:
是一个接口,继承自
ViewManager
,提供了对View
的基本操作方法。WindowManagerImpl 是它的实现类,内部通过
WindowManagerGlobal
来操作View
。
WindowManagerGlobal:
全局单例,负责将
View
添加到窗口中,通过ViewRootImpl
管理View
的显示和更新。
ViewRootImpl:
是所有
View
的父级,负责管理View
的绘制以及与系统窗口管理服务(WMS)的交互。内部包含
mView
(即DecorView
)、mSurface
(画布),和Choreographer
(用于管理帧渲染的时序)。Choreographer
的引入,主要是配合系统Vsync
垂直同步机制(Android“黄油计划”中引入的机制之一,协调APP生成UI数据和SurfaceFlinger
合成图像,避免Tearing画面撕裂的现象),给上层 App 的渲染提供一个稳定的Message
处理的时机,也就是Vsync
到来的时候 ,系统通过对Vsync
信号周期的调整,来控制每一帧绘制操作的时机。Choreographer
扮演 Android 渲染链路中承上启下的角色:承上:负责接收和处理 App 的各种更新消息和回调,等到
Vsync
到来的时候统一处理。比如集中处理 Input(主要是 Input 事件的处理) 、Animation(动画相关)、Traversal(包括measure、layout、draw
等操作) ,判断卡顿掉帧情况,记录 CallBack 耗时等;启下:负责请求和接收 Vsync 信号。
它是应用 UI 渲染的核心,负责将界面绘制到
mSurface
上,并协调vsync
信号以确保流畅的渲染。
2.3.4 我们继续讲解setView
requestLayout():
触发
measure
、layout
和draw
,即界面的重新绘制流程。
与 WMS 的交互:
通过 Binder 调用系统窗口管理服务(WMS)的
addWindow
接口,添加并注册应用窗口。传入
inputChannel
用于接收触控事件。此步骤完成后,View
就可以显示到屏幕上了。
事件接收:
创建
WindowInputEventReceiver
对象,处理应用窗口的触控事件。
View 的层次结构:
调用
view.assignParent(this)
,将DecorView
的父类设置为ViewRootImpl
。虽然ViewRootImpl
不是View
,但它是所有View
的顶层父级。
而这里开始,就和我之前讲过的出帧链接在一起,大家可以看我那一片文章的详情。