/* * 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 #include #ifdef __cplusplus #include #endif #include #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. */ typedef struct android_log_context_internal* android_log_context; /* * Elements returned when reading a list of events. */ 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; /* * 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 /* 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(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(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(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 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 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 #ifdef __cplusplus } #endif