• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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-modules-utils/sdk_level.h>
24 #include <android/binder_ibinder.h>
25 #include <private/android_filesystem_config.h>
26 
27 #include "flags/FlagProvider.h"
28 #include "stats_annotations.h"
29 #include "stats_log_util.h"
30 #include "statslog_statsd.h"
31 
32 namespace android {
33 namespace os {
34 namespace statsd {
35 
36 // for TrainInfo experiment id serialization
37 const int FIELD_ID_EXPERIMENT_ID = 1;
38 
39 using namespace android::util;
40 using android::base::StringPrintf;
41 using android::modules::sdklevel::IsAtLeastU;
42 using android::util::ProtoOutputStream;
43 using std::string;
44 using std::vector;
45 
46 namespace {
47 
getTypeId(uint8_t typeInfo)48 uint8_t getTypeId(uint8_t typeInfo) {
49     return typeInfo & 0x0F;  // type id in lower 4 bytes
50 }
51 
getNumAnnotations(uint8_t typeInfo)52 uint8_t getNumAnnotations(uint8_t typeInfo) {
53     return (typeInfo >> 4) & 0x0F;  // num annotations in upper 4 bytes
54 }
55 
56 }  // namespace
57 
LogEvent(int32_t uid,int32_t pid)58 LogEvent::LogEvent(int32_t uid, int32_t pid)
59     : mLogdTimestampNs(getWallClockNs()), mLogUid(uid), mLogPid(pid) {
60 }
61 
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)62 LogEvent::LogEvent(const string& trainName, int64_t trainVersionCode, bool requiresStaging,
63                    bool rollbackEnabled, bool requiresLowLatencyMonitor, int32_t state,
64                    const std::vector<uint8_t>& experimentIds, int32_t userId) {
65     mLogdTimestampNs = getWallClockNs();
66     mElapsedTimestampNs = getElapsedRealtimeNs();
67     mTagId = util::BINARY_PUSH_STATE_CHANGED;
68     mLogUid = AIBinder_getCallingUid();
69     mLogPid = AIBinder_getCallingPid();
70 
71     mValues.push_back(FieldValue(Field(mTagId, getSimpleField(1)), Value(trainName)));
72     mValues.push_back(FieldValue(Field(mTagId, getSimpleField(2)), Value(trainVersionCode)));
73     mValues.push_back(FieldValue(Field(mTagId, getSimpleField(3)), Value((int)requiresStaging)));
74     mValues.push_back(FieldValue(Field(mTagId, getSimpleField(4)), Value((int)rollbackEnabled)));
75     mValues.push_back(
76             FieldValue(Field(mTagId, getSimpleField(5)), Value((int)requiresLowLatencyMonitor)));
77     mValues.push_back(FieldValue(Field(mTagId, getSimpleField(6)), Value(state)));
78     mValues.push_back(FieldValue(Field(mTagId, getSimpleField(7)), Value(experimentIds)));
79     mValues.push_back(FieldValue(Field(mTagId, getSimpleField(8)), Value(userId)));
80 }
81 
LogEvent(int64_t wallClockTimestampNs,int64_t elapsedTimestampNs,const InstallTrainInfo & trainInfo)82 LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
83                    const InstallTrainInfo& trainInfo) {
84     mLogdTimestampNs = wallClockTimestampNs;
85     mElapsedTimestampNs = elapsedTimestampNs;
86     mTagId = util::TRAIN_INFO;
87 
88     mValues.push_back(
89             FieldValue(Field(mTagId, getSimpleField(1)), Value(trainInfo.trainVersionCode)));
90     std::vector<uint8_t> experimentIdsProto;
91     writeExperimentIdsToProto(trainInfo.experimentIds, &experimentIdsProto);
92     mValues.push_back(FieldValue(Field(mTagId, getSimpleField(2)), Value(experimentIdsProto)));
93     mValues.push_back(FieldValue(Field(mTagId, getSimpleField(3)), Value(trainInfo.trainName)));
94     mValues.push_back(FieldValue(Field(mTagId, getSimpleField(4)), Value(trainInfo.status)));
95 }
96 
parseInt32(int32_t * pos,int32_t depth,bool * last,uint8_t numAnnotations)97 void LogEvent::parseInt32(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
98     int32_t value = readNextValue<int32_t>();
99     addToValues(pos, depth, value, last);
100     parseAnnotations(numAnnotations);
101 }
102 
parseInt64(int32_t * pos,int32_t depth,bool * last,uint8_t numAnnotations)103 void LogEvent::parseInt64(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
104     int64_t value = readNextValue<int64_t>();
105     addToValues(pos, depth, value, last);
106     parseAnnotations(numAnnotations);
107 }
108 
parseString(int32_t * pos,int32_t depth,bool * last,uint8_t numAnnotations)109 void LogEvent::parseString(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
110     int32_t numBytes = readNextValue<int32_t>();
111     if ((uint32_t)numBytes > mRemainingLen) {
112         mValid = false;
113         return;
114     }
115 
116     string value = string((char*)mBuf, numBytes);
117     mBuf += numBytes;
118     mRemainingLen -= numBytes;
119     addToValues(pos, depth, value, last);
120     parseAnnotations(numAnnotations);
121 }
122 
parseFloat(int32_t * pos,int32_t depth,bool * last,uint8_t numAnnotations)123 void LogEvent::parseFloat(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
124     float value = readNextValue<float>();
125     addToValues(pos, depth, value, last);
126     parseAnnotations(numAnnotations);
127 }
128 
parseBool(int32_t * pos,int32_t depth,bool * last,uint8_t numAnnotations)129 void LogEvent::parseBool(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
130     // cast to int32_t because FieldValue does not support bools
131     int32_t value = (int32_t)readNextValue<uint8_t>();
132     addToValues(pos, depth, value, last);
133     parseAnnotations(numAnnotations);
134 }
135 
parseByteArray(int32_t * pos,int32_t depth,bool * last,uint8_t numAnnotations)136 void LogEvent::parseByteArray(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
137     int32_t numBytes = readNextValue<int32_t>();
138     if ((uint32_t)numBytes > mRemainingLen) {
139         mValid = false;
140         return;
141     }
142 
143     vector<uint8_t> value(mBuf, mBuf + numBytes);
144     mBuf += numBytes;
145     mRemainingLen -= numBytes;
146     addToValues(pos, depth, value, last);
147     parseAnnotations(numAnnotations);
148 }
149 
parseKeyValuePairs(int32_t * pos,int32_t depth,bool * last,uint8_t numAnnotations)150 void LogEvent::parseKeyValuePairs(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
151     int32_t numPairs = readNextValue<uint8_t>();
152 
153     for (pos[1] = 1; pos[1] <= numPairs; pos[1]++) {
154         last[1] = (pos[1] == numPairs);
155 
156         // parse key
157         pos[2] = 1;
158         parseInt32(pos, /*depth=*/2, last, /*numAnnotations=*/0);
159 
160         // parse value
161         last[2] = true;
162 
163         uint8_t typeInfo = readNextValue<uint8_t>();
164         switch (getTypeId(typeInfo)) {
165             case INT32_TYPE:
166                 pos[2] = 2;  // pos[2] determined by index of type in KeyValuePair in atoms.proto
167                 parseInt32(pos, /*depth=*/2, last, /*numAnnotations=*/0);
168                 break;
169             case INT64_TYPE:
170                 pos[2] = 3;
171                 parseInt64(pos, /*depth=*/2, last, /*numAnnotations=*/0);
172                 break;
173             case STRING_TYPE:
174                 pos[2] = 4;
175                 parseString(pos, /*depth=*/2, last, /*numAnnotations=*/0);
176                 break;
177             case FLOAT_TYPE:
178                 pos[2] = 5;
179                 parseFloat(pos, /*depth=*/2, last, /*numAnnotations=*/0);
180                 break;
181             default:
182                 mValid = false;
183         }
184     }
185 
186     parseAnnotations(numAnnotations);
187 
188     pos[1] = pos[2] = 1;
189     last[1] = last[2] = false;
190 }
191 
parseAttributionChain(int32_t * pos,int32_t depth,bool * last,uint8_t numAnnotations)192 void LogEvent::parseAttributionChain(int32_t* pos, int32_t depth, bool* last,
193                                      uint8_t numAnnotations) {
194     std::optional<size_t> firstUidInChainIndex = mValues.size();
195     const uint8_t numNodes = readNextValue<uint8_t>();
196 
197     if (numNodes > INT8_MAX) mValid = false;
198 
199     for (pos[1] = 1; pos[1] <= numNodes; pos[1]++) {
200         last[1] = (pos[1] == numNodes);
201 
202         // parse uid
203         pos[2] = 1;
204         parseInt32(pos, /*depth=*/2, last, /*numAnnotations=*/0);
205 
206         // parse tag
207         pos[2] = 2;
208         last[2] = true;
209         parseString(pos, /*depth=*/2, last, /*numAnnotations=*/0);
210     }
211 
212     if (mValues.size() > (firstUidInChainIndex.value() + 1)) {
213         // At least one node was successfully parsed.
214         mAttributionChainStartIndex = firstUidInChainIndex;
215         mAttributionChainEndIndex = mValues.size() - 1;
216     } else {
217         firstUidInChainIndex = std::nullopt;
218         mValid = false;
219     }
220 
221     if (mValid) {
222         parseAnnotations(numAnnotations, /*numElements*/ std::nullopt, firstUidInChainIndex);
223     }
224 
225     pos[1] = pos[2] = 1;
226     last[1] = last[2] = false;
227 }
228 
parseArray(int32_t * pos,int32_t depth,bool * last,uint8_t numAnnotations)229 void LogEvent::parseArray(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
230     const uint8_t numElements = readNextValue<uint8_t>();
231     const uint8_t typeInfo = readNextValue<uint8_t>();
232     const uint8_t typeId = getTypeId(typeInfo);
233 
234     if (numElements > INT8_MAX) mValid = false;
235 
236     for (pos[1] = 1; pos[1] <= numElements; pos[1]++) {
237         last[1] = (pos[1] == numElements);
238 
239         // The top-level array is at depth 0, and all of its elements are at depth 1.
240         // Once nested fields are supported, array elements will be at top-level depth + 1.
241 
242         switch (typeId) {
243             case INT32_TYPE:
244                 parseInt32(pos, /*depth=*/1, last, /*numAnnotations=*/0);
245                 break;
246             case INT64_TYPE:
247                 parseInt64(pos, /*depth=*/1, last, /*numAnnotations=*/0);
248                 break;
249             case FLOAT_TYPE:
250                 parseFloat(pos, /*depth=*/1, last, /*numAnnotations=*/0);
251                 break;
252             case BOOL_TYPE:
253                 parseBool(pos, /*depth=*/1, last, /*numAnnotations=*/0);
254                 break;
255             case STRING_TYPE:
256                 parseString(pos, /*depth=*/1, last, /*numAnnotations=*/0);
257                 break;
258             default:
259                 mValid = false;
260                 break;
261         }
262     }
263 
264     parseAnnotations(numAnnotations, numElements);
265 
266     pos[1] = 1;
267     last[1] = false;
268 }
269 
270 // Assumes that mValues is not empty
checkPreviousValueType(Type expected)271 bool LogEvent::checkPreviousValueType(Type expected) {
272     return mValues[mValues.size() - 1].mValue.getType() == expected;
273 }
274 
parseIsUidAnnotation(uint8_t annotationType,std::optional<uint8_t> numElements)275 void LogEvent::parseIsUidAnnotation(uint8_t annotationType, std::optional<uint8_t> numElements) {
276     // Need to set numElements if not an array.
277     if (!numElements) {
278         numElements = 1;
279     }
280 
281     // If array is empty, skip uid parsing.
282     if (numElements == 0 && annotationType == BOOL_TYPE) {
283         readNextValue<uint8_t>();
284         return;
285     }
286 
287     // Allowed types: INT, repeated INT
288     if (numElements > mValues.size() || !checkPreviousValueType(INT) ||
289         annotationType != BOOL_TYPE) {
290         VLOG("Atom ID %d error while parseIsUidAnnotation()", mTagId);
291         mValid = false;
292         return;
293     }
294 
295     bool isUid = readNextValue<uint8_t>();
296     if (isUid) {
297         mNumUidFields += numElements.value();
298     }
299 
300     for (int i = 1; i <= numElements; i++) {
301         mValues[mValues.size() - i].mAnnotations.setUidField(isUid);
302     }
303 }
304 
parseTruncateTimestampAnnotation(uint8_t annotationType)305 void LogEvent::parseTruncateTimestampAnnotation(uint8_t annotationType) {
306     if (!mValues.empty() || annotationType != BOOL_TYPE) {
307         VLOG("Atom ID %d error while parseTruncateTimestampAnnotation()", mTagId);
308         mValid = false;
309         return;
310     }
311 
312     mTruncateTimestamp = readNextValue<uint8_t>();
313 }
314 
parsePrimaryFieldAnnotation(uint8_t annotationType,std::optional<uint8_t> numElements,std::optional<size_t> firstUidInChainIndex)315 void LogEvent::parsePrimaryFieldAnnotation(uint8_t annotationType,
316                                            std::optional<uint8_t> numElements,
317                                            std::optional<size_t> firstUidInChainIndex) {
318     // Allowed types: all types except for attribution chains and repeated fields.
319     if (mValues.empty() || annotationType != BOOL_TYPE || firstUidInChainIndex || numElements) {
320         VLOG("Atom ID %d error while parsePrimaryFieldAnnotation()", mTagId);
321         mValid = false;
322         return;
323     }
324 
325     const bool primaryField = readNextValue<uint8_t>();
326     mValues[mValues.size() - 1].mAnnotations.setPrimaryField(primaryField);
327 }
328 
parsePrimaryFieldFirstUidAnnotation(uint8_t annotationType,std::optional<size_t> firstUidInChainIndex)329 void LogEvent::parsePrimaryFieldFirstUidAnnotation(uint8_t annotationType,
330                                                    std::optional<size_t> firstUidInChainIndex) {
331     // Allowed types: attribution chains
332     if (mValues.empty() || annotationType != BOOL_TYPE || !firstUidInChainIndex) {
333         VLOG("Atom ID %d error while parsePrimaryFieldFirstUidAnnotation()", mTagId);
334         mValid = false;
335         return;
336     }
337 
338     if (mValues.size() < firstUidInChainIndex.value() + 1) {  // AttributionChain is empty.
339         VLOG("Atom ID %d error while parsePrimaryFieldFirstUidAnnotation()", mTagId);
340         mValid = false;
341         android_errorWriteLog(0x534e4554, "174485572");
342         return;
343     }
344 
345     const bool primaryField = readNextValue<uint8_t>();
346     mValues[firstUidInChainIndex.value()].mAnnotations.setPrimaryField(primaryField);
347 }
348 
parseExclusiveStateAnnotation(uint8_t annotationType,std::optional<uint8_t> numElements)349 void LogEvent::parseExclusiveStateAnnotation(uint8_t annotationType,
350                                              std::optional<uint8_t> numElements) {
351     // Allowed types: BOOL
352     if (mValues.empty() || annotationType != BOOL_TYPE || !checkPreviousValueType(INT) ||
353         numElements) {
354         VLOG("Atom ID %d error while parseExclusiveStateAnnotation()", mTagId);
355         mValid = false;
356         return;
357     }
358 
359     const bool exclusiveState = readNextValue<uint8_t>();
360     mExclusiveStateFieldIndex = mValues.size() - 1;
361     mValues[getExclusiveStateFieldIndex().value()].mAnnotations.setExclusiveState(exclusiveState);
362 }
363 
parseTriggerStateResetAnnotation(uint8_t annotationType,std::optional<uint8_t> numElements)364 void LogEvent::parseTriggerStateResetAnnotation(uint8_t annotationType,
365                                                 std::optional<uint8_t> numElements) {
366     // Allowed types: INT
367     if (mValues.empty() || annotationType != INT32_TYPE || !checkPreviousValueType(INT) ||
368         numElements) {
369         VLOG("Atom ID %d error while parseTriggerStateResetAnnotation()", mTagId);
370         mValid = false;
371         return;
372     }
373 
374     mResetState = readNextValue<int32_t>();
375 }
376 
parseStateNestedAnnotation(uint8_t annotationType,std::optional<uint8_t> numElements)377 void LogEvent::parseStateNestedAnnotation(uint8_t annotationType,
378                                           std::optional<uint8_t> numElements) {
379     // Allowed types: BOOL
380     if (mValues.empty() || annotationType != BOOL_TYPE || !checkPreviousValueType(INT) ||
381         numElements) {
382         VLOG("Atom ID %d error while parseStateNestedAnnotation()", mTagId);
383         mValid = false;
384         return;
385     }
386 
387     bool nested = readNextValue<uint8_t>();
388     mValues[mValues.size() - 1].mAnnotations.setNested(nested);
389 }
390 
parseRestrictionCategoryAnnotation(uint8_t annotationType)391 void LogEvent::parseRestrictionCategoryAnnotation(uint8_t annotationType) {
392     // Allowed types: INT, field value should be empty since this is atom-level annotation.
393     if (!mValues.empty() || annotationType != INT32_TYPE) {
394         mValid = false;
395         return;
396     }
397     int value = readNextValue<int32_t>();
398     // should be one of predefined category in StatsLog.java
399     switch (value) {
400         // Only diagnostic is currently supported for use.
401         case ASTATSLOG_RESTRICTION_CATEGORY_DIAGNOSTIC:
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     for (pos[0] = 1; pos[0] <= bodyInfo.numElements && mValid; pos[0]++) {
547         last[0] = (pos[0] == bodyInfo.numElements);
548 
549         uint8_t typeInfo = readNextValue<uint8_t>();
550         uint8_t typeId = getTypeId(typeInfo);
551 
552         switch (typeId) {
553             case BOOL_TYPE:
554                 parseBool(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
555                 break;
556             case INT32_TYPE:
557                 parseInt32(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
558                 break;
559             case INT64_TYPE:
560                 parseInt64(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
561                 break;
562             case FLOAT_TYPE:
563                 parseFloat(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
564                 break;
565             case BYTE_ARRAY_TYPE:
566                 parseByteArray(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
567                 break;
568             case STRING_TYPE:
569                 parseString(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
570                 break;
571             case KEY_VALUE_PAIRS_TYPE:
572                 parseKeyValuePairs(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
573                 break;
574             case ATTRIBUTION_CHAIN_TYPE:
575                 parseAttributionChain(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
576                 break;
577             case LIST_TYPE:
578                 parseArray(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
579                 break;
580             case ERROR_TYPE:
581                 /* mErrorBitmask =*/readNextValue<int32_t>();
582                 mValid = false;
583                 break;
584             default:
585                 mValid = false;
586                 break;
587         }
588     }
589 
590     if (mRemainingLen != 0) mValid = false;
591     mBuf = nullptr;
592     return mValid;
593 }
594 
595 // This parsing logic is tied to the encoding scheme used in StatsEvent.java and
596 // stats_event.c
parseBuffer(const uint8_t * buf,size_t len)597 bool LogEvent::parseBuffer(const uint8_t* buf, size_t len) {
598     BodyBufferInfo bodyInfo = parseHeader(buf, len);
599 
600     // emphasize intention to parse the body, however atom data could be incomplete
601     // if header/body parsing was failed due to invalid buffer content for example
602     mParsedHeaderOnly = false;
603 
604     // early termination if header is invalid
605     if (!mValid) {
606         mBuf = nullptr;
607         return false;
608     }
609 
610     return parseBody(bodyInfo);
611 }
612 
GetLong(size_t key,status_t * err) const613 int64_t LogEvent::GetLong(size_t key, status_t* err) const {
614     // TODO(b/110561208): encapsulate the magical operations in Field struct as static functions
615     int field = getSimpleField(key);
616     for (const auto& value : mValues) {
617         if (value.mField.getField() == field) {
618             if (value.mValue.getType() == LONG) {
619                 return value.mValue.long_value;
620             } else if (value.mValue.getType() == INT) {
621                 return value.mValue.int_value;
622             } else {
623                 *err = BAD_TYPE;
624                 return 0;
625             }
626         }
627         if ((size_t)value.mField.getPosAtDepth(0) > key) {
628             break;
629         }
630     }
631 
632     *err = BAD_INDEX;
633     return 0;
634 }
635 
GetInt(size_t key,status_t * err) const636 int LogEvent::GetInt(size_t key, status_t* err) const {
637     int field = getSimpleField(key);
638     for (const auto& value : mValues) {
639         if (value.mField.getField() == field) {
640             if (value.mValue.getType() == INT) {
641                 return value.mValue.int_value;
642             } else {
643                 *err = BAD_TYPE;
644                 return 0;
645             }
646         }
647         if ((size_t)value.mField.getPosAtDepth(0) > key) {
648             break;
649         }
650     }
651 
652     *err = BAD_INDEX;
653     return 0;
654 }
655 
GetString(size_t key,status_t * err) const656 const char* LogEvent::GetString(size_t key, status_t* err) const {
657     int field = getSimpleField(key);
658     for (const auto& value : mValues) {
659         if (value.mField.getField() == field) {
660             if (value.mValue.getType() == STRING) {
661                 return value.mValue.str_value.c_str();
662             } else {
663                 *err = BAD_TYPE;
664                 return 0;
665             }
666         }
667         if ((size_t)value.mField.getPosAtDepth(0) > key) {
668             break;
669         }
670     }
671 
672     *err = BAD_INDEX;
673     return NULL;
674 }
675 
GetBool(size_t key,status_t * err) const676 bool LogEvent::GetBool(size_t key, status_t* err) const {
677     int field = getSimpleField(key);
678     for (const auto& value : mValues) {
679         if (value.mField.getField() == field) {
680             if (value.mValue.getType() == INT) {
681                 return value.mValue.int_value != 0;
682             } else if (value.mValue.getType() == LONG) {
683                 return value.mValue.long_value != 0;
684             } else {
685                 *err = BAD_TYPE;
686                 return false;
687             }
688         }
689         if ((size_t)value.mField.getPosAtDepth(0) > key) {
690             break;
691         }
692     }
693 
694     *err = BAD_INDEX;
695     return false;
696 }
697 
GetFloat(size_t key,status_t * err) const698 float LogEvent::GetFloat(size_t key, status_t* err) const {
699     int field = getSimpleField(key);
700     for (const auto& value : mValues) {
701         if (value.mField.getField() == field) {
702             if (value.mValue.getType() == FLOAT) {
703                 return value.mValue.float_value;
704             } else {
705                 *err = BAD_TYPE;
706                 return 0.0;
707             }
708         }
709         if ((size_t)value.mField.getPosAtDepth(0) > key) {
710             break;
711         }
712     }
713 
714     *err = BAD_INDEX;
715     return 0.0;
716 }
717 
GetStorage(size_t key,status_t * err) const718 std::vector<uint8_t> LogEvent::GetStorage(size_t key, status_t* err) const {
719     int field = getSimpleField(key);
720     for (const auto& value : mValues) {
721         if (value.mField.getField() == field) {
722             if (value.mValue.getType() == STORAGE) {
723                 return value.mValue.storage_value;
724             } else {
725                 *err = BAD_TYPE;
726                 return vector<uint8_t>();
727             }
728         }
729         if ((size_t)value.mField.getPosAtDepth(0) > key) {
730             break;
731         }
732     }
733 
734     *err = BAD_INDEX;
735     return vector<uint8_t>();
736 }
737 
ToString() const738 string LogEvent::ToString() const {
739     string result;
740     result += StringPrintf("{ uid(%d) %lld %lld (%d)", mLogUid, (long long)mLogdTimestampNs,
741                            (long long)mElapsedTimestampNs, mTagId);
742     string annotations;
743     if (mTruncateTimestamp) {
744         annotations = "TRUNCATE_TS";
745     }
746     if (mResetState != -1) {
747         annotations += annotations.size() ? ", RESET_STATE" : "RESET_STATE";
748     }
749     if (annotations.size()) {
750         result += " [" + annotations + "] ";
751     }
752 
753     if (isParsedHeaderOnly()) {
754         result += " ParsedHeaderOnly }";
755         return result;
756     }
757 
758     for (const auto& value : mValues) {
759         result += StringPrintf("%#x", value.mField.getField()) + "->" + value.mValue.toString();
760         result += value.mAnnotations.toString() + " ";
761     }
762     result += " }";
763     return result;
764 }
765 
ToProto(ProtoOutputStream & protoOutput) const766 void LogEvent::ToProto(ProtoOutputStream& protoOutput) const {
767     writeFieldValueTreeToStream(mTagId, getValues(), &protoOutput);
768 }
769 
hasAttributionChain(std::pair<size_t,size_t> * indexRange) const770 bool LogEvent::hasAttributionChain(std::pair<size_t, size_t>* indexRange) const {
771     if (!mAttributionChainStartIndex || !mAttributionChainEndIndex) {
772         return false;
773     }
774 
775     if (nullptr != indexRange) {
776         indexRange->first = mAttributionChainStartIndex.value();
777         indexRange->second = mAttributionChainEndIndex.value();
778     }
779 
780     return true;
781 }
782 
writeExperimentIdsToProto(const std::vector<int64_t> & experimentIds,std::vector<uint8_t> * protoOut)783 void writeExperimentIdsToProto(const std::vector<int64_t>& experimentIds,
784                                std::vector<uint8_t>* protoOut) {
785     ProtoOutputStream proto;
786     for (const auto& expId : experimentIds) {
787         proto.write(FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED | FIELD_ID_EXPERIMENT_ID,
788                     (long long)expId);
789     }
790 
791     protoOut->resize(proto.size());
792     size_t pos = 0;
793     sp<ProtoReader> reader = proto.data();
794     while (reader->readBuffer() != NULL) {
795         size_t toRead = reader->currentToRead();
796         std::memcpy(protoOut->data() + pos, reader->readBuffer(), toRead);
797         pos += toRead;
798         reader->move(toRead);
799     }
800 }
801 
802 }  // namespace statsd
803 }  // namespace os
804 }  // namespace android
805