⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fake_log_device.c

📁 Android 一些工具
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 2008 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. *//* * Intercepts log messages intended for the Android log device. * When running in the context of the simulator, the messages are * passed on to the underlying (fake) log device.  When not in the * simulator, messages are printed to stderr. */#include "cutils/logd.h"#include <stdlib.h>#include <string.h>#include <ctype.h>#include <errno.h>#include <fcntl.h>#ifdef HAVE_PTHREADS#include <pthread.h>#endif#define kMaxTagLen  16      /* from the long-dead utils/Log.cpp */#define kTagSetSize 16      /* arbitrary */#if 0#define TRACE(...) printf("fake_log_device: " __VA_ARGS__)#else#define TRACE(...) ((void)0)#endif/* from the long-dead utils/Log.cpp */typedef enum {    FORMAT_OFF = 0,    FORMAT_BRIEF,    FORMAT_PROCESS,    FORMAT_TAG,    FORMAT_THREAD,    FORMAT_RAW,    FORMAT_TIME,    FORMAT_THREADTIME,    FORMAT_LONG} LogFormat;/* * Log driver state. */typedef struct LogState {    /* the fake fd that's seen by the user */    int     fakeFd;    /* a printable name for this fake device */    char   *debugName;    /* nonzero if this is a binary log */    int     isBinary;    /* global minimum priority */    int     globalMinPriority;    /* output format */    LogFormat outputFormat;    /* tags and priorities */    struct {        char    tag[kMaxTagLen];        int     minPriority;    } tagSet[kTagSetSize];} LogState;#ifdef HAVE_PTHREADS/* * Locking.  Since we're emulating a device, we need to be prepared * to have multiple callers at the same time.  This lock is used * to both protect the fd list and to prevent LogStates from being * freed out from under a user. */static pthread_mutex_t fakeLogDeviceLock = PTHREAD_MUTEX_INITIALIZER;static void lock(){    pthread_mutex_lock(&fakeLogDeviceLock);}static void unlock(){    pthread_mutex_unlock(&fakeLogDeviceLock);}#else   // !HAVE_PTHREADS#define lock() ((void)0)#define unlock() ((void)0)#endif  // !HAVE_PTHREADS/* * File descriptor management. */#define FAKE_FD_BASE 10000#define MAX_OPEN_LOGS 16static LogState *openLogTable[MAX_OPEN_LOGS];/* * Allocate an fd and associate a new LogState with it. * The fd is available via the fakeFd field of the return value. */static LogState *createLogState(){    size_t i;    for (i = 0; i < sizeof(openLogTable); i++) {        if (openLogTable[i] == NULL) {            openLogTable[i] = calloc(1, sizeof(LogState));            openLogTable[i]->fakeFd = FAKE_FD_BASE + i;            return openLogTable[i];        }    }    return NULL;}/* * Translate an fd to a LogState. */static LogState *fdToLogState(int fd){    if (fd >= FAKE_FD_BASE && fd < FAKE_FD_BASE + MAX_OPEN_LOGS) {        return openLogTable[fd - FAKE_FD_BASE];    }    return NULL;}/* * Unregister the fake fd and free the memory it pointed to. */static void deleteFakeFd(int fd){    LogState *ls;    lock();    ls = fdToLogState(fd);    if (ls != NULL) {        openLogTable[fd - FAKE_FD_BASE] = NULL;        free(ls->debugName);        free(ls);    }    unlock();}/* * Configure logging based on ANDROID_LOG_TAGS environment variable.  We * need to parse a string that looks like * *   *:v jdwp:d dalvikvm:d dalvikvm-gc:i dalvikvmi:i * * The tag (or '*' for the global level) comes first, followed by a colon * and a letter indicating the minimum priority level we're expected to log. * This can be used to reveal or conceal logs with specific tags. * * We also want to check ANDROID_PRINTF_LOG to determine how the output * will look. */static void configureInitialState(const char* pathName, LogState* logState){    static const int kDevLogLen = sizeof("/dev/log/") - 1;    logState->debugName = strdup(pathName);    /* identify binary logs */    if (strcmp(pathName + kDevLogLen, "events") == 0) {        logState->isBinary = 1;    }    /* global min priority defaults to "info" level */    logState->globalMinPriority = ANDROID_LOG_INFO;    /*     * This is based on the the long-dead utils/Log.cpp code.     */    const char* tags = getenv("ANDROID_LOG_TAGS");    TRACE("Found ANDROID_LOG_TAGS='%s'\n", tags);    if (tags != NULL) {        int entry = 0;        while (*tags != '\0') {            char tagName[kMaxTagLen];            int i, minPrio;            while (isspace(*tags))                tags++;            i = 0;            while (*tags != '\0' && !isspace(*tags) && *tags != ':' &&                i < kMaxTagLen)            {                tagName[i++] = *tags++;            }            if (i == kMaxTagLen) {                TRACE("ERROR: env tag too long (%d chars max)\n", kMaxTagLen-1);                return;            }            tagName[i] = '\0';            /* default priority, if there's no ":" part; also zero out '*' */            minPrio = ANDROID_LOG_VERBOSE;            if (tagName[0] == '*' && tagName[1] == '\0') {                minPrio = ANDROID_LOG_DEBUG;                tagName[0] = '\0';            }            if (*tags == ':') {                tags++;                if (*tags >= '0' && *tags <= '9') {                    if (*tags >= ('0' + ANDROID_LOG_SILENT))                        minPrio = ANDROID_LOG_VERBOSE;                    else                        minPrio = *tags - '\0';                } else {                    switch (*tags) {                    case 'v':   minPrio = ANDROID_LOG_VERBOSE;  break;                    case 'd':   minPrio = ANDROID_LOG_DEBUG;    break;                    case 'i':   minPrio = ANDROID_LOG_INFO;     break;                    case 'w':   minPrio = ANDROID_LOG_WARN;     break;                    case 'e':   minPrio = ANDROID_LOG_ERROR;    break;                    case 'f':   minPrio = ANDROID_LOG_FATAL;    break;                    case 's':   minPrio = ANDROID_LOG_SILENT;   break;                    default:    minPrio = ANDROID_LOG_DEFAULT;  break;                    }                }                tags++;                if (*tags != '\0' && !isspace(*tags)) {                    TRACE("ERROR: garbage in tag env; expected whitespace\n");                    TRACE("       env='%s'\n", tags);                    return;                }            }            if (tagName[0] == 0) {                logState->globalMinPriority = minPrio;                TRACE("+++ global min prio %d\n", logState->globalMinPriority);            } else {                logState->tagSet[entry].minPriority = minPrio;                strcpy(logState->tagSet[entry].tag, tagName);                TRACE("+++ entry %d: %s:%d\n",                    entry,                    logState->tagSet[entry].tag,                    logState->tagSet[entry].minPriority);                entry++;            }        }    }    /*     * Taken from the long-dead utils/Log.cpp     */    const char* fstr = getenv("ANDROID_PRINTF_LOG");    LogFormat format;    if (fstr == NULL) {        format = FORMAT_BRIEF;    } else {        if (strcmp(fstr, "brief") == 0)            format = FORMAT_BRIEF;        else if (strcmp(fstr, "process") == 0)            format = FORMAT_PROCESS;        else if (strcmp(fstr, "tag") == 0)            format = FORMAT_PROCESS;        else if (strcmp(fstr, "thread") == 0)            format = FORMAT_PROCESS;        else if (strcmp(fstr, "raw") == 0)            format = FORMAT_PROCESS;        else if (strcmp(fstr, "time") == 0)            format = FORMAT_PROCESS;        else if (strcmp(fstr, "long") == 0)            format = FORMAT_PROCESS;        else            format = (LogFormat) atoi(fstr);        // really?!    }    logState->outputFormat = format;}/* * Return a human-readable string for the priority level.  Always returns * a valid string. */static const char* getPriorityString(int priority){    /* the first character of each string should be unique */    static const char* priorityStrings[] = {        "Verbose", "Debug", "Info", "Warn", "Error", "Assert"    };    int idx;    idx = (int) priority - (int) ANDROID_LOG_VERBOSE;    if (idx < 0 ||        idx >= (int) (sizeof(priorityStrings) / sizeof(priorityStrings[0])))        return "?unknown?";    return priorityStrings[idx];}#ifndef HAVE_WRITEV/* * Some platforms like WIN32 do not have writev(). * Make up something to replace it. */static ssize_t fake_writev(int fd, const struct iovec *iov, int iovcnt) {    int result = 0;    struct iovec* end = iov + iovcnt;    for (; iov < end; iov++) {        int w = write(fd, iov->iov_base, iov->iov_len);        if (w != iov->iov_len) {            if (w < 0)                return w;            return result + w;        }        result += w;    }    return result;}#define writev fake_writev#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -