Allow default state, reset state, and nesting for binary states

Every state atom can have a customized default state and reset state by
annotating atoms.proto.

Binary state atoms (such as WakelockStateChanged)  can turn on nested
counting by annotating atoms.proto as well.

Generated atoms_info.h before change: https://paste.googleplex.com/4626190063108096
Generated atoms_info.h after change: https://paste.googleplex.com/5410938863747072
Generated atoms_info.cpp before change: https://paste.googleplex.com/5726061016907776
Generated atoms_info.cpp after change: https://paste.googleplex.com/5540983737417728

Test: bit statsd_test:*
Change-Id: I845616f103e013a7927de869b8e8228cfb244090
diff --git a/stats/stats_log_api_gen/Collation.cpp b/stats/stats_log_api_gen/Collation.cpp
index 7bbac13..e104e4e 100644
--- a/stats/stats_log_api_gen/Collation.cpp
+++ b/stats/stats_log_api_gen/Collation.cpp
@@ -40,18 +40,21 @@
 {
 }
 
-AtomDecl::AtomDecl(const AtomDecl& that)
-    : code(that.code),
-      name(that.name),
-      message(that.message),
-      fields(that.fields),
-      primaryFields(that.primaryFields),
-      exclusiveField(that.exclusiveField),
-      uidField(that.uidField),
-      whitelisted(that.whitelisted),
-      binaryFields(that.binaryFields),
-      hasModule(that.hasModule),
-      moduleName(that.moduleName) {}
+AtomDecl::AtomDecl(const AtomDecl &that)
+      : code(that.code),
+        name(that.name),
+        message(that.message),
+        fields(that.fields),
+        primaryFields(that.primaryFields),
+        exclusiveField(that.exclusiveField),
+        defaultState(that.defaultState),
+        resetState(that.resetState),
+        nested(that.nested),
+        uidField(that.uidField),
+        whitelisted(that.whitelisted),
+        binaryFields(that.binaryFields),
+        hasModule(that.hasModule),
+        moduleName(that.moduleName) {}
 
 AtomDecl::AtomDecl(int c, const string& n, const string& m)
     :code(c),
