framework的学习,需要掌握到什么程度?
Loader 开机引导程序
由BootLoader引导开机
当手机处于关机状态时,长按电源进行开机。
原因:主板通电之后,开启引导烧录在存储器里的预设代码,然后加载引导程序到内存中,这个主要做一些内存检测以及硬件参数的初始化过程
linux kernel 硬件抽象层
开机引导程序执行完成之后,开始加载linux kernel 核心代码。
这层主要是加载一些硬件驱动,如相机驱动,视频驱动,显示屏驱动,输入驱动
上层应用想要调用这些硬件驱动的话,为了解决各大应用商提供的驱动不统一的问题,由硬件抽象层来适配,提供统一的api,
C++ FrameWork
硬件驱动加载完成之后会加载linux 中第一个用户进程 init 进程,还会孵化出adbd deme进程,以及log deme进程。
这就是为什么在运行时可以断点调试和输出日志的原因,就是因为这两个守护进程的存在
Android Framework
在ZygoteInit main方法里面还启动了SystemServer 系统服务进程
init进程
是Linux系统中用户空间的第一个进程,进程号为1(pid=1),由于Android是基于Linux内核的,所以init也是Android系统中用户空间的第一个进程。
init进程的作用
- 孵化出ueventd、logd、healthd、installd、adbd、lmkd等用户守护进程(守护进程一般以d结尾)
- 提供property service(属性服务)来管理Android系统的属性。
- 启动servicemanager(binder服务管家)、bootanim(开机动画)等重要服务
- 孵化出Zygote进程,Zygote进程是Android系统的第一个Java进程(即虚拟机进程),Zygote是所有Java进程的父进程,Zygote进程本身是由init进程孵化而来的。
Zygote进程
Init进程启动后,最重要的一个进程就是Zygote进程,Zygote是所有应用的鼻祖。SystemServer和其他所有Dalivik虚拟机进程都是由Zygote fork而来。
Zygote进程由app_process启动,Zygote是一个C/S模型,Zygote进程作为服务端,其他进程作为客户端向它发出“孵化-fork”请求,而Zygote接收到这个请求后就“孵化-fork”出一个新的进程。
是一个承上启下,连接Java世界和Linux 世界,zygote 进程创建完成之后就进入Java世界了,会调用ZygoteInit java 类,在这个类的入口方法,会创建Android Framework 系统服务,System Server 进程,所有app的进程都是由Zygote 进程孵化而来的
app进程创建完成之后,都会由ZygoteInit 反射调用app进程的入口类,也就是ActivityThread这个类,从而使app得以启动
1. 我们知道Java调用C++可以通过JNI。那么C++是如何转到Java的,也就是说ZygoteInit.java这个类是如何被调用的?
在java中,class文件是由ClassLoader来加载的,但实际上,ClassLoader在加载java文件的过程中,也是通过C++来完成的(Bootstrp loader就是用C++写的,具体可以去看java类加载过程及机制,Java类加载器ClassLoader总结),所以C++如果想要访问java文件的话,是非常轻松的2. 进程间通信通常使用的是binder,为什么SystemServer和Zygote之间通信要采用Socket
UNIX上C++程序设计守则3:多线程程序里不准使用fork
Binder通讯是需要多线程操作的,代理对象对Binder的调用是在Binder线程,需要再通过Handler调用主线程来操作。
害怕父进程binder线程有锁,然后子进程的主线程一直在等其子线程(从父进程拷贝过来的子进程)的资源,但是其实父进程的子进程并没有被拷贝过来,造成死锁。
3.为什么一个java应用一个虚拟机?
android为每个程序提供一个vm,可以使每个app都运行在独立的运行环境,使稳定性提高。每个程序一个虚拟机,各个程序之间也不可以随意访问内存,所以此类木马病毒几乎没有。
4.什么是Zygote资源预加载?
预加载是指在zygote进程启动的时候就加载,这样系统只在zygote执行一次加载操作,所有APP用到该资源不需要再重新加载,减少资源加载时间,加快了应用启动速度,一般情况下,系统中App共享的资源会被列为预加载资源。
zygote fork子进程时,根据fork的copy-on-write机制可知,有些类如果不做改变,甚至都不用复制,子进程可以和父进程共享这部分数据,从而省去不少内存的占用。5. Zygote为什么要预加载
应用程序都从Zygote孵化出来,应用程序都会继承Zygote的所有内容。
如果在Zygote启动的时候加载这些类和资源,这些孵化的应用程序就继承Zygote的类和资源,这样启动引用程序的时候就不需要加载类和资源了,启动的速度就会快很多。
开机的次数不多,但是启动应用程序的次数非常多。6.Zygote预加载的原理是什么?
zygote进程启动后将资源读取出来,保存到Resources一个全局静态变量中,下次读取系统资源的时候优先从静态变量中查找。
//1从classpath路径下搜索ZygoteInit这个类,并返回该类的Class对象,进程创建创建完成后会固定加载这个类
jClass clazz = (*env)->Findclass(env, "com/ android/internal/os/zygoteInit"):
//2获取类的默认构造方法ID
jmethodID mid_construct = (*env) ->GetMethodID (env, clazz,
"" "(v");
//3创建该类的实例
jobject jobj = (*env)->NewObject(env, clazz,mid_construct);
//4查找实例方法的ID
jmethodID mid_instance = (wenv)->GetMethodID(env, clazz, "main", "(Ljava/lang/String; I
1/5调用对象的实例方法
A
jstring str_arg = (*env)->NewstringUTF(env,”我是实例方法");
(wenv) ->CallVoidMethod (env, jobj,mid_instance, str_arg, 200) ;
Zygoteinit main 方法里做了四件事情
- 资源的预加载,加载系统的class文件,资源文件动态库。上层应用会使用大量的系统资源,如果在app启动的时候再去加载的话,会造成app启动缓慢,预加载可以提高app启动速度,也能共享这些资源文件
- 通过main方法传入的args 数组,判断是否有包含start-system-server 这个参数,来来决定是否启动systemserver 进程,该进程是Android framework 的核心进程
- 创建一个socket 服务,用来接受AMS 进程创建请求的
- socket 服务创建完成之后,进入阻塞状态,等待客户端的连接
ZygoteInit-java
public static void main(String argv []){
//1.预加载frameworks/base/preloaded-classes和framework_res.apk资源
preloadClasses();
preloadResources();
preloadSharedLibraries();
//2.启动system_server进程。该进程是framework的核心。
if (argv [1].equals("start-system-server")) {
startSystemServer();
}
//3.创建Socket服务
registerZygoteSocket();
//4.进入阻塞状态,等待连接,用以处理来自AMS申请进程创建的请求
runSelectLoopMode();
}
}
SystemService进程
在zygoteInit main 方法中启动了SystemService系统服务进程,这个进程创建成功之后
通过反射的方法启动SystemServer.java的main()方法
在他的main 方法里面会启动非常多的系统服务,比如 ActivityManagerService、PowerManagerService、DisplayManagerService、PackageManagerService、WindowManagerService、LauncherAppsService等多个核心系统服务
这些系统服务大致可分为三类
这些系统服务构成了Android的framework层,为app日常开发和运行提供了保障
当这些服务启动完成之后;其中的ActivityManagerService最终会调用systemReady()方法。是时候去通知ActivityManager去启动第三方应用了
- 手机开机后,引导芯片启动,开启引导烧录在存储器里的预设代码,然后加载引导程序到内存中,BootLoader检查RAM,初始化硬件参数等功能
- 硬件参数初始化完成后,进入到Kernel层,Kernel层主要加载一些硬件设备驱动(如相机驱动,视频驱动,显示屏驱动,输入驱动),初始化进程管理等操作。在Kernel中首先启动swapper进程(pid=0),用于初始化进程管理、内管管理、加载Driver等操作,再启动kthread进程(pid=2),这些linux系统的内核进程,kthread是所有内核进程的鼻祖;
- Kernel层加载完毕后,硬件设备驱动与HAL层进行交互。初始化进程管理等操作会启动init进程 ,这些在Native层中;
- init进程(pid=1,init进程是所有进程的鼻祖,第一个启动)启动后,会启动adbd,logd等用户守护进程,并且会启动servicemanager(binder服务管家)等重要服务,同时孵化出zygote进程,这里属于C++ Framework,代码为C++程序;
- zygote进程是由init进程解析init.rc文件后fork生成,它会加载虚拟机,启动System Server(zygote孵化的第一个进程);SystemServer负责启动和管理整个Java Framework,包含ActivityManager,WindowManager,PackageManager,PowerManager等服务;
- zygote同时会启动相关的APP进程,它启动的第一个APP进程为Launcher,然后启动Email,SMS等进程,所有的APP进程都有zygote fork生成。
进程的入口类一般有两种:
- native 进程的入口类一般是init
- Java进程的入口类一般都是main 方法
总结:Zygote 进程创建成功之后,会进入到Java世界,第一个创建的是ZygoteInit 这个Java类,在它的入口方法里主要做了系统资源的预加载,以提高App 启动的响应速度,同时也是为了App 运行时能够共享系统的资源,其次它还会启动系统服务进程SystemService,这个进程的入口类是SystemService.java,而这个类里面一个启动了一百多个服务,共同为App 运行提供保障服务,当所有的服务启动完成之后,会通知ActivityManagerService去启动launcher应用
负责管理四大组件和进程,包括生命周期和状态切换。它的systemReady()方法,是Launcher应用启动的入口。
把原先在ActivityManagerService 对Activity生命周期管理和调度等工作全部转移到此,由它来管理Activity 的工作(Android10新增)。
调用PackageManagerService去查询手机系统中已安装的所有的应用,哪一个是符合launcher标准,且得到一个Intent 对象,并交给ActivityStarter。
得到这个Intent 对象之后交由ActivityStarter启动器进一步的启动,在它里面会做启动之前的各项检查,比如检查Activity 有没有在清单文件中注册,class文件是否存在,这个activity 是否有权限启动等。
在Activity 启动的时候就会涉及到进栈和出栈的操作,在Service端是无法拿到Activity 实例的,而ActivityRecrd 是在Service端对Activity 的一种映射,它里面记录和存储了Activity 所有的信息。
代表一个Activity。
任务栈,记录一个或多个ActivityRecord 的实例。
Activity栈,内部维护一个ArrayList
任务栈的管理者,应用在运行的时候会有一个或多个任务栈,这些任务栈会交给ActivityStack 来管理。
负责管理各个Activity栈,内部维护一个ArrayList
由于手机在运行中会启动一个或多个应用,这个时候会产生一个或多个ActivityStack 对象,用来管理Launcher和非Launcher应用的ActivityStack实例。
内部持有一个ActivityStack,而ActivityStack内部也持有ActivityStackSupervisor,相当于ActivityStack的辅助管理类
职责是把原先在ActivityManagerService钟启动进程的工作转移到此(Android10新增)。
建立起与Zygote 进程的socket 链接,并且把创建进程所需要的参数给发送过去,
负责调用Activity和Application生命周期。
ActivityStackSupervisor -> ActivityStack -> TaskRecord -> ActivityRecord
BootRom -> BootLoader -> Linux Kernel -> Init -> Zygote -> SystemServer -> Launcher
1. ActivityManagerService.java 调用 systemReady() 系统服务启动完毕后,launcher应用的入口
//启动HomeActivity(即Launcher应用的入口Activity):本意是在所有的屏幕上启动桌面应用
//因为Android10.0开始是支持多屏幕的,比如手机屏幕,虚拟投屏,外接屏幕
mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady");
2. 这里的mAtmInternal是ActivityTaskManagerInternal,是一个抽象类。真正的实现类在ActivityTaskManagerService的内部类LocalService中,进而调用startHomeOnAllDisplays(),在这里会做一层转发,进而委托给RootActivityContainer
3. 在RootActivityContainer的startHomeOnAllDisplays()中调用PackageManagerService中去查询手机系统中已安装的所有的应用,哪一个符合launcher标准,且得到一个Intent对象,并交给ActivityStarter。
4. ActivityStarter中调用startActivityUnchecked() 进行清单文件校验,启动权限检查,根据启动模式和Intent.flag计算出该Activity所属的任务栈并加入,但此时并不会显示
5. ActivityTask中调用resumeTopActivityInnerLocked(),启动新的Activity之前会把当前可见的Activity暂停,计算待启动的Activity所属进程是否存在
6. 在ActivityStackSuperVisor.java类的startSpecificActivityLocked()去判断进程是否存在,如果存在,调用realStartActivityLocked去启动Activity,否则调用ActivityManagerIntenal::startProcess去创建进程
7. ActivityManagerService$LocalService.java中startProcess(),委派给ProcessList来负责进程的创建
8. ProcessList中调用startProcessLocked()
9. ProcessList中调用startProcess() 中 调用annovaote.getProcess().start()
10. ZygoteProcessor.java 中的attemptZygoteSendArgsAndGetResult()
11. ActivityThread.java 进入应用的进程