log_event_list.c revision 472245d9625b8f0c52737aa8753524facfa211db
19dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn/*
29dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn * Copyright (C) 2016 The Android Open Source Project
39dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn *
49dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn * Licensed under the Apache License, Version 2.0 (the "License");
59dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn * you may not use this file except in compliance with the License.
69dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn * You may obtain a copy of the License at
79dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn *
89dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn *      http://www.apache.org/licenses/LICENSE-2.0
99dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn *
109dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn * Unless required by applicable law or agreed to in writing, software
119dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn * distributed under the License is distributed on an "AS IS" BASIS,
129dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn * See the License for the specific language governing permissions and
149dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn * limitations under the License.
159dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn */
169dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
179dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn#include <errno.h>
189dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn#include <inttypes.h>
199dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn#include <stdbool.h>
209dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn#include <stdint.h>
219dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn#include <stdio.h>
229dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn#include <stdlib.h>
239dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn#include <string.h>
249dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
25472245d9625b8f0c52737aa8753524facfa211dbMark Salyzyn#include <log/log_event_list.h>
266debf985aa5127b43f1f79a010dc000f733793b8Mark Salyzyn#include <private/android_logger.h>
279dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
28facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn#include "log_portability.h"
296d753faaf8694792433eb78c5c3572efd74a3d54Mark Salyzyn
309dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn#define MAX_EVENT_PAYLOAD (LOGGER_ENTRY_MAX_PAYLOAD - sizeof(int32_t))
319dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
329dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyntypedef struct {
339dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    uint32_t tag;
349dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    unsigned pos; /* Read/write position into buffer */
359dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    unsigned count[ANDROID_MAX_LIST_NEST_DEPTH + 1]; /* Number of elements   */
369dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    unsigned list[ANDROID_MAX_LIST_NEST_DEPTH + 1];  /* pos for list counter */
379dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    unsigned list_nest_depth;
389dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    unsigned len; /* Length or raw buffer. */
399dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    bool overflow;
409dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    bool list_stop; /* next call decrement list_nest_depth and issue a stop */
419dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    enum {
429dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        kAndroidLoggerRead = 1,
439dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        kAndroidLoggerWrite = 2,
449dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    } read_write_flag;
459dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    uint8_t storage[LOGGER_ENTRY_MAX_PAYLOAD];
469dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn} android_log_context_internal;
479dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
486d753faaf8694792433eb78c5c3572efd74a3d54Mark SalyzynLIBLOG_ABI_PUBLIC android_log_context create_android_logger(uint32_t tag) {
499dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    size_t needed, i;
509dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    android_log_context_internal *context;
519dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
529dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context = calloc(1, sizeof(android_log_context_internal));
539dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    if (!context) {
549dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return NULL;
559dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    }
569dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context->tag = tag;
579dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context->read_write_flag = kAndroidLoggerWrite;
589dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    needed = sizeof(uint8_t) + sizeof(uint8_t);
599dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
609dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        context->overflow = true;
619dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    }
629dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    /* Everything is a list */
639dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context->storage[context->pos + 0] = EVENT_TYPE_LIST;
649dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context->list[0] = context->pos + 1;
659dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context->pos += needed;
669dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
679dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    return (android_log_context)context;
689dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn}
699dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
706d753faaf8694792433eb78c5c3572efd74a3d54Mark SalyzynLIBLOG_ABI_PUBLIC android_log_context create_android_log_parser(
716d753faaf8694792433eb78c5c3572efd74a3d54Mark Salyzyn        const char *msg,
726d753faaf8694792433eb78c5c3572efd74a3d54Mark Salyzyn        size_t len) {
739dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    android_log_context_internal *context;
749dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    size_t i;
759dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
769dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context = calloc(1, sizeof(android_log_context_internal));
779dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    if (!context) {
789dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return NULL;
799dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    }
809dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    len = (len <= MAX_EVENT_PAYLOAD) ? len : MAX_EVENT_PAYLOAD;
819dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context->len = len;
829dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    memcpy(context->storage, msg, len);
839dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context->read_write_flag = kAndroidLoggerRead;
849dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
859dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    return (android_log_context)context;
869dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn}
879dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
886d753faaf8694792433eb78c5c3572efd74a3d54Mark SalyzynLIBLOG_ABI_PUBLIC int android_log_destroy(android_log_context *ctx) {
899dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    android_log_context_internal *context;
909dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
919dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context = (android_log_context_internal *)*ctx;
929dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    if (!context) {
939dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return -EBADF;
949dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    }
959dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    memset(context, 0, sizeof(*context));
969dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    free(context);
979dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    *ctx = NULL;
989dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    return 0;
999dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn}
1009dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
1016d753faaf8694792433eb78c5c3572efd74a3d54Mark SalyzynLIBLOG_ABI_PUBLIC int android_log_write_list_begin(android_log_context ctx) {
1029dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    size_t needed;
1039dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    android_log_context_internal *context;
1049dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
1059dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context = (android_log_context_internal *)ctx;
1069dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    if (!context ||
1079dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            (kAndroidLoggerWrite != context->read_write_flag)) {
1089dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return -EBADF;
1099dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    }
1109dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    if (context->list_nest_depth > ANDROID_MAX_LIST_NEST_DEPTH) {
1119dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        context->overflow = true;
1129dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return -EOVERFLOW;
1139dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    }
1149dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    needed = sizeof(uint8_t) + sizeof(uint8_t);
1159dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
1169dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        context->overflow = true;
1179dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return -EIO;
1189dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    }
1199dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context->count[context->list_nest_depth]++;
1209dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context->list_nest_depth++;
1219dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    if (context->list_nest_depth > ANDROID_MAX_LIST_NEST_DEPTH) {
1229dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        context->overflow = true;
1239dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return -EOVERFLOW;
1249dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    }
1259dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    if (context->overflow) {
1269dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return -EIO;
1279dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    }
1289dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context->storage[context->pos + 0] = EVENT_TYPE_LIST;
1299dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context->storage[context->pos + 1] = 0;
1309dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context->list[context->list_nest_depth] = context->pos + 1;
1319dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context->count[context->list_nest_depth] = 0;
1329dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context->pos += needed;
1339dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    return 0;
1349dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn}
1359dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
1369dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzynstatic inline void copy4LE(uint8_t *buf, uint32_t val)
1379dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn{
1389dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    buf[0] = val & 0xFF;
1399dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    buf[1] = (val >> 8) & 0xFF;
1409dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    buf[2] = (val >> 16) & 0xFF;
1419dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    buf[3] = (val >> 24) & 0xFF;
1429dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn}
1439dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
1446d753faaf8694792433eb78c5c3572efd74a3d54Mark SalyzynLIBLOG_ABI_PUBLIC int android_log_write_int32(android_log_context ctx,
1456d753faaf8694792433eb78c5c3572efd74a3d54Mark Salyzyn                                              int32_t value) {
1469dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    size_t needed;
1479dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    android_log_context_internal *context;
1489dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
1499dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context = (android_log_context_internal *)ctx;
1509dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
1519dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return -EBADF;
1529dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    }
1539dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    if (context->overflow) {
1549dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return -EIO;
1559dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    }
1569dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    needed = sizeof(uint8_t) + sizeof(value);
1579dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
1589dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        context->overflow = true;
1599dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return -EIO;
1609dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    }
1619dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context->count[context->list_nest_depth]++;
1629dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context->storage[context->pos + 0] = EVENT_TYPE_INT;
1639dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    copy4LE(&context->storage[context->pos + 1], value);
1649dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context->pos += needed;
1659dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    return 0;
1669dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn}
1679dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
1689dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzynstatic inline void copy8LE(uint8_t *buf, uint64_t val)
1699dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn{
1709dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    buf[0] = val & 0xFF;
1719dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    buf[1] = (val >> 8) & 0xFF;
1729dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    buf[2] = (val >> 16) & 0xFF;
1739dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    buf[3] = (val >> 24) & 0xFF;
1749dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    buf[4] = (val >> 32) & 0xFF;
1759dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    buf[5] = (val >> 40) & 0xFF;
1769dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    buf[6] = (val >> 48) & 0xFF;
1779dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    buf[7] = (val >> 56) & 0xFF;
1789dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn}
1799dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
1806d753faaf8694792433eb78c5c3572efd74a3d54Mark SalyzynLIBLOG_ABI_PUBLIC int android_log_write_int64(android_log_context ctx,
1816d753faaf8694792433eb78c5c3572efd74a3d54Mark Salyzyn                                              int64_t value) {
1829dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    size_t needed;
1839dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    android_log_context_internal *context;
1849dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
1859dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context = (android_log_context_internal *)ctx;
1869dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
1879dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return -EBADF;
1889dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    }
1899dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    if (context->overflow) {
1909dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return -EIO;
1919dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    }
1929dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    needed = sizeof(uint8_t) + sizeof(value);
1939dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
1949dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        context->overflow = true;
1959dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return -EIO;
1969dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    }
1979dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context->count[context->list_nest_depth]++;
1989dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context->storage[context->pos + 0] = EVENT_TYPE_LONG;
1999dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    copy8LE(&context->storage[context->pos + 1], value);
2009dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context->pos += needed;
2019dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    return 0;
2029dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn}
2039dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
2046d753faaf8694792433eb78c5c3572efd74a3d54Mark SalyzynLIBLOG_ABI_PUBLIC int android_log_write_string8_len(android_log_context ctx,
2056d753faaf8694792433eb78c5c3572efd74a3d54Mark Salyzyn                                                    const char *value,
2066d753faaf8694792433eb78c5c3572efd74a3d54Mark Salyzyn                                                    size_t maxlen) {
2079dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    size_t needed;
2081d5afc9e08d0f5d6a79716d8f003cef97a01dd68Mark Salyzyn    ssize_t len;
2099dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    android_log_context_internal *context;
2109dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
2119dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context = (android_log_context_internal *)ctx;
2129dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
2139dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return -EBADF;
2149dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    }
2159dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    if (context->overflow) {
2169dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return -EIO;
2179dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    }
2189dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    if (!value) {
2191d5afc9e08d0f5d6a79716d8f003cef97a01dd68Mark Salyzyn        value = "";
2209dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    }
2211d5afc9e08d0f5d6a79716d8f003cef97a01dd68Mark Salyzyn    len = strnlen(value, maxlen);
2221d5afc9e08d0f5d6a79716d8f003cef97a01dd68Mark Salyzyn    needed = sizeof(uint8_t) + sizeof(int32_t) + len;
2239dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
2249dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        /* Truncate string for delivery */
2251d5afc9e08d0f5d6a79716d8f003cef97a01dd68Mark Salyzyn        len = MAX_EVENT_PAYLOAD - context->pos - 1 - sizeof(int32_t);
2269dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        if (len <= 0) {
2279dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            context->overflow = true;
2289dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            return -EIO;
2299dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        }
2309dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    }
2319dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context->count[context->list_nest_depth]++;
2329dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context->storage[context->pos + 0] = EVENT_TYPE_STRING;
2339dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    copy4LE(&context->storage[context->pos + 1], len);
2341d5afc9e08d0f5d6a79716d8f003cef97a01dd68Mark Salyzyn    if (len) {
2351d5afc9e08d0f5d6a79716d8f003cef97a01dd68Mark Salyzyn        memcpy(&context->storage[context->pos + 5], value, len);
2361d5afc9e08d0f5d6a79716d8f003cef97a01dd68Mark Salyzyn    }
2379dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context->pos += needed;
2381d5afc9e08d0f5d6a79716d8f003cef97a01dd68Mark Salyzyn    return len;
2391d5afc9e08d0f5d6a79716d8f003cef97a01dd68Mark Salyzyn}
2401d5afc9e08d0f5d6a79716d8f003cef97a01dd68Mark Salyzyn
2416d753faaf8694792433eb78c5c3572efd74a3d54Mark SalyzynLIBLOG_ABI_PUBLIC int android_log_write_string8(android_log_context ctx,
2426d753faaf8694792433eb78c5c3572efd74a3d54Mark Salyzyn                                                const char *value) {
2431d5afc9e08d0f5d6a79716d8f003cef97a01dd68Mark Salyzyn    return android_log_write_string8_len(ctx, value, MAX_EVENT_PAYLOAD);
2449dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn}
2459dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
2466d753faaf8694792433eb78c5c3572efd74a3d54Mark SalyzynLIBLOG_ABI_PUBLIC int android_log_write_float32(android_log_context ctx,
2476d753faaf8694792433eb78c5c3572efd74a3d54Mark Salyzyn                                                float value) {
2489dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    size_t needed;
2499dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    uint32_t ivalue;
2509dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    android_log_context_internal *context;
2519dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
2529dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context = (android_log_context_internal *)ctx;
2539dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
2549dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return -EBADF;
2559dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    }
2569dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    if (context->overflow) {
2579dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return -EIO;
2589dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    }
2599dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    needed = sizeof(uint8_t) + sizeof(ivalue);
2609dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
2619dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        context->overflow = true;
2629dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return -EIO;
2639dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    }
2649dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    ivalue = *(uint32_t *)&value;
2659dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context->count[context->list_nest_depth]++;
2669dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context->storage[context->pos + 0] = EVENT_TYPE_FLOAT;
2679dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    copy4LE(&context->storage[context->pos + 1], ivalue);
2689dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context->pos += needed;
2699dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    return 0;
2709dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn}
2719dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
2726d753faaf8694792433eb78c5c3572efd74a3d54Mark SalyzynLIBLOG_ABI_PUBLIC int android_log_write_list_end(android_log_context ctx) {
2739dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    android_log_context_internal *context;
2749dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
2759dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context = (android_log_context_internal *)ctx;
2769dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
2779dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return -EBADF;
2789dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    }
2799dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    if (context->list_nest_depth > ANDROID_MAX_LIST_NEST_DEPTH) {
2809dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        context->overflow = true;
2819dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        context->list_nest_depth--;
2829dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return -EOVERFLOW;
2839dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    }
2849dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    if (!context->list_nest_depth) {
2859dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        context->overflow = true;
2869dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return -EOVERFLOW;
2879dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    }
2889dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    if (context->list[context->list_nest_depth] <= 0) {
2899dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        context->list_nest_depth--;
2909dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        context->overflow = true;
2919dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return -EOVERFLOW;
2929dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    }
2939dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context->storage[context->list[context->list_nest_depth]] =
2949dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        context->count[context->list_nest_depth];
2959dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context->list_nest_depth--;
2969dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    return 0;
2979dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn}
2989dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
2999dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn/*
3009dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn * Logs the list of elements to the event log.
3019dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn */
3026d753faaf8694792433eb78c5c3572efd74a3d54Mark SalyzynLIBLOG_ABI_PUBLIC int android_log_write_list(android_log_context ctx,
3036d753faaf8694792433eb78c5c3572efd74a3d54Mark Salyzyn                                             log_id_t id) {
3049dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    android_log_context_internal *context;
3059dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    const char *msg;
3069dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    ssize_t len;
3079dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
3089dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    if ((id != LOG_ID_EVENTS) && (id != LOG_ID_SECURITY)) {
3099dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return -EINVAL;
3109dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    }
3119dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
3129dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context = (android_log_context_internal *)ctx;
3139dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
3149dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return -EBADF;
3159dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    }
3169dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    if (context->list_nest_depth) {
3179dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return -EIO;
3189dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    }
3199dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    /* NB: if there was overflow, then log is truncated. Nothing reported */
3209dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context->storage[1] = context->count[0];
3219dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    len = context->len = context->pos;
3229dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    msg = (const char *)context->storage;
3239dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    /* it'snot a list */
3249dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    if (context->count[0] <= 1) {
3259dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        len -= sizeof(uint8_t) + sizeof(uint8_t);
3269dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        if (len < 0) {
3279dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            len = 0;
3289dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        }
3299dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        msg += sizeof(uint8_t) + sizeof(uint8_t);
3309dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    }
3319dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    return (id == LOG_ID_EVENTS) ?
3329dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        __android_log_bwrite(context->tag, msg, len) :
3339dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        __android_log_security_bwrite(context->tag, msg, len);
3349dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn}
3359dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
3369dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn/*
3379dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn * Extract a 4-byte value from a byte stream.
3389dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn */
3399dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzynstatic inline uint32_t get4LE(const uint8_t* src)
3409dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn{
3419dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
3429dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn}
3439dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
3449dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn/*
3459dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn * Extract an 8-byte value from a byte stream.
3469dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn */
3479dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzynstatic inline uint64_t get8LE(const uint8_t* src)
3489dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn{
3499dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    uint32_t low = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
3509dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    uint32_t high = src[4] | (src[5] << 8) | (src[6] << 16) | (src[7] << 24);
3519dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    return ((uint64_t) high << 32) | (uint64_t) low;
3529dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn}
3539dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
3549dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn/*
3559dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn * Gets the next element. Parsing errors result in an EVENT_TYPE_UNKNOWN type.
3569dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn * If there is nothing to process, the complete field is set to non-zero. If
3579dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn * an EVENT_TYPE_UNKNOWN type is returned once, and the caller does not check
3589dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn * this and continues to call this function, the behavior is undefined
3599dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn * (although it won't crash).
3609dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn */
3619dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzynstatic android_log_list_element android_log_read_next_internal(
3629dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        android_log_context ctx, int peek) {
3639dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    android_log_list_element elem;
3649dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    unsigned pos;
3659dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    android_log_context_internal *context;
3669dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
3679dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context = (android_log_context_internal *)ctx;
3689dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
3699dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    memset(&elem, 0, sizeof(elem));
3709dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
3719dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    /* Nothing to parse from this context, so return complete. */
3729dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    if (!context || (kAndroidLoggerRead != context->read_write_flag) ||
3739dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            (context->list_nest_depth > ANDROID_MAX_LIST_NEST_DEPTH) ||
3749dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            (context->count[context->list_nest_depth] >=
3759dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn                (MAX_EVENT_PAYLOAD / (sizeof(uint8_t) + sizeof(uint8_t))))) {
3769dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        elem.type = EVENT_TYPE_UNKNOWN;
3779dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        if (context &&
3789dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn                (context->list_stop ||
3799dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn                ((context->list_nest_depth <= ANDROID_MAX_LIST_NEST_DEPTH) &&
3809dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn                    !context->count[context->list_nest_depth]))) {
3819dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            elem.type = EVENT_TYPE_LIST_STOP;
3829dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        }
3839dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        elem.complete = true;
3849dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return elem;
3859dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    }
3869dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
3879dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    /*
3889dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn     * Use a different variable to update the position in case this
3899dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn     * operation is a "peek".
3909dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn     */
3919dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    pos = context->pos;
3929dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    if (context->list_stop) {
3939dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        elem.type = EVENT_TYPE_LIST_STOP;
3949dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        elem.complete = !context->count[0] && (!context->list_nest_depth ||
3959dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            ((context->list_nest_depth == 1) && !context->count[1]));
3969dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        if (!peek) {
3979dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            /* Suck in superfluous stop */
3989dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            if (context->storage[pos] == EVENT_TYPE_LIST_STOP) {
3999dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn                context->pos = pos + 1;
4009dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            }
4019dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            if (context->list_nest_depth) {
4029dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn                --context->list_nest_depth;
4039dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn                if (context->count[context->list_nest_depth]) {
4049dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn                    context->list_stop = false;
4059dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn                }
4069dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            } else {
4079dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn                context->list_stop = false;
4089dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            }
4099dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        }
4109dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return elem;
4119dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    }
4129dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    if ((pos + 1) > context->len) {
4139dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        elem.type = EVENT_TYPE_UNKNOWN;
4149dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        elem.complete = true;
4159dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return elem;
4169dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    }
4179dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
4189dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    elem.type = context->storage[pos++];
4199dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    switch ((int)elem.type) {
4209dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    case EVENT_TYPE_FLOAT:
4219dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        /* Rely on union to translate elem.data.int32 into elem.data.float32 */
4229dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        /* FALLTHRU */
4239dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    case EVENT_TYPE_INT:
4249dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        elem.len = sizeof(int32_t);
4259dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        if ((pos + elem.len) > context->len) {
4269dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            elem.type = EVENT_TYPE_UNKNOWN;
4279dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            return elem;
4289dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        }
4299dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        elem.data.int32 = get4LE(&context->storage[pos]);
4309dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        /* common tangeable object suffix */
4319dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        pos += elem.len;
4329dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        elem.complete = !context->list_nest_depth && !context->count[0];
4339dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        if (!peek) {
4349dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            if (!context->count[context->list_nest_depth] ||
4359dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn                    !--(context->count[context->list_nest_depth])) {
4369dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn                context->list_stop = true;
4379dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            }
4389dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            context->pos = pos;
4399dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        }
4409dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return elem;
4419dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
4429dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    case EVENT_TYPE_LONG:
4439dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        elem.len = sizeof(int64_t);
4449dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        if ((pos + elem.len) > context->len) {
4459dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            elem.type = EVENT_TYPE_UNKNOWN;
4469dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            return elem;
4479dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        }
4489dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        elem.data.int64 = get8LE(&context->storage[pos]);
4499dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        /* common tangeable object suffix */
4509dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        pos += elem.len;
4519dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        elem.complete = !context->list_nest_depth && !context->count[0];
4529dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        if (!peek) {
4539dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            if (!context->count[context->list_nest_depth] ||
4549dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn                    !--(context->count[context->list_nest_depth])) {
4559dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn                context->list_stop = true;
4569dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            }
4579dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            context->pos = pos;
4589dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        }
4599dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return elem;
4609dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
4619dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    case EVENT_TYPE_STRING:
4629dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        if ((pos + sizeof(int32_t)) > context->len) {
4639dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            elem.type = EVENT_TYPE_UNKNOWN;
4649dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            elem.complete = true;
4659dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            return elem;
4669dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        }
4679dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        elem.len = get4LE(&context->storage[pos]);
4689dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        pos += sizeof(int32_t);
4699dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        if ((pos + elem.len) > context->len) {
4709dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            elem.len = context->len - pos; /* truncate string */
4719dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            elem.complete = true;
4729dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            if (!elem.len) {
4739dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn                elem.type = EVENT_TYPE_UNKNOWN;
4749dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn                return elem;
4759dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            }
4769dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        }
4779dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        elem.data.string = (char *)&context->storage[pos];
4789dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        /* common tangeable object suffix */
4799dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        pos += elem.len;
4809dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        elem.complete = !context->list_nest_depth && !context->count[0];
4819dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        if (!peek) {
4829dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            if (!context->count[context->list_nest_depth] ||
4839dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn                    !--(context->count[context->list_nest_depth])) {
4849dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn                context->list_stop = true;
4859dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            }
4869dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            context->pos = pos;
4879dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        }
4889dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return elem;
4899dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
4909dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    case EVENT_TYPE_LIST:
4919dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        if ((pos + sizeof(uint8_t)) > context->len) {
4929dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            elem.type = EVENT_TYPE_UNKNOWN;
4939dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            elem.complete = true;
4949dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            return elem;
4959dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        }
4969dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        elem.complete = context->list_nest_depth >= ANDROID_MAX_LIST_NEST_DEPTH;
4979dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        if (peek) {
4989dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            return elem;
4999dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        }
5009dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        if (context->count[context->list_nest_depth]) {
5019dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            context->count[context->list_nest_depth]--;
5029dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        }
5039dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        context->list_stop = !context->storage[pos];
5049dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        context->list_nest_depth++;
5059dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        if (context->list_nest_depth <= ANDROID_MAX_LIST_NEST_DEPTH) {
5069dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            context->count[context->list_nest_depth] = context->storage[pos];
5079dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        }
5089dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        context->pos = pos + sizeof(uint8_t);
5099dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return elem;
5109dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
5119dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    case EVENT_TYPE_LIST_STOP: /* Suprise Newline terminates lists. */
5129dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        if (!peek) {
5139dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            context->pos = pos;
5149dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        }
5159dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        elem.type = EVENT_TYPE_UNKNOWN;
5169dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        elem.complete = !context->list_nest_depth;
5179dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        if (context->list_nest_depth > 0) {
5189dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            elem.type = EVENT_TYPE_LIST_STOP;
5199dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            if (!peek) {
5209dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn                context->list_nest_depth--;
5219dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn            }
5229dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        }
5239dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return elem;
5249dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
5259dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    default:
5269dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        elem.type = EVENT_TYPE_UNKNOWN;
5279dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return elem;
5289dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    }
5299dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn}
5309dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
5316d753faaf8694792433eb78c5c3572efd74a3d54Mark SalyzynLIBLOG_ABI_PUBLIC android_log_list_element android_log_read_next(
5326d753faaf8694792433eb78c5c3572efd74a3d54Mark Salyzyn        android_log_context ctx) {
5339dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    return android_log_read_next_internal(ctx, 0);
5349dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn}
5359dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
5366d753faaf8694792433eb78c5c3572efd74a3d54Mark SalyzynLIBLOG_ABI_PUBLIC android_log_list_element android_log_peek_next(
5376d753faaf8694792433eb78c5c3572efd74a3d54Mark Salyzyn        android_log_context ctx) {
5389dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    return android_log_read_next_internal(ctx, 1);
5399dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn}
540