Android如何完全调试framework层代码

1 之前写过一篇文章:《Android实现开机调试system_process》

2 google的eclipse插件ADT的已经能够很方便的调试Android的apk了,但是调试的时候应用程序已经进入Activity。

3 如果我们想了解一下Activity的启动过程,只有看代码+看log输出了吗?本文可以告诉你:NO!

4 相信大家比较感兴趣的都是代码,这里先把代码再放出来

ZygoteInit.java

 

 

  1. public static List<String> readCommandOutput(String command)  {  
  2.   
  3.    Runtime rt =Runtime.getRuntime();  
  4.   
  5.    java.lang.Processproc;  
  6.   
  7.    try {  
  8.   
  9.      proc =rt.exec(command);  
  10.   
  11.        
  12.   
  13.      if (proc.waitFor() != 0) {  
  14.   
  15.         return null;  
  16.   
  17.      }  
  18.   
  19.      LinkedList<String>list = new LinkedList<String>();        
  20.   
  21.      InputStreamReader ir = new InputStreamReader(proc.getInputStream());  
  22.   
  23.      BufferedReader in = new BufferedReader(ir);         
  24.   
  25.      String line = null;        
  26.   
  27.      while ((line = in.readLine()) != null) {  
  28.   
  29.         list.add(line);  
  30.   
  31.      }        
  32.   
  33.      return list;  
  34.   
  35.    } catch (InterruptedException e) {  
  36.   
  37.      e.printStackTrace();  
  38.   
  39.    } catch (IOException e) {  
  40.   
  41.      e.printStackTrace();  
  42.   
  43.    }  
  44.   
  45.    return null;  
  46.   
  47. }  
  48.   
  49.   
  50.   
  51. public static String getPackageName(){  
  52.   
  53.    String strPid =Integer.toString(android.os.Process.myPid());  
  54.   
  55.    String cmd = "ps";  
  56.   
  57.      
  58.   
  59.    List<String>result = readCommandOutput(cmd);  
  60.   
  61.    if(result == null){  
  62.   
  63.      return "";  
  64.   
  65.    }  
  66.   
  67.      
  68.   
  69.    for(String info:result){  
  70.   
  71.      if(info.contains(strPid)){  
  72.   
  73.         int index = info.lastIndexOf(" ");  
  74.   
  75.         if(index >=0){  
  76.   
  77.           StringsubStr = info.substring(index+1);  
  78.   
  79.           Log.i(TAG,subStr);  
  80.   
  81.           return subStr;  
  82.   
  83.         }  
  84.   
  85.      }  
  86.   
  87.    }  
  88.   
  89.    return "";  
  90.   
  91. }    
  92.   
  93.   
  94.   
  95. public static boolean needDebug(String packageName){  
  96.   
  97.    String debugProcess = android.os.SystemProperties.get("persist.sys.debug");      
  98.   
  99.    Log.i(TAG,debugProcess);  
  100.   
  101.   
  102.   
  103.    if(debugProcess.equals(packageName)){  
  104.   
  105.      return true;  
  106.   
  107.    }  
  108.   
  109.    return false;  
  110.   
  111. }    
  112.   
  113.   
  114.   
  115.   public static void main(Stringargv[]) {  
  116.   
  117.          
  118.   
  119.       try {  
  120.   
  121.           // Start profiling the zygote initialization.  
  122.   
  123.          SamplingProfilerIntegration.start();  
  124.   
  125.   
  126.   
  127.           registerZygoteSocket();  
  128.   
  129.          EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,  
  130.   
  131.              SystemClock.uptimeMillis());  
  132.   
  133.           preload();  
  134.   
  135.          EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,  
  136.   
  137.              SystemClock.uptimeMillis());  
  138.   
  139.   
  140.   
  141.           // Finish profiling the zygote initialization.  
  142.   
  143.          SamplingProfilerIntegration.writeZygoteSnapshot();  
  144.   
  145.   
  146.   
  147.           // Do an initial gc to cleanup after startup  
  148.   
  149.           gc();  
  150.   
  151.   
  152.   
  153.           // If requested, start system server directlyfrom Zygote  
  154.   
  155.           if (argv.length != 2) {  
  156.   
  157.               throw new RuntimeException(argv[0] + USAGE_STRING);  
  158.   
  159.          }  
  160.   
  161.   
  162.   
  163.           if (argv[1].equals("start-system-server")) {  
  164.   
  165.               startSystemServer();  
  166.   
  167.          } else if (!argv[1].equals("")) {  
  168.   
  169.               throw new RuntimeException(argv[0] + USAGE_STRING);  
  170.   
  171.          }  
  172.   
  173.   
  174.   
  175.          Log.i(TAG, "Accepting command socket connections");  
  176.   
  177.   
  178.   
  179.           if (ZYGOTE_FORK_MODE) {  
  180.   
  181.               runForkMode();  
  182.   
  183.          } else {  
  184.   
  185.               runSelectLoopMode();  
  186.   
  187.          }  
  188.   
  189.   
  190.   
  191.           closeServerSocket();  
  192.   
  193.      } catch (MethodAndArgsCaller caller) {  
  194.   
  195.        String packageName = getPackageName();  
  196.   
  197.        if(needDebug(packageName)){  
  198.   
  199.          android.ddm.DdmHandleAppName.setAppName(packageName,UserHandle.myUserId());  
  200.   
  201.          android.os.Debug.waitForDebugger();  
  202.   
  203.          }           
  204.   
  205.        caller.run();  
  206.   
  207.      } catch (RuntimeException ex) {  
  208.   
  209.          Log.e(TAG, "Zygote died with exception", ex);  
  210.   
  211.           closeServerSocket();  
  212.   
  213.           throw ex;  
  214.   
  215.       }  
  216.   
  217.   }  



 

 

5 如果有兴趣,继续往下看!

 

6 readCommandOutput:用于执行命令并获取命令的输出

 

7 getPackageName()有于获取当前进程的包名

    这里默认进程名称即为包名

    获取ps的输出

    然后通过pid找到本程序所在的输出行。

   提取出本程序所在的输出行包名

 

8 needDebug()用于判断当前进程是否需要调试,原理是这样的:

    使用者通过setprop persist.sys.debug 包名来设置包的名称

    needDebug获取 persist.sys.debug

    再与本进程的包名进行比较,以判断是否要调试

 

9 接下来的动作就和《Android实现开机调试system_process》一样了:

    设置App在DDM中的名称:

android.ddm.DdmHandleAppName.setAppName(packageName,UserHandle.myUserId());

    等待调试器来连接:

android.os.Debug.waitForDebugger();

 

10 接下来重新编译和烧录,mmm...,一个漫长的过程,但是结果将会证明一确都是值得的。

 

11 接下来,创建一个伪工程,修改Manifest中的package为需要调试的程序包名

 

12 再在工程中将需要调试的framework层代码引进来

 

13 接下来,adb shell连接到android,进行命令行

 

14 执行命令:

setprop persist.sys.debug 包名

 

15 在需要调试的代码上设置断点

 

16 接下来,启动应用程序,注意,是直接启动程序,而不是通过eclipse启动调试!

 

17 enjoy it!

 

18 (完)

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。