Android 开机启动调试,system_process调试

下载,编译,导入,配置

作为开发者,经常会对Debug工程进行调试,Android具有debug签名的应用才可以被调试,如果想调试系统源码呢?

想要调试源码,首先必须要有源码,并且保证设备运行的源码和IED里的源码是同一份.

下载和编译AOSP源码,本人使用的ubuntu LTS 16.04系统, 磁盘剩余空间至少要150G(如果编译时,提示空间不够,可以删掉".repo" 目录), 内存16G, 8G的内存,编译死慢,调试更是卡的动不了,墙裂建议用16G的内存!

注意编译源码时,如果你是64位的机器,就编译64位的目标版本,运行起来快!

编译完成后执行如下代码:

soruce build/envsetup.sh
mmm development/tools/idegen/
sudo ./development/tools/idegen/idegen.sh

注意请在源码目录下执行,如果是按照官方的教程,应该是在 ~/WORKING_DIRECTORY 目录下

"mmm development/tools/idegen/" 执行完成后会生成idegen.jar

"sodo ./development/tools/idegen/idegen.sh"则会在源码目录下生成IEDA工程配置文件:android.ipr,android.iml

android.ipr:保存工程相关的设置,比如编译器配置,入口,相关的libraries等
android.iml:主要是描述了modules,比如modules的路径,依赖关系等,在导入源码工程是,可以编辑该文件,排除一些不使用的目录文件,这样导入会快很多,因为源码文件实在是太多了,全部导入,要花很长时间,可以排除的文件为目录为(我的机器的的配置):

<excludeFolder url="file://$MODULE_DIR$/.repo" />
      <excludeFolder url="file://$MODULE_DIR$/external" />
      <excludeFolder url="file://$MODULE_DIR$/external/bluetooth" />
      <excludeFolder url="file://$MODULE_DIR$/external/chromium" />
      <excludeFolder url="file://$MODULE_DIR$/external/emma" />
      <excludeFolder url="file://$MODULE_DIR$/external/icu4c" />
      <excludeFolder url="file://$MODULE_DIR$/external/jdiff" />
      <excludeFolder url="file://$MODULE_DIR$/external/webkit" />
      <excludeFolder url="file://$MODULE_DIR$/frameworks/base/docs" />
      <excludeFolder url="file://$MODULE_DIR$/out/eclipse" />
      <excludeFolder url="file://$MODULE_DIR$/out/host" />
      <excludeFolder url="file://$MODULE_DIR$/out/target/common/docs" />
      <excludeFolder url="file://$MODULE_DIR$/out/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates" />
      <excludeFolder url="file://$MODULE_DIR$/out/target/product" />
      <excludeFolder url="file://$MODULE_DIR$/prebuilt" />


      <excludeFolder url="file://$MODULE_DIR$/abi" />
      <excludeFolder url="file://$MODULE_DIR$/art" />
      <excludeFolder url="file://$MODULE_DIR$/bionic" />
      <excludeFolder url="file://$MODULE_DIR$/bootable" />
      <excludeFolder url="file://$MODULE_DIR$/build" />
      <excludeFolder url="file://$MODULE_DIR$/cts" />
      <excludeFolder url="file://$MODULE_DIR$/dalvik" />
      <excludeFolder url="file://$MODULE_DIR$/developers" />
      <excludeFolder url="file://$MODULE_DIR$/development" />
      <excludeFolder url="file://$MODULE_DIR$/device" />
      <excludeFolder url="file://$MODULE_DIR$/docs" />
      <excludeFolder url="file://$MODULE_DIR$/external" />
      <excludeFolder url="file://$MODULE_DIR$/hardware" />
      <excludeFolder url="file://$MODULE_DIR$/libcore" />
      <excludeFolder url="file://$MODULE_DIR$/libnativehelper" />
      <excludeFolder url="file://$MODULE_DIR$/ndk" />
      <excludeFolder url="file://$MODULE_DIR$/out" />
      <excludeFolder url="file://$MODULE_DIR$/pdk" />
      <excludeFolder url="file://$MODULE_DIR$/prebuilt" />
      <excludeFolder url="file://$MODULE_DIR$/prebuilts" />
      <excludeFolder url="file://$MODULE_DIR$/sdk" />
      <excludeFolder url="file://$MODULE_DIR$/system" />

只保留 framework(我们要调试的大部分代码就在该包下)和package 系统自带应用

然后:打开Android Studio,点击File->Open,选择刚才生成的android.ipr,等待导入完成

导入完成后,如果Android studio  scanning file into index 每隔几秒就执行一次,需要在android.iml 的

faceset 节点的 <configuration >里下加入:

<option name="ALLOW_USER_CONFIGURATION" value="false" />

。。。。当导入完成后还需要设置系统JDK和SDK等配置信息,以便关联源码和跳转等

可参考链接:JDK和SDK配置

设置完成后,可以试着对系统应用进行调试.此时系统应用都已经启动,在进程列表里直接选定某一个进程就可以调试了,但是如何调试system_process 进程呢?因为模拟器启动后, system_process进程已经启动了,如何再去断点调试呢?能不能让system_process的开机的时候暂停了,或者说是等待调试器链接,这样我们就有机会进行调试呢?先看个日志信息:

