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 {
332ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  uint32_t tag;
342ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  unsigned pos; /* Read/write position into buffer */
352ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  unsigned count[ANDROID_MAX_LIST_NEST_DEPTH + 1]; /* Number of elements   */
362ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  unsigned list[ANDROID_MAX_LIST_NEST_DEPTH + 1];  /* pos for list counter */
372ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  unsigned list_nest_depth;
382ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  unsigned len; /* Length or raw buffer. */
392ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  bool overflow;
402ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  bool list_stop; /* next call decrement list_nest_depth and issue a stop */
412ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  enum {
422ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    kAndroidLoggerRead = 1,
432ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    kAndroidLoggerWrite = 2,
442ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  } read_write_flag;
452ed51d708eda64516ec79ac6397f690de38f0075Mark 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) {
492ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  size_t needed, i;
502ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  android_log_context_internal* context;
512ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
522ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context = calloc(1, sizeof(android_log_context_internal));
532ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (!context) {
542ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return NULL;
552ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
562ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context->tag = tag;
572ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context->read_write_flag = kAndroidLoggerWrite;
582ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  needed = sizeof(uint8_t) + sizeof(uint8_t);
592ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
602ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    context->overflow = true;
612ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
622ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /* Everything is a list */
632ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context->storage[context->pos + 0] = EVENT_TYPE_LIST;
642ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context->list[0] = context->pos + 1;
652ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context->pos += needed;
662ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
672ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return (android_log_context)context;
689dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn}
699dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
702ed51d708eda64516ec79ac6397f690de38f0075Mark SalyzynLIBLOG_ABI_PUBLIC android_log_context create_android_log_parser(const char* msg,
712ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn                                                                size_t len) {
722ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  android_log_context_internal* context;
732ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  size_t i;
742ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
752ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context = calloc(1, sizeof(android_log_context_internal));
762ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (!context) {
772ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return NULL;
782ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
792ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  len = (len <= MAX_EVENT_PAYLOAD) ? len : MAX_EVENT_PAYLOAD;
802ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context->len = len;
812ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  memcpy(context->storage, msg, len);
822ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context->read_write_flag = kAndroidLoggerRead;
832ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
842ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return (android_log_context)context;
859dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn}
869dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
872ed51d708eda64516ec79ac6397f690de38f0075Mark SalyzynLIBLOG_ABI_PUBLIC int android_log_destroy(android_log_context* ctx) {
882ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  android_log_context_internal* context;
892ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
902ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context = (android_log_context_internal*)*ctx;
912ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (!context) {
922ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return -EBADF;
932ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
942ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  memset(context, 0, sizeof(*context));
952ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  free(context);
962ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  *ctx = NULL;
972ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return 0;
989dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn}
999dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
1006d753faaf8694792433eb78c5c3572efd74a3d54Mark SalyzynLIBLOG_ABI_PUBLIC int android_log_write_list_begin(android_log_context ctx) {
1012ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  size_t needed;
1022ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  android_log_context_internal* context;
1032ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
1042ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context = (android_log_context_internal*)ctx;
1052ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
1062ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return -EBADF;
1072ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
1082ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (context->list_nest_depth > ANDROID_MAX_LIST_NEST_DEPTH) {
1092ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    context->overflow = true;
1102ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return -EOVERFLOW;
1112ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
1122ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  needed = sizeof(uint8_t) + sizeof(uint8_t);
1132ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
1142ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    context->overflow = true;
1152ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return -EIO;
1162ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
1172ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context->count[context->list_nest_depth]++;
1182ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context->list_nest_depth++;
1192ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (context->list_nest_depth > ANDROID_MAX_LIST_NEST_DEPTH) {
1202ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    context->overflow = true;
1212ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return -EOVERFLOW;
1222ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
1232ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (context->overflow) {
1242ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return -EIO;
1252ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
1262ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context->storage[context->pos + 0] = EVENT_TYPE_LIST;
1272ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context->storage[context->pos + 1] = 0;
1282ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context->list[context->list_nest_depth] = context->pos + 1;
1292ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context->count[context->list_nest_depth] = 0;
1302ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context->pos += needed;
1312ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return 0;
1329dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn}
1339dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
1342ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzynstatic inline void copy4LE(uint8_t* buf, uint32_t val) {
1352ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  buf[0] = val & 0xFF;
1362ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  buf[1] = (val >> 8) & 0xFF;
1372ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  buf[2] = (val >> 16) & 0xFF;
1382ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  buf[3] = (val >> 24) & 0xFF;
1399dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn}
1409dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
1416d753faaf8694792433eb78c5c3572efd74a3d54Mark SalyzynLIBLOG_ABI_PUBLIC int android_log_write_int32(android_log_context ctx,
1426d753faaf8694792433eb78c5c3572efd74a3d54Mark Salyzyn                                              int32_t value) {
1432ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  size_t needed;
1442ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  android_log_context_internal* context;
1452ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
1462ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context = (android_log_context_internal*)ctx;
1472ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
1482ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return -EBADF;
1492ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
1502ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (context->overflow) {
1512ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return -EIO;
1522ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
1532ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  needed = sizeof(uint8_t) + sizeof(value);
1542ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
1552ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    context->overflow = true;
1562ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return -EIO;
1572ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
1582ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context->count[context->list_nest_depth]++;
1592ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context->storage[context->pos + 0] = EVENT_TYPE_INT;
1602ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  copy4LE(&context->storage[context->pos + 1], value);
1612ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context->pos += needed;
1622ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return 0;
1639dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn}
1649dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
1652ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzynstatic inline void copy8LE(uint8_t* buf, uint64_t val) {
1662ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  buf[0] = val & 0xFF;
1672ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  buf[1] = (val >> 8) & 0xFF;
1682ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  buf[2] = (val >> 16) & 0xFF;
1692ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  buf[3] = (val >> 24) & 0xFF;
1702ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  buf[4] = (val >> 32) & 0xFF;
1712ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  buf[5] = (val >> 40) & 0xFF;
1722ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  buf[6] = (val >> 48) & 0xFF;
1732ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  buf[7] = (val >> 56) & 0xFF;
1749dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn}
1759dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
1766d753faaf8694792433eb78c5c3572efd74a3d54Mark SalyzynLIBLOG_ABI_PUBLIC int android_log_write_int64(android_log_context ctx,
1776d753faaf8694792433eb78c5c3572efd74a3d54Mark Salyzyn                                              int64_t value) {
1782ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  size_t needed;
1792ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  android_log_context_internal* context;
1802ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
1812ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context = (android_log_context_internal*)ctx;
1822ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
1832ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return -EBADF;
1842ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
1852ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (context->overflow) {
1862ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return -EIO;
1872ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
1882ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  needed = sizeof(uint8_t) + sizeof(value);
1892ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
1902ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    context->overflow = true;
1912ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return -EIO;
1922ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
1932ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context->count[context->list_nest_depth]++;
1942ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context->storage[context->pos + 0] = EVENT_TYPE_LONG;
1952ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  copy8LE(&context->storage[context->pos + 1], value);
1962ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context->pos += needed;
1972ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return 0;
1989dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn}
1999dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
2006d753faaf8694792433eb78c5c3572efd74a3d54Mark SalyzynLIBLOG_ABI_PUBLIC int android_log_write_string8_len(android_log_context ctx,
2012ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn                                                    const char* value,
2026d753faaf8694792433eb78c5c3572efd74a3d54Mark Salyzyn                                                    size_t maxlen) {
2032ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  size_t needed;
2042ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  ssize_t len;
2052ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  android_log_context_internal* context;
2062ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
2072ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context = (android_log_context_internal*)ctx;
2082ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
2092ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return -EBADF;
2102ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
2112ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (context->overflow) {
2122ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return -EIO;
2132ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
2142ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (!value) {
2152ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    value = "";
2162ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
2172ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  len = strnlen(value, maxlen);
2182ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  needed = sizeof(uint8_t) + sizeof(int32_t) + len;
2192ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
2202ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    /* Truncate string for delivery */
2212ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    len = MAX_EVENT_PAYLOAD - context->pos - 1 - sizeof(int32_t);
2222ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    if (len <= 0) {
2232ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      context->overflow = true;
2242ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      return -EIO;
2252ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    }
2262ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
2272ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context->count[context->list_nest_depth]++;
2282ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context->storage[context->pos + 0] = EVENT_TYPE_STRING;
2292ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  copy4LE(&context->storage[context->pos + 1], len);
2302ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (len) {
2312ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    memcpy(&context->storage[context->pos + 5], value, len);
2322ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
2332ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context->pos += needed;
2342ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return len;
2351d5afc9e08d0f5d6a79716d8f003cef97a01dd68Mark Salyzyn}
2361d5afc9e08d0f5d6a79716d8f003cef97a01dd68Mark Salyzyn
2376d753faaf8694792433eb78c5c3572efd74a3d54Mark SalyzynLIBLOG_ABI_PUBLIC int android_log_write_string8(android_log_context ctx,
2382ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn                                                const char* value) {
2392ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return android_log_write_string8_len(ctx, value, MAX_EVENT_PAYLOAD);
2409dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn}
2419dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
2426d753faaf8694792433eb78c5c3572efd74a3d54Mark SalyzynLIBLOG_ABI_PUBLIC int android_log_write_float32(android_log_context ctx,
2436d753faaf8694792433eb78c5c3572efd74a3d54Mark Salyzyn                                                float value) {
2442ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  size_t needed;
2452ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  uint32_t ivalue;
2462ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  android_log_context_internal* context;
2472ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
2482ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context = (android_log_context_internal*)ctx;
2492ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
2502ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return -EBADF;
2512ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
2522ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (context->overflow) {
2532ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return -EIO;
2542ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
2552ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  needed = sizeof(uint8_t) + sizeof(ivalue);
2562ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
2572ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    context->overflow = true;
2582ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return -EIO;
2592ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
2602ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  ivalue = *(uint32_t*)&value;
2612ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context->count[context->list_nest_depth]++;
2622ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context->storage[context->pos + 0] = EVENT_TYPE_FLOAT;
2632ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  copy4LE(&context->storage[context->pos + 1], ivalue);
2642ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context->pos += needed;
2652ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return 0;
2669dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn}
2679dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
2686d753faaf8694792433eb78c5c3572efd74a3d54Mark SalyzynLIBLOG_ABI_PUBLIC int android_log_write_list_end(android_log_context ctx) {
2692ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  android_log_context_internal* context;
2702ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
2712ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context = (android_log_context_internal*)ctx;
2722ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
2732ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return -EBADF;
2742ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
2752ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (context->list_nest_depth > ANDROID_MAX_LIST_NEST_DEPTH) {
2762ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    context->overflow = true;
2779dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    context->list_nest_depth--;
2782ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return -EOVERFLOW;
2792ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
2802ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (!context->list_nest_depth) {
2812ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    context->overflow = true;
2822ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return -EOVERFLOW;
2832ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
2842ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (context->list[context->list_nest_depth] <= 0) {
2852ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    context->list_nest_depth--;
2862ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    context->overflow = true;
2872ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return -EOVERFLOW;
2882ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
2892ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context->storage[context->list[context->list_nest_depth]] =
2902ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      context->count[context->list_nest_depth];
2912ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context->list_nest_depth--;
2922ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return 0;
2939dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn}
2949dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
2959dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn/*
2969dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn * Logs the list of elements to the event log.
2979dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn */
2986d753faaf8694792433eb78c5c3572efd74a3d54Mark SalyzynLIBLOG_ABI_PUBLIC int android_log_write_list(android_log_context ctx,
2996d753faaf8694792433eb78c5c3572efd74a3d54Mark Salyzyn                                             log_id_t id) {
3002ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  android_log_context_internal* context;
3012ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  const char* msg;
3022ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  ssize_t len;
3032ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
3041b1b6f50c78d88e3256a5e13559d92fbb6d1c8feStefan Lafon  if ((id != LOG_ID_EVENTS) && (id != LOG_ID_SECURITY) && (id != LOG_ID_STATS)) {
3052ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return -EINVAL;
3062ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
3072ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
3082ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context = (android_log_context_internal*)ctx;
3092ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
3102ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return -EBADF;
3112ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
3122ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (context->list_nest_depth) {
3132ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return -EIO;
3142ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
3152ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /* NB: if there was overflow, then log is truncated. Nothing reported */
3162ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context->storage[1] = context->count[0];
3172ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  len = context->len = context->pos;
3182ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  msg = (const char*)context->storage;
3192ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /* it's not a list */
3202ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (context->count[0] <= 1) {
3212ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    len -= sizeof(uint8_t) + sizeof(uint8_t);
3222ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    if (len < 0) {
3232ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      len = 0;
3242ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    }
3252ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    msg += sizeof(uint8_t) + sizeof(uint8_t);
3262ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
3272ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return (id == LOG_ID_EVENTS)
3282ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn             ? __android_log_bwrite(context->tag, msg, len)
3291b1b6f50c78d88e3256a5e13559d92fbb6d1c8feStefan Lafon             : ((id == LOG_ID_STATS)
3301b1b6f50c78d88e3256a5e13559d92fbb6d1c8feStefan Lafon                    ? __android_log_stats_bwrite(context->tag, msg, len)
3311b1b6f50c78d88e3256a5e13559d92fbb6d1c8feStefan Lafon                    : __android_log_security_bwrite(context->tag, msg, len));
3329dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn}
3339dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
3342ca4f49476a4e4e46dc7b47b2ce56ccaaadb9c8dMark SalyzynLIBLOG_ABI_PRIVATE int android_log_write_list_buffer(android_log_context ctx,
3352ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn                                                     const char** buffer) {
3362ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  android_log_context_internal* context;
3372ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  const char* msg;
3382ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  ssize_t len;
3392ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
3402ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context = (android_log_context_internal*)ctx;
3412ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
3422ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return -EBADF;
3432ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
3442ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (context->list_nest_depth) {
3452ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return -EIO;
3462ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
3472ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (buffer == NULL) {
3482ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return -EFAULT;
3492ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
3502ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /* NB: if there was overflow, then log is truncated. Nothing reported */
3512ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context->storage[1] = context->count[0];
3522ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  len = context->len = context->pos;
3532ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  msg = (const char*)context->storage;
3542ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /* it's not a list */
3552ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (context->count[0] <= 1) {
3562ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    len -= sizeof(uint8_t) + sizeof(uint8_t);
3572ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    if (len < 0) {
3582ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      len = 0;
3592ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    }
3602ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    msg += sizeof(uint8_t) + sizeof(uint8_t);
3612ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
3622ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  *buffer = msg;
3632ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return len;
3642ca4f49476a4e4e46dc7b47b2ce56ccaaadb9c8dMark Salyzyn}
3652ca4f49476a4e4e46dc7b47b2ce56ccaaadb9c8dMark Salyzyn
3669dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn/*
3679dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn * Extract a 4-byte value from a byte stream.
3689dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn */
3692ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzynstatic inline uint32_t get4LE(const uint8_t* src) {
3702ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
3719dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn}
3729dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
3739dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn/*
3749dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn * Extract an 8-byte value from a byte stream.
3759dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn */
3762ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzynstatic inline uint64_t get8LE(const uint8_t* src) {
3772ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  uint32_t low = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
3782ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  uint32_t high = src[4] | (src[5] << 8) | (src[6] << 16) | (src[7] << 24);
3792ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return ((uint64_t)high << 32) | (uint64_t)low;
3809dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn}
3819dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
3829dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn/*
3839dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn * Gets the next element. Parsing errors result in an EVENT_TYPE_UNKNOWN type.
3849dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn * If there is nothing to process, the complete field is set to non-zero. If
3859dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn * an EVENT_TYPE_UNKNOWN type is returned once, and the caller does not check
3869dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn * this and continues to call this function, the behavior is undefined
3879dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn * (although it won't crash).
3889dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn */
3899dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzynstatic android_log_list_element android_log_read_next_internal(
3902ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    android_log_context ctx, int peek) {
3912ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  android_log_list_element elem;
3922ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  unsigned pos;
3932ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  android_log_context_internal* context;
3942ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
3952ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  context = (android_log_context_internal*)ctx;
3962ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
3972ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  memset(&elem, 0, sizeof(elem));
3982ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
3992ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /* Nothing to parse from this context, so return complete. */
4002ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (!context || (kAndroidLoggerRead != context->read_write_flag) ||
4012ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      (context->list_nest_depth > ANDROID_MAX_LIST_NEST_DEPTH) ||
4022ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      (context->count[context->list_nest_depth] >=
4032ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn       (MAX_EVENT_PAYLOAD / (sizeof(uint8_t) + sizeof(uint8_t))))) {
4042ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    elem.type = EVENT_TYPE_UNKNOWN;
4052ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    if (context && (context->list_stop ||
4062ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn                    ((context->list_nest_depth <= ANDROID_MAX_LIST_NEST_DEPTH) &&
4072ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn                     !context->count[context->list_nest_depth]))) {
4082ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      elem.type = EVENT_TYPE_LIST_STOP;
4092ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    }
4102ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    elem.complete = true;
4112ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return elem;
4122ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
4132ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
4142ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /*
4152ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   * Use a different variable to update the position in case this
4162ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   * operation is a "peek".
4172ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   */
4182ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  pos = context->pos;
4192ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (context->list_stop) {
4202ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    elem.type = EVENT_TYPE_LIST_STOP;
4212ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    elem.complete = !context->count[0] &&
4222ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn                    (!context->list_nest_depth ||
4232ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn                     ((context->list_nest_depth == 1) && !context->count[1]));
4242ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    if (!peek) {
4252ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      /* Suck in superfluous stop */
4262ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      if (context->storage[pos] == EVENT_TYPE_LIST_STOP) {
4272ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        context->pos = pos + 1;
4282ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
4292ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      if (context->list_nest_depth) {
4302ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        --context->list_nest_depth;
4312ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        if (context->count[context->list_nest_depth]) {
4322ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn          context->list_stop = false;
4339dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        }
4342ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      } else {
4352ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        context->list_stop = false;
4362ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
4372ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    }
4382ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return elem;
4392ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
4402ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if ((pos + 1) > context->len) {
4412ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    elem.type = EVENT_TYPE_UNKNOWN;
4422ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    elem.complete = true;
4432ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return elem;
4442ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
4452ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
4462ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  elem.type = context->storage[pos++];
4472ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  switch ((int)elem.type) {
4489dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    case EVENT_TYPE_FLOAT:
4492ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    /* Rely on union to translate elem.data.int32 into elem.data.float32 */
4502ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    /* FALLTHRU */
4519dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    case EVENT_TYPE_INT:
4522ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      elem.len = sizeof(int32_t);
4532ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      if ((pos + elem.len) > context->len) {
4542ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        elem.type = EVENT_TYPE_UNKNOWN;
4559dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return elem;
4562ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
4572ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      elem.data.int32 = get4LE(&context->storage[pos]);
4582ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      /* common tangeable object suffix */
4592ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      pos += elem.len;
4602ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      elem.complete = !context->list_nest_depth && !context->count[0];
4612ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      if (!peek) {
4622ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        if (!context->count[context->list_nest_depth] ||
4632ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn            !--(context->count[context->list_nest_depth])) {
4642ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn          context->list_stop = true;
4652ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        }
4662ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        context->pos = pos;
4672ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
4682ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      return elem;
4699dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
4709dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    case EVENT_TYPE_LONG:
4712ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      elem.len = sizeof(int64_t);
4722ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      if ((pos + elem.len) > context->len) {
4732ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        elem.type = EVENT_TYPE_UNKNOWN;
4749dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return elem;
4752ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
4762ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      elem.data.int64 = get8LE(&context->storage[pos]);
4772ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      /* common tangeable object suffix */
4782ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      pos += elem.len;
4792ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      elem.complete = !context->list_nest_depth && !context->count[0];
4802ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      if (!peek) {
4812ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        if (!context->count[context->list_nest_depth] ||
4822ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn            !--(context->count[context->list_nest_depth])) {
4832ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn          context->list_stop = true;
4842ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        }
4852ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        context->pos = pos;
4862ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
4872ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      return elem;
4889dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
4899dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    case EVENT_TYPE_STRING:
4902ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      if ((pos + sizeof(int32_t)) > context->len) {
4912ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        elem.type = EVENT_TYPE_UNKNOWN;
4922ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        elem.complete = true;
4932ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        return elem;
4942ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
4952ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      elem.len = get4LE(&context->storage[pos]);
4962ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      pos += sizeof(int32_t);
4972ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      if ((pos + elem.len) > context->len) {
4982ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        elem.len = context->len - pos; /* truncate string */
4992ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        elem.complete = true;
5002ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        if (!elem.len) {
5012ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn          elem.type = EVENT_TYPE_UNKNOWN;
5022ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn          return elem;
5039dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        }
5042ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
5052ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      elem.data.string = (char*)&context->storage[pos];
5062ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      /* common tangeable object suffix */
5072ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      pos += elem.len;
5082ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      elem.complete = !context->list_nest_depth && !context->count[0];
5092ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      if (!peek) {
5102ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        if (!context->count[context->list_nest_depth] ||
5112ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn            !--(context->count[context->list_nest_depth])) {
5122ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn          context->list_stop = true;
5139dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        }
5142ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        context->pos = pos;
5152ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
5162ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      return elem;
5179dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
5189dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    case EVENT_TYPE_LIST:
5192ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      if ((pos + sizeof(uint8_t)) > context->len) {
5202ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        elem.type = EVENT_TYPE_UNKNOWN;
5212ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        elem.complete = true;
5222ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        return elem;
5232ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
5242ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      elem.complete = context->list_nest_depth >= ANDROID_MAX_LIST_NEST_DEPTH;
5252ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      if (peek) {
5269dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        return elem;
5272ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
5282ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      if (context->count[context->list_nest_depth]) {
5292ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        context->count[context->list_nest_depth]--;
5302ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
5312ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      context->list_stop = !context->storage[pos];
5322ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      context->list_nest_depth++;
5332ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      if (context->list_nest_depth <= ANDROID_MAX_LIST_NEST_DEPTH) {
5342ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        context->count[context->list_nest_depth] = context->storage[pos];
5352ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
5362ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      context->pos = pos + sizeof(uint8_t);
5372ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      return elem;
5389dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
5399dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    case EVENT_TYPE_LIST_STOP: /* Suprise Newline terminates lists. */
5402ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      if (!peek) {
5412ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        context->pos = pos;
5422ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
5432ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      elem.type = EVENT_TYPE_UNKNOWN;
5442ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      elem.complete = !context->list_nest_depth;
5452ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      if (context->list_nest_depth > 0) {
5462ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        elem.type = EVENT_TYPE_LIST_STOP;
5479dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        if (!peek) {
5482ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn          context->list_nest_depth--;
5499dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn        }
5502ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
5512ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      return elem;
5529dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
5539dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn    default:
5542ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      elem.type = EVENT_TYPE_UNKNOWN;
5552ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      return elem;
5562ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
5579dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn}
5589dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
5592ed51d708eda64516ec79ac6397f690de38f0075Mark SalyzynLIBLOG_ABI_PUBLIC android_log_list_element
5602ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzynandroid_log_read_next(android_log_context ctx) {
5612ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return android_log_read_next_internal(ctx, 0);
5629dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn}
5639dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn
5642ed51d708eda64516ec79ac6397f690de38f0075Mark SalyzynLIBLOG_ABI_PUBLIC android_log_list_element
5652ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzynandroid_log_peek_next(android_log_context ctx) {
5662ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return android_log_read_next_internal(ctx, 1);
5679dd6510dd09f40973b8834c5cad1217ce1c3011dMark Salyzyn}
568