zoukankan      html  css  js  c++  java
  • 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 (完)

  • 相关阅读:
    Could not load file or assembly Microsoft.SqlServer.management.sdk.sfc version 11.0.0.0
    代码覆盖率 (Code Coverage)从简到繁 (一)
    vscode配置自动格式化eslint 配置模板
    无效的源发行版: 10
    java读取一个文件写入另外一个文件
    notepad++使用正则表达式匹配
    jsp页面返回字符串而非方法执行后取得的数据?
    maven的原始setting.xml文件,自带阿里云镜像,之前配的时候出错,保存一下,注意可以在localRepository处设置存储依赖的地址,大概在49到54行,我的是<localRepository>F:/MavenRepository</localRepository>,F盘要先有这个文件夹
    Java 8 lambda Stream list to Map key 重复 value合并到Collection
    BufferedReader.readLine()读取文件
  • 原文地址:https://www.cnblogs.com/xiaochao1234/p/3979159.html
Copyright © 2011-2022 走看看