LINUX系统以及ANDROID 平台log信息输出级别设置 [MTK]
一、LK層:
首先,在LK中,有一個對log打印級別的控制文檔,其路徑一般為:vendor\mediatek\proprietary\bootable\bootloader\lk\include\debug.h(以mtk平臺為例)
在include\debug.h重要代碼為:
//下面做個判斷:意思是如果makefile(相應的平臺mk文件) 定義了DEBUG的值,就是用它,否則默認為2等級
//在bootloader\lk\project\rlk6737m_65_n.mk中:DEBUG := 2
#if defined(DEBUG)
#define?DEBUGLEVEL DEBUG
#else
#define?DEBUGLEVEL?2
#endif
/* debug levels 調試級別*/???
#define?CRITICAL?0??????//數字越小級別越高,打印的信息log越少
#define?ALWAYS?0
#define?INFO?1
#define?SPEW?2
/* output */??輸出方式介紹
void _dputc(char c); // XXX for now, platform implements? 平臺工具
int _dputs(const char *str);
int _dprintf(const char *fmt, ...) __PRINTFLIKE(1, 2);
int _dvprintf(const char *fmt, va_list ap);
//下面的這些打印方法具體含義是:如果級別<=之前定義的調試級別的話就打印否則不打印
#define?dputc(level, str) do { if ((level) <= DEBUGLEVEL) { _dputc(str); } } while (0)??
#define?dputs(level, str) do { if ((level) <= DEBUGLEVEL) { _dputs(str); } } while (0)
#define?dprintf(level, x...) do { if ((level) <= DEBUGLEVEL) { _dprintf(x); } } while (0)
#define?dvprintf(level, x...) do { if ((level) <= DEBUGLEVEL) { _dvprintf(x); } } while (0)
相關DEBUG的定義有不同的方式方法,如下例子:
法①、在bootable\bootloader\lk\project\rlk6757_66_n.mk:
DEBUG?:=2??
這時也要注意:不要看到這里是2就表示都會打印,我現在遇到一個項目雖然在\lk\project\rlk6757_66_n.mk文件中配置了DEBUG?:=2,但log并沒有打印出來,原因最后找到了:
#ifdef LK_PROFILING
?? ?dprintf(INFO, "[PROFILE] ------- WDT Init? takes %d ms -------- \n", (int)get_timer(time_wdt_early_init));???//打印不出來
#endif
最后發現在類似的bootable\bootloader\lk\target\rlk6757_66_n(project)\rules.mk中:
LK_PROFILING?:=?no??????//LK_PROFILING := yes? 一般項目都會使這個宏,所以之前并沒有太關注,后續項目可能會為了性能,把log后期以這種方式關掉,注意一下
法②、在lk\include\platform\debug.h中定義了這個函數:
void debug_set_trace_level(int trace_type, int level);??//設置調試級別
法③、還有在具體的代碼中:如:
#define DEBUG??//這里定義了這個宏
#ifdef DEBUG????//判斷是不是定義了,定義了就執行下面的
#define LCM_DEBUG(fmt, args...)? _dprintf(fmt, ##args)
#else?
#define LCM_DEBUG(fmt, args...) do {} while(0)
#endif
二、kernel層:
在kernel-3.18\include\linux\kern_levels.h中定義了打印級別:
(以前定義在kernel-3.18\include\linux\kernel.h)
#define KERN_SOH?? ?"\001"?? ?????/* ASCII Start Of Header */
#define KERN_SOH_ASCII?? ?'\001'
#define KERN_EMERG?? ?KERN_SOH "0"????/* system is unusable 系統無法使用*/
#define KERN_ALERT?? ?KERN_SOH "1"????/* action must be taken immediately必須立即采取行動 */
#define KERN_CRIT?? ?KERN_SOH "2"????/* critical conditions臨界狀態---重要信息 */
#define KERN_ERR?? ?KERN_SOH "3"????/* error conditions錯誤狀況 */
#define KERN_WARNING?? ?KERN_SOH "4"????/* warning conditions 報警狀態*/
#define KERN_NOTICE?? ?KERN_SOH "5"????/* normal but significant condition正常但重要條件 */
#define KERN_INFO?? ?KERN_SOH "6"????/* informational重要信息 */
#define KERN_DEBUG?? ?KERN_SOH "7"????/* debug-level messages 調試級別信息*/
#define KERN_DEFAULT?? ?KERN_SOH "d"?? ?/* the default kernel loglevel 默認的內核loglevel----一般都為4*/
在kernel-3.18\include\linux\printk.h中定義了各默認日志的級別
/* printk's without a loglevel use this.. 沒有日志級別的printk使用*/
#define MESSAGE_LOGLEVEL_DEFAULT CONFIG_MESSAGE_LOGLEVEL_DEFAULT
/* We show everything that is MORE important than this..我們展示了所有比這更重要的東西 */
#define CONSOLE_LOGLEVEL_SILENT? 0?/* Mum's the word */
#define CONSOLE_LOGLEVEL_MIN?? ? 1?/* Minimum loglevel we let people use最低的控制臺日志級別*/
#define CONSOLE_LOGLEVEL_QUIET?? ? 4?/* Shhh ..., when booted with "quiet"默認的消息日志級別*/
#define CONSOLE_LOGLEVEL_DEFAULT 7?/* anything MORE serious than KERN_DEBUG 默認的控制臺日志級別*/
#define CONSOLE_LOGLEVEL_DEBUG?? ?10?/* issue debug messages */
#define CONSOLE_LOGLEVEL_MOTORMOUTH 15????/* You can't shut this one up */
extern int console_printk[];
#define console_loglevel (console_printk[0])
#define default_message_loglevel (console_printk[1])
#define minimum_console_loglevel (console_printk[2])
在這里注意一下:有些人在寫printk()時,并不加log級別,這是如果我們定義的log級別小于4,則它是打印不出來的,因為不寫log級別的打印內核默認為4打印級別。
在kernel-3.18\kernel\printk\printk.c中:
int console_printk[4] = {
?? ?CONSOLE_LOGLEVEL_DEFAULT,?? ?/* console_loglevel控制log級別 */
?? ?MESSAGE_LOGLEVEL_DEFAULT,?? ?/* default_message_loglevel默認的消息日志級別?*/
?? ?CONSOLE_LOGLEVEL_MIN,?? ??? ?/* minimum_console_loglevel最低的控制臺日志級別*/
?? ?CONSOLE_LOGLEVEL_DEFAULT,????/* default_console_loglevel默認的控制臺日志級別?*/
};
我們的做法:
①、我們可以在查看當前控制臺的打印級別:
cat /proc/sys/kernel/printk
7???? 4???? 1???? 7
四個值的含義:控制臺日志級別、默認的消息日志級別、最低的控制臺日志級別和默認的控制臺日志級別
其中第一個“7”表示內核打印函數printk的打印級別,只有級別比他高的信息才能在控制臺上打印出來,既 0-6級別的信息
②、修改打印:
echo "新的打印級別? 4??? 1??? 7" >/proc/sys/kernel/printk
如果用echo 8? >??/proc/sys/kernel/printk這樣所有級別<8,(0-7)的消息都可以顯示在控制臺上。
不夠打印級別的信息會被寫到日志中可通過dmesg?命令來查看
設置控制終端打印級別為0,就沒有了任何輸出
如果需要臨時關閉kernel的log,可以再串口輸入命令:echo "0 0 0 0" > /proc/sys/kernel/printk
需要恢復的話可以輸入:echo ”7 4 1 7“ > /proc/sys/kernel/printk
③、printk函數的使用
??????printk(打印級別? “要打印的信息”)
MTK問題:How to enable kernel dynamic debug log
???? 如何啟用內核動態調試日志
[DESCRIPTION]?在kernel module debug 對照代碼的時候,發現使用pr_debug 打印的log 無法找到,怎樣在mobilelog 和uart log中開啟pr_debug ?pr_debug()針對這種打印信息[SOLUTION]1?打開dynamic debug feature<project>_defconfig 中設置CONFIG_DYNAMIC_DEBUG=y (default 打開)2?打開pr_debug log 輸出? ? ?enable:echo "<match-spec> +p" > <debugfs>/dynamic_debug/control? ? disable:echo "<match-spec> -p" > <debugfs>/dynamic_debug/control? ? <match-spec>: file <path>? ? ? ? ? ? ? ? ? ? ? ? ? line line-range? module <module_name>? func <func-name> ?? ? eg:enable the message at line 1603 of file svcsock.c ? //使能消息
? ? ? ? ? ? ?echo -n "file svcsock.c line 1603 +p" > /sys/kernel/debug/dynamic_debug/control? ? eg:enable all the messages in the NFS server module? //啟用NFS服務器模塊中的所有消息
? ? ? ? ? ? echo -n "module nfsd +p" > /sys/kernel/debug/dynamic_debug/control?3mobile log 中 pr_debug log? ? ?pr_debug 默認以debug 等級輸出到kernel log 中, mobilelog 抓到的kernellog 會包含?4?uartlog 中 pr_debug log? ? ?默認pr_debug log 不送uart ,可以通過以下方式打開:? ? ? ? ?1.adb起來后,echo 8 > /proc/sys/kernel/printk
? ? ? ? ?2.改code ,修改console 默認輸出log等級? ? ? ? ? ? ? ?kernel-3.18/include/linux/printk.h : #define CONSOLE_LOGLEVEL_DEFAULT 7 -->#define CONSOLE_LOGLEVEL_DEFAULT 8
三、關于android日志打印級別
1、??目的:
為了規范軟件工程師在Android代碼編寫過程中輸出Log的行為,使得發布的產品中打印的Log是必須的,打印的Log的級別是能真實反映此Log對應的級別,標簽、Log內容具有很好的可讀性。
2、??適用范圍
android平臺Java、c++、c代碼編寫。
3、??Log的調用及等級介紹
(1)、Log的等級有Verbose,Debug,Info,Warn,Error。
?[D]:調試(Debug)信息,輸出顏色是藍色
?[I]:通告(Info)信息,輸出顏色為綠色
[W]:警告(Warn)信息,輸出顏色為橙色
[E]:錯誤(Error)信息,輸出顏色為紅色
[V]:詳細(Verbose)信息,輸出顏色為黑色
[assert],新版本加入的。
這里錯誤信息0的級別最高,其次是警告信息1,然后是通知信息2和調試信息3,級別最低的是詳細信息4。
我們如果想讓所有的信息都打印出來一般都定義成debug級別。
(2)、java層調用:在java層調用import android.util.Log,在需要打印Log的地方執行Log.v,Log.d,Log.i,Log.w,Log.e.
????????? 如: ????????????
?????????????????????? private static final String LOG_TAG = "MY_LOG_TAG";?? //這個TAG可以隨意定義,后面打印篩選的時候可以用到
????????????????????? Log.i(LOG_TAG, "This is the log printed by Log.i in android user space.");
?????????????????????? Log.e(LOG_TAG, "xxxxxxxxxxx" + mFileName, e);
?????????????????? ?? 比如:在所有的log中我想選出有包含“MY_LOG_TAG”這個標簽的,則需執行:adb logcat? -s "MY_LOG_TAG"???即可(3)、c、c++層調用:在c,c++層包含此頭文件:#include <cutils/log.h>,在需要調用Log的地方執行:ALOGV,ALOGD,ALOGI,ALOGW,ALOGE。
??????? 敝人認為:頭文件可以寫:?#include <utils/Log.h>? ---》 #include <cutils/log.h>----》#include <log/log.h>,中的任何一個,其實質在log/log.h中
?????? 具體目錄為:system\core\include\log\log.h
???????? 如:
???????????? ALOGE("This is the log printed by LOGV in android user space.");//輸出到main緩沖區
??????????? SLOGE("xxxxxxxxxxxxxxxxxx"); //輸出到system緩沖區
???????????? 還需要修改 Android.mk
????????????? LOCAL_SHARED_LIBRARIES :=?liblog
????????????? LOCAL_C_INCLUDES +=?system/core/include //可不用
3 libcore
System.out.println("##### xxxxxxxxxxxx ####### ? ");(4)、各個Log等級的使用
Verbose:?開發調試過程中一些詳細信息,不應該編譯進產品中,只在開發階段使用。
Debug:?用于調試的信息,編譯進產品,但可以在運行時關閉。
Info:例如一些運行時的狀態信息,這些狀態信息在出現問題的時候能提供幫助。
Warn:警告系統出現了異常,即將出現錯誤。
Error:系統已經出現了錯誤。
Info、Warn、Error這三個等級的Log的警示作用依次提高,需要一直保留。這些信息在系統異常時能提供有價值的分析線索。
4、??具體規則
(1)、Verbose等級的Log,請不要在user版本中出現。Verbose級別的Log輸出參見下面例子。
示例Java部分:
import android.os.Build;
import android.util.Log
final public Boolean isEng =Build.TYPE.equals("eng");
if (isEng)
?Log.v(“LOG_TAG”,“LOG_MESSAGE”);
?
示例c、c++部分:
#include<cutils/log.h>
char value[PROPERTY_VALUE_MAX];
int isEng=0;
property_get("ro.build.type",value, "user");
isEng=strcmp(value, "eng");
if (isEng)
?ALOGV();
?
(2)、Debug等級的log,默認不開啟,通過終端命令開啟。
Debug級別的log輸出參見下面例子。
示例Java部分:
import android.util.Log
final String TAG=”MyActivity”;
final public Boolean LOG_DEBUG = Log.isLoggable(TAG, Log.DEBUG);
?
if (LOG_DEBUG)
??Log.d(“LOG_TAG”,“LOG_MESSAGE”);
?
運行時開啟log:?在終端輸入:setprop log.tag.MyActivity DEBUG
運行時關閉log:?在終端輸入:setprop log.tag.MyActivity INFO
?
示例c、c++部分:
#include<cutils/log.h>
#defineLOG_CTL?“debug.MyActivity.enablelog”
charvalue[PROPERTY_VALUE_MAX];
int isDebug=0;
property_get(LOG_CTL,value, "0");
isDebug=strcmp(value,"1");
if (isDebug)
??ALOGD();
運行時開啟log:?在終端輸入:setpropdebug.MyActivity.enablelog 1
運行時關閉log:?在終端輸入:setpropdebug.MyActivity.enablelog 0
?
最近遇到一個問題:
在.cpp應用代碼中有類似這樣的信息:
?SLOGD("[boot_logo_updater %s %d]boot_logo_updater,\n",__FUNCTION__,__LINE__)
SLOGD("[libshowlogo: %s %d]show kernel logo, index = 38 \n",__FUNCTION__,__LINE__);
但輸出的log信息中就是打印不出來,我懷疑級別不夠。最終發現確實有定義級別的地方:
打開:system\core\include\log\log.h發現:
/*
?* Normally we strip ALOGV (VERBOSE messages) from release builds.
?* You can modify this (for example with "#define LOG_NDEBUG 0"
?* at the top of your source file) to change that behavior.
?*/
//對log級別的
#ifndef LOG_NDEBUG????//如果我們沒有定義,我們就給它賦值為0,表示不關閉
#ifdef NDEBUG
#define LOG_NDEBUG 1
#else
#define LOG_NDEBUG 0
#endif
#endif
#ifdef MTK_LOG_ENABLE??//如果我們沒有定義它,我們就定義為0,這里就是定義打印級別,很重要。
#define MTK_LOG_ENABLE 0
#endif
例如:#define MTK_LOG_ENABLE 1???//這里在源代碼已經定義好了,但級別為1,表示只能打印LOGE最高級別的錯誤信息,其它的都不能打印,我們調試是可以在這里改
/*
?* This is the local tag used for the following simplified
?* logging macros.? You can change this preprocessor definition
?* before using the other macros to change the tag.
?*/
//這里定義log日志記錄宏,即標簽,方便過濾log消息。
#ifndef LOG_TAG
#define LOG_TAG NULL??? //如果沒有定義則我們默認標簽為NULL
#endif
總結:
如果要輸出打印信息:
①、定義頭文件
#include <cutils/log.h>或#include <log/log.h>等等
②、定義打印級別
#define MTK_LOG_ENABLE4???
③、定義標簽
#define LOG_TAG "JIANMIN.NIU"?
④、調用打印信息
SLOGD("[libshowlogo] read %s : %s\n",name,value);
⑤、執行
adb logcat -s "jianmin.niu"?? //獲取相關信息即可
⑥、如果以上操作還是不行,則有可能打印環境有問題;或者用一下方法:
⑦或者是不是Debug等級的log,默認不開啟,通過終端命令開啟才行
⑧或者用一下方法
添加#include "cutils/logd.h"
定義TAG,如:#define TAG "errorlog"
直接調用__android_log_print(ANDROID_LOG_ERROR,TAG,"print content");函數打印log信息。
該 __android_log_print 函數在system\core\include\log\log.h中定義?* The stuff in the rest of this file should not be used directly.
?*/
#define android_printLog(prio, tag, fmt...) \
??? __android_log_print(prio, tag, fmt)
#define android_vprintLog(prio, cond, tag, fmt...) \
??? __android_log_vprint(prio, tag, fmt)
⑨、MTK的建議
????? [1]、法一:失敗
??????????關機充電的時候,mobilelog是無法抓取
同樣uart log這邊也是無法抓取的,logcat這邊由于沒有加載,所以也抓取不到log
所以請您幫忙在
1.
init.rc中添加如下
在
on property:ro.debuggable=1
# Give writes to anyone for the trace folder on debug builds.
# The folder is used to store method traces.
chmod 0773 /data/misc/trace
start console
之后添加
????#add by mtk13230 debug for charger log
on property:ro.debuggable=0
# Give writes to anyone for the trace folder on debug builds.
# The folder is used to store method traces.
chmod 0773 /data/misc/trace
start console
????#end add
2.?
在init.mt6735.rc中添加
在on charger 這段的最后start servicemanager 之后添加
????#add by mtk13230 for debug charger log
????start logd
????start logcatd
????#end add
然后您build code后,在uart上面再輸入logcat,看是否可以抓取到charging_animation這邊的log
結果:按照你描述的方式修改init.rc和init.mt6735.rc后 show_animation_common.c文件中添加的ALOGD,SLOGE,SLOGD 打印串口log還是均無法輸出出來
【2】法二:
請您使用如下的命令抓取log
logcat -b main -b system -v threadtime
看是否能抓取到您想要的log
結果:關機充電連不上adb的怎么使用logcat?
關機充電只能打串口log,串口log使用不了logcat
【3】、法三:
???????===>> 下面第一步中有開console, 所以uart 可以獲取console, 第二步中有拉logd和logcat 就能用logcat 抓log
關機充電的時候,mobilelog是無法抓取
同樣uart log這邊也是無法抓取的,logcat這邊由于沒有加載,所以也抓取不到log
所以請您幫忙在
1.
init.rc中添加如下
在
on property:ro.debuggable=1
# Give writes to anyone for the trace folder on debug builds.
# The folder is used to store method traces.
chmod 0773 /data/misc/trace
start console
之后添加
????#add by mtk13230 debug for charger log
on property:ro.debuggable=0
# Give writes to anyone for the trace folder on debug builds.
# The folder is used to store method traces.
chmod 0773 /data/misc/trace
start console
????#end add
2.?
在init.mt6735.rc中添加
在on charger 這段的最后start servicemanager 之后添加
????#add by mtk13230 for debug charger log
????start logd
????start logcatd
????#end add
然后您build code后,在uart上面再輸入logcat,看是否可以抓取到charging_animation這邊的log
串口上應當是可以輸入command的
您看一下是否TX、RX,地線都有接
結果:沒有出來
【4】法四:可以了
從您這邊看到,
/vendor/mediatek/proprietary/external/charger 下面的log是可以show出來的
[ 4.971466] <0>.(0)[205:kpoc_charger]charger: [ChargingAnimation: bootlogo_init 97]
[ 4.972426] <0>.(0)[205:kpoc_charger]charger: [ChargingAnimation: sync_anim_version 55]
您可以在/vendor/mediatek/proprietary/external/libshowlogo/ 中也借鑒一下這里的打印方式
charger這邊的打印方式為KPOC_LOGI 等
定義應當是在
/vendor/mediatek/proprietary/external/charger/main.h
#define KPOC_LOGI(x...) do { KLOG_ERROR("charger", x); } while (0)
// HACK: Sprout drops previous console logs below log level 4
#define KPOC_LOGE(x...) do { KLOG_WARNING("charger", x); } while (0)
#define KPOC_LOGD(x...) do { KLOG_DEBUG("charger", x); } while (0)
結果:使用 KPOC_LOGI 就可以打印了
(3)、禁止使用new Exception("print trace").printStackTrace()或者Log. getStackTraceString(Exception)方式打印普通調試信息,因為這種方式打印Log非常消耗系統資源。此種方式打印Log一般只出現try..catch某個異常使用。
(4)、Log的tag命名,使用Activity名稱或者類、模塊的名稱,不要出現自己的姓名拼音或其他簡稱。在c++/c代碼中調用ALOGD等宏函數,參數沒有傳入tag,需要在文件頭部#define LOG_TAG"YOUR_TAG_NAME"。------》如:#define LOG_TAG "BootLogoUpdater"
(5)、Log的內容,不要出現公司名稱、個人名稱或相關簡稱,Log內容不要出現無意義的內容,如連續的等號或星號或連續的數字等,Log內容要方便其他分析Log的人員查看。
(6)、Log輸出的頻率需要控制,例如1s打印一次的Log,盡量只在eng版本使用,user版本如需開啟,請默認關閉,通過設置setprop命令來開啟。
5、各層詳細說明
1. java層
import android.util.Log;
對應的級別 打印方法 ?
VERBOSE Log.v()
DEBUG Log.d()
INFO Log.i()
WARN Log.w()
ERROR Log.e()
方法:
Log.d(TAG, "something to say.");
java層打印log由類android.util.Log類實現,該類定義于文件:
frameworks/base/core/java/android/util/Log.java (APP 框架層)
對應的JNI層代碼在文件:frameworks/base/core/jni/android_util_Log.cpp (本地框架層)
這個層次主要調用了HAL層的liblog庫中的函數__android_log_buf_write() --> write_to_log() -->?
?__write_to_log_kernel() --> log_writev() (這些函數都處于庫liblog中: system/core/liblog)。
?
這樣在上層java中只要包含了類android.util.Log,都可以使用Log.v, Log.d, Log.i來打印log。
其實,android編譯版本可以根據TARGET_BUILD_TYPE等于debug或者release來打開和屏蔽掉log信息,但是這必須得有個前提,
就是我們在上層調用Log.d等函數的時候需要按照如下格式來寫即可:
static boolean DEBUG = true && Config.DEBUG;
if(DEBUG)
?Log.d(TAG, "storeMessage " + this.toString());
這里實際上是可以直接用if(Config.DEBUG)的,但是為了能夠我們自己控制這個log的輸出的話,建議使用上面的方式。比如在debug版本
的時候,我們就可以通過flase && Config.DEBUG來去掉這些log輸出。
Config類的實現在文件:frameworks/base/core/java/android/util/Config.java,其中將會引用類ConfigBuildFlags,這個類是在
目錄:frameworks/base/core/config/? - debug、ndebug、sdk目錄,到底使用哪一個目錄下的ConfigBuildFlags定義,需要取決于
TARGET_BUILD_TYPE的定義:(這個config目錄下還有一個readme文件,可以讀讀,會有幫助的)
One of the subdirectories {debug, ndebug} is included in framework.jar by http://www.cnblogs.com/Android.mk depending on the value of
$(TARGET_BUILD_TYPE).
那就來看一下http://www.cnblogs.com/Android.mk這個文件中如何決定的:
frameworks/base/Android.mk
# Include a different set of source files when building a debug build.
# TODO: Maybe build these into a separate .jar and put it on the classpath
#?????? in front of framework.jar.
# NOTE: Do not use this as an example; this is a very special situation.
#?????? Do not modify LOCAL_SRC_FILES based on any variable other
#?????? than TARGET_BUILD_TYPE, otherwise builds can become inconsistent.
ifeq ($(TARGET_BUILD_TYPE),debug)
? LOCAL_SRC_FILES += $(call find-other-java-files,core/config/debug)
else
? LOCAL_SRC_FILES += $(call find-other-java-files,core/config/ndebug)
endif
這里就是通過TARGET_BUILD_TYPE來選擇將那個目錄下的ConfigBuildFlags定義編譯進framework.jar。
編譯android的時候可以通過這兩個宏來進行組合:TARGET_BUILD_VARIANT 和TARGET_BUILD_TYPE
TARGET_BUILD_VARIANT: user userdebug eng tests (默認eng)
TARGET_BUILD_TYPE: debug release (默認release)
這兩個宏可以定義在文件buildspec.mk下,也可以直接加載make命令中,也可以使用. build/envsetup.sh之后使用choosevariant來選擇。
對java層log輸出的實現修改:
lizhiguo@informax-ui1:~/new_hope/alps/frameworks/base/core/jni$?svn diff android_util_Log.cpp
Index: android_util_Log.cpp
===================================================================
--- android_util_Log.cpp??????? (revision 510)
+++ android_util_Log.cpp??????? (working copy)
@@ -79,9 +79,12 @@
?static int toLevel(const char* value)
?{
???? switch (value[0]) {
-??????? case 'V': return levels.verbose;
-??????? case 'D': return levels.debug;
-??????? case 'I': return levels.info;
+?????????????? case 'V': return -1;? // lizhiguo 2011-07-19
+??????? //case 'V': return levels.verbose;
+??????? //case 'D': return levels.debug;
+??????? //case 'I': return levels.info;
+??????? case 'D': return -1;
+??????? case 'I': return -1;
???????? case 'W': return levels.warn;
???????? case 'E': return levels.error;
???????? case 'A': return levels.assert;
@@ -165,7 +168,9 @@
???????? tag = env->GetStringUTFChars(tagObj, NULL);
???? msg = env->GetStringUTFChars(msgObj, NULL);
-??? int res = __android_log_buf_write(bufID, (android_LogPriority)priority, tag, msg);
+??? int res = 1;?? /* lizhiguo 2011-07-19, for release sofe */
+??? if( (priority != 2) && (priority != 3) && (priority != 4) )
+??????? res = __android_log_buf_write(bufID, (android_LogPriority)priority, tag, msg);
???? if (tag != NULL)
???????? env->ReleaseStringUTFChars(tagObj, tag);
2、?FRAMEWORK層import android.util.Slog;
對應的級別 打印方法 ?
VERBOSE Slog.v()
DEBUG Slog.d()
INFO Slog.i()
WARN Slog.w()
ERROR Slog.e()
方法:
Slog.d(TAG, "something to say.");
3. 中間層(HAL+JNI)
HAL層:
頭文件:
#include <utils/Log.h>
對應的級別 打印方法 ?
VERBOSE LOGV()
DEBUG LOGD()
INFO LOGI()
WARN LOGW()
ERROR LOGE()
方法:
LOGD("%d, %s", int, char* )
JNI層頭文件:
#include <utils/Log.h>
對應的級別 打印方法 ?
VERBOSE LOGV()
DEBUG LOGD()
INFO LOGI()
WARN LOGW()
ERROR LOGE()
方法:
LOGD("%d, %s", int, char* )
?JNI層代碼需包含頭文件frameworks/base/include/utils/Log.h,實際上這個頭文件include了HAL層代碼使用的頭文件system/core/include/cutils/log.h
?在相應的中間層代碼中包含log TAG的地方,使用如下形式:
??? //#define? NDEBUG
??? #define? LOG_NDEBUG? 1
??? #define? LOG_TAG? "RFID_HAL"
?? ?#include <cutils/log.h>
?? ?
下面是關于HAL層log的屏蔽代碼:主要是去掉V、D、I等級的log輸出:
lizhiguo@informax-ui1:~/new_hope/alps$?svn diff system/core/include/cutils/log.h
Index: system/core/include/cutils/log.h
===================================================================
--- system/core/include/cutils/log.h??? (revision 510)
+++ system/core/include/cutils/log.h??? (working copy)
@@ -51,6 +51,8 @@
? * You can modify this (for example with "#define LOG_NDEBUG 0"
? * at the top of your source file) to change that behavior.
? */
+#define LOG_NDEBUG 1?? /* lizhiguo 2011-07-19, for release sofe*/
+
?#ifndef LOG_NDEBUG
?#ifdef NDEBUG
?#define LOG_NDEBUG 1
@@ -98,29 +100,45 @@
? * Simplified macro to send a debug log message using the current LOG_TAG.
? */
?#ifndef LOGD
+#if LOG_NDEBUG????????? /* lizhiguo 2011-07-19, for release sofe*/
+#define LOGD(...)?? ((void)0)
+#else
?#define LOGD(...) ((void)LOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__))
?#endif
+#endif
?#ifndef LOGD_IF
+#if LOG_NDEBUG
+#define LOGD_IF(cond, ...)?? ((void)0)
+#else
?#define LOGD_IF(cond, ...) \
???? ( (CONDITION(cond)) \
???? ? ((void)LOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \
???? : (void)0 )
?#endif
+#endif
?/*
? * Simplified macro to send an info log message using the current LOG_TAG.
? */
?#ifndef LOGI
+#if LOG_NDEBUG????????? /* lizhiguo 2011-07-19, for release sofe*/
+#define LOGI(...)?? ((void)0)
+#else
?#define LOGI(...) ((void)LOG(LOG_INFO, LOG_TAG, __VA_ARGS__))
?#endif
+#endif
?#ifndef LOGI_IF
+#if LOG_NDEBUG
+#define LOGI_IF(cond, ...)?? ((void)0)
+#else
?#define LOGI_IF(cond, ...) \
???? ( (CONDITION(cond)) \
???? ? ((void)LOG(LOG_INFO, LOG_TAG, __VA_ARGS__)) \
???? : (void)0 )
?#endif
+#endif
?/*
? * Simplified macro to send a warning log message using the current LOG_TAG.
@@ -169,16 +187,24 @@
? * debug priority.
? */
?#ifndef IF_LOGD
+#if LOG_NDEBUG????????????? /* lizhiguo 2011-07-19, for release sofe*/
+#define IF_LOGD() if (false)
+#else
?#define IF_LOGD() IF_LOG(LOG_DEBUG, LOG_TAG)
?#endif
+#endif
?/*
? * Conditional based on whether the current LOG_TAG is enabled at
? * info priority.
? */
?#ifndef IF_LOGI
+#if LOG_NDEBUG????????? /* lizhiguo 2011-07-19, for release sofe*/
+#define IF_LOGI() if (false)
+#else
?#define IF_LOGI() IF_LOG(LOG_INFO, LOG_TAG)
?#endif
+#endif
?/*
? * Conditional based on whether the current LOG_TAG is enabled at
@@ -227,29 +253,45 @@
? * Simplified macro to send a debug system log message using the current LOG_TAG.
? */
?#ifndef SLOGD
+#if LOG_NDEBUG????????????? /* lizhiguo 2011-07-19, for release sofe*/
+#define SLOGD(...)?? ((void)0)
+#else
?#define SLOGD(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
?#endif
+#endif
?#ifndef SLOGD_IF
+#if LOG_NDEBUG
+#define SLOGD_IF(cond, ...)?? ((void)0)
+#else
?#define SLOGD_IF(cond, ...) \
???? ( (CONDITION(cond)) \
???? ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \
???? : (void)0 )
?#endif
+#endif
?/*
? * Simplified macro to send an info system log message using the current LOG_TAG.
? */
?#ifndef SLOGI
+#if LOG_NDEBUG????????????? /* lizhiguo 2011-07-19, for release sofe*/
+#define SLOGI(...)?? ((void)0)
+#else
?#define SLOGI(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
?#endif
+#endif
?#ifndef SLOGI_IF
+#if LOG_NDEBUG
+#define SLOGI_IF(cond, ...)?? ((void)0)
+#else
?#define SLOGI_IF(cond, ...) \
???? ( (CONDITION(cond)) \
???? ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) \
???? : (void)0 )
?#endif
+#endif
?/*
? * Simplified macro to send a warning system log message using the current LOG_TAG.
??
4. c代碼
?對于c代碼,為了更好更容易地控制log輸出,在每個模塊中單獨定義print語句時,最好在全局控制宏的控制之下來定義。
?#define C_PRINTF_CONTROL
?
?模塊中定義:
?#define CUSTOM_DEF_TPD
?#ifdef? C_PRINTF_CONTROL
?#ifdef? CUSTOM_DEF_TPD
?#define TPD_DEBUG(a,arg...) ?printk(TPD_DEVICE ": " a,##arg)
?#else???????// CUSTOM_DEF_TPD
?#define TPD_DEBUG(arg...)
?#endif???????// CUSTOM_DEF_TPD
?#else? ???????// C_PRINTF_CONTROL
?#define TPD_DEBUG(arg...)
?#endif? ??????// C_PRINTF_CONTROL
四、使用logcat來打印系統日志信息
logCat是用來獲取系統日志信息的工具,它可以捕獲的信息包括Dalvik虛擬機產生的信息,進程信息,ActivityManager信息,PackagerManager信息,Android運行時信息和應用程序信息等等。
我們可以在打開Eclipse之后,選擇Window?–>?Show?View?->Other菜單,然后在Android->LogCat中選擇LogCat,這樣LogCat便會在Eclipse的下方區域出現了。
其中,在LogCat的右上方的5個字母分別表示了5種不同類型的日志信息(并以不同顏色加以區分,級別越高,顏色越突出):
1.?[V]:詳細(Verbose)信息,輸出顏色為黑色
2.?[D]:調試(Debug)信息,輸出顏色是藍色
3.?[I]:通告(Info)信息,輸出顏色為綠色
4.?[W]:警告(Warn)信息,輸出顏色為橙色
5.?[E]:錯誤(Error)信息,輸出顏色為紅色,這里錯誤信息的級別最高,其次是警告信息,然后是通知信息和調試信息,級別最低的是詳細信息。
6.[assert],新版本加入的。
在LogCat中,我們可以通告這5個字母圖標選擇要顯示的信息類型,級別高于所選類型的信息也會在LogCat中顯示,但級別低于所選類型的信息則不會被顯示。
androidsdk中提供了log輸出的api,方法在android.util.Log類中。
Log.v(tag,message);???????//verbose模式,打印最詳細的日志?
Log.d(tag,message);???????//debug的日志?
Log.i(tag,message);???????//info的日志?
Log.w(tag,message);?? ? ? //warn的日志?
Log.e(tag,message);???????//error的日志?
根據首字母對應VERBOSE,DEBUG,INFO,WARN,ERROR。
tag和message分別是兩個String值?
tag用來標記log消息的源頭的. message是這條log的內容。
1.自定義打印TAG
自定義全局TAG
新建一個Application類LoggerDemoApplication,在onCreate方法中調用Logger.init(TAG)。
public class LoggerDemoApplication extends Application {private String TAG = "LoggerDemo";@Overridepublic void onCreate() {super.onCreate();Logger.init(TAG);} }在AndroidManifest中加入application的name屬性。
<applicationandroid:name=".LoggerDemoApplication"... </application>自定義單個TAG
Logger.t("MyTag").d("Hello World!");3.關閉日志打印
在LoggerDemoApplication中,設置log的級別為NONE即可關閉日志打印。
Logger.init(TAG).logLevel(LogLevel.NONE);3.更多設置
Logger.methodCount(3) // 設置打印方法棧的個數,默認是2.hideThreadInfo() // 隱藏線程信息,默認顯示.methodOffset(2) // 設置調用堆棧的偏移值,默認是0.logAdapter(new AndroidLogAdapter()); // 自定義Log適配器 }總結
以上是生活随笔為你收集整理的LINUX系统以及ANDROID 平台log信息输出级别设置 [MTK]的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android——APK 在32bit/
- 下一篇: Android 编译命令