Merge "hidl2aidl: add support for bitfields"
diff --git a/hidl2aidl/AidlTranslate.cpp b/hidl2aidl/AidlTranslate.cpp
index 13db08c..df38cf3 100644
--- a/hidl2aidl/AidlTranslate.cpp
+++ b/hidl2aidl/AidlTranslate.cpp
@@ -209,6 +209,9 @@
                                  AidlBackend backend) {
     if (type.isString()) {
         return wrapToString16(payload, backend);
+    } else if (type.isBitField()) {
+        return wrapStaticCast(payload, *static_cast<const BitFieldType&>(type).getElementEnumType(),
+                              fqName, backend);
     } else {
         return wrapStaticCast(payload, type, fqName, backend);
     }
@@ -312,13 +315,12 @@
 static void h2aFieldTranslation(Formatter& out, const std::set<const NamedType*>& namedTypes,
                                 const CompoundType* parent, const FieldWithVersion& field,
                                 AidlBackend backend) {
-    // TODO(b/158489355) Need to support and validate more types like arrays/vectors.
-    if (field.field->type().isNamedType()) {
+    if (field.field->type().isNamedType() && !field.field->type().isEnum()) {
         namedTypeTranslation(out, namedTypes, field, parent, backend);
     } else if (field.field->type().isArray() || field.field->type().isVector()) {
         containerTranslation(out, field, parent, backend);
     } else if (field.field->type().isEnum() || field.field->type().isScalar() ||
-               field.field->type().isString()) {
+               field.field->type().isString() || field.field->type().isBitField()) {
         simpleTranslation(out, field, parent, backend);
     } else {
         AidlHelper::notes() << "An unhandled type was found in translation: "
diff --git a/hidl2aidl/AidlType.cpp b/hidl2aidl/AidlType.cpp
index d3209cf..85c7c36 100644
--- a/hidl2aidl/AidlType.cpp
+++ b/hidl2aidl/AidlType.cpp
@@ -19,6 +19,7 @@
 
 #include "AidlHelper.h"
 #include "ArrayType.h"
+#include "EnumType.h"
 #include "FmqType.h"
 #include "NamedType.h"
 #include "Type.h"
@@ -83,6 +84,9 @@
         // enum type goes to the primitive java type in HIDL, but AIDL should use
         // the enum type name itself
         return type.definedName();
+    } else if (type.isBitField()) {
+        const BitFieldType& bitfield = static_cast<const BitFieldType&>(type);
+        return getAidlType(*bitfield.getElementType(), relativeTo);
     } else {
         return type.getJavaType();
     }
diff --git a/hidl2aidl/test/1.2/types.hal b/hidl2aidl/test/1.2/types.hal
index 12990b9..afa7d2f 100644
--- a/hidl2aidl/test/1.2/types.hal
+++ b/hidl2aidl/test/1.2/types.hal
@@ -33,6 +33,13 @@
     @1.1::OnlyIn11 c;
 };
 
+enum FooFlag : uint32_t {
+    NONE = 0x0,
+    FIRST = 0x1 << 0,
+    SECOND = 0x1 << 1,
+    THIRD = 0x1 << 2,
+};
+
 safe_union SafeUnionBar {
     Monostate noInit;
     int8_t a;
@@ -45,6 +52,8 @@
     string d;
     float e;
     double f;
+    bitfield<FooFlag> g;
+    @1.1::Value h;
 };
 
 struct ArrayFoo {
diff --git a/hidl2aidl/test/Android.bp b/hidl2aidl/test/Android.bp
index 696b7d3..193068e 100644
--- a/hidl2aidl/test/Android.bp
+++ b/hidl2aidl/test/Android.bp
@@ -42,6 +42,7 @@
     out: [
         "hidl2aidl/test/ArrayFoo.aidl",
         "hidl2aidl/test/VectorFoo.aidl",
+        "hidl2aidl/test/FooFlag.aidl",
         "hidl2aidl/test/IBar.aidl",
         "hidl2aidl/test/IBarInner.aidl",
         "hidl2aidl/test/IFoo.aidl",
diff --git a/hidl2aidl/test/TranslateJavaTest.java b/hidl2aidl/test/TranslateJavaTest.java
index 5ff8550..818a9af 100644
--- a/hidl2aidl/test/TranslateJavaTest.java
+++ b/hidl2aidl/test/TranslateJavaTest.java
@@ -193,6 +193,24 @@
     }
 
     @Test
+    public void SafeUnionBarBitfield() {
+        hidl2aidl.test.SafeUnionBar dest;
+        hidl2aidl.test.V1_2.SafeUnionBar source = new hidl2aidl.test.V1_2.SafeUnionBar();
+        source.g(hidl2aidl.test.V1_2.FooFlag.THIRD);
+        dest = Translate.h2aTranslate(source);
+        assertThat(source.g(), is(dest.getG()));
+    }
+
+    @Test
+    public void SafeUnionBarEnum() {
+        hidl2aidl.test.SafeUnionBar dest;
+        hidl2aidl.test.V1_2.SafeUnionBar source = new hidl2aidl.test.V1_2.SafeUnionBar();
+        source.h(hidl2aidl.test.V1_1.Value.B);
+        dest = Translate.h2aTranslate(source);
+        assertThat(source.h(), is(dest.getH()));
+    }
+
+    @Test
     public void ArrayFoo() {
         hidl2aidl.test.ArrayFoo dest;
         hidl2aidl.test.V1_2.ArrayFoo source = new hidl2aidl.test.V1_2.ArrayFoo();
diff --git a/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/FooFlag.aidl b/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/FooFlag.aidl
new file mode 100644
index 0000000..8370ba5
--- /dev/null
+++ b/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/FooFlag.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package hidl2aidl.test;
+@Backing(type="int") @VintfStability
+enum FooFlag {
+  NONE = 0,
+  FIRST = 1,
+  SECOND = 2,
+  THIRD = 4,
+}
diff --git a/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/SafeUnionBar.aidl b/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/SafeUnionBar.aidl
index 2a2c929..a9b28af 100644
--- a/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/SafeUnionBar.aidl
+++ b/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/SafeUnionBar.aidl
@@ -26,4 +26,6 @@
   String d;
   float e;
   double f;
+  hidl2aidl.test.FooFlag g;
+  hidl2aidl.test.Value h;
 }
diff --git a/hidl2aidl/test/translate_cpp_test.cpp b/hidl2aidl/test/translate_cpp_test.cpp
index 0d94c29..9ffc40b 100644
--- a/hidl2aidl/test/translate_cpp_test.cpp
+++ b/hidl2aidl/test/translate_cpp_test.cpp
@@ -167,6 +167,26 @@
     EXPECT_EQ(source.f(), dest.get<hidl2aidl::test::SafeUnionBar::f>());
 }
 
+TEST_F(Hidl2aidlTranslateTest, SafeUnionBarBitfield) {
+    hidl2aidl::test::SafeUnionBar dest;
+    hidl2aidl::test::V1_2::SafeUnionBar source;
+    ::android::hardware::hidl_bitfield<::hidl2aidl::test::V1_2::FooFlag> bits(0);
+    bits |= hidl2aidl::test::V1_2::FooFlag::THIRD;
+    source.g(bits);
+    ASSERT_TRUE(h2a::translate(source, &dest));
+    EXPECT_EQ(static_cast<hidl2aidl::test::FooFlag>(source.g()),
+              dest.get<hidl2aidl::test::SafeUnionBar::g>());
+}
+
+TEST_F(Hidl2aidlTranslateTest, SafeUnionBarEnum) {
+    hidl2aidl::test::SafeUnionBar dest;
+    hidl2aidl::test::V1_2::SafeUnionBar source;
+    source.h(hidl2aidl::test::V1_1::Value::B);
+    ASSERT_TRUE(h2a::translate(source, &dest));
+    EXPECT_EQ(static_cast<hidl2aidl::test::Value>(source.h()),
+              dest.get<hidl2aidl::test::SafeUnionBar::h>());
+}
+
 TEST_F(Hidl2aidlTranslateTest, ArrayFoo) {
     hidl2aidl::test::ArrayFoo dest;
     hidl2aidl::test::V1_2::ArrayFoo source;
diff --git a/hidl2aidl/test/translate_ndk_test.cpp b/hidl2aidl/test/translate_ndk_test.cpp
index 125c236..4fd160d 100644
--- a/hidl2aidl/test/translate_ndk_test.cpp
+++ b/hidl2aidl/test/translate_ndk_test.cpp
@@ -167,6 +167,26 @@
     EXPECT_EQ(source.f(), dest.get<aidl::hidl2aidl::test::SafeUnionBar::f>());
 }
 
+TEST_F(Hidl2aidlTranslateTest, SafeUnionBarBitfield) {
+    aidl::hidl2aidl::test::SafeUnionBar dest;
+    hidl2aidl::test::V1_2::SafeUnionBar source;
+    ::android::hardware::hidl_bitfield<::hidl2aidl::test::V1_2::FooFlag> bits(0);
+    bits |= hidl2aidl::test::V1_2::FooFlag::THIRD;
+    source.g(bits);
+    ASSERT_TRUE(h2a::translate(source, &dest));
+    EXPECT_EQ(static_cast<aidl::hidl2aidl::test::FooFlag>(source.g()),
+              dest.get<aidl::hidl2aidl::test::SafeUnionBar::g>());
+}
+
+TEST_F(Hidl2aidlTranslateTest, SafeUnionBarEnum) {
+    aidl::hidl2aidl::test::SafeUnionBar dest;
+    hidl2aidl::test::V1_2::SafeUnionBar source;
+    source.h(hidl2aidl::test::V1_1::Value::B);
+    ASSERT_TRUE(h2a::translate(source, &dest));
+    EXPECT_EQ(static_cast<aidl::hidl2aidl::test::Value>(source.h()),
+              dest.get<aidl::hidl2aidl::test::SafeUnionBar::h>());
+}
+
 TEST_F(Hidl2aidlTranslateTest, ArrayFoo) {
     aidl::hidl2aidl::test::ArrayFoo dest;
     hidl2aidl::test::V1_2::ArrayFoo source;