安卓进阶一:准备知识
本文是学习罗升阳大佬的《安卓系统源代码情景分析》做的笔记和总结
一、下载、编译和运行安卓和内核源码
1、参考:
2、可以用update-alternatives对安装包进行管理,方便不同版本的切换,比如你装有多个版本的gcc、python的时候切换很方便
3、export PATH=$PATH:xxx 只是临时设置环境变量,重启就没了,想要长久设置可以改用户目录下的.bashrc。export既可以导出PATH ,也可以导出其他的变量,比如
TEXT=/core/bin
ANDROID =~/android
PATH=$PATH:$(TEXT) //TEXT前面记得加$
export PATH ANDROID//一起导出去
二、开发第一个安卓应用程序
1、Android.mk的一些语法
参考: Android.mk的用法介绍、Android.mk详解
举例1:
1 LOCAL_PATH := $(call my-dir)
2 include $(CLEAR_VARS)
3 LOCAL_MODULE:= helloandroid
4 LOCAL_SRC_FILES := helloandroid.c
5 #LOCAL_C_INCLUDES := //'#'在这里是注释掉的意思,不是格式
6 TARGET_PRELINK_MODULES := false
7 include $(BUILD_SHARED_LIBRARY)
第1行:mk文件需要定义好LOCAL_PATH变量,用于在开发树中查找源文件,宏函数’my-dir’, 由编译系统提供,用于返回当前路径,即包含Android.mk的目录
第2行:CLEAR_VARS由编译系统提供,指定让GNU MAKEFILE为你清除许多除了 LOCAL_PATH之外的LOCAL_XXX变量(比如 LOCAL_MODULE, LOCAL_SRC_FILES, LOCAL_STATIC_LIBRARIES等等),这是必要的,因为所有的编译控制文件都在同一个GNU MAKE执行环境中,所有的变量都是全局的
第3行:LOCAL_MODULE变量必须定义,以标识你在Android.mk文件中描述的每个模块。名称必须是唯一的,而且不包含任何空格。注意编译系统会自动产生合适的前缀和后缀,换句话说,一个被命名为'food'的共享库模块,将会生成'libfood.so'文件
第4行:LOCAL_SRC_FILES变量必须包含将要编译打包进模块中的C或C++源代码文件。不用在这里列出头文件和包含文件,因为编译系统将会自动为你找出依赖型的文件,只需列出直接传递给编译器的源代码文件
第5行:加入所需要包含的头文件路径
第6行:不做prelink操作,用于动态库(静态库和可执行程序则把这句注释掉)。prelink操作利用事先链接代替运行时链接的方法来加速共享库的加载,它不仅可以加快起动速度,还可以减少部分内存开销
第7行:include $(BUILD_SHARED_LIBRARY)表示编译一个动态库(*.so)
同样有:
include $(BUILD_STATIC_LIBRARY)表示编译一个静态库(*.a);
include $(BUILD_EXECUTABLE)表示编译一个可执行程序;
include $(BUILD_PACKAGE)编译打包成APK文件;
include $(BUILD_STATIC_JAVA_LIBRARY)用它来编译生成JAVA库(打包成.jar文件)
一个Android.mk文件可以编译多个模块,生成结果在
out/target/product/generic/obj/APPS/XXX_intermediates //apk
out/target/product/generic/obj/JAVA_LIBRARIES/XXX_intermediates //jar文件
out/target/product/generic/obj/EXECUTABLE/XXX_intermediates //c/c++应用程序
out/target/product/generic/obj/STATIC_LIBRARY/XXX_static_intermediates //C\C++静态库,并打包成.a文件
out/target/product/generic/obj/SHARED_LIBRARY/XXX_shared_intermediates //成共享库(动态链接库),并打包成.so文, 有且只有共享库才能被安装/复制到您的应用软件(APK)包中
举例2:
1 LOCAL_PATH := $(call my-dir)
2 include $(CLEAR_VARS)
3 LOCAL_MODULE_TAGS:= optional
4 LOCAL_SRC_FILES := $(call all-subdir-java-files)
5 LOCAL_PACKAGE_NAME :=HelloAndroid
6 include $(BUILD_PACKAGE)
第3行:optional指该模块在所有版本下都编译。此外还有user、eng、tests版本LOCAL_MODULE_TAGS :=user \ eng \ tests
第4行:它的作用就是包含所有子目录中的Android.mk文件。比如说需要编译的模块比较多,我们可能会将对应的模块放置在相应的目录中,这样,我们可以在每个目录中定义对应的Android.mk文件,最后,在根目录放置一个Android.mk文件
2、source 、 . 执行脚本的区别
source命令是bash shell的内置命令
. 点命令,就是一个点符号,是source的另一名称,所以 . file = source file ,如下:
3、可以通过&& ||执行命令,好处是脚本里面可以避免一些程序执行的错误
4、在eclipse编辑好代码后,复制到linux源码里面的时候只需留下这四个文件即可
5、各个输出的目录
安卓源码中:
out/target/product/generic/system/app 系统apk
out/target/product/generic/system/bin C可执行文件
out/target/product/generic/system/lib 动态链接库文件
out/target/product/generic/system/lib/hw 硬件抽象层模块文件
out/target/product/generic/ system.img
out/target/product/generic/ ramdisk.img
out/target/product/generic/ userdata.img
out/host/linux-x86/sdk/ sdk
内核源码中:
arch/arm/boot zImage linux内核
三、为真机刷ROM
自己编译的安卓源码既可以运行在模拟器上面,也可以运行在真机上面,这需要通过刷ROM来实现。
1、什么是刷ROM?
先了解三个模式及它们的功能:
Normal Mode:正常模式,也就是我们平时开机进去的模式。包含System和Boot两个分区,System主要包含Android运行时框架、系统APP和预装的第三方APP;Boot主要包含根文件系统和内核。刷入System和Boot分区的镜像分别称为system.img和boot.img。通常把这两个镜像做成一个zip包,然后进入Recovery Mode(恢复模式,怎么进入该模式下文会介绍)中更新正常模式下的这两个镜像,这就是刷ROM。个人理解,ROM是计算机或者手机系统里面专门用来存储一些固化好的系统或者程序的,所以更新了system和boot镜像之后,就相当于把ROM刷新了一遍,而不是说ROM=system.img+boot.img
Recovery Mode:恢复模式(长按电源键 和 音量+ 进入)。是一个小型Linux操作系统,可以用来对手机恢复出厂设置,或者使用供应商image对设备进行更新。既然Recovery Mode是一个小系统,那怎么安装这个系统呢?这就需要FastBoot Mode
Fastboot Mode:快速启动模式(长按电源键 和 音量- 进入)。在这个模式下可以通过fastboot工具将镜像recovery.img(也就是上面说到的恢复模式的小系统)刷入Recovery分区,完成安装。那Fastboot模式是怎么来的,由Bootloader提供,个人理解就像uboot启动linux系统的时候按任意键进行打断进入uboot的命令行那种情形,我们进入uboot后可以设置内核和文件系统的位置等,只不过在安卓里是加载recovery.img
所有的设备都存在Recovery, 但并非所有设备都提供Fastboot
综上,个人理解:Bootloader ---->Fastboot ----->Recovery------>Normal
2、ROM怎么来?
第三方提供或者自己从源码编译。其中第三方提供的不容易找到,所以最好的办法就是自己从源码中编译,可以修改源码定制自己想要的功能。需要的源码如上图分为三种:
Android Source:也就是我们平常说的安卓源码。来自官方AOSP或者第三方定制如LineageOS。后者适配性更高
Device Open Source :设备开源源码。和设备相关。可在Github或者LineageOS中直接获取。
Device Close Source :设备闭源源码。和设备相关,对应的库文件称为设备私有文件。可从手机提取或者Github的TheMuppets中找。
所以主要的还是搞闭源源码。
3、怎么刷ROM?
ROM编译出来后可以用自带的Recovery烧进去或者用第三方的Recovery比如TWRP。
个人理解,所以为真机刷ROM就是围绕怎么获取那三种源码,编译出ROM,然后刷TWRP,再通过TWRP刷ROM