diff options
Diffstat (limited to 'cmds/statsd/src/logd/LogEvent.cpp')
-rw-r--r-- | cmds/statsd/src/logd/LogEvent.cpp | 618 |
1 files changed, 0 insertions, 618 deletions
diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp deleted file mode 100644 index 4f031724763f..000000000000 --- a/cmds/statsd/src/logd/LogEvent.cpp +++ /dev/null @@ -1,618 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define DEBUG false // STOPSHIP if true -#include "logd/LogEvent.h" - -#include <android-base/stringprintf.h> -#include <android/binder_ibinder.h> -#include <log/log.h> -#include <private/android_filesystem_config.h> - -#include "annotations.h" -#include "stats_log_util.h" -#include "statslog_statsd.h" - -namespace android { -namespace os { -namespace statsd { - -// for TrainInfo experiment id serialization -const int FIELD_ID_EXPERIMENT_ID = 1; - -using namespace android::util; -using android::base::StringPrintf; -using android::util::ProtoOutputStream; -using std::string; -using std::vector; - -// stats_event.h socket types. Keep in sync. -/* ERRORS */ -#define ERROR_NO_TIMESTAMP 0x1 -#define ERROR_NO_ATOM_ID 0x2 -#define ERROR_OVERFLOW 0x4 -#define ERROR_ATTRIBUTION_CHAIN_TOO_LONG 0x8 -#define ERROR_TOO_MANY_KEY_VALUE_PAIRS 0x10 -#define ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD 0x20 -#define ERROR_INVALID_ANNOTATION_ID 0x40 -#define ERROR_ANNOTATION_ID_TOO_LARGE 0x80 -#define ERROR_TOO_MANY_ANNOTATIONS 0x100 -#define ERROR_TOO_MANY_FIELDS 0x200 -#define ERROR_INVALID_VALUE_TYPE 0x400 -#define ERROR_STRING_NOT_NULL_TERMINATED 0x800 - -/* TYPE IDS */ -#define INT32_TYPE 0x00 -#define INT64_TYPE 0x01 -#define STRING_TYPE 0x02 -#define LIST_TYPE 0x03 -#define FLOAT_TYPE 0x04 -#define BOOL_TYPE 0x05 -#define BYTE_ARRAY_TYPE 0x06 -#define OBJECT_TYPE 0x07 -#define KEY_VALUE_PAIRS_TYPE 0x08 -#define ATTRIBUTION_CHAIN_TYPE 0x09 -#define ERROR_TYPE 0x0F - -LogEvent::LogEvent(int32_t uid, int32_t pid) - : mLogdTimestampNs(time(nullptr)), mLogUid(uid), mLogPid(pid) { -} - -LogEvent::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) { - mLogdTimestampNs = getWallClockNs(); - mElapsedTimestampNs = getElapsedRealtimeNs(); - mTagId = util::BINARY_PUSH_STATE_CHANGED; - mLogUid = AIBinder_getCallingUid(); - mLogPid = AIBinder_getCallingPid(); - - mValues.push_back(FieldValue(Field(mTagId, getSimpleField(1)), Value(trainName))); - mValues.push_back(FieldValue(Field(mTagId, getSimpleField(2)), Value(trainVersionCode))); - mValues.push_back(FieldValue(Field(mTagId, getSimpleField(3)), Value((int)requiresStaging))); - mValues.push_back(FieldValue(Field(mTagId, getSimpleField(4)), Value((int)rollbackEnabled))); - mValues.push_back( - FieldValue(Field(mTagId, getSimpleField(5)), Value((int)requiresLowLatencyMonitor))); - mValues.push_back(FieldValue(Field(mTagId, getSimpleField(6)), Value(state))); - mValues.push_back(FieldValue(Field(mTagId, getSimpleField(7)), Value(experimentIds))); - mValues.push_back(FieldValue(Field(mTagId, getSimpleField(8)), Value(userId))); -} - -LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs, - const InstallTrainInfo& trainInfo) { - mLogdTimestampNs = wallClockTimestampNs; - mElapsedTimestampNs = elapsedTimestampNs; - mTagId = util::TRAIN_INFO; - - mValues.push_back( - FieldValue(Field(mTagId, getSimpleField(1)), Value(trainInfo.trainVersionCode))); - std::vector<uint8_t> experimentIdsProto; - writeExperimentIdsToProto(trainInfo.experimentIds, &experimentIdsProto); - mValues.push_back(FieldValue(Field(mTagId, getSimpleField(2)), Value(experimentIdsProto))); - mValues.push_back(FieldValue(Field(mTagId, getSimpleField(3)), Value(trainInfo.trainName))); - mValues.push_back(FieldValue(Field(mTagId, getSimpleField(4)), Value(trainInfo.status))); -} - -void LogEvent::parseInt32(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) { - int32_t value = readNextValue<int32_t>(); - addToValues(pos, depth, value, last); - parseAnnotations(numAnnotations); -} - -void LogEvent::parseInt64(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) { - int64_t value = readNextValue<int64_t>(); - addToValues(pos, depth, value, last); - parseAnnotations(numAnnotations); -} - -void LogEvent::parseString(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) { - int32_t numBytes = readNextValue<int32_t>(); - if ((uint32_t)numBytes > mRemainingLen) { - mValid = false; - return; - } - - string value = string((char*)mBuf, numBytes); - mBuf += numBytes; - mRemainingLen -= numBytes; - addToValues(pos, depth, value, last); - parseAnnotations(numAnnotations); -} - -void LogEvent::parseFloat(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) { - float value = readNextValue<float>(); - addToValues(pos, depth, value, last); - parseAnnotations(numAnnotations); -} - -void LogEvent::parseBool(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) { - // cast to int32_t because FieldValue does not support bools - int32_t value = (int32_t)readNextValue<uint8_t>(); - addToValues(pos, depth, value, last); - parseAnnotations(numAnnotations); -} - -void LogEvent::parseByteArray(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) { - int32_t numBytes = readNextValue<int32_t>(); - if ((uint32_t)numBytes > mRemainingLen) { - mValid = false; - return; - } - - vector<uint8_t> value(mBuf, mBuf + numBytes); - mBuf += numBytes; - mRemainingLen -= numBytes; - addToValues(pos, depth, value, last); - parseAnnotations(numAnnotations); -} - -void LogEvent::parseKeyValuePairs(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) { - int32_t numPairs = readNextValue<uint8_t>(); - - for (pos[1] = 1; pos[1] <= numPairs; pos[1]++) { - last[1] = (pos[1] == numPairs); - - // parse key - pos[2] = 1; - parseInt32(pos, /*depth=*/2, last, /*numAnnotations=*/0); - - // parse value - last[2] = true; - - uint8_t typeInfo = readNextValue<uint8_t>(); - switch (getTypeId(typeInfo)) { - case INT32_TYPE: - pos[2] = 2; // pos[2] determined by index of type in KeyValuePair in atoms.proto - parseInt32(pos, /*depth=*/2, last, /*numAnnotations=*/0); - break; - case INT64_TYPE: - pos[2] = 3; - parseInt64(pos, /*depth=*/2, last, /*numAnnotations=*/0); - break; - case STRING_TYPE: - pos[2] = 4; - parseString(pos, /*depth=*/2, last, /*numAnnotations=*/0); - break; - case FLOAT_TYPE: - pos[2] = 5; - parseFloat(pos, /*depth=*/2, last, /*numAnnotations=*/0); - break; - default: - mValid = false; - } - } - - parseAnnotations(numAnnotations); - - pos[1] = pos[2] = 1; - last[1] = last[2] = false; -} - -void LogEvent::parseAttributionChain(int32_t* pos, int32_t depth, bool* last, - uint8_t numAnnotations) { - const unsigned int firstUidInChainIndex = mValues.size(); - const int32_t numNodes = readNextValue<uint8_t>(); - for (pos[1] = 1; pos[1] <= numNodes; pos[1]++) { - last[1] = (pos[1] == numNodes); - - // parse uid - pos[2] = 1; - parseInt32(pos, /*depth=*/2, last, /*numAnnotations=*/0); - - // parse tag - pos[2] = 2; - last[2] = true; - parseString(pos, /*depth=*/2, last, /*numAnnotations=*/0); - } - - if (mValues.size() - 1 > INT8_MAX) { - mValid = false; - } else if (mValues.size() - 1 > firstUidInChainIndex) { - // At least one node was successfully parsed. - mAttributionChainStartIndex = static_cast<int8_t>(firstUidInChainIndex); - mAttributionChainEndIndex = static_cast<int8_t>(mValues.size() - 1); - } - - if (mValid) { - parseAnnotations(numAnnotations, firstUidInChainIndex); - } - - pos[1] = pos[2] = 1; - last[1] = last[2] = false; -} - -// Assumes that mValues is not empty -bool LogEvent::checkPreviousValueType(Type expected) { - return mValues[mValues.size() - 1].mValue.getType() == expected; -} - -void LogEvent::parseIsUidAnnotation(uint8_t annotationType) { - if (mValues.empty() || mValues.size() - 1 > INT8_MAX || !checkPreviousValueType(INT) - || annotationType != BOOL_TYPE) { - mValid = false; - return; - } - - bool isUid = readNextValue<uint8_t>(); - if (isUid) mUidFieldIndex = static_cast<int8_t>(mValues.size() - 1); - mValues[mValues.size() - 1].mAnnotations.setUidField(isUid); -} - -void LogEvent::parseTruncateTimestampAnnotation(uint8_t annotationType) { - if (!mValues.empty() || annotationType != BOOL_TYPE) { - mValid = false; - return; - } - - mTruncateTimestamp = readNextValue<uint8_t>(); -} - -void LogEvent::parsePrimaryFieldAnnotation(uint8_t annotationType) { - if (mValues.empty() || annotationType != BOOL_TYPE) { - mValid = false; - return; - } - - const bool primaryField = readNextValue<uint8_t>(); - mValues[mValues.size() - 1].mAnnotations.setPrimaryField(primaryField); -} - -void LogEvent::parsePrimaryFieldFirstUidAnnotation(uint8_t annotationType, - int firstUidInChainIndex) { - if (mValues.empty() || annotationType != BOOL_TYPE || -1 == firstUidInChainIndex) { - mValid = false; - return; - } - - if (static_cast<int>(mValues.size() - 1) < firstUidInChainIndex) { // AttributionChain is empty. - mValid = false; - android_errorWriteLog(0x534e4554, "174485572"); - return; - } - - const bool primaryField = readNextValue<uint8_t>(); - mValues[firstUidInChainIndex].mAnnotations.setPrimaryField(primaryField); -} - -void LogEvent::parseExclusiveStateAnnotation(uint8_t annotationType) { - if (mValues.empty() || annotationType != BOOL_TYPE) { - mValid = false; - return; - } - - if (mValues.size() - 1 > INT8_MAX) { - android_errorWriteLog(0x534e4554, "174488848"); - mValid = false; - return; - } - - const bool exclusiveState = readNextValue<uint8_t>(); - mExclusiveStateFieldIndex = static_cast<int8_t>(mValues.size() - 1); - mValues[getExclusiveStateFieldIndex()].mAnnotations.setExclusiveState(exclusiveState); -} - -void LogEvent::parseTriggerStateResetAnnotation(uint8_t annotationType) { - if (mValues.empty() || annotationType != INT32_TYPE) { - mValid = false; - return; - } - - mResetState = readNextValue<int32_t>(); -} - -void LogEvent::parseStateNestedAnnotation(uint8_t annotationType) { - if (mValues.empty() || annotationType != BOOL_TYPE) { - mValid = false; - return; - } - - bool nested = readNextValue<uint8_t>(); - mValues[mValues.size() - 1].mAnnotations.setNested(nested); -} - -// firstUidInChainIndex is a default parameter that is only needed when parsing -// annotations for attribution chains. -void LogEvent::parseAnnotations(uint8_t numAnnotations, int firstUidInChainIndex) { - for (uint8_t i = 0; i < numAnnotations; i++) { - uint8_t annotationId = readNextValue<uint8_t>(); - uint8_t annotationType = readNextValue<uint8_t>(); - - switch (annotationId) { - case ANNOTATION_ID_IS_UID: - parseIsUidAnnotation(annotationType); - break; - case ANNOTATION_ID_TRUNCATE_TIMESTAMP: - parseTruncateTimestampAnnotation(annotationType); - break; - case ANNOTATION_ID_PRIMARY_FIELD: - parsePrimaryFieldAnnotation(annotationType); - break; - case ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID: - parsePrimaryFieldFirstUidAnnotation(annotationType, firstUidInChainIndex); - break; - case ANNOTATION_ID_EXCLUSIVE_STATE: - parseExclusiveStateAnnotation(annotationType); - break; - case ANNOTATION_ID_TRIGGER_STATE_RESET: - parseTriggerStateResetAnnotation(annotationType); - break; - case ANNOTATION_ID_STATE_NESTED: - parseStateNestedAnnotation(annotationType); - break; - default: - mValid = false; - return; - } - } -} - -// This parsing logic is tied to the encoding scheme used in StatsEvent.java and -// stats_event.c -bool LogEvent::parseBuffer(uint8_t* buf, size_t len) { - mBuf = buf; - mRemainingLen = (uint32_t)len; - - int32_t pos[] = {1, 1, 1}; - bool last[] = {false, false, false}; - - // Beginning of buffer is OBJECT_TYPE | NUM_FIELDS | TIMESTAMP | ATOM_ID - uint8_t typeInfo = readNextValue<uint8_t>(); - if (getTypeId(typeInfo) != OBJECT_TYPE) mValid = false; - - uint8_t numElements = readNextValue<uint8_t>(); - if (numElements < 2 || numElements > 127) mValid = false; - - typeInfo = readNextValue<uint8_t>(); - if (getTypeId(typeInfo) != INT64_TYPE) mValid = false; - mElapsedTimestampNs = readNextValue<int64_t>(); - numElements--; - - typeInfo = readNextValue<uint8_t>(); - if (getTypeId(typeInfo) != INT32_TYPE) mValid = false; - mTagId = readNextValue<int32_t>(); - numElements--; - parseAnnotations(getNumAnnotations(typeInfo)); // atom-level annotations - - for (pos[0] = 1; pos[0] <= numElements && mValid; pos[0]++) { - last[0] = (pos[0] == numElements); - - typeInfo = readNextValue<uint8_t>(); - uint8_t typeId = getTypeId(typeInfo); - - switch (typeId) { - case BOOL_TYPE: - parseBool(pos, /*depth=*/0, last, getNumAnnotations(typeInfo)); - break; - case INT32_TYPE: - parseInt32(pos, /*depth=*/0, last, getNumAnnotations(typeInfo)); - break; - case INT64_TYPE: - parseInt64(pos, /*depth=*/0, last, getNumAnnotations(typeInfo)); - break; - case FLOAT_TYPE: - parseFloat(pos, /*depth=*/0, last, getNumAnnotations(typeInfo)); - break; - case BYTE_ARRAY_TYPE: - parseByteArray(pos, /*depth=*/0, last, getNumAnnotations(typeInfo)); - break; - case STRING_TYPE: - parseString(pos, /*depth=*/0, last, getNumAnnotations(typeInfo)); - break; - case KEY_VALUE_PAIRS_TYPE: - parseKeyValuePairs(pos, /*depth=*/0, last, getNumAnnotations(typeInfo)); - break; - case ATTRIBUTION_CHAIN_TYPE: - parseAttributionChain(pos, /*depth=*/0, last, getNumAnnotations(typeInfo)); - break; - case ERROR_TYPE: - /* mErrorBitmask =*/ readNextValue<int32_t>(); - mValid = false; - break; - default: - mValid = false; - break; - } - } - - if (mRemainingLen != 0) mValid = false; - mBuf = nullptr; - return mValid; -} - -uint8_t LogEvent::getTypeId(uint8_t typeInfo) { - return typeInfo & 0x0F; // type id in lower 4 bytes -} - -uint8_t LogEvent::getNumAnnotations(uint8_t typeInfo) { - return (typeInfo >> 4) & 0x0F; // num annotations in upper 4 bytes -} - -int64_t LogEvent::GetLong(size_t key, status_t* err) const { - // TODO(b/110561208): encapsulate the magical operations in Field struct as static functions - int field = getSimpleField(key); - for (const auto& value : mValues) { - if (value.mField.getField() == field) { - if (value.mValue.getType() == LONG) { - return value.mValue.long_value; - } else if (value.mValue.getType() == INT) { - return value.mValue.int_value; - } else { - *err = BAD_TYPE; - return 0; - } - } - if ((size_t)value.mField.getPosAtDepth(0) > key) { - break; - } - } - - *err = BAD_INDEX; - return 0; -} - -int LogEvent::GetInt(size_t key, status_t* err) const { - int field = getSimpleField(key); - for (const auto& value : mValues) { - if (value.mField.getField() == field) { - if (value.mValue.getType() == INT) { - return value.mValue.int_value; - } else { - *err = BAD_TYPE; - return 0; - } - } - if ((size_t)value.mField.getPosAtDepth(0) > key) { - break; - } - } - - *err = BAD_INDEX; - return 0; -} - -const char* LogEvent::GetString(size_t key, status_t* err) const { - int field = getSimpleField(key); - for (const auto& value : mValues) { - if (value.mField.getField() == field) { - if (value.mValue.getType() == STRING) { - return value.mValue.str_value.c_str(); - } else { - *err = BAD_TYPE; - return 0; - } - } - if ((size_t)value.mField.getPosAtDepth(0) > key) { - break; - } - } - - *err = BAD_INDEX; - return NULL; -} - -bool LogEvent::GetBool(size_t key, status_t* err) const { - int field = getSimpleField(key); - for (const auto& value : mValues) { - if (value.mField.getField() == field) { - if (value.mValue.getType() == INT) { - return value.mValue.int_value != 0; - } else if (value.mValue.getType() == LONG) { - return value.mValue.long_value != 0; - } else { - *err = BAD_TYPE; - return false; - } - } - if ((size_t)value.mField.getPosAtDepth(0) > key) { - break; - } - } - - *err = BAD_INDEX; - return false; -} - -float LogEvent::GetFloat(size_t key, status_t* err) const { - int field = getSimpleField(key); - for (const auto& value : mValues) { - if (value.mField.getField() == field) { - if (value.mValue.getType() == FLOAT) { - return value.mValue.float_value; - } else { - *err = BAD_TYPE; - return 0.0; - } - } - if ((size_t)value.mField.getPosAtDepth(0) > key) { - break; - } - } - - *err = BAD_INDEX; - return 0.0; -} - -std::vector<uint8_t> LogEvent::GetStorage(size_t key, status_t* err) const { - int field = getSimpleField(key); - for (const auto& value : mValues) { - if (value.mField.getField() == field) { - if (value.mValue.getType() == STORAGE) { - return value.mValue.storage_value; - } else { - *err = BAD_TYPE; - return vector<uint8_t>(); - } - } - if ((size_t)value.mField.getPosAtDepth(0) > key) { - break; - } - } - - *err = BAD_INDEX; - return vector<uint8_t>(); -} - -string LogEvent::ToString() const { - string result; - result += StringPrintf("{ uid(%d) %lld %lld (%d)", mLogUid, (long long)mLogdTimestampNs, - (long long)mElapsedTimestampNs, mTagId); - for (const auto& value : mValues) { - result += - StringPrintf("%#x", value.mField.getField()) + "->" + value.mValue.toString() + " "; - } - result += " }"; - return result; -} - -void LogEvent::ToProto(ProtoOutputStream& protoOutput) const { - writeFieldValueTreeToStream(mTagId, getValues(), &protoOutput); -} - -bool LogEvent::hasAttributionChain(std::pair<int, int>* indexRange) const { - if (mAttributionChainStartIndex == -1 || mAttributionChainEndIndex == -1) { - return false; - } - - if (nullptr != indexRange) { - indexRange->first = static_cast<int>(mAttributionChainStartIndex); - indexRange->second = static_cast<int>(mAttributionChainEndIndex); - } - - return true; -} - -void writeExperimentIdsToProto(const std::vector<int64_t>& experimentIds, - std::vector<uint8_t>* protoOut) { - ProtoOutputStream proto; - for (const auto& expId : experimentIds) { - proto.write(FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED | FIELD_ID_EXPERIMENT_ID, - (long long)expId); - } - - protoOut->resize(proto.size()); - size_t pos = 0; - sp<ProtoReader> reader = proto.data(); - while (reader->readBuffer() != NULL) { - size_t toRead = reader->currentToRead(); - std::memcpy(protoOut->data() + pos, reader->readBuffer(), toRead); - pos += toRead; - reader->move(toRead); - } -} - -} // namespace statsd -} // namespace os -} // namespace android |