1 /*
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
17 #define STATSD_DEBUG false // STOPSHIP if true
18 #include "Log.h"
19
20 #include "logd/LogEvent.h"
21
22 #include <android-base/stringprintf.h>
23 #include <android/binder_ibinder.h>
24 #include <private/android_filesystem_config.h>
25
26 #include "flags/FlagProvider.h"
27 #include "stats_annotations.h"
28 #include "stats_log_util.h"
29 #include "statslog_statsd.h"
30
31 namespace android {
32 namespace os {
33 namespace statsd {
34
35 // for TrainInfo experiment id serialization
36 const int FIELD_ID_EXPERIMENT_ID = 1;
37
38 using namespace android::util;
39 using android::base::StringPrintf;
40 using android::util::ProtoOutputStream;
41 using std::string;
42 using std::vector;
43
44 namespace {
45
getTypeId(uint8_t typeInfo)46 uint8_t getTypeId(uint8_t typeInfo) {
47 return typeInfo & 0x0F; // type id in lower 4 bytes
48 }
49
getNumAnnotations(uint8_t typeInfo)50 uint8_t getNumAnnotations(uint8_t typeInfo) {
51 return (typeInfo >> 4) & 0x0F; // num annotations in upper 4 bytes
52 }
53
54 } // namespace
55
LogEvent(int32_t uid,int32_t pid)56 LogEvent::LogEvent(int32_t uid, int32_t pid)
57 : mLogdTimestampNs(getWallClockNs()), mLogUid(uid), mLogPid(pid) {
58 }
59
LogEvent(const string & trainName,int64_t trainVersionCode,bool requiresStaging,bool rollbackEnabled,bool requiresLowLatencyMonitor,int32_t state,const std::vector<uint8_t> & experimentIds,int32_t userId)60 LogEvent::LogEvent(const string& trainName, int64_t trainVersionCode, bool requiresStaging,
61 bool rollbackEnabled, bool requiresLowLatencyMonitor, int32_t state,
62 const std::vector<uint8_t>& experimentIds, int32_t userId) {
63 mLogdTimestampNs = getWallClockNs();
64 mElapsedTimestampNs = getElapsedRealtimeNs();
65 mTagId = util::BINARY_PUSH_STATE_CHANGED;
66 mLogUid = AIBinder_getCallingUid();
67 mLogPid = AIBinder_getCallingPid();
68
69 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(1)), Value(trainName)));
70 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(2)), Value(trainVersionCode)));
71 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(3)), Value((int)requiresStaging)));
72 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(4)), Value((int)rollbackEnabled)));
73 mValues.push_back(
74 FieldValue(Field(mTagId, getSimpleField(5)), Value((int)requiresLowLatencyMonitor)));
75 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(6)), Value(state)));
76 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(7)), Value(experimentIds)));
77 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(8)), Value(userId)));
78 }
79
LogEvent(int64_t wallClockTimestampNs,int64_t elapsedTimestampNs,const InstallTrainInfo & trainInfo)80 LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
81 const InstallTrainInfo& trainInfo) {
82 mLogdTimestampNs = wallClockTimestampNs;
83 mElapsedTimestampNs = elapsedTimestampNs;
84 mTagId = util::TRAIN_INFO;
85
86 mValues.push_back(
87 FieldValue(Field(mTagId, getSimpleField(1)), Value(trainInfo.trainVersionCode)));
88 std::vector<uint8_t> experimentIdsProto;
89 writeExperimentIdsToProto(trainInfo.experimentIds, &experimentIdsProto);
90 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(2)), Value(experimentIdsProto)));
91 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(3)), Value(trainInfo.trainName)));
92 mValues.push_back(FieldValue(Field(mTagId, getSimpleField(4)), Value(trainInfo.status)));
93 }
94
parseInt32(int32_t * pos,int32_t depth,bool * last,uint8_t numAnnotations)95 void LogEvent::parseInt32(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
96 int32_t value = readNextValue<int32_t>();
97 addToValues(pos, depth, value, last);
98 parseAnnotations(numAnnotations);
99 }
100
parseInt64(int32_t * pos,int32_t depth,bool * last,uint8_t numAnnotations)101 void LogEvent::parseInt64(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
102 int64_t value = readNextValue<int64_t>();
103 addToValues(pos, depth, value, last);
104 parseAnnotations(numAnnotations);
105 }
106
parseString(int32_t * pos,int32_t depth,bool * last,uint8_t numAnnotations)107 void LogEvent::parseString(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
108 int32_t numBytes = readNextValue<int32_t>();
109 if ((uint32_t)numBytes > mRemainingLen) {
110 mValid = false;
111 return;
112 }
113
114 string value = string((char*)mBuf, numBytes);
115 mBuf += numBytes;
116 mRemainingLen -= numBytes;
117 addToValues(pos, depth, value, last);
118 parseAnnotations(numAnnotations);
119 }
120
parseFloat(int32_t * pos,int32_t depth,bool * last,uint8_t numAnnotations)121 void LogEvent::parseFloat(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
122 float value = readNextValue<float>();
123 addToValues(pos, depth, value, last);
124 parseAnnotations(numAnnotations);
125 }
126
parseBool(int32_t * pos,int32_t depth,bool * last,uint8_t numAnnotations)127 void LogEvent::parseBool(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
128 // cast to int32_t because FieldValue does not support bools
129 int32_t value = (int32_t)readNextValue<uint8_t>();
130 addToValues(pos, depth, value, last);
131 parseAnnotations(numAnnotations);
132 }
133
parseByteArray(int32_t * pos,int32_t depth,bool * last,uint8_t numAnnotations)134 void LogEvent::parseByteArray(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
135 int32_t numBytes = readNextValue<int32_t>();
136 if ((uint32_t)numBytes > mRemainingLen) {
137 mValid = false;
138 return;
139 }
140
141 vector<uint8_t> value(mBuf, mBuf + numBytes);
142 mBuf += numBytes;
143 mRemainingLen -= numBytes;
144 addToValues(pos, depth, value, last);
145 parseAnnotations(numAnnotations);
146 }
147
parseKeyValuePairs(int32_t * pos,int32_t depth,bool * last,uint8_t numAnnotations)148 void LogEvent::parseKeyValuePairs(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
149 int32_t numPairs = readNextValue<uint8_t>();
150
151 for (pos[1] = 1; pos[1] <= numPairs; pos[1]++) {
152 last[1] = (pos[1] == numPairs);
153
154 // parse key
155 pos[2] = 1;
156 parseInt32(pos, /*depth=*/2, last, /*numAnnotations=*/0);
157
158 // parse value
159 last[2] = true;
160
161 uint8_t typeInfo = readNextValue<uint8_t>();
162 switch (getTypeId(typeInfo)) {
163 case INT32_TYPE:
164 pos[2] = 2; // pos[2] determined by index of type in KeyValuePair in atoms.proto
165 parseInt32(pos, /*depth=*/2, last, /*numAnnotations=*/0);
166 break;
167 case INT64_TYPE:
168 pos[2] = 3;
169 parseInt64(pos, /*depth=*/2, last, /*numAnnotations=*/0);
170 break;
171 case STRING_TYPE:
172 pos[2] = 4;
173 parseString(pos, /*depth=*/2, last, /*numAnnotations=*/0);
174 break;
175 case FLOAT_TYPE:
176 pos[2] = 5;
177 parseFloat(pos, /*depth=*/2, last, /*numAnnotations=*/0);
178 break;
179 default:
180 mValid = false;
181 }
182 }
183
184 parseAnnotations(numAnnotations);
185
186 pos[1] = pos[2] = 1;
187 last[1] = last[2] = false;
188 }
189
parseAttributionChain(int32_t * pos,int32_t depth,bool * last,uint8_t numAnnotations)190 void LogEvent::parseAttributionChain(int32_t* pos, int32_t depth, bool* last,
191 uint8_t numAnnotations) {
192 std::optional<size_t> firstUidInChainIndex = mValues.size();
193 const uint8_t numNodes = readNextValue<uint8_t>();
194
195 if (numNodes > INT8_MAX) mValid = false;
196
197 for (pos[1] = 1; pos[1] <= numNodes; pos[1]++) {
198 last[1] = (pos[1] == numNodes);
199
200 // parse uid
201 pos[2] = 1;
202 parseInt32(pos, /*depth=*/2, last, /*numAnnotations=*/0);
203
204 // parse tag
205 pos[2] = 2;
206 last[2] = true;
207 parseString(pos, /*depth=*/2, last, /*numAnnotations=*/0);
208 }
209
210 if (mValues.size() > (firstUidInChainIndex.value() + 1)) {
211 // At least one node was successfully parsed.
212 mAttributionChainStartIndex = firstUidInChainIndex;
213 mAttributionChainEndIndex = mValues.size() - 1;
214 } else {
215 firstUidInChainIndex = std::nullopt;
216 mValid = false;
217 }
218
219 if (mValid) {
220 parseAnnotations(numAnnotations, /*numElements*/ std::nullopt, firstUidInChainIndex);
221 }
222
223 pos[1] = pos[2] = 1;
224 last[1] = last[2] = false;
225 }
226
parseArray(int32_t * pos,int32_t depth,bool * last,uint8_t numAnnotations)227 void LogEvent::parseArray(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
228 const uint8_t numElements = readNextValue<uint8_t>();
229 const uint8_t typeInfo = readNextValue<uint8_t>();
230 const uint8_t typeId = getTypeId(typeInfo);
231
232 if (numElements > INT8_MAX) mValid = false;
233
234 for (pos[1] = 1; pos[1] <= numElements; pos[1]++) {
235 last[1] = (pos[1] == numElements);
236
237 // The top-level array is at depth 0, and all of its elements are at depth 1.
238 // Once nested fields are supported, array elements will be at top-level depth + 1.
239
240 switch (typeId) {
241 case INT32_TYPE:
242 parseInt32(pos, /*depth=*/1, last, /*numAnnotations=*/0);
243 break;
244 case INT64_TYPE:
245 parseInt64(pos, /*depth=*/1, last, /*numAnnotations=*/0);
246 break;
247 case FLOAT_TYPE:
248 parseFloat(pos, /*depth=*/1, last, /*numAnnotations=*/0);
249 break;
250 case BOOL_TYPE:
251 parseBool(pos, /*depth=*/1, last, /*numAnnotations=*/0);
252 break;
253 case STRING_TYPE:
254 parseString(pos, /*depth=*/1, last, /*numAnnotations=*/0);
255 break;
256 default:
257 mValid = false;
258 break;
259 }
260 }
261
262 parseAnnotations(numAnnotations, numElements);
263
264 pos[1] = 1;
265 last[1] = false;
266 }
267
268 // Assumes that mValues is not empty
checkPreviousValueType(Type expected) const269 bool LogEvent::checkPreviousValueType(Type expected) const {
270 return mValues[mValues.size() - 1].mValue.getType() == expected;
271 }
272
parseIsUidAnnotation(uint8_t annotationType,std::optional<uint8_t> numElements)273 void LogEvent::parseIsUidAnnotation(uint8_t annotationType, std::optional<uint8_t> numElements) {
274 // Need to set numElements if not an array.
275 if (!numElements) {
276 numElements = 1;
277 }
278
279 // If array is empty, skip uid parsing.
280 if (numElements == 0 && annotationType == BOOL_TYPE) {
281 readNextValue<uint8_t>();
282 return;
283 }
284
285 // Allowed types: INT, repeated INT
286 if (mValues.empty() || numElements > mValues.size() || !checkPreviousValueType(INT) ||
287 annotationType != BOOL_TYPE) {
288 VLOG("Atom ID %d error while parseIsUidAnnotation()", mTagId);
289 mValid = false;
290 return;
291 }
292
293 bool isUid = readNextValue<uint8_t>();
294 if (isUid) {
295 mNumUidFields += numElements.value();
296 }
297
298 for (int i = 1; i <= numElements; i++) {
299 mValues[mValues.size() - i].mAnnotations.setUidField(isUid);
300 }
301 }
302
parseTruncateTimestampAnnotation(uint8_t annotationType)303 void LogEvent::parseTruncateTimestampAnnotation(uint8_t annotationType) {
304 if (!mValues.empty() || annotationType != BOOL_TYPE) {
305 VLOG("Atom ID %d error while parseTruncateTimestampAnnotation()", mTagId);
306 mValid = false;
307 return;
308 }
309
310 mTruncateTimestamp = readNextValue<uint8_t>();
311 }
312
parsePrimaryFieldAnnotation(uint8_t annotationType,std::optional<uint8_t> numElements,std::optional<size_t> firstUidInChainIndex)313 void LogEvent::parsePrimaryFieldAnnotation(uint8_t annotationType,
314 std::optional<uint8_t> numElements,
315 std::optional<size_t> firstUidInChainIndex) {
316 // Allowed types: all types except for attribution chains and repeated fields.
317 if (mValues.empty() || annotationType != BOOL_TYPE || firstUidInChainIndex || numElements) {
318 VLOG("Atom ID %d error while parsePrimaryFieldAnnotation()", mTagId);
319 mValid = false;
320 return;
321 }
322
323 const bool primaryField = readNextValue<uint8_t>();
324 mValues[mValues.size() - 1].mAnnotations.setPrimaryField(primaryField);
325 }
326
parsePrimaryFieldFirstUidAnnotation(uint8_t annotationType,std::optional<size_t> firstUidInChainIndex)327 void LogEvent::parsePrimaryFieldFirstUidAnnotation(uint8_t annotationType,
328 std::optional<size_t> firstUidInChainIndex) {
329 // Allowed types: attribution chains
330 if (mValues.empty() || annotationType != BOOL_TYPE || !firstUidInChainIndex) {
331 VLOG("Atom ID %d error while parsePrimaryFieldFirstUidAnnotation()", mTagId);
332 mValid = false;
333 return;
334 }
335
336 if (mValues.size() < firstUidInChainIndex.value() + 1) { // AttributionChain is empty.
337 VLOG("Atom ID %d error while parsePrimaryFieldFirstUidAnnotation()", mTagId);
338 mValid = false;
339 android_errorWriteLog(0x534e4554, "174485572");
340 return;
341 }
342
343 const bool primaryField = readNextValue<uint8_t>();
344 mValues[firstUidInChainIndex.value()].mAnnotations.setPrimaryField(primaryField);
345 }
346
parseExclusiveStateAnnotation(uint8_t annotationType,std::optional<uint8_t> numElements)347 void LogEvent::parseExclusiveStateAnnotation(uint8_t annotationType,
348 std::optional<uint8_t> numElements) {
349 // Allowed types: BOOL
350 if (mValues.empty() || annotationType != BOOL_TYPE || !checkPreviousValueType(INT) ||
351 numElements) {
352 VLOG("Atom ID %d error while parseExclusiveStateAnnotation()", mTagId);
353 mValid = false;
354 return;
355 }
356
357 const bool exclusiveState = readNextValue<uint8_t>();
358 mExclusiveStateFieldIndex = mValues.size() - 1;
359 mValues[getExclusiveStateFieldIndex().value()].mAnnotations.setExclusiveState(exclusiveState);
360 }
361
parseTriggerStateResetAnnotation(uint8_t annotationType,std::optional<uint8_t> numElements)362 void LogEvent::parseTriggerStateResetAnnotation(uint8_t annotationType,
363 std::optional<uint8_t> numElements) {
364 // Allowed types: INT
365 if (mValues.empty() || annotationType != INT32_TYPE || !checkPreviousValueType(INT) ||
366 numElements) {
367 VLOG("Atom ID %d error while parseTriggerStateResetAnnotation()", mTagId);
368 mValid = false;
369 return;
370 }
371
372 mResetState = readNextValue<int32_t>();
373 }
374
parseStateNestedAnnotation(uint8_t annotationType,std::optional<uint8_t> numElements)375 void LogEvent::parseStateNestedAnnotation(uint8_t annotationType,
376 std::optional<uint8_t> numElements) {
377 // Allowed types: BOOL
378 if (mValues.empty() || annotationType != BOOL_TYPE || !checkPreviousValueType(INT) ||
379 numElements) {
380 VLOG("Atom ID %d error while parseStateNestedAnnotation()", mTagId);
381 mValid = false;
382 return;
383 }
384
385 bool nested = readNextValue<uint8_t>();
386 mValues[mValues.size() - 1].mAnnotations.setNested(nested);
387 }
388
parseRestrictionCategoryAnnotation(uint8_t annotationType)389 void LogEvent::parseRestrictionCategoryAnnotation(uint8_t annotationType) {
390 // Allowed types: INT, field value should be empty since this is atom-level annotation.
391 if (!mValues.empty() || annotationType != INT32_TYPE) {
392 mValid = false;
393 return;
394 }
395 int value = readNextValue<int32_t>();
396 // should be one of predefined category in StatsLog.java
397 switch (value) {
398 case ASTATSLOG_RESTRICTION_CATEGORY_DIAGNOSTIC:
399 case ASTATSLOG_RESTRICTION_CATEGORY_SYSTEM_INTELLIGENCE:
400 case ASTATSLOG_RESTRICTION_CATEGORY_AUTHENTICATION:
401 case ASTATSLOG_RESTRICTION_CATEGORY_FRAUD_AND_ABUSE:
402 break;
403 default:
404 mValid = false;
405 return;
406 }
407 mRestrictionCategory = static_cast<StatsdRestrictionCategory>(value);
408 return;
409 }
410
parseFieldRestrictionAnnotation(uint8_t annotationType)411 void LogEvent::parseFieldRestrictionAnnotation(uint8_t annotationType) {
412 // Allowed types: BOOL
413 if (mValues.empty() || annotationType != BOOL_TYPE) {
414 mValid = false;
415 return;
416 }
417 // Read the value so that the rest of the event is correctly parsed
418 // TODO: store the field annotations once the metrics need to parse them.
419 readNextValue<uint8_t>();
420 return;
421 }
422
423 // firstUidInChainIndex is a default parameter that is only needed when parsing
424 // annotations for attribution chains.
425 // numElements is a default param that is only needed when parsing annotations for repeated fields
parseAnnotations(uint8_t numAnnotations,std::optional<uint8_t> numElements,std::optional<size_t> firstUidInChainIndex)426 void LogEvent::parseAnnotations(uint8_t numAnnotations, std::optional<uint8_t> numElements,
427 std::optional<size_t> firstUidInChainIndex) {
428 for (uint8_t i = 0; i < numAnnotations; i++) {
429 uint8_t annotationId = readNextValue<uint8_t>();
430 uint8_t annotationType = readNextValue<uint8_t>();
431
432 switch (annotationId) {
433 case ASTATSLOG_ANNOTATION_ID_IS_UID:
434 parseIsUidAnnotation(annotationType, numElements);
435 break;
436 case ASTATSLOG_ANNOTATION_ID_TRUNCATE_TIMESTAMP:
437 parseTruncateTimestampAnnotation(annotationType);
438 break;
439 case ASTATSLOG_ANNOTATION_ID_PRIMARY_FIELD:
440 parsePrimaryFieldAnnotation(annotationType, numElements, firstUidInChainIndex);
441 break;
442 case ASTATSLOG_ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID:
443 parsePrimaryFieldFirstUidAnnotation(annotationType, firstUidInChainIndex);
444 break;
445 case ASTATSLOG_ANNOTATION_ID_EXCLUSIVE_STATE:
446 parseExclusiveStateAnnotation(annotationType, numElements);
447 break;
448 case ASTATSLOG_ANNOTATION_ID_TRIGGER_STATE_RESET:
449 parseTriggerStateResetAnnotation(annotationType, numElements);
450 break;
451 case ASTATSLOG_ANNOTATION_ID_STATE_NESTED:
452 parseStateNestedAnnotation(annotationType, numElements);
453 break;
454 case ASTATSLOG_ANNOTATION_ID_RESTRICTION_CATEGORY:
455 if (isAtLeastU()) {
456 parseRestrictionCategoryAnnotation(annotationType);
457 } else {
458 mValid = false;
459 }
460 break;
461 // Currently field restrictions are ignored, so we parse but do not store them.
462 case ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_PERIPHERAL_DEVICE_INFO:
463 case ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_APP_USAGE:
464 case ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_APP_ACTIVITY:
465 case ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_HEALTH_CONNECT:
466 case ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_ACCESSIBILITY:
467 case ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_SYSTEM_SEARCH:
468 case ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_USER_ENGAGEMENT:
469 case ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_AMBIENT_SENSING:
470 case ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_DEMOGRAPHIC_CLASSIFICATION:
471 if (isAtLeastU()) {
472 parseFieldRestrictionAnnotation(annotationType);
473 } else {
474 mValid = false;
475 }
476 break;
477 default:
478 VLOG("Atom ID %d error while parseAnnotations() - wrong annotationId(%d)", mTagId,
479 annotationId);
480 mValid = false;
481 return;
482 }
483 }
484 }
485
parseHeader(const uint8_t * buf,size_t len)486 LogEvent::BodyBufferInfo LogEvent::parseHeader(const uint8_t* buf, size_t len) {
487 BodyBufferInfo bodyInfo;
488
489 mParsedHeaderOnly = true;
490
491 mBuf = buf;
492 mRemainingLen = (uint32_t)len;
493
494 // Beginning of buffer is OBJECT_TYPE | NUM_FIELDS | TIMESTAMP | ATOM_ID
495 uint8_t typeInfo = readNextValue<uint8_t>();
496 if (getTypeId(typeInfo) != OBJECT_TYPE) {
497 mValid = false;
498 mBuf = nullptr;
499 return bodyInfo;
500 }
501
502 uint8_t numElements = readNextValue<uint8_t>();
503 if (numElements < 2 || numElements > INT8_MAX) {
504 mValid = false;
505 mBuf = nullptr;
506 return bodyInfo;
507 }
508
509 typeInfo = readNextValue<uint8_t>();
510 if (getTypeId(typeInfo) != INT64_TYPE) {
511 mValid = false;
512 mBuf = nullptr;
513 return bodyInfo;
514 }
515 mElapsedTimestampNs = readNextValue<int64_t>();
516 numElements--;
517
518 typeInfo = readNextValue<uint8_t>();
519 if (getTypeId(typeInfo) != INT32_TYPE) {
520 mValid = false;
521 mBuf = nullptr;
522 return bodyInfo;
523 }
524 mTagId = readNextValue<int32_t>();
525 numElements--;
526
527 parseAnnotations(getNumAnnotations(typeInfo)); // atom-level annotations
528
529 bodyInfo.numElements = numElements;
530 bodyInfo.buffer = mBuf;
531 bodyInfo.bufferSize = mRemainingLen;
532
533 mBuf = nullptr;
534 return bodyInfo;
535 }
536
parseBody(const BodyBufferInfo & bodyInfo)537 bool LogEvent::parseBody(const BodyBufferInfo& bodyInfo) {
538 mParsedHeaderOnly = false;
539
540 mBuf = bodyInfo.buffer;
541 mRemainingLen = (uint32_t)bodyInfo.bufferSize;
542
543 int32_t pos[] = {1, 1, 1};
544 bool last[] = {false, false, false};
545
546 // While this number is not guaranteed to be correct due to repeated fields and
547 // attribution chains, it still positively affects performance and reduces the number
548 // of vector buffer reallocations.
549 mValues.reserve(bodyInfo.numElements);
550
551 for (pos[0] = 1; pos[0] <= bodyInfo.numElements && mValid; pos[0]++) {
552 last[0] = (pos[0] == bodyInfo.numElements);
553
554 uint8_t typeInfo = readNextValue<uint8_t>();
555 uint8_t typeId = getTypeId(typeInfo);
556
557 switch (typeId) {
558 case BOOL_TYPE:
559 parseBool(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
560 break;
561 case INT32_TYPE:
562 parseInt32(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
563 break;
564 case INT64_TYPE:
565 parseInt64(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
566 break;
567 case FLOAT_TYPE:
568 parseFloat(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
569 break;
570 case BYTE_ARRAY_TYPE:
571 parseByteArray(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
572 break;
573 case STRING_TYPE:
574 parseString(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
575 break;
576 case KEY_VALUE_PAIRS_TYPE:
577 parseKeyValuePairs(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
578 break;
579 case ATTRIBUTION_CHAIN_TYPE:
580 parseAttributionChain(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
581 break;
582 case LIST_TYPE:
583 parseArray(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
584 break;
585 case ERROR_TYPE:
586 /* mErrorBitmask =*/readNextValue<int32_t>();
587 mValid = false;
588 break;
589 default:
590 mValid = false;
591 break;
592 }
593 }
594
595 if (mRemainingLen != 0) mValid = false;
596 mBuf = nullptr;
597 return mValid;
598 }
599
600 // This parsing logic is tied to the encoding scheme used in StatsEvent.java and
601 // stats_event.c
parseBuffer(const uint8_t * buf,size_t len)602 bool LogEvent::parseBuffer(const uint8_t* buf, size_t len) {
603 BodyBufferInfo bodyInfo = parseHeader(buf, len);
604
605 // emphasize intention to parse the body, however atom data could be incomplete
606 // if header/body parsing was failed due to invalid buffer content for example
607 mParsedHeaderOnly = false;
608
609 // early termination if header is invalid
610 if (!mValid) {
611 mBuf = nullptr;
612 return false;
613 }
614
615 return parseBody(bodyInfo);
616 }
617
GetLong(size_t key,status_t * err) const618 int64_t LogEvent::GetLong(size_t key, status_t* err) const {
619 // TODO(b/110561208): encapsulate the magical operations in Field struct as static functions
620 int field = getSimpleField(key);
621 for (const auto& value : mValues) {
622 if (value.mField.getField() == field) {
623 if (value.mValue.getType() == LONG) {
624 return value.mValue.long_value;
625 } else if (value.mValue.getType() == INT) {
626 return value.mValue.int_value;
627 } else {
628 *err = BAD_TYPE;
629 return 0;
630 }
631 }
632 if ((size_t)value.mField.getPosAtDepth(0) > key) {
633 break;
634 }
635 }
636
637 *err = BAD_INDEX;
638 return 0;
639 }
640
GetInt(size_t key,status_t * err) const641 int LogEvent::GetInt(size_t key, status_t* err) const {
642 int field = getSimpleField(key);
643 for (const auto& value : mValues) {
644 if (value.mField.getField() == field) {
645 if (value.mValue.getType() == INT) {
646 return value.mValue.int_value;
647 } else {
648 *err = BAD_TYPE;
649 return 0;
650 }
651 }
652 if ((size_t)value.mField.getPosAtDepth(0) > key) {
653 break;
654 }
655 }
656
657 *err = BAD_INDEX;
658 return 0;
659 }
660
GetString(size_t key,status_t * err) const661 const char* LogEvent::GetString(size_t key, status_t* err) const {
662 int field = getSimpleField(key);
663 for (const auto& value : mValues) {
664 if (value.mField.getField() == field) {
665 if (value.mValue.getType() == STRING) {
666 return value.mValue.str_value.c_str();
667 } else {
668 *err = BAD_TYPE;
669 return 0;
670 }
671 }
672 if ((size_t)value.mField.getPosAtDepth(0) > key) {
673 break;
674 }
675 }
676
677 *err = BAD_INDEX;
678 return NULL;
679 }
680
GetBool(size_t key,status_t * err) const681 bool LogEvent::GetBool(size_t key, status_t* err) const {
682 int field = getSimpleField(key);
683 for (const auto& value : mValues) {
684 if (value.mField.getField() == field) {
685 if (value.mValue.getType() == INT) {
686 return value.mValue.int_value != 0;
687 } else if (value.mValue.getType() == LONG) {
688 return value.mValue.long_value != 0;
689 } else {
690 *err = BAD_TYPE;
691 return false;
692 }
693 }
694 if ((size_t)value.mField.getPosAtDepth(0) > key) {
695 break;
696 }
697 }
698
699 *err = BAD_INDEX;
700 return false;
701 }
702
GetFloat(size_t key,status_t * err) const703 float LogEvent::GetFloat(size_t key, status_t* err) const {
704 int field = getSimpleField(key);
705 for (const auto& value : mValues) {
706 if (value.mField.getField() == field) {
707 if (value.mValue.getType() == FLOAT) {
708 return value.mValue.float_value;
709 } else {
710 *err = BAD_TYPE;
711 return 0.0;
712 }
713 }
714 if ((size_t)value.mField.getPosAtDepth(0) > key) {
715 break;
716 }
717 }
718
719 *err = BAD_INDEX;
720 return 0.0;
721 }
722
GetStorage(size_t key,status_t * err) const723 std::vector<uint8_t> LogEvent::GetStorage(size_t key, status_t* err) const {
724 int field = getSimpleField(key);
725 for (const auto& value : mValues) {
726 if (value.mField.getField() == field) {
727 if (value.mValue.getType() == STORAGE) {
728 return value.mValue.storage_value;
729 } else {
730 *err = BAD_TYPE;
731 return vector<uint8_t>();
732 }
733 }
734 if ((size_t)value.mField.getPosAtDepth(0) > key) {
735 break;
736 }
737 }
738
739 *err = BAD_INDEX;
740 return vector<uint8_t>();
741 }
742
ToString() const743 string LogEvent::ToString() const {
744 string result;
745 result += StringPrintf("{ uid(%d) %lld %lld (%d)", mLogUid, (long long)mLogdTimestampNs,
746 (long long)mElapsedTimestampNs, mTagId);
747 string annotations;
748 if (mTruncateTimestamp) {
749 annotations = "TRUNCATE_TS";
750 }
751 if (mResetState != -1) {
752 annotations += annotations.size() ? ", RESET_STATE" : "RESET_STATE";
753 }
754 if (annotations.size()) {
755 result += " [" + annotations + "] ";
756 }
757
758 if (isParsedHeaderOnly()) {
759 result += " ParsedHeaderOnly }";
760 return result;
761 }
762
763 for (const auto& value : mValues) {
764 result += StringPrintf("%#x", value.mField.getField()) + "->" + value.mValue.toString();
765 result += value.mAnnotations.toString() + " ";
766 }
767 result += " }";
768 return result;
769 }
770
ToProto(ProtoOutputStream & protoOutput) const771 void LogEvent::ToProto(ProtoOutputStream& protoOutput) const {
772 writeFieldValueTreeToStream(mTagId, getValues(), &protoOutput);
773 }
774
hasAttributionChain(std::pair<size_t,size_t> * indexRange) const775 bool LogEvent::hasAttributionChain(std::pair<size_t, size_t>* indexRange) const {
776 if (!mAttributionChainStartIndex || !mAttributionChainEndIndex) {
777 return false;
778 }
779
780 if (nullptr != indexRange) {
781 indexRange->first = mAttributionChainStartIndex.value();
782 indexRange->second = mAttributionChainEndIndex.value();
783 }
784
785 return true;
786 }
787
writeExperimentIdsToProto(const std::vector<int64_t> & experimentIds,std::vector<uint8_t> * protoOut)788 void writeExperimentIdsToProto(const std::vector<int64_t>& experimentIds,
789 std::vector<uint8_t>* protoOut) {
790 ProtoOutputStream proto;
791 for (const auto& expId : experimentIds) {
792 proto.write(FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED | FIELD_ID_EXPERIMENT_ID,
793 (long long)expId);
794 }
795
796 protoOut->resize(proto.size());
797 size_t pos = 0;
798 sp<ProtoReader> reader = proto.data();
799 while (reader->readBuffer() != NULL) {
800 size_t toRead = reader->currentToRead();
801 std::memcpy(protoOut->data() + pos, reader->readBuffer(), toRead);
802 pos += toRead;
803 reader->move(toRead);
804 }
805 }
806
807 } // namespace statsd
808 } // namespace os
809 } // namespace android
810