如果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

参考腾讯公司提供的一个SDK更新镜像站点。更新所有的API 23下面的内容,包括sdk源码,镜像那些。因为站点是在国内,所以更新速度也是蛮快的。感谢鹅厂提供这一个方便的途径升级SDK和AS。

生成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>
在Android Studio中导入源码AS内存设置

在导入之前先调整AS的内存配置,加大内存。修改/home/wubaiyu/android-studio/bin/studio64.vmoptions(如果是32位系统就改studio.vmoptions)文件的如下几项:

-Xms1024m

-Xmx1280m

-XX:MaxPermSize=350m

后面的数值取决于你的物理内存大小。

AS项目配置

在上一小节中,我们生成了项目配置文件,这个是idegen脚本生成的整个系统源码的配置文件,所以我们打开AS的时候,选择导入已有项目这个选项,导入AOSP这个源码目录。

剩下的就是等等等了!!!导入之后,会显示有很多错误信息,无视即可,我们后面也是可以跳转到相关的代码的。

载入完成之后,点击下图扳手图标右边的图标(Project Structure)。

android源码 swap设置 如何调试android源码_android

会弹出Project Structure的设置窗口,设置Android API 23 Platform为仅对当前项目有效。(注,不需要使用1.8 noLibrary。在参考的文章里面有,但是我这里并没有用到。)

android源码 swap设置 如何调试android源码_android_02

同时在该界面的Project中设置SDK和JDK:

android源码 swap设置 如何调试android源码_调试_03

并且在Modules界面设置如下:

android源码 swap设置 如何调试android源码_源代码_04

选中中间的android,然后点+号会在下拉里面显示有Android这个选项,选择Android就可以添加到下面了。右边的Dependencies里面先删掉除了最上面两项之外的所有list,然后点击+号,选JARs or directories”,将源码目录里面的external文件夹和frameworks文件夹添加进来。AS会扫描这两个文件夹下面的所有JAR文件,所以会花一些时间。

创建对应版本的模拟器

特别注意,我们上面建立的都是Android API 23和JDK 1.8的配置,所以我们创建模拟器的时候,一定要创建对应SDK版本的,否则肯定是没法正常调试的。如下所示,创建第二个Nexus 5X API 23模拟器.

android源码 swap设置 如何调试android源码_源代码_05

在AS中调试源码

我们一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里面再打一个断点保险一些。

android源码 swap设置 如何调试android源码_Android_06

将debugger附加上正确的进程

也就是将debugger附上com.android.settings这个进程,一般模拟器刚开始运行的时候,没有启动settings模块,所以并没有运行该线程,我们先点击Settings,启动之后。点击”Attach Debugger to Android process”图标

android源码 swap设置 如何调试android源码_源代码_07

,并选择com.android.settings进程。如下所示:

android源码 swap设置 如何调试android源码_android_08

一定要选中上面的“Show all processes”复选框,否则下面的进程信息是不会显示出来的。点击OK,这样调试器就附加到settings进程上面了,当模拟机上的Settings模块再次运行的时候,调试器就可以截获到该进程的信息,并且跳转到对应的语句上了。见如下界面。

android源码 swap设置 如何调试android源码_android_09

注意,左下角的Debugger标签里面显示了当前断点所处的代码在onResume函数。在Run菜单下面有对应的调试命令,比如Step Over/Step Into等等。详细方法同样参考上面提到的weishu的那篇博文。

模拟器还是处于onResume的状态,如下:

android源码 swap设置 如何调试android源码_android_10

总结

所以,综上所示,我们已经可以成功调试Android源码了。成功走出了第一步,下面的就好办了。如果想了解更多,请综合阅读参考文献里面的博文。

参考文献

weishu–如何调试Android Framework?

Lefter–如何使用Android Studio开发/调试Android源码

云涛–使用Android Studio调试Android Framework代码

知乎上的相关回答–Android Studio如何调试Framework层的代码?