众所周知,Android是一个基于Linux实现的操作系统。但对于Linux内核来说,Android也仅仅只是一个运行在内核之上的应用程序,与其他运行在内核之上的应用程序没有任何区别。所以Android也需要运行环境,需要Linux内核在启动完成后加载Android Framework运行所需要的资源。当Framework完成初始化后才能继续启动相应的APK应用程序。
一、Framework启动分析
Framework运行的第一个Java虚拟机进程为zygote(对应具体程序为app_process,该程序位于system/bin目录下),zygote是APK应用程序的父进程,此后所有的虚拟机进程都由zygote创建。
zygote有两个功能:
- 接受请求创建新的Dalvik进程
- 共享类和资源(需要加载的资源在preload-classes文本文件中声明)
对于Android来说,每一个应用程序对应着一个Linux 进程,每一个进程都是一个Dalvik虚拟机,Dalvik虚拟机是一种类似Java虚拟机的实现。
zygote进程在启动时会预先装载共享类和共享资源,这些类及资源实际上就是SDK中定义的大部分类和资源。当zygote进程创建新进程时,新的APK进程只需装载自身类和资源即可。共享的资源位于同一段物理内存空间中,zygote进程及其创建的Dalvik进程都可以访问,这就解决了多个APK共享Framework资源的问题。(更多关于资源的讨论请看Android资源加载机制详解)
zygote创建的第一个进程名为SystemServer,SystemServer创建了一个Socket客户端,并创建了ActivityManagerService线程来管理该客户端。之后所有的Dalvik进程都是由该客户端启动的。当需要启动新的APK进程时,AmS会通过该Socket客户端向zygote进程的Socket服务端发送一个启动命令,然后zygote就会创建出新的应用程序进程。
1. 系统服务
SystemServer进程内部运行着APK应用中能够直接交互的大部分系统服务。比如WindowManagerService(简称WmS),ActivityManagerService(简称AmS),PackageManagerService(简称PmS)等。这些系统服务都是以一个线程的方式生存在SystemServer进程中。SystemServer启动的各种服务线程如下所示:
- PowerManagerService电源管理服务
- ActivityManagerService管理Activity
- PackageManagerService程序包管理服务
- BatteryService电池管理服务
- LightService自然光强度感应传感器服务
- VibratorService震动传感器服务
- ClipboardService剪切板服务
- NetworkManagerService网络管理服务
- InputMethodManagerService输入法管理服务
- BluetoothService蓝牙服务
- …
2. Dalvik与Android Runtime(ART)
Dalvik是一种类Java虚拟机的实现,其执行的是class优化后的dex字节码文件。Dalvik通过一个JIT(Just-In-Time)编译器去解释字节码,但执行效率并不理想。
自动Android 4.4后安卓就内置了ART实现,从5.0开始更是直接抛弃了Dalvik全面使用ART。ART通过AOT机制(Ahead-Of-Time)在应程序安装时将字节码编译成机器语言,因此执行速度更快。并且ART也完全兼容Dalvik。
二、应用程序启动分析
在计算机的世界里每个程序都有一个main()方法,程序代码都是从main()方法开始执行,Android应用程序也不例外。
当应用程序启动时系统首先会为其创建一个Dalvik虚拟机进程,并加载APK应用程序类及资源。然后,APK应用程序从ActivityThred的main()方法处开始执行。
首先main()方法为UI线程创建一个消息队列(MessageQueue)。然后创建ActivityThread对象,ActivityThread初始化时会创建一个Handler和一个Binder。Binder负责接收远程AmS的IPC调用,接收到调用后通过Handler将消息发送到消息队列,UI主线程会异步地从消息队列中取出消息并执行相应操作,比如start,stop,pause等。
接着UI主线程调用Looper.loop()方法进入消息循环体,进入后就会不断从消息队列中读取并处理消息。
ActivityThread是APK程序的UI线程,也就是我们所说的主线程。主线程要求执行时间不能超过5秒,超过就会报ANR,这个5秒就是UI线程消息队列循环一次的最大时间阈值。
当ActivityThread接收到AmS发送的start某个Activity消息后,就会创建指定Activity对象。Activity又会创建PhoneWindow类,PhoneWindow创建DecorView,DecorView内部包含Activity.setContentView(R.layout.xxx)指定的布局。
创建完成后,Activity需要将布局显示在屏幕上,于是调用WindowManager.addView()方法。WindowManager为Activity对应的窗口(Window)创建一个ViewRoot对象(每一个窗口对应一个ViewRoot对象),然后调用WmS提供的远程接口将窗口(布局)显示到屏幕上。至此应用程序中的Activity就显示在屏幕上了。
1. APK中的线程
在现在操作系统中,任何应用程序都运行在线程之中。客户端在启动时系统会首先为其分配一个线程,然后该线程从程序的入口处开始执行。对于包含Activity的客户端程序,至少包含三个线程:
1. 主线程,又称UI线程,也就是应用程序本身所在的线程,主要用于处理用户消息以及绘制程序界面。
2. ViewRoot.W对象对应的线程,Activity启动后会创建一个ViewRoot.W对象,W对象继承自Binder,因此会启动一个对象负责接收Linux Binder驱动的IPC调用。
3. ApplicationThread对象所对应的线程,该对象也继承自Binder,因此也会启动一个线程用于IPC调用。
2. 自定义Thread与UI线程的区别
对于UI线程,在启动时已经创建了消息队列(MessageQueue),既在ActivityThread的main()方法中已经使用Looper.prepareMainLooper()方法为UI线程添加了Looper对象。程序员可以直接在Activity中定义Handler对象发送处理消息。
而对于普通线程,需要手动调用Looper.prepareLooper()方法为Thread创建消息队列,这样才能定义Handler处理消息。即不能直接在Thread中定义Handler。
从使用场景上说,就是不能直接给Thread对象发消息,但是却可以给UI线程发消息。
具体Handler的使用及解释请移步Android异步通信机制详解
三、一些重要的类:
下面是一些系统中常见的类及其功能介绍,通读一遍会对理解Android源码很有帮助。
1. 两个重要的系统服务
- WindowManagerService,管理所有的窗口,包括创建删除窗口,隐藏显示窗口,决定窗口的层级顺序,指定当前正在与应用程序交互的窗口。
- ActivityManagerService,内存管理,进程管理,统一调度所有应用程序中的Activity。所有Activity的启动必须通知AmS,AmS也决定了某个进程会不会被杀死。
2. 两个消息处理类
- KeyQ类:该类是WmS的内部类,继承自KeyInputQueue,一旦创建就立即启动一个线程,该线程会不断读取用户UI操作消息,比如按键、触摸屏、等,并把这些消息放到一个消息队列QueueEvent类中。
- InputDispatcherThread类:该类一旦创建也会启动一个线程,该线程会不断地从QueueEvent中读取用户消息,并进行一定的过滤,过滤后发送给当前活动的而应用程序中。
3. 其他常用类
- ActivityThread类,应用程序主线程类,所有的APK都有且仅有一个ActivityThread类,程序的入口为该类中的static main()方法,ActivityThread所在的线程即为UI线程或主线程。
- ViewRoot类,WmS管理客户端窗口时,需要通知客户端进行某种操作,这些都是通过IPC调用来完成的,而客户端在接收到IPC后,都需要将该调用转换成本地异步调用。ViewRoot继承自Handler,其作用就是将远程接口调用转换成本地异步调用。
- W类,ViewRoot内部类,继承自Binder,Wms通知客户端时就是该类进行IPC调用。该类内部会向其所在的ViewRoot发送一个Handler消息,以便进行异步处理。
- Window类,是一个抽象类,提供了一套操作窗口的通用方法(Callback接口)。Activity就是通过实现这个Callback接口来获得对消息的处理机会。因为消息首先会由WmS传递给窗口中的View树,View树不处理消息的话才会传递给Window,这时候就会回调Activity实现的Callback方法使Activity有机会处理事件。
- PhoneWindow类,是Window的具体实现类,其内部保存有DecorView对象。
- DecorView类,应用程序视图的根布局View,该类继承自FrameLayout。客户端使用WindowManager添加窗口就是将该类(及其子View)添加到WmS中,并将其所代表的视图绘制到屏幕上。
- Activity类,该类APK程序最小运行单元。ActivityThread根据用户的操作选择加载哪个Activity。
- WindowManager类,该类是WindowManagerService在客户端的管理类,客户端通过WindowManager申请创建一个窗口,而具体创建窗口的任务是由WMS来完成的。