| /* |
| * Copyright (C) 2005-2016 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #pragma once |
| |
| #include <errno.h> |
| #include <stdint.h> |
| |
| #ifdef __cplusplus |
| #include <string> |
| #endif |
| |
| #include <log/log.h> |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| /* For manipulating lists of events. */ |
| |
| #define ANDROID_MAX_LIST_NEST_DEPTH 8 |
| |
| /* |
| * The opaque context used to manipulate lists of events. |
| */ |
| #ifndef __android_log_context_defined |
| #define __android_log_context_defined |
| typedef struct android_log_context_internal* android_log_context; |
| #endif |
| |
| /* |
| * Elements returned when reading a list of events. |
| */ |
| #ifndef __android_log_list_element_defined |
| #define __android_log_list_element_defined |
| typedef struct { |
| AndroidEventLogType type; |
| uint16_t complete; |
| uint16_t len; |
| union { |
| int32_t int32; |
| int64_t int64; |
| char* string; |
| float float32; |
| } data; |
| } android_log_list_element; |
| #endif |
| |
| /* |
| * Creates a context associated with an event tag to write elements to |
| * the list of events. |
| */ |
| android_log_context create_android_logger(uint32_t tag); |
| |
| /* All lists must be braced by a begin and end call */ |
| /* |
| * NB: If the first level braces are missing when specifying multiple |
| * elements, we will manufacturer a list to embrace it for your API |
| * convenience. For a single element, it will remain solitary. |
| */ |
| int android_log_write_list_begin(android_log_context ctx); |
| int android_log_write_list_end(android_log_context ctx); |
| |
| int android_log_write_int32(android_log_context ctx, int32_t value); |
| int android_log_write_int64(android_log_context ctx, int64_t value); |
| int android_log_write_string8(android_log_context ctx, const char* value); |
| int android_log_write_string8_len(android_log_context ctx, const char* value, |
| size_t maxlen); |
| int android_log_write_float32(android_log_context ctx, float value); |
| |
| /* Submit the composed list context to the specified logger id */ |
| /* NB: LOG_ID_EVENTS and LOG_ID_SECURITY only valid binary buffers */ |
| int android_log_write_list(android_log_context ctx, log_id_t id); |
| |
| /* |
| * Creates a context from a raw buffer representing a list of events to be read. |
| */ |
| android_log_context create_android_log_parser(const char* msg, size_t len); |
| |
| android_log_list_element android_log_read_next(android_log_context ctx); |
| android_log_list_element android_log_peek_next(android_log_context ctx); |
| |
| /* Reset writer context */ |
| int android_log_reset(android_log_context ctx); |
| |
| /* Reset reader context */ |
| int android_log_parser_reset(android_log_context ctx, |
| const char* msg, size_t len); |
| |
| /* Finished with reader or writer context */ |
| int android_log_destroy(android_log_context* ctx); |
| |
| #ifdef __cplusplus |
| #ifndef __class_android_log_event_list_defined |
| #define __class_android_log_event_list_defined |
| /* android_log_list C++ helpers */ |
| extern "C++" { |
| class android_log_event_list { |
| private: |
| android_log_context ctx; |
| int ret; |
| |
| android_log_event_list(const android_log_event_list&) = delete; |
| void operator=(const android_log_event_list&) = delete; |
| |
| public: |
| explicit android_log_event_list(int tag) : ret(0) { |
| ctx = create_android_logger(static_cast<uint32_t>(tag)); |
| } |
| ~android_log_event_list() { |
| android_log_destroy(&ctx); |
| } |
| |
| int close() { |
| int retval = android_log_destroy(&ctx); |
| if (retval < 0) ret = retval; |
| return retval; |
| } |
| |
| /* To allow above C calls to use this class as parameter */ |
| operator android_log_context() const { |
| return ctx; |
| } |
| |
| /* return errors or transmit status */ |
| int status() const { |
| return ret; |
| } |
| |
| int begin() { |
| int retval = android_log_write_list_begin(ctx); |
| if (retval < 0) ret = retval; |
| return ret; |
| } |
| int end() { |
| int retval = android_log_write_list_end(ctx); |
| if (retval < 0) ret = retval; |
| return ret; |
| } |
| |
| android_log_event_list& operator<<(int32_t value) { |
| int retval = android_log_write_int32(ctx, value); |
| if (retval < 0) ret = retval; |
| return *this; |
| } |
| |
| android_log_event_list& operator<<(uint32_t value) { |
| int retval = android_log_write_int32(ctx, static_cast<int32_t>(value)); |
| if (retval < 0) ret = retval; |
| return *this; |
| } |
| |
| android_log_event_list& operator<<(bool value) { |
| int retval = android_log_write_int32(ctx, value ? 1 : 0); |
| if (retval < 0) ret = retval; |
| return *this; |
| } |
| |
| android_log_event_list& operator<<(int64_t value) { |
| int retval = android_log_write_int64(ctx, value); |
| if (retval < 0) ret = retval; |
| return *this; |
| } |
| |
| android_log_event_list& operator<<(uint64_t value) { |
| int retval = android_log_write_int64(ctx, static_cast<int64_t>(value)); |
| if (retval < 0) ret = retval; |
| return *this; |
| } |
| |
| android_log_event_list& operator<<(const char* value) { |
| int retval = android_log_write_string8(ctx, value); |
| if (retval < 0) ret = retval; |
| return *this; |
| } |
| |
| android_log_event_list& operator<<(const std::string& value) { |
| int retval = |
| android_log_write_string8_len(ctx, value.data(), value.length()); |
| if (retval < 0) ret = retval; |
| return *this; |
| } |
| |
| android_log_event_list& operator<<(float value) { |
| int retval = android_log_write_float32(ctx, value); |
| if (retval < 0) ret = retval; |
| return *this; |
| } |
| |
| int write(log_id_t id = LOG_ID_EVENTS) { |
| /* facilitate -EBUSY retry */ |
| if ((ret == -EBUSY) || (ret > 0)) ret = 0; |
| int retval = android_log_write_list(ctx, id); |
| /* existing errors trump transmission errors */ |
| if (!ret) ret = retval; |
| return ret; |
| } |
| |
| int operator<<(log_id_t id) { |
| write(id); |
| android_log_destroy(&ctx); |
| return ret; |
| } |
| |
| /* |
| * Append<Type> methods removes any integer promotion |
| * confusion, and adds access to string with length. |
| * Append methods are also added for all types for |
| * convenience. |
| */ |
| |
| bool AppendInt(int32_t value) { |
| int retval = android_log_write_int32(ctx, value); |
| if (retval < 0) ret = retval; |
| return ret >= 0; |
| } |
| |
| bool AppendLong(int64_t value) { |
| int retval = android_log_write_int64(ctx, value); |
| if (retval < 0) ret = retval; |
| return ret >= 0; |
| } |
| |
| bool AppendString(const char* value) { |
| int retval = android_log_write_string8(ctx, value); |
| if (retval < 0) ret = retval; |
| return ret >= 0; |
| } |
| |
| bool AppendString(const char* value, size_t len) { |
| int retval = android_log_write_string8_len(ctx, value, len); |
| if (retval < 0) ret = retval; |
| return ret >= 0; |
| } |
| |
| bool AppendString(const std::string& value) { |
| int retval = |
| android_log_write_string8_len(ctx, value.data(), value.length()); |
| if (retval < 0) ret = retval; |
| return ret; |
| } |
| |
| bool Append(const std::string& value) { |
| int retval = |
| android_log_write_string8_len(ctx, value.data(), value.length()); |
| if (retval < 0) ret = retval; |
| return ret; |
| } |
| |
| bool AppendFloat(float value) { |
| int retval = android_log_write_float32(ctx, value); |
| if (retval < 0) ret = retval; |
| return ret >= 0; |
| } |
| |
| template <typename Tvalue> |
| bool Append(Tvalue value) { |
| *this << value; |
| return ret >= 0; |
| } |
| |
| bool Append(const char* value, size_t len) { |
| int retval = android_log_write_string8_len(ctx, value, len); |
| if (retval < 0) ret = retval; |
| return ret >= 0; |
| } |
| }; |
| } |
| #endif |
| #endif |
| |
| #ifdef __cplusplus |
| } |
| #endif |