- 1:刷机
- 1.1:卡刷
- 1.2:线刷
- 2:Android系统常用分区
- 2.1:bootloader
- 2.2:recovery
- 2.3:boot
- 2.4:system
- 2.5:userdata
- 2.6:cache
- 2.7:sdcard
- 3:out目录
- 3.1:out/host/
- 3.2:/out/target/common/
- 3.3:/out/target/product/<product_name>/
- 4:AOSP常见的命令
- 4.1:gettop
- 4.2:croot
- 4.3:mm
- 4.4:cgrep
- 4.5:jgrep
- 4.6:resgrep
- 4.7:godir
- 5:常见AOSP目录
- 5.1:build/
- 5.2:packages/
- 5.3: frameworks/
- 5.4:device/<vendor_name>/<product_name>
- 5.5:vendor/<vendor_name>/<product_name>
- 6:Android Build系统
- 6.1:Makefile
- 7:AOSP下进行系统开发
- 7.1:修改系统APP代码
- 8:将源码导入到Android Studio
- 9:关于系统的一些知识和调试技巧
- 9.1:查看进程相关信息
- 9.2:安卓进程间的相互关系
- 9.3:代码定位
- 9.4:主要jar介绍
- 10:调试技巧
在上一篇文章中,主要介绍了Android Framework开发的编译环境搭建和源码下载,在本篇文章中,主要介绍一些系统开发的基础知识和如何将代码导入到Anroid studio中等。
刷机
卡刷
线刷
Android系统常用分区
bootloader
相当于PC的BIOS,负责硬件自检和初始化,以及启动模式选择。在bootloader模式下可以进行分区的烧写。
recovery
包含Linux内核和recovery程序,简易的linux系统。在recovery模式下可以进行分区的擦写,OTA升级操作。
boot
包含Linux内核和一个迷你的根文件系统。负责system、cache、userdata等分区的挂载。
system
userdata
用户数据分区。挂载在/data目录下。用户安装的APK,以及app的数据都在这个分区。
cache
缓存分区,一般用于OTA升级进入recovery前,临时放置OAT升级包,以及保存OTA升级的一些临时输出文件。
sdcard
out目录
在第一次完全编译完成后会生成out目录,里面存放着编译过程生成的文件以及最终生成的文件。
out/host/
该目录下包含了针对当前操作系统所编译出的Android开发工具产物。例如adb、aapt、fastboot等命令。
/out/target/common/
该目录下包含了针对Android设备的通用的编译产物,主要是 Java 应用代码和 Java 库。(framework.jar,services.jar,android.policy.jar等等)
/out/target/product/<product_name>/
ramdisk.img
在启动时将被 Linux 内核挂载为只读分区,它包含了 /init 文件和一些配置文件。它用来挂载其他系统镜像并启动 init 进程。
system.img
包含了 Android OS 的系统文件,库,可执行文件以及预置的应用程序,将被挂载为system分区。
userdata.img
将被挂载为 /data,包含了应用程序相关的数据以及和用户相关的数据。
AOSP常见的命令
aosp常见的命令是在envsetup.sh里定义的一些shell函数,必须先source该脚本才能执行。
gettop
获取WORKING_DIRECTORY目录的完整路径。如我的就会打印:
/home/melrose/aosp/alps-release-q0.mp1-v8.4
croot
回到WORKING_DIRECTORY目录。
mm
编译当前目录下的模块。比如在packages/apps/Calculator目录下执行mm,就是编译Calculator.apk。
cgrep
执行grep命令,但只匹配C/C++的源文件。
jgrep
执行grep命令,但只匹配java源文件。
resgrep
执行grep,但只匹配路径名为res/下的xml资源文件。
godir
去某一个目录。第一次执行会将AOSP的所有目录路径存到filelist文件中。类似everythings的作用。
常见AOSP目录
介绍一些做AOSP开发时,一般会接触到的目录。
build/
build/core
AOSP整个编译过程中核心的编译规则makefile。
build/envsetup.sh
编译环境初始化脚本。
build/target/
AOSP自带的Target(模拟器)的一些makefile。
编译中使用的shell及python写的工具脚本。
build/tools/
编译中使用的shell及python写的工具脚本。
packages/
电话,桌面,设置,相册,照相机,闹铃,日历等经常操作的系统app,以及一些provider,输入法等桌面上看不到的app。
frameworks/
frameworks/av/
多媒体相关的native层的源码目录。
framework/webview
浏览器内核chromium的源码目录。
framework/native
power,surface,input,binder等服务的native层实现的源码目录。
frameworks/base/
core framework.jar ,framework-res.apk,libandroid_runtime.so等的源文件。
- native libandroid.so的源代码目录。java api的native实现。比如assertmanager,looper等。
- media 多媒体相关的JavaAPI及JNI层的源文件。
- packages SettingsProvider,SystemUI等不在桌面直接启动的APP的源码目录。
- services services.jar,libandroid_servers.so的源文件。
- wifi wifi服务相关的Java API,WifiManager,WifiService等。
device/<vendor_name>/<product_name>
跟某些厂商的某个硬件平台相关的内核,硬件配置等。
vendor/<vendor_name>/<product_name>
厂商对AOSP进行的修改或者定制,放在vendor目录。包括但不限于framework层新增API,新增APP等业务需求。但是现在Google更推荐放在devices目录下。
Android Build系统
Android Build 系统用来编译 Android 系统,Android SDK 以及相关文档。该系统主要由 Make 文件,Shell 脚本以及 Python 脚本组成,在编译时能够支持面向不同的硬件设备,不同的编译类型,且提供面向各个厂商的定制扩展。
Makefile
在之前的文章中,简单介绍过makefile的使用。makefile是一些有特定语法的,可供make命令读取并执行的脚本性质的配置文件。作用就是可以告知编译系统,对哪些源文件进行编译,怎么编译,怎么处理依赖关系。makefile可以定义变量,函数,调用系统命令,shell/python脚本,管理module之间的依赖。整个 Android Build 系统中的 Make 文件可以分为三类:
Build系统核心Makefile
这类makefile定义了整个 Build 系统的框架,而其他所有 Make 文件都是在这个框架的基础上编写出来的。位于/build/core目录下。
针对某个产品的Makefile
这类makefile是针对某个产品Make 文件,这些文件通常位于 device/<vendor>/<product> 目录下。
针对某个模块的Makefile-Android.mk
AOSP下进行系统开发
从系统APP开发,Framework层定制,native层定制三个环节,学会如何修改AOSP代码达到开发需求。AOSP开发的覆盖面是非常广的,从上层的系统APP到底层的HAL层驱动,每一个环节都是息息相关的。了解Android的启动流程,会帮助我们加深对Andorid系统的理解。
修改系统APP代码
mm –B :强制重新编译。相当于clean后再编译。
将源码导入到Android Studio
如果想把aosp的源码加载到Android studio中,则需要执行如下四条命令:
#设置环境和选择要编译的项目,如果设置过不需要重新设置
. build/envsetup.sh
lunch
#编译android studio支持的项目文件
make idegen -j4
sudo development/tools/idegen/idegen.sh
在执行完以上的命令后,会在工作目录的根目录下生成两个文件:
- android.iml
- android.ipr
然后打开anroid studio将ipr文件加载到工程中。
如果电脑性能不够则可以在anroid.iml中将不需要的文件排除掉:
<div><excludeFolder url=“file://$MODULE_DIR$out”/></div>
<div><excludeFolder url=“file://$MODULE_DIR$kernel”/></div>
关于系统的一些知识和调试技巧
查看进程相关信息
adb shell
ps -A | grep “setting"
#查看进程号为1729相关的log
logcat | grep “1729"
安卓进程间的相互关系
SurfaceFlinger进程
赋值整个系统的界面显示绘制:binder通信、共享内存。
Zygote进程
孵化出各种进程:socket通信。
ServiceManager进程
系统服务的管理器:binder通信。
System_Server进程
负责所有的系统核心服务:binder通信。
代码定位
一般Android sdk 里面的代码都是运行在外部app进程的,一般sdk里面的是android.jar,其实就是编译出的framework.jar,因为app需要依赖sdk才能编译通过,说明各个app的会使用sdk中的代码,这块代码,属于所有app共用,因此修改其中的一个类就会影响所有的应用进程。
一般com.android.server.*相关的类都是运行在system_server,这一部分的代码平时是接触不到的,因为普通应用根本无法引入相关的server代码,这些代码属于system_server特殊应用自己的代码,普通应用指南通过跨进程通信的方式与其进行数据交换。一般Java代码对于的是services.jar。
主要jar介绍
- framework-res.apk :android系统资源库
- framework.jar:android的sdk中核心代码
- services.jar:框架层服务器的编译后jar包
调试技巧
在无法定位代码运行位置时,可以通过抛异常的方式来打印代码调用的堆栈:
public static void printStackTrace(){
try {
throw new IllegalStateException("debug mode");
}catch (IllegalStateException ex){
ex.printStackTrace();
}
}