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