@@ -281,7 +284,7 @@
     atomDecl->fields.push_back(atField);
 
     if (field->options().GetExtension(os::statsd::state_field_option).option() ==
-        os::statsd::StateField::PRIMARY) {
+        os::statsd::StateField::PRIMARY_FIELD) {
         if (javaType == JAVA_TYPE_UNKNOWN ||
             javaType == JAVA_TYPE_ATTRIBUTION_CHAIN ||
             javaType == JAVA_TYPE_OBJECT || javaType == JAVA_TYPE_BYTE_ARRAY) {
@@ -300,7 +303,7 @@
     }
 
     if (field->options().GetExtension(os::statsd::state_field_option).option() ==
-        os::statsd::StateField::EXCLUSIVE) {
+        os::statsd::StateField::EXCLUSIVE_STATE) {
         if (javaType == JAVA_TYPE_UNKNOWN ||
             javaType == JAVA_TYPE_ATTRIBUTION_CHAIN ||
             javaType == JAVA_TYPE_OBJECT || javaType == JAVA_TYPE_BYTE_ARRAY) {
@@ -312,6 +315,21 @@
         } else {
             errorCount++;
         }
+
+        if (field->options()
+                    .GetExtension(os::statsd::state_field_option)
+                    .has_default_state_value()) {
+            atomDecl->defaultState = field->options()
+                                             .GetExtension(os::statsd::state_field_option)
+                                             .default_state_value();
+        }
+
+        if (field->options().GetExtension(os::statsd::state_field_option).has_reset_state_value()) {
+            atomDecl->resetState = field->options()
+                                           .GetExtension(os::statsd::state_field_option)
+                                           .reset_state_value();
+        }
+        atomDecl->nested = field->options().GetExtension(os::statsd::state_field_option).nested();
     }
 
     if (field->options().GetExtension(os::statsd::is_uid) == true) {
diff --git a/stats/stats_log_api_gen/Collation.h b/stats/stats_log_api_gen/Collation.h
index 87d4d5d..65d8e3e 100644
--- a/stats/stats_log_api_gen/Collation.h
+++ b/stats/stats_log_api_gen/Collation.h
@@ -88,6 +88,9 @@
 
     vector<int> primaryFields;
     int exclusiveField = 0;
+    int defaultState = INT_MAX;
+    int resetState = INT_MAX;
+    bool nested;
 
     int uidField = 0;
 
diff --git a/stats/stats_log_api_gen/atoms_info_writer.cpp b/stats/stats_log_api_gen/atoms_info_writer.cpp
index 66ae964..984c929 100644
--- a/stats/stats_log_api_gen/atoms_info_writer.cpp
+++ b/stats/stats_log_api_gen/atoms_info_writer.cpp
@@ -25,11 +25,15 @@
 namespace stats_log_api_gen {
 
 static void write_atoms_info_header_body(FILE* out, const Atoms& atoms) {
+    fprintf(out, "static int UNSET_VALUE = INT_MAX;\n");
     fprintf(out, "static int FIRST_UID_IN_CHAIN = 0;\n");
 
     fprintf(out, "struct StateAtomFieldOptions {\n");
     fprintf(out, "  std::vector<int> primaryFields;\n");
     fprintf(out, "  int exclusiveField;\n");
+    fprintf(out, "  int defaultState = UNSET_VALUE;\n");
+    fprintf(out, "  int resetState = UNSET_VALUE;\n");
+    fprintf(out, "  bool nested;\n");
     fprintf(out, "};\n");
     fprintf(out, "\n");
 
@@ -126,7 +130,7 @@
             "static std::map<int, StateAtomFieldOptions> "
             "getStateAtomFieldOptions() {\n");
     fprintf(out, "    std::map<int, StateAtomFieldOptions> options;\n");
-    fprintf(out, "    StateAtomFieldOptions opt;\n");
+    fprintf(out, "    StateAtomFieldOptions* opt;\n");
     for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
          atom != atoms.decls.end(); atom++) {
         if (atom->primaryFields.size() == 0 && atom->exclusiveField == 0) {
@@ -136,14 +140,26 @@
                 "\n    // Adding primary and exclusive fields for atom "
                 "(%d)%s\n",
                 atom->code, atom->name.c_str());
-        fprintf(out, "    opt.primaryFields.clear();\n");
+        fprintf(out, "    opt = &(options[static_cast<int>(%s)]);\n",
+                make_constant_name(atom->name).c_str());
+        fprintf(out, "    opt->primaryFields.reserve(%lu);\n", atom->primaryFields.size());
         for (const auto& field : atom->primaryFields) {
-            fprintf(out, "    opt.primaryFields.push_back(%d);\n", field);
+            fprintf(out, "    opt->primaryFields.push_back(%d);\n", field);
         }
 
-        fprintf(out, "    opt.exclusiveField = %d;\n", atom->exclusiveField);
-        fprintf(out, "    options[static_cast<int>(%s)] = opt;\n",
-                make_constant_name(atom->name).c_str());
+        fprintf(out, "    opt->exclusiveField = %d;\n", atom->exclusiveField);
+        if (atom->defaultState != INT_MAX) {
+            fprintf(out, "    opt->defaultState = %d;\n", atom->defaultState);
+        } else {
+            fprintf(out, "    opt->defaultState = UNSET_VALUE;\n");
+        }
+
+        if (atom->resetState != INT_MAX) {
+            fprintf(out, "    opt->resetState = %d;\n", atom->resetState);
+        } else {
+            fprintf(out, "    opt->resetState = UNSET_VALUE;\n");
+        }
+        fprintf(out, "    opt->nested = %d;\n", atom->nested);
     }
 
     fprintf(out, "    return options;\n");
diff --git a/stats/stats_log_api_gen/test.proto b/stats/stats_log_api_gen/test.proto
index c9a4763..b892194 100644
--- a/stats/stats_log_api_gen/test.proto
+++ b/stats/stats_log_api_gen/test.proto
@@ -148,53 +148,42 @@
 
 // The atom has only primary field but no exclusive state field.
 message BadStateAtom1 {
-    optional int32 uid = 1
-            [(android.os.statsd.state_field_option).option = PRIMARY];
+    optional int32 uid = 1 [(android.os.statsd.state_field_option).option = PRIMARY_FIELD];
 }
 
 // Only primative types can be annotated.
 message BadStateAtom2 {
     repeated android.os.statsd.AttributionNode attribution = 1
-            [(android.os.statsd.state_field_option).option = PRIMARY];
-    optional int32 state = 2
-            [(android.os.statsd.state_field_option).option = EXCLUSIVE];
+            [(android.os.statsd.state_field_option).option = PRIMARY_FIELD];
+    optional int32 state = 2 [(android.os.statsd.state_field_option).option = EXCLUSIVE_STATE];
 }
 
 // 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.
 message BadStateAtom3 {
-    optional int32 uid = 1
-            [(android.os.statsd.state_field_option).option = PRIMARY];
-    optional int32 state = 2
-            [(android.os.statsd.state_field_option).option = EXCLUSIVE];
-    optional int32 state2 = 3
-            [(android.os.statsd.state_field_option).option = EXCLUSIVE];
+    optional int32 uid = 1 [(android.os.statsd.state_field_option).option = PRIMARY_FIELD];
+    optional int32 state = 2 [(android.os.statsd.state_field_option).option = EXCLUSIVE_STATE];
+    optional int32 state2 = 3 [(android.os.statsd.state_field_option).option = EXCLUSIVE_STATE];
 }
 
 message GoodStateAtom1 {
-    optional int32 uid = 1
-            [(android.os.statsd.state_field_option).option = PRIMARY];
-    optional int32 state = 2
-            [(android.os.statsd.state_field_option).option = EXCLUSIVE];
+    optional int32 uid = 1 [(android.os.statsd.state_field_option).option = PRIMARY_FIELD];
+    optional int32 state = 2 [(android.os.statsd.state_field_option).option = EXCLUSIVE_STATE];
 }
 
 // Atoms can have exclusive state field, but no primary field. That means
 // the state is globally exclusive (e.g., DisplayState).
 message GoodStateAtom2 {
     optional int32 uid = 1;
-    optional int32 state = 2
-            [(android.os.statsd.state_field_option).option = EXCLUSIVE];
+    optional int32 state = 2 [(android.os.statsd.state_field_option).option = EXCLUSIVE_STATE];
 }
 
 // We can have more than one primary fields. That means their combination is a
 // primary key.
 message GoodStateAtom3 {
-    optional int32 uid = 1
-            [(android.os.statsd.state_field_option).option = PRIMARY];
-    optional int32 tid = 2
-            [(android.os.statsd.state_field_option).option = PRIMARY];
-    optional int32 state = 3
-            [(android.os.statsd.state_field_option).option = EXCLUSIVE];
+    optional int32 uid = 1 [(android.os.statsd.state_field_option).option = PRIMARY_FIELD];
+    optional int32 tid = 2 [(android.os.statsd.state_field_option).option = PRIMARY_FIELD];
+    optional int32 state = 3 [(android.os.statsd.state_field_option).option = EXCLUSIVE_STATE];
 }
 
 message WhitelistedAtom {