Android系统架构
Android系统大体可以分为四层,从下往上依次是:
- Linux内核层:包含了Linux内核和一些驱动模块(比如USB驱动,Camera驱动,蓝牙驱动等)。
- Libraries层:这一层提供动态库(也叫共享库)、Android运行时库,Dalvik虚拟机等。从编程语言角度来看,这一层大部分都是用C或C++写的,所以也可以简单的把它看成是Native层。
- Framework层:这一层大部分用Java语言编写,它是Android平台上Java世界的基石。
- Application层:与用户直接交互的就是这些应用程序,他们都是用Java开发的。
Java世界和Native世界交互
- Native层包括Init、Audio(包括AudioTrack,AudioFlinger和AudioPolicyService)、Surface系统(包括Surface和SurfaceFlinger)、常用类(包括RefBase、sp、wp等)Vold和Rild。
- Java Framework层包括Zygote、System_server以及Java中的常用类(包括Handler和Looper等)。
- Java Application层包括MediaProvider和Phone。
JNI
JNI是Java native interface的缩写,通俗而言,JNI可以实现:
- JAVA程序中的函数可以调用Native语言写的函数,Native一般指的是C/C++编写的函数。
- Native程序中的函数可以调用Java层的函数,也就是说在C/C++程序中可以调用Java的函数。
以MediaScanner为例了解JNI
- Java世界对应的是MediaScanner,而这个MediaScanner类有一些函数需要由Native层来实现。
- JNI层对应的是libmedia_jni.so,media_jni是JNI库的名字,其中下划线钱的media是Native层库的名字,这里就是libmedia库,下划线后的jni表示他是一个JNI库。
- Native层对应的libmedia.so。
- MediaScanner将通过libmedia_jni.so和Native层的libmedia.so交互。 tips:MediaScanner是Android平台中多媒体系统的重要组成部分,它的功能是扫描媒体文件,得到诸如歌曲市场,歌曲作者等媒体信息。
public class MediaScanner implements AutoCloseable {
static {
/* 加载对应的JNI库,media_jni是JNI库的名字,在实际加载动态库的时候会将其扩展成libmedia_jni.so,在Windows平台上则扩展为media_jni.dll */
System.loadLibrary("media_jni");
native_init();
}
/* 声明一个native,native为java的关键字,表示他将由JNI层完成 */
private static native final void native_init();
动态注册的Native函数什么时候被调用? 当Java层通过System.loadLibrary加载完JNI动态库之后,紧接着会查找该库中一个叫JNI_Onload的函数,如果有,就调用它,而动态注册的工作就是在这里完成的。 所以如果想使用动态注册方法,就必须实现JNI_OnLoad函数,只有在这个函数中才有机会完成动态注册的工作。静态注册的方法则没有这个要求,但建议还是实现这个JNI_OnLoad函数,因为有一些初始化工作是可以在这里做的。
JNI层代码中一般要包含jni.h这个头文件,也可以包JNIHelp.h文件。
demo:processFile函数
// Java层processFile有三个参数
processFile(String path, String mimeType, MediaScannerClient client);
// JNI层对应的参数,最后三个参数与processFile的参数对应
android_media_MediaScanner_processFile(JNIEnv *env, jobjcet thiz,
jstring path, jstring mimeType, jobject client);
从上面这段代码可以发现:
- Java的String类型在JNI层对应为jstring类型。
- Java的MediaScannerClient类型在JNI层对应为jobjcet。 那么问题来了,为什么Java层只有三个函数,到了Native层变成了5个函数? 其中jobjcet代表Java层的MediaScanner对象,它表示是在哪个MediaScanner对象上调用processFile。
JNIEnv
JNIEnv是一个与线程相关的代表JNI环境的结构体。
基于上图可知,JNIEnv实际上就是提供了一些JNI系统函数,通过这些函数可以做到
- 调用Java的函数。
- 操作jobjcet对象等很多事情。
深入理解init
涉及的源码
- system/core/init/init.c
- system/core/init/parser.c
- system/core/init/builtins.c
- system/core/init/keywords.h
- system/core/rootdir/init.rc
- system/core/init/properties_service.c
- system/core/bionic/libc_init_common.c
- system/core/bionic/libc_init_dynamic.c
- system/core/libcutils/properties.c
init进程
init是一个进程,确切的说,他是Linux系统重用户空间的第一个进程。由于Android是基于Linux内核的,所以init也是Android系统中用户空间的第一个进程。init进程作为一号进程,被赋予了很多重要的工作职责,比较重要的两个是:
- init进程负责创建系统中的几个关键进程,尤其是zygote,它是java世界的开创者。
- Android系统有很多的属性,于是init就提供了一个property service(属性服务)来管理它们。
zygote进程
zygote创建Java世界的步骤:
- 创建AppRuntime对象,并调用它的start,此后的活动则由AppRuntime来控制。
- 调用startVm创建java虚拟机,然后调用startReg来注册JNI函数。
- 通过JNI调用com.android.internal.os.ZygoteInit类的main函数,从此进入了java世界。
- 调用registerZygoteSocket,调用这个函数,他可以响应子孙后代的请求,同时zygote调用preloadClasses和perloadResources为Java世界添砖加瓦。
- 调用startSystemServer分裂一个子进程system_server来为Java世界服务。
- zygote完成了Java世界的初创工作,下一步调用runSelectLoopMode后,便沉沉的睡去了。
SystemServer
创建了surfaceFlinger服务、电源管理服务、WindowManager服务、ActivityManager服务。
SystemServer的总结:
- ZygoteInit调用startSystemServer创建system_server进程
- 调用bandleSystemServerProcess完成自己的使命。
- handleSystemServerProcess抛出异常,最终调用com.android.server.SystemServer的mainhanshu .
- main函数加载libandroid_server.so并调用native的init1函数。
- init1函数通过JNI调用,com.android.server类的init2函数,init2函数创建一个线程,用于加载各种service.
- init1函数最终加入Binder通信系统。
zygote分裂
可以看到最终还是zygote创建了子进程。
Looper和Handler类分析
就应用程序而言,Android系统中Java的应用程序和其他系统上相同,都是考消息驱动来工作的,它们大致的工作原理如下:
- 有一个消息队列,可以王这个消息队列中投递消息。
- 有一个消息循环,不断的从消息队列中去除消息,然后处理。
binder
Binder是Android系统提供的一种IPC机制。在基于Binder通信的C/S架构体系中,除了C/S架构所包括的Client和Server端外,Android还有一个全局的ServiceManger端,它的作用是管理系统中的各种服务(service)。Client,Server和ServiceManger这三者之间交互关系。
一个Server进程可以注册多个Service。
MediaServer
MediaServer是系统诸多重要Service的栖息地,它们包括 AudioFlinger:音频系统中的核心服务 AudioPolicyService:音频系统中关于音频策略的重要服务 MediaPlayerService:多媒体系统中的重要服务 CameraService:有关摄影/拍照的重要服务