blob: 3e46d131a813c1cb07811f38b6e61619948ab61c [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
Ruchir Rastogi1736ba42019-11-04 14:37:13 -080068// Msg is expected to begin at the start of the serialized atom -- it should not
69// include the android_log_header_t or the StatsEventTag.
Ruchir Rastogiab71ef02020-01-30 01:24:50 -080070LogEvent::LogEvent(uint8_t* msg, uint32_t len, int32_t uid, int32_t pid)
Ruchir Rastogi1736ba42019-11-04 14:37:13 -080071 : mBuf(msg),
72 mRemainingLen(len),
73 mLogdTimestampNs(time(nullptr)),
Ruchir Rastogiab71ef02020-01-30 01:24:50 -080074 mLogUid(uid),
75 mLogPid(pid)
Ruchir Rastogi1736ba42019-11-04 14:37:13 -080076{
Ruchir Rastogi1736ba42019-11-04 14:37:13 -080077 initNew();
Tej Singh89817632019-12-09 16:58:08 -080078}
79
Chenjie Yu0bd73db2018-12-16 07:37:04 -080080LogEvent::LogEvent(const LogEvent& event) {
81 mTagId = event.mTagId;
82 mLogUid = event.mLogUid;
Ruchir Rastogiab71ef02020-01-30 01:24:50 -080083 mLogPid = event.mLogPid;
Chenjie Yu0bd73db2018-12-16 07:37:04 -080084 mElapsedTimestampNs = event.mElapsedTimestampNs;
85 mLogdTimestampNs = event.mLogdTimestampNs;
86 mValues = event.mValues;
87}
88
Yangster-mac330af582018-02-08 15:24:38 -080089LogEvent::LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedTimestampNs) {
90 mLogdTimestampNs = wallClockTimestampNs;
Yao Chen0f861862019-03-27 11:51:15 -070091 mElapsedTimestampNs = elapsedTimestampNs;
Yao Chen80235402017-11-13 20:42:25 -080092 mTagId = tagId;
Yangster-mac20877162017-12-22 17:19:39 -080093 mLogUid = 0;
Yao Chen80235402017-11-13 20:42:25 -080094 mContext = create_android_logger(1937006964); // the event tag shared by all stats logs
95 if (mContext) {
Yangster-mac330af582018-02-08 15:24:38 -080096 android_log_write_int64(mContext, elapsedTimestampNs);
97 android_log_write_int32(mContext, tagId);
98 }
99}
100
Yangster-mac48b3d622018-08-18 12:38:11 -0700101LogEvent::LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
102 int32_t uid,
Howard Ro4078dd42018-09-27 17:41:08 -0700103 const std::map<int32_t, int32_t>& int_map,
104 const std::map<int32_t, int64_t>& long_map,
Yangster-mac48b3d622018-08-18 12:38:11 -0700105 const std::map<int32_t, std::string>& string_map,
106 const std::map<int32_t, float>& float_map) {
107 mLogdTimestampNs = wallClockTimestampNs;
108 mElapsedTimestampNs = elapsedTimestampNs;
109 mTagId = android::util::KEY_VALUE_PAIRS_ATOM;
110 mLogUid = uid;
111
112 int pos[] = {1, 1, 1};
113
114 mValues.push_back(FieldValue(Field(mTagId, pos, 0 /* depth */), Value(uid)));
115 pos[0]++;
116 for (const auto&itr : int_map) {
117 pos[2] = 1;
118 mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.first)));
119 pos[2] = 2;
120 mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.second)));
121 mValues.back().mField.decorateLastPos(2);
122 pos[1]++;
123 }
124
Howard Ro4078dd42018-09-27 17:41:08 -0700125 for (const auto&itr : long_map) {
Yangster-mac48b3d622018-08-18 12:38:11 -0700126 pos[2] = 1;
127 mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.first)));
128 pos[2] = 3;
129 mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.second)));
130 mValues.back().mField.decorateLastPos(2);
131 pos[1]++;
132 }
133
Howard Ro4078dd42018-09-27 17:41:08 -0700134 for (const auto&itr : string_map) {
Yangster-mac48b3d622018-08-18 12:38:11 -0700135 pos[2] = 1;
136 mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.first)));
137 pos[2] = 4;
138 mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.second)));
139 mValues.back().mField.decorateLastPos(2);
140 pos[1]++;
141 }
Howard Ro4078dd42018-09-27 17:41:08 -0700142
143 for (const auto&itr : float_map) {
144 pos[2] = 1;
145 mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.first)));
146 pos[2] = 5;
147 mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.second)));
148 mValues.back().mField.decorateLastPos(2);
149 pos[1]++;
150 }
Yangster-mac48b3d622018-08-18 12:38:11 -0700151 if (!mValues.empty()) {
152 mValues.back().mField.decorateLastPos(1);
153 mValues.at(mValues.size() - 2).mField.decorateLastPos(1);
154 }
155}
156
Chenjie Yu6b1667c2019-01-18 10:09:33 -0800157LogEvent::LogEvent(const string& trainName, int64_t trainVersionCode, bool requiresStaging,
158 bool rollbackEnabled, bool requiresLowLatencyMonitor, int32_t state,
159 const std::vector<uint8_t>& experimentIds, int32_t userId) {
160 mLogdTimestampNs = getWallClockNs();
161 mElapsedTimestampNs = getElapsedRealtimeNs();
162 mTagId = android::util::BINARY_PUSH_STATE_CHANGED;
Ruchir Rastogie449b0c2020-02-10 17:40:09 -0800163 mLogUid = AIBinder_getCallingUid();
164 mLogPid = AIBinder_getCallingPid();
Chenjie Yu6b1667c2019-01-18 10:09:33 -0800165
166 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(1)), Value(trainName)));
167 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(2)), Value(trainVersionCode)));
168 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(3)), Value((int)requiresStaging)));
169 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(4)), Value((int)rollbackEnabled)));
170 mValues.push_back(
171 FieldValue(Field(mTagId, getSimpleField(5)), Value((int)requiresLowLatencyMonitor)));
172 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(6)), Value(state)));
173 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(7)), Value(experimentIds)));
174 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(8)), Value(userId)));
175}
176
Howard Roa46b6582018-09-18 16:45:02 -0700177LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
Chenjie Yu97dbb202019-02-13 16:42:04 -0800178 const InstallTrainInfo& trainInfo) {
179 mLogdTimestampNs = wallClockTimestampNs;
180 mElapsedTimestampNs = elapsedTimestampNs;
181 mTagId = android::util::TRAIN_INFO;
Muhammad Qureshif4ca8242019-03-01 09:20:15 -0800182
Chenjie Yu97dbb202019-02-13 16:42:04 -0800183 mValues.push_back(
184 FieldValue(Field(mTagId, getSimpleField(1)), Value(trainInfo.trainVersionCode)));
Jeff Hamiltonfa2f91c2019-03-22 00:25:02 -0400185 std::vector<uint8_t> experimentIdsProto;
186 writeExperimentIdsToProto(trainInfo.experimentIds, &experimentIdsProto);
187 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(2)), Value(experimentIdsProto)));
Muhammad Qureshif4ca8242019-03-01 09:20:15 -0800188 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(3)), Value(trainInfo.trainName)));
189 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(4)), Value(trainInfo.status)));
Chenjie Yu97dbb202019-02-13 16:42:04 -0800190}
191
Yao Chen0f861862019-03-27 11:51:15 -0700192LogEvent::LogEvent(int32_t tagId, int64_t timestampNs) : LogEvent(tagId, timestampNs, timestampNs) {
193}
Howard Ro1a2a3992018-10-22 22:51:57 -0700194
195LogEvent::LogEvent(int32_t tagId, int64_t timestampNs, int32_t uid) {
Yangster-mac330af582018-02-08 15:24:38 -0800196 mLogdTimestampNs = timestampNs;
197 mTagId = tagId;
Howard Ro1a2a3992018-10-22 22:51:57 -0700198 mLogUid = uid;
Yangster-mac330af582018-02-08 15:24:38 -0800199 mContext = create_android_logger(1937006964); // the event tag shared by all stats logs
200 if (mContext) {
201 android_log_write_int64(mContext, timestampNs);
Yao Chen80235402017-11-13 20:42:25 -0800202 android_log_write_int32(mContext, tagId);
203 }
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700204}
205
Yangster-mac20877162017-12-22 17:19:39 -0800206LogEvent::~LogEvent() {
207 if (mContext) {
Yao Chen48d75182018-01-23 09:40:48 -0800208 // This is for the case when LogEvent is created using the test interface
209 // but init() isn't called.
Yangster-mac20877162017-12-22 17:19:39 -0800210 android_log_destroy(&mContext);
Yao Chen80235402017-11-13 20:42:25 -0800211 }
212}
213
214bool LogEvent::write(int32_t value) {
215 if (mContext) {
216 return android_log_write_int32(mContext, value) >= 0;
217 }
218 return false;
219}
220
221bool LogEvent::write(uint32_t value) {
222 if (mContext) {
223 return android_log_write_int32(mContext, value) >= 0;
224 }
225 return false;
226}
227
Chenjie Yud9dfda72017-12-11 17:41:20 -0800228bool LogEvent::write(int64_t value) {
229 if (mContext) {
230 return android_log_write_int64(mContext, value) >= 0;
231 }
232 return false;
233}
234
Yao Chen80235402017-11-13 20:42:25 -0800235bool LogEvent::write(uint64_t value) {
236 if (mContext) {
237 return android_log_write_int64(mContext, value) >= 0;
238 }
239 return false;
240}
241
242bool LogEvent::write(const string& value) {
243 if (mContext) {
244 return android_log_write_string8_len(mContext, value.c_str(), value.length()) >= 0;
245 }
246 return false;
247}
248
249bool LogEvent::write(float value) {
250 if (mContext) {
251 return android_log_write_float32(mContext, value) >= 0;
252 }
253 return false;
254}
255
Tej Singha02bfab2019-10-01 19:03:24 -0700256bool LogEvent::writeBytes(const string& value) {
Ruchir Rastogi00763a32020-02-14 13:07:44 -0800257 /* if (mContext) {
Tej Singha02bfab2019-10-01 19:03:24 -0700258 return android_log_write_char_array(mContext, value.c_str(), value.length()) >= 0;
Ruchir Rastogi00763a32020-02-14 13:07:44 -0800259 }*/
Tej Singha02bfab2019-10-01 19:03:24 -0700260 return false;
261}
262
Howard Ro1a2a3992018-10-22 22:51:57 -0700263bool LogEvent::writeKeyValuePairs(int32_t uid,
264 const std::map<int32_t, int32_t>& int_map,
Howard Ro4078dd42018-09-27 17:41:08 -0700265 const std::map<int32_t, int64_t>& long_map,
Yangster-mace124e422018-08-16 10:30:28 -0700266 const std::map<int32_t, std::string>& string_map,
267 const std::map<int32_t, float>& float_map) {
268 if (mContext) {
269 if (android_log_write_list_begin(mContext) < 0) {
270 return false;
271 }
Howard Ro1a2a3992018-10-22 22:51:57 -0700272 write(uid);
Yangster-mace124e422018-08-16 10:30:28 -0700273 for (const auto& itr : int_map) {
274 if (android_log_write_list_begin(mContext) < 0) {
275 return false;
276 }
277 write(itr.first);
278 write(itr.second);
279 if (android_log_write_list_end(mContext) < 0) {
280 return false;
281 }
282 }
283
Howard Ro4078dd42018-09-27 17:41:08 -0700284 for (const auto& itr : long_map) {
285 if (android_log_write_list_begin(mContext) < 0) {
286 return false;
287 }
288 write(itr.first);
289 write(itr.second);
290 if (android_log_write_list_end(mContext) < 0) {
291 return false;
292 }
293 }
294
Yangster-mace124e422018-08-16 10:30:28 -0700295 for (const auto& itr : string_map) {
296 if (android_log_write_list_begin(mContext) < 0) {
297 return false;
298 }
299 write(itr.first);
300 write(itr.second.c_str());
301 if (android_log_write_list_end(mContext) < 0) {
302 return false;
303 }
304 }
305
306 for (const auto& itr : float_map) {
307 if (android_log_write_list_begin(mContext) < 0) {
308 return false;
309 }
310 write(itr.first);
311 write(itr.second);
312 if (android_log_write_list_end(mContext) < 0) {
313 return false;
314 }
315 }
316
317 if (android_log_write_list_end(mContext) < 0) {
318 return false;
319 }
320 return true;
321 }
322 return false;
323}
324
Yao Chen9c1debe2018-02-19 14:39:19 -0800325bool LogEvent::write(const std::vector<AttributionNodeInternal>& nodes) {
Yao Chen80235402017-11-13 20:42:25 -0800326 if (mContext) {
Yangster-mac20877162017-12-22 17:19:39 -0800327 if (android_log_write_list_begin(mContext) < 0) {
328 return false;
329 }
330 for (size_t i = 0; i < nodes.size(); ++i) {
331 if (!write(nodes[i])) {
332 return false;
333 }
334 }
335 if (android_log_write_list_end(mContext) < 0) {
336 return false;
337 }
338 return true;
339 }
340 return false;
341}
342
Yao Chen9c1debe2018-02-19 14:39:19 -0800343bool LogEvent::write(const AttributionNodeInternal& node) {
Yangster-mac20877162017-12-22 17:19:39 -0800344 if (mContext) {
345 if (android_log_write_list_begin(mContext) < 0) {
346 return false;
347 }
348 if (android_log_write_int32(mContext, node.uid()) < 0) {
349 return false;
350 }
351 if (android_log_write_string8(mContext, node.tag().c_str()) < 0) {
352 return false;
353 }
Yangster-mac20877162017-12-22 17:19:39 -0800354 if (android_log_write_list_end(mContext) < 0) {
355 return false;
356 }
357 return true;
358 }
359 return false;
360}
361
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800362void LogEvent::parseInt32(int32_t* pos, int32_t depth, bool* last) {
363 int32_t value = readNextValue<int32_t>();
364 addToValues(pos, depth, value, last);
365}
366
367void LogEvent::parseInt64(int32_t* pos, int32_t depth, bool* last) {
368 int64_t value = readNextValue<int64_t>();
369 addToValues(pos, depth, value, last);
370}
371
372void LogEvent::parseString(int32_t* pos, int32_t depth, bool* last) {
373 int32_t numBytes = readNextValue<int32_t>();
374 if ((uint32_t)numBytes > mRemainingLen) {
375 mValid = false;
376 return;
377 }
378
379 string value = string((char*)mBuf, numBytes);
380 mBuf += numBytes;
381 mRemainingLen -= numBytes;
382 addToValues(pos, depth, value, last);
383}
384
385void LogEvent::parseFloat(int32_t* pos, int32_t depth, bool* last) {
386 float value = readNextValue<float>();
387 addToValues(pos, depth, value, last);
388}
389
390void LogEvent::parseBool(int32_t* pos, int32_t depth, bool* last) {
391 // cast to int32_t because FieldValue does not support bools
392 int32_t value = (int32_t)readNextValue<uint8_t>();
393 addToValues(pos, depth, value, last);
394}
395
396void LogEvent::parseByteArray(int32_t* pos, int32_t depth, bool* last) {
397 int32_t numBytes = readNextValue<int32_t>();
398 if ((uint32_t)numBytes > mRemainingLen) {
399 mValid = false;
400 return;
401 }
402
403 vector<uint8_t> value(mBuf, mBuf + numBytes);
404 mBuf += numBytes;
405 mRemainingLen -= numBytes;
406 addToValues(pos, depth, value, last);
407}
408
409void LogEvent::parseKeyValuePairs(int32_t* pos, int32_t depth, bool* last) {
410 int32_t numPairs = readNextValue<uint8_t>();
411
412 for (pos[1] = 1; pos[1] <= numPairs; pos[1]++) {
413 last[1] = (pos[1] == numPairs);
414
415 // parse key
416 pos[2] = 1;
417 parseInt32(pos, 2, last);
418
419 // parse value
420 last[2] = true;
421 uint8_t typeId = getTypeId(readNextValue<uint8_t>());
422 switch (typeId) {
423 case INT32_TYPE:
424 pos[2] = 2; // pos[2] determined by index of type in KeyValuePair in atoms.proto
425 parseInt32(pos, 2, last);
426 break;
427 case INT64_TYPE:
428 pos[2] = 3;
429 parseInt64(pos, 2, last);
430 break;
431 case STRING_TYPE:
432 pos[2] = 4;
433 parseString(pos, 2, last);
434 break;
435 case FLOAT_TYPE:
436 pos[2] = 5;
437 parseFloat(pos, 2, last);
438 break;
439 default:
440 mValid = false;
441 }
442 }
443
444 pos[1] = pos[2] = 1;
445 last[1] = last[2] = false;
446}
447
448void LogEvent::parseAttributionChain(int32_t* pos, int32_t depth, bool* last) {
449 int32_t numNodes = readNextValue<uint8_t>();
450 for (pos[1] = 1; pos[1] <= numNodes; pos[1]++) {
451 last[1] = (pos[1] == numNodes);
452
453 // parse uid
454 pos[2] = 1;
455 parseInt32(pos, 2, last);
456
457 // parse tag
458 pos[2] = 2;
459 last[2] = true;
460 parseString(pos, 2, last);
461 }
462
463 pos[1] = pos[2] = 1;
464 last[1] = last[2] = false;
465}
466
467
468// This parsing logic is tied to the encoding scheme used in StatsEvent.java and
469// stats_event.c
470void LogEvent::initNew() {
471 int32_t pos[] = {1, 1, 1};
472 bool last[] = {false, false, false};
473
474 // Beginning of buffer is OBJECT_TYPE | NUM_FIELDS | TIMESTAMP | ATOM_ID
475 uint8_t typeInfo = readNextValue<uint8_t>();
476 if (getTypeId(typeInfo) != OBJECT_TYPE) mValid = false;
477
478 uint8_t numElements = readNextValue<uint8_t>();
479 if (numElements < 2 || numElements > 127) mValid = false;
480
481 typeInfo = readNextValue<uint8_t>();
482 if (getTypeId(typeInfo) != INT64_TYPE) mValid = false;
483 mElapsedTimestampNs = readNextValue<int64_t>();
484 numElements--;
485
486 typeInfo = readNextValue<uint8_t>();
487 if (getTypeId(typeInfo) != INT32_TYPE) mValid = false;
488 mTagId = readNextValue<int32_t>();
489 numElements--;
490
491
492 for (pos[0] = 1; pos[0] <= numElements && mValid; pos[0]++) {
493 typeInfo = readNextValue<uint8_t>();
494 uint8_t typeId = getTypeId(typeInfo);
495
496 last[0] = (pos[0] == numElements);
497
498 // TODO(b/144373276): handle errors passed to the socket
499 // TODO(b/144373257): parse annotations
500 switch(typeId) {
501 case BOOL_TYPE:
502 parseBool(pos, 0, last);
503 break;
504 case INT32_TYPE:
505 parseInt32(pos, 0, last);
506 break;
507 case INT64_TYPE:
508 parseInt64(pos, 0, last);
509 break;
510 case FLOAT_TYPE:
511 parseFloat(pos, 0, last);
512 break;
513 case BYTE_ARRAY_TYPE:
514 parseByteArray(pos, 0, last);
515 break;
516 case STRING_TYPE:
517 parseString(pos, 0, last);
518 break;
519 case KEY_VALUE_PAIRS_TYPE:
520 parseKeyValuePairs(pos, 0, last);
521 break;
522 case ATTRIBUTION_CHAIN_TYPE:
523 parseAttributionChain(pos, 0, last);
524 break;
525 default:
526 mValid = false;
527 }
528 }
529
530 if (mRemainingLen != 0) mValid = false;
531 mBuf = nullptr;
532}
533
534uint8_t LogEvent::getTypeId(uint8_t typeInfo) {
535 return typeInfo & 0x0F; // type id in lower 4 bytes
536}
537
538uint8_t LogEvent::getNumAnnotations(uint8_t typeInfo) {
539 return (typeInfo >> 4) & 0x0F;
540}
541
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700542int64_t LogEvent::GetLong(size_t key, status_t* err) const {
Yao Chen5bfffb52018-06-21 16:58:51 -0700543 // TODO(b/110561208): encapsulate the magical operations in Field struct as static functions
Yao Chen8a8d16c2018-02-08 14:50:40 -0800544 int field = getSimpleField(key);
545 for (const auto& value : mValues) {
546 if (value.mField.getField() == field) {
Yao Chenab92a1f2018-02-13 15:17:55 -0800547 if (value.mValue.getType() == LONG) {
548 return value.mValue.long_value;
549 } else if (value.mValue.getType() == INT) {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800550 return value.mValue.int_value;
551 } else {
552 *err = BAD_TYPE;
553 return 0;
554 }
555 }
556 if ((size_t)value.mField.getPosAtDepth(0) > key) {
557 break;
Yangster-mac20877162017-12-22 17:19:39 -0800558 }
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700559 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800560
561 *err = BAD_INDEX;
562 return 0;
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700563}
564
Chenjie Yu80f91122018-01-31 20:24:50 -0800565int LogEvent::GetInt(size_t key, status_t* err) const {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800566 int field = getSimpleField(key);
567 for (const auto& value : mValues) {
568 if (value.mField.getField() == field) {
569 if (value.mValue.getType() == INT) {
570 return value.mValue.int_value;
571 } else {
572 *err = BAD_TYPE;
573 return 0;
574 }
575 }
576 if ((size_t)value.mField.getPosAtDepth(0) > key) {
577 break;
578 }
579 }
580
Chenjie Yu80f91122018-01-31 20:24:50 -0800581 *err = BAD_INDEX;
582 return 0;
Chenjie Yu80f91122018-01-31 20:24:50 -0800583}
584
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700585const char* LogEvent::GetString(size_t key, status_t* err) const {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800586 int field = getSimpleField(key);
587 for (const auto& value : mValues) {
588 if (value.mField.getField() == field) {
589 if (value.mValue.getType() == STRING) {
590 return value.mValue.str_value.c_str();
591 } else {
592 *err = BAD_TYPE;
593 return 0;
594 }
595 }
596 if ((size_t)value.mField.getPosAtDepth(0) > key) {
597 break;
Yangster-mac20877162017-12-22 17:19:39 -0800598 }
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700599 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800600
601 *err = BAD_INDEX;
602 return NULL;
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700603}
604
605bool LogEvent::GetBool(size_t key, status_t* err) const {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800606 int field = getSimpleField(key);
607 for (const auto& value : mValues) {
608 if (value.mField.getField() == field) {
609 if (value.mValue.getType() == INT) {
610 return value.mValue.int_value != 0;
611 } else if (value.mValue.getType() == LONG) {
612 return value.mValue.long_value != 0;
613 } else {
614 *err = BAD_TYPE;
615 return false;
616 }
617 }
618 if ((size_t)value.mField.getPosAtDepth(0) > key) {
619 break;
Yangster-mac20877162017-12-22 17:19:39 -0800620 }
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700621 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800622
623 *err = BAD_INDEX;
624 return false;
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700625}
626
627float LogEvent::GetFloat(size_t key, status_t* err) const {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800628 int field = getSimpleField(key);
629 for (const auto& value : mValues) {
630 if (value.mField.getField() == field) {
631 if (value.mValue.getType() == FLOAT) {
632 return value.mValue.float_value;
633 } else {
634 *err = BAD_TYPE;
635 return 0.0;
636 }
637 }
638 if ((size_t)value.mField.getPosAtDepth(0) > key) {
639 break;
Yangster-mac20877162017-12-22 17:19:39 -0800640 }
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700641 }
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700642
Yao Chen8a8d16c2018-02-08 14:50:40 -0800643 *err = BAD_INDEX;
644 return 0.0;
Yangster-macd40053e2018-01-09 16:29:22 -0800645}
646
Jonathan Nguyena0e6de12020-01-28 18:33:55 -0800647std::vector<uint8_t> LogEvent::GetStorage(size_t key, status_t* err) const {
648 int field = getSimpleField(key);
649 for (const auto& value : mValues) {
650 if (value.mField.getField() == field) {
651 if (value.mValue.getType() == STORAGE) {
652 return value.mValue.storage_value;
653 } else {
654 *err = BAD_TYPE;
655 return vector<uint8_t>();
656 }
657 }
658 if ((size_t)value.mField.getPosAtDepth(0) > key) {
659 break;
660 }
661 }
662
663 *err = BAD_INDEX;
664 return vector<uint8_t>();
665}
666
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700667string LogEvent::ToString() const {
Yao Chen20e9e622018-02-28 11:18:51 -0800668 string result;
Yao Chen8e6f9982018-11-29 09:39:45 -0800669 result += StringPrintf("{ uid(%d) %lld %lld (%d)", mLogUid, (long long)mLogdTimestampNs,
Yao Chen20e9e622018-02-28 11:18:51 -0800670 (long long)mElapsedTimestampNs, mTagId);
Yao Chen8a8d16c2018-02-08 14:50:40 -0800671 for (const auto& value : mValues) {
Yao Chen20e9e622018-02-28 11:18:51 -0800672 result +=
673 StringPrintf("%#x", value.mField.getField()) + "->" + value.mValue.toString() + " ";
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700674 }
Yao Chen20e9e622018-02-28 11:18:51 -0800675 result += " }";
676 return result;
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700677}
678
Yangster-mac20877162017-12-22 17:19:39 -0800679void LogEvent::ToProto(ProtoOutputStream& protoOutput) const {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800680 writeFieldValueTreeToStream(mTagId, getValues(), &protoOutput);
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700681}
682
Tej Singh9b4a5ec2019-04-25 12:43:35 -0700683void writeExperimentIdsToProto(const std::vector<int64_t>& experimentIds,
684 std::vector<uint8_t>* protoOut) {
Jeff Hamiltonfa2f91c2019-03-22 00:25:02 -0400685 ProtoOutputStream proto;
686 for (const auto& expId : experimentIds) {
687 proto.write(FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED | FIELD_ID_EXPERIMENT_ID,
688 (long long)expId);
689 }
690
691 protoOut->resize(proto.size());
692 size_t pos = 0;
693 sp<ProtoReader> reader = proto.data();
694 while (reader->readBuffer() != NULL) {
695 size_t toRead = reader->currentToRead();
696 std::memcpy(protoOut->data() + pos, reader->readBuffer(), toRead);
697 pos += toRead;
698 reader->move(toRead);
699 }
700}
701
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700702} // namespace statsd
703} // namespace os
704} // namespace android