学习书籍: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. 编译过程

Android底层Kernel屏幕 android系统底层开发_Android

 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/