diff options
| -rw-r--r-- | libs/binder/include/binder/SafeInterface.h | 20 | ||||
| -rw-r--r-- | libs/binder/tests/binderSafeInterfaceTest.cpp | 56 |
2 files changed, 75 insertions, 1 deletions
diff --git a/libs/binder/include/binder/SafeInterface.h b/libs/binder/include/binder/SafeInterface.h index 1a535220ce..52037049c8 100644 --- a/libs/binder/include/binder/SafeInterface.h +++ b/libs/binder/include/binder/SafeInterface.h @@ -55,6 +55,17 @@ public: return callParcel("write(Flattenable)", [&]() { return parcel->write(t); }); } template <typename T> + typename std::enable_if<std::is_base_of<Flattenable<T>, T>::value, status_t>::type read( + const Parcel& parcel, sp<T>* t) const { + *t = new T{}; + return callParcel("read(sp<Flattenable>)", [&]() { return parcel.read(*(t->get())); }); + } + template <typename T> + typename std::enable_if<std::is_base_of<Flattenable<T>, T>::value, status_t>::type write( + Parcel* parcel, const sp<T>& t) const { + return callParcel("write(sp<Flattenable>)", [&]() { return parcel->write(*(t.get())); }); + } + template <typename T> typename std::enable_if<std::is_base_of<LightFlattenable<T>, T>::value, status_t>::type read( const Parcel& parcel, T* t) const { return callParcel("read(LightFlattenable)", [&]() { return parcel.read(*t); }); @@ -81,7 +92,8 @@ public: return callParcel("writeString8", [&]() { return parcel->writeString8(str); }); } template <typename T> - status_t read(const Parcel& parcel, sp<T>* pointer) const { + typename std::enable_if<std::is_same<IBinder, T>::value, status_t>::type read( + const Parcel& parcel, sp<T>* pointer) const { return callParcel("readNullableStrongBinder", [&]() { return parcel.readNullableStrongBinder(pointer); }); } @@ -92,6 +104,12 @@ public: [&]() { return parcel->writeStrongBinder(pointer); }); } template <typename T> + typename std::enable_if<std::is_base_of<IInterface, T>::value, status_t>::type read( + const Parcel& parcel, sp<T>* pointer) const { + return callParcel("readNullableStrongBinder[IInterface]", + [&]() { return parcel.readNullableStrongBinder(pointer); }); + } + template <typename T> typename std::enable_if<std::is_base_of<IInterface, T>::value, status_t>::type write( Parcel* parcel, const sp<T>& interface) const { return write(parcel, IInterface::asBinder(interface)); diff --git a/libs/binder/tests/binderSafeInterfaceTest.cpp b/libs/binder/tests/binderSafeInterfaceTest.cpp index 26b0cc270e..70f49000f1 100644 --- a/libs/binder/tests/binderSafeInterfaceTest.cpp +++ b/libs/binder/tests/binderSafeInterfaceTest.cpp @@ -28,6 +28,8 @@ #include <gtest/gtest.h> #pragma clang diagnostic pop +#include <utils/LightRefBase.h> + #include <optional> using namespace std::chrono_literals; // NOLINT - google-build-using-namespace @@ -90,6 +92,30 @@ struct TestLightFlattenable : LightFlattenablePod<TestLightFlattenable> { int32_t value = 0; }; +// It seems like this should be able to inherit from TestFlattenable (to avoid duplicating code), +// but the SafeInterface logic can't easily be extended to find an indirect Flattenable<T> +// base class +class TestLightRefBaseFlattenable : public Flattenable<TestLightRefBaseFlattenable>, + public LightRefBase<TestLightRefBaseFlattenable> { +public: + TestLightRefBaseFlattenable() = default; + explicit TestLightRefBaseFlattenable(int32_t v) : value(v) {} + + // Flattenable protocol + size_t getFlattenedSize() const { return sizeof(value); } + size_t getFdCount() const { return 0; } + status_t flatten(void*& buffer, size_t& size, int*& /*fds*/, size_t& /*count*/) const { + FlattenableUtils::write(buffer, size, value); + return NO_ERROR; + } + status_t unflatten(void const*& buffer, size_t& size, int const*& /*fds*/, size_t& /*count*/) { + FlattenableUtils::read(buffer, size, value); + return NO_ERROR; + } + + int32_t value = 0; +}; + class ExitOnDeath : public IBinder::DeathRecipient { public: ~ExitOnDeath() override = default; @@ -163,6 +189,7 @@ public: LogicalNot, IncrementFlattenable, IncrementLightFlattenable, + IncrementLightRefBaseFlattenable, IncrementNoCopyNoMove, ToUpper, CallMeBack, @@ -186,6 +213,8 @@ public: virtual status_t increment(const TestFlattenable& a, TestFlattenable* aPlusOne) const = 0; virtual status_t increment(const TestLightFlattenable& a, TestLightFlattenable* aPlusOne) const = 0; + virtual status_t increment(const sp<TestLightRefBaseFlattenable>& a, + sp<TestLightRefBaseFlattenable>* aPlusOne) const = 0; virtual status_t increment(const NoCopyNoMove& a, NoCopyNoMove* aPlusOne) const = 0; virtual status_t toUpper(const String8& str, String8* upperStr) const = 0; // As mentioned above, sp<IBinder> is already tested by setDeathToken @@ -230,6 +259,12 @@ public: ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__); return callRemote<Signature>(Tag::IncrementLightFlattenable, a, aPlusOne); } + status_t increment(const sp<TestLightRefBaseFlattenable>& a, + sp<TestLightRefBaseFlattenable>* aPlusOne) const override { + using Signature = status_t (ISafeInterfaceTest::*)(const sp<TestLightRefBaseFlattenable>&, + sp<TestLightRefBaseFlattenable>*) const; + return callRemote<Signature>(Tag::IncrementLightRefBaseFlattenable, a, aPlusOne); + } status_t increment(const NoCopyNoMove& a, NoCopyNoMove* aPlusOne) const override { ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__); using Signature = status_t (ISafeInterfaceTest::*)(const NoCopyNoMove& a, @@ -315,6 +350,12 @@ public: aPlusOne->value = a.value + 1; return NO_ERROR; } + status_t increment(const sp<TestLightRefBaseFlattenable>& a, + sp<TestLightRefBaseFlattenable>* aPlusOne) const override { + ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__); + *aPlusOne = new TestLightRefBaseFlattenable(a->value + 1); + return NO_ERROR; + } status_t increment(const NoCopyNoMove& a, NoCopyNoMove* aPlusOne) const override { ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__); aPlusOne->setValue(a.getValue() + 1); @@ -384,6 +425,12 @@ public: TestLightFlattenable* aPlusOne) const; return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment); } + case ISafeInterfaceTest::Tag::IncrementLightRefBaseFlattenable: { + using Signature = + status_t (ISafeInterfaceTest::*)(const sp<TestLightRefBaseFlattenable>&, + sp<TestLightRefBaseFlattenable>*) const; + return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment); + } case ISafeInterfaceTest::Tag::IncrementNoCopyNoMove: { using Signature = status_t (ISafeInterfaceTest::*)(const NoCopyNoMove& a, NoCopyNoMove* aPlusOne) const; @@ -513,6 +560,15 @@ TEST_F(SafeInterfaceTest, TestIncrementLightFlattenable) { ASSERT_EQ(a.value + 1, aPlusOne.value); } +TEST_F(SafeInterfaceTest, TestIncrementLightRefBaseFlattenable) { + sp<TestLightRefBaseFlattenable> a = new TestLightRefBaseFlattenable{1}; + sp<TestLightRefBaseFlattenable> aPlusOne; + status_t result = mSafeInterfaceTest->increment(a, &aPlusOne); + ASSERT_EQ(NO_ERROR, result); + ASSERT_NE(nullptr, aPlusOne.get()); + ASSERT_EQ(a->value + 1, aPlusOne->value); +} + TEST_F(SafeInterfaceTest, TestIncrementNoCopyNoMove) { const NoCopyNoMove a{1}; NoCopyNoMove aPlusOne{0}; |