logprint.c revision 4bf3c02e026077d14a4512c7c2f71937da3c2d50
14f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project/* //device/libs/cutils/logprint.c
24f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project**
34f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project** Copyright 2006, The Android Open Source Project
44f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project**
54f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");
64f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project** you may not use this file except in compliance with the License.
74f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project** You may obtain a copy of the License at
84f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project**
94f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project**     http://www.apache.org/licenses/LICENSE-2.0
104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project**
114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project** Unless required by applicable law or agreed to in writing, software
124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS,
134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project** See the License for the specific language governing permissions and
154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project** limitations under the License.
164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project*/
174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#define _GNU_SOURCE /* for asprintf */
194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <ctype.h>
214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <stdio.h>
224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <errno.h>
234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <stdlib.h>
244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <stdint.h>
254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <string.h>
264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <assert.h>
274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <arpa/inet.h>
284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <cutils/logd.h>
304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <cutils/logprint.h>
314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projecttypedef struct FilterInfo_t {
334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char *mTag;
344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    android_LogPriority mPri;
354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct FilterInfo_t *p_next;
364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project} FilterInfo;
374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstruct AndroidLogFormat_t {
394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    android_LogPriority global_pri;
404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    FilterInfo *filters;
414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AndroidLogPrintFormat format;
424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project};
434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic FilterInfo * filterinfo_new(const char * tag, android_LogPriority pri)
454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    FilterInfo *p_ret;
474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    p_ret = (FilterInfo *)calloc(1, sizeof(FilterInfo));
494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    p_ret->mTag = strdup(tag);
504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    p_ret->mPri = pri;
514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return p_ret;
534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void filterinfo_free(FilterInfo *p_info)
564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (p_info == NULL) {
584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    free(p_info->mTag);
624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    p_info->mTag = NULL;
634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project/*
664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * Note: also accepts 0-9 priorities
674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * returns ANDROID_LOG_UNKNOWN if the character is unrecognized
684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project */
694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic android_LogPriority filterCharToPri (char c)
704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    android_LogPriority pri;
724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    c = tolower(c);
744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (c >= '0' && c <= '9') {
764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (c >= ('0'+ANDROID_LOG_SILENT)) {
774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            pri = ANDROID_LOG_VERBOSE;
784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else {
794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            pri = (android_LogPriority)(c - '0');
804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else if (c == 'v') {
824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        pri = ANDROID_LOG_VERBOSE;
834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else if (c == 'd') {
844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        pri = ANDROID_LOG_DEBUG;
854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else if (c == 'i') {
864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        pri = ANDROID_LOG_INFO;
874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else if (c == 'w') {
884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        pri = ANDROID_LOG_WARN;
894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else if (c == 'e') {
904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        pri = ANDROID_LOG_ERROR;
914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else if (c == 'f') {
924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        pri = ANDROID_LOG_FATAL;
934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else if (c == 's') {
944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        pri = ANDROID_LOG_SILENT;
954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else if (c == '*') {
964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        pri = ANDROID_LOG_DEFAULT;
974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        pri = ANDROID_LOG_UNKNOWN;
994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return pri;
1024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
1034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char filterPriToChar (android_LogPriority pri)
1054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
1064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    switch (pri) {
1074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        case ANDROID_LOG_VERBOSE:       return 'V';
1084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        case ANDROID_LOG_DEBUG:         return 'D';
1094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        case ANDROID_LOG_INFO:          return 'I';
1104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        case ANDROID_LOG_WARN:          return 'W';
1114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        case ANDROID_LOG_ERROR:         return 'E';
1124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        case ANDROID_LOG_FATAL:         return 'F';
1134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        case ANDROID_LOG_SILENT:        return 'S';
1144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        case ANDROID_LOG_DEFAULT:
1164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        case ANDROID_LOG_UNKNOWN:
1174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        default:                        return '?';
1184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
1204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic android_LogPriority filterPriForTag(
1224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        AndroidLogFormat *p_format, const char *tag)
1234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
1244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    FilterInfo *p_curFilter;
1254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for (p_curFilter = p_format->filters
1274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ; p_curFilter != NULL
1284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ; p_curFilter = p_curFilter->p_next
1294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ) {
1304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (0 == strcmp(tag, p_curFilter->mTag)) {
1314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (p_curFilter->mPri == ANDROID_LOG_DEFAULT) {
1324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                return p_format->global_pri;
1334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            } else {
1344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                return p_curFilter->mPri;
1354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
1364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
1374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return p_format->global_pri;
1404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
1414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project/** for debugging */
1434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void dumpFilters(AndroidLogFormat *p_format)
1444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
1454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    FilterInfo *p_fi;
1464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for (p_fi = p_format->filters ; p_fi != NULL ; p_fi = p_fi->p_next) {
1484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        char cPri = filterPriToChar(p_fi->mPri);
1494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (p_fi->mPri == ANDROID_LOG_DEFAULT) {
1504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            cPri = filterPriToChar(p_format->global_pri);
1514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
1524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fprintf(stderr,"%s:%c\n", p_fi->mTag, cPri);
1534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    fprintf(stderr,"*:%c\n", filterPriToChar(p_format->global_pri));
1564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
1584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project/**
1604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * returns 1 if this log line should be printed based on its priority
1614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * and tag, and 0 if it should not
1624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project */
1634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectint android_log_shouldPrintLine (
1644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        AndroidLogFormat *p_format, const char *tag, android_LogPriority pri)
1654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
1664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return pri >= filterPriForTag(p_format, tag);
1674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
1684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source ProjectAndroidLogFormat *android_log_format_new()
1704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
1714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AndroidLogFormat *p_ret;
1724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    p_ret = calloc(1, sizeof(AndroidLogFormat));
1744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    p_ret->global_pri = ANDROID_LOG_VERBOSE;
1764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    p_ret->format = FORMAT_BRIEF;
1774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return p_ret;
1794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
1804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid android_log_format_free(AndroidLogFormat *p_format)
1824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
1834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    FilterInfo *p_info, *p_info_old;
1844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    p_info = p_format->filters;
1864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    while (p_info != NULL) {
1884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        p_info_old = p_info;
1894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        p_info = p_info->p_next;
1904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        free(p_info_old);
1924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    free(p_format);
1954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
1964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid android_log_setPrintFormat(AndroidLogFormat *p_format,
2004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        AndroidLogPrintFormat format)
2014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
2024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    p_format->format=format;
2034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
2044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project/**
2064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * Returns FORMAT_OFF on invalid string
2074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project */
2084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source ProjectAndroidLogPrintFormat android_log_formatFromString(const char * formatString)
2094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
2104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static AndroidLogPrintFormat format;
2114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (strcmp(formatString, "brief") == 0) format = FORMAT_BRIEF;
2134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    else if (strcmp(formatString, "process") == 0) format = FORMAT_PROCESS;
2144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    else if (strcmp(formatString, "tag") == 0) format = FORMAT_TAG;
2154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    else if (strcmp(formatString, "thread") == 0) format = FORMAT_THREAD;
2164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    else if (strcmp(formatString, "raw") == 0) format = FORMAT_RAW;
2174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    else if (strcmp(formatString, "time") == 0) format = FORMAT_TIME;
2184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    else if (strcmp(formatString, "threadtime") == 0) format = FORMAT_THREADTIME;
2194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    else if (strcmp(formatString, "long") == 0) format = FORMAT_LONG;
2204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    else format = FORMAT_OFF;
2214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return format;
2234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
2244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project/**
2264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * filterExpression: a single filter expression
2274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * eg "AT:d"
2284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project *
2294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * returns 0 on success and -1 on invalid expression
2304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project *
2314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * Assumes single threaded execution
2324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project */
2334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectint android_log_addFilterRule(AndroidLogFormat *p_format,
2354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const char *filterExpression)
2364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
2374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    size_t i=0;
2384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    size_t tagNameLength;
2394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    android_LogPriority pri = ANDROID_LOG_DEFAULT;
2404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    tagNameLength = strcspn(filterExpression, ":");
2424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (tagNameLength == 0) {
2444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        goto error;
2454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
2464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if(filterExpression[tagNameLength] == ':') {
2484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        pri = filterCharToPri(filterExpression[tagNameLength+1]);
2494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (pri == ANDROID_LOG_UNKNOWN) {
2514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            goto error;
2524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
2544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if(0 == strncmp("*", filterExpression, tagNameLength)) {
2564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // This filter expression refers to the global filter
2574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // The default level for this is DEBUG if the priority
2584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // is unspecified
2594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (pri == ANDROID_LOG_DEFAULT) {
2604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            pri = ANDROID_LOG_DEBUG;
2614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        p_format->global_pri = pri;
2644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
2654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // for filter expressions that don't refer to the global
2664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // filter, the default is verbose if the priority is unspecified
2674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (pri == ANDROID_LOG_DEFAULT) {
2684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            pri = ANDROID_LOG_VERBOSE;
2694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        char *tagName;
2724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project// Presently HAVE_STRNDUP is never defined, so the second case is always taken
2744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project// Darwin doesn't have strnup, everything else does
2754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#ifdef HAVE_STRNDUP
2764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        tagName = strndup(filterExpression, tagNameLength);
2774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#else
2784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        //a few extra bytes copied...
2794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        tagName = strdup(filterExpression);
2804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        tagName[tagNameLength] = '\0';
2814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#endif /*HAVE_STRNDUP*/
2824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        FilterInfo *p_fi = filterinfo_new(tagName, pri);
2844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        free(tagName);
2854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        p_fi->p_next = p_format->filters;
2874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        p_format->filters = p_fi;
2884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
2894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return 0;
2914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projecterror:
2924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return -1;
2934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
2944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project/**
2974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * filterString: a comma/whitespace-separated set of filter expressions
2984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project *
2994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * eg "AT:d *:i"
3004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project *
3014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * returns 0 on success and -1 on invalid expression
3024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project *
3034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * Assumes single threaded execution
3044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project *
3054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project */
3064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectint android_log_addFilterString(AndroidLogFormat *p_format,
3084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const char *filterString)
3094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
3104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char *filterStringCopy = strdup (filterString);
3114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char *p_cur = filterStringCopy;
3124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char *p_ret;
3134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int err;
3144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // Yes, I'm using strsep
3164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    while (NULL != (p_ret = strsep(&p_cur, " \t,"))) {
3174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // ignore whitespace-only entries
3184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if(p_ret[0] != '\0') {
3194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            err = android_log_addFilterRule(p_format, p_ret);
3204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (err < 0) {
3224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                goto error;
3234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
3244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
3254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    free (filterStringCopy);
3284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return 0;
3294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projecterror:
3304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    free (filterStringCopy);
3314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return -1;
3324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
3334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic inline char * strip_end(char *str)
3354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
3364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char *end = str + strlen(str) - 1;
3374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    while (end >= str && isspace(*end))
3394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        *end-- = '\0';
3404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return str;
3414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
3424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project/**
3444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * Splits a wire-format buffer into an AndroidLogEntry
3454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * entry allocated by caller. Pointers will point directly into buf
3464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project *
3474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * Returns 0 on success and -1 on invalid wire format (entry will be
3484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * in unspecified state)
3494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project */
3504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectint android_log_processLogBuffer(struct logger_entry *buf,
3514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                 AndroidLogEntry *entry)
3524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
3534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    entry->tv_sec = buf->sec;
3544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    entry->tv_nsec = buf->nsec;
3554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    entry->priority = buf->msg[0];
3564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    entry->pid = buf->pid;
3574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    entry->tid = buf->tid;
3584bf3c02e026077d14a4512c7c2f71937da3c2d50Kenny Root
3594bf3c02e026077d14a4512c7c2f71937da3c2d50Kenny Root    /*
3604bf3c02e026077d14a4512c7c2f71937da3c2d50Kenny Root     * format: <priority:1><tag:N>\0<message:N>\0
3614bf3c02e026077d14a4512c7c2f71937da3c2d50Kenny Root     *
3624bf3c02e026077d14a4512c7c2f71937da3c2d50Kenny Root     * tag str
3634bf3c02e026077d14a4512c7c2f71937da3c2d50Kenny Root     *   starts at msg+1
3644bf3c02e026077d14a4512c7c2f71937da3c2d50Kenny Root     * msg
3654bf3c02e026077d14a4512c7c2f71937da3c2d50Kenny Root     *   starts at msg+1+len(tag)+1
3664bf3c02e026077d14a4512c7c2f71937da3c2d50Kenny Root     */
3674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    entry->tag = buf->msg + 1;
3684bf3c02e026077d14a4512c7c2f71937da3c2d50Kenny Root    const size_t tag_len = strlen(entry->tag);
3694bf3c02e026077d14a4512c7c2f71937da3c2d50Kenny Root    const size_t preambleAndNullLen = tag_len + 3;
3704bf3c02e026077d14a4512c7c2f71937da3c2d50Kenny Root    if (buf->len <= preambleAndNullLen) {
3714bf3c02e026077d14a4512c7c2f71937da3c2d50Kenny Root        fprintf(stderr, "+++ LOG: entry corrupt or truncated\n");
3724bf3c02e026077d14a4512c7c2f71937da3c2d50Kenny Root        return -1;
3734bf3c02e026077d14a4512c7c2f71937da3c2d50Kenny Root    }
3744bf3c02e026077d14a4512c7c2f71937da3c2d50Kenny Root    entry->messageLen = buf->len - preambleAndNullLen;
3754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    entry->message = entry->tag + tag_len + 1;
3764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return 0;
3784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
3794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project/*
3814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * Extract a 4-byte value from a byte stream.
3824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project */
3834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic inline uint32_t get4LE(const uint8_t* src)
3844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
3854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
3864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
3874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project/*
3894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * Extract an 8-byte value from a byte stream.
3904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project */
3914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic inline uint64_t get8LE(const uint8_t* src)
3924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
3934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    uint32_t low, high;
3944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    low = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
3964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    high = src[4] | (src[5] << 8) | (src[6] << 16) | (src[7] << 24);
3974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return ((long long) high << 32) | (long long) low;
3984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
3994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project/*
4024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * Recursively convert binary log data to printable form.
4034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project *
4044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * This needs to be recursive because you can have lists of lists.
4054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project *
4064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * If we run out of room, we stop processing immediately.  It's important
4074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * for us to check for space on every output element to avoid producing
4084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * garbled output.
4094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project *
4104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * Returns 0 on success, 1 on buffer full, -1 on failure.
4114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project */
4124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic int android_log_printBinaryEvent(const unsigned char** pEventData,
4134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    size_t* pEventDataLen, char** pOutBuf, size_t* pOutBufLen)
4144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
4154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const unsigned char* eventData = *pEventData;
4164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    size_t eventDataLen = *pEventDataLen;
4174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char* outBuf = *pOutBuf;
4184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    size_t outBufLen = *pOutBufLen;
4194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    unsigned char type;
4204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    size_t outCount;
4214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int result = 0;
4224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (eventDataLen < 1)
4244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return -1;
4254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    type = *eventData++;
4264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    eventDataLen--;
4274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    //fprintf(stderr, "--- type=%d (rem len=%d)\n", type, eventDataLen);
4294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    switch (type) {
4314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case EVENT_TYPE_INT:
4324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* 32-bit signed int */
4334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        {
4344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int ival;
4354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (eventDataLen < 4)
4374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                return -1;
4384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ival = get4LE(eventData);
4394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            eventData += 4;
4404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            eventDataLen -= 4;
4414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            outCount = snprintf(outBuf, outBufLen, "%d", ival);
4434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (outCount < outBufLen) {
4444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                outBuf += outCount;
4454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                outBufLen -= outCount;
4464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            } else {
4474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                /* halt output */
4484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                goto no_room;
4494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
4504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
4514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        break;
4524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case EVENT_TYPE_LONG:
4534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* 64-bit signed long */
4544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        {
4554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            long long lval;
4564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (eventDataLen < 8)
4584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                return -1;
4594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            lval = get8LE(eventData);
4604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            eventData += 8;
4614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            eventDataLen -= 8;
4624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            outCount = snprintf(outBuf, outBufLen, "%lld", lval);
4644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (outCount < outBufLen) {
4654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                outBuf += outCount;
4664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                outBufLen -= outCount;
4674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            } else {
4684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                /* halt output */
4694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                goto no_room;
4704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
4714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
4724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        break;
4734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case EVENT_TYPE_STRING:
4744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* UTF-8 chars, not NULL-terminated */
4754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        {
4764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            unsigned int strLen;
4774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (eventDataLen < 4)
4794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                return -1;
4804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strLen = get4LE(eventData);
4814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            eventData += 4;
4824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            eventDataLen -= 4;
4834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (eventDataLen < strLen)
4854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                return -1;
4864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (strLen < outBufLen) {
4884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                memcpy(outBuf, eventData, strLen);
4894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                outBuf += strLen;
4904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                outBufLen -= strLen;
4914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            } else if (outBufLen > 0) {
4924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                /* copy what we can */
4934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                memcpy(outBuf, eventData, outBufLen);
4944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                outBuf += outBufLen;
4954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                outBufLen -= outBufLen;
4964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                goto no_room;
4974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
4984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            eventData += strLen;
4994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            eventDataLen -= strLen;
5004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            break;
5014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
5024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case EVENT_TYPE_LIST:
5034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* N items, all different types */
5044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        {
5054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            unsigned char count;
5064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int i;
5074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (eventDataLen < 1)
5094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                return -1;
5104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            count = *eventData++;
5124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            eventDataLen--;
5134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (outBufLen > 0) {
5154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                *outBuf++ = '[';
5164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                outBufLen--;
5174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            } else {
5184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                goto no_room;
5194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
5204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            for (i = 0; i < count; i++) {
5224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                result = android_log_printBinaryEvent(&eventData, &eventDataLen,
5234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                        &outBuf, &outBufLen);
5244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (result != 0)
5254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    goto bail;
5264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (i < count-1) {
5284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    if (outBufLen > 0) {
5294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                        *outBuf++ = ',';
5304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                        outBufLen--;
5314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    } else {
5324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                        goto no_room;
5334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    }
5344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                }
5354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
5364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (outBufLen > 0) {
5384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                *outBuf++ = ']';
5394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                outBufLen--;
5404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            } else {
5414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                goto no_room;
5424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
5434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
5444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        break;
5454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    default:
5464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fprintf(stderr, "Unknown binary event type %d\n", type);
5474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return -1;
5484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
5494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectbail:
5514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    *pEventData = eventData;
5524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    *pEventDataLen = eventDataLen;
5534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    *pOutBuf = outBuf;
5544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    *pOutBufLen = outBufLen;
5554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return result;
5564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectno_room:
5584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    result = 1;
5594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    goto bail;
5604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
5614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project/**
5634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * Convert a binary log entry to ASCII form.
5644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project *
5654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * For convenience we mimic the processLogBuffer API.  There is no
5664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * pre-defined output length for the binary data, since we're free to format
5674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * it however we choose, which means we can't really use a fixed-size buffer
5684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * here.
5694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project */
5704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectint android_log_processBinaryLogBuffer(struct logger_entry *buf,
5714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AndroidLogEntry *entry, const EventTagMap* map, char* messageBuf,
5724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int messageBufLen)
5734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
5744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    size_t inCount;
5754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    unsigned int tagIndex;
5764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const unsigned char* eventData;
5774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    entry->tv_sec = buf->sec;
5794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    entry->tv_nsec = buf->nsec;
5804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    entry->priority = ANDROID_LOG_INFO;
5814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    entry->pid = buf->pid;
5824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    entry->tid = buf->tid;
5834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /*
5854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project     * Pull the tag out.
5864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project     */
5874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    eventData = (const unsigned char*) buf->msg;
5884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    inCount = buf->len;
5894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (inCount < 4)
5904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return -1;
5914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    tagIndex = get4LE(eventData);
5924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    eventData += 4;
5934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    inCount -= 4;
5944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (map != NULL) {
5964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        entry->tag = android_lookupEventTag(map, tagIndex);
5974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
5984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        entry->tag = NULL;
5994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
6004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /*
6024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project     * If we don't have a map, or didn't find the tag number in the map,
6034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project     * stuff a generated tag value into the start of the output buffer and
6044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project     * shift the buffer pointers down.
6054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project     */
6064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (entry->tag == NULL) {
6074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int tagLen;
6084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        tagLen = snprintf(messageBuf, messageBufLen, "[%d]", tagIndex);
6104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        entry->tag = messageBuf;
6114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        messageBuf += tagLen+1;
6124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        messageBufLen -= tagLen+1;
6134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
6144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /*
6164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project     * Format the event log data into the buffer.
6174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project     */
6184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char* outBuf = messageBuf;
6194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    size_t outRemaining = messageBufLen-1;      /* leave one for nul byte */
6204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int result;
6214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    result = android_log_printBinaryEvent(&eventData, &inCount, &outBuf,
6224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                &outRemaining);
6234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (result < 0) {
6244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fprintf(stderr, "Binary log entry conversion failed\n");
6254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return -1;
6264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else if (result == 1) {
6274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (outBuf > messageBuf) {
6284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            /* leave an indicator */
6294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            *(outBuf-1) = '!';
6304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else {
6314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            /* no room to output anything at all */
6324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            *outBuf++ = '!';
6334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            outRemaining--;
6344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
6354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* pretend we ate all the data */
6364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        inCount = 0;
6374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
6384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* eat the silly terminating '\n' */
6404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (inCount == 1 && *eventData == '\n') {
6414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        eventData++;
6424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        inCount--;
6434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
6444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (inCount != 0) {
6464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fprintf(stderr,
6474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            "Warning: leftover binary log data (%d bytes)\n", inCount);
6484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
6494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /*
6514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project     * Terminate the buffer.  The NUL byte does not count as part of
6524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project     * entry->messageLen.
6534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project     */
6544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    *outBuf = '\0';
6554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    entry->messageLen = outBuf - messageBuf;
6564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    assert(entry->messageLen == (messageBufLen-1) - outRemaining);
6574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    entry->message = messageBuf;
6594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return 0;
6614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
6624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project/**
6644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * Formats a log message into a buffer
6654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project *
6664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * Uses defaultBuffer if it can, otherwise malloc()'s a new buffer
6674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * If return value != defaultBuffer, caller must call free()
6684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * Returns NULL on malloc error
6694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project */
6704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectchar *android_log_formatLogLine (
6724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AndroidLogFormat *p_format,
6734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char *defaultBuffer,
6744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    size_t defaultBufferSize,
6754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const AndroidLogEntry *entry,
6764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    size_t *p_outLength)
6774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
6784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#if defined(HAVE_LOCALTIME_R)
6794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct tm tmBuf;
6804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#endif
6814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct tm* ptm;
6824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char timeBuf[32];
6834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char headerBuf[128];
6844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char prefixBuf[128], suffixBuf[128];
6854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char priChar;
6864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int prefixSuffixIsHeaderFooter = 0;
6874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char * ret = NULL;
6884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    priChar = filterPriToChar(entry->priority);
6904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /*
6924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project     * Get the current date/time in pretty form
6934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project     *
6944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project     * It's often useful when examining a log with "less" to jump to
6954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project     * a specific point in the file by searching for the date/time stamp.
6964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project     * For this reason it's very annoying to have regexp meta characters
6974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project     * in the time stamp.  Don't use forward slashes, parenthesis,
6984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project     * brackets, asterisks, or other special chars here.
6994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project     */
7004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#if defined(HAVE_LOCALTIME_R)
7014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ptm = localtime_r(&(entry->tv_sec), &tmBuf);
7024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#else
7034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ptm = localtime(&(entry->tv_sec));
7044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#endif
7054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    //strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", ptm);
7064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    strftime(timeBuf, sizeof(timeBuf), "%m-%d %H:%M:%S", ptm);
7074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /*
7094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project     * Construct a buffer containing the log header and log message.
7104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project     */
7114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    size_t prefixLen, suffixLen;
7124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    switch (p_format->format) {
7144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        case FORMAT_TAG:
7154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
7164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                "%c/%-8s: ", priChar, entry->tag);
7174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strcpy(suffixBuf, "\n"); suffixLen = 1;
7184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            break;
7194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        case FORMAT_PROCESS:
7204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
7214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                "%c(%5d) ", priChar, entry->pid);
7224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            suffixLen = snprintf(suffixBuf, sizeof(suffixBuf),
7234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                "  (%s)\n", entry->tag);
7244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            break;
7254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        case FORMAT_THREAD:
7264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
7274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                "%c(%5d:%p) ", priChar, entry->pid, (void*)entry->tid);
7284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strcpy(suffixBuf, "\n");
7294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            suffixLen = 1;
7304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            break;
7314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        case FORMAT_RAW:
7324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            prefixBuf[0] = 0;
7334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            prefixLen = 0;
7344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strcpy(suffixBuf, "\n");
7354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            suffixLen = 1;
7364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            break;
7374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        case FORMAT_TIME:
7384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
7394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                "%s.%03ld %c/%-8s(%5d): ", timeBuf, entry->tv_nsec / 1000000,
7404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                priChar, entry->tag, entry->pid);
7414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strcpy(suffixBuf, "\n");
7424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            suffixLen = 1;
7434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            break;
7444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        case FORMAT_THREADTIME:
7454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
7464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                "%s.%03ld %5d %5d %c %-8s: ", timeBuf, entry->tv_nsec / 1000000,
7474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                (int)entry->pid, (int)entry->tid, priChar, entry->tag);
7484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strcpy(suffixBuf, "\n");
7494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            suffixLen = 1;
7504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            break;
7514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        case FORMAT_LONG:
7524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
7534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                "[ %s.%03ld %5d:%p %c/%-8s ]\n",
7544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                timeBuf, entry->tv_nsec / 1000000, entry->pid,
7554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                (void*)entry->tid, priChar, entry->tag);
7564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strcpy(suffixBuf, "\n\n");
7574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            suffixLen = 2;
7584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            prefixSuffixIsHeaderFooter = 1;
7594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            break;
7604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        case FORMAT_BRIEF:
7614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        default:
7624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
7634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                "%c/%-8s(%5d): ", priChar, entry->tag, entry->pid);
7644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strcpy(suffixBuf, "\n");
7654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            suffixLen = 1;
7664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            break;
7674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
768b45b5c9f227473050ef785d11e518e947c8754fbKeith Preston    /* snprintf has a weird return value.   It returns what would have been
769b45b5c9f227473050ef785d11e518e947c8754fbKeith Preston     * written given a large enough buffer.  In the case that the prefix is
770b45b5c9f227473050ef785d11e518e947c8754fbKeith Preston     * longer then our buffer(128), it messes up the calculations below
771b45b5c9f227473050ef785d11e518e947c8754fbKeith Preston     * possibly causing heap corruption.  To avoid this we double check and
772b45b5c9f227473050ef785d11e518e947c8754fbKeith Preston     * set the length at the maximum (size minus null byte)
773b45b5c9f227473050ef785d11e518e947c8754fbKeith Preston     */
774b45b5c9f227473050ef785d11e518e947c8754fbKeith Preston    if(prefixLen >= sizeof(prefixBuf))
775b45b5c9f227473050ef785d11e518e947c8754fbKeith Preston        prefixLen = sizeof(prefixBuf) - 1;
776b45b5c9f227473050ef785d11e518e947c8754fbKeith Preston    if(suffixLen >= sizeof(suffixBuf))
777b45b5c9f227473050ef785d11e518e947c8754fbKeith Preston        suffixLen = sizeof(suffixBuf) - 1;
7784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* the following code is tragically unreadable */
7804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    size_t numLines;
7824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    size_t i;
7834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char *p;
7844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    size_t bufferSize;
7854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const char *pm;
7864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (prefixSuffixIsHeaderFooter) {
7884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // we're just wrapping message with a header/footer
7894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        numLines = 1;
7904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
7914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        pm = entry->message;
7924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        numLines = 0;
7934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // The line-end finding here must match the line-end finding
7954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // in for ( ... numLines...) loop below
7964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        while (pm < (entry->message + entry->messageLen)) {
7974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (*pm++ == '\n') numLines++;
7984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
7994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // plus one line for anything not newline-terminated at the end
8004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (pm > entry->message && *(pm-1) != '\n') numLines++;
8014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
8024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // this is an upper bound--newlines in message may be counted
8044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // extraneously
8054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    bufferSize = (numLines * (prefixLen + suffixLen)) + entry->messageLen + 1;
8064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (defaultBufferSize >= bufferSize) {
8084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ret = defaultBuffer;
8094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
8104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ret = (char *)malloc(bufferSize);
8114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (ret == NULL) {
8134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            return ret;
8144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
8154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
8164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ret[0] = '\0';       /* to start strcat off */
8184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    p = ret;
8204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    pm = entry->message;
8214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (prefixSuffixIsHeaderFooter) {
8234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        strcat(p, prefixBuf);
8244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        p += prefixLen;
8254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        strncat(p, entry->message, entry->messageLen);
8264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        p += entry->messageLen;
8274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        strcat(p, suffixBuf);
8284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        p += suffixLen;
8294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
8304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        while(pm < (entry->message + entry->messageLen)) {
8314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            const char *lineStart;
8324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            size_t lineLen;
8334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            lineStart = pm;
8354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // Find the next end-of-line in message
8374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            while (pm < (entry->message + entry->messageLen)
8384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    && *pm != '\n') pm++;
8394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            lineLen = pm - lineStart;
8404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strcat(p, prefixBuf);
8424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            p += prefixLen;
8434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strncat(p, lineStart, lineLen);
8444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            p += lineLen;
8454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strcat(p, suffixBuf);
8464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            p += suffixLen;
8474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (*pm == '\n') pm++;
8494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
8504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
8514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (p_outLength != NULL) {
8534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        *p_outLength = p - ret;
8544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
8554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return ret;
8574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
8584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project/**
8604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * Either print or do not print log line, based on filter
8614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project *
8624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * Returns count bytes written
8634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project */
8644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
865e2bf2ea4d2846031edfc52b942ad53e5467243f6Joe Onoratoint android_log_printLogLine(
8664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AndroidLogFormat *p_format,
8674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int fd,
8684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const AndroidLogEntry *entry)
8694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
8704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int ret;
8714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char defaultBuffer[512];
8724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char *outBuffer = NULL;
8734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    size_t totalLen;
8744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    outBuffer = android_log_formatLogLine(p_format, defaultBuffer,
8764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            sizeof(defaultBuffer), entry, &totalLen);
8774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (!outBuffer)
8794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return -1;
8804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    do {
8824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ret = write(fd, outBuffer, totalLen);
8834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } while (ret < 0 && errno == EINTR);
8844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (ret < 0) {
8864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fprintf(stderr, "+++ LOG: write failed (errno=%d)\n", errno);
8874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ret = 0;
8884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        goto done;
8894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
8904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (((size_t)ret) < totalLen) {
8924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fprintf(stderr, "+++ LOG: write partial (%d of %d)\n", ret,
8934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                (int)totalLen);
8944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        goto done;
8954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
8964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectdone:
8984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (outBuffer != defaultBuffer) {
8994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        free(outBuffer);
9004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
9014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return ret;
9034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
9044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid logprint_run_tests()
9084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
9094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#if 0
9104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    fprintf(stderr, "tests disabled\n");
9124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#else
9144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int err;
9164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const char *tag;
9174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AndroidLogFormat *p_format;
9184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    p_format = android_log_format_new();
9204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    fprintf(stderr, "running tests\n");
9224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    tag = "random";
9244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    android_log_addFilterRule(p_format,"*:i");
9264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    assert (ANDROID_LOG_INFO == filterPriForTag(p_format, "random"));
9284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) == 0);
9294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    android_log_addFilterRule(p_format, "*");
9304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    assert (ANDROID_LOG_DEBUG == filterPriForTag(p_format, "random"));
9314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) > 0);
9324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    android_log_addFilterRule(p_format, "*:v");
9334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    assert (ANDROID_LOG_VERBOSE == filterPriForTag(p_format, "random"));
9344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) > 0);
9354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    android_log_addFilterRule(p_format, "*:i");
9364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    assert (ANDROID_LOG_INFO == filterPriForTag(p_format, "random"));
9374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) == 0);
9384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    android_log_addFilterRule(p_format, "random");
9404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    assert (ANDROID_LOG_VERBOSE == filterPriForTag(p_format, "random"));
9414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) > 0);
9424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    android_log_addFilterRule(p_format, "random:v");
9434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    assert (ANDROID_LOG_VERBOSE == filterPriForTag(p_format, "random"));
9444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) > 0);
9454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    android_log_addFilterRule(p_format, "random:d");
9464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    assert (ANDROID_LOG_DEBUG == filterPriForTag(p_format, "random"));
9474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) > 0);
9484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    android_log_addFilterRule(p_format, "random:w");
9494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    assert (ANDROID_LOG_WARN == filterPriForTag(p_format, "random"));
9504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) == 0);
9514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    android_log_addFilterRule(p_format, "crap:*");
9534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    assert (ANDROID_LOG_VERBOSE== filterPriForTag(p_format, "crap"));
9544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    assert(android_log_shouldPrintLine(p_format, "crap", ANDROID_LOG_VERBOSE) > 0);
9554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // invalid expression
9574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    err = android_log_addFilterRule(p_format, "random:z");
9584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    assert (err < 0);
9594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    assert (ANDROID_LOG_WARN == filterPriForTag(p_format, "random"));
9604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) == 0);
9614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // Issue #550946
9634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    err = android_log_addFilterString(p_format, " ");
9644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    assert(err == 0);
9654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    assert(ANDROID_LOG_WARN == filterPriForTag(p_format, "random"));
9664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // note trailing space
9684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    err = android_log_addFilterString(p_format, "*:s random:d ");
9694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    assert(err == 0);
9704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    assert(ANDROID_LOG_DEBUG == filterPriForTag(p_format, "random"));
9714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    err = android_log_addFilterString(p_format, "*:s random:z");
9734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    assert(err < 0);
9744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#if 0
9774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char *ret;
9784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char defaultBuffer[512];
9794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ret = android_log_formatLogLine(p_format,
9814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        defaultBuffer, sizeof(defaultBuffer), 0, ANDROID_LOG_ERROR, 123,
9824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        123, 123, "random", "nofile", strlen("Hello"), "Hello", NULL);
9834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#endif
9844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    fprintf(stderr, "tests complete\n");
9874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#endif
9884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
989