Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 81ea3efb authored by Dan Stoza's avatar Dan Stoza
Browse files

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
parent 6dd325b9
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -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 {
+28 −0
Original line number Diff line number Diff line
@@ -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};