08-05 15:40:06.791 1550-1550/? I/System.out: Sending WAIT chunk
08-05 15:40:11.950 1550-1556/system_process I/zygote64: Debugger is active
08-05 15:40:12.003 1550-1550/system_process I/System.out: Debugger has connected
08-05 15:40:12.004 1550-1550/system_process I/System.out: waiting for debugger to settle...
08-05 15:40:13.205 1550-1550/system_process I/chatty: uid=1000 system_server identical 6 lines
08-05 15:40:13.405 1550-1550/system_process I/System.out: waiting for debugger to settle...
08-05 15:40:13.606 1550-1550/system_process I/System.out: debugger has settled (1441)
08-05 15:40:13.606 1550-1550/system_process W/zygote64: Got a deoptimization request on un-deoptimizable void android.os.Debug.waitForDebugger() at PC 0x728c321eb4ee
08-05 15:40:26.876 1383-1383/? I/qemu-props: skip starting adbd ...
08-05 15:41:26.877 1383-1383/? I/qemu-props: skip starting adbd ...
08-05 15:42:26.877 1383-1383/? I/qemu-props: skip starting adbd ...
08-05 15:43:26.877 1383-1383/? I/qemu-props: skip starting adbd ...
08-05 15:44:26.877 1383-1383/? I/qemu-props: skip starting adbd ...
08-05 15:45:26.878 1383-1383/? I/qemu-props: skip starting adbd ...
08-05 15:46:26.878 1383-1383/? I/qemu-props: skip starting adbd ...
08-05 15:47:26.878 1383-1383/? I/qemu-props: skip starting adbd ...
08-05 15:48:26.879 1383-1383/? I/qemu-props: skip starting adbd ...
08-05 15:49:26.879 1383-1383/? I/qemu-props: skip starting adbd ...
08-05 15:50:26.879 1383-1383/? I/qemu-props: skip starting adbd ...
08-05 15:51:26.879 1383-1383/? I/qemu-props: skip starting adbd ...
08-05 15:52:26.879 1383-1383/? I/qemu-props: skip starting adbd ...
08-05 15:53:26.880 1383-1383/? I/qemu-props: skip starting adbd ...

在我编辑文档 的时候,一直在等待连接调试器,每分钟检查一次,我的调试面板里的进程:

⚠️注意:上面情况是我经过调整源码后的重新编译才会出现的情况,正常情况启动模拟器,是不是一只等待调试的!

如何开机调试

正常情况下,如果不是开机调试,则进程选择面板里,应该包含除了system_process进程之外的所有其他进程,包括Launcher, contact,calendar 等等进程,

现在我是处于开机调试状态,已经在system_process进程所在的SystemServer的 run()方法断点,所有其他进程都必须等待system_process进程启动完成之后再开始,system_process进程要启动很多系统依赖的服务进程

我的模拟器也一直停留在开机状态:

如何让模拟器停在开机状态呢?答案在于如何能让模拟器等待连接调试器,当模拟器连接上调试器后,我们再下断点,自然就可以断点system_process进程了,system_process进程的代码SystemServer.

sytem_process进程有Zygote进程启动,就是通过main()方法启动的:

    /**
     * The main entry point from zygote.
     */
    public static void main(String[] args) {
       
        new SystemServer().run();
    }

在 new SystemServer().run()方法的上面我么可以加上下面这段代码:

 java.io.File f = new java.io.File("/system/debug");
        if(f.exists()){
            android.ddm.DdmHandleAppName.setAppName("system_process",
                    UserHandle.myUserId());
            android.os.Debug.waitForDebugger();
        }
  • 首先通过判断/system/debug是否存在来判断是否要等待调试器连接.
  • android.os.Debug.waitForDebugger()就是等待调试器来连接,在调试器连接上之前代码不会往下执行.
  • 但是第一行代码就比较费解了,先来解析下什么叫ddm,ddm就是Dalvik Debug Monitor的缩写.
  • android.ddm.DdmHandleAppName.setAppName就是要设置Java App在ddm里的名称.

如果不设置的话,你在DDMS里看到的Name一栏就会有一个“?”,这个时候,eclipse找不到对应的工程,所以就没法调试了。
修改好源码后,重新编译(需要等待2-3个小时,取决于你的机器的配置),最后还要说名一点,你需要在/system/ 目录下创建对应的文件debug,模拟器启动后,默认是/system/是read-only 的,你无法修改和写入,注意,启动的时候,使用下面的启动方式:

~/WORKING_DIRECTORY$ emulator -writable-system

启动后,通过adb shell 进入模拟器,在模拟期的/system 目录下创建debug文件,然后用相同的方式重启模拟器,就可以进行system_process的启动调试了!

参考链接:

开机调试:https://blog.csdn.net/i2cbus/article/details/21476401

环境配置和导入源码:https://www.jianshu.com/p/30a628335114

图解Android-Zygote,SystemServer启动分析:https://www.cnblogs.com/samchen2009/p/3294713.html

猜你喜欢

转载自blog.csdn.net/l491337898/article/details/81432456