📄 logprint.c
字号:
/* //device/libs/cutils/logprint.c**** Copyright 2006, The Android Open Source Project**** Licensed under the Apache License, Version 2.0 (the "License");** you may not use this file except in compliance with the License.** You may obtain a copy of the License at**** http://www.apache.org/licenses/LICENSE-2.0**** Unless required by applicable law or agreed to in writing, software** distributed under the License is distributed on an "AS IS" BASIS,** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.** See the License for the specific language governing permissions and** limitations under the License.*/#define _GNU_SOURCE /* for asprintf */#include <ctype.h>#include <stdio.h>#include <errno.h>#include <stdlib.h>#include <stdint.h>#include <string.h>#include <alloca.h>#include <assert.h>#include <arpa/inet.h>#include <cutils/logd.h>#include <cutils/logprint.h>typedef struct FilterInfo_t { char *mTag; android_LogPriority mPri; struct FilterInfo_t *p_next;} FilterInfo;struct AndroidLogFormat_t { android_LogPriority global_pri; FilterInfo *filters; AndroidLogPrintFormat format;};static FilterInfo * filterinfo_new(const char * tag, android_LogPriority pri){ FilterInfo *p_ret; p_ret = (FilterInfo *)calloc(1, sizeof(FilterInfo)); p_ret->mTag = strdup(tag); p_ret->mPri = pri; return p_ret;}static void filterinfo_free(FilterInfo *p_info){ if (p_info == NULL) { return; } free(p_info->mTag); p_info->mTag = NULL;}/* * Note: also accepts 0-9 priorities * returns ANDROID_LOG_UNKNOWN if the character is unrecognized */static android_LogPriority filterCharToPri (char c){ android_LogPriority pri; c = tolower(c); if (c >= '0' && c <= '9') { if (c >= ('0'+ANDROID_LOG_SILENT)) { pri = ANDROID_LOG_VERBOSE; } else { pri = (android_LogPriority)(c - '0'); } } else if (c == 'v') { pri = ANDROID_LOG_VERBOSE; } else if (c == 'd') { pri = ANDROID_LOG_DEBUG; } else if (c == 'i') { pri = ANDROID_LOG_INFO; } else if (c == 'w') { pri = ANDROID_LOG_WARN; } else if (c == 'e') { pri = ANDROID_LOG_ERROR; } else if (c == 'f') { pri = ANDROID_LOG_FATAL; } else if (c == 's') { pri = ANDROID_LOG_SILENT; } else if (c == '*') { pri = ANDROID_LOG_DEFAULT; } else { pri = ANDROID_LOG_UNKNOWN; } return pri;}static char filterPriToChar (android_LogPriority pri){ switch (pri) { case ANDROID_LOG_VERBOSE: return 'V'; case ANDROID_LOG_DEBUG: return 'D'; case ANDROID_LOG_INFO: return 'I'; case ANDROID_LOG_WARN: return 'W'; case ANDROID_LOG_ERROR: return 'E'; case ANDROID_LOG_FATAL: return 'F'; case ANDROID_LOG_SILENT: return 'S'; case ANDROID_LOG_DEFAULT: case ANDROID_LOG_UNKNOWN: default: return '?'; }}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 (0 == strcmp(tag, p_curFilter->mTag)) { if (p_curFilter->mPri == ANDROID_LOG_DEFAULT) { return p_format->global_pri; } else { return p_curFilter->mPri; } } } return p_format->global_pri;}/** for debugging */static void dumpFilters(AndroidLogFormat *p_format){ FilterInfo *p_fi; for (p_fi = p_format->filters ; p_fi != NULL ; p_fi = p_fi->p_next) { char cPri = filterPriToChar(p_fi->mPri); if (p_fi->mPri == ANDROID_LOG_DEFAULT) { cPri = filterPriToChar(p_format->global_pri); } fprintf(stderr,"%s:%c\n", p_fi->mTag, cPri); } fprintf(stderr,"*:%c\n", filterPriToChar(p_format->global_pri));}/** * returns 1 if this log line should be printed based on its priority * and tag, and 0 if it should not */int android_log_shouldPrintLine ( AndroidLogFormat *p_format, const char *tag, android_LogPriority pri){ return pri >= filterPriForTag(p_format, tag);}AndroidLogFormat *android_log_format_new(){ AndroidLogFormat *p_ret; p_ret = calloc(1, sizeof(AndroidLogFormat)); p_ret->global_pri = ANDROID_LOG_VERBOSE; p_ret->format = FORMAT_BRIEF; return p_ret;}void android_log_format_free(AndroidLogFormat *p_format){ FilterInfo *p_info, *p_info_old; p_info = p_format->filters; while (p_info != NULL) { p_info_old = p_info; p_info = p_info->p_next; free(p_info_old); } free(p_format);}void android_log_setPrintFormat(AndroidLogFormat *p_format, AndroidLogPrintFormat format){ p_format->format=format;}/** * Returns FORMAT_OFF on invalid string */AndroidLogPrintFormat android_log_formatFromString(const char * formatString){ static AndroidLogPrintFormat format; if (strcmp(formatString, "brief") == 0) format = FORMAT_BRIEF; else if (strcmp(formatString, "process") == 0) format = FORMAT_PROCESS; else if (strcmp(formatString, "tag") == 0) format = FORMAT_TAG; else if (strcmp(formatString, "thread") == 0) format = FORMAT_THREAD; else if (strcmp(formatString, "raw") == 0) format = FORMAT_RAW; else if (strcmp(formatString, "time") == 0) format = FORMAT_TIME; else if (strcmp(formatString, "threadtime") == 0) format = FORMAT_THREADTIME; else if (strcmp(formatString, "long") == 0) format = FORMAT_LONG; else format = FORMAT_OFF; return format;}/** * filterExpression: a single filter expression * eg "AT:d" * * returns 0 on success and -1 on invalid expression * * Assumes single threaded execution */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;}/** * filterString: a comma/whitespace-separated set of filter expressions * * eg "AT:d *:i" * * returns 0 on success and -1 on invalid expression * * Assumes single threaded execution * */int android_log_addFilterString(AndroidLogFormat *p_format, const char *filterString){ char *filterStringCopy = strdup (filterString); char *p_cur = filterStringCopy; char *p_ret; int err; // Yes, I'm using strsep while (NULL != (p_ret = strsep(&p_cur, " \t,"))) { // ignore whitespace-only entries if(p_ret[0] != '\0') { err = android_log_addFilterRule(p_format, p_ret); if (err < 0) { goto error; } } } free (filterStringCopy); return 0;error: free (filterStringCopy); return -1;}static inline char * strip_end(char *str){ char *end = str + strlen(str) - 1; while (end >= str && isspace(*end)) *end-- = '\0'; return str;}/** * Splits a wire-format buffer into an AndroidLogEntry * entry allocated by caller. Pointers will point directly into buf * * Returns 0 on success and -1 on invalid wire format (entry will be * in unspecified state) */int android_log_processLogBuffer(struct logger_entry *buf, AndroidLogEntry *entry){ size_t tag_len; entry->tv_sec = buf->sec; entry->tv_nsec = buf->nsec; entry->priority = buf->msg[0]; entry->pid = buf->pid; entry->tid = buf->tid; entry->tag = buf->msg + 1; tag_len = strlen(entry->tag); entry->messageLen = buf->len - tag_len - 3; entry->message = entry->tag + tag_len + 1; return 0;}/* * Extract a 4-byte value from a byte stream. */static inline uint32_t get4LE(const uint8_t* src){ return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);}/* * Extract an 8-byte value from a byte stream. */static inline uint64_t get8LE(const uint8_t* src){ uint32_t low, high; low = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24); high = src[4] | (src[5] << 8) | (src[6] << 16) | (src[7] << 24); return ((long long) high << 32) | (long long) low;}/* * Recursively convert binary log data to printable form. * * This needs to be recursive because you can have lists of lists. * * If we run out of room, we stop processing immediately. It's important * for us to check for space on every output element to avoid producing * garbled output. * * Returns 0 on success, 1 on buffer full, -1 on failure. */static int android_log_printBinaryEvent(const unsigned char** pEventData, size_t* pEventDataLen, char** pOutBuf, size_t* pOutBufLen){ const unsigned char* eventData = *pEventData; size_t eventDataLen = *pEventDataLen; char* outBuf = *pOutBuf; size_t outBufLen = *pOutBufLen; unsigned char type; size_t outCount; int result = 0; if (eventDataLen < 1) return -1; type = *eventData++; eventDataLen--; //fprintf(stderr, "--- type=%d (rem len=%d)\n", type, eventDataLen); switch (type) { case EVENT_TYPE_INT: /* 32-bit signed int */ { int ival; if (eventDataLen < 4) return -1; ival = get4LE(eventData); eventData += 4; eventDataLen -= 4; outCount = snprintf(outBuf, outBufLen, "%d", ival); if (outCount < outBufLen) { outBuf += outCount; outBufLen -= outCount; } else { /* halt output */ goto no_room; } } break; case EVENT_TYPE_LONG: /* 64-bit signed long */ { long long lval; if (eventDataLen < 8) return -1; lval = get8LE(eventData); eventData += 8; eventDataLen -= 8; outCount = snprintf(outBuf, outBufLen, "%lld", lval); if (outCount < outBufLen) { outBuf += outCount; outBufLen -= outCount; } else { /* halt output */ goto no_room; } } break; case EVENT_TYPE_STRING: /* UTF-8 chars, not NULL-terminated */ { unsigned int strLen; if (eventDataLen < 4) return -1; strLen = get4LE(eventData); eventData += 4; eventDataLen -= 4; if (eventDataLen < strLen) return -1; if (strLen < outBufLen) { memcpy(outBuf, eventData, strLen); outBuf += strLen; outBufLen -= strLen; } else if (outBufLen > 0) { /* copy what we can */ memcpy(outBuf, eventData, outBufLen); outBuf += outBufLen; outBufLen -= outBufLen; goto no_room; } eventData += strLen;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -