前言
一直是在source insight上直接看android源码,可是一直没有调试过,而调试才能对代码了解的更加深刻,所以就想到了自己编译rom,然后动态调试各个系统Service。这篇文章记录了2天的忐忑的编译历程。
环境
手机:nexus6p(已经解锁)
电脑:ubuntu 16.04(ubuntu-16.04.2-desktop-amd64.iso),
提醒:
硬盘剩余容量100G以上(第一次安装时linux分配了80G,结果编译到90%左右时提示 backend i/o error,最后只好格掉硬盘重新安装linux)。
准备工作
1 翻墙上网,公司网络提供了翻墙服务,所以这一步我就省了,公司网络还不错,一个晚上就把代码下载下来.
2 gmail邮箱,在下载源码的过程中,谷歌为了防止匿名连接过多,对同一个ip的访问次数进行了限制,这就导致我们下载过程中很可能会失败,因此我们需要用一个谷歌账号(也就是Gmail邮箱)来进行验证。
下载源码
1. 安装git
sudo apt-get install git
2. 配置git
这里用户名可以随便写,但是邮箱请务必使用你的Gmail邮箱,因为涉及到下面的访问验证
git config --global user.name "Your Name" git config --global user.email "Your Gmail@gmail.com"
3. google账号验证:
对于匿名访问,为了防止连接过多,谷歌对同一个ip的访问次数进行了限制,所以我们需要添加一个下载验证,打开下面的链接:
https://android.googlesource.com/new-password
登录谷歌账号,会看到下面的界面:
通过复制下面框中的脚本代码到shell中,为Git配置cookie,用于访问谷歌服务。
我们使用的是Ubuntu,所以我们打开shell窗口,将下面框框的代码一行一行的复制到shell中执行,复制一行执行一行就可以了。
4. 安装repo
android源码包括很多模块,每个模块都是一个个工程,不同版本依赖不同模块,总不能一个一个去下载这些工程吧,所以为了管理这些工程,谷歌开发了一个管理Git仓库的工具叫repo,官网的安装教程是这样的:
首先创建bin文件夹:
$ mkdir ~/bin $ PATH=~/bin:$PATH
下载repo工具:
$ curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo $ chmod a+x ~/bin/repo
5. 选择合适的源码版本
android源码除了大版本外还有很多小版本,例如:android-7.1.1_r31,7.1.1就是大版本号,r31就是小版本号,因此我们需要先确定好需要下载的版本号,具体有哪些版本请看下面的链接:
https://source.android.com/source/build-numbers.html#source-code-tags-and-builds
由于我的手机是nexus 6p 所以我选择了以下版本:
第一列是编译的代号,第二列是版本号,第三列是版本名称,最后一列是该版本支持的手机型号,请下载与你手机对应的版本。
5. 开始下载源码
确定了版本号之后,首先创建文件夹,这里以版本号命名:
$ mkdir android-7.1.1_r31 $ cd android-7.1.1_r31
初始化repo,注意把 -b 后面改为你要下载的版本号:
$ repo init -u https://android.googlesource.com/platform/manifest -b android-7.1.1_r31
使用下面的命令就可以开始下载了:
$ repo sync
但是,请先不要着急下载,由于下载过程中还会遇到各种各样的问题,所以我们需要创建一个自动下载脚本,确保出错了之后会自动执行repo sync,在 android-7.1.1_r31下创建一个脚本down.sh,代码如下:
#!/bin/bash repo sync -j16 while [ $? = 1 ]; do echo “======sync failed, re-sync again======” sleep 3 repo sync -j16 done
这样就可以不用执行repo sync命令了,直接执行以下命令:
chmod a+x down.sh ./down.sh
好了,开始下载源码了,android 7.1.1整个源码大概有50G左右,建议在晚上下载。在没有下载完毕之前,源码的文件夹中只有一个.repo文件夹,这是正常的,等到所有源码下载完毕,其余文件夹就会出现,不要着急。下载完毕后如下图:
看到syncing work tree: 100%..... 就说明下载成功了,道路又前进了一大步,道行且阻,行则将至。
全部下载完后android-7.1.1_r62中文件如下:
源码下载完毕后,先不要着急着编译,我们先备份一下源码,万一玩坏了还可以推倒重来,否则又要辛辛苦苦下载一遍。源码怎么这么大呢,后来发现都是.repo这个文件夹太大了,这个文件夹只是与代码同步有关,并不影响编译,删掉之后,压缩打包源码,这次只有7G左右,而且删掉之后编译成功。
首先删掉 .repo 文件夹,然后使用下面的命令备份源码:
cd ~ tar -zcvf android-7.1.1_r31.tar.gz android-7.1.1_r31/
下载完源码请务必删掉 .repo 文件夹,以便备份源码,同时防止编译时磁盘空间不够用.
编译源码
1. 安装依赖
sudo apt-get install -y git flex bison gperf build-essential libncurses5-dev:i386 sudo apt-get install libx11-dev:i386 libreadline6-dev:i386 libgl1-mesa-dev g++-multilib sudo apt-get install tofrodos python-markdown libxml2-utils xsltproc zlib1g-dev:i386 sudo apt-get install dpkg-dev libsdl1.2-dev libesd0-dev sudo apt-get install git-core gnupg flex bison gperf build-essential sudo apt-get install zip curl zlib1g-dev gcc-multilib g++-multilib sudo apt-get install libc6-dev-i386 sudo apt-get install lib32ncurses5-dev x11proto-core-dev libx11-dev sudo apt-get install lib32z-dev ccache sudo apt-get install libgl1-mesa-dev libxml2-utils xsltproc unzip m4
Ubuntu 16.04请务必使用上面的依赖,Ubuntu 16.04需要的依赖和Ubuntu 14.04所需要的依赖是不同的.
2. 安装open JDK8
从Android 6.0开始Android源码的编译需要安装OpenJDK,不能使用Oracle JDK,而且Android 7.1.1只能使用OpenJDK8, 刚开始按照其他blog安装了open-jdk7,编译时提示require java_1.8_XXXX, 果断又重新安装了一次open-jdk8。
由于Ubuntu 16.04没有OpenJDK7的源,因此在16.04上安装OpenJDK7需要执行下面的命令:
sudo add-apt-repository ppa:openjdk-r/ppa sudo apt-get update sudo apt-get install openjdk-8-jdk
检查OpenJDK配置是否正确:
java -version
配置正确则如下图:
3. 设置jack服务内存
export ANDROID_JACK_VM_ARGS="-Dfile.encoding=UTF-8 -XX:+TieredCompilation -Xmx6g"
4. 开始编译
4.1导入编译Android源码所需的环境变量和其它参数:
source build/envsetup.sh
4.2运行lunch命令选择编译目标:
lunch
选择aosp_angler-userdebug版本,这个版本才是debug 版本,可以调试。当然eng也可以。
解释一下,angler是nexus 6p的代号(code name),每个设备对应的代号如下:
userdebug 是编译类型,含义如下:
user 用于正式产品
userdebug 和user类似,但是有root权限,并且可以调试,主要用于调试
eng 开发用的选项,配有额外的调试工具。
如果编译后只在模拟器上运行,则lunch时选择:1
如果你不知道lunch该选哪一个,请参考下面的链接,根据第三列选择编译选项:
https://source.android.com/source/running.html
4.3开始执行编译:
执行make -j8, 8为同时编译的线程数,一般google推荐这个数字为2倍的cpu个数再加上2,比如4核,就是10。博主使用的是8:
make -j8
关于cpu个数,可以用下面命令查看:
cat /proc/cpuinfo
好了,开始编译了, 晚上开始编译,大约2个小时,编译成功了。(当然了上面这个过程是成功的步骤,我自己编译的时候,参考几个blog,每个blog写的不一样,所以就很痛苦, 并且有些都是过时的或者错的,但是只要相信自己能解决,当编译出错的时候不要慌张,仔细查看log提示,然后google,总能找到解决问题的答案的。比如说上面我提到的 backend i/o error,我就是通过看log才发现的。还有一个提示是源码肯定是完备的,在编译之前尽量不修改任何文件,先编译一次试试。我在编译之前看某个blog修改了一个文件,导致编译不过,我又赶紧修改了回来。)
如果在编译过程中遇到了错误,请先执行以下命令:
make clean
然后再重新编译:
source build/envsetup.sh lunch make -j8
编译成功的截图如下:
哈哈,到此为止,又前进了一大步~, 下面就是怎么把rom刷入手机了。
驱动
(1) 为何还要下载工厂镜像呢?
前面我们提到了,只有nexus系列手机放出了驱动,所以我们需要去谷歌官网获取驱动。
(2) 驱动又是以什么形式放出的呢?
在nexus 6p(5x)之前,例如nexus 5,驱动的二进制代码(当然不可能有源码啦)是压缩包的形式,下载后在aosp源码根目录下面解压,然后执行里面的sh脚本文件,接着编译全部源码就能编译出驱动镜像,谷歌一下都是这种方法,然而关于nexus 6p编译AOSP后刷机时驱动问题的资料就很少了,博主在这里卡了很长时间才搞清楚了nexus 6p刷入AOSP时如何刷入驱动的方法。
(3) 如何获取nexus 6p的驱动?
从nexus 6p(5x)起,驱动都放在了专门的vender分区中,谷歌官网上只有工厂镜像,没有二进制文件的压缩包了。我们需要下载工厂镜像,然后提取出里面的vender.img镜像,刷入nexus 6p中就可以了。当然,经过实践发现,这android7.1.1 nexus6p手机上是可以的,但是其他博主说不行,可能和版本有关系吧。
首先到谷歌官网下载工厂镜像,下载地址如下:
https://developers.google.com/android/nexus/images
根据前面下载源码时候的编译代号(Build)来选择工厂镜像:
根据源码下载那一节,我们选择的android-7.1.1_r31版本对应的build是N4F26U,所以我们下载N4F26U的工厂镜像,点击link下载镜像, 下载完成后解压:
再解压image-angler-n4f26u.zip
vender.img就是我们的驱动文件。
刷机就是将我们编译出来的系统镜像和工厂镜像里面的vernder.img用fastboot命令写入手机中,那么我们可以将image-angler-n4f26u中的镜像除vender.img以外全部替换成我们自己的,然后打包,用flash-all.sh脚本一次性刷入,省时省力。在image-angler-n4f26u下将所有文件压缩打成包image-angler-n4f26u.zip。然后将手机进入fastboot模式。执行flash-all.sh/flash_all.bat, 等待2分钟,刷机就完成了。 哈哈,刷机到此结束。
刷机完毕,开机,原生android就呈现在你面前,没有Google全家桶。电话蓝牙都正常。
就是每次开机都会弹出个对话框:
There’s an internal problem with your device. Contact your manufacturer for details
不影响使用,这个网址有解决方案。
http://blog.csdn.net/jerrywu145/article/details/56342863
下一篇文章讲讲如何基于自己编译的rom,进行Android源码级调试。
参考文章:
http://blog.csdn.net/jerrywu145/article/details/56342863
http://www.jb51.net/article/101929.htm