summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Dan Stoza <stoza@google.com> 2017-04-07 15:00:18 -0700
committer Dan Stoza <stoza@google.com> 2017-04-10 14:35:41 -0700
commit81ea3efb75a6427c946221f95dcf9c388b27a977 (patch)
tree52f97ee1433992ef737689930a76ce09ac11a0c5
parent6dd325b9396c9946ced9d01665152a44167a8fa2 (diff)
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
-rw-r--r--libs/binder/include/binder/SafeInterface.h13
-rw-r--r--libs/binder/tests/binderSafeInterfaceTest.cpp28
2 files changed, 41 insertions, 0 deletions
diff --git a/libs/binder/include/binder/SafeInterface.h b/libs/binder/include/binder/SafeInterface.h
index 52037049c8..f931304b95 100644
--- a/libs/binder/include/binder/SafeInterface.h
+++ b/libs/binder/include/binder/SafeInterface.h
@@ -44,6 +44,19 @@ public:
status_t write(Parcel* parcel, bool b) const {
return callParcel("writeBool", [&]() { return parcel->writeBool(b); });
}
+ template <typename E>
+ typename std::enable_if<std::is_enum<E>::value, status_t>::type read(const Parcel& parcel,
+ E* e) const {
+ typename std::underlying_type<E>::type u{};
+ status_t result = read(parcel, &u);
+ *e = static_cast<E>(u);
+ return result;
+ }
+ template <typename E>
+ typename std::enable_if<std::is_enum<E>::value, status_t>::type write(Parcel* parcel,
+ E e) const {
+ return write(parcel, static_cast<typename std::underlying_type<E>::type>(e));
+ }
template <typename T>
typename std::enable_if<std::is_base_of<Flattenable<T>, T>::value, status_t>::type read(
const Parcel& parcel, T* t) const {
diff --git a/libs/binder/tests/binderSafeInterfaceTest.cpp b/libs/binder/tests/binderSafeInterfaceTest.cpp
index 70f49000f1..ccb023d2ce 100644
--- a/libs/binder/tests/binderSafeInterfaceTest.cpp
+++ b/libs/binder/tests/binderSafeInterfaceTest.cpp
@@ -37,6 +37,12 @@ using namespace std::chrono_literals; // NOLINT - google-build-using-namespace
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 @@ public:
SetDeathToken = IBinder::FIRST_CALL_TRANSACTION,
ReturnsNoMemory,
LogicalNot,
+ ModifyEnum,
IncrementFlattenable,
IncrementLightFlattenable,
IncrementLightRefBaseFlattenable,
@@ -210,6 +217,7 @@ public:
// 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 @@ public:
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 @@ public:
*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 @@ public:
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 @@ TEST_F(SafeInterfaceTest, TestLogicalNot) {
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};