libbinder: Support enums in SafeInterface

Adds support for sending and receiving enum values (as their underlying
types) as part of a SafeInterface.

Test: New test in binderSafeInterfaceTest
Change-Id: I9c3b6b7e7728d8c95514928354136be84bfd7875
diff --git a/libs/binder/tests/binderSafeInterfaceTest.cpp b/libs/binder/tests/binderSafeInterfaceTest.cpp
index 70f4900..ccb023d 100644
--- a/libs/binder/tests/binderSafeInterfaceTest.cpp
+++ b/libs/binder/tests/binderSafeInterfaceTest.cpp
@@ -37,6 +37,12 @@
 namespace android {
 namespace tests {
 
+enum class TestEnum : uint32_t {
+    INVALID = 0,
+    INITIAL = 1,
+    FINAL = 2,
+};
+
 // This class serves two purposes:
 //   1) It ensures that the implementation doesn't require copying or moving the data (for
 //      efficiency purposes)
@@ -187,6 +193,7 @@
         SetDeathToken = IBinder::FIRST_CALL_TRANSACTION,
         ReturnsNoMemory,
         LogicalNot,
+        ModifyEnum,
         IncrementFlattenable,
         IncrementLightFlattenable,
         IncrementLightRefBaseFlattenable,
@@ -210,6 +217,7 @@
 
     // These are ordered according to their corresponding methods in SafeInterface::ParcelHandler
     virtual status_t logicalNot(bool a, bool* notA) const = 0;
+    virtual status_t modifyEnum(TestEnum a, TestEnum* b) const = 0;
     virtual status_t increment(const TestFlattenable& a, TestFlattenable* aPlusOne) const = 0;
     virtual status_t increment(const TestLightFlattenable& a,
                                TestLightFlattenable* aPlusOne) const = 0;
@@ -246,6 +254,10 @@
         ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
         return callRemote<decltype(&ISafeInterfaceTest::logicalNot)>(Tag::LogicalNot, a, notA);
     }
+    status_t modifyEnum(TestEnum a, TestEnum* b) const override {
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        return callRemote<decltype(&ISafeInterfaceTest::modifyEnum)>(Tag::ModifyEnum, a, b);
+    }
     status_t increment(const TestFlattenable& a, TestFlattenable* aPlusOne) const override {
         using Signature =
                 status_t (ISafeInterfaceTest::*)(const TestFlattenable&, TestFlattenable*) const;
@@ -339,6 +351,11 @@
         *notA = !a;
         return NO_ERROR;
     }
+    status_t modifyEnum(TestEnum a, TestEnum* b) const override {
+        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+        *b = (a == TestEnum::INITIAL) ? TestEnum::FINAL : TestEnum::INVALID;
+        return NO_ERROR;
+    }
     status_t increment(const TestFlattenable& a, TestFlattenable* aPlusOne) const override {
         ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
         aPlusOne->value = a.value + 1;
@@ -414,6 +431,9 @@
             case ISafeInterfaceTest::Tag::LogicalNot: {
                 return callLocal(data, reply, &ISafeInterfaceTest::logicalNot);
             }
+            case ISafeInterfaceTest::Tag::ModifyEnum: {
+                return callLocal(data, reply, &ISafeInterfaceTest::modifyEnum);
+            }
             case ISafeInterfaceTest::Tag::IncrementFlattenable: {
                 using Signature = status_t (ISafeInterfaceTest::*)(const TestFlattenable& a,
                                                                    TestFlattenable* aPlusOne) const;
@@ -544,6 +564,14 @@
     ASSERT_EQ(!b, notB);
 }
 
+TEST_F(SafeInterfaceTest, TestModifyEnum) {
+    const TestEnum a = TestEnum::INITIAL;
+    TestEnum b = TestEnum::INVALID;
+    status_t result = mSafeInterfaceTest->modifyEnum(a, &b);
+    ASSERT_EQ(NO_ERROR, result);
+    ASSERT_EQ(TestEnum::FINAL, b);
+}
+
 TEST_F(SafeInterfaceTest, TestIncrementFlattenable) {
     const TestFlattenable a{1};
     TestFlattenable aPlusOne{0};