Merge changes from topics "add-gc-type-in-art-metrics", "art-value-metrics-as-deltas", "report-uffd-minor-fault"

* changes:
  Add field for uffd/minor fault support in ArtDatum{Delta}Reported
  Add ArtGcCollectorType enum in ArtDatumReported/ArtDatumDeltaReported
  Create a new ArtDatumDeltaReported atom to report ART value metrics
diff --git a/stats/atoms/placeholder/placeholder_atoms.proto b/stats/atoms/placeholder/placeholder_extension_atoms.proto
similarity index 100%
rename from stats/atoms/placeholder/placeholder_atoms.proto
rename to stats/atoms/placeholder/placeholder_extension_atoms.proto
diff --git a/stats/stats_log_api_gen/Collation.cpp b/stats/stats_log_api_gen/Collation.cpp
index 99d21e4..f69eaaa 100644
--- a/stats/stats_log_api_gen/Collation.cpp
+++ b/stats/stats_log_api_gen/Collation.cpp
@@ -371,6 +371,7 @@
         AtomField atField(field->name(), javaType);
 
         if (javaType == JAVA_TYPE_ENUM || javaType == JAVA_TYPE_ENUM_ARRAY) {
+            atField.enumTypeName = field->enum_type()->name();
             // All enums are treated as ints when it comes to function signatures.
             collate_enums(*field->enum_type(), &atField);
         }
diff --git a/stats/stats_log_api_gen/Collation.h b/stats/stats_log_api_gen/Collation.h
index cd8fea4..d4b30ab 100644
--- a/stats/stats_log_api_gen/Collation.h
+++ b/stats/stats_log_api_gen/Collation.h
@@ -148,11 +148,16 @@
     // If the field is of type enum, the following map contains the list of enum
     // values.
     map<int /* numeric value */, string /* value name */> enumValues;
+    // If the field is of type enum, the following field contains enum type name
+    string enumTypeName;
 
     inline AtomField() : name(), javaType(JAVA_TYPE_UNKNOWN_OR_INVALID) {
     }
     inline AtomField(const AtomField& that)
