1. 程式人生 > >Android 開機啟動除錯,system_process除錯

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等配置資訊,以便關聯原始碼和跳轉等

設定完成後,可以試著對系統應用進行除錯.此時系統應用都已經啟動,在程序列表裡直接選定某一個程序就可以除錯了,但是如何除錯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的啟動除錯了!

參考連結: