Merge "Support to enable profiling dynamically."
diff --git a/Annotation.cpp b/Annotation.cpp
index d3b4d01..1205079 100644
--- a/Annotation.cpp
+++ b/Annotation.cpp
@@ -16,6 +16,7 @@
 
 #include "Annotation.h"
 
+#include <android-base/logging.h>
 #include <hidl-util/Formatter.h>
 #include <vector>
 
@@ -43,6 +44,36 @@
     return mValues;
 }
 
+const std::string &AnnotationParam::getSingleValue() const {
+    CHECK_EQ(mValues->size(), 1u) << mName << " requires one values but has multiple";
+    return mValues->at(0);
+}
+
+std::string AnnotationParam::getSingleString() const {
+    std::string value = getSingleValue();
+
+    CHECK(value.size() >= 2 && value[0] == '"' && value[value.size() - 1] == '"')
+        << mName << " must be a string";
+
+    // unquote string
+    value = value.substr(1, value.size() - 2);
+
+    return value;
+}
+
+bool AnnotationParam::getSingleBool() const {
+    std::string value = getSingleString();
+
+    if (value == "true") {
+        return true;
+    } else if (value == "false") {
+        return false;
+    }
+
+    CHECK(false) << mName << " must be of boolean value (true/false).";
+    return false;
+}
+
 Annotation::Annotation(const char *name,AnnotationParamVector *params)
         : mName(name),
           mParams(params) {
diff --git a/Annotation.h b/Annotation.h
index 063b8e4..18d9ab0 100644
--- a/Annotation.h
+++ b/Annotation.h
@@ -37,6 +37,14 @@
     const std::string &getName() const;
     const std::vector<std::string> *getValues() const;
 
+    const std::string &getSingleValue() const;
+
+    /* Returns unquoted version of getSingleValue */
+    std::string getSingleString() const;
+
+    /* Returns value interpretted as a boolean */
+    bool getSingleBool() const;
+
 private:
     const std::string mName;
     std::vector<std::string> *mValues;
diff --git a/CompoundType.cpp b/CompoundType.cpp
index 6527f86..19abea4 100644
--- a/CompoundType.cpp
+++ b/CompoundType.cpp
@@ -355,15 +355,71 @@
 
     Scope::emitTypeDeclarations(out);
 
-    for (const auto &field : *mFields) {
-        out << field->type().getCppStackType()
-            << " "
-            << field->name()
-            << ";\n";
+    if (!isJavaCompatible()) {
+        for (const auto &field : *mFields) {
+            out << field->type().getCppStackType()
+                << " "
+                << field->name()
+                << ";\n";
+        }
+
+        out.unindent();
+        out << "};\n\n";
+
+        return OK;
     }
 
-    out.unindent();
-    out << "};\n\n";
+    for (int pass = 0; pass < 2; ++pass) {
+        size_t offset = 0;
+        for (const auto &field : *mFields) {
+            size_t fieldAlign, fieldSize;
+            field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
+
+            size_t pad = offset % fieldAlign;
+            if (pad > 0) {
+                offset += fieldAlign - pad;
+            }
+
+            if (pass == 0) {
+                out << field->type().getCppStackType()
+                    << " "
+                    << field->name()
+                    << " __attribute__ ((aligned("
+                    << fieldAlign
+                    << ")));\n";
+            } else {
+                out << "static_assert(offsetof("
+                    << fullName()
+                    << ", "
+                    << field->name()
+                    << ") == "
+                    << offset
+                    << ", \"wrong offset\");\n";
+            }
+
+            offset += fieldSize;
+        }
+
+        if (pass == 0) {
+            out.unindent();
+            out << "};\n\n";
+        }
+    }
+
+    size_t structAlign, structSize;
+    getAlignmentAndSize(&structAlign, &structSize);
+
+    out << "static_assert(sizeof("
+        << fullName()
+        << ") == "
+        << structSize
+        << ", \"wrong size\");\n";
+
+    out << "static_assert(__alignof("
+        << fullName()
+        << ") == "
+        << structAlign
+        << ", \"wrong alignment\");\n\n";
 
     return OK;
 }
@@ -973,6 +1029,11 @@
     }
 
     *size = offset;
+
+    if (*size == 0) {
+        // An empty struct still occupies a byte of space in C++.
+        *size = 1;
+    }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/EnumType.cpp b/EnumType.cpp
index 0f0542a..6ce8010 100644
--- a/EnumType.cpp
+++ b/EnumType.cpp
@@ -406,33 +406,37 @@
 
     const AnnotationParam *nameParam = annotation->getParam("name");
     if (nameParam != nullptr) {
-        CHECK_EQ(nameParam->getValues()->size(), 1u);
+        name = nameParam->getSingleString();
+    }
 
-        std::string quotedString = nameParam->getValues()->at(0);
-        name = quotedString.substr(1, quotedString.size() - 2);
+    bool exportParent = true;
+    const AnnotationParam *exportParentParam = annotation->getParam("export_parent");
+    if (exportParentParam != nullptr) {
+        exportParent = exportParentParam->getSingleBool();
     }
 
     std::string valuePrefix;
     const AnnotationParam *prefixParam = annotation->getParam("value_prefix");
     if (prefixParam != nullptr) {
-        CHECK_EQ(prefixParam->getValues()->size(), 1u);
-
-        std::string quotedString = prefixParam->getValues()->at(0);
-        valuePrefix = quotedString.substr(1, quotedString.size() - 2);
+        valuePrefix = prefixParam->getSingleString();
     }
 
     std::string valueSuffix;
     const AnnotationParam *suffixParam = annotation->getParam("value_suffix");
     if (suffixParam != nullptr) {
-        CHECK_EQ(suffixParam->getValues()->size(), 1u);
-
-        std::string quotedString = suffixParam->getValues()->at(0);
-        valueSuffix = quotedString.substr(1, quotedString.size() - 2);
+        valueSuffix = suffixParam->getSingleString();
     }
 
     const ScalarType *scalarType = mStorageType->resolveToScalarType();
     CHECK(scalarType != nullptr);
 
+    std::vector<const EnumType *> chain;
+    if (exportParent) {
+        getTypeChain(&chain);
+    } else {
+        chain = { this };
+    }
+
     if (forJava) {
         if (!name.empty()) {
             out << "public final class "
@@ -447,9 +451,6 @@
         const std::string typeName =
             scalarType->getJavaType(false /* forInitializer */);
 
-        std::vector<const EnumType *> chain;
-        getTypeChain(&chain);
-
         for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
             const auto &type = *it;
 
@@ -495,9 +496,6 @@
 
     out.indent();
 
-    std::vector<const EnumType *> chain;
-    getTypeChain(&chain);
-
     for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
         const auto &type = *it;
 
diff --git a/test/vendor/1.0/Android.bp b/test/vendor/1.0/Android.bp
index 7f3aa3e..869b03a 100644
--- a/test/vendor/1.0/Android.bp
+++ b/test/vendor/1.0/Android.bp
@@ -5,9 +5,11 @@
     tools: ["hidl-gen"],
     cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -rtests:system/tools/hidl/test/ -randroid.hidl:system/libhidl/transport tests.vendor@1.0",
     srcs: [
+        "types.hal",
         "IVendor.hal",
     ],
     out: [
+        "tests/vendor/1.0/types.cpp",
         "tests/vendor/1.0/VendorAll.cpp",
     ],
 }
@@ -17,9 +19,11 @@
     tools: ["hidl-gen"],
     cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -rtests:system/tools/hidl/test/ -randroid.hidl:system/libhidl/transport tests.vendor@1.0",
     srcs: [
+        "types.hal",
         "IVendor.hal",
     ],
     out: [
+        "tests/vendor/1.0/types.h",
         "tests/vendor/1.0/IVendor.h",
         "tests/vendor/1.0/IHwVendor.h",
         "tests/vendor/1.0/BnVendor.h",
diff --git a/test/vendor/1.0/Android.mk b/test/vendor/1.0/Android.mk
new file mode 100644
index 0000000..ee341d4
--- /dev/null
+++ b/test/vendor/1.0/Android.mk
@@ -0,0 +1,40 @@
+# This file is autogenerated by hidl-gen. Do not edit manually.
+
+LOCAL_PATH := $(call my-dir)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := tests.vendor@1.0-java-constants
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+#
+GEN := $(intermediates)/tests/vendor/V1_0/Constants.java
+$(GEN): $(HIDL)
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/IVendor.hal
+
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava-constants \
+        -rtests:system/tools/hidl/test/ \
+        -randroid.hidl:system/libhidl/transport \
+        tests.vendor@1.0
+
+$(GEN):
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+# Avoid dependency cycle of framework.jar -> this-library -> framework.jar
+LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_JAVA_LIBRARIES := core-oj
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/test/vendor/1.0/types.hal b/test/vendor/1.0/types.hal
new file mode 100644
index 0000000..511389e
--- /dev/null
+++ b/test/vendor/1.0/types.hal
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.vendor@1.0;
+
+enum Bar : uint32_t {
+    A
+};
+
+/* WARNING:
+ *
+ * @export is used to expose this enumeration in a C header using -Lexport-header.
+ *
+ * It should only be used to make a backwards compatible header definition so that
+ * constant values defined in a .hal file can be used in a C library.
+ *
+ * export_parent below is used to test the functionality of export_parent. Typically,
+ * you would only use it when inheriting from a parent type. Obviously if name is not empty,
+ * then export_parent isn't required.
+ */
+@export(name="") // export_parent is implicitly true
+enum Foo : Bar {
+    B,
+    C
+};
+
+@export(name="", export_parent="false")
+enum FooToo : Foo {
+    D
+};
\ No newline at end of file
diff --git a/test/vendor/1.0/update-base.sh b/test/vendor/1.0/update-base.sh
new file mode 100755
index 0000000..8c7d688
--- /dev/null
+++ b/test/vendor/1.0/update-base.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+
+# WARNING: vendor-base is placed here only for testing.
+# It should typically be created elsewhere.
+
+options="-Lexport-header \
+         -r tests:system/tools/hidl/test/\
+         -r android.hidl:system/libhidl/transport"
+
+hidl-gen $options \
+         -o system/tools/hidl/test/vendor/1.0/vendor-base.h \
+         tests.vendor@1.0
\ No newline at end of file
diff --git a/test/vendor/1.0/vendor-base.h b/test/vendor/1.0/vendor-base.h
new file mode 100644
index 0000000..b9775f4
--- /dev/null
+++ b/test/vendor/1.0/vendor-base.h
@@ -0,0 +1,25 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+// Source: tests.vendor@1.0
+
+#ifndef HIDL_GENERATED_TESTS_VENDOR_V1_0_EXPORTED_CONSTANTS_H_
+#define HIDL_GENERATED_TESTS_VENDOR_V1_0_EXPORTED_CONSTANTS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+    A = 0u, // 0
+    B = 1u, // 1
+    C = 2u, // 2
+};
+
+enum {
+    D = 3u, // 3
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // HIDL_GENERATED_TESTS_VENDOR_V1_0_EXPORTED_CONSTANTS_H_