标签:
在Android安全的研究工作中,我们时常要对Android进行改进并对其进行源码编译,由于目前几乎所有的手机厂商均对其底层驱动实行封闭政策,导致我们在完成Android编译后无法将我们编译好的系统刷到普通的Android手机上,因此在一般的科学实验中我们更多的是将修改好的android源码编译成模拟器,以模拟器的形式证明实验的成功与否。
事实上,Android作为一款开放源代码的移动设备操作系统,Google最初就考虑到了真机编译的问题,而关于这个问题的解决方案体现在每次Google I/O大会发布的官方手机,即Nexus系列手机上。Nexus系列手机作为Google发布的Android标杆机,不仅在一定程度上代表和引领了该年度的Android手机发展方向,更解决的开发者真机编译源码的问题。此系列设备采用了完全开放设备的层驱动的形式使得开发者可以实现将自己的源码烧录到真机的功能,从而使得源码编译真机调试不再是难题。下面,我就来介绍一下这项工作是如何完成的。
实验设备:Nexus5(日版 D821)。
实验环境:Ubuntu14.04 (x64) + JDK 1.7 + python 2.7.6 + make 3.81
首先要声明的一点是,这是一部零基础教程,上述实验环境是作者电脑最初的状态,它不一定符合我们此次试验的要求,因此会在后面逐步完善实验环境,这样写的目的也是为了将我在实验中所遇到的问题以及解决方案原原本本展示给大家,让大家少走一些弯路。
我们参照android opensource project官网(http://source.android.com/source/requirements.html)上的guide来进行实验,在AOSP的guide中对编译的硬件要求和软件要求做出了详细的规定。此次我们要编译的源码是Android 4.4.x版本,根据官网中的信息,我们要使用64位Ubuntu进行编译,并且至少有100G的磁盘空间;在软件方面,由于我们编译的是4.4.x (Kitkat) 版本的源码,因此需要JDK 1.6,除此之外,official guide中还有一些其他要求:Python2.6 -- 2.7,GNU Make 3.81 -- 3.82,Git1.7 or newer(这里我们不需要配置git,因为在officialguide中源码的获取是通过git + repo在线下载完成的,而我们采取另一种方式获取源码)。
在我的编译环境中,操作系统为64位Ubuntu 14.04,磁盘空间预留100G,JDK版本为1.7,make 版本3.81,python 版本2.7.6。
现在我们可以发现,java环境的版本比要求的jdk 1.6要高,因此下面,我们需要进行jdk的降级工作。
首先我们要找到jdk 1.6的包,目前在oracle的官方网站上已经无法下载了,只能自己百度。在此我提供一个jdk 1.6 for Linux x64的安装包供大家使用:http://pan.baidu.com/s/1c2e8x6S。
Jdk 1.6的安装包是一个bin文件,我们需要先安装它。
把这个文件放到你自己定义的地方,这里我放到了Home下的java文件里,当然也可以放在别的地方。首先要修改这个文件的权限,否则直接安装会报错,系统会告诉你权限不够。
chmod 777 jdk-6u45-linux-x64.bin
修改完权限后就可以运行安装了。
./jdk-6u45-linux-x64.bin
这个过程其实就是生成了jdk的目录。
Jdk1.6的目录生成后,我们需要修其改环境变量,原有的java变量是在/etc/profile中配置的,在此只需要修改此文件中的环境变量就可以了。
修改之后只需使/etc/profile生效即可。
source /etc/profile
执行这个命令之后,重启。
然后我们可以查看一下是否生效:java –version
修改成功!
有的环境中可能会出现make版本不符合要求的情况,针对这种情况可以参考这篇博客:http://blog.csdn.net/lr2131/article/details/45673603(内附make下载地址和安装指南)。
另外,在编译环境的配置上,我们还需要安装一些依赖包,Google在AOSP official guide 中已经给出了不同版本的Ubuntu需要安装哪些依赖(http://source.android.com/source/initializing.html),摘录如下:
在准备好了编译环境后,我们就该准备要编译的源码了。此次实验的目标是将Android4.4.x编译后烧录到Nexus 5上,由于Google的官方设备目前已经更新至第七代,而且种类繁多,不仅有智能手机,还有平板电脑,智能手表,笔记本电脑等其他智能设备,而且不同代次的设备所兼容的源码版本也是处在一定范围内的。因此,Google对Android源码构建了种类繁多而又详细的分支,使其分别适配不同的设备,例如:分支android-5.1.1_r3( build: LMY48B )只支持Nexus 5,而android-5.1.1_r1(build: LMY47V )支持的是Nexus 7 (flo/grouper), Nexus 10, Nexus Player;由于存在不同的运营商定制版设备,不同的运营商定制的设备甚至都不能共用一个分支的源码,例如:android-5.1.1_r4( build: LMY47Z )支持除T-Mobile美国之外的所有Nexus6设备,而T-Mobile定制版本的Nexus 6设备则需要android-5.1.1_r5( build: LYZ28E )分支来支持。综上所述,我们可以得出结论,在真机编译中,选择正确的源码分支至关重要,否则一旦没有选择对,耗费了大量的时间进行编译,即便烧录到真机中也会出现开不了机的情况(最常见的就是手机开机后卡在Google的开机界面中)。
首先,我们需要确定我们的设备所对应的源码分支是哪一个,我的设备是日版Nexus 5 (即D821)Nexus 5手机只分两个大的版本:D820和D821,D820是面向美国本土发售的机型,俗称美版,D821是除美版之外的所有版本,即所谓亚太版。当然,在不同国家和地区也会有不同的运营商定制版本,针对这种情况也要注意,看看有没有对应专有的源码分支。我们可以通过http://source.android.com/source/build-numbers.html来查询自己的设备属于对应的源码分支,由于我们要编译的是Android 4.4.x版本的源码,因此只列出此版本的分支与设备的对应关系:
先来解释一下表格中每一列代表什么:
第一列是build代码,我们根据build码查找对应设备的驱动程序,并下载之。
第二列是分支(branch)代码,不同的分支会对应不同的设备。
第三列是Android版本代号,这里我们关注的是4.4系列的版本,因此是KitKat。
第四列是对应的设备名称,值得注意的是,同一设备即便是不同运营商发布的也可能使用不同分支的源码,例如android-4.4.4_r2就是只针对上述运营商的定制版本的分支,而r1就支持其余的Nexus 5设备。
这里,我们选择android-4.4.4_r1进行编译,因为它支持我的设备。注意要记住这个分支的build号:KTU84P,后面我们要用这个码查找对应的设备驱动并下载。
Official guide中获取源码的方式是通过git+ repo的方式在线获取,而由于Android源码的网站https://android.googlesource.com/在正常情况下无法访问,因此我们不采取官方提供的方式获取源码。事实上,我们在百度上查找一下就会发现有很多已经下载并打包好的安卓源码,比如百度网盘中就有很多,我也是从百度网盘上找到的,在此分享一下我所需源码的链接,供大家下载使用:http://pan.baidu.com/s/1skJjkfj。注意,在解压时最好是在Linux下直接解压,切勿在Windows环境中使用图形化工具,如2345好压。亲测证明,使用图形化界面解压会导致源码中缺失文件和文件夹。我提供的源码是一个7z格式的压缩包,在Linux下解压此种格式的文件的方法可参见:http://www.educity.cn/linux/1241489.html。
在编译工作开始之前,我们可以使用编译器高速缓存工具complier cache(ccache)来加快编译速度。首先,我们在环境变量中加入:
export USE_CCACHE=1
并使环境变量文件生效。然后,我们在命令行执行
prebuilts/misc/linux-x86/ccache/ccache -M 50G
即可。
下载好源码之后,我们要将驱动文件加入源码中。我们可以在https://developers.google.com/android/nexus/drivers#hikey中找到对应设备与源码分支的硬件驱动。此时,上一步中的build码就该派上用场了,我们根据build码来找到对应的驱动程序,我们刚才选择的源码分支所对应的build码是KTU84P,因此,就下载此代号的驱动程序即可。
下载得到的是三个tgz文件,我们只需依次解压三个文件,得到的是三个shell脚本文件,我们先将其置于源码根目录中。
依次执行这三个脚本文件,这里要注意,三个脚本文件的作用是生成驱动文件,但是在执行操作前,它会让你阅读相关协议,你必须一直按enter键一行一行往下读,更不能一键摁到底,因为程序在最后会让你输入“I ACCEPT”,如果你一键摁到底,也就是说最后一步也摁enter键的话它就会执行默认操作,即不接受此协议,那生成驱动文件的操作就不会执行。这里有个小窍门,一直摁住enter,注意命令行中闪过的协议项,当读到第八项时可以放慢速度,一下一下的摁enter键了,最后慢慢的到最后一步,输入I ACCEPT即可。这三个文件都是这样的操作流程。上图展示了在执行完脚本文件后生成的驱动文件目录。
在完成了以上任务之后,我们就可以进行源码的编译工作了。首先,我们在terminal中进入Android源码所在目录,我就把我的源码放在了Home下。
初始化编译环境,输入
. build/envsetup.sh
会出现这样的效果。
加载机型,输入lunch命令,会列出不同设备可能编译出的结果。
在这一步中,我们选择6号:aosp_hammerhead_userdebug,因为我们的Nexus 5设备代号就是hammerhead。
aosp则代表着编译出的系统是纯净的、没有Google服务框架的。而buildtype也分为user、userdebug和eng,具体区别见下图。
在选择好设备之后,系统会生成详细的编译信息,这里我们可以再确认一下源码的分支,build号是否正确。
然后我们就可以进行编译了,输入make –j16 或make –j8,j后面的参数取决于你电脑处理器的核心数,j=核心数*2,由于我的电脑是8核的,因此我选择
make –j16
在经过将近三个小时的编译后,我们的源码终于编译完成,而此时,在源码根目录中多出了一个out目录,编译的结果就存放在里面。
源码编译完成后,我们开始将编译好的系统烧录进手机中。首先,先将我们的Nexus 5连接到电脑上,注意一定要打开USB调试,连接后手机可能会提示电脑要调试这台手机,允许即可。然后,我们令手机进入recovery模式,还是刚才的terminal(在源码根目录下),输入以下命令:
sudo adb reboot bootloader
随后手机就会进入recovery模式。
然后,我们开始刷机:
fastboot flashall –w 或者 fastboot -w flashall
刷机的过程大概在一至两分钟左右,刷机结束后会自动开机。
刷机成功,我们看到了我们编译好的原生aosp版本的源码。
标签:
原文地址:http://blog.csdn.net/liu1075538266/article/details/51272398