Merge "Make state_option top-level boolean annotations" into rvc-dev

This commit is contained in:
TreeHugger Robot
2020-04-04 05:13:01 +00:00
committed by Android (Google) Code Review
14 changed files with 243 additions and 233 deletions

View File

@@ -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

View File

@@ -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.

View File

@@ -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;

View File

@@ -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);
@@ -372,7 +380,7 @@ bool LogEvent::parseBuffer(uint8_t* buf, size_t len) {
uint8_t typeId = getTypeId(typeInfo); uint8_t typeId = getTypeId(typeInfo);
// TODO(b/144373276): handle errors passed to the socket // TODO(b/144373276): handle errors passed to the socket
switch(typeId) { switch (typeId) {
case BOOL_TYPE: case BOOL_TYPE:
parseBool(pos, /*depth=*/0, last, getNumAnnotations(typeInfo)); parseBool(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
break; break;

View File

@@ -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);
/** /**

View File

@@ -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);
@@ -104,7 +137,7 @@ TEST(LogEventTest, TestStringAndByteArrayParsing) {
size_t size; size_t size;
uint8_t* buf = AStatsEvent_getBuffer(event, &size); uint8_t* buf = AStatsEvent_getBuffer(event, &size);
LogEvent logEvent(/*uid=*/ 1000, /*pid=*/ 1001); LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
EXPECT_TRUE(logEvent.parseBuffer(buf, size)); EXPECT_TRUE(logEvent.parseBuffer(buf, size));
EXPECT_EQ(100, logEvent.GetTagId()); EXPECT_EQ(100, logEvent.GetTagId());
@@ -140,7 +173,7 @@ TEST(LogEventTest, TestEmptyString) {
size_t size; size_t size;
uint8_t* buf = AStatsEvent_getBuffer(event, &size); uint8_t* buf = AStatsEvent_getBuffer(event, &size);
LogEvent logEvent(/*uid=*/ 1000, /*pid=*/ 1001); LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
EXPECT_TRUE(logEvent.parseBuffer(buf, size)); EXPECT_TRUE(logEvent.parseBuffer(buf, size));
EXPECT_EQ(100, logEvent.GetTagId()); EXPECT_EQ(100, logEvent.GetTagId());
@@ -169,7 +202,7 @@ TEST(LogEventTest, TestByteArrayWithNullCharacter) {
size_t size; size_t size;
uint8_t* buf = AStatsEvent_getBuffer(event, &size); uint8_t* buf = AStatsEvent_getBuffer(event, &size);
LogEvent logEvent(/*uid=*/ 1000, /*pid=*/ 1001); LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
EXPECT_TRUE(logEvent.parseBuffer(buf, size)); EXPECT_TRUE(logEvent.parseBuffer(buf, size));
EXPECT_EQ(100, logEvent.GetTagId()); EXPECT_EQ(100, logEvent.GetTagId());
@@ -205,7 +238,7 @@ TEST(LogEventTest, TestAttributionChain) {
size_t size; size_t size;
uint8_t* buf = AStatsEvent_getBuffer(event, &size); uint8_t* buf = AStatsEvent_getBuffer(event, &size);
LogEvent logEvent(/*uid=*/ 1000, /*pid=*/ 1001); LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
EXPECT_TRUE(logEvent.parseBuffer(buf, size)); EXPECT_TRUE(logEvent.parseBuffer(buf, size));
EXPECT_EQ(100, logEvent.GetTagId()); EXPECT_EQ(100, logEvent.GetTagId());
@@ -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);

View File

@@ -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,

View File

@@ -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;

View File

@@ -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");
} }

View File

@@ -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);

View File

@@ -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);

View File

@@ -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 {

View File

@@ -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

View File

@@ -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);