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