如果Android程序员想往更高一级发展,对Android系统的了解深入程度决定了你以后的终点。所以对于系统源码的了解可谓事半功倍。如果我们死扛源代码,会浪费很多时间在判断代码走哪个分支上面,对于一些多层嵌套的代码,基本上到后面就忘记前面到底走哪个分支了。如果能够实时看到程序的流程,那么对于我们理解的吃透代码就非常有价值了。
本文将从代码下载,编译,生成AS项目文件,导入和调试入手,让读者可以从无到有搭建出一个可用的Android源码调试环境。
AS版本:Android Studio 2.1.1
Ubuntu 版本: ubuntu 14.04 LTS
JDK版本: openjdk version “1.8.0_91”
清华大学TUNA镜像源非常贴心的提供了AOSP代码的最新版本,代码下载方法参考他们的官方说明文档。下面有一个简化的命令,方便大家晚上挂机下载,这样晚上的时间就利用上了。
wget -c -t 0 https://mirrors.tuna.tsinghua.edu.cn/aosp-monthly/aosp-latest.tar && tar xf aosp-latest.tar && cd AOSP && repo sync
上面用&&串起来的四条命令用中文描述就是:
用断点续传的方式下载aosp-latest.tar文件,下载完成之后用tar解压这个文件,解压完成进入AOSP文件夹,并且用repo sync来同步最新代码
注意参考里面的文档安装repo命令。
下载并解压完之后,使用下面的命令来编译:
source build/envsetup.sh && lunch 1 && make -j8
其实两条命令也可以合并,这样第二天就不用再花时间编译了。
wget -c -t 0 https://mirrors.tuna.tsinghua.edu.cn/aosp-monthly/aosp-latest.tar && tar xf aosp-latest.tar && cd AOSP && repo sync && source build/envsetup.sh && lunch 1 && make -j8
这样就可以用晚上的非工作时间来下载Android源码,下载下来的压缩过的tar代码文件有26.8G,编译之后代码(包含tar包)有76.1G左右(具体大小要看你选择编译的项目,所以最好预留80G,推荐100G空间)。
参考腾讯公司提供的一个SDK更新镜像站点。更新所有的API 23下面的内容,包括sdk源码,镜像那些。因为站点是在国内,所以更新速度也是蛮快的。感谢鹅厂提供这一个方便的途径升级SDK和AS。
如果编译通过之后,可以使用AOSP代码自带的idegen命令来生成IDE工具用到的项目配置文件。执行:
mmm development/tools/idegen/
development/tools/idegen/idegen.sh
第二条命令可能耗时稍久,如果运行成功会显示如下信息:
Read excludes: 5ms
Traversed tree: 367564ms
会在源码根目录AOSP下面生成android.ipr和android.iml两个工程配置文件。对于android.iml需要特别说明,最好在这个里面添加如下的过滤器,免得AS加载系统源码花太长时间。
编辑该文件,添加:
<excludeFolder url="file://$MODULE_DIR$/.repo" />
<excludeFolder url="file://$MODULE_DIR$/abi" />
<excludeFolder url="file://$MODULE_DIR$/art" />
<excludeFolder url="file://$MODULE_DIR$/bionic" />
<excludeFolder url="file://$MODULE_DIR$/bootable" />
未验证的另外一个过滤方式,删除所有的module-library项。忍受不了的朋友可以试试。
同时因为在加载源码并保存的时候会提示根目录没有AndroidManifest文件,所以在根目录手动添加一个AndroidManifest.xml文件,内容为:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-sdk android:minSdkVersion="23" />
</manifest>
在导入之前先调整AS的内存配置,加大内存。修改/home/wubaiyu/android-studio/bin/studio64.vmoptions(如果是32位系统就改studio.vmoptions)文件的如下几项:
-Xms1024m
-Xmx1280m
-XX:MaxPermSize=350m
后面的数值取决于你的物理内存大小。
在上一小节中,我们生成了项目配置文件,这个是idegen脚本生成的整个系统源码的配置文件,所以我们打开AS的时候,选择导入已有项目这个选项,导入AOSP这个源码目录。
剩下的就是等等等了!!!导入之后,会显示有很多错误信息,无视即可,我们后面也是可以跳转到相关的代码的。
载入完成之后,点击下图扳手图标右边的图标(Project Structure)。
会弹出Project Structure的设置窗口,设置Android API 23 Platform为仅对当前项目有效。(注,不需要使用1.8 noLibrary。在参考的文章里面有,但是我这里并没有用到。)
同时在该界面的Project中设置SDK和JDK:
并且在Modules界面设置如下:
选中中间的android,然后点+号会在下拉里面显示有Android这个选项,选择Android就可以添加到下面了。右边的Dependencies里面先删掉除了最上面两项之外的所有list,然后点击+号,选JARs or directories”,将源码目录里面的external文件夹和frameworks文件夹添加进来。AS会扫描这两个文件夹下面的所有JAR文件,所以会花一些时间。
特别注意,我们上面建立的都是Android API 23和JDK 1.8的配置,所以我们创建模拟器的时候,一定要创建对应SDK版本的,否则肯定是没法正常调试的。如下所示,创建第二个Nexus 5X API 23模拟器.
我们一Settings模块为例,演示如何调试。更详细的内容参考weishu的文章如何调试Android Framework?,非常详细,人非常好,帮我解决了很多疑问。
各位老司机应该不用我说就知道怎么找Settings模块的入口了吧。对于新手的话,分下面两步就可以找到入口了:
第一步. 找Settings模块的AndroidManifest文件,找里面的包含如下intent-filter的项
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
第二步,找到这个类,顺藤摸瓜找到他的父类SettingsActivity,并在其onCreate和onResume函数中打断点。因为有时候你的Settings模块是先运行过的,所以onCreate函数并不一定会跑到,所以在onResume里面再打一个断点保险一些。
也就是将debugger附上com.android.settings这个进程,一般模拟器刚开始运行的时候,没有启动settings模块,所以并没有运行该线程,我们先点击Settings,启动之后。点击”Attach Debugger to Android process”图标
,并选择com.android.settings进程。如下所示:
一定要选中上面的“Show all processes”复选框,否则下面的进程信息是不会显示出来的。点击OK,这样调试器就附加到settings进程上面了,当模拟机上的Settings模块再次运行的时候,调试器就可以截获到该进程的信息,并且跳转到对应的语句上了。见如下界面。
注意,左下角的Debugger标签里面显示了当前断点所处的代码在onResume函数。在Run菜单下面有对应的调试命令,比如Step Over/Step Into等等。详细方法同样参考上面提到的weishu的那篇博文。
模拟器还是处于onResume的状态,如下:
所以,综上所示,我们已经可以成功调试Android源码了。成功走出了第一步,下面的就好办了。如果想了解更多,请综合阅读参考文献里面的博文。
weishu–如何调试Android Framework?
Lefter–如何使用Android Studio开发/调试Android源码
云涛–使用Android Studio调试Android Framework代码
知乎上的相关回答–Android Studio如何调试Framework层的代码?