blob: 8ec0173ce461b16a3307de5217cd29f0fae97fe1 [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
Chenjie Yu0bd73db2018-12-16 07:37:04 -080069LogEvent::LogEvent(const LogEvent& event) {
70 mTagId = event.mTagId;
71 mLogUid = event.mLogUid;
Ruchir Rastogiab71ef02020-01-30 01:24:50 -080072 mLogPid = event.mLogPid;
Chenjie Yu0bd73db2018-12-16 07:37:04 -080073 mElapsedTimestampNs = event.mElapsedTimestampNs;
74 mLogdTimestampNs = event.mLogdTimestampNs;
75 mValues = event.mValues;
76}
77
Ruchir Rastogidfd63d42020-02-20 17:54:13 -080078LogEvent::LogEvent(int32_t uid, int32_t pid)
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -070079 : mLogdTimestampNs(time(nullptr)), mLogUid(uid), mLogPid(pid) {
Ruchir Rastogidfd63d42020-02-20 17:54:13 -080080}
81
Chenjie Yu6b1667c2019-01-18 10:09:33 -080082LogEvent::LogEvent(const string& trainName, int64_t trainVersionCode, bool requiresStaging,
83 bool rollbackEnabled, bool requiresLowLatencyMonitor, int32_t state,
84 const std::vector<uint8_t>& experimentIds, int32_t userId) {
85 mLogdTimestampNs = getWallClockNs();
86 mElapsedTimestampNs = getElapsedRealtimeNs();
Jeffrey Huang74fc4352020-03-06 15:18:33 -080087 mTagId = util::BINARY_PUSH_STATE_CHANGED;
Ruchir Rastogie449b0c2020-02-10 17:40:09 -080088 mLogUid = AIBinder_getCallingUid();
89 mLogPid = AIBinder_getCallingPid();
Chenjie Yu6b1667c2019-01-18 10:09:33 -080090
91 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(1)), Value(trainName)));
92 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(2)), Value(trainVersionCode)));
93 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(3)), Value((int)requiresStaging)));
94 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(4)), Value((int)rollbackEnabled)));
95 mValues.push_back(
96 FieldValue(Field(mTagId, getSimpleField(5)), Value((int)requiresLowLatencyMonitor)));
97 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(6)), Value(state)));
98 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(7)), Value(experimentIds)));
99 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(8)), Value(userId)));
100}
101
Howard Roa46b6582018-09-18 16:45:02 -0700102LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
Chenjie Yu97dbb202019-02-13 16:42:04 -0800103 const InstallTrainInfo& trainInfo) {
104 mLogdTimestampNs = wallClockTimestampNs;
105 mElapsedTimestampNs = elapsedTimestampNs;
Jeffrey Huang74fc4352020-03-06 15:18:33 -0800106 mTagId = util::TRAIN_INFO;
Muhammad Qureshif4ca8242019-03-01 09:20:15 -0800107
Chenjie Yu97dbb202019-02-13 16:42:04 -0800108 mValues.push_back(
109 FieldValue(Field(mTagId, getSimpleField(1)), Value(trainInfo.trainVersionCode)));
Jeff Hamiltonfa2f91c2019-03-22 00:25:02 -0400110 std::vector<uint8_t> experimentIdsProto;
111 writeExperimentIdsToProto(trainInfo.experimentIds, &experimentIdsProto);
112 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(2)), Value(experimentIdsProto)));
Muhammad Qureshif4ca8242019-03-01 09:20:15 -0800113 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(3)), Value(trainInfo.trainName)));
114 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(4)), Value(trainInfo.status)));
Chenjie Yu97dbb202019-02-13 16:42:04 -0800115}
116
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700117void LogEvent::parseInt32(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800118 int32_t value = readNextValue<int32_t>();
119 addToValues(pos, depth, value, last);
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700120 parseAnnotations(numAnnotations);
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800121}
122
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700123void LogEvent::parseInt64(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800124 int64_t value = readNextValue<int64_t>();
125 addToValues(pos, depth, value, last);
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700126 parseAnnotations(numAnnotations);
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800127}
128
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700129void LogEvent::parseString(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800130 int32_t numBytes = readNextValue<int32_t>();
131 if ((uint32_t)numBytes > mRemainingLen) {
132 mValid = false;
133 return;
134 }
135
136 string value = string((char*)mBuf, numBytes);
137 mBuf += numBytes;
138 mRemainingLen -= numBytes;
139 addToValues(pos, depth, value, last);
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700140 parseAnnotations(numAnnotations);
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800141}
142
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700143void LogEvent::parseFloat(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800144 float value = readNextValue<float>();
145 addToValues(pos, depth, value, last);
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700146 parseAnnotations(numAnnotations);
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800147}
148
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700149void LogEvent::parseBool(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800150 // cast to int32_t because FieldValue does not support bools
151 int32_t value = (int32_t)readNextValue<uint8_t>();
152 addToValues(pos, depth, value, last);
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700153 parseAnnotations(numAnnotations);
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800154}
155
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700156void LogEvent::parseByteArray(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800157 int32_t numBytes = readNextValue<int32_t>();
158 if ((uint32_t)numBytes > mRemainingLen) {
159 mValid = false;
160 return;
161 }
162
163 vector<uint8_t> value(mBuf, mBuf + numBytes);
164 mBuf += numBytes;
165 mRemainingLen -= numBytes;
166 addToValues(pos, depth, value, last);
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700167 parseAnnotations(numAnnotations);
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800168}
169
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700170void LogEvent::parseKeyValuePairs(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800171 int32_t numPairs = readNextValue<uint8_t>();
172
173 for (pos[1] = 1; pos[1] <= numPairs; pos[1]++) {
174 last[1] = (pos[1] == numPairs);
175
176 // parse key
177 pos[2] = 1;
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700178 parseInt32(pos, /*depth=*/2, last, /*numAnnotations=*/0);
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800179
180 // parse value
181 last[2] = true;
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700182
183 uint8_t typeInfo = readNextValue<uint8_t>();
184 switch (getTypeId(typeInfo)) {
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800185 case INT32_TYPE:
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700186 pos[2] = 2; // pos[2] determined by index of type in KeyValuePair in atoms.proto
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700187 parseInt32(pos, /*depth=*/2, last, /*numAnnotations=*/0);
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800188 break;
189 case INT64_TYPE:
190 pos[2] = 3;
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700191 parseInt64(pos, /*depth=*/2, last, /*numAnnotations=*/0);
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800192 break;
193 case STRING_TYPE:
194 pos[2] = 4;
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700195 parseString(pos, /*depth=*/2, last, /*numAnnotations=*/0);
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800196 break;
197 case FLOAT_TYPE:
198 pos[2] = 5;
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700199 parseFloat(pos, /*depth=*/2, last, /*numAnnotations=*/0);
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800200 break;
201 default:
202 mValid = false;
203 }
204 }
205
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700206 parseAnnotations(numAnnotations);
207
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800208 pos[1] = pos[2] = 1;
209 last[1] = last[2] = false;
210}
211
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700212void LogEvent::parseAttributionChain(int32_t* pos, int32_t depth, bool* last,
213 uint8_t numAnnotations) {
Muhammad Qureshi83aaa662020-04-21 12:51:36 -0700214 const unsigned int firstUidInChainIndex = mValues.size();
215 const int32_t numNodes = readNextValue<uint8_t>();
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800216 for (pos[1] = 1; pos[1] <= numNodes; pos[1]++) {
217 last[1] = (pos[1] == numNodes);
218
219 // parse uid
220 pos[2] = 1;
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700221 parseInt32(pos, /*depth=*/2, last, /*numAnnotations=*/0);
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800222
223 // parse tag
224 pos[2] = 2;
225 last[2] = true;
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700226 parseString(pos, /*depth=*/2, last, /*numAnnotations=*/0);
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800227 }
Muhammad Qureshi83aaa662020-04-21 12:51:36 -0700228 // Check if at least one node was successfully parsed.
229 if (mValues.size() - 1 > firstUidInChainIndex) {
Ruchir Rastogi1e8c57f2020-04-27 17:41:58 -0700230 mAttributionChainStartIndex = static_cast<int8_t>(firstUidInChainIndex);
231 mAttributionChainEndIndex = static_cast<int8_t>(mValues.size() - 1);
Muhammad Qureshi83aaa662020-04-21 12:51:36 -0700232 }
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800233
Ruchir Rastogi13296512020-03-24 10:59:49 -0700234 parseAnnotations(numAnnotations, firstUidInChainIndex);
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700235
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800236 pos[1] = pos[2] = 1;
237 last[1] = last[2] = false;
238}
239
Ruchir Rastogiffa34f02020-04-04 15:30:11 -0700240// Assumes that mValues is not empty
241bool LogEvent::checkPreviousValueType(Type expected) {
242 return mValues[mValues.size() - 1].mValue.getType() == expected;
243}
244
Ruchir Rastogi13296512020-03-24 10:59:49 -0700245void LogEvent::parseIsUidAnnotation(uint8_t annotationType) {
Ruchir Rastogiffa34f02020-04-04 15:30:11 -0700246 if (mValues.empty() || !checkPreviousValueType(INT) || annotationType != BOOL_TYPE) {
Ruchir Rastogi13296512020-03-24 10:59:49 -0700247 mValid = false;
248 return;
249 }
250
251 bool isUid = readNextValue<uint8_t>();
Ruchir Rastogi1e8c57f2020-04-27 17:41:58 -0700252 if (isUid) mUidFieldIndex = static_cast<int8_t>(mValues.size() - 1);
Ruchir Rastogiffa34f02020-04-04 15:30:11 -0700253 mValues[mValues.size() - 1].mAnnotations.setUidField(isUid);
Ruchir Rastogi13296512020-03-24 10:59:49 -0700254}
255
256void LogEvent::parseTruncateTimestampAnnotation(uint8_t annotationType) {
257 if (!mValues.empty() || annotationType != BOOL_TYPE) {
258 mValid = false;
259 return;
260 }
261
262 mTruncateTimestamp = readNextValue<uint8_t>();
263}
264
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700265void LogEvent::parsePrimaryFieldAnnotation(uint8_t annotationType) {
266 if (mValues.empty() || annotationType != BOOL_TYPE) {
Ruchir Rastogi13296512020-03-24 10:59:49 -0700267 mValid = false;
268 return;
269 }
270
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700271 const bool primaryField = readNextValue<uint8_t>();
272 mValues[mValues.size() - 1].mAnnotations.setPrimaryField(primaryField);
Ruchir Rastogi13296512020-03-24 10:59:49 -0700273}
274
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700275void LogEvent::parsePrimaryFieldFirstUidAnnotation(uint8_t annotationType,
276 int firstUidInChainIndex) {
277 if (mValues.empty() || annotationType != BOOL_TYPE || -1 == firstUidInChainIndex) {
278 mValid = false;
279 return;
280 }
281
282 const bool primaryField = readNextValue<uint8_t>();
283 mValues[firstUidInChainIndex].mAnnotations.setPrimaryField(primaryField);
284}
285
286void LogEvent::parseExclusiveStateAnnotation(uint8_t annotationType) {
287 if (mValues.empty() || annotationType != BOOL_TYPE) {
288 mValid = false;
289 return;
290 }
291
292 const bool exclusiveState = readNextValue<uint8_t>();
Ruchir Rastogi1e8c57f2020-04-27 17:41:58 -0700293 mExclusiveStateFieldIndex = static_cast<int8_t>(mValues.size() - 1);
Muhammad Qureshibfc4bdb2020-04-08 06:26:49 -0700294 mValues[getExclusiveStateFieldIndex()].mAnnotations.setExclusiveState(exclusiveState);
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700295}
296
297void LogEvent::parseTriggerStateResetAnnotation(uint8_t annotationType) {
Ruchir Rastogi13296512020-03-24 10:59:49 -0700298 if (mValues.empty() || annotationType != INT32_TYPE) {
299 mValid = false;
300 return;
301 }
302
Ruchir Rastogi48dbf832020-04-20 16:50:46 -0700303 mResetState = readNextValue<int32_t>();
Ruchir Rastogi13296512020-03-24 10:59:49 -0700304}
305
306void LogEvent::parseStateNestedAnnotation(uint8_t annotationType) {
307 if (mValues.empty() || annotationType != BOOL_TYPE) {
308 mValid = false;
309 return;
310 }
311
312 bool nested = readNextValue<uint8_t>();
313 mValues[mValues.size() - 1].mAnnotations.setNested(nested);
314}
315
316// firstUidInChainIndex is a default parameter that is only needed when parsing
317// annotations for attribution chains.
318void LogEvent::parseAnnotations(uint8_t numAnnotations, int firstUidInChainIndex) {
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700319 for (uint8_t i = 0; i < numAnnotations; i++) {
Ruchir Rastogi13296512020-03-24 10:59:49 -0700320 uint8_t annotationId = readNextValue<uint8_t>();
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700321 uint8_t annotationType = readNextValue<uint8_t>();
Ruchir Rastogi13296512020-03-24 10:59:49 -0700322
323 switch (annotationId) {
324 case ANNOTATION_ID_IS_UID:
325 parseIsUidAnnotation(annotationType);
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700326 break;
Ruchir Rastogi13296512020-03-24 10:59:49 -0700327 case ANNOTATION_ID_TRUNCATE_TIMESTAMP:
328 parseTruncateTimestampAnnotation(annotationType);
329 break;
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700330 case ANNOTATION_ID_PRIMARY_FIELD:
331 parsePrimaryFieldAnnotation(annotationType);
Ruchir Rastogi13296512020-03-24 10:59:49 -0700332 break;
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700333 case ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID:
334 parsePrimaryFieldFirstUidAnnotation(annotationType, firstUidInChainIndex);
335 break;
336 case ANNOTATION_ID_EXCLUSIVE_STATE:
337 parseExclusiveStateAnnotation(annotationType);
338 break;
339 case ANNOTATION_ID_TRIGGER_STATE_RESET:
340 parseTriggerStateResetAnnotation(annotationType);
Ruchir Rastogi13296512020-03-24 10:59:49 -0700341 break;
342 case ANNOTATION_ID_STATE_NESTED:
343 parseStateNestedAnnotation(annotationType);
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700344 break;
345 default:
346 mValid = false;
Ruchir Rastogi13296512020-03-24 10:59:49 -0700347 return;
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700348 }
349 }
350}
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800351
352// This parsing logic is tied to the encoding scheme used in StatsEvent.java and
353// stats_event.c
Ruchir Rastogidfd63d42020-02-20 17:54:13 -0800354bool LogEvent::parseBuffer(uint8_t* buf, size_t len) {
355 mBuf = buf;
356 mRemainingLen = (uint32_t)len;
357
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800358 int32_t pos[] = {1, 1, 1};
359 bool last[] = {false, false, false};
360
361 // Beginning of buffer is OBJECT_TYPE | NUM_FIELDS | TIMESTAMP | ATOM_ID
362 uint8_t typeInfo = readNextValue<uint8_t>();
363 if (getTypeId(typeInfo) != OBJECT_TYPE) mValid = false;
364
365 uint8_t numElements = readNextValue<uint8_t>();
366 if (numElements < 2 || numElements > 127) mValid = false;
367
368 typeInfo = readNextValue<uint8_t>();
369 if (getTypeId(typeInfo) != INT64_TYPE) mValid = false;
370 mElapsedTimestampNs = readNextValue<int64_t>();
371 numElements--;
372
373 typeInfo = readNextValue<uint8_t>();
374 if (getTypeId(typeInfo) != INT32_TYPE) mValid = false;
375 mTagId = readNextValue<int32_t>();
376 numElements--;
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700377 parseAnnotations(getNumAnnotations(typeInfo)); // atom-level annotations
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800378
379 for (pos[0] = 1; pos[0] <= numElements && mValid; pos[0]++) {
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700380 last[0] = (pos[0] == numElements);
381
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800382 typeInfo = readNextValue<uint8_t>();
383 uint8_t typeId = getTypeId(typeInfo);
384
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700385 switch (typeId) {
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800386 case BOOL_TYPE:
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700387 parseBool(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800388 break;
389 case INT32_TYPE:
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700390 parseInt32(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800391 break;
392 case INT64_TYPE:
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700393 parseInt64(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800394 break;
395 case FLOAT_TYPE:
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700396 parseFloat(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800397 break;
398 case BYTE_ARRAY_TYPE:
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700399 parseByteArray(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800400 break;
401 case STRING_TYPE:
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700402 parseString(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800403 break;
404 case KEY_VALUE_PAIRS_TYPE:
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700405 parseKeyValuePairs(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800406 break;
407 case ATTRIBUTION_CHAIN_TYPE:
Ruchir Rastogi84eb44b2020-03-12 18:48:48 -0700408 parseAttributionChain(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800409 break;
Ruchir Rastogi07f7adb2020-04-16 17:46:12 -0700410 case ERROR_TYPE:
Ruchir Rastogi1e8c57f2020-04-27 17:41:58 -0700411 /* mErrorBitmask =*/ readNextValue<int32_t>();
Ruchir Rastogi07f7adb2020-04-16 17:46:12 -0700412 mValid = false;
413 break;
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800414 default:
415 mValid = false;
Ruchir Rastogi07f7adb2020-04-16 17:46:12 -0700416 break;
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800417 }
418 }
419
420 if (mRemainingLen != 0) mValid = false;
421 mBuf = nullptr;
Ruchir Rastogidfd63d42020-02-20 17:54:13 -0800422 return mValid;
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800423}
424
425uint8_t LogEvent::getTypeId(uint8_t typeInfo) {
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700426 return typeInfo & 0x0F; // type id in lower 4 bytes
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800427}
428
429uint8_t LogEvent::getNumAnnotations(uint8_t typeInfo) {
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700430 return (typeInfo >> 4) & 0x0F; // num annotations in upper 4 bytes
Ruchir Rastogi1736ba42019-11-04 14:37:13 -0800431}
432
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700433int64_t LogEvent::GetLong(size_t key, status_t* err) const {
Yao Chen5bfffb52018-06-21 16:58:51 -0700434 // TODO(b/110561208): encapsulate the magical operations in Field struct as static functions
Yao Chen8a8d16c2018-02-08 14:50:40 -0800435 int field = getSimpleField(key);
436 for (const auto& value : mValues) {
437 if (value.mField.getField() == field) {
Yao Chenab92a1f2018-02-13 15:17:55 -0800438 if (value.mValue.getType() == LONG) {
439 return value.mValue.long_value;
440 } else if (value.mValue.getType() == INT) {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800441 return value.mValue.int_value;
442 } else {
443 *err = BAD_TYPE;
444 return 0;
445 }
446 }
447 if ((size_t)value.mField.getPosAtDepth(0) > key) {
448 break;
Yangster-mac20877162017-12-22 17:19:39 -0800449 }
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700450 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800451
452 *err = BAD_INDEX;
453 return 0;
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700454}
455
Chenjie Yu80f91122018-01-31 20:24:50 -0800456int LogEvent::GetInt(size_t key, status_t* err) const {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800457 int field = getSimpleField(key);
458 for (const auto& value : mValues) {
459 if (value.mField.getField() == field) {
460 if (value.mValue.getType() == INT) {
461 return value.mValue.int_value;
462 } else {
463 *err = BAD_TYPE;
464 return 0;
465 }
466 }
467 if ((size_t)value.mField.getPosAtDepth(0) > key) {
468 break;
469 }
470 }
471
Chenjie Yu80f91122018-01-31 20:24:50 -0800472 *err = BAD_INDEX;
473 return 0;
Chenjie Yu80f91122018-01-31 20:24:50 -0800474}
475
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700476const char* LogEvent::GetString(size_t key, status_t* err) const {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800477 int field = getSimpleField(key);
478 for (const auto& value : mValues) {
479 if (value.mField.getField() == field) {
480 if (value.mValue.getType() == STRING) {
481 return value.mValue.str_value.c_str();
482 } else {
483 *err = BAD_TYPE;
484 return 0;
485 }
486 }
487 if ((size_t)value.mField.getPosAtDepth(0) > key) {
488 break;
Yangster-mac20877162017-12-22 17:19:39 -0800489 }
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700490 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800491
492 *err = BAD_INDEX;
493 return NULL;
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700494}
495
496bool LogEvent::GetBool(size_t key, status_t* err) const {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800497 int field = getSimpleField(key);
498 for (const auto& value : mValues) {
499 if (value.mField.getField() == field) {
500 if (value.mValue.getType() == INT) {
501 return value.mValue.int_value != 0;
502 } else if (value.mValue.getType() == LONG) {
503 return value.mValue.long_value != 0;
504 } else {
505 *err = BAD_TYPE;
506 return false;
507 }
508 }
509 if ((size_t)value.mField.getPosAtDepth(0) > key) {
510 break;
Yangster-mac20877162017-12-22 17:19:39 -0800511 }
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700512 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800513
514 *err = BAD_INDEX;
515 return false;
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700516}
517
518float LogEvent::GetFloat(size_t key, status_t* err) const {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800519 int field = getSimpleField(key);
520 for (const auto& value : mValues) {
521 if (value.mField.getField() == field) {
522 if (value.mValue.getType() == FLOAT) {
523 return value.mValue.float_value;
524 } else {
525 *err = BAD_TYPE;
526 return 0.0;
527 }
528 }
529 if ((size_t)value.mField.getPosAtDepth(0) > key) {
530 break;
Yangster-mac20877162017-12-22 17:19:39 -0800531 }
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700532 }
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700533
Yao Chen8a8d16c2018-02-08 14:50:40 -0800534 *err = BAD_INDEX;
535 return 0.0;
Yangster-macd40053e2018-01-09 16:29:22 -0800536}
537
Jonathan Nguyena0e6de12020-01-28 18:33:55 -0800538std::vector<uint8_t> LogEvent::GetStorage(size_t key, status_t* err) const {
539 int field = getSimpleField(key);
540 for (const auto& value : mValues) {
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700541 if (value.mField.getField() == field) {
542 if (value.mValue.getType() == STORAGE) {
543 return value.mValue.storage_value;
544 } else {
545 *err = BAD_TYPE;
546 return vector<uint8_t>();
547 }
Jonathan Nguyena0e6de12020-01-28 18:33:55 -0800548 }
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700549 if ((size_t)value.mField.getPosAtDepth(0) > key) {
550 break;
551 }
Jonathan Nguyena0e6de12020-01-28 18:33:55 -0800552 }
553
554 *err = BAD_INDEX;
555 return vector<uint8_t>();
556}
557
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700558string LogEvent::ToString() const {
Yao Chen20e9e622018-02-28 11:18:51 -0800559 string result;
Yao Chen8e6f9982018-11-29 09:39:45 -0800560 result += StringPrintf("{ uid(%d) %lld %lld (%d)", mLogUid, (long long)mLogdTimestampNs,
Yao Chen20e9e622018-02-28 11:18:51 -0800561 (long long)mElapsedTimestampNs, mTagId);
Yao Chen8a8d16c2018-02-08 14:50:40 -0800562 for (const auto& value : mValues) {
Yao Chen20e9e622018-02-28 11:18:51 -0800563 result +=
564 StringPrintf("%#x", value.mField.getField()) + "->" + value.mValue.toString() + " ";
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700565 }
Yao Chen20e9e622018-02-28 11:18:51 -0800566 result += " }";
567 return result;
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700568}
569
Yangster-mac20877162017-12-22 17:19:39 -0800570void LogEvent::ToProto(ProtoOutputStream& protoOutput) const {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800571 writeFieldValueTreeToStream(mTagId, getValues(), &protoOutput);
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700572}
573
Muhammad Qureshi83aaa662020-04-21 12:51:36 -0700574bool LogEvent::hasAttributionChain(std::pair<int, int>* indexRange) const {
575 if (mAttributionChainStartIndex == -1 || mAttributionChainEndIndex == -1) {
576 return false;
577 }
578
579 if (nullptr != indexRange) {
Ruchir Rastogi1e8c57f2020-04-27 17:41:58 -0700580 indexRange->first = static_cast<int>(mAttributionChainStartIndex);
581 indexRange->second = static_cast<int>(mAttributionChainEndIndex);
Muhammad Qureshi83aaa662020-04-21 12:51:36 -0700582 }
583
584 return true;
585}
586
Tej Singh9b4a5ec2019-04-25 12:43:35 -0700587void writeExperimentIdsToProto(const std::vector<int64_t>& experimentIds,
588 std::vector<uint8_t>* protoOut) {
Jeff Hamiltonfa2f91c2019-03-22 00:25:02 -0400589 ProtoOutputStream proto;
590 for (const auto& expId : experimentIds) {
591 proto.write(FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED | FIELD_ID_EXPERIMENT_ID,
592 (long long)expId);
593 }
594
595 protoOut->resize(proto.size());
596 size_t pos = 0;
597 sp<ProtoReader> reader = proto.data();
598 while (reader->readBuffer() != NULL) {
599 size_t toRead = reader->currentToRead();
600 std::memcpy(protoOut->data() + pos, reader->readBuffer(), toRead);
601 pos += toRead;
602 reader->move(toRead);
603 }
604}
605
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700606} // namespace statsd
607} // namespace os
608} // namespace android