AOSP编译保姆级教程(一)
今日记载一下AOSP编译过程,首要包括预备和添加部分功能的描述,那么don’t say too much,直接开搞
预备
体系环境
体系版别:Ubuntu 20.04
Java版别:使用源码自带的JDK,途径$AOSP_HOME/$prebuilts/jdk
Python版别:2.7.18、3.8.10
装置repo
$ mkdir ~/bin
$ PATH=~/bin:$PATH
$ curl https://mirrors.tuna.tsinghua.edu.cn/git/git-repo > ~/bin/repo
$ chmod a+x ~/bin/repo
初始化 Repo 客户端
$ git config --global user.name "Your Name"
$ git config --global user.email "you@example.com"
# 指定同步的版别
同步源码
AOSP | 镜像站使用协助 | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror
# init时指定只克隆包括最近一次commit的一个分支,可削减同步的代码数量,削减项目文件大小
$ repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-9.0.0_r46 --depth=1
# 同步代码,开端用的repo sync,可是缺少很多文件,后面用了repo sync -l文件才被checkout,详细原因不知道
$ repo sync
$ repo sync -l
创立本地分支
# 创立分支
repo start YOURBRANCH --all
下载驱动
下载后的驱动放在源码文件夹中履行,履行完成后源码根目录下会生成vendor文件夹,其中存在如下两个文件夹
检查体系版别和代号等信息
代号、标签和内部版别号 | Android 开源项目 | Android Open Source Project
下载对应版别二进制文件
Driver Binaries for Nexus and Pixel Devices | Google Play services | Google Developers
关闭预优化加快编译速度
- 翻开build/core/main.mk
- 查找eng
- 在判别处添加
WITH_DEXPREOPT:=false
禁用Jackserver
设置ANDROID_COMPILE_WITH_JACK:=false
make 'ANDROID_COMPILE_WITH_JACK:=false' -j1
添加frida-gadget.so
Zygote中添加
- 将fridagadget.so和fridagadget.config.so存放到out/target/product/sailfish/system/lib64目录下
- 修正aosp/frameworks/base/core/jni/com_android_internal_os_Zygote.cpp,的ForkAndSpecializeCommon函数中添加对应功能,在App发动前将so注入
- 在ForkAndSpecializeCommon的if (pid == 0) 分支中添加以下内容
//此处经过修正buildinfo.sh添加对应特点来设置需求注入的App的包名,也可经过其他办法完成,如修正fridagadget.config.so的装备
std::string package = android::base::GetProperty("fd.packageName","");
//此处经过修正buildinfo.sh添加对应特点来设置第一步的fridagadget.so途径使其默许翻开对应fridagadget.so
std::string gdpath = android::base::GetProperty("fd.gdpath64","");
//或许std::string gdpath{ "/system/lib64/gdpath.so" };
std::string gdpath32 = { "/system/lib64/gdpath32.so" };
if(package.compare(se_name_c_str) == 0){
void* gadget64 = dlopen(gdpath.c_str(),RTLD_NOW);
if(NULL == gadget64){
ALOGE("load gadget64 for app %s failed",se_name_c_str);
}else{
ALOGE("load gadget64 for app %s success",se_name_c_str);
}
}
delete se_info;//此处为原始代码,当时编译的aosp添加gadget的方位即在此处以上
ActivityThread中添加(来自MikRom的计划)
- 将fridagadget.so和fridagadget.config.so存放到out/target/product/sailfish/system/lib64目录下
- 在App发动前将so注入
- 修正android.app.ActivityThread的handleBindApplication办法,添加对应功能,在App发动前将so注入
int flags = mBoundApplication == null ? 0 : mBoundApplication.appInfo.flags;
if(flags>0&&((flags&ApplicationInfo.FLAG_SYSTEM)!=1)){
Fartext.loadGadget();
}
app = data.info.makeApplication(data.restrictedBackupMode, null); //在此段代码前添加
MikRom做了很多判别,首要是写入装备文件,判别体系类型等,假如只需求将gadget注入,则首要代码便是下面这些,感兴趣的去能够看下MIKROM源码
public static void loadSo(String path){
String processName = ActivityThread.currentProcessName();
String fName = path.trim();
String fileName = fName.substring(fName.lastIndexOf("/")+1);
String tagPath = "/data/data/" + processName + "/"+fileName;//64位so的目录
mycopy(path, tagPath);
int perm = FileUtils.S_IRWXU | FileUtils.S_IRWXG | FileUtils.S_IRWXO;
FileUtils.setPermissions(tagPath, perm, -1, -1);//将权限改为777
File file = new File(tagPath);
if (file.exists()){
Log.e("mikrom", "load so src:"+path+" to:"+tagPath);
System.load(tagPath);
file.delete();//用完就删不然不会更新
}
}
fridagadget.config.so装备
{
"interaction": {
"type": "listen", //形式,有listen、Connect、script、ScriptDirectory四种
"address": "0.0.0.0", //侦听地址,支持IPV4和IPV6
"port": 27042, //侦听端口
"on_port_conflict": "fail", //两种形式,fail和pick-next,fail:端口被占用则不发动,pick-next:继续测验下一个端口直到端口可用
"on_load": "wait" //两种形式resume和wait,wait:会等待附加,resume:不会
}
}
添加可修正的properties
我们能够看到,经过zygote添加gadget时使用了GetProperty来获取gadget的path和需求注入的App的packageName,可是假如编译user版别是无法自定义properties的,此刻能够经过修正build/make/tools/buildinfo.sh和system/core/init/property_service.cppproperty_service.cpp来添加
# buildinfo.sh
echo "fd.gdpath64=/system/lib64/gdpath.so"
// property_service.cpp
// 在CheckMacPerms办法中回来前添加如下内容
if (StartsWith(name, "fd.")) { return true; }
此刻即可完成自定义以fd开头的properties,假如需求其他的计划可根据需求修正。
编译
开端编译
#激活环境
source ./build/envsetup.sh
#设置编译版别
lunch
#或许
lunch aosp_sailfish-user
# 设置编译线程
make -j2
其他编译相关指令
# 部分编译
mmm frameworks/base # 编译指定目录且不编译依靠
mm #编译当时途径下的模块且不编译依靠
mmma frameworks/base # 编译指定目录且编译依靠
# 修正躲藏API:@hide,必须先履行以下指令
make update-api
# 将部分编译后的模块打包进img
make snod
其他记载
Repo常用指令
repo相关指令 – 张大猛 – 博客园 (cnblogs.com)
# 创立分支
repo start YOURBRANCH --all
# 遍历并履行git指令
repo forall -c git xxx
# 切换分支
repo forall -c git checkout default
# 丢弃分支
repo forall -c git git reset --hard HEAD
# 检查每个目录下的分支并且打印目录途径
repo forall -p -c git branch # -p参数在遍历到每个仓库的时候先打印出当时的途径再履行git指令
# 检查分支
repo branch
# add
# commit...
问题记载
-
编译失利
ninja: build stopped: subcommand failed. 14:52:38 ninja failed with: exit status 1
解决计划1:测验:在~/.bashrc中添加 export LC_ALL=C
解决计划2:检查是否使用的为JDK8
解决计划3:看看是否内存不足,假如内存不足则削减编译线程或添加内容和swap
sudo dd if=/dev/zero of=/swapfile bs=1G count=12 sudo mkswap -f /swapfile sudo swapon /swapfile sudo swapoff /swap rm /swap sudo vim /etc/fstab #将里边的swap文件名改成新的swapfile
-
模拟器发动失利
# 呈现: context mismatch in svga_surface_destroy # 履行 export SVGA_VGPU10=0
-
假如是Ubuntu 20.04.2 LTS全新装置,则可能没有Python2,此刻会报错
/usr/bin/env 'python' no such file or directory
,解决办法如下(可是,编译旧版别时还是需求装置python2的,因为部分编译脚本为Python2,目前编译9.0版别时需求装置Python2):sudo ln -s /usr/bin/python3 /usr/bin/python