Android如何完全調試framework層代碼


1 之前寫過一篇文章:《Android實現開機調試system_process》

2 google的eclipse插件ADT的已經能夠很方便的調試Android的apk了,但是調試的時候應用程序已經進入Activity。

3 如果我們想了解一下Activity的啟動過程,只有看代碼+看log輸出了嗎?本文可以告訴你:NO!

4 相信大家比較感興趣的都是代碼,這里先把代碼再放出來

ZygoteInit.java

 

 

[java]  view plain copy 在CODE上查看代碼片 派生到我的代碼片
  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 (完)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM