学习书籍:Android底层开发实践
使用代码:AOSP源码
带@的行表示关键点;
橙色背景的文字表示:整编log分析的关键字
绿色“待补充”文字表示:有待补充内容
-----第三章 Android系统开发环境搭建
3.1 Android上的开发工作
3.1.1 Android的移植开发
1. Linux驱动
@p47
@工作在系统内核空间
2. Android系统硬件抽象层
@p47
@工作在用户控件
@向下调用Linux中的驱动程序,向上提供接口
3. Android移植的几个主要类型
@p48第2段,第3段:电源管理
3.1.2 系统开发
1. JNI库的开发
JNI库是Java应用程序访问其他语言,尤其是中低级语言的接口;
一般将电源管理、传感器等系统独有设备的用户态驱动放入JNI中;
除此之外,高级视频编解码算法、压缩解压等Android自身不提供的算法也被封装在JNI中;
3.1.3 应用开发
若需要使用特定的JNI库,可以使用Android NDK,并将NDK便已生成的.so文件封装到.apk文件中;注意,.so文件不能跨平台,因此要为不同的平台编译不同的so文件;
3.2 Android系统架构
3.2.1 软件结构
1. Linux操作系统及驱动
Android系统运行于Linux kernel之上;
Android系统的Linux kernel控制包括安全、存储器管理、程序管理、网络堆栈、驱动程序模型等;
2. Android系统程序库
(1)Bionic(p49最后一段)
基础C库源代码,Android根据Linux系统glibc库改造的C/C++库同时包含了Webkit和Surface flinger;
(2)Dalvik虚拟机(p50第一段)
一种Java虚拟机,运行一种称为.dex格式的文件;
(3)HAL(p50第2段)
目的是为了把Android framework和Linux kernel隔开;
(4)HAL Stub(p50-3)
Sub以*.so文件的形式存在,向HAL “提供” 操作函数;
HAL中包含了很多Stub;
3. Android Java程序库
@p50最后一段
3.2.2 源代码的结构
1. Android的工程目录
(1)核心工程(p51-1):...
(2)扩展工程(p51-2):包含在externel文件夹中
有很多关于工具库包的解释
2. Android中的Java程序包
(1)主要包括(p53-1):应用程序和内容提供器两部分;
有一个表对其中的文件夹做了详细解释)
有一个表对其中的文件夹做了详细解释)
3.3 搭建开发环境
3.3.1 搭建编译环境
1. 安装VirtualBox
@p54-1
(1)网址:www.virtualbox.org
(2)4GB以上内存,200GB虚拟内存,64位编译环境、i5以上cpu;
2. 安装VirtualBox扩展包
@p55-1
3. 安装Ubuntu
@p56-1
(1)Ubuntu镜像下载(p58-1)
4. 配置Ubuntu
@p60-1
5. 安装所需软件包
@p62-2
6. 安装JDK
@63-1
3.3.2 使用repo
@p64
------第四章 Android系统层源码结构分析
4.1 源码结构分析
@p69
@Android系统层次结构图(p69)
@Android层次结构分析(p70)
4.1.1 底层库结构介绍
1. 底层函数库的基本结构
@p71
系统源代码目录结构
4.1.2 C基础函数库bionic
@p73
@文件位置:/bionic
@包含一些使用频率低并且资源消耗比较高的函数,使其具有更小的体积和内存占用;
1. bionic函数库结构
@p73-表4-2
bionic文件夹内的子文件夹功能;
2. libc函数库结构
@p73-表4-3
@文件位置:/bionic/libc
libc内的各文件夹功能;
4.1.3 C语言底层库libcutils
@p74
/system/core/libcutils
@提供C语言最基础的功能;
@基本上Android中所有的本地仓库和程序都连接了这个库;
解释了其中主要的头文件作用;
4.1.4 C++工具库libutils
@p75
/system/core/libutils
@头文件在:/system/core/libutils/include/utils/
@源文件在:/system/core/libutils/
@库名称:libutil.so
@Android底层库,以C++实现;
@Android层次的C语言程序和库,大都基于libutils开发;
4.1.5 底层文件系统库 system
1. system目录结构
@p75-表4-4
system中的core和extra文件夹解释分析;
@bionic文件和system文件完成了Android对Linux的封装,并在二者的基础上构建了Android系统的两大核心模块:Dalvik和Frameworks;
4.1.6 增加本地库的方法
@p76
@讲解了:编译可执行程序模板、编译静态库模板、编译动态库模板;
1. 编译可执行程序模板
# :=代表赋值操作
# $代表引用变量的值
# 指定LOCAL_PATH变量,用于查找源文件
LOCAL_PATH := $(call my-dir)
# CLEAR_VARS清除LOCAL_PATH以外所有以LOCAL开头的变量
# include $(CLEAR_VARS)
# LOCAL_SRC_FILES存入源文件路径
LOCAL_SRC_FILES := main.c
# LOCAL_MODULE存入编译后的模块名称
LOCAL_MODULE := test_exe
# LOCAL_C_INCLUDES存入所需要包含的头文件路径
#LOCAL_C_INCLUDES :=
# LOCAL_STATIC_LIBRARIES存入所需链接的静态库(*.a)的名称
#LOCAL_STATIC_LIBRARIES :=
# LOCAL_SHARED_LIBRARIES存入所需链接的动态库(*.so)的名称
#LOCAL_SHARED_LIBRARIES :=
# BUILD_EXECUTABLE表示以一个可执行程序的方式进行编译
include $(BUILD_EXECUTABLE)
2. 编译静态库文件
# 指定LOCAL_PATH变量,用于查找源文件
LOCAL_PATH := $(call my-dir)
# CLEAR_VARS清除LOCAL_PATH以外所有以LOCAL开头的变量
include $(CLEAR_VARS)
# LOCAL_SRC_FILES存入源文件路径
LOCAL_SRC_FILES := mk_statis_library.c
# LOCAL_MODULE存入编译后的模块名称
LOCAL_MODULE := libtest_static
# LOCAL_C_INCLUDES存入所需要包含的头文件路径
#LOCAL_C_INCLUDES :=
# LOCAL_STATIC_LIBRARIES存入所需链接的静态库(*.a)的名称
#LOCAL_STATIC_LIBRARIES :=
# LOCAL_SHARED_LIBRARIES存入所需链接的动态库(*.so)的名称
#LOCAL_SHARED_LIBRARIES :=
# BUILD_STATIC_LIBRARY表示以一个静态库的方式进行编译
include $(BUILD_STATIC_LIBRARY)
3. 编译动态库文件
# 指定LOCAL_PATH变量,用于查找源文件
LOCAL_PATH := $(call my-dir)
# CLEAR_VARS清除LOCAL_PATH以外所有以LOCAL开头的变量
# include $(CLEAR_VARS)
# LOCAL_SRC_FILES存入源文件路径
LOCAL_SRC_FILES := mk_shared_library.c
# LOCAL_MODULE存入编译后的模块名称
LOCAL_MODULE := libtest_shared
TARGET_PRELINK_MODULES := false
# LOCAL_C_INCLUDES存入所需要包含的头文件路径
#LOCAL_C_INCLUDES :=
# LOCAL_STATIC_LIBRARIES存入所需链接的静态库(*.a)的名称
#LOCAL_STATIC_LIBRARIES :=
# LOCAL_SHARED_LIBRARIES存入所需链接的动态库(*.so)的名称
#LOCAL_SHARED_LIBRARIES :=
# BUILD_SHARED表示以一个动态库的方式进行编译
include $(BUILD_SHARED_LIBRARY)
静态库生成的文件目录:out/target/product/*/obj/下
Android.mk的每个模块都是以include $(CLEAR_VARS)开始,以include $(BUILD_XXX)结束;
4.2 Android编译系统介绍
@p78
4.2.1 build系统
@p78
@代码位置:build/core/
@介绍了:编译系统的功能、结构、编译过程、编译生成文件的位置(以及对应位置下生成文件的含义)
1. 编译系统简介
该系统主要由make文件(即.mk文件)、Shell脚本以及Python脚本组成,支持多架构(Linux-x86、Windows、ARM等)、多语言(汇编、C、C++、Java等)、多目标、多编译方式;
2. 编译过程
3. 编译输出
@p79-1
out目录做了详细介绍;
@有待补充
4. 编译框架
@p79-2
编译核心框架(.mk)文件做了功能解释;
4.3 init初始化脚本语言介绍
4.3.1 概述
Linux系统启动时依次执行:start_kernel()、init_post()、run_init_process()、init进程;
Android系统启动也和Linux类似;
Android的init进程主要提供4个功能:
(1)分析启动init.rc脚本文件;
@有待补充
启动init进程的具体代码:
4.3.2 init进程源码分析
init进程的事件处理流程图(p85-图4-5)
4.3.3 脚本文件的创建与分析
1. init.rc文件
2. action list
3. service list
4. init.rc脚本文件解析
init.rc脚本文件的解析由init_parse_config_file()函数实现(p88-1);
init_parse_config_file()函数主要调用了read_file()函数和parse_config()函数;
4.3.4 创建设备节点文件
Android系统通过设备驱动来访问硬件设备,设备节点文件时设备驱动的逻辑文件(p89);
Linux创建设备节点文件:通过mknod进程;
Android创建设备节点文件:使用init进程创建,创建的设备节点文件分为静态节点文件和动态节点文件;
init节点创建过程代码(p89-2)
4.4 Zygote
4.4.1 Zygote概述
Zygote应用于Dalvik虚拟机的内存管理(p95-2);
Zygote进程的源文件:app_main.cpp(p95-2);
Dalvik虚拟机是Android程序的虚拟机,是Android中Java程序的运行基础。其指令集基于寄存器架构,执行其特有的文件格式——dex字节码来完成对象生命周期管理、堆栈管理、线程管理、安全异常管理、垃圾回收等重要功能。它的核心内容是实现库(libdvm.so),大体由C语言实现。依赖于Linux内核的一部分功能——线程机制、内存管理机制,能高效使用内存,并在低速CPU上表现出的高性能。每一个Android应用在底层都会对应一个独立的Dalvik虚拟机实例,其代码在虚拟机的解释下得以执行
讲解了Zygote创建了什么,怎么创建的(p95-3);
@主要从两方面分析Zygote:App-Runtime、system_server;
4.4.2 AppRuntime分析
Zygote启动应用程序的过程图解(p95);
@AppRuntime对象的生成代码(p96);
@AppRuntime用于初始化Dalvik虚拟机,为Android应用程序运行做好准备(p96最后一段);
@AppRuntime.cpp源代码位置:framework/base/core/jni/AppRuntime.cpp
1. 创建虚拟机--startVm
@AndroidRuntime::startVm()主要用于设置Java虚拟机的启动参数:JNI check选项(p98);
@JNI参数用于Native层实现对所调用的JNI函数的检查;
2. 注册JNI函数--startReg
@注册JNI的代码(p99)
@至此Java应用框架就已经建立起来了(p100);
4.4.3 system_server分析
@system_server进程由ZygoteInit.main函数中的startSystemServer函数启动(p100);
@ZygoteInit.main函数位置:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
@SystemServer进程的启动和调用流程图(p102);
------第五章 Android系统内核分析
5.1 Linux内核基础
5.1.1 概述
@Linux操作系统分为:用户空间(User Space)、内核空间(Kernel Space);
@用户空间:用户应用程序执行的地方;
@Linux为单内核,内核分为多个子系统(从上至下):系统调用接口、内核代码、依赖于体系结构的代码(BSP 平台支持包);
5.1.2 Linux内核的主要子系统
@p110
1. 系统调用接口(SCI)
@ SCI层、依赖于体系结构
@ 定义了从用户空间到内核的函数调用接口
@ SCI层实现:./linux/kernel
@ 依赖于体系结构的部分:./linux/arch
2. 进程管理(PM)
@ PM、负责进程的执行
@ 包含的函数:fork(创建)、exec(执行)、Portable Operating System Interface【POSIX】
@ O(1)调度算法:调度多个进程所使用的时间和一个进程所使用的时间时相同的;
3. 内存管理 (MM)
@ 两种内存形式:物理内存、虚拟内存;
@ 内存管理源代码:./linux/mm
4. 虚拟文件系统 (VFS)
@ 在SCI和内核所支持的文件系统之间提供了一个交换层;
文件系统-源代码位置:./linux/fs
文件系统层之下时缓冲区缓存,为文件系统层提供了一个通用函数集;
5. 网络堆栈(NS)
遵循分层体系结构,为各种网络协议提供了一个用户接口;
网络堆栈-源代码位置:./linux/net
6. 设备驱动程序(DD)
实现特定硬件设备的运转;
设备驱动程序-源代码位置:./linux/drivers
7. 依赖体系结构的代码(Arch)
Linux需要在不同体系结构下实现高效率的操作;
Arch-源代码位置:./linux/arch
每个子目录对应某一特定方面的功能;
5.1.3 Linux启动过程分析
@开机启动过程:启动驱动器、启动内核、初始化过程、启动用户登录界面(p111);
5.2 Android内核概况
@Android系统分为:硬件、系统内核、系统服务、应用程序(p112);
@Android内核主要实现:内存管理、进程调度、进程间通信等功能;
文件系统:YAFFS2文件系统;
进程间通信机制:IPC Binder;
内存管理:LMK低内存管理策略、Ashmem内存共享处理方式;
电源管理:...
其他:Android内核增加了字符输入系统、... 、USB设备等相关设备驱动,增加了LOgger子系统;
5.3 Android启动过程分析
1. init进程
@ 代码位置:system/core/init(p113)
@ init进程是第一个进程,会建立servicemanager、zygote等服务,创建结束后承担property service的功能;
2. Zygote框架建立
@zygote进程启动代码位置:frameworks/base/cmds/app_process/app_main.cpp,由其中的main函数开始执行(p113);
@Android启动框架图(p114)
@功能:启动虚拟机、调用JNI创建JavaVM、调用startReg函数注册JNI接口、调用ZygoteInit中的main函数,注册用来接受请求的Listen端口、启动SystemServer,至此,Zygote建立完成;
3. System Server
@startSystemServer在Zygote上fork了SystemServer进程(p115);
@代码位置:com.android.server.SystemServer
Android的所有服务框架都是建立在SystemServer上的,在SystemServer.java中调用init2()函数,由init2()建立Android中所用到的服务循环框架;
4. Home启动
@p115
5.4 Binder框架分析
Android为进程间通信提供Binder机制;
1. Binder机制的功能
(1)利用驱动程序来推进进程间的通信;
(2)通过共享内存来提高性能;
(3)为进程请求分配每个进程的线程池;
(4)引入了引用计数和跨进程的对象引用映射;
------第六章 Android系统相关工具及运行环境
6.2 Dalvik虚拟机
6.2.1 概述
加快程序的运行速度、较少应用程序的占用空间、Dalvik采用寄存器架构(p160);
1. Dalvik虚拟机的主要功能
每个程序对应一个独立的Dalvik进程(p160);
Linux内核作为硬件和软件栈之间的抽象层;
Dalvik虚拟机从层次结构上与程序库位于同一层;
应用程序在Dalvik虚拟机中的执行流程(p160);
Dalvik虚拟机的输入是已经编译好的class文件或者jar文件;
@源码位置:/dalvik/目录下(p161);
@/dalvik/目录下的dx文件夹是:将class文件或者jar文件转换成dex文件的工具;
2. Dalvik虚拟机和Java虚拟机的区别
@最显著的差别:具有不同的类文件格式以及指令集(p162);
一个dex文件可以包含多个类,二一个class文件只能包含一个类;
@Dalvik虚拟机的特点:p163-2;
每个Dalvik虚拟机都是一个独立的进程空间,每个Android Dalvik应用程序都被赋予了一个独立的Linux PID(app_*);
6.2.2 dex文件
1. dex文件格式
@概念:Dalvik可执行文件由Dalvik虚拟机编译,并且被压缩成apk文件放在设备上(p163);
dex文件的结构
2. dex文件转换
class文件转换成dex文件过程图(p164);
@.odex文件:dex的优化文件;
@Android应用程序编译过程图;
6.2.3 Dalvik内存管理
1. 栈架构与寄存器架构
@Dalvik是基于寄存器架构的虚拟机(p165);
2. 内存管理
@虚拟机的初始化(p166);
6.2.4 Dalvik编译器
@p169
6.3 JNI
6.3.1 概述
@Java Native Interface Java本地调用(p171)
JNI是一种技术,可实现如下功能:
Java程序中的函数可以调用Native语言写的函数,Native一般指的是C/C++编写的函数;(2)Native程序中的函数可以调用Java层的函数,也就是说在C/C++程序中可以调用Java的函数;
6.3.2 JNI的架构
@(p171)Native函数要想注册到系统中,需要使用一个工具库nativehelper;
libnativehelper.so动态链接库,这样虚拟机就可以随时进行库的加载和调用了;
jni.h(JNI标准头文件)、JNIHelper.h(JNI注册功能头文件)
libandroid_runtime.so动态链接库
libmedia_jni.so动态链接库;
6.3.3 JNI的实现方式
@主要介绍原生方法在系统中的注册(p172);
JNI调用实例分析(p172最后一段);
6.4 Boot Loader
6.4.1 概述
概述:U-Boot,全称Universal Boot Loader,是在操作系统内核运行之前运行的一小段程序;为最终调用操作系统内核准备好正确的环境(p173);
@功能:(p174-2)
6.4.2 Boot Loader的操作模式
“下载”模式(p174);
6.4.3 启动过程
@U-Boot启动流程图(p175)
6.5 Busybox的使用
bionic取代glibc,作为C库使用(p176);
------第七章 Android驱动程序设计
7.1 Andoid驱动概述
在安装有Android系统的设备上,需要为一些外部硬件安装对应的驱动程序(p177-1);
@驱动程序是添加到操作系统上的一段代码,包含了硬件相关的设备信息和操作接口。用户可以通过设备的操作接口来操作硬件(p177-1)。
@Android系统驱动分为两层(p177-2):
(1)内核空间的Linux内核驱动层;(2)用户空间的Android硬件抽象层(HAL);
@驱动层主要的工作:
(1)Linux设备驱动程序
LCD、触摸屏、键盘等驱动
Android驱动开发结构图(p177);
7.2 Android NDK编程
@NDK是一系列工具的集合,全称:Android Native Development Kit;这个开发包帮助开发者快速开发C(或C++)的动态库或本地应用(p178);
NDK开发流程图(p178),帮助理解NDK在Android开发过程中的作用;
@C源代码、Android.mk、头文件可以通过NDK的编译组合成动态库(.so文件);
7.3 Android系统中的HAL层
@在Linux内核层之上,HAL实现了硬件抽象化,将硬件平台的差异隐藏,为上层提供统一的硬件平台,方便开发者在不同硬件平台上进行代码移植;
@HAL:Hardware Abstration Layer 硬件抽象层(p183-1)
Android中的内核空间使用Linux驱动,用户空间则以HAL的模块的方式,对硬件设备的细节进行封装,就也可以访问设备;(p183最后一段)
7.3.1 HAL_legacy和HAL对比
libhardware_legacy(旧框架)、libhardware(新框架)
新旧HAL层架构图(p184)
7.3.2 HAL_module架构分析
@p184
7.3.3 HAL实现流程
@p186
7.4 Android系统Camera与WiFi实现
7.4.1 Camera实现
Camera系统结构图(p187)
1. 应用层
应用层代码位置:package/apps/Camera
2. Framework层硬件服务
1.Java接口层代码位置(p188):frameworks/base/core/java/android/hardware/Camera.java;
framework.jar,成为SDK API;
2.JNI接口代码位置(p188):frameworks/base/core/jni/android_hardware_Camera.cpp
这部分内容编译成libandroid_runtime.so;
3.Camera Client代码位置(p188):frameworks/base/libs/camera
libcamera_client.so,该库是作为Camera框架中的客户端,并通过Binder与服务端进行通信;
4.Camera Service代码位置(p188):frameworks/base/services/camera/libcameraservices,这部分被编译成libcameraservice.so;
3. Camera HAL
libcamera.so;
4. Camera Linux驱动
@驱动目录(p190):kernel/driver/media/video
7.4.2 WiFi实现
@WiFi系统的上层接口包括(p190):数据部分、控制部分;
WiFi系统结构图(p190)
1. wpa_supplicant
@守护进程,负责认证的登录、加密等(p191);
源码路径:external/wpa_supplicant_8/
libwpaclient.so动态链接库和守护进程wpa_supplicant;
2. 适配器层
@主要实现与wpa_supplicant的通信工作,实现Framework层的加载、控制(p191);
源码路径:hardware/libhardware_legacy/wifi/
3. WiFi JNI
@本地函数通过调用适配层的接口实现;
@WiFi JNI接口的源码路径:frameworks/base/core/jni/android_net_wifi_Wifi.cpp
4. WiFi Framework层
@WiFi系统分为WiFi客户端与WiFi服务端,两者通过Binder机制进行通信;
@源码路径:
frameworks/base/services/java/com/android/server/
frameworks/base/wifi/java/android/net/wifi/
5. WiFi Settings
@通过Android系统的Setting应用程序实现对WiFi的配置、控制等操作;
@代码目录:packages/apps/Settings/src/com/android/settings/wifi/