我们平时打印log信息,一般情况下是可以打印指定tag信息,首先是你知道这个程序或则个服务的tag,对于第三方的apk我们一般情况下不知道他们的tag,所有在这种情况下想知道他们的log信息特别麻烦,
所以我们改进了原来的logcat工具。使它可以打印指定指定进程的log日志信息!
按照我们平时习惯!加入我们想打印TAG=Gank的log信息。我们在终端在adb shell 连上情况下,
可以输入logcat -s Gank ,如果设备有这个Gank的log信息就会不断输出,在我们中断如下:
V/Gank ( 826): Action: android.intent.action.TIME_TICK V/Gank ( 826): ActivityController -- activityStarting PKG: com.pptv.setting---LastPkg: null Int nt: Intent { cmp=com.pptv.setting/.root.SettingsActivity } V/Gank ( 826): == App Login! I/Gank ( 854): log=t:34409714810,p:launcher.pptv.com%2Fv3%2Fnavigation,e:mv,tp:launcher.pptv.co %2Fv3%2F%E8%AE%BE%E7%BD%AE,a:clk,ch:100030; V/Gank ( 826): ActivityController -- activityStarting PKG: com.pptv.setting---LastPkg: com.pptv setting Intent: Intent { cmp=com.pptv.setting/.SystemInfoSetting } V/Gank ( 826): == At Some app -- com.pptv.setting I/Gank ( 990): log=t:3790,p:launcher.pptv.com%2Fv3%2F%E8%AE%BE%E7%BD%AE,e:mv,pr:launcher.pptv.c m%2Fv3%2Fnavigation,a:clk,op:setting_SystemInfo; V/Gank ( 826): Action: android.intent.action.TIME_TICK I/Gank ( 826): BootLog Init and Upload我们改进的可以打印的logcat工具也是按照 -s 指定进程,用同一个标识,例如: logcat -s 625 ,625是进程Id。
改动总共是四个文件分别是
system/core/include/cutils/logprint.h
system/core/include/log/logprint.h
system/core/liblog/logprint.c
system/core/logcat/logcat.cpp
在文件 logcat.cpp代码中
switch(ret) { case 's': // default to all silent android_log_addFilterRule(g_logformat, "*:s"); break;android_log_addFilterRule添加过滤规则的,所以我们在这个函数里面添加过滤pid进程。
在头文件logprint.h中我们先修改上面函数需要用到的结构体
typedef struct FilterInfo_t { char *mTag; int32_t mPid; android_LogPriority mPri; struct FilterInfo_t *p_next; } FilterInfo;我们添加了 int32_t mPid用于存贮pid进程号。
原函数是:
int android_log_addFilterRule(AndroidLogFormat *p_format, const char *filterExpression) { size_t i=0; size_t tagNameLength; android_LogPriority pri = ANDROID_LOG_DEFAULT; tagNameLength = strcspn(filterExpression, ":"); if (tagNameLength == 0) { goto error; } if(filterExpression[tagNameLength] == ':') { pri = filterCharToPri(filterExpression[tagNameLength+1]); if (pri == ANDROID_LOG_UNKNOWN) { goto error; } } if(0 == strncmp("*", filterExpression, tagNameLength)) { // This filter expression refers to the global filter // The default level for this is DEBUG if the priority // is unspecified if (pri == ANDROID_LOG_DEFAULT) { pri = ANDROID_LOG_DEBUG; } p_format->global_pri = pri; } else { // for filter expressions that don't refer to the global // filter, the default is verbose if the priority is unspecified if (pri == ANDROID_LOG_DEFAULT) { pri = ANDROID_LOG_VERBOSE; } char *tagName; // Presently HAVE_STRNDUP is never defined, so the second case is always taken // Darwin doesn't have strnup, everything else does #ifdef HAVE_STRNDUP tagName = strndup(filterExpression, tagNameLength); #else //a few extra bytes copied... tagName = strdup(filterExpression); tagName[tagNameLength] = '\0'; #endif /*HAVE_STRNDUP*/ FilterInfo *p_fi = filterinfo_new(tagName, pri); free(tagName); p_fi->p_next = p_format->filters; p_format->filters = p_fi; } return 0; error: return -1; }
int android_log_addFilterRule(AndroidLogFormat *p_format, const char *filterExpression) { size_t i=0; size_t tagNameLength; android_LogPriority pri = ANDROID_LOG_DEFAULT; tagNameLength = strcspn(filterExpression, ":"); if (tagNameLength == 0) { goto error; } if(filterExpression[tagNameLength] == ':') { pri = filterCharToPri(filterExpression[tagNameLength+1]); if (pri == ANDROID_LOG_UNKNOWN) { goto error; } } if(0 == strncmp("*", filterExpression, tagNameLength)) { // This filter expression refers to the global filter // The default level for this is DEBUG if the priority // is unspecified if (pri == ANDROID_LOG_DEFAULT) { pri = ANDROID_LOG_DEBUG; } p_format->global_pri = pri; } else { // for filter expressions that don't refer to the global // filter, the default is verbose if the priority is unspecified if (pri == ANDROID_LOG_DEFAULT) { pri = ANDROID_LOG_VERBOSE; } char *tagName; // Presently HAVE_STRNDUP is never defined, so the second case is always taken // Darwin doesn't have strnup, everything else does #ifdef HAVE_STRNDUP tagName = strndup(filterExpression, tagNameLength); #else //a few extra bytes copied... tagName = strdup(filterExpression); tagName[tagNameLength] = '\0'; #endif /*HAVE_STRNDUP*/ int n=strlen(tagName); int i,mpid=1,flag=1; FilterInfo *p_fi; for(i=0;i<n;i++) { if(!isdigit(tagName[i])) { flag=0; break; } } if(flag) { mpid=atoi(tagName); p_fi =filterinfo_new("",mpid,pri); } else { p_fi = filterinfo_new(tagName,0, pri); } free(tagName); p_fi->p_next = p_format->filters; p_format->filters = p_fi; } return 0; error: return -1; }
首先获得tagname大小 ,tagname就是 我们的tag(Gank或者625 ),在 c 语言中 通过main函数传递参数一律都是按照字符串对待, int main(int argc, char **argv),所以logcat 获得 argv参数都是字符串,然后判断tagname每一个字符是否都是小于9大于0,若都是我们就认为传递的是进程id,我们就用构造函数 filterinfo_new 构造 FilterInfo *p_fi结构体,
static FilterInfo * filterinfo_new(const char*tag,int32_t pid, android_LogPriority pri) { FilterInfo *p_ret; <pre code_snippet_id="598655" snippet_file_name="blog_20150205_8_9575285" name="code" class="html">p_ret = (FilterInfo *)calloc(1, sizeof(FilterInfo));
p_ret->mTag = strdup(tag);
p_ret->mPid = pid; return p_ret; }
</pre><pre code_snippet_id="598655" snippet_file_name="blog_20150205_9_3771230" name="code" class="html"> p_fi->p_next = p_format->filters; p_format->filters = p_fi;上面两行复制过后全局p_format就保存了我们的p_fi。
下面函数处理我们写到buf的log信息
static void processBuffer(log_device_t* dev, struct logger_entry *buf) { int bytesWritten = 0; int err; AndroidLogEntry entry; char binaryMsgBuf[1024]; if (dev->binary) { err = android_log_processBinaryLogBuffer(buf, &entry, g_eventTagMap, binaryMsgBuf, sizeof(binaryMsgBuf)); //printf(">>> pri=%d len=%d msg='%s'\n", // entry.priority, entry.messageLen, entry.message); } else { err = android_log_processLogBuffer(buf, &entry); } if (err < 0) { goto error; } if (android_log_shouldPrintLine(g_logformat, entry.tag, entry.pid,entry.priority)) { if (false && g_devCount > 1) { binaryMsgBuf[0] = dev->label; binaryMsgBuf[1] = ' '; bytesWritten = write(g_outFD, binaryMsgBuf, 2); if (bytesWritten < 0) { perror("output error"); exit(-1); } }函数android_log_shouldPrintLine
用于确定打印指定log日志信息,
原函数是
int android_log_shouldPrintLine ( AndroidLogFormat *p_format, const char *tag, android_LogPriority pri) { return pri >= filterPriForTag(p_format, tag); }
int android_log_shouldPrintLine ( AndroidLogFormat *p_format, const char *tag,int32_t pid, android_LogPriority pri) { return pri >= filterPriForTag(p_format, tag,pid); }
原函数:
static android_LogPriority filterPriForTag( AndroidLogFormat *p_format, const char *tag) { FilterInfo *p_curFilter; for (p_curFilter = p_format->filters ; p_curFilter != NULL ; p_curFilter = p_curFilter->p_next ) { if (p_curFilter->mPri == ANDROID_LOG_DEFAULT) { return p_format->global_pri; } else { return p_curFilter->mPri; } } return p_format->global_pri; }
static android_LogPriority filterPriForTag( AndroidLogFormat *p_format, const char *tag,int32_t pid) { FilterInfo *p_curFilter; for (p_curFilter = p_format->filters ; p_curFilter != NULL ; p_curFilter = p_curFilter->p_next) { if(p_curFilter->mPid != 0) { if (pid==p_curFilter->mPid) { if (p_curFilter->mPri == ANDROID_LOG_DEFAULT) { return p_format->global_pri; } else { return p_curFilter->mPri; } } } else { if(0 == strcmp(tag, p_curFilter->mTag)) { if (pid==p_curFilter->mPid) { if (p_curFilter->mPri == ANDROID_LOG_DEFAULT) { return p_format->global_pri; } else { return p_curFilter->mPri; } } } } } return p_format->global_pri; }
--------- beginning of /dev/log/system D/PowerManagerNotifier( 625): onWakeLockReleased: flags=1, tag="AlarmManager", packageName=android, ownerUid=1000, ownerPid=625, workSource=WorkSource{10016} D/PowerManagerService( 625): updateWakeLockSummaryLocked: mWakefulness=Awake, mWakeLockSummary=0x0 D/PowerManagerService( 625): newScreenState = 2 D/PowerManagerService( 625): updateScreenStateLocked: mScreenBrightnessModeSetting=2, autoBrightness=false, ecoBrightness=true, screenAutoBrightnessAdjustment=0.0, screenBrightness=102 D/PowerManagerDisplayController( 625): requestPowerState: screenState=2, useProximitySensor=false, forceProximitySensorEnable=false, forceWakeUpEnable=false, screenBrightness=102, screenAutoBrightnessAdjustment=0.0, useAutoBrightness=false, useEcoBrightness=true, blockScreenOn=false, waitForNegativeProximity=false I/PowerManagerService( 625): setBrightness mButtonLight 0. D/PowerManagerService( 625): updateScreenStateLocked: mDisplayReady=true, newScreenState=2, mWakefulness=1, mWakeLockSummary=0x0, mUserActivitySummary=0x1, mBootCompleted=true D/PowerManagerService( 625): Releasing suspend blocker "PowerManagerService.WakeLocks". D/PowerManagerService( 625): handleSandman: canDream=true, mWakefulness=Awake V/ActivityManager( 625): Broadcast: Intent { act=android.intent.action.TIME_TICK flg=0x50000014 (has extras) } ordered=true userid=-1 callerApp=null D/PowerManagerService( 625): acquireWakeLockInternal: lock=1106590840, flags=0x1, tag="AlarmManager", ws=WorkSource{1000}, uid=1000, pid=625 D/PowerManagerNotifier( 625): onWakeLockAcquired: flags=1, tag="AlarmManager", packageName=android, ownerUid=1000, ownerPid=625, workSource=WorkSource{1000} @