# 源码获取
获取源码的方法有两种,一种是用谷歌的 repo 工具从 aosp 获取源码,这个对硬盘空间的要求比较高,大约需要 100+G;另一种就是从其他地方直接下载打包好的代码,不便于选择特定 release 版本。
## AOSP
由于官方源网络不稳定,可以选择[中科大源](https://lug.ustc.edu.cn/wiki/mirrors/help/aosp)或[清华源](https://mirrors.tuna.tsinghua.edu.cn/help/AOSP/)
以中科大源为例,使用清华源仅需修改初始化时的仓库地址
```
# 下载 repo 工具
mkdir ~/bin
PATH=~/bin:$PATH
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo
# 建立工作目录
mkdir AOSP_DIRECTORY
cd AOSP_DIRECTORY
# 初始化仓库
repo init -u git://mirrors.ustc.edu.cn/aosp/platform/manifest -b android-6.0.1_r72
repo sync
```
## 源码包
我用的源码包是从[这里](https://pan.baidu.com/s/1ngsZs#list/path=%2F&parentPath=%2F)下载的,下载到本地解压即可。我使用的版本是 6.0.1_r72。
# 构建编译环境
AOSP 项目对编译环境的 JDK 版本和系统版本都作出了要求,详见[搭建编译环境](https://source.android.google.cn/source/initializing?hl=zh-cn)
我使用 docker 镜像作为编译环境,来自[kylemanna/aosp](https://hub.docker.com/r/kylemanna/aosp),作者提供了从 4.4~7.0的编译环境。
# 编译及烧录
初始化编译环境
```
cd AOSP_DIRECTORY
source build/envsetup.sh
```
选择编译版本
```
lunch
You're building on Linux
Lunch menu... pick a combo:
1. aosp_arm-eng
2. aosp_arm64-eng
3. aosp_mips-eng
4. aosp_mips64-eng
5. aosp_x86-eng
6. aosp_x86_64-eng
7. aosp_deb-userdebug
8. aosp_flo-userdebug
9. full_fugu-userdebug
10. aosp_fugu-userdebug
11. mini_emulator_arm64-userdebug
12. m_e_arm-userdebug
13. mini_emulator_mips-userdebug
14. mini_emulator_x86-userdebug
15. mini_emulator_x86_64-userdebug
16. aosp_flounder-userdebug
17. aosp_angler-userdebug
18. aosp_bullhead-userdebug
19. aosp_hammerhead-userdebug
20. aosp_hammerhead_fp-userdebug
21. aosp_shamu-userdebug
Which would you like? [aosp_arm-eng]
```
我是为 Nexus5 编译的,对应的设备代码为 hammerhead,选择 19。其他机型可以查阅[机型对照表](https://source.android.google.cn/setup/build/running?hl=zh-cn#booting-into-fastboot-mode)。
接下来要下载设备对应的[驱动](https://developers.google.com/android/drivers#hammerheadm4b30x),一共三个 sh 文件,下载好之后放到 AOSP 源码根目录执行,驱动会解压到 vender 目录下。
然后是漫长的编译
```
# 核心数 * 2
make -j8
```
编译好之后就是烧录,首先将设备重启至 recovery 模式,方法见上文机型对照表,然后在源码根目录执行,大约1分多钟会自动重启进入系统,编译完成。
```
fastboot -w flashall
```
# 修改代码使 app 可以获取 root 权限
```
# system/extra/su/su.c
# 注释 main 函数第二行用户判断
// if (current_uid != AID_ROOT && current_uid != AID_SHELL) error(1, 0, "not allowed");
# system\core\libcutils/fs_config.c
# 修改 xbin/su 权限为 06755,在 user 部分添加 bin/su 权限
{ 06755, AID_ROOT, AID_SHELL, 0, "system/xbin/su" },
/* the following files have enhanced capabilities and ARE included in user builds. */
{ 06755, AID_ROOT, AID_ROOT, 0, "system/bin/su" },
# frameworks\base\cmds\app_process\app_main.cpp
# 注释 main 函数头部权限判断
/* if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
// Older kernels don't understand PR_SET_NO_NEW_PRIVS and return
// EINVAL. Don't die on such kernels.
if (errno != EINVAL) {
LOG_ALWAYS_FATAL("PR_SET_NO_NEW_PRIVS failed: %s", strerror(errno));
return 12;
}
} */
# frameworks\base\core\jni\com_android_internal_os_Zygote.cpp
# 注释 DropCapabilitiesBoundingSet 函数权限判断
/* for (int i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0; i++) {
int rc = prctl(PR_CAPBSET_DROP, i, 0, 0, 0);
if (rc == -1) {
if (errno == EINVAL) {
ALOGE("prctl(PR_CAPBSET_DROP) failed with EINVAL. Please verify "
"your kernel is compiled with file capabilities support");
} else {
ALOGE("prctl(PR_CAPBSET_DROP) failed");
RuntimeAbort(env);
}
}
} */
# system\core\adb\adb_main.cpp
# should_drop_privileges 函数直接返回 false
static bool should_drop_privileges() {
return false;
# ...
}
# system\core\init\init.cpp
# 关闭 selinux
static bool selinux_is_enforcing(void) {
return false;
if (ALLOW_DISABLE_SELINUX) {
return selinux_status_from_cmdline() == SELINUX_ENFORCING;
}
return true;
}
```