转载请注明出处:https://blog.csdn.net/turtlejj/article/details/83860708,谢谢~
在上一遍文章《使用Android Studio导入Android系统源码》中,我们已经介绍了如何将Android源代码导入Android Studio进行阅读,这篇文章我们开始介绍,如何使用Android Studio对系统源代码打断点并进行单步调试。
想要对手机系统进行单步调试,需要具备以下几个条件:
1. 手机的软件版本必须是userdebug或者eng,user版本的手机由于各种权限限制,是没办法进行单步调试的
2. 在"开发者选项"中打开"USB调试",否则Android Studio无法连接我们的手机 (如何调出"开发者选项"请自行百度)
3. 手机中的版本最好是当前代码编译出来的,如果版本与代码不一致,可能导致在断点断住代码时发生错行的问题
如果上述的条件都满足,那么我们就可以继续了。
举例来说,我们想要学习一下不同类型(无条件、遇忙、不可及、无应答)的呼叫转移传递给Modem的参数有哪些不同。这个时候,我们可以在RIL.java文件的setCallForward()方法中打上断点(虽然这里没什么必要,因为会打印log,不过我们只是拿这个地方来学习一下如何打断点^_^)
在代码窗口点击最左边,点击一下,会在该行代码前面出现一个红色的小圆点,表明代码在运行到这里之后,会被断住,不再往下执行。
打好断点之后,我们还需要选择要当前代码运行的进程,首先将手机与电脑连接,打开上面提到过的"USB调试"功能,点击下图中的按钮,或点击"Run -> Attach debugger to Android process"
点击后,会弹出一个名叫"Choose Process"的窗口,勾选"Show all processes","Debugger"选择Auto,如果顺利的话,下面会列出当前手机中正在运行的所有进程(如果没有列出来进程,请查看文章最后列出的一些有可能出问题的点,帮你提供一些思路),如下图所示
由于RIL.java文件是跑在com.android.phone进程中的,所以这里我们选中phone进程,并点击OK。点击后,Android Studio的最下方会弹出一个窗口,如下图所示:
并且,如果选中的进程没错的话,刚刚打断点的那个红色小圆点中会被打上一个对勾,反之则没有(即,如果我们刚才选择的是一个其他的进程,如com.android.bluetooth,则小圆点不会被打钩,因为RIL.java不是跑在该进程中的)。
好,准备工作都已经结束了,接下来在手机上设置呼叫转移,当点击"启用"(或"开启"/"设置",不同手机按钮不同)后,手机界面会卡住,Android Studio的最下面的Debug界面也会显示出当前各个变量的值,如下图所示:
从图中可以看到如下关键变量信息:
1. action = 3 -> CF_ACTION_REGISTRATION(注册呼叫转移)
2. cfReason = 0 -> CF_REASON_UNCONDITIONAL(无条件转移)
3. serviceClass = 1 -> SERVICE_CLASS_VOICE(转移的是语音通话业务)
4. number = "13011112222" -> 所这设置的呼叫转移号码,即转移给哪个号码
在变量窗口的左边还有代码的Call Stack信息(涉及保密信息,故隐去一部分信息)以及调试按钮,如下图所示:
上面的四个按钮从左到右分别为:
1. Step Over: 执行当前行代码后,在下一行代码处断住,即单步调试
2. Step Info: 单步执行代码,若遇到方法调用,则进入该方法内部
3. Force Step Info: 单步执行代码,若遇到方法调用,强制进入该方法内部(与Step Info的区别是,比如在调试一个App的代码时,遇到了一个你自己实现的方法,此时两个按钮的效果相同;但如果遇到了一个SDK中实现的方法,如字符串比较或者取子串的方法,这个时候Step Info不会进入,而Force Step Info会进入)
4. Step Out: 如果你已经使用 Step Info / Force Step Info 进入了某一个方法调用的内部,点击该按钮,则会跳出当前方法(注意: 此处并不是直接跳出,而是执行完当前方法后跳出,即不再在该方法中一句句地断住程序,而在该方法执行完毕后的下一行断住程序)
5. 如果希望程序继续执行,直到下一个断点处断住,则可以点击最左侧从上往下数的第二个"绿色箭头"按钮
6. 如果希望结束调试,则可以点击最左侧从上往下数的第四个"红色方块"按钮
以上就是使用Android Studio对系统源码进行调试的方法,希望对大家的开发以及Debug能有所帮助。
PS: 最后说一下,如果"Choose Process"界面在勾选了"Show all processes"后,却依旧没有列出当前运行的进程的话,我们可以从以下这些方面进行check
1. 查看手机是否是userdebug版本或者eng版本,user版本的手机一般是看不到进程的 (至少我手里的这台不行)。如果确定软件版本没有问题,那么查看"USB调试"选项是否打开
2. 查看usb端口是否识别了当前手机,以Linux为例,在终端中输入lsusb命令即可看到
如果无法分辨哪一个是自己的手机,可以拔下手机运行一遍命令,然后插上手机再运行一遍,看是否会多出来一条。
如果没有识别,可以看看是否是由于USB驱动不正确导致
xxxxxx@xxxxxx-Ubuntu:~/code/android$ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 002: ID 03f0:1f4a Hewlett-Packard
Bus 001 Device 008: ID 05c6:9091 Qualcomm, Inc. ---> 这个是我的手机设备
Bus 001 Device 003: ID 03f0:2f4a Hewlett-Packard
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
3. 按照第2步中的方法,如果可以看到自己的手机设备,那么尝试一下,adb shell是否可以成功连接手机
如果提示"insufficient permissions for device",可以尝试一下重启adb server
xxxxxx@xxxxxx-Ubuntu:~/code/android$ adb kill-server
xxxxxx@xxxxxx-Ubuntu:~/code/android$ adb start-server
* daemon not running. starting it now at tcp:5037 *
* daemon started successfully *
xxxxxx@xxxxxx-Ubuntu:~/code/android$ adb shell
android:/ $
如果还是失败,或该方法在重新插拔手机后再次出现问题,请尝试如下方法:
在/etc/udev/rules.d/目录下
新建一个文件
sudo touch 51-android.rules
编辑该文件
sudo gedit 51-android.rules
输入一行内容为
SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", MODE="0666"
保存
如果不生效,重启adb server或者电脑尝试
4. 如果adb shell连接手机没有问题,但还是不出现进程,请查看你的系统源代码是否配置了正确的SDK版本
点击"File -> Project Structure...",中间的窗口选择"android"(首字母小写的那一个),在弹出的窗口中左边栏中选择"Modules",而后在右边的窗口中选择"Dependencies"。查看Module SDK是否为系统源代码所对应的API版本(如:8.0的代码对应的是API 26,9.0的代码对应的是API 28),如果这里选择的是JDK的版本,如JDK 1.8,请在下拉菜单中更改为Android API。
如果在下拉菜单中没有找到相应的SDK版本,就打开Android Studio自带的SDK Manager下载即可。
一般来说,如果以上问题都解决了以后,就可以看到手机当前运行的进程了;如果依旧不能,那么还是求助百度吧T_T...