Add truncate_timestamp annotation
Mark privacy-sensitive atoms with truncate_timestamp annotation.
Factor out annotation collation to a helper method.
Add truncate_timestamp annotation support in stats-log-api-gen.
Add writeAnnotation* calls in Java and native generated code for
atom id annotations.
TODO: remove kTruncatingTimestampAtoms from atoms_info.
TODO: use truncate_timestamp annotation inside statsd.
Bug: 151111680
Test: stats-log-api-gen-test
Test: m statslog-framework-java-gen
Test: m libstatsmetadata
Change-Id: I3db5f4ffbf959bd36c62f890cc88606912798d40
diff --git a/cmds/statsd/src/atom_field_options.proto b/cmds/statsd/src/atom_field_options.proto
index 40a24dc..afee79d 100644
--- a/cmds/statsd/src/atom_field_options.proto
+++ b/cmds/statsd/src/atom_field_options.proto
@@ -117,4 +117,6 @@
optional bool allow_from_any_uid = 50003 [default = false];
repeated string module = 50004;
+
+ optional bool truncate_timestamp = 50005 [default = false];
}
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index f9711c3..e60ac7f 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -93,7 +93,8 @@
10 [(module) = "framework", (module) = "statsdtest"];
LongPartialWakelockStateChanged long_partial_wakelock_state_changed =
11 [(module) = "framework"];
- MobileRadioPowerStateChanged mobile_radio_power_state_changed = 12 [(module) = "framework"];
+ MobileRadioPowerStateChanged mobile_radio_power_state_changed =
+ 12 [(module) = "framework", (truncate_timestamp) = true];
WifiRadioPowerStateChanged wifi_radio_power_state_changed = 13 [(module) = "framework"];
ActivityManagerSleepStateChanged activity_manager_sleep_state_changed =
14 [(module) = "framework"];
@@ -106,7 +107,8 @@
20 [(module) = "framework", (module) = "statsdtest"];
DeviceIdleModeStateChanged device_idle_mode_state_changed = 21 [(module) = "framework"];
DeviceIdlingModeStateChanged device_idling_mode_state_changed = 22 [(module) = "framework"];
- AudioStateChanged audio_state_changed = 23 [(module) = "framework"];
+ AudioStateChanged audio_state_changed =
+ 23 [(module) = "framework", (truncate_timestamp) = true];
MediaCodecStateChanged media_codec_state_changed = 24 [(module) = "framework"];
CameraStateChanged camera_state_changed = 25 [(module) = "framework"];
FlashlightStateChanged flashlight_state_changed = 26 [(module) = "framework"];
@@ -127,7 +129,8 @@
WifiLockStateChanged wifi_lock_state_changed = 37 [(module) = "wifi"];
WifiSignalStrengthChanged wifi_signal_strength_changed = 38 [(module) = "wifi"];
WifiScanStateChanged wifi_scan_state_changed = 39 [(module) = "wifi"];
- PhoneSignalStrengthChanged phone_signal_strength_changed = 40 [(module) = "framework"];
+ PhoneSignalStrengthChanged phone_signal_strength_changed =
+ 40 [(module) = "framework", (truncate_timestamp) = true];
SettingChanged setting_changed = 41 [(module) = "framework"];
ActivityForegroundStateChanged activity_foreground_state_changed =
42 [(module) = "framework", (module) = "statsdtest"];
@@ -153,7 +156,8 @@
59 [(module) = "framework", (module) = "statsdtest"];
ForegroundServiceStateChanged foreground_service_state_changed
= 60 [(module) = "framework"];
- CallStateChanged call_state_changed = 61 [(module) = "telecom"];
+ CallStateChanged call_state_changed =
+ 61 [(module) = "telecom", (truncate_timestamp) = true];
KeyguardStateChanged keyguard_state_changed = 62 [(module) = "sysui"];
KeyguardBouncerStateChanged keyguard_bouncer_state_changed = 63 [(module) = "sysui"];
KeyguardBouncerPasswordEntered keyguard_bouncer_password_entered = 64 [(module) = "sysui"];
@@ -419,8 +423,10 @@
oneof pulled {
WifiBytesTransfer wifi_bytes_transfer = 10000 [(module) = "framework"];
WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 10001 [(module) = "framework"];
- MobileBytesTransfer mobile_bytes_transfer = 10002 [(module) = "framework"];
- MobileBytesTransferByFgBg mobile_bytes_transfer_by_fg_bg = 10003 [(module) = "framework"];
+ MobileBytesTransfer mobile_bytes_transfer =
+ 10002 [(module) = "framework", (truncate_timestamp) = true];
+ MobileBytesTransferByFgBg mobile_bytes_transfer_by_fg_bg =
+ 10003 [(module) = "framework", (truncate_timestamp) = true];
BluetoothBytesTransfer bluetooth_bytes_transfer = 10006 [(module) = "framework"];
KernelWakelock kernel_wakelock = 10004 [(module) = "framework"];
SubsystemSleepState subsystem_sleep_state = 10005 [(module) = "statsdtest"];
diff --git a/tools/stats_log_api_gen/Collation.cpp b/tools/stats_log_api_gen/Collation.cpp
index 47eb63e..27cc259 100644
--- a/tools/stats_log_api_gen/Collation.cpp
+++ b/tools/stats_log_api_gen/Collation.cpp
@@ -55,7 +55,8 @@
resetState(that.resetState),
nested(that.nested),
uidField(that.uidField),
- whitelisted(that.whitelisted) {}
+ whitelisted(that.whitelisted),
+ truncateTimestamp(that.truncateTimestamp) {}
AtomDecl::AtomDecl(int c, const string& n, const string& m)
:code(c),
@@ -173,6 +174,126 @@
annotationId, atomDecl->code, annotationType, annotationValue));
}
+static int collate_field_annotations(AtomDecl* atomDecl, const FieldDescriptor* field,
+ const int fieldNumber, const java_type_t& javaType) {
+ int errorCount = 0;
+
+ if (field->options().HasExtension(os::statsd::state_field_option)) {
+ const int option = field->options().GetExtension(os::statsd::state_field_option).option();
+ if (option != STATE_OPTION_UNSET) {
+ addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_STATE_OPTION,
+ ANNOTATION_TYPE_INT, AnnotationValue(option));
+ }
+
+ if (option == STATE_OPTION_PRIMARY) {
+ if (javaType == JAVA_TYPE_UNKNOWN ||
+ javaType == JAVA_TYPE_ATTRIBUTION_CHAIN ||
+ javaType == JAVA_TYPE_OBJECT || javaType == JAVA_TYPE_BYTE_ARRAY) {
+ print_error(
+ field,
+ "Invalid primary state field: '%s'\n",
+ atomDecl->message.c_str());
+ errorCount++;
+ }
+ atomDecl->primaryFields.push_back(fieldNumber);
+
+ }
+
+ if (option == STATE_OPTION_PRIMARY_FIELD_FIRST_UID) {
+ if (javaType != JAVA_TYPE_ATTRIBUTION_CHAIN) {
+ print_error(
+ field,
+ "PRIMARY_FIELD_FIRST_UID annotation is only for AttributionChains: '%s'\n",
+ atomDecl->message.c_str());
+ errorCount++;
+ } else {
+ atomDecl->primaryFields.push_back(FIRST_UID_IN_CHAIN_ID);
+ }
+ }
+
+ if (option == STATE_OPTION_EXCLUSIVE) {
+ if (javaType == JAVA_TYPE_UNKNOWN ||
+ javaType == JAVA_TYPE_ATTRIBUTION_CHAIN ||
+ javaType == JAVA_TYPE_OBJECT || javaType == JAVA_TYPE_BYTE_ARRAY) {
+ print_error(
+ field,
+ "Invalid exclusive state field: '%s'\n",
+ atomDecl->message.c_str());
+ errorCount++;
+ }
+
+ if (atomDecl->exclusiveField == 0) {
+ atomDecl->exclusiveField = fieldNumber;
+ } else {
+ print_error(
+ field,
+ "Cannot have more than one exclusive state field in an atom: '%s'\n",
+ atomDecl->message.c_str());
+ errorCount++;
+ }
+
+ if (field->options()
+ .GetExtension(os::statsd::state_field_option)
+ .has_default_state_value()) {
+ const int defaultState =
+ field->options().GetExtension(os::statsd::state_field_option)
+ .default_state_value();
+ atomDecl->defaultState = defaultState;
+
+ addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_DEFAULT_STATE,
+ ANNOTATION_TYPE_INT, AnnotationValue(defaultState));
+ }
+
+ if (field->options().GetExtension(os::statsd::state_field_option)
+ .has_reset_state_value()) {
+ const int resetState = field->options()
+ .GetExtension(os::statsd::state_field_option)
+ .reset_state_value();
+
+ atomDecl->resetState = resetState;
+ addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_RESET_STATE,
+ ANNOTATION_TYPE_INT, AnnotationValue(resetState));
+ }
+
+ if (field->options().GetExtension(os::statsd::state_field_option)
+ .has_nested()) {
+ const bool nested =
+ field->options().GetExtension(os::statsd::state_field_option).nested();
+ atomDecl->nested = nested;
+
+ addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_STATE_NESTED,
+ ANNOTATION_TYPE_BOOL, AnnotationValue(nested));
+ }
+ }
+
+ }
+
+ if (field->options().GetExtension(os::statsd::is_uid) == true) {
+ if (javaType != JAVA_TYPE_INT) {
+ print_error(
+ field,
+ "is_uid annotation can only be applied to int32 fields: '%s'\n",
+ atomDecl->message.c_str());
+ errorCount++;
+ }
+
+ if (atomDecl->uidField == 0) {
+ atomDecl->uidField = fieldNumber;
+
+ addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_IS_UID,
+ ANNOTATION_TYPE_BOOL, AnnotationValue(true));
+ } else {
+ print_error(
+ field,
+ "Cannot have more than one field in an atom with is_uid annotation: '%s'\n",
+ atomDecl->message.c_str());
+ errorCount++;
+ }
+ }
+
+ return errorCount;
+}
+
/**
* Gather the info about an atom proto.
*/
@@ -287,6 +408,12 @@
os::statsd::LogMode::MODE_BYTES;
AtomField atField(field->name(), javaType);
+
+ if (javaType == JAVA_TYPE_ENUM) {
+ // All enums are treated as ints when it comes to function signatures.
+ collate_enums(*field->enum_type(), &atField);
+ }
+
// Generate signature for pushed atoms
if (atomDecl->code < PULL_ATOM_START_ID) {
if (javaType == JAVA_TYPE_ENUM) {
@@ -298,129 +425,10 @@
signature->push_back(javaType);
}
}
- if (javaType == JAVA_TYPE_ENUM) {
- // All enums are treated as ints when it comes to function signatures.
- collate_enums(*field->enum_type(), &atField);
- }
+
atomDecl->fields.push_back(atField);
- if (field->options().HasExtension(os::statsd::state_field_option)) {
- const int option = field->options().GetExtension(os::statsd::state_field_option).option();
- if (option != STATE_OPTION_UNSET) {
- addAnnotationToAtomDecl(atomDecl, signature->size(), ANNOTATION_ID_STATE_OPTION,
- ANNOTATION_TYPE_INT, AnnotationValue(option));
- }
-
- if (option == STATE_OPTION_PRIMARY) {
- if (javaType == JAVA_TYPE_UNKNOWN ||
- javaType == JAVA_TYPE_ATTRIBUTION_CHAIN ||
- javaType == JAVA_TYPE_OBJECT || javaType == JAVA_TYPE_BYTE_ARRAY) {
- print_error(
- field,
- "Invalid primary state field: '%s'\n",
- atom->name().c_str());
- errorCount++;
- continue;
- }
- atomDecl->primaryFields.push_back(it->first);
-
- }
-
- if (option == STATE_OPTION_PRIMARY_FIELD_FIRST_UID) {
- if (javaType != JAVA_TYPE_ATTRIBUTION_CHAIN) {
- print_error(
- field,
- "PRIMARY_FIELD_FIRST_UID annotation is only for AttributionChains: '%s'\n",
- atom->name().c_str());
- errorCount++;
- continue;
- } else {
- atomDecl->primaryFields.push_back(FIRST_UID_IN_CHAIN_ID);
- }
- }
-
- if (option == STATE_OPTION_EXCLUSIVE) {
- if (javaType == JAVA_TYPE_UNKNOWN ||
- javaType == JAVA_TYPE_ATTRIBUTION_CHAIN ||
- javaType == JAVA_TYPE_OBJECT || javaType == JAVA_TYPE_BYTE_ARRAY) {
- print_error(
- field,
- "Invalid exclusive state field: '%s'\n",
- atom->name().c_str());
- errorCount++;
- continue;
- }
-
- if (atomDecl->exclusiveField == 0) {
- atomDecl->exclusiveField = it->first;
- } else {
- print_error(
- field,
- "Cannot have more than one exclusive state field in an atom: '%s'\n",
- atom->name().c_str());
- errorCount++;
- continue;
- }
-
- if (field->options()
- .GetExtension(os::statsd::state_field_option)
- .has_default_state_value()) {
- const int defaultState =
- field->options().GetExtension(os::statsd::state_field_option)
- .default_state_value();
- atomDecl->defaultState = defaultState;
-
- addAnnotationToAtomDecl(atomDecl, signature->size(), ANNOTATION_ID_DEFAULT_STATE,
- ANNOTATION_TYPE_INT, AnnotationValue(defaultState));
- }
-
- if (field->options().GetExtension(os::statsd::state_field_option)
- .has_reset_state_value()) {
- const int resetState = field->options()
- .GetExtension(os::statsd::state_field_option)
- .reset_state_value();
-
- atomDecl->resetState = resetState;
- addAnnotationToAtomDecl(atomDecl, signature->size(), ANNOTATION_ID_RESET_STATE,
- ANNOTATION_TYPE_INT, AnnotationValue(resetState));
- }
-
- if (field->options().GetExtension(os::statsd::state_field_option)
- .has_nested()) {
- const bool nested =
- field->options().GetExtension(os::statsd::state_field_option).nested();
- atomDecl->nested = nested;
-
- addAnnotationToAtomDecl(atomDecl, signature->size(), ANNOTATION_ID_STATE_NESTED,
- ANNOTATION_TYPE_BOOL, AnnotationValue(nested));
- }
- }
-
- }
- if (field->options().GetExtension(os::statsd::is_uid) == true) {
- if (javaType != JAVA_TYPE_INT) {
- print_error(
- field,
- "is_uid annotation can only be applied to int32 fields: '%s'\n",
- atom->name().c_str());
- errorCount++;
- continue;
- }
-
- if (atomDecl->uidField == 0) {
- atomDecl->uidField = it->first;
-
- addAnnotationToAtomDecl(atomDecl, signature->size(), ANNOTATION_ID_IS_UID,
- ANNOTATION_TYPE_BOOL, AnnotationValue(true));
- } else {
- print_error(
- field,
- "Cannot have more than one field in an atom with is_uid annotation: '%s'\n",
- atom->name().c_str());
- errorCount++;
- continue;
- }
- }
+ errorCount += collate_field_annotations(atomDecl, field, it->first, javaType);
}
return errorCount;
@@ -537,6 +545,18 @@
if (atomField->options().GetExtension(os::statsd::allow_from_any_uid) == true) {
atomDecl.whitelisted = true;
+ if (dbg) {
+ printf("%s is whitelisted\n", atomField->name().c_str());
+ }
+ }
+
+ if (atomDecl.code < PULL_ATOM_START_ID
+ && atomField->options().GetExtension(os::statsd::truncate_timestamp)) {
+ addAnnotationToAtomDecl(&atomDecl, ATOM_ID_FIELD_NUMBER, ANNOTATION_ID_TRUNCATE_TIMESTAMP,
+ ANNOTATION_TYPE_BOOL, AnnotationValue(true));
+ if (dbg) {
+ printf("%s can have timestamp truncated\n", atomField->name().c_str());
+ }
}
vector<java_type_t> signature;
diff --git a/tools/stats_log_api_gen/Collation.h b/tools/stats_log_api_gen/Collation.h
index c6dad1d..be5966c 100644
--- a/tools/stats_log_api_gen/Collation.h
+++ b/tools/stats_log_api_gen/Collation.h
@@ -52,6 +52,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 string DEFAULT_MODULE_NAME = "DEFAULT";
/**
@@ -147,6 +149,8 @@
bool whitelisted = false;
+ bool truncateTimestamp = false;
+
AtomDecl();
AtomDecl(const AtomDecl& that);
AtomDecl(int code, const string& name, const string& message);
diff --git a/tools/stats_log_api_gen/java_writer.cpp b/tools/stats_log_api_gen/java_writer.cpp
index 18508d2..1a7efba 100644
--- a/tools/stats_log_api_gen/java_writer.cpp
+++ b/tools/stats_log_api_gen/java_writer.cpp
@@ -121,6 +121,7 @@
// Write atom code.
fprintf(out, "%s builder.setAtomId(code);\n", indent.c_str());
+ write_annotations(out, ATOM_ID_FIELD_NUMBER, fieldNumberToAnnotations);
// Write the args.
argIndex = 1;
diff --git a/tools/stats_log_api_gen/native_writer.cpp b/tools/stats_log_api_gen/native_writer.cpp
index 90dcae4..b171f0e 100644
--- a/tools/stats_log_api_gen/native_writer.cpp
+++ b/tools/stats_log_api_gen/native_writer.cpp
@@ -82,6 +82,7 @@
if (supportQ) {
fprintf(out, " StatsEventCompat event;\n");
fprintf(out, " event.setAtomId(code);\n");
+ write_annotations(out, ATOM_ID_FIELD_NUMBER, fieldNumberToAnnotations, "event.", "");
for (vector<java_type_t>::const_iterator arg = signature.begin();
arg != signature.end(); arg++) {
switch (*arg) {
@@ -124,6 +125,8 @@
} else {
fprintf(out, " AStatsEvent* event = AStatsEvent_obtain();\n");
fprintf(out, " AStatsEvent_setAtomId(event, code);\n");
+ write_annotations(out, ATOM_ID_FIELD_NUMBER, fieldNumberToAnnotations, "AStatsEvent_",
+ "event, ");
for (vector<java_type_t>::const_iterator arg = signature.begin();
arg != signature.end(); arg++) {
switch (*arg) {