blob: 974e203cd6129b52ac413e75733b89fcddeff225 [file] [log] [blame]
Joe Onoratoc4dfae52017-10-17 23:38:21 -07001/*
2 * Copyright (C) 2017 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
Tej Singh484524a2018-02-01 15:10:05 -080017#define DEBUG false // STOPSHIP if true
Joe Onoratoc4dfae52017-10-17 23:38:21 -070018#include "logd/LogEvent.h"
19
Yangster-mac20877162017-12-22 17:19:39 -080020#include "stats_log_util.h"
Yangster-mac48b3d622018-08-18 12:38:11 -070021#include "statslog.h"
Joe Onoratoc4dfae52017-10-17 23:38:21 -070022
Ruchir Rastogie449b0c2020-02-10 17:40:09 -080023#include <android/binder_ibinder.h>
24#include <android-base/stringprintf.h>
Tej Singh8928ed72019-02-22 19:06:22 -080025#include <private/android_filesystem_config.h>
Chenjie Yu6b1667c2019-01-18 10:09:33 -080026
Joe Onoratoc4dfae52017-10-17 23:38:21 -070027namespace android {
28namespace os {
29namespace statsd {
30
Jeff Hamiltonfa2f91c2019-03-22 00:25:02 -040031// for TrainInfo experiment id serialization
32const int FIELD_ID_EXPERIMENT_ID = 1;
33
yro24809bd2017-10-31 23:06:53 -070034using namespace android::util;
Ruchir Rastogie449b0c2020-02-10 17:40:09 -080035using android::base::StringPrintf;
Yao Chen9c1debe2018-02-19 14:39:19 -080036using android::util::ProtoOutputStream;
David Chen1481fe12017-10-16 13:16:34 -070037using std::string;
Yao Chen9c1debe2018-02-19 14:39:19 -080038using std::vector;
Joe Onoratoc4dfae52017-10-17 23:38:21 -070039
Tej Singhb26d0442020-01-31 16:18:21 -080040// stats_event.h socket types. Keep in sync.
41/* ERRORS */
42#define ERROR_NO_TIMESTAMP 0x1
43#define ERROR_NO_ATOM_ID 0x2
44#define ERROR_OVERFLOW 0x4
45#define ERROR_ATTRIBUTION_CHAIN_TOO_LONG 0x8
46#define ERROR_TOO_MANY_KEY_VALUE_PAIRS 0x10
47#define ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD 0x20
48#define ERROR_INVALID_ANNOTATION_ID 0x40
49#define ERROR_ANNOTATION_ID_TOO_LARGE 0x80
50#define ERROR_TOO_MANY_ANNOTATIONS 0x100
51#define ERROR_TOO_MANY_FIELDS 0x200
52#define ERROR_INVALID_VALUE_TYPE 0x400
53#define ERROR_STRING_NOT_NULL_TERMINATED 0x800
54
55/* TYPE IDS */
56#define INT32_TYPE 0x00
57#define INT64_TYPE 0x01
58#define STRING_TYPE 0x02
59#define LIST_TYPE 0x03
60#define FLOAT_TYPE 0x04
61#define BOOL_TYPE 0x05
62#define BYTE_ARRAY_TYPE 0x06
63#define OBJECT_TYPE 0x07
64#define KEY_VALUE_PAIRS_TYPE 0x08
65#define ATTRIBUTION_CHAIN_TYPE 0x09
66#define ERROR_TYPE 0x0F
67
Chenjie Yu0bd73db2018-12-16 07:37:04 -080068LogEvent::LogEvent(const LogEvent& event) {
69 mTagId = event.mTagId;
70 mLogUid = event.mLogUid;
Ruchir Rastogiab71ef02020-01-30 01:24:50 -080071 mLogPid = event.mLogPid;
Chenjie Yu0bd73db2018-12-16 07:37:04 -080072 mElapsedTimestampNs = event.mElapsedTimestampNs;
73 mLogdTimestampNs = event.mLogdTimestampNs;
74 mValues = event.mValues;
75}
76
Ruchir Rastogidfd63d42020-02-20 17:54:13 -080077LogEvent::LogEvent(int32_t uid, int32_t pid)
78 : mLogdTimestampNs(time(nullptr)),
79 mLogUid(uid),
80 mLogPid(pid) {
81}
82
Yangster-mac330af582018-02-08 15:24:38 -080083LogEvent::LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedTimestampNs) {
84 mLogdTimestampNs = wallClockTimestampNs;
Yao Chen0f861862019-03-27 11:51:15 -070085 mElapsedTimestampNs = elapsedTimestampNs;
Yao Chen80235402017-11-13 20:42:25 -080086 mTagId = tagId;
Yangster-mac20877162017-12-22 17:19:39 -080087 mLogUid = 0;
Yao Chen80235402017-11-13 20:42:25 -080088 mContext = create_android_logger(1937006964); // the event tag shared by all stats logs
89 if (mContext) {
Yangster-mac330af582018-02-08 15:24:38 -080090 android_log_write_int64(mContext, elapsedTimestampNs);
91 android_log_write_int32(mContext, tagId);
92 }
93}
94
Yangster-mac48b3d622018-08-18 12:38:11 -070095LogEvent::LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
96 int32_t uid,
Howard Ro4078dd42018-09-27 17:41:08 -070097 const std::map<int32_t, int32_t>& int_map,
98 const std::map<int32_t, int64_t>& long_map,
Yangster-mac48b3d622018-08-18 12:38:11 -070099 const std::map<int32_t, std::string>& string_map,
100 const std::map<int32_t, float>& float_map) {
101 mLogdTimestampNs = wallClockTimestampNs;
102 mElapsedTimestampNs = elapsedTimestampNs;
103 mTagId = android::util::KEY_VALUE_PAIRS_ATOM;
104 mLogUid = uid;
105
106 int pos[] = {1, 1, 1};
107
108 mValues.push_back(FieldValue(Field(mTagId, pos, 0 /* depth */), Value(uid)));
109 pos[0]++;
110 for (const auto&itr : int_map) {
111 pos[2] = 1;
112 mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.first)));
113 pos[2] = 2;
114 mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.second)));
115 mValues.back().mField.decorateLastPos(2);
116 pos[1]++;
117 }
118
Howard Ro4078dd42018-09-27 17:41:08 -0700119 for (const auto&itr : long_map) {
Yangster-mac48b3d622018-08-18 12:38:11 -0700120 pos[2] = 1;
121 mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.first)));
122 pos[2] = 3;
123 mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.second)));
124 mValues.back().mField.decorateLastPos(2);
125 pos[1]++;
126 }
127
Howard Ro4078dd42018-09-27 17:41:08 -0700128 for (const auto&itr : string_map) {
Yangster-mac48b3d622018-08-18 12:38:11 -0700129 pos[2] = 1;
130 mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.first)));
131 pos[2] = 4;
132 mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.second)));
133 mValues.back().mField.decorateLastPos(2);
134 pos[1]++;
135 }
Howard Ro4078dd42018-09-27 17:41:08 -0700136
137 for (const auto&itr : float_map) {
138 pos[2] = 1;
139 mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.first)));
140 pos[2] = 5;
141 mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.second)));
142 mValues.back().mField.decorateLastPos(2);
143 pos[1]++;
144 }
Yangster-mac48b3d622018-08-18 12:38:11 -0700145 if (!mValues.empty()) {
146 mValues.back().mField.decorateLastPos(1);
147 mValues.at(mValues.size() - 2).mField.decorateLastPos(1);
148 }
149}
150
Chenjie Yu6b1667c2019-01-18 10:09:33 -0800151LogEvent::LogEvent(const string& trainName, int64_t trainVersionCode, bool requiresStaging,
152 bool rollbackEnabled, bool requiresLowLatencyMonitor, int32_t state,
153 const std::vector<uint8_t>& experimentIds, int32_t userId) {
154 mLogdTimestampNs = getWallClockNs();
155 mElapsedTimestampNs = getElapsedRealtimeNs();
156 mTagId = android::util::BINARY_PUSH_STATE_CHANGED;
Ruchir Rastogie449b0c2020-02-10 17:40:09 -0800157 mLogUid = AIBinder_getCallingUid();
158 mLogPid = AIBinder_getCallingPid();
Chenjie Yu6b1667c2019-01-18 10:09:33 -0800159
160 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(1)), Value(trainName)));
161 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(2)), Value(trainVersionCode)));
162 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(3)), Value((int)requiresStaging)));
163 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(4)), Value((int)rollbackEnabled)));
164 mValues.push_back(
165 FieldValue(Field(mTagId, getSimpleField(5)), Value((int)requiresLowLatencyMonitor)));
166 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(6)), Value(state)));
167 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(7)), Value(experimentIds)));
168 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(8)), Value(userId)));
169}
170
Howard Roa46b6582018-09-18 16:45:02 -0700171LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
Chenjie Yu97dbb202019-02-13 16:42:04 -0800172 const InstallTrainInfo& trainInfo) {
173 mLogdTimestampNs = wallClockTimestampNs;
174 mElapsedTimestampNs = elapsedTimestampNs;
175 mTagId = android::util::TRAIN_INFO;
Muhammad Qureshif4ca8242019-03-01 09:20:15 -0800176
Chenjie Yu97dbb202019-02-13 16:42:04 -0800177 mValues.push_back(
178 FieldValue(Field(mTagId, getSimpleField(1)), Value(trainInfo.trainVersionCode)));
Jeff Hamiltonfa2f91c2019-03-22 00:25:02 -0400179 std::vector<uint8_t> experimentIdsProto;
180 writeExperimentIdsToProto(trainInfo.experimentIds, &experimentIdsProto);
181 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(2)), Value(experimentIdsProto)));
Muhammad Qureshif4ca8242019-03-01 09:20:15 -0800182 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(3)), Value(trainInfo.trainName)));
183 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(4)), Value(trainInfo.status)));
Chenjie Yu97dbb202019-02-13 16:42:04 -0800184}
185
Howard Ro1a2a3992018-10-22 22:51:57 -0700186LogEvent::LogEvent(int32_t tagId, int64_t timestampNs, int32_t uid) {
Yangster-mac330af582018-02-08 15:24:38 -0800187 mLogdTimestampNs = timestampNs;
188 mTagId = tagId;
Howard Ro1a2a3992018-10-22 22:51:57 -0700189 mLogUid = uid;
Yangster-mac330af582018-02-08 15:24:38 -0800190 mContext = create_android_logger(1937006964); // the event tag shared by all stats logs
191 if (mContext) {
192 android_log_write_int64(mContext, timestampNs);
Yao Chen80235402017-11-13 20:42:25 -0800193 android_log_write_int32(mContext, tagId);
194 }
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700195}
196
Yangster-mac20877162017-12-22 17:19:39 -0800197LogEvent::~LogEvent() {
198 if (mContext) {
Yao Chen48d75182018-01-23 09:40:48 -0800199 // This is for the case when LogEvent is created using the test interface
200 // but init() isn't called.
Yangster-mac20877162017-12-22 17:19:39 -0800201 android_log_destroy(&mContext);
Yao Chen80235402017-11-13 20:42:25 -0800202 }
203}
204
205bool LogEvent::write(int32_t value) {
206 if (mContext) {
207 return android_log_write_int32(mContext, value) >= 0;
208 }
209 return false;
210}
211
212bool LogEvent::write(uint32_t value) {
213 if (mContext) {
214 return android_log_write_int32(mContext, value) >= 0;
215 }
216 return false;
217}
218
Chenjie Yud9dfda72017-12-11 17:41:20 -0800219bool LogEvent::write(int64_t value) {
220 if (mContext) {
221 return android_log_write_int64(mContext, value) >= 0;
222 }
223 return false;
224}
225
Yao Chen80235402017-11-13 20:42:25 -0800226bool LogEvent::write(uint64_t value) {
227 if (mContext) {
228 return android_log_write_int64(mContext, value) >= 0;
229 }
230 return false;
231}
232
233bool LogEvent::write(const string& value) {
234 if (mContext) {
235 return android_log_write_string8_len(mContext, value.c_str(), value.length()) >= 0;
236 }
237 return false;
238}
239
240bool LogEvent::write(float value) {
241 if (mContext) {
242 return android_log_write_float32(mContext, value) >= 0;
243 }
244 return false;
245}
246
Tej Singha02bfab2019-10-01 19:03:24 -0700247bool LogEvent::writeBytes(const string& value) {
Ruchir Rastogi00763a32020-02-14 13:07:44 -0800248 /* if (mContext) {
Tej Singha02bfab2019-10-01 19:03:24 -0700249 return android_log_write_char_array(mContext, value.c_str(), value.length()) >= 0;
Ruchir Rastogi00763a32020-02-14 13:07:44 -0800250 }*/
Tej Singha02bfab2019-10-01 19:03:24 -0700251 return false;
252}
253
Howard Ro1a2a3992018-10-22 22:51:57 -0700254bool LogEvent::writeKeyValuePairs(int32_t uid,
255 const std::map<int32_t, int32_t>& int_map,
Howard Ro4078dd42018-09-27 17:41:08 -0700256 const std::map<int32_t, int64_t>& long_map,
Yangster-mace124e422018-08-16 10:30:28 -0700257 const std::map<int32_t, std::string>& string_map,
258 const std::map<int32_t, float>& float_map) {
259 if (mContext) {
260 if (android_log_write_list_begin(mContext) < 0) {
261 return false;
262 }
Howard Ro1a2a3992018-10-22 22:51:57 -0700263 write(uid);
Yangster-mace124e422018-08-16 10:30:28 -0700264 for (const auto& itr : int_map) {
265 if (android_log_write_list_begin(mContext) < 0) {
266 return false;
267 }
268 write(itr.first);
269 write(itr.second);
270 if (android_log_write_list_end(mContext) < 0) {
271 return false;
272 }
273 }
274
Howard Ro4078dd42018-09-27 17:41:08 -0700275 for (const auto& itr : long_map) {
276 if (android_log_write_list_begin(mContext) < 0) {
277 return false;
278 }
279 write(itr.first);
280 write(itr.second);
281 if (android_log_write_list_end(mContext) < 0) {
282 return false;
283 }
284 }
285
Yangster-mace124e422018-08-16 10:30:28 -0700286 for (const auto& itr : string_map) {
287 if (android_log_write_list_begin(mContext) < 0) {
288 return false;
289 }
290 write(itr.first);
291 write(itr.second.c_str());
292 if (android_log_write_list_end(mContext) < 0) {
293 return false;
294 }
295 }
296
297 for (const auto& itr : float_map) {
298 if (android_log_write_list_begin(mContext) < 0) {
299 return false;
300 }
301 write(itr.first);
302 write(itr.second);
303 if (android_log_write_list_end(mContext) < 0) {
304 return false;
305 }
306 }
307
308 if (android_log_write_list_end(mContext) < 0) {
309 return false;
310 }
311 return true;
312 }
313 return false;
314}
315
Yao Chen9c1debe2018-02-19 14:39:19 -0800316bool LogEvent::write(const std::vector<AttributionNodeInternal>& nodes) {
Yao Chen80235402017-11-13 20:42:25 -0800317 if (mContext) {
Yangster-mac20877162017-12-22 17:19:39 -0800318 if (android_log_write_list_begin(mContext) < 0) {
319 return false;
320 }
321 for (size_t i = 0; i < nodes.size(); ++i) {
322 if (!write(nodes[i])) {
323 return false;
324 }
325 }
326 if (android_log_write_list_end(mContext) < 0) {
327 return false;
328 }
329 return true;
330 }
331 return false;
332}
333
Yao Chen9c1debe2018-02-19 14:39:19 -0800334bool LogEvent::write(const AttributionNodeInternal& node) {
Yangster-mac20877162017-12-22 17:19:39 -0800335 if (mContext) {
336 if (android_log_write_list_begin(mContext) < 0) {
337 return false;
338 }
339 if (android_log_write_int32(mContext, node.uid()) < 0) {
340 return false;
341 }
342 if (android_log_write_string8(mContext, node.tag().c_str()) < 0) {
343 return false;
344 }
Yangster-mac20877162017-12-22 17:19:39 -0800345 if (android_log_write_list_end(mContext) < 0) {
346 return false;
347 }
348 return true;
349 }
350 return false;
351}
352
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800353void LogEvent::parseInt32(int32_t* pos, int32_t depth, bool* last) {
354 int32_t value = readNextValue<int32_t>();
355 addToValues(pos, depth, value, last);
356}
357
358void LogEvent::parseInt64(int32_t* pos, int32_t depth, bool* last) {
359 int64_t value = readNextValue<int64_t>();
360 addToValues(pos, depth, value, last);
361}
362
363void LogEvent::parseString(int32_t* pos, int32_t depth, bool* last) {
364 int32_t numBytes = readNextValue<int32_t>();
365 if ((uint32_t)numBytes > mRemainingLen) {
366 mValid = false;
367 return;
368 }
369
370 string value = string((char*)mBuf, numBytes);
371 mBuf += numBytes;
372 mRemainingLen -= numBytes;
373 addToValues(pos, depth, value, last);
374}
375
376void LogEvent::parseFloat(int32_t* pos, int32_t depth, bool* last) {
377 float value = readNextValue<float>();
378 addToValues(pos, depth, value, last);
379}
380
381void LogEvent::parseBool(int32_t* pos, int32_t depth, bool* last) {
382 // cast to int32_t because FieldValue does not support bools
383 int32_t value = (int32_t)readNextValue<uint8_t>();
384 addToValues(pos, depth, value, last);
385}
386
387void LogEvent::parseByteArray(int32_t* pos, int32_t depth, bool* last) {
388 int32_t numBytes = readNextValue<int32_t>();
389 if ((uint32_t)numBytes > mRemainingLen) {
390 mValid = false;
391 return;
392 }
393
394 vector<uint8_t> value(mBuf, mBuf + numBytes);
395 mBuf += numBytes;
396 mRemainingLen -= numBytes;
397 addToValues(pos, depth, value, last);
398}
399
400void LogEvent::parseKeyValuePairs(int32_t* pos, int32_t depth, bool* last) {
401 int32_t numPairs = readNextValue<uint8_t>();
402
403 for (pos[1] = 1; pos[1] <= numPairs; pos[1]++) {
404 last[1] = (pos[1] == numPairs);
405
406 // parse key
407 pos[2] = 1;
408 parseInt32(pos, 2, last);
409
410 // parse value
411 last[2] = true;
412 uint8_t typeId = getTypeId(readNextValue<uint8_t>());
413 switch (typeId) {
414 case INT32_TYPE:
415 pos[2] = 2; // pos[2] determined by index of type in KeyValuePair in atoms.proto
416 parseInt32(pos, 2, last);
417 break;
418 case INT64_TYPE:
419 pos[2] = 3;
420 parseInt64(pos, 2, last);
421 break;
422 case STRING_TYPE:
423 pos[2] = 4;
424 parseString(pos, 2, last);
425 break;
426 case FLOAT_TYPE:
427 pos[2] = 5;
428 parseFloat(pos, 2, last);
429 break;
430 default:
431 mValid = false;
432 }
433 }
434
435 pos[1] = pos[2] = 1;
436 last[1] = last[2] = false;
437}
438
439void LogEvent::parseAttributionChain(int32_t* pos, int32_t depth, bool* last) {
440 int32_t numNodes = readNextValue<uint8_t>();
441 for (pos[1] = 1; pos[1] <= numNodes; pos[1]++) {
442 last[1] = (pos[1] == numNodes);
443
444 // parse uid
445 pos[2] = 1;
446 parseInt32(pos, 2, last);
447
448 // parse tag
449 pos[2] = 2;
450 last[2] = true;
451 parseString(pos, 2, last);
452 }
453
454 pos[1] = pos[2] = 1;
455 last[1] = last[2] = false;
456}
457
458
459// This parsing logic is tied to the encoding scheme used in StatsEvent.java and
460// stats_event.c
Ruchir Rastogidfd63d42020-02-20 17:54:13 -0800461bool LogEvent::parseBuffer(uint8_t* buf, size_t len) {
462 mBuf = buf;
463 mRemainingLen = (uint32_t)len;
464
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800465 int32_t pos[] = {1, 1, 1};
466 bool last[] = {false, false, false};
467
468 // Beginning of buffer is OBJECT_TYPE | NUM_FIELDS | TIMESTAMP | ATOM_ID
469 uint8_t typeInfo = readNextValue<uint8_t>();
470 if (getTypeId(typeInfo) != OBJECT_TYPE) mValid = false;
471
472 uint8_t numElements = readNextValue<uint8_t>();
473 if (numElements < 2 || numElements > 127) mValid = false;
474
475 typeInfo = readNextValue<uint8_t>();
476 if (getTypeId(typeInfo) != INT64_TYPE) mValid = false;
477 mElapsedTimestampNs = readNextValue<int64_t>();
478 numElements--;
479
480 typeInfo = readNextValue<uint8_t>();
481 if (getTypeId(typeInfo) != INT32_TYPE) mValid = false;
482 mTagId = readNextValue<int32_t>();
483 numElements--;
484
485
486 for (pos[0] = 1; pos[0] <= numElements && mValid; pos[0]++) {
487 typeInfo = readNextValue<uint8_t>();
488 uint8_t typeId = getTypeId(typeInfo);
489
490 last[0] = (pos[0] == numElements);
491
492 // TODO(b/144373276): handle errors passed to the socket
493 // TODO(b/144373257): parse annotations
494 switch(typeId) {
495 case BOOL_TYPE:
496 parseBool(pos, 0, last);
497 break;
498 case INT32_TYPE:
499 parseInt32(pos, 0, last);
500 break;
501 case INT64_TYPE:
502 parseInt64(pos, 0, last);
503 break;
504 case FLOAT_TYPE:
505 parseFloat(pos, 0, last);
506 break;
507 case BYTE_ARRAY_TYPE:
508 parseByteArray(pos, 0, last);
509 break;
510 case STRING_TYPE:
511 parseString(pos, 0, last);
512 break;
513 case KEY_VALUE_PAIRS_TYPE:
514 parseKeyValuePairs(pos, 0, last);
515 break;
516 case ATTRIBUTION_CHAIN_TYPE:
517 parseAttributionChain(pos, 0, last);
518 break;
519 default:
520 mValid = false;
521 }
522 }
523
524 if (mRemainingLen != 0) mValid = false;
525 mBuf = nullptr;
Ruchir Rastogidfd63d42020-02-20 17:54:13 -0800526 return mValid;
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800527}
528
529uint8_t LogEvent::getTypeId(uint8_t typeInfo) {
530 return typeInfo & 0x0F; // type id in lower 4 bytes
531}
532
533uint8_t LogEvent::getNumAnnotations(uint8_t typeInfo) {
534 return (typeInfo >> 4) & 0x0F;
535}
536
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700537int64_t LogEvent::GetLong(size_t key, status_t* err) const {
Yao Chen5bfffb52018-06-21 16:58:51 -0700538 // TODO(b/110561208): encapsulate the magical operations in Field struct as static functions
Yao Chen8a8d16c2018-02-08 14:50:40 -0800539 int field = getSimpleField(key);
540 for (const auto& value : mValues) {
541 if (value.mField.getField() == field) {
Yao Chenab92a1f2018-02-13 15:17:55 -0800542 if (value.mValue.getType() == LONG) {
543 return value.mValue.long_value;
544 } else if (value.mValue.getType() == INT) {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800545 return value.mValue.int_value;
546 } else {
547 *err = BAD_TYPE;
548 return 0;
549 }
550 }
551 if ((size_t)value.mField.getPosAtDepth(0) > key) {
552 break;
Yangster-mac20877162017-12-22 17:19:39 -0800553 }
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700554 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800555
556 *err = BAD_INDEX;
557 return 0;
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700558}
559
Chenjie Yu80f91122018-01-31 20:24:50 -0800560int LogEvent::GetInt(size_t key, status_t* err) const {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800561 int field = getSimpleField(key);
562 for (const auto& value : mValues) {
563 if (value.mField.getField() == field) {
564 if (value.mValue.getType() == INT) {
565 return value.mValue.int_value;
566 } else {
567 *err = BAD_TYPE;
568 return 0;
569 }
570 }
571 if ((size_t)value.mField.getPosAtDepth(0) > key) {
572 break;
573 }
574 }
575
Chenjie Yu80f91122018-01-31 20:24:50 -0800576 *err = BAD_INDEX;
577 return 0;
Chenjie Yu80f91122018-01-31 20:24:50 -0800578}
579
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700580const char* LogEvent::GetString(size_t key, status_t* err) const {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800581 int field = getSimpleField(key);
582 for (const auto& value : mValues) {
583 if (value.mField.getField() == field) {
584 if (value.mValue.getType() == STRING) {
585 return value.mValue.str_value.c_str();
586 } else {
587 *err = BAD_TYPE;
588 return 0;
589 }
590 }
591 if ((size_t)value.mField.getPosAtDepth(0) > key) {
592 break;
Yangster-mac20877162017-12-22 17:19:39 -0800593 }
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700594 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800595
596 *err = BAD_INDEX;
597 return NULL;
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700598}
599
600bool LogEvent::GetBool(size_t key, status_t* err) const {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800601 int field = getSimpleField(key);
602 for (const auto& value : mValues) {
603 if (value.mField.getField() == field) {
604 if (value.mValue.getType() == INT) {
605 return value.mValue.int_value != 0;
606 } else if (value.mValue.getType() == LONG) {
607 return value.mValue.long_value != 0;
608 } else {
609 *err = BAD_TYPE;
610 return false;
611 }
612 }
613 if ((size_t)value.mField.getPosAtDepth(0) > key) {
614 break;
Yangster-mac20877162017-12-22 17:19:39 -0800615 }
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700616 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800617
618 *err = BAD_INDEX;
619 return false;
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700620}
621
622float LogEvent::GetFloat(size_t key, status_t* err) const {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800623 int field = getSimpleField(key);
624 for (const auto& value : mValues) {
625 if (value.mField.getField() == field) {
626 if (value.mValue.getType() == FLOAT) {
627 return value.mValue.float_value;
628 } else {
629 *err = BAD_TYPE;
630 return 0.0;
631 }
632 }
633 if ((size_t)value.mField.getPosAtDepth(0) > key) {
634 break;
Yangster-mac20877162017-12-22 17:19:39 -0800635 }
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700636 }
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700637
Yao Chen8a8d16c2018-02-08 14:50:40 -0800638 *err = BAD_INDEX;
639 return 0.0;
Yangster-macd40053e2018-01-09 16:29:22 -0800640}
641
Jonathan Nguyena0e6de12020-01-28 18:33:55 -0800642std::vector<uint8_t> LogEvent::GetStorage(size_t key, status_t* err) const {
643 int field = getSimpleField(key);
644 for (const auto& value : mValues) {
645 if (value.mField.getField() == field) {
646 if (value.mValue.getType() == STORAGE) {
647 return value.mValue.storage_value;
648 } else {
649 *err = BAD_TYPE;
650 return vector<uint8_t>();
651 }
652 }
653 if ((size_t)value.mField.getPosAtDepth(0) > key) {
654 break;
655 }
656 }
657
658 *err = BAD_INDEX;
659 return vector<uint8_t>();
660}
661
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700662string LogEvent::ToString() const {
Yao Chen20e9e622018-02-28 11:18:51 -0800663 string result;
Yao Chen8e6f9982018-11-29 09:39:45 -0800664 result += StringPrintf("{ uid(%d) %lld %lld (%d)", mLogUid, (long long)mLogdTimestampNs,
Yao Chen20e9e622018-02-28 11:18:51 -0800665 (long long)mElapsedTimestampNs, mTagId);
Yao Chen8a8d16c2018-02-08 14:50:40 -0800666 for (const auto& value : mValues) {
Yao Chen20e9e622018-02-28 11:18:51 -0800667 result +=
668 StringPrintf("%#x", value.mField.getField()) + "->" + value.mValue.toString() + " ";
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700669 }
Yao Chen20e9e622018-02-28 11:18:51 -0800670 result += " }";
671 return result;
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700672}
673
Yangster-mac20877162017-12-22 17:19:39 -0800674void LogEvent::ToProto(ProtoOutputStream& protoOutput) const {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800675 writeFieldValueTreeToStream(mTagId, getValues(), &protoOutput);
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700676}
677
Tej Singh9b4a5ec2019-04-25 12:43:35 -0700678void writeExperimentIdsToProto(const std::vector<int64_t>& experimentIds,
679 std::vector<uint8_t>* protoOut) {
Jeff Hamiltonfa2f91c2019-03-22 00:25:02 -0400680 ProtoOutputStream proto;
681 for (const auto& expId : experimentIds) {
682 proto.write(FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED | FIELD_ID_EXPERIMENT_ID,
683 (long long)expId);
684 }
685
686 protoOut->resize(proto.size());
687 size_t pos = 0;
688 sp<ProtoReader> reader = proto.data();
689 while (reader->readBuffer() != NULL) {
690 size_t toRead = reader->currentToRead();
691 std::memcpy(protoOut->data() + pos, reader->readBuffer(), toRead);
692 pos += toRead;
693 reader->move(toRead);
694 }
695}
696
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700697} // namespace statsd
698} // namespace os
699} // namespace android