adb 打印指定进程的log信息

我们平时打印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);
}

多了一个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;
}

先是判断判断entry.pid大于0就是传递pid,等于0就是传递tag, 接着我们entry结构体中的pid,entry.pid是否和p_format 结构体中相等, 就打印entry的log信息进程pid的日志信息。

--------- 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}
@                                                          

结果先是正确








  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

九霄的爸爸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值