Loading apex/statsd/framework/Android.bp +2 −1 Original line number Diff line number Diff line Loading @@ -146,7 +146,8 @@ java_library { visibility: [ "//frameworks/base", // Framework "//frameworks/base/apex/statsd", // statsd apex "//frameworks/opt/net/wifi/service" // wifi service "//frameworks/opt/net/wifi/service", // wifi service "//packages/providers/MediaProvider", // MediaProvider apk ], } Loading cmds/statsd/src/FieldValue.h +52 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #pragma once #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" #include "annotations.h" namespace android { namespace os { Loading Loading @@ -357,6 +358,56 @@ struct Value { Value& operator=(const Value& that); }; class Annotations { public: Annotations() {} // This enum stores where particular annotations can be found in the // bitmask. Note that these pos do not correspond to annotation ids. enum { NESTED_POS = 0x0, PRIMARY_POS = 0x1, EXCLUSIVE_POS = 0x2 }; inline void setNested(bool nested) { setBitmaskAtPos(NESTED_POS, nested); } inline void setPrimaryField(bool primary) { setBitmaskAtPos(PRIMARY_POS, primary); } inline void setExclusiveState(bool exclusive) { setBitmaskAtPos(EXCLUSIVE_POS, exclusive); } inline void setResetState(int resetState) { mResetState = resetState; } // Default value = false inline bool isNested() const { return getValueFromBitmask(NESTED_POS); } // Default value = false inline bool isPrimaryField() const { return getValueFromBitmask(PRIMARY_POS); } // Default value = false inline bool isExclusiveState() const { return getValueFromBitmask(EXCLUSIVE_POS); } // If a reset state is not sent in the StatsEvent, returns -1. Note that a // reset satate is only sent if and only if a reset should be triggered. inline int getResetState() const { return mResetState; } private: inline void setBitmaskAtPos(int pos, bool value) { mBooleanBitmask &= ~(1 << pos); // clear mBooleanBitmask |= (value << pos); // set } inline bool getValueFromBitmask(int pos) const { return (mBooleanBitmask >> pos) & 0x1; } // This is a bitmask over all annotations stored in boolean form. Because // there are only 3 booleans, just one byte is required. uint8_t mBooleanBitmask = 0; int mResetState = -1; }; /** * Represents a log item, or a dimension item (They are essentially the same). */ Loading Loading @@ -384,6 +435,7 @@ struct FieldValue { Field mField; Value mValue; Annotations mAnnotations; }; bool HasPositionANY(const FieldMatcher& matcher); Loading cmds/statsd/src/annotations.h 0 → 100644 +35 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 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. */ #pragma once namespace android { namespace os { namespace statsd { const uint8_t ANNOTATION_ID_IS_UID = 1; const uint8_t ANNOTATION_ID_TRUNCATE_TIMESTAMP = 2; const uint8_t ANNOTATION_ID_STATE_OPTION = 3; const uint8_t ANNOTATION_ID_RESET_STATE = 5; const uint8_t ANNOTATION_ID_STATE_NESTED = 6; const int32_t STATE_OPTION_PRIMARY_FIELD = 1; const int32_t STATE_OPTION_EXCLUSIVE_STATE = 2; const int32_t STATE_OPTION_PRIMARY_FIELD_FIRST_UID = 3; } // namespace statsd } // namespace os } // namespace android cmds/statsd/src/atoms.proto +3 −3 Original line number Diff line number Diff line Loading @@ -5810,7 +5810,7 @@ message NotificationRemoteViews { */ message PackageNotificationPreferences { // Uid under which the package is installed. optional int32 uid = 1; optional int32 uid = 1 [(is_uid) = true]; // Notification importance, which specifies when and how a notification is displayed. // Specified under core/java/android/app/NotificationManager.java. optional int32 importance = 2; Loading @@ -5827,7 +5827,7 @@ message PackageNotificationPreferences { */ message PackageNotificationChannelPreferences { // Uid under which the package is installed. optional int32 uid = 1; optional int32 uid = 1 [(is_uid) = true]; // Channel's ID. Should always be available. optional string channel_id = 2; // Channel's name. Should always be available. Loading @@ -5850,7 +5850,7 @@ message PackageNotificationChannelPreferences { */ message PackageNotificationChannelGroupPreferences { // Uid under which the package is installed. optional int32 uid = 1; optional int32 uid = 1 [(is_uid) = true]; // Channel Group's ID. Should always be available. optional string group_id = 2; // Channel Group's name. Should always be available. Loading cmds/statsd/src/logd/LogEvent.cpp +90 −10 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #define DEBUG false // STOPSHIP if true #include "logd/LogEvent.h" #include "annotations.h" #include "stats_log_util.h" #include "statslog_statsd.h" Loading Loading @@ -447,6 +448,7 @@ void LogEvent::parseKeyValuePairs(int32_t* pos, int32_t depth, bool* last, uint8 void LogEvent::parseAttributionChain(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) { int firstUidInChainIndex = mValues.size(); int32_t numNodes = readNextValue<uint8_t>(); for (pos[1] = 1; pos[1] <= numNodes; pos[1]++) { last[1] = (pos[1] == numNodes); Loading @@ -461,26 +463,103 @@ void LogEvent::parseAttributionChain(int32_t* pos, int32_t depth, bool* last, parseString(pos, /*depth=*/2, last, /*numAnnotations=*/0); } parseAnnotations(numAnnotations); parseAnnotations(numAnnotations, firstUidInChainIndex); pos[1] = pos[2] = 1; last[1] = last[2] = false; } // TODO(b/151109630): store annotation information within LogEvent void LogEvent::parseAnnotations(uint8_t numAnnotations) { void LogEvent::parseIsUidAnnotation(uint8_t annotationType) { if (mValues.empty() || annotationType != BOOL_TYPE) { mValid = false; return; } bool isUid = readNextValue<uint8_t>(); if (isUid) mUidFieldIndex = mValues.size() - 1; } void LogEvent::parseTruncateTimestampAnnotation(uint8_t annotationType) { if (!mValues.empty() || annotationType != BOOL_TYPE) { mValid = false; return; } mTruncateTimestamp = readNextValue<uint8_t>(); } void LogEvent::parseStateOptionAnnotation(uint8_t annotationType, int firstUidInChainIndex) { if (mValues.empty() || annotationType != INT32_TYPE) { mValid = false; return; } int32_t stateOption = readNextValue<int32_t>(); switch (stateOption) { case STATE_OPTION_EXCLUSIVE_STATE: mValues[mValues.size() - 1].mAnnotations.setExclusiveState(true); break; case STATE_OPTION_PRIMARY_FIELD: mValues[mValues.size() - 1].mAnnotations.setPrimaryField(true); break; case STATE_OPTION_PRIMARY_FIELD_FIRST_UID: if (firstUidInChainIndex == -1) { mValid = false; } else { mValues[firstUidInChainIndex].mAnnotations.setPrimaryField(true); } break; default: mValid = false; } } void LogEvent::parseResetStateAnnotation(uint8_t annotationType) { if (mValues.empty() || annotationType != INT32_TYPE) { mValid = false; return; } int32_t resetState = readNextValue<int32_t>(); mValues[mValues.size() - 1].mAnnotations.setResetState(resetState); } 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 annotationId = readNextValue<uint8_t>(); uint8_t annotationType = readNextValue<uint8_t>(); switch (annotationType) { case BOOL_TYPE: /*bool annotationValue = */ readNextValue<uint8_t>(); switch (annotationId) { case ANNOTATION_ID_IS_UID: parseIsUidAnnotation(annotationType); break; case INT32_TYPE: /*int32_t annotationValue =*/ readNextValue<int32_t>(); case ANNOTATION_ID_TRUNCATE_TIMESTAMP: parseTruncateTimestampAnnotation(annotationType); break; case ANNOTATION_ID_STATE_OPTION: parseStateOptionAnnotation(annotationType, firstUidInChainIndex); break; case ANNOTATION_ID_RESET_STATE: parseResetStateAnnotation(annotationType); break; case ANNOTATION_ID_STATE_NESTED: parseStateNestedAnnotation(annotationType); break; default: mValid = false; return; } } } Loading Loading @@ -509,8 +588,8 @@ bool LogEvent::parseBuffer(uint8_t* buf, size_t len) { typeInfo = readNextValue<uint8_t>(); if (getTypeId(typeInfo) != INT32_TYPE) mValid = false; mTagId = readNextValue<int32_t>(); parseAnnotations(getNumAnnotations(typeInfo)); // atom-level annotations numElements--; parseAnnotations(getNumAnnotations(typeInfo)); // atom-level annotations for (pos[0] = 1; pos[0] <= numElements && mValid; pos[0]++) { Loading Loading @@ -544,6 +623,7 @@ bool LogEvent::parseBuffer(uint8_t* buf, size_t len) { break; case ATTRIBUTION_CHAIN_TYPE: parseAttributionChain(pos, /*depth=*/0, last, getNumAnnotations(typeInfo)); if (mAttributionChainIndex == -1) mAttributionChainIndex = pos[0]; break; default: mValid = false; Loading Loading
apex/statsd/framework/Android.bp +2 −1 Original line number Diff line number Diff line Loading @@ -146,7 +146,8 @@ java_library { visibility: [ "//frameworks/base", // Framework "//frameworks/base/apex/statsd", // statsd apex "//frameworks/opt/net/wifi/service" // wifi service "//frameworks/opt/net/wifi/service", // wifi service "//packages/providers/MediaProvider", // MediaProvider apk ], } Loading
cmds/statsd/src/FieldValue.h +52 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #pragma once #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" #include "annotations.h" namespace android { namespace os { Loading Loading @@ -357,6 +358,56 @@ struct Value { Value& operator=(const Value& that); }; class Annotations { public: Annotations() {} // This enum stores where particular annotations can be found in the // bitmask. Note that these pos do not correspond to annotation ids. enum { NESTED_POS = 0x0, PRIMARY_POS = 0x1, EXCLUSIVE_POS = 0x2 }; inline void setNested(bool nested) { setBitmaskAtPos(NESTED_POS, nested); } inline void setPrimaryField(bool primary) { setBitmaskAtPos(PRIMARY_POS, primary); } inline void setExclusiveState(bool exclusive) { setBitmaskAtPos(EXCLUSIVE_POS, exclusive); } inline void setResetState(int resetState) { mResetState = resetState; } // Default value = false inline bool isNested() const { return getValueFromBitmask(NESTED_POS); } // Default value = false inline bool isPrimaryField() const { return getValueFromBitmask(PRIMARY_POS); } // Default value = false inline bool isExclusiveState() const { return getValueFromBitmask(EXCLUSIVE_POS); } // If a reset state is not sent in the StatsEvent, returns -1. Note that a // reset satate is only sent if and only if a reset should be triggered. inline int getResetState() const { return mResetState; } private: inline void setBitmaskAtPos(int pos, bool value) { mBooleanBitmask &= ~(1 << pos); // clear mBooleanBitmask |= (value << pos); // set } inline bool getValueFromBitmask(int pos) const { return (mBooleanBitmask >> pos) & 0x1; } // This is a bitmask over all annotations stored in boolean form. Because // there are only 3 booleans, just one byte is required. uint8_t mBooleanBitmask = 0; int mResetState = -1; }; /** * Represents a log item, or a dimension item (They are essentially the same). */ Loading Loading @@ -384,6 +435,7 @@ struct FieldValue { Field mField; Value mValue; Annotations mAnnotations; }; bool HasPositionANY(const FieldMatcher& matcher); Loading
cmds/statsd/src/annotations.h 0 → 100644 +35 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 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. */ #pragma once namespace android { namespace os { namespace statsd { const uint8_t ANNOTATION_ID_IS_UID = 1; const uint8_t ANNOTATION_ID_TRUNCATE_TIMESTAMP = 2; const uint8_t ANNOTATION_ID_STATE_OPTION = 3; const uint8_t ANNOTATION_ID_RESET_STATE = 5; const uint8_t ANNOTATION_ID_STATE_NESTED = 6; const int32_t STATE_OPTION_PRIMARY_FIELD = 1; const int32_t STATE_OPTION_EXCLUSIVE_STATE = 2; const int32_t STATE_OPTION_PRIMARY_FIELD_FIRST_UID = 3; } // namespace statsd } // namespace os } // namespace android
cmds/statsd/src/atoms.proto +3 −3 Original line number Diff line number Diff line Loading @@ -5810,7 +5810,7 @@ message NotificationRemoteViews { */ message PackageNotificationPreferences { // Uid under which the package is installed. optional int32 uid = 1; optional int32 uid = 1 [(is_uid) = true]; // Notification importance, which specifies when and how a notification is displayed. // Specified under core/java/android/app/NotificationManager.java. optional int32 importance = 2; Loading @@ -5827,7 +5827,7 @@ message PackageNotificationPreferences { */ message PackageNotificationChannelPreferences { // Uid under which the package is installed. optional int32 uid = 1; optional int32 uid = 1 [(is_uid) = true]; // Channel's ID. Should always be available. optional string channel_id = 2; // Channel's name. Should always be available. Loading @@ -5850,7 +5850,7 @@ message PackageNotificationChannelPreferences { */ message PackageNotificationChannelGroupPreferences { // Uid under which the package is installed. optional int32 uid = 1; optional int32 uid = 1 [(is_uid) = true]; // Channel Group's ID. Should always be available. optional string group_id = 2; // Channel Group's name. Should always be available. Loading
cmds/statsd/src/logd/LogEvent.cpp +90 −10 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #define DEBUG false // STOPSHIP if true #include "logd/LogEvent.h" #include "annotations.h" #include "stats_log_util.h" #include "statslog_statsd.h" Loading Loading @@ -447,6 +448,7 @@ void LogEvent::parseKeyValuePairs(int32_t* pos, int32_t depth, bool* last, uint8 void LogEvent::parseAttributionChain(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) { int firstUidInChainIndex = mValues.size(); int32_t numNodes = readNextValue<uint8_t>(); for (pos[1] = 1; pos[1] <= numNodes; pos[1]++) { last[1] = (pos[1] == numNodes); Loading @@ -461,26 +463,103 @@ void LogEvent::parseAttributionChain(int32_t* pos, int32_t depth, bool* last, parseString(pos, /*depth=*/2, last, /*numAnnotations=*/0); } parseAnnotations(numAnnotations); parseAnnotations(numAnnotations, firstUidInChainIndex); pos[1] = pos[2] = 1; last[1] = last[2] = false; } // TODO(b/151109630): store annotation information within LogEvent void LogEvent::parseAnnotations(uint8_t numAnnotations) { void LogEvent::parseIsUidAnnotation(uint8_t annotationType) { if (mValues.empty() || annotationType != BOOL_TYPE) { mValid = false; return; } bool isUid = readNextValue<uint8_t>(); if (isUid) mUidFieldIndex = mValues.size() - 1; } void LogEvent::parseTruncateTimestampAnnotation(uint8_t annotationType) { if (!mValues.empty() || annotationType != BOOL_TYPE) { mValid = false; return; } mTruncateTimestamp = readNextValue<uint8_t>(); } void LogEvent::parseStateOptionAnnotation(uint8_t annotationType, int firstUidInChainIndex) { if (mValues.empty() || annotationType != INT32_TYPE) { mValid = false; return; } int32_t stateOption = readNextValue<int32_t>(); switch (stateOption) { case STATE_OPTION_EXCLUSIVE_STATE: mValues[mValues.size() - 1].mAnnotations.setExclusiveState(true); break; case STATE_OPTION_PRIMARY_FIELD: mValues[mValues.size() - 1].mAnnotations.setPrimaryField(true); break; case STATE_OPTION_PRIMARY_FIELD_FIRST_UID: if (firstUidInChainIndex == -1) { mValid = false; } else { mValues[firstUidInChainIndex].mAnnotations.setPrimaryField(true); } break; default: mValid = false; } } void LogEvent::parseResetStateAnnotation(uint8_t annotationType) { if (mValues.empty() || annotationType != INT32_TYPE) { mValid = false; return; } int32_t resetState = readNextValue<int32_t>(); mValues[mValues.size() - 1].mAnnotations.setResetState(resetState); } 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 annotationId = readNextValue<uint8_t>(); uint8_t annotationType = readNextValue<uint8_t>(); switch (annotationType) { case BOOL_TYPE: /*bool annotationValue = */ readNextValue<uint8_t>(); switch (annotationId) { case ANNOTATION_ID_IS_UID: parseIsUidAnnotation(annotationType); break; case INT32_TYPE: /*int32_t annotationValue =*/ readNextValue<int32_t>(); case ANNOTATION_ID_TRUNCATE_TIMESTAMP: parseTruncateTimestampAnnotation(annotationType); break; case ANNOTATION_ID_STATE_OPTION: parseStateOptionAnnotation(annotationType, firstUidInChainIndex); break; case ANNOTATION_ID_RESET_STATE: parseResetStateAnnotation(annotationType); break; case ANNOTATION_ID_STATE_NESTED: parseStateNestedAnnotation(annotationType); break; default: mValid = false; return; } } } Loading Loading @@ -509,8 +588,8 @@ bool LogEvent::parseBuffer(uint8_t* buf, size_t len) { typeInfo = readNextValue<uint8_t>(); if (getTypeId(typeInfo) != INT32_TYPE) mValid = false; mTagId = readNextValue<int32_t>(); parseAnnotations(getNumAnnotations(typeInfo)); // atom-level annotations numElements--; parseAnnotations(getNumAnnotations(typeInfo)); // atom-level annotations for (pos[0] = 1; pos[0] <= numElements && mValid; pos[0]++) { Loading Loading @@ -544,6 +623,7 @@ bool LogEvent::parseBuffer(uint8_t* buf, size_t len) { break; case ATTRIBUTION_CHAIN_TYPE: parseAttributionChain(pos, /*depth=*/0, last, getNumAnnotations(typeInfo)); if (mAttributionChainIndex == -1) mAttributionChainIndex = pos[0]; break; default: mValid = false; Loading