blob: cb70d488a0a73f20ebc4470cc28a42bee3476c49 [file] [log] [blame]
Mark Salyzyn9dd65102016-02-17 16:08:13 -08001/*
2 * Copyright (C) 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#include <errno.h>
18#include <inttypes.h>
19#include <stdbool.h>
20#include <stdint.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24
Mark Salyzyn472245d2016-11-18 10:45:45 -080025#include <log/log_event_list.h>
Mark Salyzyn6debf982016-10-05 08:13:56 -070026#include <private/android_logger.h>
Mark Salyzyn9dd65102016-02-17 16:08:13 -080027
28#define MAX_EVENT_PAYLOAD (LOGGER_ENTRY_MAX_PAYLOAD - sizeof(int32_t))
29
Tom Cherry71ba1642019-01-10 10:37:36 -080030enum ReadWriteFlag {
31 kAndroidLoggerRead = 1,
32 kAndroidLoggerWrite = 2,
33};
34
35struct android_log_context_internal {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080036 uint32_t tag;
Tom Cherry71ba1642019-01-10 10:37:36 -080037 unsigned pos; /* Read/write position into buffer */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080038 unsigned count[ANDROID_MAX_LIST_NEST_DEPTH + 1]; /* Number of elements */
39 unsigned list[ANDROID_MAX_LIST_NEST_DEPTH + 1]; /* pos for list counter */
40 unsigned list_nest_depth;
41 unsigned len; /* Length or raw buffer. */
42 bool overflow;
43 bool list_stop; /* next call decrement list_nest_depth and issue a stop */
Tom Cherry71ba1642019-01-10 10:37:36 -080044 ReadWriteFlag read_write_flag;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080045 uint8_t storage[LOGGER_ENTRY_MAX_PAYLOAD];
Tom Cherry71ba1642019-01-10 10:37:36 -080046};
47
Suren Baghdasaryanbb20b9e2018-07-27 12:47:26 -070048static void init_context(android_log_context_internal* context, uint32_t tag) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080049 context->tag = tag;
50 context->read_write_flag = kAndroidLoggerWrite;
Tom Cherrybbbf0892019-10-09 10:53:37 -070051 size_t needed = sizeof(android_event_list_t);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080052 if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
53 context->overflow = true;
54 }
55 /* Everything is a list */
56 context->storage[context->pos + 0] = EVENT_TYPE_LIST;
57 context->list[0] = context->pos + 1;
58 context->pos += needed;
Suren Baghdasaryanbb20b9e2018-07-27 12:47:26 -070059}
60
Tom Cherry71ba1642019-01-10 10:37:36 -080061static void init_parser_context(android_log_context_internal* context, const char* msg,
62 size_t len) {
Suren Baghdasaryanbb20b9e2018-07-27 12:47:26 -070063 len = (len <= MAX_EVENT_PAYLOAD) ? len : MAX_EVENT_PAYLOAD;
64 context->len = len;
65 memcpy(context->storage, msg, len);
66 context->read_write_flag = kAndroidLoggerRead;
67}
68
Tom Cherry2d9779e2019-02-08 11:46:19 -080069android_log_context create_android_logger(uint32_t tag) {
Suren Baghdasaryanbb20b9e2018-07-27 12:47:26 -070070 android_log_context_internal* context;
71
Tom Cherry71ba1642019-01-10 10:37:36 -080072 context =
73 static_cast<android_log_context_internal*>(calloc(1, sizeof(android_log_context_internal)));
Suren Baghdasaryanbb20b9e2018-07-27 12:47:26 -070074 if (!context) {
75 return NULL;
76 }
77 init_context(context, tag);
Mark Salyzyn9dd65102016-02-17 16:08:13 -080078
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080079 return (android_log_context)context;
Mark Salyzyn9dd65102016-02-17 16:08:13 -080080}
81
Tom Cherry2d9779e2019-02-08 11:46:19 -080082android_log_context create_android_log_parser(const char* msg, size_t len) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080083 android_log_context_internal* context;
Mark Salyzyn9dd65102016-02-17 16:08:13 -080084
Tom Cherry71ba1642019-01-10 10:37:36 -080085 context =
86 static_cast<android_log_context_internal*>(calloc(1, sizeof(android_log_context_internal)));
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080087 if (!context) {
88 return NULL;
89 }
Suren Baghdasaryanbb20b9e2018-07-27 12:47:26 -070090 init_parser_context(context, msg, len);
Mark Salyzyn9dd65102016-02-17 16:08:13 -080091
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080092 return (android_log_context)context;
Mark Salyzyn9dd65102016-02-17 16:08:13 -080093}
94
Tom Cherry2d9779e2019-02-08 11:46:19 -080095int android_log_destroy(android_log_context* ctx) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080096 android_log_context_internal* context;
Mark Salyzyn9dd65102016-02-17 16:08:13 -080097
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080098 context = (android_log_context_internal*)*ctx;
99 if (!context) {
100 return -EBADF;
101 }
102 memset(context, 0, sizeof(*context));
103 free(context);
104 *ctx = NULL;
105 return 0;
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800106}
107
Tom Cherry828db1a2019-11-14 10:39:40 -0800108int android_log_reset(android_log_context context) {
Suren Baghdasaryanbb20b9e2018-07-27 12:47:26 -0700109 uint32_t tag;
110
Suren Baghdasaryanbb20b9e2018-07-27 12:47:26 -0700111 if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
112 return -EBADF;
113 }
114
115 tag = context->tag;
116 memset(context, 0, sizeof(*context));
117 init_context(context, tag);
118
119 return 0;
120}
121
Tom Cherry828db1a2019-11-14 10:39:40 -0800122int android_log_parser_reset(android_log_context context, const char* msg, size_t len) {
Suren Baghdasaryanbb20b9e2018-07-27 12:47:26 -0700123 if (!context || (kAndroidLoggerRead != context->read_write_flag)) {
124 return -EBADF;
125 }
126
127 memset(context, 0, sizeof(*context));
128 init_parser_context(context, msg, len);
129
130 return 0;
131}
132
Tom Cherry828db1a2019-11-14 10:39:40 -0800133int android_log_write_list_begin(android_log_context context) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800134 if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
135 return -EBADF;
136 }
137 if (context->list_nest_depth > ANDROID_MAX_LIST_NEST_DEPTH) {
138 context->overflow = true;
139 return -EOVERFLOW;
140 }
Tom Cherrybbbf0892019-10-09 10:53:37 -0700141 size_t needed = sizeof(android_event_list_t);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800142 if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
143 context->overflow = true;
144 return -EIO;
145 }
146 context->count[context->list_nest_depth]++;
147 context->list_nest_depth++;
148 if (context->list_nest_depth > ANDROID_MAX_LIST_NEST_DEPTH) {
149 context->overflow = true;
150 return -EOVERFLOW;
151 }
152 if (context->overflow) {
153 return -EIO;
154 }
Tom Cherrybbbf0892019-10-09 10:53:37 -0700155 auto* event_list = reinterpret_cast<android_event_list_t*>(&context->storage[context->pos]);
156 event_list->type = EVENT_TYPE_LIST;
157 event_list->element_count = 0;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800158 context->list[context->list_nest_depth] = context->pos + 1;
159 context->count[context->list_nest_depth] = 0;
160 context->pos += needed;
161 return 0;
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800162}
163
Tom Cherry828db1a2019-11-14 10:39:40 -0800164int android_log_write_int32(android_log_context context, int32_t value) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800165 if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
166 return -EBADF;
167 }
168 if (context->overflow) {
169 return -EIO;
170 }
Tom Cherrybbbf0892019-10-09 10:53:37 -0700171 size_t needed = sizeof(android_event_int_t);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800172 if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
173 context->overflow = true;
174 return -EIO;
175 }
176 context->count[context->list_nest_depth]++;
Tom Cherrybbbf0892019-10-09 10:53:37 -0700177 auto* event_int = reinterpret_cast<android_event_int_t*>(&context->storage[context->pos]);
178 event_int->type = EVENT_TYPE_INT;
179 event_int->data = value;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800180 context->pos += needed;
181 return 0;
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800182}
183
Tom Cherry828db1a2019-11-14 10:39:40 -0800184int android_log_write_int64(android_log_context context, int64_t value) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800185 if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
186 return -EBADF;
187 }
188 if (context->overflow) {
189 return -EIO;
190 }
Tom Cherrybbbf0892019-10-09 10:53:37 -0700191 size_t needed = sizeof(android_event_long_t);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800192 if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
193 context->overflow = true;
194 return -EIO;
195 }
196 context->count[context->list_nest_depth]++;
Tom Cherrybbbf0892019-10-09 10:53:37 -0700197 auto* event_long = reinterpret_cast<android_event_long_t*>(&context->storage[context->pos]);
198 event_long->type = EVENT_TYPE_LONG;
199 event_long->data = value;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800200 context->pos += needed;
201 return 0;
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800202}
203
Tom Cherry828db1a2019-11-14 10:39:40 -0800204int android_log_write_string8_len(android_log_context context, const char* value, size_t maxlen) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800205 if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
206 return -EBADF;
207 }
208 if (context->overflow) {
209 return -EIO;
210 }
211 if (!value) {
212 value = "";
213 }
Tom Cherrybbbf0892019-10-09 10:53:37 -0700214 int32_t len = strnlen(value, maxlen);
215 size_t needed = sizeof(android_event_string_t) + len;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800216 if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
217 /* Truncate string for delivery */
218 len = MAX_EVENT_PAYLOAD - context->pos - 1 - sizeof(int32_t);
219 if (len <= 0) {
220 context->overflow = true;
221 return -EIO;
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800222 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800223 }
224 context->count[context->list_nest_depth]++;
Tom Cherrybbbf0892019-10-09 10:53:37 -0700225 auto* event_string = reinterpret_cast<android_event_string_t*>(&context->storage[context->pos]);
226 event_string->type = EVENT_TYPE_STRING;
227 event_string->length = len;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800228 if (len) {
Tom Cherrybbbf0892019-10-09 10:53:37 -0700229 memcpy(&event_string->data, value, len);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800230 }
231 context->pos += needed;
232 return len;
Mark Salyzyn1d5afc92016-02-25 08:41:25 -0800233}
234
Tom Cherry2d9779e2019-02-08 11:46:19 -0800235int android_log_write_string8(android_log_context ctx, const char* value) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800236 return android_log_write_string8_len(ctx, value, MAX_EVENT_PAYLOAD);
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800237}
238
Tom Cherry828db1a2019-11-14 10:39:40 -0800239int android_log_write_float32(android_log_context context, float value) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800240 if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
241 return -EBADF;
242 }
243 if (context->overflow) {
244 return -EIO;
245 }
Tom Cherrybbbf0892019-10-09 10:53:37 -0700246 size_t needed = sizeof(android_event_float_t);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800247 if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
248 context->overflow = true;
249 return -EIO;
250 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800251 context->count[context->list_nest_depth]++;
Tom Cherrybbbf0892019-10-09 10:53:37 -0700252 auto* event_float = reinterpret_cast<android_event_float_t*>(&context->storage[context->pos]);
253 event_float->type = EVENT_TYPE_FLOAT;
254 event_float->data = value;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800255 context->pos += needed;
256 return 0;
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800257}
258
Tom Cherry828db1a2019-11-14 10:39:40 -0800259int android_log_write_list_end(android_log_context context) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800260 if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
261 return -EBADF;
262 }
263 if (context->list_nest_depth > ANDROID_MAX_LIST_NEST_DEPTH) {
264 context->overflow = true;
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800265 context->list_nest_depth--;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800266 return -EOVERFLOW;
267 }
268 if (!context->list_nest_depth) {
269 context->overflow = true;
270 return -EOVERFLOW;
271 }
272 if (context->list[context->list_nest_depth] <= 0) {
273 context->list_nest_depth--;
274 context->overflow = true;
275 return -EOVERFLOW;
276 }
277 context->storage[context->list[context->list_nest_depth]] =
278 context->count[context->list_nest_depth];
279 context->list_nest_depth--;
280 return 0;
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800281}
282
283/*
284 * Logs the list of elements to the event log.
285 */
Tom Cherry828db1a2019-11-14 10:39:40 -0800286int android_log_write_list(android_log_context context, log_id_t id) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800287 const char* msg;
288 ssize_t len;
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800289
Stefan Lafon701a0652017-08-24 20:14:06 -0700290 if ((id != LOG_ID_EVENTS) && (id != LOG_ID_SECURITY) && (id != LOG_ID_STATS)) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800291 return -EINVAL;
292 }
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800293
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800294 if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
295 return -EBADF;
296 }
297 if (context->list_nest_depth) {
298 return -EIO;
299 }
300 /* NB: if there was overflow, then log is truncated. Nothing reported */
301 context->storage[1] = context->count[0];
302 len = context->len = context->pos;
303 msg = (const char*)context->storage;
304 /* it's not a list */
305 if (context->count[0] <= 1) {
306 len -= sizeof(uint8_t) + sizeof(uint8_t);
307 if (len < 0) {
308 len = 0;
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800309 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800310 msg += sizeof(uint8_t) + sizeof(uint8_t);
311 }
312 return (id == LOG_ID_EVENTS)
313 ? __android_log_bwrite(context->tag, msg, len)
Tom Cherry71ba1642019-01-10 10:37:36 -0800314 : ((id == LOG_ID_STATS) ? __android_log_stats_bwrite(context->tag, msg, len)
315 : __android_log_security_bwrite(context->tag, msg, len));
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800316}
317
Tom Cherry828db1a2019-11-14 10:39:40 -0800318int android_log_write_list_buffer(android_log_context context, const char** buffer) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800319 const char* msg;
320 ssize_t len;
Mark Salyzyn2ca4f492016-09-12 11:54:57 -0700321
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800322 if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
323 return -EBADF;
324 }
325 if (context->list_nest_depth) {
326 return -EIO;
327 }
328 if (buffer == NULL) {
329 return -EFAULT;
330 }
331 /* NB: if there was overflow, then log is truncated. Nothing reported */
332 context->storage[1] = context->count[0];
333 len = context->len = context->pos;
334 msg = (const char*)context->storage;
335 /* it's not a list */
336 if (context->count[0] <= 1) {
337 len -= sizeof(uint8_t) + sizeof(uint8_t);
338 if (len < 0) {
339 len = 0;
Mark Salyzyn2ca4f492016-09-12 11:54:57 -0700340 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800341 msg += sizeof(uint8_t) + sizeof(uint8_t);
342 }
343 *buffer = msg;
344 return len;
Mark Salyzyn2ca4f492016-09-12 11:54:57 -0700345}
346
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800347/*
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800348 * Gets the next element. Parsing errors result in an EVENT_TYPE_UNKNOWN type.
349 * If there is nothing to process, the complete field is set to non-zero. If
350 * an EVENT_TYPE_UNKNOWN type is returned once, and the caller does not check
351 * this and continues to call this function, the behavior is undefined
352 * (although it won't crash).
353 */
Tom Cherry828db1a2019-11-14 10:39:40 -0800354static android_log_list_element android_log_read_next_internal(android_log_context context,
355 int peek) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800356 android_log_list_element elem;
357 unsigned pos;
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800358
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800359 memset(&elem, 0, sizeof(elem));
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800360
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800361 /* Nothing to parse from this context, so return complete. */
362 if (!context || (kAndroidLoggerRead != context->read_write_flag) ||
363 (context->list_nest_depth > ANDROID_MAX_LIST_NEST_DEPTH) ||
364 (context->count[context->list_nest_depth] >=
365 (MAX_EVENT_PAYLOAD / (sizeof(uint8_t) + sizeof(uint8_t))))) {
366 elem.type = EVENT_TYPE_UNKNOWN;
Tom Cherry71ba1642019-01-10 10:37:36 -0800367 if (context &&
368 (context->list_stop || ((context->list_nest_depth <= ANDROID_MAX_LIST_NEST_DEPTH) &&
369 !context->count[context->list_nest_depth]))) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800370 elem.type = EVENT_TYPE_LIST_STOP;
371 }
372 elem.complete = true;
373 return elem;
374 }
375
376 /*
377 * Use a different variable to update the position in case this
378 * operation is a "peek".
379 */
380 pos = context->pos;
381 if (context->list_stop) {
382 elem.type = EVENT_TYPE_LIST_STOP;
Tom Cherry71ba1642019-01-10 10:37:36 -0800383 elem.complete = !context->count[0] && (!context->list_nest_depth ||
384 ((context->list_nest_depth == 1) && !context->count[1]));
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800385 if (!peek) {
386 /* Suck in superfluous stop */
387 if (context->storage[pos] == EVENT_TYPE_LIST_STOP) {
388 context->pos = pos + 1;
389 }
390 if (context->list_nest_depth) {
391 --context->list_nest_depth;
392 if (context->count[context->list_nest_depth]) {
393 context->list_stop = false;
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800394 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800395 } else {
396 context->list_stop = false;
397 }
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800398 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800399 return elem;
400 }
401 if ((pos + 1) > context->len) {
402 elem.type = EVENT_TYPE_UNKNOWN;
403 elem.complete = true;
404 return elem;
405 }
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800406
Tom Cherrybbbf0892019-10-09 10:53:37 -0700407 elem.type = static_cast<AndroidEventLogType>(context->storage[pos]);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800408 switch ((int)elem.type) {
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800409 case EVENT_TYPE_FLOAT:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800410 /* Rely on union to translate elem.data.int32 into elem.data.float32 */
411 /* FALLTHRU */
Tom Cherrybbbf0892019-10-09 10:53:37 -0700412 case EVENT_TYPE_INT: {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800413 elem.len = sizeof(int32_t);
Tom Cherrybbbf0892019-10-09 10:53:37 -0700414 if ((pos + sizeof(android_event_int_t)) > context->len) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800415 elem.type = EVENT_TYPE_UNKNOWN;
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800416 return elem;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800417 }
Tom Cherrybbbf0892019-10-09 10:53:37 -0700418
419 auto* event_int = reinterpret_cast<android_event_int_t*>(&context->storage[pos]);
420 pos += sizeof(android_event_int_t);
421 elem.data.int32 = event_int->data;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800422 /* common tangeable object suffix */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800423 elem.complete = !context->list_nest_depth && !context->count[0];
424 if (!peek) {
425 if (!context->count[context->list_nest_depth] ||
426 !--(context->count[context->list_nest_depth])) {
427 context->list_stop = true;
428 }
429 context->pos = pos;
430 }
431 return elem;
Tom Cherrybbbf0892019-10-09 10:53:37 -0700432 }
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800433
Tom Cherrybbbf0892019-10-09 10:53:37 -0700434 case EVENT_TYPE_LONG: {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800435 elem.len = sizeof(int64_t);
Tom Cherrybbbf0892019-10-09 10:53:37 -0700436 if ((pos + sizeof(android_event_long_t)) > context->len) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800437 elem.type = EVENT_TYPE_UNKNOWN;
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800438 return elem;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800439 }
Tom Cherrybbbf0892019-10-09 10:53:37 -0700440
441 auto* event_long = reinterpret_cast<android_event_long_t*>(&context->storage[pos]);
442 pos += sizeof(android_event_long_t);
443 elem.data.int64 = event_long->data;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800444 /* common tangeable object suffix */
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800445 elem.complete = !context->list_nest_depth && !context->count[0];
446 if (!peek) {
447 if (!context->count[context->list_nest_depth] ||
448 !--(context->count[context->list_nest_depth])) {
449 context->list_stop = true;
450 }
451 context->pos = pos;
452 }
453 return elem;
Tom Cherrybbbf0892019-10-09 10:53:37 -0700454 }
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800455
Tom Cherrybbbf0892019-10-09 10:53:37 -0700456 case EVENT_TYPE_STRING: {
457 if ((pos + sizeof(android_event_string_t)) > context->len) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800458 elem.type = EVENT_TYPE_UNKNOWN;
459 elem.complete = true;
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800460 return elem;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800461 }
Tom Cherrybbbf0892019-10-09 10:53:37 -0700462 auto* event_string = reinterpret_cast<android_event_string_t*>(&context->storage[pos]);
463 pos += sizeof(android_event_string_t);
464 // Wire format is int32_t, but elem.len is uint16_t...
465 if (event_string->length >= UINT16_MAX) {
466 elem.type = EVENT_TYPE_UNKNOWN;
467 return elem;
468 }
469 elem.len = event_string->length;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800470 if ((pos + elem.len) > context->len) {
471 elem.len = context->len - pos; /* truncate string */
472 elem.complete = true;
473 if (!elem.len) {
474 elem.type = EVENT_TYPE_UNKNOWN;
475 return elem;
476 }
477 }
Tom Cherrybbbf0892019-10-09 10:53:37 -0700478 elem.data.string = event_string->data;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800479 /* common tangeable object suffix */
480 pos += elem.len;
481 elem.complete = !context->list_nest_depth && !context->count[0];
482 if (!peek) {
483 if (!context->count[context->list_nest_depth] ||
484 !--(context->count[context->list_nest_depth])) {
485 context->list_stop = true;
486 }
487 context->pos = pos;
488 }
489 return elem;
Tom Cherrybbbf0892019-10-09 10:53:37 -0700490 }
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800491
Tom Cherrybbbf0892019-10-09 10:53:37 -0700492 case EVENT_TYPE_LIST: {
493 if ((pos + sizeof(android_event_list_t)) > context->len) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800494 elem.type = EVENT_TYPE_UNKNOWN;
495 elem.complete = true;
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800496 return elem;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800497 }
Tom Cherrybbbf0892019-10-09 10:53:37 -0700498 auto* event_list = reinterpret_cast<android_event_list_t*>(&context->storage[pos]);
499 pos += sizeof(android_event_list_t);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800500 elem.complete = context->list_nest_depth >= ANDROID_MAX_LIST_NEST_DEPTH;
501 if (peek) {
502 return elem;
503 }
504 if (context->count[context->list_nest_depth]) {
505 context->count[context->list_nest_depth]--;
506 }
Tom Cherrybbbf0892019-10-09 10:53:37 -0700507 context->list_stop = event_list->element_count == 0;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800508 context->list_nest_depth++;
509 if (context->list_nest_depth <= ANDROID_MAX_LIST_NEST_DEPTH) {
Tom Cherrybbbf0892019-10-09 10:53:37 -0700510 context->count[context->list_nest_depth] = event_list->element_count;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800511 }
Tom Cherrybbbf0892019-10-09 10:53:37 -0700512 context->pos = pos;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800513 return elem;
Tom Cherrybbbf0892019-10-09 10:53:37 -0700514 }
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800515
516 case EVENT_TYPE_LIST_STOP: /* Suprise Newline terminates lists. */
Tom Cherrybbbf0892019-10-09 10:53:37 -0700517 pos++;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800518 if (!peek) {
519 context->pos = pos;
520 }
521 elem.type = EVENT_TYPE_UNKNOWN;
522 elem.complete = !context->list_nest_depth;
523 if (context->list_nest_depth > 0) {
524 elem.type = EVENT_TYPE_LIST_STOP;
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800525 if (!peek) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800526 context->list_nest_depth--;
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800527 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800528 }
529 return elem;
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800530
531 default:
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800532 elem.type = EVENT_TYPE_UNKNOWN;
533 return elem;
534 }
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800535}
536
Tom Cherry2d9779e2019-02-08 11:46:19 -0800537android_log_list_element android_log_read_next(android_log_context ctx) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800538 return android_log_read_next_internal(ctx, 0);
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800539}
540
Tom Cherry2d9779e2019-02-08 11:46:19 -0800541android_log_list_element android_log_peek_next(android_log_context ctx) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800542 return android_log_read_next_internal(ctx, 1);
Mark Salyzyn9dd65102016-02-17 16:08:13 -0800543}