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

Commit 1af8a880 authored by Dan Stoza's avatar Dan Stoza
Browse files

libbinder: Add vector<Parcelable> to SafeInterface

Adds support fo sending and receiving std::vector<Parcelable>
parameters (such as the vector of OccupancyTracker::Segments in
IGraphicBufferConsumer::getOccupancyHistory) as part of a SafeInterface.

Test: New test in binderSafeInterfaceTest
Change-Id: Ifb7d2cece79ee9fd52791f61d2488e6a490805f3
parent 2537db72
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -141,6 +141,17 @@ public:
            Parcel* parcel, const sp<T>& interface) const {
        return write(parcel, IInterface::asBinder(interface));
    }
    template <typename T>
    typename std::enable_if<std::is_base_of<Parcelable, T>::value, status_t>::type read(
            const Parcel& parcel, std::vector<T>* v) const {
        return callParcel("readParcelableVector", [&]() { return parcel.readParcelableVector(v); });
    }
    template <typename T>
    typename std::enable_if<std::is_base_of<Parcelable, T>::value, status_t>::type write(
            Parcel* parcel, const std::vector<T>& v) const {
        return callParcel("writeParcelableVector",
                          [&]() { return parcel->writeParcelableVector(v); });
    }

    // Templates to handle integral types. We use a struct template to require that the called
    // function exactly matches the signedness and size of the argument (e.g., the argument isn't
+53 −0
Original line number Diff line number Diff line
@@ -127,6 +127,24 @@ public:
    int32_t value = 0;
};

class TestParcelable : public Parcelable {
public:
    TestParcelable() = default;
    explicit TestParcelable(int32_t value) : mValue(value) {}
    TestParcelable(const TestParcelable& other) : TestParcelable(other.mValue) {}
    TestParcelable(TestParcelable&& other) : TestParcelable(other.mValue) {}

    // Parcelable interface
    status_t writeToParcel(Parcel* parcel) const override { return parcel->writeInt32(mValue); }
    status_t readFromParcel(const Parcel* parcel) override { return parcel->readInt32(&mValue); }

    int32_t getValue() const { return mValue; }
    void setValue(int32_t value) { mValue = value; }

private:
    int32_t mValue = 0;
};

class ExitOnDeath : public IBinder::DeathRecipient {
public:
    ~ExitOnDeath() override = default;
@@ -204,6 +222,7 @@ public:
        IncrementLightRefBaseFlattenable,
        IncrementNativeHandle,
        IncrementNoCopyNoMove,
        IncrementParcelableVector,
        ToUpper,
        CallMeBack,
        IncrementInt32,
@@ -231,6 +250,8 @@ public:
                               sp<TestLightRefBaseFlattenable>* aPlusOne) const = 0;
    virtual status_t increment(const sp<NativeHandle>& a, sp<NativeHandle>* aPlusOne) const = 0;
    virtual status_t increment(const NoCopyNoMove& a, NoCopyNoMove* aPlusOne) const = 0;
    virtual status_t increment(const std::vector<TestParcelable>& a,
                               std::vector<TestParcelable>* aPlusOne) const = 0;
    virtual status_t toUpper(const String8& str, String8* upperStr) const = 0;
    // As mentioned above, sp<IBinder> is already tested by setDeathToken
    virtual void callMeBack(const sp<ICallback>& callback, int32_t a) const = 0;
@@ -296,6 +317,13 @@ public:
                                                           NoCopyNoMove* aPlusOne) const;
        return callRemote<Signature>(Tag::IncrementNoCopyNoMove, a, aPlusOne);
    }
    status_t increment(const std::vector<TestParcelable>& a,
                       std::vector<TestParcelable>* aPlusOne) const override {
        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
        using Signature = status_t (ISafeInterfaceTest::*)(const std::vector<TestParcelable>&,
                                                           std::vector<TestParcelable>*);
        return callRemote<Signature>(Tag::IncrementParcelableVector, a, aPlusOne);
    }
    status_t toUpper(const String8& str, String8* upperStr) const override {
        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
        return callRemote<decltype(&ISafeInterfaceTest::toUpper)>(Tag::ToUpper, str, upperStr);
@@ -407,6 +435,15 @@ public:
        aPlusOne->setValue(a.getValue() + 1);
        return NO_ERROR;
    }
    status_t increment(const std::vector<TestParcelable>& a,
                       std::vector<TestParcelable>* aPlusOne) const override {
        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
        aPlusOne->resize(a.size());
        for (size_t i = 0; i < a.size(); ++i) {
            (*aPlusOne)[i].setValue(a[i].getValue() + 1);
        }
        return NO_ERROR;
    }
    status_t toUpper(const String8& str, String8* upperStr) const override {
        ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
        *upperStr = str;
@@ -490,6 +527,12 @@ public:
                                                                   NoCopyNoMove* aPlusOne) const;
                return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
            }
            case ISafeInterfaceTest::Tag::IncrementParcelableVector: {
                using Signature =
                        status_t (ISafeInterfaceTest::*)(const std::vector<TestParcelable>&,
                                                         std::vector<TestParcelable>*) const;
                return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
            }
            case ISafeInterfaceTest::Tag::ToUpper: {
                return callLocal(data, reply, &ISafeInterfaceTest::toUpper);
            }
@@ -680,6 +723,16 @@ TEST_F(SafeInterfaceTest, TestIncrementNoCopyNoMove) {
    ASSERT_EQ(a.getValue() + 1, aPlusOne.getValue());
}

TEST_F(SafeInterfaceTest, TestIncremementParcelableVector) {
    const std::vector<TestParcelable> a{TestParcelable{1}, TestParcelable{2}};
    std::vector<TestParcelable> aPlusOne;
    status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
    ASSERT_EQ(a.size(), aPlusOne.size());
    for (size_t i = 0; i < a.size(); ++i) {
        ASSERT_EQ(a[i].getValue() + 1, aPlusOne[i].getValue());
    }
}

TEST_F(SafeInterfaceTest, TestToUpper) {
    const String8 str{"Hello, world!"};
    String8 upperStr;