<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                要想理清一個Service,最面好從它提供的服務開始進行分析。根據前面對DBMS的介紹可知,它提供了記錄系統運行時日志信息的功能,所以這里先從dropbox日志文件的生成時說起。 當某個應用程序因為發生異常而崩潰(crash)時,ActivityManagerService(簡稱AMS,下同)的handleApplicationCrash函數被調用,其代碼如下: **ActivityManagerService.java** ~~~ public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfocrashInfo) { ProcessRecordr = findAppProcess(app, "Crash"); ...... //調用addErrorToDropBox函數,第一個參數是一個字符串,為“crash” addErrorToDropBox("crash",r, null, null, null, null, null, crashInfo); ...... } ~~~ 下面來看addErrorToDropBox函數: **ActivityManagerService.java** ~~~ public void addErrorToDropBox(String eventType, ProcessRecord process, ActivityRecord activity, ActivityRecordparent, String subject, final String report, final File logFile, final ApplicationErrorReport.CrashInfo crashInfo) { /* dropbox日志文件的命名有一定的規則,其前綴都是一個特定的tag(標簽), tag由兩部分組成,合起來是”進程類型”_”事件類型”。 下邊代碼中的processClass函數返回該進程的類型,包括“system_server”、“system_app” 和“data_app”三種。eventType用于指定事件類型,目前也有三種類型:“crash“、”wtf“ (what aterrible failure)和“anr” */ finalString dropboxTag = processClass(process) + "_" + eventType; //獲取DBMS Bn端的對象DropBoxManager final DropBoxManager dbox = (DropBoxManager) mContext.getSystemService(Context.DROPBOX_SERVICE); /* 對于DBMS,不僅通過tag于標示文件名,還可以根據配置的情況,允許或禁止特定tag日志 文件的記錄。isTagEnable將判斷DBMS是否禁止該標簽,如果該tag已被禁止,則不允許記 錄日志文件 */ if(dbox == null || !dbox.isTagEnabled(dropboxTag)) return; //創建一個StringBuilder,用于保存日志信息 final StringBuilder sb = new StringBuilder(1024); appendDropBoxProcessHeaders(process, sb); ......//將信息保存到字符串sb中 //單獨啟動一個線程用于向DBMS添加信息 Thread worker = new Thread("Error dump: " + dropboxTag) { @Override public void run() { if (report != null) { sb.append(report); } if (logFile != null) { try {//如果有log文件,那么就把log文件內容讀到sb中 sb.append(FileUtils.readTextFile(logFile, 128 * 1024,"\n\n[[TRUNCATED]]")); } ...... } //讀取crashInfo信息,一般記錄的是調用堆棧信息 if (crashInfo != null && crashInfo.stackTrace != null) { sb.append(crashInfo.stackTrace); } String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag; //查詢Settings數據庫,判斷該tag類型的日志是否對所記錄的信息有行數限制, //例如某些tag的日志文件只準記錄1000行的信息 int lines =Settings.Secure.getInt(mContext.getContentResolver(), setting, 0); if (lines > 0) { sb.append("\n"); InputStreamReader input =null; try { //創建一個新進程以運行logcat,后面的參數都是logcat常用的參數 java.lang.Processlogcat = new ProcessBuilder("/system/bin/logcat", "-v","time", "-b", "events", "-b","system", "-b", "main", "-t", String.valueOf(lines)) .redirectErrorStream(true).start(); //由于新進程的輸出已經重定向,因此這里可以獲取最后lines行的信息, //不熟悉ProcessBuidler的讀者可以查看SDK中關于它的用法說明 ...... } } //調用DBMS的addText dbox.addText(dropboxTag, sb.toString()); } }; if(process == null || process.pid == MY_PID) { worker.run(); //如果是SystemServer進程crash了,則不能在別的線程執行 }else { worker.start(); } } ~~~ 由上面代碼可知,addErrorToDropBox在生成日志的內容上花了不少工夫,因為這些是最重要的,最后僅調用addText函數便將內容傳給DBMS的功能。 addText函數定義在DropBoxManager類中,代碼如下: **DropBoxManager.java** ~~~ public void addText(String tag, String data) { /* mService和DBMS交互。DBMS對外只提供一個add函數用于日志添加,而DBM提供了3個函數, 分別是addText、addData、addFile,以方便我們的使用 */ try {mService.add(new Entry(tag, 0, data)); } ...... } ~~~ DBM向DBMS傳遞的數據被封裝在一個Entry中。下面來看DBMS的add函數,其代碼如下: **DropBoxManagerService.java** ~~~ public void add(DropBoxManager.Entry entry) { Filetemp = null; OutputStream output = null; finalString tag = entry.getTag();//先取出這個Entry的tag try{ int flags = entry.getFlags(); ...... //做一些初始化工作,包括生成dropbox目錄、統計當前已有的dropbox文件信息等 init(); if (!isTagEnabled(tag)) return;//如果該tag被禁止,則不能生成日志文件 long max = trimToFit(); long lastTrim = System.currentTimeMillis(); //BlockSize一般是4KB byte[] buffer = new byte[mBlockSize]; //從Entry中得到一個輸入流。與Java I/O相關的類比較多,且用法非常靈活 //建議讀者閱讀《Java編程思想》中“Java I/O系統”一章 InputStreaminput = entry.getInputStream(); ...... int read = 0; while (read < buffer.length) { int n = input.read(buffer, read, buffer.length - read); if (n <= 0) break; read += n; } //先生成一個臨時文件,命名方式為”drop線程id.tmp” temp = new File(mDropBoxDir, "drop" + Thread.currentThread().getId()+ ".tmp"); int bufferSize = mBlockSize; if (bufferSize > 4096) bufferSize = 4096; if (bufferSize < 512) bufferSize = 512; FileOutputStream foutput = new FileOutputStream(temp); output = new BufferedOutputStream(foutput, bufferSize); //生成GZIP壓縮文件 if (read == buffer.length && ((flags &DropBoxManager.IS_GZIPPED) == 0)) { output = new GZIPOutputStream(output); flags = flags | DropBoxManager.IS_GZIPPED; } /* DBMS很珍惜/data分區,若所生成文件的size大于一個BlockSize, 則一定要先壓縮。 */ ......//寫文件,這段代碼非常繁瑣,其主要目的是盡量節省存儲空間 /* 生成一個EntryFile對象,并保存到DBMS內部的一個數據容器中。 DBMS除了負責生成文件外,還提供查詢的功能,這個功能由getNextEntry完成。 另外,剛才生成的臨時文件在createEntry函數中會重命為帶標簽的名字, 讀者可自行分析createEntry函數 */ long time = createEntry(temp, tag, flags); temp = null; Intent dropboxIntent = new Intent(DropBoxManager.ACTION_DROPBOX_ENTRY_ADDED); dropboxIntent.putExtra(DropBoxManager.EXTRA_TAG, tag); dropboxIntent.putExtra(DropBoxManager.EXTRA_TIME, time); if (!mBooted) { dropboxIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); } //發送DROPBOX_ENTRY_ADDED廣播。系統中目前還沒有程序接收該廣播 mContext.sendBroadcast(dropboxIntent, android.Manifest.permission.READ_LOGS); }...... } ~~~ 上面代碼中略去了DBMS寫文件的部分,我們從代碼注釋中可獲悉,DBMS非常珍惜/data分區的空間,每一個日志文件都需要考慮壓縮以節省存儲空間。如果說細節體現功力,那么這正是一個極好的例證。 一個真實設備上/data/system/dropbox目錄的內容如圖3-2所示。 :-: ![](http://img.blog.csdn.net/20150803104313385?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 圖3-2 真實設備中dropbox目錄的內容 圖3-2中最后一項data_app_anr@1324836096560.txt.gz的大小是6.1KB,該文件解壓后得到的文件大小是42kB。看來,壓縮確實節省了不少存儲空間。 另外,我們從圖3-2中還發現了其他不同的tag,如SYSTEM_BOOT、SYSTEM_TOMBSTONE等,這些都是由BootReceiver在收到BOOT_COMPLETE廣播后收集相關信息并傳遞給DBMS而生成的日志文件。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看