Android FrameWork学习(二)Android系统源码调试
2018-03-03 08:12
609 查看
点击打开链接通过上一篇 Android FrameWork学习(一)Android 7.0系统源码下载\编译 我们了解了如何进行系统源码的下载和编译工作。
为了更进一步地学习跟研究 Android 系统源码,今天我们来讲讲如何进行 Android 系统源码的调试,只有学会了如何进行系统源码的调试,才能帮助我们更高效地阅读跟理解源码。
我们知道,Android Framework 的代码主要由Java、C\C++等代码组成,因此,对于系统源码的调试,我们这里将其分为了两部分
1. Java 相关代码的调试
2. C\C++ Native 相关代码的调试
它位于我们所下载的系统源码路径中:
引用 README 的一句话
IDEGen automatically generates Android IDE configurations for IntelliJ IDEA
and Eclipse.
idegen 工具会自动生成针对 Android 开发工具(Android Studio和Eclipse)的配置文件。
既然如此,那我们就来使用 idegen 工具生成导入源码所需的配置文件。
首先打开命令行工具,cd 进入到源码路径下,
执行如下指令:
2
3
4
5
6
在执行完上述指令后,会在源码路径下生成下面三个文件
android.ipr:工程相关的设置,比如编译器配置、入口,相关的libraries等。
android.iml:描述了modules,比如modules的路径,依赖关系等。
android.iws:包含了一些个人工作区的设置。
如果你是第一次导入源码, Android Studio 可能需要占用大量的内存,我们需要设置下我们的 VM 选项。
Linux 设备的话在 Android Studio 的
如果你使用的是 Mac ,那么在 AS 目录的
由于 Android 的系统源码非常庞大,一次性导入 Android Studio 的话需要加载非常长的时间
因此,在正式开始导入前,我们可以打开 android.iml 文件根据自己需要调整要加载的源码。
这里
接着,选择
这时 Android Studio 就会开始加载源码了
在没有添加修改
这里红色的目录代表被 exclude 排除了,代码加载 scan index 的时候会过滤掉该目录。
在加载完源码后,我们也可以在 Project Structure 中的 Module 选项中右键 exclude 来排除不需要加载的源码目录,如图:
首先是 AOSP 源码的跳转,我们通过
然后是 SDK 的设置,确保关联对应版本的 SDK 于系统版本一直
确保 Android Studio 允许 ADB 调试
接着我们参照上一篇文章中讲的方法打开 Android 模拟器
此时点击 Android Studio 工具栏的 attach debugger to Android process 按钮,会打开 Choose Process 窗口,我们根据自己需要调试的代码选择对应的进程:
这里假设我们要调试 Android 自带浏览器的源码,如图,我们在它的入口文件 WebViewBrowserActivity 中的 loadUrlFromUrlBar 方法中打上断点。
点击 WebViewBrowser 打开 app
打开之后,点击 attach to Android process 按钮打开 choose Process,可以看到 webViewBrowser 运行的进程,选中,ok
然后我们在 app 的 url 输入栏输入 网址进行跳转
如图所示我们可以看到,代码成功进入了断点,然后我们就可以随心所欲地调试我们想要的调试的 Java 代码了。
对于使用习惯了可视化 IDE 的同学们来说,它最大的缺点可能就是它不支持图形化了
但是 GDB 提供的指令非常灵活,通过指令我们
* 可以随心所欲地启动程序,
* 可以根据自己的需要设置断点,
* 可以查看断点处的变量,代码信息
* 可以查看程序运行的调用栈
一旦你熟悉了它,你便可以玩得飞起!
一般情况下,使用 gdb 来调试 Android 源码需要在 Android 设备上安装 gbdserver attach 关联我们需要调试的进程,再使用 gdb 指令去连接 gdbserver 进行调试
不过官方给我们提供了 gdbclient 工具,可以让我们方便地进行 gdb 调试。
跟上面 Java 调试一样,我们这里还是以系统自带的浏览器为例。
2
3
4
5
6
2
如图,2157 为系统自带浏览器 app 所在进程的 PID
2
等待进入 gdb 调试命令界面
这里我们选择 frameworks/base/libs/hwui/renderthread/DrawFrameTask.cpp 代码文件的 drawFrame 方法打上断点,位于文件 71 行:
该方法主要用于绘制帧,当浏览器 app 的界面发生变化时会触发该方法。
我们输入设置断点命令:
输入指令后显示
Breakpoint 2 at 0x7f69e9892c11: file frameworks/base/libs/hwui/renderthread/DrawFrameTask.cpp, line 71.
说明我们的断点设置成功了。
c 即 continue,此时界面上出现 Continuing 说明开始监听进程了
我们点开模拟器,随意操作,触发界面变化时,便会进入绘制帧的代码断点了:
如图,显示进入断点,这样代表我们的代码调试成功了。
这里我们只是演示了一个大概流程,
gdb 代码的调试需要你对源码有一定的熟悉,知道哪个进程会调用哪个文件方法。
同时,我们还需要熟悉 gdb 的各种命令,这里给大家推荐一篇不错的入门文章,可以快速入门:
GDB十分钟教程
这里补充一点,如果你希望在某个进程启动时就监听,可以使用下面的指令关联目录,得到 pid,再通过 gdbclient 来进行调试
2
3
如果你希望通过 Android Studio 来调试 Framework 的 C\C++ 代码的话,也可以参考下面的两篇文章,不过个人觉得这种方法有一定的局限性。
如何调试Android Native Framework
用Android Studio调试Framework层代码
为了更进一步地学习跟研究 Android 系统源码,今天我们来讲讲如何进行 Android 系统源码的调试,只有学会了如何进行系统源码的调试,才能帮助我们更高效地阅读跟理解源码。
我们知道,Android Framework 的代码主要由Java、C\C++等代码组成,因此,对于系统源码的调试,我们这里将其分为了两部分
1. Java 相关代码的调试
2. C\C++ Native 相关代码的调试
一、Java 相关代码的调试
对于 Java 相关代码的调试,这里我们主要使用 Android Studio 开发工具来进行。导入源码到 Android Studio
要在 Android Studio 中调试源码,那第一步自然是导入系统源码到 Android Studio 中了。1. 编译 idegen
对于 Android 源码的导入, Google 官方给我们提供了一个很方便的工具 idegen它位于我们所下载的系统源码路径中:
developement/tools/idegen1
引用 README 的一句话
IDEGen automatically generates Android IDE configurations for IntelliJ IDEA
and Eclipse.
idegen 工具会自动生成针对 Android 开发工具(Android Studio和Eclipse)的配置文件。
既然如此,那我们就来使用 idegen 工具生成导入源码所需的配置文件。
首先打开命令行工具,cd 进入到源码路径下,
执行如下指令:
#初始化命令工具 soruce build/envsetup.sh #编译 idegen 模块,生成idegen.jar mmm development/tools/idegen/ #生成针对 Android 开发工具的配置文件 sudo ./development/tools/idegen/idegen.sh1
2
3
4
5
6
在执行完上述指令后,会在源码路径下生成下面三个文件
android.ipr:工程相关的设置,比如编译器配置、入口,相关的libraries等。
android.iml:描述了modules,比如modules的路径,依赖关系等。
android.iws:包含了一些个人工作区的设置。
2. 导入源码
接下来我们可以开始导入源码了.如果你是第一次导入源码, Android Studio 可能需要占用大量的内存,我们需要设置下我们的 VM 选项。
Linux 设备的话在 Android Studio 的
bin/studio64.vmoptions文件中添加
-Xms748m -Xmx748m,
如果你使用的是 Mac ,那么在 AS 目录的
Contents/Info.plist目录中进行添加。
由于 Android 的系统源码非常庞大,一次性导入 Android Studio 的话需要加载非常长的时间
因此,在正式开始导入前,我们可以打开 android.iml 文件根据自己需要调整要加载的源码。
这里
<excludeFolder>表示不需要加载的目录,我们根据自己的需要使用
<excludeFolder>标签添加对应的目录地址即可。
接着,选择
File -> open选中 android.ipr 文件,打开
这时 Android Studio 就会开始加载源码了
在没有添加修改
<excludeFolder>的情况下,这个加载的时间会比较长,经过一段时间的等待后,代码就加载完毕了,如图:
这里红色的目录代表被 exclude 排除了,代码加载 scan index 的时候会过滤掉该目录。
在加载完源码后,我们也可以在 Project Structure 中的 Module 选项中右键 exclude 来排除不需要加载的源码目录,如图:
3. 配置代码依赖,确保代码跳转正确
为了阅读和调试代码的时候能够保证代码跳转正确,我们需要配置下相关依赖。首先是 AOSP 源码的跳转,我们通过
File -> Project Structure打开 Module,然后选中 Dependencies, 保留 JDK 跟 Module Source 项,并添加源码的 external 和 frameworks 依赖,如图:
然后是 SDK 的设置,确保关联对应版本的 SDK 于系统版本一直
开始调试源码
调试前要设置 Project 的 SDK ,File -> Project下打开 Project Structure,选中 Project 设置对应版本的 SDK,于系统版本一致:
确保 Android Studio 允许 ADB 调试
接着我们参照上一篇文章中讲的方法打开 Android 模拟器
此时点击 Android Studio 工具栏的 attach debugger to Android process 按钮,会打开 Choose Process 窗口,我们根据自己需要调试的代码选择对应的进程:
这里假设我们要调试 Android 自带浏览器的源码,如图,我们在它的入口文件 WebViewBrowserActivity 中的 loadUrlFromUrlBar 方法中打上断点。
点击 WebViewBrowser 打开 app
打开之后,点击 attach to Android process 按钮打开 choose Process,可以看到 webViewBrowser 运行的进程,选中,ok
然后我们在 app 的 url 输入栏输入 网址进行跳转
如图所示我们可以看到,代码成功进入了断点,然后我们就可以随心所欲地调试我们想要的调试的 Java 代码了。
二、Native C\C++ 相关代码调试
对于 Framework Native 代码,我们这里使用 GDB 工具来进行调试。什么是 GDB 呢?
它是一款 GNU 项目调试工具,它的功能非常强大,可以用来调试 C 、C++、Object-C、Pascal 等语言编写的项目。对于使用习惯了可视化 IDE 的同学们来说,它最大的缺点可能就是它不支持图形化了
但是 GDB 提供的指令非常灵活,通过指令我们
* 可以随心所欲地启动程序,
* 可以根据自己的需要设置断点,
* 可以查看断点处的变量,代码信息
* 可以查看程序运行的调用栈
一旦你熟悉了它,你便可以玩得飞起!
一般情况下,使用 gdb 来调试 Android 源码需要在 Android 设备上安装 gbdserver attach 关联我们需要调试的进程,再使用 gdb 指令去连接 gdbserver 进行调试
不过官方给我们提供了 gdbclient 工具,可以让我们方便地进行 gdb 调试。
开始 GDB 调试
这里我们就基于 gdbclient 来进行实际的 gdb 调试演示:跟上面 Java 调试一样,我们这里还是以系统自带的浏览器为例。
1. 点击启动图标打开浏览器 app:
2. 打开一个命令行终端,cd 进入到系统源码目录(我的源码路径为 aosp),初始化命令工具:
#进入源码路径 cd aosp #初始化命令工具 source build/envsetup.sh #选择编译的源码的版本,参考上一篇文章 lunch1
2
3
4
5
6
3. 通过 adb 指令来查找要调试进程的 PID
#通过 shell ps 指令查找相关进程,grep 搜索过滤 webview 进程 adb shell ps -A | grep webview1
2
如图,2157 为系统自带浏览器 app 所在进程的 PID
4. 使用 gdbclient 命令工具启用 gdb 调试 PID 对应进程
# gdbclient <app pid> 可以启用 gdb 调试对应 PID 进程 gdbclient 21571
2
等待进入 gdb 调试命令界面
5. 使用 GDB b 命令打断点
在 gdb 指令中,我们使用b <代码文件>:行号来设置断点.
这里我们选择 frameworks/base/libs/hwui/renderthread/DrawFrameTask.cpp 代码文件的 drawFrame 方法打上断点,位于文件 71 行:
该方法主要用于绘制帧,当浏览器 app 的界面发生变化时会触发该方法。
我们输入设置断点命令:
b frameworks/base/libs/hwui/renderthread/DrawFrameTask.cpp:711
输入指令后显示
Breakpoint 2 at 0x7f69e9892c11: file frameworks/base/libs/hwui/renderthread/DrawFrameTask.cpp, line 71.
说明我们的断点设置成功了。
6. 在命令行输入c 开始监听
c 即 continue,此时界面上出现 Continuing 说明开始监听进程了
我们点开模拟器,随意操作,触发界面变化时,便会进入绘制帧的代码断点了:
如图,显示进入断点,这样代表我们的代码调试成功了。
这里我们只是演示了一个大概流程,
gdb 代码的调试需要你对源码有一定的熟悉,知道哪个进程会调用哪个文件方法。
同时,我们还需要熟悉 gdb 的各种命令,这里给大家推荐一篇不错的入门文章,可以快速入门:
GDB十分钟教程
这里补充一点,如果你希望在某个进程启动时就监听,可以使用下面的指令关联目录,得到 pid,再通过 gdbclient 来进行调试
adb shell gdbserver :5039 /system/bin/my_test_app Process my_test_app created; pid = 3460 Listening on port 50391
2
3
gdbclient <app pid>1
如果你希望通过 Android Studio 来调试 Framework 的 C\C++ 代码的话,也可以参考下面的两篇文章,不过个人觉得这种方法有一定的局限性。
如何调试Android Native Framework
用Android Studio调试Framework层代码
相关文章推荐
- Android FrameWork学习(二)Android系统源码调试
- android系统源码目录system/framework下各个jar包的用途
- Android源码学习之八—系统启动过程
- android系统源码目录system/framework下各个jar包的用途
- android系统源码目录system/framework下各个jar包的用途
- Android系统源码学习步骤
- android系统源码目录system/framework下各个jar包的用途
- android系统源码目录system/framework下各个jar包的用途
- android系统源码目录system/framework下各个jar包的用途
- Android系统源码学习步骤
- Android源码开发----usb调试的开关以及系统配置信息
- Android源码学习之八—系统启动过程
- Android Framework学习——Launcher启动应用程序过程源码分析
- 如何编译android 4.1 的源码并在android的ADT里面调试framework相关的代码
- Android源码学习—系统启动过程
- Android源码学习之八—系统启动过程
- android系统源码目录system/framework下各个jar包的用途
- 从零开始--系统深入学习android(理论--开发前准备--开发入门--DDMS调试)
- 在android源码中调试系统浏览器代码
- Android源码学习之八—系统启动过程