Merge "Make state_option top-level boolean annotations" into rvc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
4e83de27c2
@@ -22,13 +22,11 @@ namespace statsd {
|
|||||||
|
|
||||||
const uint8_t ANNOTATION_ID_IS_UID = 1;
|
const uint8_t ANNOTATION_ID_IS_UID = 1;
|
||||||
const uint8_t ANNOTATION_ID_TRUNCATE_TIMESTAMP = 2;
|
const uint8_t ANNOTATION_ID_TRUNCATE_TIMESTAMP = 2;
|
||||||
const uint8_t ANNOTATION_ID_STATE_OPTION = 3;
|
const uint8_t ANNOTATION_ID_PRIMARY_FIELD = 3;
|
||||||
const uint8_t ANNOTATION_ID_RESET_STATE = 5;
|
const uint8_t ANNOTATION_ID_EXCLUSIVE_STATE = 4;
|
||||||
const uint8_t ANNOTATION_ID_STATE_NESTED = 6;
|
const uint8_t ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID = 5;
|
||||||
|
const uint8_t ANNOTATION_ID_TRIGGER_STATE_RESET = 7;
|
||||||
const int32_t STATE_OPTION_PRIMARY_FIELD = 1;
|
const uint8_t ANNOTATION_ID_STATE_NESTED = 8;
|
||||||
const int32_t STATE_OPTION_EXCLUSIVE_STATE = 2;
|
|
||||||
const int32_t STATE_OPTION_PRIMARY_FIELD_FIRST_UID = 3;
|
|
||||||
|
|
||||||
} // namespace statsd
|
} // namespace statsd
|
||||||
} // namespace os
|
} // namespace os
|
||||||
|
|||||||
@@ -23,25 +23,12 @@ option java_outer_classname = "AtomFieldOptions";
|
|||||||
|
|
||||||
import "google/protobuf/descriptor.proto";
|
import "google/protobuf/descriptor.proto";
|
||||||
|
|
||||||
enum StateField {
|
|
||||||
// Default value for fields that are not a primary or exclusive state field.
|
|
||||||
STATE_FIELD_UNSET = 0;
|
|
||||||
// Fields that represent the key that the state belongs to.
|
|
||||||
// Used on simple proto fields. Do not use on attribution chains.
|
|
||||||
PRIMARY_FIELD = 1;
|
|
||||||
// The field that represents the state. It's an exclusive state.
|
|
||||||
EXCLUSIVE_STATE = 2;
|
|
||||||
// Used on an attribution chain field to indicate that the first uid is the
|
|
||||||
// primary field.
|
|
||||||
PRIMARY_FIELD_FIRST_UID = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used to annotate an atom that represents a state change. A state change atom must have exactly
|
// Used to annotate an atom that represents a state change. A state change atom must have exactly
|
||||||
// ONE exclusive state field, and any number of primary key fields. For example, message
|
// ONE exclusive state field, and any number of primary key fields. For example, message
|
||||||
// UidProcessStateChanged {
|
// UidProcessStateChanged {
|
||||||
// optional int32 uid = 1 [(state_field_option).option = PRIMARY_FIELD];
|
// optional int32 uid = 1 [(state_field_option).primary_field = true];
|
||||||
// optional android.app.ProcessStateEnum state = 2 [(state_field_option).option =
|
// optional android.app.ProcessStateEnum state =
|
||||||
// EXCLUSIVE_STATE];
|
// 2 [(state_field_option).exclusive_state = true];
|
||||||
// }
|
// }
|
||||||
// Each UidProcessStateChanged atom event represents a state change for a specific uid.
|
// Each UidProcessStateChanged atom event represents a state change for a specific uid.
|
||||||
// A new state automatically overrides the previous state.
|
// A new state automatically overrides the previous state.
|
||||||
@@ -50,23 +37,23 @@ enum StateField {
|
|||||||
// primary fields are the primary key.
|
// primary fields are the primary key.
|
||||||
// For example:
|
// For example:
|
||||||
// message ThreadStateChanged {
|
// message ThreadStateChanged {
|
||||||
// optional int32 pid = 1 [(state_field_option).option = PRIMARY_FIELD];
|
// optional int32 pid = 1 [(state_field_option).primary_field = true];
|
||||||
// optional int32 tid = 2 [(state_field_option).option = PRIMARY_FIELD];
|
// optional int32 tid = 2 [(state_field_option).primary_field = true];
|
||||||
// optional int32 state = 3 [(state_field_option).option = EXCLUSIVE_STATE];
|
// optional int32 state = 3 [(state_field_option).exclusive_state = true];
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// Sometimes, there is no primary key field, when the state is GLOBAL.
|
// Sometimes, there is no primary key field, when the state is GLOBAL.
|
||||||
// For example,
|
// For example,
|
||||||
// message ScreenStateChanged {
|
// message ScreenStateChanged {
|
||||||
// optional android.view.DisplayStateEnum state = 1 [(state_field_option).option =
|
// optional android.view.DisplayStateEnum state =
|
||||||
// EXCLUSIVE_STATE];
|
// 1 [(state_field_option).exclusive_state = true];
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// For state atoms with attribution chain, sometimes the primary key is the first uid in the chain.
|
// For state atoms with attribution chain, sometimes the primary key is the first uid in the chain.
|
||||||
// For example:
|
// For example:
|
||||||
// message AudioStateChanged {
|
// message AudioStateChanged {
|
||||||
// repeated AttributionNode attribution_node = 1
|
// repeated AttributionNode attribution_node = 1
|
||||||
// [(stateFieldOption).option = PRIMARY_KEY_FIRST_UID];
|
// [(stateFieldOption).primary_field_first_uid = true];
|
||||||
//
|
//
|
||||||
// enum State {
|
// enum State {
|
||||||
// OFF = 0;
|
// OFF = 0;
|
||||||
@@ -74,10 +61,19 @@ enum StateField {
|
|||||||
// // RESET indicates all audio stopped. Used when it (re)starts (e.g. after it crashes).
|
// // RESET indicates all audio stopped. Used when it (re)starts (e.g. after it crashes).
|
||||||
// RESET = 2;
|
// RESET = 2;
|
||||||
// }
|
// }
|
||||||
// optional State state = 2 [(stateFieldOption).option = EXCLUSIVE_STATE];
|
// optional State state = 2 [(stateFieldOption).exclusive_state = true];
|
||||||
// }
|
// }
|
||||||
message StateAtomFieldOption {
|
message StateAtomFieldOption {
|
||||||
optional StateField option = 1 [default = STATE_FIELD_UNSET];
|
// Fields that represent the key that the state belongs to.
|
||||||
|
// Used on simple proto fields. Do not use on attribution chains.
|
||||||
|
optional bool primary_field = 1 [default = false];
|
||||||
|
|
||||||
|
// The field that represents the state. It's an exclusive state.
|
||||||
|
optional bool exclusive_state = 2 [default = false];
|
||||||
|
|
||||||
|
// Used on an attribution chain field to indicate that the first uid is the
|
||||||
|
// primary field.
|
||||||
|
optional bool primary_field_first_uid = 3 [default = false];
|
||||||
|
|
||||||
// Note: We cannot annotate directly on the enums because many enums are imported from other
|
// Note: We cannot annotate directly on the enums because many enums are imported from other
|
||||||
// proto files in the platform. proto-lite cc library does not support annotations unfortunately
|
// proto files in the platform. proto-lite cc library does not support annotations unfortunately
|
||||||
@@ -85,14 +81,14 @@ message StateAtomFieldOption {
|
|||||||
// Knowing the default state value allows state trackers to remove entries that become the
|
// Knowing the default state value allows state trackers to remove entries that become the
|
||||||
// default state. If there is no default value specified, the default value is unknown, and all
|
// default state. If there is no default value specified, the default value is unknown, and all
|
||||||
// states will be tracked in memory.
|
// states will be tracked in memory.
|
||||||
optional int32 default_state_value = 2;
|
optional int32 default_state_value = 4;
|
||||||
|
|
||||||
// A reset state signals all states go to default value. For example, BLE reset means all active
|
// A reset state signals all states go to default value. For example, BLE reset means all active
|
||||||
// BLE scans are to be turned off.
|
// BLE scans are to be turned off.
|
||||||
optional int32 reset_state_value = 3;
|
optional int32 trigger_state_reset_value = 5;
|
||||||
|
|
||||||
// If the state change needs to count nesting.
|
// If the state change needs to count nesting.
|
||||||
optional bool nested = 4 [default = true];
|
optional bool nested = 6 [default = true];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used to generate StatsLog.write APIs.
|
// Used to generate StatsLog.write APIs.
|
||||||
|
|||||||
@@ -610,7 +610,7 @@ message ThermalThrottlingStateChanged {
|
|||||||
message ScreenStateChanged {
|
message ScreenStateChanged {
|
||||||
// New screen state, from frameworks/base/core/proto/android/view/enums.proto.
|
// New screen state, from frameworks/base/core/proto/android/view/enums.proto.
|
||||||
optional android.view.DisplayStateEnum state = 1
|
optional android.view.DisplayStateEnum state = 1
|
||||||
[(state_field_option).option = EXCLUSIVE_STATE, (state_field_option).nested = false];
|
[(state_field_option).exclusive_state = true, (state_field_option).nested = false];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -621,11 +621,11 @@ message ScreenStateChanged {
|
|||||||
* frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java
|
* frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java
|
||||||
*/
|
*/
|
||||||
message UidProcessStateChanged {
|
message UidProcessStateChanged {
|
||||||
optional int32 uid = 1 [(state_field_option).option = PRIMARY_FIELD, (is_uid) = true];
|
optional int32 uid = 1 [(state_field_option).primary_field = true, (is_uid) = true];
|
||||||
|
|
||||||
// The state, from frameworks/base/core/proto/android/app/enums.proto.
|
// The state, from frameworks/base/core/proto/android/app/enums.proto.
|
||||||
optional android.app.ProcessStateEnum state = 2
|
optional android.app.ProcessStateEnum state = 2
|
||||||
[(state_field_option).option = EXCLUSIVE_STATE, (state_field_option).nested = false];
|
[(state_field_option).exclusive_state = true, (state_field_option).nested = false];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -657,7 +657,7 @@ message ActivityManagerSleepStateChanged {
|
|||||||
ASLEEP = 1;
|
ASLEEP = 1;
|
||||||
AWAKE = 2;
|
AWAKE = 2;
|
||||||
}
|
}
|
||||||
optional State state = 1 [(state_field_option).option = EXCLUSIVE_STATE];
|
optional State state = 1 [(state_field_option).exclusive_state = true];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -676,7 +676,7 @@ message MemoryFactorStateChanged {
|
|||||||
CRITICAL = 4; // critical memory.
|
CRITICAL = 4; // critical memory.
|
||||||
|
|
||||||
}
|
}
|
||||||
optional State factor = 1 [(state_field_option).option = EXCLUSIVE_STATE];
|
optional State factor = 1 [(state_field_option).exclusive_state = true];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -854,7 +854,7 @@ message ProcessLifeCycleStateChanged {
|
|||||||
*/
|
*/
|
||||||
message BleScanStateChanged {
|
message BleScanStateChanged {
|
||||||
repeated AttributionNode attribution_node = 1
|
repeated AttributionNode attribution_node = 1
|
||||||
[(state_field_option).option = PRIMARY_FIELD_FIRST_UID];
|
[(state_field_option).primary_field_first_uid = true];
|
||||||
|
|
||||||
enum State {
|
enum State {
|
||||||
OFF = 0;
|
OFF = 0;
|
||||||
@@ -863,18 +863,18 @@ message BleScanStateChanged {
|
|||||||
RESET = 2;
|
RESET = 2;
|
||||||
}
|
}
|
||||||
optional State state = 2 [
|
optional State state = 2 [
|
||||||
(state_field_option).option = EXCLUSIVE_STATE,
|
(state_field_option).exclusive_state = true,
|
||||||
(state_field_option).default_state_value = 0 /* State.OFF */,
|
(state_field_option).default_state_value = 0 /* State.OFF */,
|
||||||
(state_field_option).reset_state_value = 2 /* State.RESET */,
|
(state_field_option).trigger_state_reset_value = 2 /* State.RESET */,
|
||||||
(state_field_option).nested = true
|
(state_field_option).nested = true
|
||||||
];
|
];
|
||||||
|
|
||||||
// Does the scan have a filter.
|
// Does the scan have a filter.
|
||||||
optional bool is_filtered = 3 [(state_field_option).option = PRIMARY_FIELD];
|
optional bool is_filtered = 3 [(state_field_option).primary_field = true];
|
||||||
// Whether the scan is a CALLBACK_TYPE_FIRST_MATCH scan. Called 'background' scan internally.
|
// Whether the scan is a CALLBACK_TYPE_FIRST_MATCH scan. Called 'background' scan internally.
|
||||||
optional bool is_first_match = 4 [(state_field_option).option = PRIMARY_FIELD];
|
optional bool is_first_match = 4 [(state_field_option).primary_field = true];
|
||||||
// Whether the scan set to piggy-back off the results of other scans (SCAN_MODE_OPPORTUNISTIC).
|
// Whether the scan set to piggy-back off the results of other scans (SCAN_MODE_OPPORTUNISTIC).
|
||||||
optional bool is_opportunistic = 5 [(state_field_option).option = PRIMARY_FIELD];
|
optional bool is_opportunistic = 5 [(state_field_option).primary_field = true];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1105,15 +1105,14 @@ message CameraStateChanged {
|
|||||||
*/
|
*/
|
||||||
message WakelockStateChanged {
|
message WakelockStateChanged {
|
||||||
repeated AttributionNode attribution_node = 1
|
repeated AttributionNode attribution_node = 1
|
||||||
[(state_field_option).option = PRIMARY_FIELD_FIRST_UID];
|
[(state_field_option).primary_field_first_uid = true];
|
||||||
|
|
||||||
// The type (level) of the wakelock; e.g. a partial wakelock or a full wakelock.
|
// The type (level) of the wakelock; e.g. a partial wakelock or a full wakelock.
|
||||||
// From frameworks/base/core/proto/android/os/enums.proto.
|
// From frameworks/base/core/proto/android/os/enums.proto.
|
||||||
optional android.os.WakeLockLevelEnum type = 2 [(state_field_option).option = PRIMARY_FIELD];
|
optional android.os.WakeLockLevelEnum type = 2 [(state_field_option).primary_field = true];
|
||||||
;
|
|
||||||
|
|
||||||
// The wakelock tag (Called tag in the Java API, sometimes name elsewhere).
|
// The wakelock tag (Called tag in the Java API, sometimes name elsewhere).
|
||||||
optional string tag = 3 [(state_field_option).option = PRIMARY_FIELD];
|
optional string tag = 3 [(state_field_option).primary_field = true];
|
||||||
|
|
||||||
enum State {
|
enum State {
|
||||||
RELEASE = 0;
|
RELEASE = 0;
|
||||||
@@ -1122,7 +1121,7 @@ message WakelockStateChanged {
|
|||||||
CHANGE_ACQUIRE = 3;
|
CHANGE_ACQUIRE = 3;
|
||||||
}
|
}
|
||||||
optional State state = 4 [
|
optional State state = 4 [
|
||||||
(state_field_option).option = EXCLUSIVE_STATE,
|
(state_field_option).exclusive_state = true,
|
||||||
(state_field_option).default_state_value = 0,
|
(state_field_option).default_state_value = 0,
|
||||||
(state_field_option).nested = true
|
(state_field_option).nested = true
|
||||||
];
|
];
|
||||||
@@ -3494,9 +3493,9 @@ message PictureInPictureStateChanged {
|
|||||||
* services/core/java/com/android/server/wm/Session.java
|
* services/core/java/com/android/server/wm/Session.java
|
||||||
*/
|
*/
|
||||||
message OverlayStateChanged {
|
message OverlayStateChanged {
|
||||||
optional int32 uid = 1 [(state_field_option).option = PRIMARY_FIELD, (is_uid) = true];
|
optional int32 uid = 1 [(state_field_option).primary_field = true, (is_uid) = true];
|
||||||
|
|
||||||
optional string package_name = 2 [(state_field_option).option = PRIMARY_FIELD];
|
optional string package_name = 2 [(state_field_option).primary_field = true];
|
||||||
|
|
||||||
optional bool using_alert_window = 3;
|
optional bool using_alert_window = 3;
|
||||||
|
|
||||||
@@ -3505,7 +3504,7 @@ message OverlayStateChanged {
|
|||||||
EXITED = 2;
|
EXITED = 2;
|
||||||
}
|
}
|
||||||
optional State state = 4 [
|
optional State state = 4 [
|
||||||
(state_field_option).option = EXCLUSIVE_STATE,
|
(state_field_option).exclusive_state = true,
|
||||||
(state_field_option).nested = false,
|
(state_field_option).nested = false,
|
||||||
(state_field_option).default_state_value = 2
|
(state_field_option).default_state_value = 2
|
||||||
];
|
];
|
||||||
@@ -3713,7 +3712,7 @@ message LmkKillOccurred {
|
|||||||
*/
|
*/
|
||||||
message AppDied {
|
message AppDied {
|
||||||
// timestamp(elapsedRealtime) of record creation
|
// timestamp(elapsedRealtime) of record creation
|
||||||
optional uint64 timestamp_millis = 1 [(state_field_option).option = EXCLUSIVE_STATE];
|
optional uint64 timestamp_millis = 1 [(state_field_option).exclusive_state = true];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -4235,7 +4234,7 @@ message PrivacyIndicatorsInteracted {
|
|||||||
DIALOG_LINE_ITEM = 5;
|
DIALOG_LINE_ITEM = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
optional Type type = 1 [(state_field_option).option = EXCLUSIVE_STATE];
|
optional Type type = 1 [(state_field_option).exclusive_state = true];
|
||||||
|
|
||||||
// Used if the type is LINE_ITEM
|
// Used if the type is LINE_ITEM
|
||||||
optional string package_name = 2;
|
optional string package_name = 2;
|
||||||
|
|||||||
@@ -17,14 +17,14 @@
|
|||||||
#define DEBUG false // STOPSHIP if true
|
#define DEBUG false // STOPSHIP if true
|
||||||
#include "logd/LogEvent.h"
|
#include "logd/LogEvent.h"
|
||||||
|
|
||||||
|
#include <android-base/stringprintf.h>
|
||||||
|
#include <android/binder_ibinder.h>
|
||||||
|
#include <private/android_filesystem_config.h>
|
||||||
|
|
||||||
#include "annotations.h"
|
#include "annotations.h"
|
||||||
#include "stats_log_util.h"
|
#include "stats_log_util.h"
|
||||||
#include "statslog_statsd.h"
|
#include "statslog_statsd.h"
|
||||||
|
|
||||||
#include <android/binder_ibinder.h>
|
|
||||||
#include <android-base/stringprintf.h>
|
|
||||||
#include <private/android_filesystem_config.h>
|
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
namespace os {
|
namespace os {
|
||||||
namespace statsd {
|
namespace statsd {
|
||||||
@@ -76,9 +76,7 @@ LogEvent::LogEvent(const LogEvent& event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
LogEvent::LogEvent(int32_t uid, int32_t pid)
|
LogEvent::LogEvent(int32_t uid, int32_t pid)
|
||||||
: mLogdTimestampNs(time(nullptr)),
|
: mLogdTimestampNs(time(nullptr)), mLogUid(uid), mLogPid(pid) {
|
||||||
mLogUid(uid),
|
|
||||||
mLogPid(pid) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LogEvent::LogEvent(const string& trainName, int64_t trainVersionCode, bool requiresStaging,
|
LogEvent::LogEvent(const string& trainName, int64_t trainVersionCode, bool requiresStaging,
|
||||||
@@ -261,33 +259,38 @@ void LogEvent::parseTruncateTimestampAnnotation(uint8_t annotationType) {
|
|||||||
mTruncateTimestamp = readNextValue<uint8_t>();
|
mTruncateTimestamp = readNextValue<uint8_t>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogEvent::parseStateOptionAnnotation(uint8_t annotationType, int firstUidInChainIndex) {
|
void LogEvent::parsePrimaryFieldAnnotation(uint8_t annotationType) {
|
||||||
if (mValues.empty() || annotationType != INT32_TYPE) {
|
if (mValues.empty() || annotationType != BOOL_TYPE) {
|
||||||
mValid = false;
|
mValid = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t stateOption = readNextValue<int32_t>();
|
const bool primaryField = readNextValue<uint8_t>();
|
||||||
switch (stateOption) {
|
mValues[mValues.size() - 1].mAnnotations.setPrimaryField(primaryField);
|
||||||
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) {
|
void LogEvent::parsePrimaryFieldFirstUidAnnotation(uint8_t annotationType,
|
||||||
|
int firstUidInChainIndex) {
|
||||||
|
if (mValues.empty() || annotationType != BOOL_TYPE || -1 == firstUidInChainIndex) {
|
||||||
|
mValid = false;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool exclusiveState = readNextValue<uint8_t>();
|
||||||
|
mValues[mValues.size() - 1].mAnnotations.setExclusiveState(exclusiveState);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LogEvent::parseTriggerStateResetAnnotation(uint8_t annotationType) {
|
||||||
if (mValues.empty() || annotationType != INT32_TYPE) {
|
if (mValues.empty() || annotationType != INT32_TYPE) {
|
||||||
mValid = false;
|
mValid = false;
|
||||||
return;
|
return;
|
||||||
@@ -321,11 +324,17 @@ void LogEvent::parseAnnotations(uint8_t numAnnotations, int firstUidInChainIndex
|
|||||||
case ANNOTATION_ID_TRUNCATE_TIMESTAMP:
|
case ANNOTATION_ID_TRUNCATE_TIMESTAMP:
|
||||||
parseTruncateTimestampAnnotation(annotationType);
|
parseTruncateTimestampAnnotation(annotationType);
|
||||||
break;
|
break;
|
||||||
case ANNOTATION_ID_STATE_OPTION:
|
case ANNOTATION_ID_PRIMARY_FIELD:
|
||||||
parseStateOptionAnnotation(annotationType, firstUidInChainIndex);
|
parsePrimaryFieldAnnotation(annotationType);
|
||||||
break;
|
break;
|
||||||
case ANNOTATION_ID_RESET_STATE:
|
case ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID:
|
||||||
parseResetStateAnnotation(annotationType);
|
parsePrimaryFieldFirstUidAnnotation(annotationType, firstUidInChainIndex);
|
||||||
|
break;
|
||||||
|
case ANNOTATION_ID_EXCLUSIVE_STATE:
|
||||||
|
parseExclusiveStateAnnotation(annotationType);
|
||||||
|
break;
|
||||||
|
case ANNOTATION_ID_TRIGGER_STATE_RESET:
|
||||||
|
parseTriggerStateResetAnnotation(annotationType);
|
||||||
break;
|
break;
|
||||||
case ANNOTATION_ID_STATE_NESTED:
|
case ANNOTATION_ID_STATE_NESTED:
|
||||||
parseStateNestedAnnotation(annotationType);
|
parseStateNestedAnnotation(annotationType);
|
||||||
@@ -364,7 +373,6 @@ bool LogEvent::parseBuffer(uint8_t* buf, size_t len) {
|
|||||||
numElements--;
|
numElements--;
|
||||||
parseAnnotations(getNumAnnotations(typeInfo)); // atom-level annotations
|
parseAnnotations(getNumAnnotations(typeInfo)); // atom-level annotations
|
||||||
|
|
||||||
|
|
||||||
for (pos[0] = 1; pos[0] <= numElements && mValid; pos[0]++) {
|
for (pos[0] = 1; pos[0] <= numElements && mValid; pos[0]++) {
|
||||||
last[0] = (pos[0] == numElements);
|
last[0] = (pos[0] == numElements);
|
||||||
|
|
||||||
|
|||||||
@@ -208,8 +208,10 @@ private:
|
|||||||
void parseAnnotations(uint8_t numAnnotations, int firstUidInChainIndex = -1);
|
void parseAnnotations(uint8_t numAnnotations, int firstUidInChainIndex = -1);
|
||||||
void parseIsUidAnnotation(uint8_t annotationType);
|
void parseIsUidAnnotation(uint8_t annotationType);
|
||||||
void parseTruncateTimestampAnnotation(uint8_t annotationType);
|
void parseTruncateTimestampAnnotation(uint8_t annotationType);
|
||||||
void parseStateOptionAnnotation(uint8_t annotationType, int firstUidInChainIndex);
|
void parsePrimaryFieldAnnotation(uint8_t annotationType);
|
||||||
void parseResetStateAnnotation(uint8_t annotationType);
|
void parsePrimaryFieldFirstUidAnnotation(uint8_t annotationType, int firstUidInChainIndex);
|
||||||
|
void parseExclusiveStateAnnotation(uint8_t annotationType);
|
||||||
|
void parseTriggerStateResetAnnotation(uint8_t annotationType);
|
||||||
void parseStateNestedAnnotation(uint8_t annotationType);
|
void parseStateNestedAnnotation(uint8_t annotationType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,15 +12,15 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "src/logd/LogEvent.h"
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
#include "frameworks/base/cmds/statsd/src/atoms.pb.h"
|
#include "frameworks/base/cmds/statsd/src/atoms.pb.h"
|
||||||
#include "frameworks/base/core/proto/android/stats/launcher/launcher.pb.h"
|
#include "frameworks/base/core/proto/android/stats/launcher/launcher.pb.h"
|
||||||
#include "log/log_event_list.h"
|
#include "log/log_event_list.h"
|
||||||
#include "src/logd/LogEvent.h"
|
|
||||||
#include "stats_event.h"
|
#include "stats_event.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
@@ -32,6 +32,8 @@ using std::vector;
|
|||||||
using util::ProtoOutputStream;
|
using util::ProtoOutputStream;
|
||||||
using util::ProtoReader;
|
using util::ProtoReader;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
Field getField(int32_t tag, const vector<int32_t>& pos, int32_t depth, const vector<bool>& last) {
|
Field getField(int32_t tag, const vector<int32_t>& pos, int32_t depth, const vector<bool>& last) {
|
||||||
Field f(tag, (int32_t*)pos.data(), depth);
|
Field f(tag, (int32_t*)pos.data(), depth);
|
||||||
|
|
||||||
@@ -43,6 +45,38 @@ Field getField(int32_t tag, const vector<int32_t>& pos, int32_t depth, const vec
|
|||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void createIntWithBoolAnnotationLogEvent(LogEvent* logEvent, uint8_t annotationId,
|
||||||
|
bool annotationValue) {
|
||||||
|
AStatsEvent* statsEvent = AStatsEvent_obtain();
|
||||||
|
AStatsEvent_setAtomId(statsEvent, /*atomId=*/100);
|
||||||
|
AStatsEvent_writeInt32(statsEvent, 10);
|
||||||
|
AStatsEvent_addBoolAnnotation(statsEvent, annotationId, annotationValue);
|
||||||
|
AStatsEvent_build(statsEvent);
|
||||||
|
|
||||||
|
size_t size;
|
||||||
|
uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
|
||||||
|
EXPECT_TRUE(logEvent->parseBuffer(buf, size));
|
||||||
|
|
||||||
|
AStatsEvent_release(statsEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void createIntWithIntAnnotationLogEvent(LogEvent* logEvent, uint8_t annotationId,
|
||||||
|
int annotationValue) {
|
||||||
|
AStatsEvent* statsEvent = AStatsEvent_obtain();
|
||||||
|
AStatsEvent_setAtomId(statsEvent, /*atomId=*/100);
|
||||||
|
AStatsEvent_writeInt32(statsEvent, 10);
|
||||||
|
AStatsEvent_addInt32Annotation(statsEvent, annotationId, annotationValue);
|
||||||
|
AStatsEvent_build(statsEvent);
|
||||||
|
|
||||||
|
size_t size;
|
||||||
|
uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
|
||||||
|
EXPECT_TRUE(logEvent->parseBuffer(buf, size));
|
||||||
|
|
||||||
|
AStatsEvent_release(statsEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
TEST(LogEventTest, TestPrimitiveParsing) {
|
TEST(LogEventTest, TestPrimitiveParsing) {
|
||||||
AStatsEvent* event = AStatsEvent_obtain();
|
AStatsEvent* event = AStatsEvent_obtain();
|
||||||
AStatsEvent_setAtomId(event, 100);
|
AStatsEvent_setAtomId(event, 100);
|
||||||
@@ -92,7 +126,6 @@ TEST(LogEventTest, TestPrimitiveParsing) {
|
|||||||
AStatsEvent_release(event);
|
AStatsEvent_release(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(LogEventTest, TestStringAndByteArrayParsing) {
|
TEST(LogEventTest, TestStringAndByteArrayParsing) {
|
||||||
AStatsEvent* event = AStatsEvent_obtain();
|
AStatsEvent* event = AStatsEvent_obtain();
|
||||||
AStatsEvent_setAtomId(event, 100);
|
AStatsEvent_setAtomId(event, 100);
|
||||||
@@ -244,21 +277,6 @@ TEST(LogEventTest, TestAttributionChain) {
|
|||||||
AStatsEvent_release(event);
|
AStatsEvent_release(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void createIntWithBoolAnnotationLogEvent(LogEvent* logEvent, uint8_t annotationId,
|
|
||||||
bool annotationValue) {
|
|
||||||
AStatsEvent* statsEvent = AStatsEvent_obtain();
|
|
||||||
AStatsEvent_setAtomId(statsEvent, /*atomId=*/100);
|
|
||||||
AStatsEvent_writeInt32(statsEvent, 10);
|
|
||||||
AStatsEvent_addBoolAnnotation(statsEvent, annotationId, annotationValue);
|
|
||||||
AStatsEvent_build(statsEvent);
|
|
||||||
|
|
||||||
size_t size;
|
|
||||||
uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
|
|
||||||
EXPECT_TRUE(logEvent->parseBuffer(buf, size));
|
|
||||||
|
|
||||||
AStatsEvent_release(statsEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(LogEventTest, TestAnnotationIdIsUid) {
|
TEST(LogEventTest, TestAnnotationIdIsUid) {
|
||||||
LogEvent event(/*uid=*/0, /*pid=*/0);
|
LogEvent event(/*uid=*/0, /*pid=*/0);
|
||||||
createIntWithBoolAnnotationLogEvent(&event, ANNOTATION_ID_IS_UID, true);
|
createIntWithBoolAnnotationLogEvent(&event, ANNOTATION_ID_IS_UID, true);
|
||||||
@@ -277,25 +295,9 @@ TEST(LogEventTest, TestAnnotationIdStateNested) {
|
|||||||
EXPECT_TRUE(values[0].mAnnotations.isNested());
|
EXPECT_TRUE(values[0].mAnnotations.isNested());
|
||||||
}
|
}
|
||||||
|
|
||||||
void createIntWithIntAnnotationLogEvent(LogEvent* logEvent, uint8_t annotationId,
|
|
||||||
int annotationValue) {
|
|
||||||
AStatsEvent* statsEvent = AStatsEvent_obtain();
|
|
||||||
AStatsEvent_setAtomId(statsEvent, /*atomId=*/100);
|
|
||||||
AStatsEvent_writeInt32(statsEvent, 10);
|
|
||||||
AStatsEvent_addInt32Annotation(statsEvent, annotationId, annotationValue);
|
|
||||||
AStatsEvent_build(statsEvent);
|
|
||||||
|
|
||||||
size_t size;
|
|
||||||
uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
|
|
||||||
EXPECT_TRUE(logEvent->parseBuffer(buf, size));
|
|
||||||
|
|
||||||
AStatsEvent_release(statsEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(LogEventTest, TestPrimaryFieldAnnotation) {
|
TEST(LogEventTest, TestPrimaryFieldAnnotation) {
|
||||||
LogEvent event(/*uid=*/0, /*pid=*/0);
|
LogEvent event(/*uid=*/0, /*pid=*/0);
|
||||||
createIntWithIntAnnotationLogEvent(&event, ANNOTATION_ID_STATE_OPTION,
|
createIntWithBoolAnnotationLogEvent(&event, ANNOTATION_ID_PRIMARY_FIELD, true);
|
||||||
STATE_OPTION_PRIMARY_FIELD);
|
|
||||||
|
|
||||||
const vector<FieldValue>& values = event.getValues();
|
const vector<FieldValue>& values = event.getValues();
|
||||||
EXPECT_EQ(values.size(), 1);
|
EXPECT_EQ(values.size(), 1);
|
||||||
@@ -304,8 +306,7 @@ TEST(LogEventTest, TestPrimaryFieldAnnotation) {
|
|||||||
|
|
||||||
TEST(LogEventTest, TestExclusiveStateAnnotation) {
|
TEST(LogEventTest, TestExclusiveStateAnnotation) {
|
||||||
LogEvent event(/*uid=*/0, /*pid=*/0);
|
LogEvent event(/*uid=*/0, /*pid=*/0);
|
||||||
createIntWithIntAnnotationLogEvent(&event, ANNOTATION_ID_STATE_OPTION,
|
createIntWithBoolAnnotationLogEvent(&event, ANNOTATION_ID_EXCLUSIVE_STATE, true);
|
||||||
STATE_OPTION_EXCLUSIVE_STATE);
|
|
||||||
|
|
||||||
const vector<FieldValue>& values = event.getValues();
|
const vector<FieldValue>& values = event.getValues();
|
||||||
EXPECT_EQ(values.size(), 1);
|
EXPECT_EQ(values.size(), 1);
|
||||||
@@ -328,8 +329,7 @@ TEST(LogEventTest, TestPrimaryFieldFirstUidAnnotation) {
|
|||||||
AStatsEvent_writeInt32(statsEvent, 10);
|
AStatsEvent_writeInt32(statsEvent, 10);
|
||||||
}
|
}
|
||||||
AStatsEvent_writeAttributionChain(statsEvent, uids, tags, 2);
|
AStatsEvent_writeAttributionChain(statsEvent, uids, tags, 2);
|
||||||
AStatsEvent_addInt32Annotation(statsEvent, ANNOTATION_ID_STATE_OPTION,
|
AStatsEvent_addBoolAnnotation(statsEvent, ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID, true);
|
||||||
STATE_OPTION_PRIMARY_FIELD_FIRST_UID);
|
|
||||||
AStatsEvent_build(statsEvent);
|
AStatsEvent_build(statsEvent);
|
||||||
|
|
||||||
// Construct LogEvent
|
// Construct LogEvent
|
||||||
@@ -348,7 +348,7 @@ TEST(LogEventTest, TestPrimaryFieldFirstUidAnnotation) {
|
|||||||
TEST(LogEventTest, TestResetStateAnnotation) {
|
TEST(LogEventTest, TestResetStateAnnotation) {
|
||||||
int32_t resetState = 10;
|
int32_t resetState = 10;
|
||||||
LogEvent event(/*uid=*/0, /*pid=*/0);
|
LogEvent event(/*uid=*/0, /*pid=*/0);
|
||||||
createIntWithIntAnnotationLogEvent(&event, ANNOTATION_ID_RESET_STATE, resetState);
|
createIntWithIntAnnotationLogEvent(&event, ANNOTATION_ID_TRIGGER_STATE_RESET, resetState);
|
||||||
|
|
||||||
const vector<FieldValue>& values = event.getValues();
|
const vector<FieldValue>& values = event.getValues();
|
||||||
EXPECT_EQ(values.size(), 1);
|
EXPECT_EQ(values.size(), 1);
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ AtomDecl::AtomDecl(const AtomDecl& that)
|
|||||||
primaryFields(that.primaryFields),
|
primaryFields(that.primaryFields),
|
||||||
exclusiveField(that.exclusiveField),
|
exclusiveField(that.exclusiveField),
|
||||||
defaultState(that.defaultState),
|
defaultState(that.defaultState),
|
||||||
resetState(that.resetState),
|
triggerStateReset(that.triggerStateReset),
|
||||||
nested(that.nested),
|
nested(that.nested),
|
||||||
uidField(that.uidField),
|
uidField(that.uidField),
|
||||||
whitelisted(that.whitelisted),
|
whitelisted(that.whitelisted),
|
||||||
@@ -153,7 +153,8 @@ void collate_enums(const EnumDescriptor& enumDescriptor, AtomField* atomField) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void addAnnotationToAtomDecl(AtomDecl* atomDecl, const int fieldNumber,
|
static void addAnnotationToAtomDecl(AtomDecl* atomDecl, const int fieldNumber,
|
||||||
const int annotationId, const AnnotationType annotationType,
|
const AnnotationId annotationId,
|
||||||
|
const AnnotationType annotationType,
|
||||||
const AnnotationValue annotationValue) {
|
const AnnotationValue annotationValue) {
|
||||||
if (dbg) {
|
if (dbg) {
|
||||||
printf(" Adding annotation to %s: [%d] = {id: %d, type: %d}\n", atomDecl->name.c_str(),
|
printf(" Adding annotation to %s: [%d] = {id: %d, type: %d}\n", atomDecl->name.c_str(),
|
||||||
@@ -168,23 +169,35 @@ static int collate_field_annotations(AtomDecl* atomDecl, const FieldDescriptor*
|
|||||||
int errorCount = 0;
|
int errorCount = 0;
|
||||||
|
|
||||||
if (field->options().HasExtension(os::statsd::state_field_option)) {
|
if (field->options().HasExtension(os::statsd::state_field_option)) {
|
||||||
const int option = field->options().GetExtension(os::statsd::state_field_option).option();
|
const os::statsd::StateAtomFieldOption& stateFieldOption =
|
||||||
if (option != STATE_OPTION_UNSET) {
|
field->options().GetExtension(os::statsd::state_field_option);
|
||||||
addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_STATE_OPTION,
|
const bool primaryField = stateFieldOption.primary_field();
|
||||||
ANNOTATION_TYPE_INT, AnnotationValue(option));
|
const bool exclusiveState = stateFieldOption.exclusive_state();
|
||||||
|
const bool primaryFieldFirstUid = stateFieldOption.primary_field_first_uid();
|
||||||
|
|
||||||
|
// Check the field is only one of primaryField, exclusiveState, or primaryFieldFirstUid.
|
||||||
|
if (primaryField + primaryFieldFirstUid + exclusiveState > 1) {
|
||||||
|
print_error(field,
|
||||||
|
"Field can be max 1 of primary_field, exclusive_state, "
|
||||||
|
"or primary_field_first_uid: '%s'\n",
|
||||||
|
atomDecl->message.c_str());
|
||||||
|
errorCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (option == STATE_OPTION_PRIMARY) {
|
if (primaryField) {
|
||||||
if (javaType == JAVA_TYPE_UNKNOWN || javaType == JAVA_TYPE_ATTRIBUTION_CHAIN ||
|
if (javaType == JAVA_TYPE_UNKNOWN || javaType == JAVA_TYPE_ATTRIBUTION_CHAIN ||
|
||||||
javaType == JAVA_TYPE_OBJECT || javaType == JAVA_TYPE_BYTE_ARRAY) {
|
javaType == JAVA_TYPE_OBJECT || javaType == JAVA_TYPE_BYTE_ARRAY) {
|
||||||
print_error(field, "Invalid primary state field: '%s'\n",
|
print_error(field, "Invalid primary state field: '%s'\n",
|
||||||
atomDecl->message.c_str());
|
atomDecl->message.c_str());
|
||||||
errorCount++;
|
errorCount++;
|
||||||
}
|
} else {
|
||||||
atomDecl->primaryFields.push_back(fieldNumber);
|
atomDecl->primaryFields.push_back(fieldNumber);
|
||||||
|
addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_PRIMARY_FIELD,
|
||||||
|
ANNOTATION_TYPE_BOOL, AnnotationValue(true));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (option == STATE_OPTION_PRIMARY_FIELD_FIRST_UID) {
|
if (primaryFieldFirstUid) {
|
||||||
if (javaType != JAVA_TYPE_ATTRIBUTION_CHAIN) {
|
if (javaType != JAVA_TYPE_ATTRIBUTION_CHAIN) {
|
||||||
print_error(field,
|
print_error(field,
|
||||||
"PRIMARY_FIELD_FIRST_UID annotation is only for AttributionChains: "
|
"PRIMARY_FIELD_FIRST_UID annotation is only for AttributionChains: "
|
||||||
@@ -193,10 +206,13 @@ static int collate_field_annotations(AtomDecl* atomDecl, const FieldDescriptor*
|
|||||||
errorCount++;
|
errorCount++;
|
||||||
} else {
|
} else {
|
||||||
atomDecl->primaryFields.push_back(FIRST_UID_IN_CHAIN_ID);
|
atomDecl->primaryFields.push_back(FIRST_UID_IN_CHAIN_ID);
|
||||||
|
addAnnotationToAtomDecl(atomDecl, fieldNumber,
|
||||||
|
ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID, ANNOTATION_TYPE_BOOL,
|
||||||
|
AnnotationValue(true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (option == STATE_OPTION_EXCLUSIVE) {
|
if (exclusiveState) {
|
||||||
if (javaType == JAVA_TYPE_UNKNOWN || javaType == JAVA_TYPE_ATTRIBUTION_CHAIN ||
|
if (javaType == JAVA_TYPE_UNKNOWN || javaType == JAVA_TYPE_ATTRIBUTION_CHAIN ||
|
||||||
javaType == JAVA_TYPE_OBJECT || javaType == JAVA_TYPE_BYTE_ARRAY) {
|
javaType == JAVA_TYPE_OBJECT || javaType == JAVA_TYPE_BYTE_ARRAY) {
|
||||||
print_error(field, "Invalid exclusive state field: '%s'\n",
|
print_error(field, "Invalid exclusive state field: '%s'\n",
|
||||||
@@ -204,43 +220,36 @@ static int collate_field_annotations(AtomDecl* atomDecl, const FieldDescriptor*
|
|||||||
errorCount++;
|
errorCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (atomDecl->exclusiveField == 0) {
|
if (atomDecl->exclusiveField != 0) {
|
||||||
atomDecl->exclusiveField = fieldNumber;
|
|
||||||
} else {
|
|
||||||
print_error(field,
|
print_error(field,
|
||||||
"Cannot have more than one exclusive state field in an "
|
"Cannot have more than one exclusive state field in an "
|
||||||
"atom: '%s'\n",
|
"atom: '%s'\n",
|
||||||
atomDecl->message.c_str());
|
atomDecl->message.c_str());
|
||||||
errorCount++;
|
errorCount++;
|
||||||
|
} else {
|
||||||
|
atomDecl->exclusiveField = fieldNumber;
|
||||||
|
addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_EXCLUSIVE_STATE,
|
||||||
|
ANNOTATION_TYPE_BOOL, AnnotationValue(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (field->options()
|
if (stateFieldOption.has_default_state_value()) {
|
||||||
.GetExtension(os::statsd::state_field_option)
|
const int defaultState = stateFieldOption.default_state_value();
|
||||||
.has_default_state_value()) {
|
|
||||||
const int defaultState = field->options()
|
|
||||||
.GetExtension(os::statsd::state_field_option)
|
|
||||||
.default_state_value();
|
|
||||||
atomDecl->defaultState = defaultState;
|
atomDecl->defaultState = defaultState;
|
||||||
|
|
||||||
addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_DEFAULT_STATE,
|
addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_DEFAULT_STATE,
|
||||||
ANNOTATION_TYPE_INT, AnnotationValue(defaultState));
|
ANNOTATION_TYPE_INT, AnnotationValue(defaultState));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (field->options()
|
if (stateFieldOption.has_trigger_state_reset_value()) {
|
||||||
.GetExtension(os::statsd::state_field_option)
|
const int triggerStateReset = stateFieldOption.trigger_state_reset_value();
|
||||||
.has_reset_state_value()) {
|
|
||||||
const int resetState = field->options()
|
|
||||||
.GetExtension(os::statsd::state_field_option)
|
|
||||||
.reset_state_value();
|
|
||||||
|
|
||||||
atomDecl->resetState = resetState;
|
atomDecl->triggerStateReset = triggerStateReset;
|
||||||
addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_RESET_STATE,
|
addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_TRIGGER_STATE_RESET,
|
||||||
ANNOTATION_TYPE_INT, AnnotationValue(resetState));
|
ANNOTATION_TYPE_INT, AnnotationValue(triggerStateReset));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (field->options().GetExtension(os::statsd::state_field_option).has_nested()) {
|
if (stateFieldOption.has_nested()) {
|
||||||
const bool nested =
|
const bool nested = stateFieldOption.nested();
|
||||||
field->options().GetExtension(os::statsd::state_field_option).nested();
|
|
||||||
atomDecl->nested = nested;
|
atomDecl->nested = nested;
|
||||||
|
|
||||||
addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_STATE_NESTED,
|
addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_STATE_NESTED,
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#define ANDROID_STATS_LOG_API_GEN_COLLATION_H
|
#define ANDROID_STATS_LOG_API_GEN_COLLATION_H
|
||||||
|
|
||||||
#include <google/protobuf/descriptor.h>
|
#include <google/protobuf/descriptor.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
@@ -40,17 +41,16 @@ const int PULL_ATOM_START_ID = 10000;
|
|||||||
|
|
||||||
const int FIRST_UID_IN_CHAIN_ID = 0;
|
const int FIRST_UID_IN_CHAIN_ID = 0;
|
||||||
|
|
||||||
const unsigned char ANNOTATION_ID_IS_UID = 1;
|
enum AnnotationId : uint8_t {
|
||||||
const unsigned char ANNOTATION_ID_TRUNCATE_TIMESTAMP = 2;
|
ANNOTATION_ID_IS_UID = 1,
|
||||||
const unsigned char ANNOTATION_ID_STATE_OPTION = 3;
|
ANNOTATION_ID_TRUNCATE_TIMESTAMP = 2,
|
||||||
const unsigned char ANNOTATION_ID_DEFAULT_STATE = 4;
|
ANNOTATION_ID_PRIMARY_FIELD = 3,
|
||||||
const unsigned char ANNOTATION_ID_RESET_STATE = 5;
|
ANNOTATION_ID_EXCLUSIVE_STATE = 4,
|
||||||
const unsigned char ANNOTATION_ID_STATE_NESTED = 6;
|
ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID = 5,
|
||||||
|
ANNOTATION_ID_DEFAULT_STATE = 6,
|
||||||
const int STATE_OPTION_UNSET = os::statsd::StateField::STATE_FIELD_UNSET;
|
ANNOTATION_ID_TRIGGER_STATE_RESET = 7,
|
||||||
const int STATE_OPTION_EXCLUSIVE = os::statsd::StateField::EXCLUSIVE_STATE;
|
ANNOTATION_ID_STATE_NESTED = 8,
|
||||||
const int STATE_OPTION_PRIMARY_FIELD_FIRST_UID = os::statsd::StateField::PRIMARY_FIELD_FIRST_UID;
|
};
|
||||||
const int STATE_OPTION_PRIMARY = os::statsd::StateField::PRIMARY_FIELD;
|
|
||||||
|
|
||||||
const int ATOM_ID_FIELD_NUMBER = -1;
|
const int ATOM_ID_FIELD_NUMBER = -1;
|
||||||
|
|
||||||
@@ -93,12 +93,12 @@ union AnnotationValue {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct Annotation {
|
struct Annotation {
|
||||||
const unsigned char annotationId;
|
const AnnotationId annotationId;
|
||||||
const int atomId;
|
const int atomId;
|
||||||
AnnotationType type;
|
AnnotationType type;
|
||||||
AnnotationValue value;
|
AnnotationValue value;
|
||||||
|
|
||||||
inline Annotation(unsigned char annotationId, int atomId, AnnotationType type,
|
inline Annotation(AnnotationId annotationId, int atomId, AnnotationType type,
|
||||||
AnnotationValue value)
|
AnnotationValue value)
|
||||||
: annotationId(annotationId), atomId(atomId), type(type), value(value) {
|
: annotationId(annotationId), atomId(atomId), type(type), value(value) {
|
||||||
}
|
}
|
||||||
@@ -159,7 +159,7 @@ struct AtomDecl {
|
|||||||
vector<int> primaryFields;
|
vector<int> primaryFields;
|
||||||
int exclusiveField = 0;
|
int exclusiveField = 0;
|
||||||
int defaultState = INT_MAX;
|
int defaultState = INT_MAX;
|
||||||
int resetState = INT_MAX;
|
int triggerStateReset = INT_MAX;
|
||||||
bool nested;
|
bool nested;
|
||||||
|
|
||||||
int uidField = 0;
|
int uidField = 0;
|
||||||
|
|||||||
@@ -151,8 +151,8 @@ static void write_atoms_info_cpp_body(FILE* out, const Atoms& atoms) {
|
|||||||
fprintf(out, " opt->defaultState = UNSET_VALUE;\n");
|
fprintf(out, " opt->defaultState = UNSET_VALUE;\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((*atomIt)->resetState != INT_MAX) {
|
if ((*atomIt)->triggerStateReset != INT_MAX) {
|
||||||
fprintf(out, " opt->resetState = %d;\n", (*atomIt)->resetState);
|
fprintf(out, " opt->resetState = %d;\n", (*atomIt)->triggerStateReset);
|
||||||
} else {
|
} else {
|
||||||
fprintf(out, " opt->resetState = UNSET_VALUE;\n");
|
fprintf(out, " opt->resetState = UNSET_VALUE;\n");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,11 +63,10 @@ static void write_annotations(FILE* out, int argIndex,
|
|||||||
int resetState = -1;
|
int resetState = -1;
|
||||||
int defaultState = -1;
|
int defaultState = -1;
|
||||||
for (const shared_ptr<Annotation>& annotation : annotations) {
|
for (const shared_ptr<Annotation>& annotation : annotations) {
|
||||||
const string& annotationConstant =
|
const string& annotationConstant = ANNOTATION_ID_CONSTANTS.at(annotation->annotationId);
|
||||||
ANNOTATION_ID_CONSTANTS.at(annotation->annotationId);
|
|
||||||
switch (annotation->type) {
|
switch (annotation->type) {
|
||||||
case ANNOTATION_TYPE_INT:
|
case ANNOTATION_TYPE_INT:
|
||||||
if (ANNOTATION_ID_RESET_STATE == annotation->annotationId) {
|
if (ANNOTATION_ID_TRIGGER_STATE_RESET == annotation->annotationId) {
|
||||||
resetState = annotation->value.intValue;
|
resetState = annotation->value.intValue;
|
||||||
} else if (ANNOTATION_ID_DEFAULT_STATE == annotation->annotationId) {
|
} else if (ANNOTATION_ID_DEFAULT_STATE == annotation->annotationId) {
|
||||||
defaultState = annotation->value.intValue;
|
defaultState = annotation->value.intValue;
|
||||||
@@ -87,7 +86,7 @@ static void write_annotations(FILE* out, int argIndex,
|
|||||||
}
|
}
|
||||||
if (defaultState != -1 && resetState != -1) {
|
if (defaultState != -1 && resetState != -1) {
|
||||||
const string& annotationConstant =
|
const string& annotationConstant =
|
||||||
ANNOTATION_ID_CONSTANTS.at(ANNOTATION_ID_RESET_STATE);
|
ANNOTATION_ID_CONSTANTS.at(ANNOTATION_ID_TRIGGER_STATE_RESET);
|
||||||
fprintf(out, " if (arg%d == %d) {\n", argIndex, resetState);
|
fprintf(out, " if (arg%d == %d) {\n", argIndex, resetState);
|
||||||
fprintf(out, " builder.addIntAnnotation(%s, %d);\n",
|
fprintf(out, " builder.addIntAnnotation(%s, %d);\n",
|
||||||
annotationConstant.c_str(), defaultState);
|
annotationConstant.c_str(), defaultState);
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ static void write_native_annotation_constants(FILE* out) {
|
|||||||
fprintf(out, "\n");
|
fprintf(out, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void write_annotations(FILE* out, int argIndex,
|
static void write_annotations(FILE* out, int argIndex,
|
||||||
const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet,
|
const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet,
|
||||||
const string& methodPrefix, const string& methodSuffix) {
|
const string& methodPrefix, const string& methodSuffix) {
|
||||||
@@ -47,11 +46,10 @@ static void write_annotations(FILE* out, int argIndex,
|
|||||||
int resetState = -1;
|
int resetState = -1;
|
||||||
int defaultState = -1;
|
int defaultState = -1;
|
||||||
for (const shared_ptr<Annotation>& annotation : annotations) {
|
for (const shared_ptr<Annotation>& annotation : annotations) {
|
||||||
const string& annotationConstant =
|
const string& annotationConstant = ANNOTATION_ID_CONSTANTS.at(annotation->annotationId);
|
||||||
ANNOTATION_ID_CONSTANTS.at(annotation->annotationId);
|
|
||||||
switch (annotation->type) {
|
switch (annotation->type) {
|
||||||
case ANNOTATION_TYPE_INT:
|
case ANNOTATION_TYPE_INT:
|
||||||
if (ANNOTATION_ID_RESET_STATE == annotation->annotationId) {
|
if (ANNOTATION_ID_TRIGGER_STATE_RESET == annotation->annotationId) {
|
||||||
resetState = annotation->value.intValue;
|
resetState = annotation->value.intValue;
|
||||||
} else if (ANNOTATION_ID_DEFAULT_STATE == annotation->annotationId) {
|
} else if (ANNOTATION_ID_DEFAULT_STATE == annotation->annotationId) {
|
||||||
defaultState = annotation->value.intValue;
|
defaultState = annotation->value.intValue;
|
||||||
@@ -74,7 +72,7 @@ static void write_annotations(FILE* out, int argIndex,
|
|||||||
}
|
}
|
||||||
if (defaultState != -1 && resetState != -1) {
|
if (defaultState != -1 && resetState != -1) {
|
||||||
const string& annotationConstant =
|
const string& annotationConstant =
|
||||||
ANNOTATION_ID_CONSTANTS.at(ANNOTATION_ID_RESET_STATE);
|
ANNOTATION_ID_CONSTANTS.at(ANNOTATION_ID_TRIGGER_STATE_RESET);
|
||||||
fprintf(out, " if (arg%d == %d) {\n", argIndex, resetState);
|
fprintf(out, " if (arg%d == %d) {\n", argIndex, resetState);
|
||||||
fprintf(out, " %saddInt32Annotation(%s%s, %d);\n", methodPrefix.c_str(),
|
fprintf(out, " %saddInt32Annotation(%s%s, %d);\n", methodPrefix.c_str(),
|
||||||
methodSuffix.c_str(), annotationConstant.c_str(), defaultState);
|
methodSuffix.c_str(), annotationConstant.c_str(), defaultState);
|
||||||
|
|||||||
@@ -149,42 +149,42 @@ message GoodStateAtoms {
|
|||||||
|
|
||||||
// The atom has only primary field but no exclusive state field.
|
// The atom has only primary field but no exclusive state field.
|
||||||
message BadStateAtom1 {
|
message BadStateAtom1 {
|
||||||
optional int32 uid = 1 [(android.os.statsd.state_field_option).option = PRIMARY_FIELD];
|
optional int32 uid = 1 [(android.os.statsd.state_field_option).primary_field = true];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only primative types can be annotated.
|
// Only primative types can be annotated.
|
||||||
message BadStateAtom2 {
|
message BadStateAtom2 {
|
||||||
repeated android.os.statsd.AttributionNode attribution = 1
|
repeated android.os.statsd.AttributionNode attribution = 1
|
||||||
[(android.os.statsd.state_field_option).option = PRIMARY_FIELD];
|
[(android.os.statsd.state_field_option).primary_field = true];
|
||||||
optional int32 state = 2 [(android.os.statsd.state_field_option).option = EXCLUSIVE_STATE];
|
optional int32 state = 2 [(android.os.statsd.state_field_option).exclusive_state = true];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Having 2 exclusive state field in the atom means the atom is badly designed.
|
// Having 2 exclusive state field in the atom means the atom is badly designed.
|
||||||
// E.g., putting bluetooth state and wifi state in the same atom.
|
// E.g., putting bluetooth state and wifi state in the same atom.
|
||||||
message BadStateAtom3 {
|
message BadStateAtom3 {
|
||||||
optional int32 uid = 1 [(android.os.statsd.state_field_option).option = PRIMARY_FIELD];
|
optional int32 uid = 1 [(android.os.statsd.state_field_option).primary_field = true];
|
||||||
optional int32 state = 2 [(android.os.statsd.state_field_option).option = EXCLUSIVE_STATE];
|
optional int32 state = 2 [(android.os.statsd.state_field_option).exclusive_state = true];
|
||||||
optional int32 state2 = 3 [(android.os.statsd.state_field_option).option = EXCLUSIVE_STATE];
|
optional int32 state2 = 3 [(android.os.statsd.state_field_option).exclusive_state = true];
|
||||||
}
|
}
|
||||||
|
|
||||||
message GoodStateAtom1 {
|
message GoodStateAtom1 {
|
||||||
optional int32 uid = 1 [(android.os.statsd.state_field_option).option = PRIMARY_FIELD];
|
optional int32 uid = 1 [(android.os.statsd.state_field_option).primary_field = true];
|
||||||
optional int32 state = 2 [(android.os.statsd.state_field_option).option = EXCLUSIVE_STATE];
|
optional int32 state = 2 [(android.os.statsd.state_field_option).exclusive_state = true];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Atoms can have exclusive state field, but no primary field. That means
|
// Atoms can have exclusive state field, but no primary field. That means
|
||||||
// the state is globally exclusive (e.g., DisplayState).
|
// the state is globally exclusive (e.g., DisplayState).
|
||||||
message GoodStateAtom2 {
|
message GoodStateAtom2 {
|
||||||
optional int32 uid = 1;
|
optional int32 uid = 1;
|
||||||
optional int32 state = 2 [(android.os.statsd.state_field_option).option = EXCLUSIVE_STATE];
|
optional int32 state = 2 [(android.os.statsd.state_field_option).exclusive_state = true];
|
||||||
}
|
}
|
||||||
|
|
||||||
// We can have more than one primary fields. That means their combination is a
|
// We can have more than one primary fields. That means their combination is a
|
||||||
// primary key.
|
// primary key.
|
||||||
message GoodStateAtom3 {
|
message GoodStateAtom3 {
|
||||||
optional int32 uid = 1 [(android.os.statsd.state_field_option).option = PRIMARY_FIELD];
|
optional int32 uid = 1 [(android.os.statsd.state_field_option).primary_field = true];
|
||||||
optional int32 tid = 2 [(android.os.statsd.state_field_option).option = PRIMARY_FIELD];
|
optional int32 tid = 2 [(android.os.statsd.state_field_option).primary_field = true];
|
||||||
optional int32 state = 3 [(android.os.statsd.state_field_option).option = EXCLUSIVE_STATE];
|
optional int32 state = 3 [(android.os.statsd.state_field_option).exclusive_state = true];
|
||||||
}
|
}
|
||||||
|
|
||||||
message WhitelistedAtom {
|
message WhitelistedAtom {
|
||||||
@@ -214,7 +214,7 @@ message ModuleTwoAtom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message ModuleOneAndTwoAtom {
|
message ModuleOneAndTwoAtom {
|
||||||
optional int32 field = 1 [(android.os.statsd.state_field_option).option = EXCLUSIVE_STATE];
|
optional int32 field = 1 [(android.os.statsd.state_field_option).exclusive_state = true];
|
||||||
}
|
}
|
||||||
|
|
||||||
message NoModuleAtom {
|
message NoModuleAtom {
|
||||||
|
|||||||
@@ -308,10 +308,10 @@ TEST(CollationTest, RecognizeModuleAtom) {
|
|||||||
EXPECT_EQ(1ul, annotationSet->size());
|
EXPECT_EQ(1ul, annotationSet->size());
|
||||||
annotationSetIt = annotationSet->begin();
|
annotationSetIt = annotationSet->begin();
|
||||||
annotation = annotationSetIt->get();
|
annotation = annotationSetIt->get();
|
||||||
EXPECT_EQ(ANNOTATION_ID_STATE_OPTION, annotation->annotationId);
|
EXPECT_EQ(ANNOTATION_ID_EXCLUSIVE_STATE, annotation->annotationId);
|
||||||
EXPECT_EQ(3, annotation->atomId);
|
EXPECT_EQ(3, annotation->atomId);
|
||||||
EXPECT_EQ(ANNOTATION_TYPE_INT, annotation->type);
|
EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type);
|
||||||
EXPECT_EQ(os::statsd::StateField::EXCLUSIVE_STATE, annotation->value.intValue);
|
EXPECT_TRUE(annotation->value.boolValue);
|
||||||
|
|
||||||
signatureInfoMapIt++;
|
signatureInfoMapIt++;
|
||||||
signature = &signatureInfoMapIt->first;
|
signature = &signatureInfoMapIt->first;
|
||||||
@@ -378,10 +378,10 @@ TEST(CollationTest, RecognizeModule1Atom) {
|
|||||||
EXPECT_EQ(1ul, annotationSet->size());
|
EXPECT_EQ(1ul, annotationSet->size());
|
||||||
annotationSetIt = annotationSet->begin();
|
annotationSetIt = annotationSet->begin();
|
||||||
annotation = annotationSetIt->get();
|
annotation = annotationSetIt->get();
|
||||||
EXPECT_EQ(ANNOTATION_ID_STATE_OPTION, annotation->annotationId);
|
EXPECT_EQ(ANNOTATION_ID_EXCLUSIVE_STATE, annotation->annotationId);
|
||||||
EXPECT_EQ(3, annotation->atomId);
|
EXPECT_EQ(3, annotation->atomId);
|
||||||
EXPECT_EQ(ANNOTATION_TYPE_INT, annotation->type);
|
EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type);
|
||||||
EXPECT_EQ(os::statsd::StateField::EXCLUSIVE_STATE, annotation->value.intValue);
|
EXPECT_TRUE(annotation->value.boolValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace stats_log_api_gen
|
} // namespace stats_log_api_gen
|
||||||
|
|||||||
@@ -38,13 +38,14 @@ const int JAVA_MODULE_REQUIRES_FLOAT = 0x01;
|
|||||||
const int JAVA_MODULE_REQUIRES_ATTRIBUTION = 0x02;
|
const int JAVA_MODULE_REQUIRES_ATTRIBUTION = 0x02;
|
||||||
const int JAVA_MODULE_REQUIRES_KEY_VALUE_PAIRS = 0x04;
|
const int JAVA_MODULE_REQUIRES_KEY_VALUE_PAIRS = 0x04;
|
||||||
|
|
||||||
const map<unsigned char, string> ANNOTATION_ID_CONSTANTS = {
|
const map<AnnotationId, string> ANNOTATION_ID_CONSTANTS = {
|
||||||
{ANNOTATION_ID_IS_UID, "ANNOTATION_ID_IS_UID"},
|
{ANNOTATION_ID_IS_UID, "ANNOTATION_ID_IS_UID"},
|
||||||
{ANNOTATION_ID_TRUNCATE_TIMESTAMP, "ANNOTATION_ID_TRUNCATE_TIMESTAMP"},
|
{ANNOTATION_ID_TRUNCATE_TIMESTAMP, "ANNOTATION_ID_TRUNCATE_TIMESTAMP"},
|
||||||
{ ANNOTATION_ID_STATE_OPTION, "ANNOTATION_ID_STATE_OPTION" },
|
{ANNOTATION_ID_PRIMARY_FIELD, "ANNOTATION_ID_PRIMARY_FIELD"},
|
||||||
{ ANNOTATION_ID_RESET_STATE, "ANNOTATION_ID_RESET_STATE" },
|
{ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID, "ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID"},
|
||||||
{ ANNOTATION_ID_STATE_NESTED, "ANNOTATION_ID_STATE_NESTED" }
|
{ANNOTATION_ID_EXCLUSIVE_STATE, "ANNOTATION_ID_EXCLUSIVE_STATE"},
|
||||||
};
|
{ANNOTATION_ID_TRIGGER_STATE_RESET, "ANNOTATION_ID_TRIGGER_STATE_RESET"},
|
||||||
|
{ANNOTATION_ID_STATE_NESTED, "ANNOTATION_ID_STATE_NESTED"}};
|
||||||
|
|
||||||
string make_constant_name(const string& str);
|
string make_constant_name(const string& str);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user