-        : name(that.name), javaType(that.javaType), enumValues(that.enumValues) {
+        : name(that.name),
+          javaType(that.javaType),
+          enumValues(that.enumValues),
+          enumTypeName(that.enumTypeName) {
     }
 
     inline AtomField(string n, java_type_t jt) : name(n), javaType(jt) {
diff --git a/stats/stats_log_api_gen/native_writer.cpp b/stats/stats_log_api_gen/native_writer.cpp
index ec525f8..26571e3 100644
--- a/stats/stats_log_api_gen/native_writer.cpp
+++ b/stats/stats_log_api_gen/native_writer.cpp
@@ -575,7 +575,39 @@
                                   const string& cppNamespace) {
     write_stats_log_header_preamble(out, cppNamespace, false);
     write_native_atom_constants(out, atoms, attributionDecl);
-    write_native_atom_enums(out, atoms);
+
+    for (AtomDeclSet::const_iterator atomIt = atoms.decls.begin(); atomIt != atoms.decls.end();
+         atomIt++) {
+        fprintf(out, "class %s final {\n", (*atomIt)->message.c_str());
+        fprintf(out, "public:\n\n");
+
+        set<string> processedEnums;
+        for (vector<AtomField>::const_iterator field = (*atomIt)->fields.begin();
+             field != (*atomIt)->fields.end(); field++) {
+            // there might be N fields with the same enum type
+            // avoid duplication definitions
+            if (processedEnums.find(field->enumTypeName) != processedEnums.end()) {
+                continue;
+            }
+            processedEnums.insert(field->enumTypeName);
+            if (field->javaType == JAVA_TYPE_ENUM || field->javaType == JAVA_TYPE_ENUM_ARRAY) {
+                fprintf(out, "enum %s {\n", field->enumTypeName.c_str());
+                size_t i = 0;
+                for (map<int, string>::const_iterator value = field->enumValues.begin();
+                     value != field->enumValues.end(); value++) {
+                    fprintf(out, "    %s = %d", make_constant_name(value->second).c_str(),
+                            value->first);
+                    char const* const comma = (i == field->enumValues.size() - 1) ? "" : ",";
+                    fprintf(out, "%s\n", comma);
+                    i++;
+                }
+                fprintf(out, "};\n");
+            }
+        }
+
+        fprintf(out, "};\n\n");
+    }
+
     write_stats_log_header_epilogue(out, cppNamespace);
 
     return 0;
diff --git a/stats/stats_log_api_gen/test_api_gen_vendor.cpp b/stats/stats_log_api_gen/test_api_gen_vendor.cpp
index 9a16a2b..68f20c7 100644
--- a/stats/stats_log_api_gen/test_api_gen_vendor.cpp
+++ b/stats/stats_log_api_gen/test_api_gen_vendor.cpp
@@ -34,11 +34,41 @@
 /**
  * Tests native auto generated code for specific vendor atom contains proper enums
  */
-TEST(ApiGenVendorAtomTest, AtomEnumsConstantsTest) {
-    EXPECT_EQ(VENDOR_ATOM1__TYPE__VENDOR_ATOM1_TYPE_UNKNOWN, 0);
-    EXPECT_EQ(VENDOR_ATOM1__TYPE__VENDOR_ATOM1_TYPE_1, 1);
-    EXPECT_EQ(VENDOR_ATOM1__TYPE__VENDOR_ATOM1_TYPE_2, 2);
-    EXPECT_EQ(VENDOR_ATOM1__TYPE__VENDOR_ATOM1_TYPE_3, 3);
+TEST(ApiGenVendorAtomTest, AtomEnumTest) {
+    EXPECT_EQ(VendorAtom1::TYPE_UNKNOWN, 0);
+    EXPECT_EQ(VendorAtom1::TYPE_1, 1);
+    EXPECT_EQ(VendorAtom1::TYPE_2, 2);
+    EXPECT_EQ(VendorAtom1::TYPE_3, 3);
+
+    EXPECT_EQ(VendorAtom1::ANOTHER_TYPE_UNKNOWN, 0);
+    EXPECT_EQ(VendorAtom1::ANOTHER_TYPE_1, 1);
+    EXPECT_EQ(VendorAtom1::ANOTHER_TYPE_2, 2);
+    EXPECT_EQ(VendorAtom1::ANOTHER_TYPE_3, 3);
+
+    EXPECT_EQ(VendorAtom2::TYPE_UNKNOWN, 0);
+    EXPECT_EQ(VendorAtom2::TYPE_1, 1);
+    EXPECT_EQ(VendorAtom2::TYPE_2, 2);
+    EXPECT_EQ(VendorAtom2::TYPE_3, 3);
+
+    EXPECT_EQ(VendorAtom2::ANOTHER_TYPE_UNKNOWN, 0);
+    EXPECT_EQ(VendorAtom2::ANOTHER_TYPE_1, 1);
+    EXPECT_EQ(VendorAtom2::ANOTHER_TYPE_2, 2);
+    EXPECT_EQ(VendorAtom2::ANOTHER_TYPE_3, 3);
+
+    typedef void (*Atom1FuncWithEnum)(VendorAtom1::EnumType arg);
+    typedef void (*Atom1FuncWithEnum2)(VendorAtom1::EnumType2 arg);
+    typedef void (*Atom2FuncWithEnum)(VendorAtom2::EnumType arg);
+    typedef void (*Atom2FuncWithEnum2)(VendorAtom2::EnumType2 arg);
+
+    Atom1FuncWithEnum f1 = nullptr;
+    Atom1FuncWithEnum2 f2 = nullptr;
+    Atom2FuncWithEnum f3 = nullptr;
+    Atom2FuncWithEnum2 f4 = nullptr;
+
+    EXPECT_EQ(f1, nullptr);
+    EXPECT_EQ(f2, nullptr);
+    EXPECT_EQ(f3, nullptr);
+    EXPECT_EQ(f4, nullptr);
 }
 
 }  // namespace stats_log_api_gen
diff --git a/stats/stats_log_api_gen/test_vendor_atoms.proto b/stats/stats_log_api_gen/test_vendor_atoms.proto
index de12b55..733175c 100644
--- a/stats/stats_log_api_gen/test_vendor_atoms.proto
+++ b/stats/stats_log_api_gen/test_vendor_atoms.proto
@@ -26,21 +26,49 @@
 }
 
 message VendorAtom1 {
-    enum VendorAtom1Type {
-        VENDOR_ATOM1_TYPE_UNKNOWN = 0;
-        VENDOR_ATOM1_TYPE_1 = 1;
-        VENDOR_ATOM1_TYPE_2 = 2;
-        VENDOR_ATOM1_TYPE_3 = 3;
+    enum EnumType {
+        TYPE_UNKNOWN = 0;
+        TYPE_1 = 1;
+        TYPE_2 = 2;
+        TYPE_3 = 3;
     }
+
+    enum EnumType2 {
+        ANOTHER_TYPE_UNKNOWN = 0;
+        ANOTHER_TYPE_1 = 1;
+        ANOTHER_TYPE_2 = 2;
+        ANOTHER_TYPE_3 = 3;
+    }
+
     optional string reverse_domain_name = 1;
-    optional VendorAtom1Type type = 2;
-    optional int32 int_value32 = 3;
-    optional int64 int_value64 = 4;
-    optional float float_value = 5;
-    optional bool bool_value = 6;
+    optional EnumType enumField1 = 2;
+    optional EnumType enumField2 = 3;
+    optional int32 int_value32 = 4;
+    optional int64 int_value64 = 5;
+    optional float float_value = 6;
+    optional bool bool_value = 7;
+    optional EnumType2 enumField3 = 8;
+    optional EnumType2 enumField4 = 9;
 }
 
 message VendorAtom2 {
+    enum EnumType {
+        TYPE_UNKNOWN = 0;
+        TYPE_1 = 1;
+        TYPE_2 = 2;
+        TYPE_3 = 3;
+    }
+
+    enum EnumType2 {
+        ANOTHER_TYPE_UNKNOWN = 0;
+        ANOTHER_TYPE_1 = 1;
+        ANOTHER_TYPE_2 = 2;
+        ANOTHER_TYPE_3 = 3;
+    }
+
     optional string reverse_domain_name = 1;
-    optional int32 int_value = 2;
+    optional EnumType enumField1 = 2;
+    optional EnumType enumField2 = 3;
+    optional EnumType2 enumField3 = 4;
+    optional EnumType2 enumField4 = 5;
 }