• 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 "logd/LogEvent.h"
19 
20 #include <android-base/stringprintf.h>
21 #include <android/binder_ibinder.h>
22 #include <log/log.h>
23 #include <private/android_filesystem_config.h>
24 
25 #include "annotations.h"
26 #include "stats_log_util.h"
27 #include "statslog_statsd.h"
28 
29 namespace android {
30 namespace os {
31 namespace statsd {
32 
33 // for TrainInfo experiment id serialization
34 const int FIELD_ID_EXPERIMENT_ID = 1;
35 
36 using namespace android::util;
37 using android::base::StringPrintf;
38 using android::util::ProtoOutputStream;
39 using std::string;
40 using std::vector;
41 
LogEvent(int32_t uid,int32_t pid)42 LogEvent::LogEvent(int32_t uid, int32_t pid)
43     : mLogdTimestampNs(time(nullptr)), mLogUid(uid), mLogPid(pid) {
44 }
45 
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)46 LogEvent::LogEvent(const string& trainName, int64_t trainVersionCode, bool requiresStaging,
47                    bool rollbackEnabled, bool requiresLowLatencyMonitor, int32_t state,
48                    const std::vector<uint8_t>& experimentIds, int32_t userId) {
49     mLogdTimestampNs = getWallClockNs();
50     mElapsedTimestampNs = getElapsedRealtimeNs();
51     mTagId = util::BINARY_PUSH_STATE_CHANGED;
52     mLogUid = AIBinder_getCallingUid();
53     mLogPid = AIBinder_getCallingPid();
54 
55     mValues.push_back(FieldValue(Field(mTagId, getSimpleField(1)), Value(trainName)));
56     mValues.push_back(FieldValue(Field(mTagId, getSimpleField(2)), Value(trainVersionCode)));
57     mValues.push_back(FieldValue(Field(mTagId, getSimpleField(3)), Value((int)requiresStaging)));
58     mValues.push_back(FieldValue(Field(mTagId, getSimpleField(4)), Value((int)rollbackEnabled)));
59     mValues.push_back(
60             FieldValue(Field(mTagId, getSimpleField(5)), Value((int)requiresLowLatencyMonitor)));
61     mValues.push_back(FieldValue(Field(mTagId, getSimpleField(6)), Value(state)));
62     mValues.push_back(FieldValue(Field(mTagId, getSimpleField(7)), Value(experimentIds)));
63     mValues.push_back(FieldValue(Field(mTagId, getSimpleField(8)), Value(userId)));
64 }
65 
LogEvent(int64_t wallClockTimestampNs,int64_t elapsedTimestampNs,const InstallTrainInfo & trainInfo)66 LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
67                    const InstallTrainInfo& trainInfo) {
68     mLogdTimestampNs = wallClockTimestampNs;
69     mElapsedTimestampNs = elapsedTimestampNs;
70     mTagId = util::TRAIN_INFO;
71 
72     mValues.push_back(
73             FieldValue(Field(mTagId, getSimpleField(1)), Value(trainInfo.trainVersionCode)));
74     std::vector<uint8_t> experimentIdsProto;
75     writeExperimentIdsToProto(trainInfo.experimentIds, &experimentIdsProto);
76     mValues.push_back(FieldValue(Field(mTagId, getSimpleField(2)), Value(experimentIdsProto)));
77     mValues.push_back(FieldValue(Field(mTagId, getSimpleField(3)), Value(trainInfo.trainName)));
78     mValues.push_back(FieldValue(Field(mTagId, getSimpleField(4)), Value(trainInfo.status)));
79 }
80 
parseInt32(int32_t * pos,int32_t depth,bool * last,uint8_t numAnnotations)81 void LogEvent::parseInt32(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
82     int32_t value = readNextValue<int32_t>();
83     addToValues(pos, depth, value, last);
84     parseAnnotations(numAnnotations);
85 }
86 
parseInt64(int32_t * pos,int32_t depth,bool * last,uint8_t numAnnotations)87 void LogEvent::parseInt64(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
88     int64_t value = readNextValue<int64_t>();
89     addToValues(pos, depth, value, last);
90     parseAnnotations(numAnnotations);
91 }
92 
parseString(int32_t * pos,int32_t depth,bool * last,uint8_t numAnnotations)93 void LogEvent::parseString(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
94     int32_t numBytes = readNextValue<int32_t>();
95     if ((uint32_t)numBytes > mRemainingLen) {
96         mValid = false;
97         return;
98     }
99 
100     string value = string((char*)mBuf, numBytes);
101     mBuf += numBytes;
102     mRemainingLen -= numBytes;
103     addToValues(pos, depth, value, last);
104     parseAnnotations(numAnnotations);
105 }
106 
parseFloat(int32_t * pos,int32_t depth,bool * last,uint8_t numAnnotations)107 void LogEvent::parseFloat(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
108     float value = readNextValue<float>();
109     addToValues(pos, depth, value, last);
110     parseAnnotations(numAnnotations);
111 }
112 
parseBool(int32_t * pos,int32_t depth,bool * last,uint8_t numAnnotations)113 void LogEvent::parseBool(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
114     // cast to int32_t because FieldValue does not support bools
115     int32_t value = (int32_t)readNextValue<uint8_t>();
116     addToValues(pos, depth, value, last);
117     parseAnnotations(numAnnotations);
118 }
119 
parseByteArray(int32_t * pos,int32_t depth,bool * last,uint8_t numAnnotations)120 void LogEvent::parseByteArray(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
121     int32_t numBytes = readNextValue<int32_t>();
122     if ((uint32_t)numBytes > mRemainingLen) {
123         mValid = false;
124         return;
125     }
126 
127     vector<uint8_t> value(mBuf, mBuf + numBytes);
128     mBuf += numBytes;
129     mRemainingLen -= numBytes;
130     addToValues(pos, depth, value, last);
131     parseAnnotations(numAnnotations);
132 }
133 
parseKeyValuePairs(int32_t * pos,int32_t depth,bool * last,uint8_t numAnnotations)134 void LogEvent::parseKeyValuePairs(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
135     int32_t numPairs = readNextValue<uint8_t>();
136 
137     for (pos[1] = 1; pos[1] <= numPairs; pos[1]++) {
138         last[1] = (pos[1] == numPairs);
139 
140         // parse key
141         pos[2] = 1;
142         parseInt32(pos, /*depth=*/2, last, /*numAnnotations=*/0);
143 
144         // parse value
145         last[2] = true;
146 
147         uint8_t typeInfo = readNextValue<uint8_t>();
148         switch (getTypeId(typeInfo)) {
149             case INT32_TYPE:
150                 pos[2] = 2;  // pos[2] determined by index of type in KeyValuePair in atoms.proto
151                 parseInt32(pos, /*depth=*/2, last, /*numAnnotations=*/0);
152                 break;
153             case INT64_TYPE:
154                 pos[2] = 3;
155                 parseInt64(pos, /*depth=*/2, last, /*numAnnotations=*/0);
156                 break;
157             case STRING_TYPE:
158                 pos[2] = 4;
159                 parseString(pos, /*depth=*/2, last, /*numAnnotations=*/0);
160                 break;
161             case FLOAT_TYPE:
162                 pos[2] = 5;
163                 parseFloat(pos, /*depth=*/2, last, /*numAnnotations=*/0);
164                 break;
165             default:
166                 mValid = false;
167         }
168     }
169 
170     parseAnnotations(numAnnotations);
171 
172     pos[1] = pos[2] = 1;
173     last[1] = last[2] = false;
174 }
175 
parseAttributionChain(int32_t * pos,int32_t depth,bool * last,uint8_t numAnnotations)176 void LogEvent::parseAttributionChain(int32_t* pos, int32_t depth, bool* last,
177                                      uint8_t numAnnotations) {
178     std::optional<size_t> firstUidInChainIndex = mValues.size();
179     const uint8_t numNodes = readNextValue<uint8_t>();
180 
181     if (numNodes > INT8_MAX) mValid = false;
182 
183     for (pos[1] = 1; pos[1] <= numNodes; pos[1]++) {
184         last[1] = (pos[1] == numNodes);
185 
186         // parse uid
187         pos[2] = 1;
188         parseInt32(pos, /*depth=*/2, last, /*numAnnotations=*/0);
189 
190         // parse tag
191         pos[2] = 2;
192         last[2] = true;
193         parseString(pos, /*depth=*/2, last, /*numAnnotations=*/0);
194     }
195 
196     if (mValues.size() > (firstUidInChainIndex.value() + 1)) {
197         // At least one node was successfully parsed.
198         mAttributionChainStartIndex = firstUidInChainIndex;
199         mAttributionChainEndIndex = mValues.size() - 1;
200     } else {
201         firstUidInChainIndex = std::nullopt;
202         mValid = false;
203     }
204 
205     if (mValid) {
206         parseAnnotations(numAnnotations, /*numElements*/ std::nullopt, firstUidInChainIndex);
207     }
208 
209     pos[1] = pos[2] = 1;
210     last[1] = last[2] = false;
211 }
212 
parseArray(int32_t * pos,int32_t depth,bool * last,uint8_t numAnnotations)213 void LogEvent::parseArray(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
214     const uint8_t numElements = readNextValue<uint8_t>();
215     const uint8_t typeInfo = readNextValue<uint8_t>();
216     const uint8_t typeId = getTypeId(typeInfo);
217 
218     if (numElements > INT8_MAX) mValid = false;
219 
220     for (pos[1] = 1; pos[1] <= numElements; pos[1]++) {
221         last[1] = (pos[1] == numElements);
222 
223         // The top-level array is at depth 0, and all of its elements are at depth 1.
224         // Once nested fields are supported, array elements will be at top-level depth + 1.
225 
226         switch (typeId) {
227             case INT32_TYPE:
228                 parseInt32(pos, /*depth=*/1, last, /*numAnnotations=*/0);
229                 break;
230             case INT64_TYPE:
231                 parseInt64(pos, /*depth=*/1, last, /*numAnnotations=*/0);
232                 break;
233             case FLOAT_TYPE:
234                 parseFloat(pos, /*depth=*/1, last, /*numAnnotations=*/0);
235                 break;
236             case BOOL_TYPE:
237                 parseBool(pos, /*depth=*/1, last, /*numAnnotations=*/0);
238                 break;
239             case STRING_TYPE:
240                 parseString(pos, /*depth=*/1, last, /*numAnnotations=*/0);
241                 break;
242             default:
243                 mValid = false;
244                 break;
245         }
246     }
247 
248     parseAnnotations(numAnnotations, numElements);
249 
250     pos[1] = 1;
251     last[1] = false;
252 }
253 
254 // Assumes that mValues is not empty
checkPreviousValueType(Type expected)255 bool LogEvent::checkPreviousValueType(Type expected) {
256     return mValues[mValues.size() - 1].mValue.getType() == expected;
257 }
258 
parseIsUidAnnotation(uint8_t annotationType,std::optional<uint8_t> numElements)259 void LogEvent::parseIsUidAnnotation(uint8_t annotationType, std::optional<uint8_t> numElements) {
260     // Need to set numElements if not an array.
261     if (!numElements) {
262         numElements = 1;
263     }
264 
265     // If array is empty, skip uid parsing.
266     if (numElements == 0 && annotationType == BOOL_TYPE) {
267         readNextValue<uint8_t>();
268         return;
269     }
270 
271     // Allowed types: INT, repeated INT
272     if (numElements > mValues.size() || !checkPreviousValueType(INT) ||
273         annotationType != BOOL_TYPE) {
274         mValid = false;
275         return;
276     }
277 
278     bool isUid = readNextValue<uint8_t>();
279     if (isUid) {
280         mNumUidFields += numElements.value();
281     }
282 
283     for (int i = 1; i <= numElements; i++) {
284         mValues[mValues.size() - i].mAnnotations.setUidField(isUid);
285     }
286 }
287 
parseTruncateTimestampAnnotation(uint8_t annotationType)288 void LogEvent::parseTruncateTimestampAnnotation(uint8_t annotationType) {
289     if (!mValues.empty() || annotationType != BOOL_TYPE) {
290         mValid = false;
291         return;
292     }
293 
294     mTruncateTimestamp = readNextValue<uint8_t>();
295 }
296 
parsePrimaryFieldAnnotation(uint8_t annotationType,std::optional<uint8_t> numElements,std::optional<size_t> firstUidInChainIndex)297 void LogEvent::parsePrimaryFieldAnnotation(uint8_t annotationType,
298                                            std::optional<uint8_t> numElements,
299                                            std::optional<size_t> firstUidInChainIndex) {
300     // Allowed types: all types except for attribution chains and repeated fields.
301     if (mValues.empty() || annotationType != BOOL_TYPE || firstUidInChainIndex || numElements) {
302         mValid = false;
303         return;
304     }
305 
306     const bool primaryField = readNextValue<uint8_t>();
307     mValues[mValues.size() - 1].mAnnotations.setPrimaryField(primaryField);
308 }
309 
parsePrimaryFieldFirstUidAnnotation(uint8_t annotationType,std::optional<size_t> firstUidInChainIndex)310 void LogEvent::parsePrimaryFieldFirstUidAnnotation(uint8_t annotationType,
311                                                    std::optional<size_t> firstUidInChainIndex) {
312     // Allowed types: attribution chains
313     if (mValues.empty() || annotationType != BOOL_TYPE || !firstUidInChainIndex) {
314         mValid = false;
315         return;
316     }
317 
318     if (mValues.size() < firstUidInChainIndex.value() + 1) {  // AttributionChain is empty.
319         mValid = false;
320         android_errorWriteLog(0x534e4554, "174485572");
321         return;
322     }
323 
324     const bool primaryField = readNextValue<uint8_t>();
325     mValues[firstUidInChainIndex.value()].mAnnotations.setPrimaryField(primaryField);
326 }
327 
parseExclusiveStateAnnotation(uint8_t annotationType,std::optional<uint8_t> numElements)328 void LogEvent::parseExclusiveStateAnnotation(uint8_t annotationType,
329                                              std::optional<uint8_t> numElements) {
330     // Allowed types: INT
331     if (mValues.empty() || annotationType != BOOL_TYPE || !checkPreviousValueType(INT) ||
332         numElements) {
333         mValid = false;
334         return;
335     }
336 
337     const bool exclusiveState = readNextValue<uint8_t>();
338     mExclusiveStateFieldIndex = mValues.size() - 1;
339     mValues[getExclusiveStateFieldIndex().value()].mAnnotations.setExclusiveState(exclusiveState);
340 }
341 
parseTriggerStateResetAnnotation(uint8_t annotationType,std::optional<uint8_t> numElements)342 void LogEvent::parseTriggerStateResetAnnotation(uint8_t annotationType,
343                                                 std::optional<uint8_t> numElements) {
344     // Allowed types: INT
345     if (mValues.empty() || annotationType != INT32_TYPE || !checkPreviousValueType(INT) ||
346         numElements) {
347         mValid = false;
348         return;
349     }
350 
351     mResetState = readNextValue<int32_t>();
352 }
353 
parseStateNestedAnnotation(uint8_t annotationType,std::optional<uint8_t> numElements)354 void LogEvent::parseStateNestedAnnotation(uint8_t annotationType,
355                                           std::optional<uint8_t> numElements) {
356     // Allowed types: INT
357     if (mValues.empty() || annotationType != BOOL_TYPE || !checkPreviousValueType(INT) ||
358         numElements) {
359         mValid = false;
360         return;
361     }
362 
363     bool nested = readNextValue<uint8_t>();
364     mValues[mValues.size() - 1].mAnnotations.setNested(nested);
365 }
366 
367 // firstUidInChainIndex is a default parameter that is only needed when parsing
368 // annotations for attribution chains.
369 // 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)370 void LogEvent::parseAnnotations(uint8_t numAnnotations, std::optional<uint8_t> numElements,
371                                 std::optional<size_t> firstUidInChainIndex) {
372     for (uint8_t i = 0; i < numAnnotations; i++) {
373         uint8_t annotationId = readNextValue<uint8_t>();
374         uint8_t annotationType = readNextValue<uint8_t>();
375 
376         switch (annotationId) {
377             case ANNOTATION_ID_IS_UID:
378                 parseIsUidAnnotation(annotationType, numElements);
379                 break;
380             case ANNOTATION_ID_TRUNCATE_TIMESTAMP:
381                 parseTruncateTimestampAnnotation(annotationType);
382                 break;
383             case ANNOTATION_ID_PRIMARY_FIELD:
384                 parsePrimaryFieldAnnotation(annotationType, numElements, firstUidInChainIndex);
385                 break;
386             case ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID:
387                 parsePrimaryFieldFirstUidAnnotation(annotationType, firstUidInChainIndex);
388                 break;
389             case ANNOTATION_ID_EXCLUSIVE_STATE:
390                 parseExclusiveStateAnnotation(annotationType, numElements);
391                 break;
392             case ANNOTATION_ID_TRIGGER_STATE_RESET:
393                 parseTriggerStateResetAnnotation(annotationType, numElements);
394                 break;
395             case ANNOTATION_ID_STATE_NESTED:
396                 parseStateNestedAnnotation(annotationType, numElements);
397                 break;
398             default:
399                 mValid = false;
400                 return;
401         }
402     }
403 }
404 
405 // This parsing logic is tied to the encoding scheme used in StatsEvent.java and
406 // stats_event.c
parseBuffer(uint8_t * buf,size_t len)407 bool LogEvent::parseBuffer(uint8_t* buf, size_t len) {
408     mBuf = buf;
409     mRemainingLen = (uint32_t)len;
410 
411     int32_t pos[] = {1, 1, 1};
412     bool last[] = {false, false, false};
413 
414     // Beginning of buffer is OBJECT_TYPE | NUM_FIELDS | TIMESTAMP | ATOM_ID
415     uint8_t typeInfo = readNextValue<uint8_t>();
416     if (getTypeId(typeInfo) != OBJECT_TYPE) mValid = false;
417 
418     uint8_t numElements = readNextValue<uint8_t>();
419     if (numElements < 2 || numElements > INT8_MAX) mValid = false;
420 
421     typeInfo = readNextValue<uint8_t>();
422     if (getTypeId(typeInfo) != INT64_TYPE) mValid = false;
423     mElapsedTimestampNs = readNextValue<int64_t>();
424     numElements--;
425 
426     typeInfo = readNextValue<uint8_t>();
427     if (getTypeId(typeInfo) != INT32_TYPE) mValid = false;
428     mTagId = readNextValue<int32_t>();
429     numElements--;
430     parseAnnotations(getNumAnnotations(typeInfo));  // atom-level annotations
431 
432     for (pos[0] = 1; pos[0] <= numElements && mValid; pos[0]++) {
433         last[0] = (pos[0] == numElements);
434 
435         typeInfo = readNextValue<uint8_t>();
436         uint8_t typeId = getTypeId(typeInfo);
437 
438         switch (typeId) {
439             case BOOL_TYPE:
440                 parseBool(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
441                 break;
442             case INT32_TYPE:
443                 parseInt32(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
444                 break;
445             case INT64_TYPE:
446                 parseInt64(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
447                 break;
448             case FLOAT_TYPE:
449                 parseFloat(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
450                 break;
451             case BYTE_ARRAY_TYPE:
452                 parseByteArray(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
453                 break;
454             case STRING_TYPE:
455                 parseString(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
456                 break;
457             case KEY_VALUE_PAIRS_TYPE:
458                 parseKeyValuePairs(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
459                 break;
460             case ATTRIBUTION_CHAIN_TYPE:
461                 parseAttributionChain(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
462                 break;
463             case LIST_TYPE:
464                 parseArray(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
465                 break;
466             case ERROR_TYPE:
467                 /* mErrorBitmask =*/ readNextValue<int32_t>();
468                 mValid = false;
469                 break;
470             default:
471                 mValid = false;
472                 break;
473         }
474     }
475 
476     if (mRemainingLen != 0) mValid = false;
477     mBuf = nullptr;
478     return mValid;
479 }
480 
getTypeId(uint8_t typeInfo)481 uint8_t LogEvent::getTypeId(uint8_t typeInfo) {
482     return typeInfo & 0x0F;  // type id in lower 4 bytes
483 }
484 
getNumAnnotations(uint8_t typeInfo)485 uint8_t LogEvent::getNumAnnotations(uint8_t typeInfo) {
486     return (typeInfo >> 4) & 0x0F;  // num annotations in upper 4 bytes
487 }
488 
GetLong(size_t key,status_t * err) const489 int64_t LogEvent::GetLong(size_t key, status_t* err) const {
490     // TODO(b/110561208): encapsulate the magical operations in Field struct as static functions
491     int field = getSimpleField(key);
492     for (const auto& value : mValues) {
493         if (value.mField.getField() == field) {
494             if (value.mValue.getType() == LONG) {
495                 return value.mValue.long_value;
496             } else if (value.mValue.getType() == INT) {
497                 return value.mValue.int_value;
498             } else {
499                 *err = BAD_TYPE;
500                 return 0;
501             }
502         }
503         if ((size_t)value.mField.getPosAtDepth(0) > key) {
504             break;
505         }
506     }
507 
508     *err = BAD_INDEX;
509     return 0;
510 }
511 
GetInt(size_t key,status_t * err) const512 int LogEvent::GetInt(size_t key, status_t* err) const {
513     int field = getSimpleField(key);
514     for (const auto& value : mValues) {
515         if (value.mField.getField() == field) {
516             if (value.mValue.getType() == INT) {
517                 return value.mValue.int_value;
518             } else {
519                 *err = BAD_TYPE;
520                 return 0;
521             }
522         }
523         if ((size_t)value.mField.getPosAtDepth(0) > key) {
524             break;
525         }
526     }
527 
528     *err = BAD_INDEX;
529     return 0;
530 }
531 
GetString(size_t key,status_t * err) const532 const char* LogEvent::GetString(size_t key, status_t* err) const {
533     int field = getSimpleField(key);
534     for (const auto& value : mValues) {
535         if (value.mField.getField() == field) {
536             if (value.mValue.getType() == STRING) {
537                 return value.mValue.str_value.c_str();
538             } else {
539                 *err = BAD_TYPE;
540                 return 0;
541             }
542         }
543         if ((size_t)value.mField.getPosAtDepth(0) > key) {
544             break;
545         }
546     }
547 
548     *err = BAD_INDEX;
549     return NULL;
550 }
551 
GetBool(size_t key,status_t * err) const552 bool LogEvent::GetBool(size_t key, status_t* err) const {
553     int field = getSimpleField(key);
554     for (const auto& value : mValues) {
555         if (value.mField.getField() == field) {
556             if (value.mValue.getType() == INT) {
557                 return value.mValue.int_value != 0;
558             } else if (value.mValue.getType() == LONG) {
559                 return value.mValue.long_value != 0;
560             } else {
561                 *err = BAD_TYPE;
562                 return false;
563             }
564         }
565         if ((size_t)value.mField.getPosAtDepth(0) > key) {
566             break;
567         }
568     }
569 
570     *err = BAD_INDEX;
571     return false;
572 }
573 
GetFloat(size_t key,status_t * err) const574 float LogEvent::GetFloat(size_t key, status_t* err) const {
575     int field = getSimpleField(key);
576     for (const auto& value : mValues) {
577         if (value.mField.getField() == field) {
578             if (value.mValue.getType() == FLOAT) {
579                 return value.mValue.float_value;
580             } else {
581                 *err = BAD_TYPE;
582                 return 0.0;
583             }
584         }
585         if ((size_t)value.mField.getPosAtDepth(0) > key) {
586             break;
587         }
588     }
589 
590     *err = BAD_INDEX;
591     return 0.0;
592 }
593 
GetStorage(size_t key,status_t * err) const594 std::vector<uint8_t> LogEvent::GetStorage(size_t key, status_t* err) const {
595     int field = getSimpleField(key);
596     for (const auto& value : mValues) {
597         if (value.mField.getField() == field) {
598             if (value.mValue.getType() == STORAGE) {
599                 return value.mValue.storage_value;
600             } else {
601                 *err = BAD_TYPE;
602                 return vector<uint8_t>();
603             }
604         }
605         if ((size_t)value.mField.getPosAtDepth(0) > key) {
606             break;
607         }
608     }
609 
610     *err = BAD_INDEX;
611     return vector<uint8_t>();
612 }
613 
ToString() const614 string LogEvent::ToString() const {
615     string result;
616     result += StringPrintf("{ uid(%d) %lld %lld (%d)", mLogUid, (long long)mLogdTimestampNs,
617                            (long long)mElapsedTimestampNs, mTagId);
618     for (const auto& value : mValues) {
619         result +=
620                 StringPrintf("%#x", value.mField.getField()) + "->" + value.mValue.toString() + " ";
621     }
622     result += " }";
623     return result;
624 }
625 
ToProto(ProtoOutputStream & protoOutput) const626 void LogEvent::ToProto(ProtoOutputStream& protoOutput) const {
627     writeFieldValueTreeToStream(mTagId, getValues(), &protoOutput);
628 }
629 
hasAttributionChain(std::pair<size_t,size_t> * indexRange) const630 bool LogEvent::hasAttributionChain(std::pair<size_t, size_t>* indexRange) const {
631     if (!mAttributionChainStartIndex || !mAttributionChainEndIndex) {
632         return false;
633     }
634 
635     if (nullptr != indexRange) {
636         indexRange->first = mAttributionChainStartIndex.value();
637         indexRange->second = mAttributionChainEndIndex.value();
638     }
639 
640     return true;
641 }
642 
writeExperimentIdsToProto(const std::vector<int64_t> & experimentIds,std::vector<uint8_t> * protoOut)643 void writeExperimentIdsToProto(const std::vector<int64_t>& experimentIds,
644                                std::vector<uint8_t>* protoOut) {
645     ProtoOutputStream proto;
646     for (const auto& expId : experimentIds) {
647         proto.write(FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED | FIELD_ID_EXPERIMENT_ID,
648                     (long long)expId);
649     }
650 
651     protoOut->resize(proto.size());
652     size_t pos = 0;
653     sp<ProtoReader> reader = proto.data();
654     while (reader->readBuffer() != NULL) {
655         size_t toRead = reader->currentToRead();
656         std::memcpy(protoOut->data() + pos, reader->readBuffer(), toRead);
657         pos += toRead;
658         reader->move(toRead);
659     }
660 }
661 
662 }  // namespace statsd
663 }  // namespace os
664 }  // namespace android
665