1/*
2 * Copyright (C) 2005-2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef _LIBS_LOG_EVENT_LIST_H
18#define _LIBS_LOG_EVENT_LIST_H
19
20#include <errno.h>
21#include <stdint.h>
22
23#if (defined(__cplusplus) && defined(_USING_LIBCXX))
24extern "C++" {
25#include <string>
26}
27#endif
28
29#include <log/log.h>
30
31#ifdef __cplusplus
32extern "C" {
33#endif
34
35#ifndef __ANDROID_USE_LIBLOG_EVENT_INTERFACE
36#ifndef __ANDROID_API__
37#define __ANDROID_USE_LIBLOG_EVENT_INTERFACE 1
38#elif __ANDROID_API__ > 23 /* > Marshmallow */
39#define __ANDROID_USE_LIBLOG_EVENT_INTERFACE 1
40#else
41#define __ANDROID_USE_LIBLOG_EVENT_INTERFACE 0
42#endif
43#endif
44
45#if __ANDROID_USE_LIBLOG_EVENT_INTERFACE
46
47/* For manipulating lists of events. */
48
49#define ANDROID_MAX_LIST_NEST_DEPTH 8
50
51/*
52 * The opaque context used to manipulate lists of events.
53 */
54#ifndef __android_log_context_defined
55#define __android_log_context_defined
56typedef struct android_log_context_internal* android_log_context;
57#endif
58
59/*
60 * Elements returned when reading a list of events.
61 */
62#ifndef __android_log_list_element_defined
63#define __android_log_list_element_defined
64typedef struct {
65  AndroidEventLogType type;
66  uint16_t complete;
67  uint16_t len;
68  union {
69    int32_t int32;
70    int64_t int64;
71    char* string;
72    float float32;
73  } data;
74} android_log_list_element;
75#endif
76
77/*
78 * Creates a context associated with an event tag to write elements to
79 * the list of events.
80 */
81android_log_context create_android_logger(uint32_t tag);
82
83/* All lists must be braced by a begin and end call */
84/*
85 * NB: If the first level braces are missing when specifying multiple
86 *     elements, we will manufacturer a list to embrace it for your API
87 *     convenience. For a single element, it will remain solitary.
88 */
89int android_log_write_list_begin(android_log_context ctx);
90int android_log_write_list_end(android_log_context ctx);
91
92int android_log_write_int32(android_log_context ctx, int32_t value);
93int android_log_write_int64(android_log_context ctx, int64_t value);
94int android_log_write_string8(android_log_context ctx, const char* value);
95int android_log_write_string8_len(android_log_context ctx, const char* value,
96                                  size_t maxlen);
97int android_log_write_float32(android_log_context ctx, float value);
98
99/* Submit the composed list context to the specified logger id */
100/* NB: LOG_ID_EVENTS and LOG_ID_SECURITY only valid binary buffers */
101int android_log_write_list(android_log_context ctx, log_id_t id);
102
103/*
104 * Creates a context from a raw buffer representing a list of events to be read.
105 */
106android_log_context create_android_log_parser(const char* msg, size_t len);
107
108android_log_list_element android_log_read_next(android_log_context ctx);
109android_log_list_element android_log_peek_next(android_log_context ctx);
110
111/* Finished with reader or writer context */
112int android_log_destroy(android_log_context* ctx);
113
114#ifdef __cplusplus
115#ifndef __class_android_log_event_list_defined
116#define __class_android_log_event_list_defined
117/* android_log_list C++ helpers */
118extern "C++" {
119class android_log_event_list {
120  friend class __android_log_event_list;
121
122 private:
123  android_log_context ctx;
124  int ret;
125
126  android_log_event_list(const android_log_event_list&) = delete;
127  void operator=(const android_log_event_list&) = delete;
128
129 public:
130  explicit android_log_event_list(int tag) : ret(0) {
131    ctx = create_android_logger(static_cast<uint32_t>(tag));
132  }
133  explicit android_log_event_list(log_msg& log_msg) : ret(0) {
134    ctx = create_android_log_parser(log_msg.msg() + sizeof(uint32_t),
135                                    log_msg.entry.len - sizeof(uint32_t));
136  }
137  ~android_log_event_list() {
138    android_log_destroy(&ctx);
139  }
140
141  int close() {
142    int retval = android_log_destroy(&ctx);
143    if (retval < 0) ret = retval;
144    return retval;
145  }
146
147  /* To allow above C calls to use this class as parameter */
148  operator android_log_context() const {
149    return ctx;
150  }
151
152  /* return errors or transmit status */
153  int status() const {
154    return ret;
155  }
156
157  int begin() {
158    int retval = android_log_write_list_begin(ctx);
159    if (retval < 0) ret = retval;
160    return ret;
161  }
162  int end() {
163    int retval = android_log_write_list_end(ctx);
164    if (retval < 0) ret = retval;
165    return ret;
166  }
167
168  android_log_event_list& operator<<(int32_t value) {
169    int retval = android_log_write_int32(ctx, value);
170    if (retval < 0) ret = retval;
171    return *this;
172  }
173
174  android_log_event_list& operator<<(uint32_t value) {
175    int retval = android_log_write_int32(ctx, static_cast<int32_t>(value));
176    if (retval < 0) ret = retval;
177    return *this;
178  }
179
180  android_log_event_list& operator<<(bool value) {
181    int retval = android_log_write_int32(ctx, value ? 1 : 0);
182    if (retval < 0) ret = retval;
183    return *this;
184  }
185
186  android_log_event_list& operator<<(int64_t value) {
187    int retval = android_log_write_int64(ctx, value);
188    if (retval < 0) ret = retval;
189    return *this;
190  }
191
192  android_log_event_list& operator<<(uint64_t value) {
193    int retval = android_log_write_int64(ctx, static_cast<int64_t>(value));
194    if (retval < 0) ret = retval;
195    return *this;
196  }
197
198  android_log_event_list& operator<<(const char* value) {
199    int retval = android_log_write_string8(ctx, value);
200    if (retval < 0) ret = retval;
201    return *this;
202  }
203
204#if defined(_USING_LIBCXX)
205  android_log_event_list& operator<<(const std::string& value) {
206    int retval =
207        android_log_write_string8_len(ctx, value.data(), value.length());
208    if (retval < 0) ret = retval;
209    return *this;
210  }
211#endif
212
213  android_log_event_list& operator<<(float value) {
214    int retval = android_log_write_float32(ctx, value);
215    if (retval < 0) ret = retval;
216    return *this;
217  }
218
219  int write(log_id_t id = LOG_ID_EVENTS) {
220    /* facilitate -EBUSY retry */
221    if ((ret == -EBUSY) || (ret > 0)) ret = 0;
222    int retval = android_log_write_list(ctx, id);
223    /* existing errors trump transmission errors */
224    if (!ret) ret = retval;
225    return ret;
226  }
227
228  int operator<<(log_id_t id) {
229    write(id);
230    android_log_destroy(&ctx);
231    return ret;
232  }
233
234  /*
235   * Append<Type> methods removes any integer promotion
236   * confusion, and adds access to string with length.
237   * Append methods are also added for all types for
238   * convenience.
239   */
240
241  bool AppendInt(int32_t value) {
242    int retval = android_log_write_int32(ctx, value);
243    if (retval < 0) ret = retval;
244    return ret >= 0;
245  }
246
247  bool AppendLong(int64_t value) {
248    int retval = android_log_write_int64(ctx, value);
249    if (retval < 0) ret = retval;
250    return ret >= 0;
251  }
252
253  bool AppendString(const char* value) {
254    int retval = android_log_write_string8(ctx, value);
255    if (retval < 0) ret = retval;
256    return ret >= 0;
257  }
258
259  bool AppendString(const char* value, size_t len) {
260    int retval = android_log_write_string8_len(ctx, value, len);
261    if (retval < 0) ret = retval;
262    return ret >= 0;
263  }
264
265#if defined(_USING_LIBCXX)
266  bool AppendString(const std::string& value) {
267    int retval =
268        android_log_write_string8_len(ctx, value.data(), value.length());
269    if (retval < 0) ret = retval;
270    return ret;
271  }
272
273  bool Append(const std::string& value) {
274    int retval =
275        android_log_write_string8_len(ctx, value.data(), value.length());
276    if (retval < 0) ret = retval;
277    return ret;
278  }
279#endif
280
281  bool AppendFloat(float value) {
282    int retval = android_log_write_float32(ctx, value);
283    if (retval < 0) ret = retval;
284    return ret >= 0;
285  }
286
287  template <typename Tvalue>
288  bool Append(Tvalue value) {
289    *this << value;
290    return ret >= 0;
291  }
292
293  bool Append(const char* value, size_t len) {
294    int retval = android_log_write_string8_len(ctx, value, len);
295    if (retval < 0) ret = retval;
296    return ret >= 0;
297  }
298
299  android_log_list_element read() {
300    return android_log_read_next(ctx);
301  }
302  android_log_list_element peek() {
303    return android_log_peek_next(ctx);
304  }
305};
306}
307#endif
308#endif
309
310#endif /* __ANDROID_USE_LIBLOG_EVENT_INTERFACE */
311
312#ifdef __cplusplus
313}
314#endif
315
316#endif /* _LIBS_LOG_EVENT_LIST_H */
317