blob: f56fa6221bc99666d1466196b1ebfb02b92adeb7 [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
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -070020#include <android-base/stringprintf.h>
21#include <android/binder_ibinder.h>
22#include <private/android_filesystem_config.h>
23
Ruchir Rastogi13296512020-03-24 10:59:49 -070024#include "annotations.h"
Yangster-mac20877162017-12-22 17:19:39 -080025#include "stats_log_util.h"
Jeffrey Huang74fc4352020-03-06 15:18:33 -080026#include "statslog_statsd.h"
Joe Onoratoc4dfae52017-10-17 23:38:21 -070027
28namespace android {
29namespace os {
30namespace statsd {
31
Jeff Hamiltonfa2f91c2019-03-22 00:25:02 -040032// for TrainInfo experiment id serialization
33const int FIELD_ID_EXPERIMENT_ID = 1;
34
yro24809bd2017-10-31 23:06:53 -070035using namespace android::util;
Ruchir Rastogie449b0c2020-02-10 17:40:09 -080036using android::base::StringPrintf;
Yao Chen9c1debe2018-02-19 14:39:19 -080037using android::util::ProtoOutputStream;
David Chen1481fe12017-10-16 13:16:34 -070038using std::string;
Yao Chen9c1debe2018-02-19 14:39:19 -080039using std::vector;
Joe Onoratoc4dfae52017-10-17 23:38:21 -070040
Tej Singhb26d0442020-01-31 16:18:21 -080041// stats_event.h socket types. Keep in sync.
42/* ERRORS */
43#define ERROR_NO_TIMESTAMP 0x1
44#define ERROR_NO_ATOM_ID 0x2
45#define ERROR_OVERFLOW 0x4
46#define ERROR_ATTRIBUTION_CHAIN_TOO_LONG 0x8
47#define ERROR_TOO_MANY_KEY_VALUE_PAIRS 0x10
48#define ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD 0x20
49#define ERROR_INVALID_ANNOTATION_ID 0x40
50#define ERROR_ANNOTATION_ID_TOO_LARGE 0x80
51#define ERROR_TOO_MANY_ANNOTATIONS 0x100
52#define ERROR_TOO_MANY_FIELDS 0x200
53#define ERROR_INVALID_VALUE_TYPE 0x400
54#define ERROR_STRING_NOT_NULL_TERMINATED 0x800
55
56/* TYPE IDS */
57#define INT32_TYPE 0x00
58#define INT64_TYPE 0x01
59#define STRING_TYPE 0x02
60#define LIST_TYPE 0x03
61#define FLOAT_TYPE 0x04
62#define BOOL_TYPE 0x05
63#define BYTE_ARRAY_TYPE 0x06
64#define OBJECT_TYPE 0x07
65#define KEY_VALUE_PAIRS_TYPE 0x08
66#define ATTRIBUTION_CHAIN_TYPE 0x09
67#define ERROR_TYPE 0x0F
68
Ruchir Rastogidfd63d42020-02-20 17:54:13 -080069LogEvent::LogEvent(int32_t uid, int32_t pid)
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -070070 : mLogdTimestampNs(time(nullptr)), mLogUid(uid), mLogPid(pid) {
Ruchir Rastogidfd63d42020-02-20 17:54:13 -080071}
72
Chenjie Yu6b1667c2019-01-18 10:09:33 -080073LogEvent::LogEvent(const string& trainName, int64_t trainVersionCode, bool requiresStaging,
74 bool rollbackEnabled, bool requiresLowLatencyMonitor, int32_t state,
75 const std::vector<uint8_t>& experimentIds, int32_t userId) {
76 mLogdTimestampNs = getWallClockNs();
77 mElapsedTimestampNs = getElapsedRealtimeNs();
Jeffrey Huang74fc4352020-03-06 15:18:33 -080078 mTagId = util::BINARY_PUSH_STATE_CHANGED;
Ruchir Rastogie449b0c2020-02-10 17:40:09 -080079 mLogUid = AIBinder_getCallingUid();
80 mLogPid = AIBinder_getCallingPid();
Chenjie Yu6b1667c2019-01-18 10:09:33 -080081
82 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(1)), Value(trainName)));
83 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(2)), Value(trainVersionCode)));
84 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(3)), Value((int)requiresStaging)));
85 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(4)), Value((int)rollbackEnabled)));
86 mValues.push_back(
87 FieldValue(Field(mTagId, getSimpleField(5)), Value((int)requiresLowLatencyMonitor)));
88 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(6)), Value(state)));
89 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(7)), Value(experimentIds)));
90 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(8)), Value(userId)));
91}
92
Howard Roa46b6582018-09-18 16:45:02 -070093LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
Chenjie Yu97dbb202019-02-13 16:42:04 -080094 const InstallTrainInfo& trainInfo) {
95 mLogdTimestampNs = wallClockTimestampNs;
96 mElapsedTimestampNs = elapsedTimestampNs;
Jeffrey Huang74fc4352020-03-06 15:18:33 -080097 mTagId = util::TRAIN_INFO;
Muhammad Qureshif4ca8242019-03-01 09:20:15 -080098
Chenjie Yu97dbb202019-02-13 16:42:04 -080099 mValues.push_back(
100 FieldValue(Field(mTagId, getSimpleField(1)), Value(trainInfo.trainVersionCode)));
Jeff Hamiltonfa2f91c2019-03-22 00:25:02 -0400101 std::vector<uint8_t> experimentIdsProto;
102 writeExperimentIdsToProto(trainInfo.experimentIds, &experimentIdsProto);
103 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(2)), Value(experimentIdsProto)));
Muhammad Qureshif4ca8242019-03-01 09:20:15 -0800104 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(3)), Value(trainInfo.trainName)));
105 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(4)), Value(trainInfo.status)));
Chenjie Yu97dbb202019-02-13 16:42:04 -0800106}
107
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700108void LogEvent::parseInt32(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800109 int32_t value = readNextValue<int32_t>();
110 addToValues(pos, depth, value, last);
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700111 parseAnnotations(numAnnotations);
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800112}
113
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700114void LogEvent::parseInt64(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800115 int64_t value = readNextValue<int64_t>();
116 addToValues(pos, depth, value, last);
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700117 parseAnnotations(numAnnotations);
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800118}
119
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700120void LogEvent::parseString(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800121 int32_t numBytes = readNextValue<int32_t>();
122 if ((uint32_t)numBytes > mRemainingLen) {
123 mValid = false;
124 return;
125 }
126
127 string value = string((char*)mBuf, numBytes);
128 mBuf += numBytes;
129 mRemainingLen -= numBytes;
130 addToValues(pos, depth, value, last);
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700131 parseAnnotations(numAnnotations);
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800132}
133
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700134void LogEvent::parseFloat(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800135 float value = readNextValue<float>();
136 addToValues(pos, depth, value, last);
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700137 parseAnnotations(numAnnotations);
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800138}
139
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700140void LogEvent::parseBool(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800141 // cast to int32_t because FieldValue does not support bools
142 int32_t value = (int32_t)readNextValue<uint8_t>();
143 addToValues(pos, depth, value, last);
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700144 parseAnnotations(numAnnotations);
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800145}
146
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700147void LogEvent::parseByteArray(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800148 int32_t numBytes = readNextValue<int32_t>();
149 if ((uint32_t)numBytes > mRemainingLen) {
150 mValid = false;
151 return;
152 }
153
154 vector<uint8_t> value(mBuf, mBuf + numBytes);
155 mBuf += numBytes;
156 mRemainingLen -= numBytes;
157 addToValues(pos, depth, value, last);
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700158 parseAnnotations(numAnnotations);
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800159}
160
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700161void LogEvent::parseKeyValuePairs(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800162 int32_t numPairs = readNextValue<uint8_t>();
163
164 for (pos[1] = 1; pos[1] <= numPairs; pos[1]++) {
165 last[1] = (pos[1] == numPairs);
166
167 // parse key
168 pos[2] = 1;
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700169 parseInt32(pos, /*depth=*/2, last, /*numAnnotations=*/0);
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800170
171 // parse value
172 last[2] = true;
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700173
174 uint8_t typeInfo = readNextValue<uint8_t>();
175 switch (getTypeId(typeInfo)) {
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800176 case INT32_TYPE:
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700177 pos[2] = 2; // pos[2] determined by index of type in KeyValuePair in atoms.proto
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700178 parseInt32(pos, /*depth=*/2, last, /*numAnnotations=*/0);
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800179 break;
180 case INT64_TYPE:
181 pos[2] = 3;
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700182 parseInt64(pos, /*depth=*/2, last, /*numAnnotations=*/0);
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800183 break;
184 case STRING_TYPE:
185 pos[2] = 4;
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700186 parseString(pos, /*depth=*/2, last, /*numAnnotations=*/0);
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800187 break;
188 case FLOAT_TYPE:
189 pos[2] = 5;
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700190 parseFloat(pos, /*depth=*/2, last, /*numAnnotations=*/0);
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800191 break;
192 default:
193 mValid = false;
194 }
195 }
196
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700197 parseAnnotations(numAnnotations);
198
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800199 pos[1] = pos[2] = 1;
200 last[1] = last[2] = false;
201}
202
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700203void LogEvent::parseAttributionChain(int32_t* pos, int32_t depth, bool* last,
204 uint8_t numAnnotations) {
Muhammad Qureshi83aaa662020-04-21 12:51:36 -0700205 const unsigned int firstUidInChainIndex = mValues.size();
206 const int32_t numNodes = readNextValue<uint8_t>();
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800207 for (pos[1] = 1; pos[1] <= numNodes; pos[1]++) {
208 last[1] = (pos[1] == numNodes);
209
210 // parse uid
211 pos[2] = 1;
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700212 parseInt32(pos, /*depth=*/2, last, /*numAnnotations=*/0);
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800213
214 // parse tag
215 pos[2] = 2;
216 last[2] = true;
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700217 parseString(pos, /*depth=*/2, last, /*numAnnotations=*/0);
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800218 }
Muhammad Qureshi83aaa662020-04-21 12:51:36 -0700219 // Check if at least one node was successfully parsed.
220 if (mValues.size() - 1 > firstUidInChainIndex) {
Ruchir Rastogi1e8c57f2020-04-27 17:41:58 -0700221 mAttributionChainStartIndex = static_cast<int8_t>(firstUidInChainIndex);
222 mAttributionChainEndIndex = static_cast<int8_t>(mValues.size() - 1);
Muhammad Qureshi83aaa662020-04-21 12:51:36 -0700223 }
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800224
Ruchir Rastogi13296512020-03-24 10:59:49 -0700225 parseAnnotations(numAnnotations, firstUidInChainIndex);
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700226
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800227 pos[1] = pos[2] = 1;
228 last[1] = last[2] = false;
229}
230
Ruchir Rastogiffa34f02020-04-04 15:30:11 -0700231// Assumes that mValues is not empty
232bool LogEvent::checkPreviousValueType(Type expected) {
233 return mValues[mValues.size() - 1].mValue.getType() == expected;
234}
235
Ruchir Rastogi13296512020-03-24 10:59:49 -0700236void LogEvent::parseIsUidAnnotation(uint8_t annotationType) {
Ruchir Rastogiffa34f02020-04-04 15:30:11 -0700237 if (mValues.empty() || !checkPreviousValueType(INT) || annotationType != BOOL_TYPE) {
Ruchir Rastogi13296512020-03-24 10:59:49 -0700238 mValid = false;
239 return;
240 }
241
242 bool isUid = readNextValue<uint8_t>();
Ruchir Rastogi1e8c57f2020-04-27 17:41:58 -0700243 if (isUid) mUidFieldIndex = static_cast<int8_t>(mValues.size() - 1);
Ruchir Rastogiffa34f02020-04-04 15:30:11 -0700244 mValues[mValues.size() - 1].mAnnotations.setUidField(isUid);
Ruchir Rastogi13296512020-03-24 10:59:49 -0700245}
246
247void LogEvent::parseTruncateTimestampAnnotation(uint8_t annotationType) {
248 if (!mValues.empty() || annotationType != BOOL_TYPE) {
249 mValid = false;
250 return;
251 }
252
253 mTruncateTimestamp = readNextValue<uint8_t>();
254}
255
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700256void LogEvent::parsePrimaryFieldAnnotation(uint8_t annotationType) {
257 if (mValues.empty() || annotationType != BOOL_TYPE) {
Ruchir Rastogi13296512020-03-24 10:59:49 -0700258 mValid = false;
259 return;
260 }
261
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700262 const bool primaryField = readNextValue<uint8_t>();
263 mValues[mValues.size() - 1].mAnnotations.setPrimaryField(primaryField);
Ruchir Rastogi13296512020-03-24 10:59:49 -0700264}
265
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700266void LogEvent::parsePrimaryFieldFirstUidAnnotation(uint8_t annotationType,
267 int firstUidInChainIndex) {
268 if (mValues.empty() || annotationType != BOOL_TYPE || -1 == firstUidInChainIndex) {
269 mValid = false;
270 return;
271 }
272
273 const bool primaryField = readNextValue<uint8_t>();
274 mValues[firstUidInChainIndex].mAnnotations.setPrimaryField(primaryField);
275}
276
277void LogEvent::parseExclusiveStateAnnotation(uint8_t annotationType) {
278 if (mValues.empty() || annotationType != BOOL_TYPE) {
279 mValid = false;
280 return;
281 }
282
283 const bool exclusiveState = readNextValue<uint8_t>();
Ruchir Rastogi1e8c57f2020-04-27 17:41:58 -0700284 mExclusiveStateFieldIndex = static_cast<int8_t>(mValues.size() - 1);
Muhammad Qureshibfc4bdb2020-04-08 06:26:49 -0700285 mValues[getExclusiveStateFieldIndex()].mAnnotations.setExclusiveState(exclusiveState);
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700286}
287
288void LogEvent::parseTriggerStateResetAnnotation(uint8_t annotationType) {
Ruchir Rastogi13296512020-03-24 10:59:49 -0700289 if (mValues.empty() || annotationType != INT32_TYPE) {
290 mValid = false;
291 return;
292 }
293
Ruchir Rastogi48dbf832020-04-20 16:50:46 -0700294 mResetState = readNextValue<int32_t>();
Ruchir Rastogi13296512020-03-24 10:59:49 -0700295}
296
297void LogEvent::parseStateNestedAnnotation(uint8_t annotationType) {
298 if (mValues.empty() || annotationType != BOOL_TYPE) {
299 mValid = false;
300 return;
301 }
302
303 bool nested = readNextValue<uint8_t>();
304 mValues[mValues.size() - 1].mAnnotations.setNested(nested);
305}
306
307// firstUidInChainIndex is a default parameter that is only needed when parsing
308// annotations for attribution chains.
309void LogEvent::parseAnnotations(uint8_t numAnnotations, int firstUidInChainIndex) {
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700310 for (uint8_t i = 0; i < numAnnotations; i++) {
Ruchir Rastogi13296512020-03-24 10:59:49 -0700311 uint8_t annotationId = readNextValue<uint8_t>();
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700312 uint8_t annotationType = readNextValue<uint8_t>();
Ruchir Rastogi13296512020-03-24 10:59:49 -0700313
314 switch (annotationId) {
315 case ANNOTATION_ID_IS_UID:
316 parseIsUidAnnotation(annotationType);
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700317 break;
Ruchir Rastogi13296512020-03-24 10:59:49 -0700318 case ANNOTATION_ID_TRUNCATE_TIMESTAMP:
319 parseTruncateTimestampAnnotation(annotationType);
320 break;
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700321 case ANNOTATION_ID_PRIMARY_FIELD:
322 parsePrimaryFieldAnnotation(annotationType);
Ruchir Rastogi13296512020-03-24 10:59:49 -0700323 break;
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700324 case ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID:
325 parsePrimaryFieldFirstUidAnnotation(annotationType, firstUidInChainIndex);
326 break;
327 case ANNOTATION_ID_EXCLUSIVE_STATE:
328 parseExclusiveStateAnnotation(annotationType);
329 break;
330 case ANNOTATION_ID_TRIGGER_STATE_RESET:
331 parseTriggerStateResetAnnotation(annotationType);
Ruchir Rastogi13296512020-03-24 10:59:49 -0700332 break;
333 case ANNOTATION_ID_STATE_NESTED:
334 parseStateNestedAnnotation(annotationType);
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700335 break;
336 default:
337 mValid = false;
Ruchir Rastogi13296512020-03-24 10:59:49 -0700338 return;
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700339 }
340 }
341}
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800342
343// This parsing logic is tied to the encoding scheme used in StatsEvent.java and
344// stats_event.c
Ruchir Rastogidfd63d42020-02-20 17:54:13 -0800345bool LogEvent::parseBuffer(uint8_t* buf, size_t len) {
346 mBuf = buf;
347 mRemainingLen = (uint32_t)len;
348
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800349 int32_t pos[] = {1, 1, 1};
350 bool last[] = {false, false, false};
351
352 // Beginning of buffer is OBJECT_TYPE | NUM_FIELDS | TIMESTAMP | ATOM_ID
353 uint8_t typeInfo = readNextValue<uint8_t>();
354 if (getTypeId(typeInfo) != OBJECT_TYPE) mValid = false;
355
356 uint8_t numElements = readNextValue<uint8_t>();
357 if (numElements < 2 || numElements > 127) mValid = false;
358
359 typeInfo = readNextValue<uint8_t>();
360 if (getTypeId(typeInfo) != INT64_TYPE) mValid = false;
361 mElapsedTimestampNs = readNextValue<int64_t>();
362 numElements--;
363
364 typeInfo = readNextValue<uint8_t>();
365 if (getTypeId(typeInfo) != INT32_TYPE) mValid = false;
366 mTagId = readNextValue<int32_t>();
367 numElements--;
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700368 parseAnnotations(getNumAnnotations(typeInfo)); // atom-level annotations
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800369
370 for (pos[0] = 1; pos[0] <= numElements && mValid; pos[0]++) {
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700371 last[0] = (pos[0] == numElements);
372
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800373 typeInfo = readNextValue<uint8_t>();
374 uint8_t typeId = getTypeId(typeInfo);
375
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700376 switch (typeId) {
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800377 case BOOL_TYPE:
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700378 parseBool(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800379 break;
380 case INT32_TYPE:
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700381 parseInt32(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800382 break;
383 case INT64_TYPE:
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700384 parseInt64(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800385 break;
386 case FLOAT_TYPE:
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700387 parseFloat(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800388 break;
389 case BYTE_ARRAY_TYPE:
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700390 parseByteArray(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800391 break;
392 case STRING_TYPE:
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700393 parseString(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800394 break;
395 case KEY_VALUE_PAIRS_TYPE:
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700396 parseKeyValuePairs(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800397 break;
398 case ATTRIBUTION_CHAIN_TYPE:
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700399 parseAttributionChain(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800400 break;
Ruchir Rastogi07f7adb2020-04-16 17:46:12 -0700401 case ERROR_TYPE:
Ruchir Rastogi1e8c57f2020-04-27 17:41:58 -0700402 /* mErrorBitmask =*/ readNextValue<int32_t>();
Ruchir Rastogi07f7adb2020-04-16 17:46:12 -0700403 mValid = false;
404 break;
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800405 default:
406 mValid = false;
Ruchir Rastogi07f7adb2020-04-16 17:46:12 -0700407 break;
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800408 }
409 }
410
411 if (mRemainingLen != 0) mValid = false;
412 mBuf = nullptr;
Ruchir Rastogidfd63d42020-02-20 17:54:13 -0800413 return mValid;
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800414}
415
416uint8_t LogEvent::getTypeId(uint8_t typeInfo) {
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700417 return typeInfo & 0x0F; // type id in lower 4 bytes
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800418}
419
420uint8_t LogEvent::getNumAnnotations(uint8_t typeInfo) {
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700421 return (typeInfo >> 4) & 0x0F; // num annotations in upper 4 bytes
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800422}
423
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700424int64_t LogEvent::GetLong(size_t key, status_t* err) const {
Yao Chen5bfffb52018-06-21 16:58:51 -0700425 // TODO(b/110561208): encapsulate the magical operations in Field struct as static functions
Yao Chen8a8d16c2018-02-08 14:50:40 -0800426 int field = getSimpleField(key);
427 for (const auto& value : mValues) {
428 if (value.mField.getField() == field) {
Yao Chenab92a1f2018-02-13 15:17:55 -0800429 if (value.mValue.getType() == LONG) {
430 return value.mValue.long_value;
431 } else if (value.mValue.getType() == INT) {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800432 return value.mValue.int_value;
433 } else {
434 *err = BAD_TYPE;
435 return 0;
436 }
437 }
438 if ((size_t)value.mField.getPosAtDepth(0) > key) {
439 break;
Yangster-mac20877162017-12-22 17:19:39 -0800440 }
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700441 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800442
443 *err = BAD_INDEX;
444 return 0;
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700445}
446
Chenjie Yu80f91122018-01-31 20:24:50 -0800447int LogEvent::GetInt(size_t key, status_t* err) const {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800448 int field = getSimpleField(key);
449 for (const auto& value : mValues) {
450 if (value.mField.getField() == field) {
451 if (value.mValue.getType() == INT) {
452 return value.mValue.int_value;
453 } else {
454 *err = BAD_TYPE;
455 return 0;
456 }
457 }
458 if ((size_t)value.mField.getPosAtDepth(0) > key) {
459 break;
460 }
461 }
462
Chenjie Yu80f91122018-01-31 20:24:50 -0800463 *err = BAD_INDEX;
464 return 0;
Chenjie Yu80f91122018-01-31 20:24:50 -0800465}
466
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700467const char* LogEvent::GetString(size_t key, status_t* err) const {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800468 int field = getSimpleField(key);
469 for (const auto& value : mValues) {
470 if (value.mField.getField() == field) {
471 if (value.mValue.getType() == STRING) {
472 return value.mValue.str_value.c_str();
473 } else {
474 *err = BAD_TYPE;
475 return 0;
476 }
477 }
478 if ((size_t)value.mField.getPosAtDepth(0) > key) {
479 break;
Yangster-mac20877162017-12-22 17:19:39 -0800480 }
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700481 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800482
483 *err = BAD_INDEX;
484 return NULL;
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700485}
486
487bool LogEvent::GetBool(size_t key, status_t* err) const {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800488 int field = getSimpleField(key);
489 for (const auto& value : mValues) {
490 if (value.mField.getField() == field) {
491 if (value.mValue.getType() == INT) {
492 return value.mValue.int_value != 0;
493 } else if (value.mValue.getType() == LONG) {
494 return value.mValue.long_value != 0;
495 } else {
496 *err = BAD_TYPE;
497 return false;
498 }
499 }
500 if ((size_t)value.mField.getPosAtDepth(0) > key) {
501 break;
Yangster-mac20877162017-12-22 17:19:39 -0800502 }
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700503 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800504
505 *err = BAD_INDEX;
506 return false;
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700507}
508
509float LogEvent::GetFloat(size_t key, status_t* err) const {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800510 int field = getSimpleField(key);
511 for (const auto& value : mValues) {
512 if (value.mField.getField() == field) {
513 if (value.mValue.getType() == FLOAT) {
514 return value.mValue.float_value;
515 } else {
516 *err = BAD_TYPE;
517 return 0.0;
518 }
519 }
520 if ((size_t)value.mField.getPosAtDepth(0) > key) {
521 break;
Yangster-mac20877162017-12-22 17:19:39 -0800522 }
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700523 }
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700524
Yao Chen8a8d16c2018-02-08 14:50:40 -0800525 *err = BAD_INDEX;
526 return 0.0;
Yangster-macd40053e2018-01-09 16:29:22 -0800527}
528
Jonathan Nguyena0e6de12020-01-28 18:33:55 -0800529std::vector<uint8_t> LogEvent::GetStorage(size_t key, status_t* err) const {
530 int field = getSimpleField(key);
531 for (const auto& value : mValues) {
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700532 if (value.mField.getField() == field) {
533 if (value.mValue.getType() == STORAGE) {
534 return value.mValue.storage_value;
535 } else {
536 *err = BAD_TYPE;
537 return vector<uint8_t>();
538 }
Jonathan Nguyena0e6de12020-01-28 18:33:55 -0800539 }
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700540 if ((size_t)value.mField.getPosAtDepth(0) > key) {
541 break;
542 }
Jonathan Nguyena0e6de12020-01-28 18:33:55 -0800543 }
544
545 *err = BAD_INDEX;
546 return vector<uint8_t>();
547}
548
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700549string LogEvent::ToString() const {
Yao Chen20e9e622018-02-28 11:18:51 -0800550 string result;
Yao Chen8e6f9982018-11-29 09:39:45 -0800551 result += StringPrintf("{ uid(%d) %lld %lld (%d)", mLogUid, (long long)mLogdTimestampNs,
Yao Chen20e9e622018-02-28 11:18:51 -0800552 (long long)mElapsedTimestampNs, mTagId);
Yao Chen8a8d16c2018-02-08 14:50:40 -0800553 for (const auto& value : mValues) {
Yao Chen20e9e622018-02-28 11:18:51 -0800554 result +=
555 StringPrintf("%#x", value.mField.getField()) + "->" + value.mValue.toString() + " ";
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700556 }
Yao Chen20e9e622018-02-28 11:18:51 -0800557 result += " }";
558 return result;
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700559}
560
Yangster-mac20877162017-12-22 17:19:39 -0800561void LogEvent::ToProto(ProtoOutputStream& protoOutput) const {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800562 writeFieldValueTreeToStream(mTagId, getValues(), &protoOutput);
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700563}
564
Muhammad Qureshi83aaa662020-04-21 12:51:36 -0700565bool LogEvent::hasAttributionChain(std::pair<int, int>* indexRange) const {
566 if (mAttributionChainStartIndex == -1 || mAttributionChainEndIndex == -1) {
567 return false;
568 }
569
570 if (nullptr != indexRange) {
Ruchir Rastogi1e8c57f2020-04-27 17:41:58 -0700571 indexRange->first = static_cast<int>(mAttributionChainStartIndex);
572 indexRange->second = static_cast<int>(mAttributionChainEndIndex);
Muhammad Qureshi83aaa662020-04-21 12:51:36 -0700573 }
574
575 return true;
576}
577
Tej Singh9b4a5ec2019-04-25 12:43:35 -0700578void writeExperimentIdsToProto(const std::vector<int64_t>& experimentIds,
579 std::vector<uint8_t>* protoOut) {
Jeff Hamiltonfa2f91c2019-03-22 00:25:02 -0400580 ProtoOutputStream proto;
581 for (const auto& expId : experimentIds) {
582 proto.write(FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED | FIELD_ID_EXPERIMENT_ID,
583 (long long)expId);
584 }
585
586 protoOut->resize(proto.size());
587 size_t pos = 0;
588 sp<ProtoReader> reader = proto.data();
589 while (reader->readBuffer() != NULL) {
590 size_t toRead = reader->currentToRead();
591 std::memcpy(protoOut->data() + pos, reader->readBuffer(), toRead);
592 pos += toRead;
593 reader->move(toRead);
594 }
595}
596
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700597} // namespace statsd
598} // namespace os
599} // namespace android