diff options
| author | 2021-02-18 13:25:15 +0100 | |
|---|---|---|
| committer | 2021-02-18 14:52:29 +0100 | |
| commit | 8c9d2483cad988a5e84ad8c3108f8143cd9cbf3a (patch) | |
| tree | c0de4d3f9c7c191f4cbc5feb43689142b24d80cb | |
| parent | 75f37254cfcef4e54fab8121cc03c021842aa59a (diff) | |
Serialize LightFlattenable trivially copyable objects as LightFlattenable
Currently if an object is LightFlattenable and trivially copyable
FlattenableHelpers serialize it as a trivially copyable. Instead
the overloaded methods should be used.
Bug: 180539476
Test: atest FlattenableHelpersTest
Change-Id: I37d9c207db6bf7be869d919e3d96b85dc3a6cd16
| -rw-r--r-- | libs/ui/include_private/ui/FlattenableHelpers.h | 17 | ||||
| -rw-r--r-- | libs/ui/tests/FlattenableHelpers_test.cpp | 63 |
2 files changed, 75 insertions, 5 deletions
diff --git a/libs/ui/include_private/ui/FlattenableHelpers.h b/libs/ui/include_private/ui/FlattenableHelpers.h index 8e316d8ae0..378f37f077 100644 --- a/libs/ui/include_private/ui/FlattenableHelpers.h +++ b/libs/ui/include_private/ui/FlattenableHelpers.h @@ -29,20 +29,29 @@ namespace android { struct FlattenableHelpers { - // Helpers for reading and writing POD structures - template <class T, typename = std::enable_if_t<std::is_trivially_copyable_v<T>>> + // Helpers for reading and writing POD structures which are not LightFlattenable. + template <class T, + typename = std::enable_if_t< + std::conjunction_v<std::is_trivially_copyable<T>, + std::negation<std::is_base_of<LightFlattenable<T>, T>>>>> static constexpr size_t getFlattenedSize(const T&) { return sizeof(T); } - template <class T, typename = std::enable_if_t<std::is_trivially_copyable_v<T>>> + template <class T, + typename = std::enable_if_t< + std::conjunction_v<std::is_trivially_copyable<T>, + std::negation<std::is_base_of<LightFlattenable<T>, T>>>>> static status_t flatten(void** buffer, size_t* size, const T& value) { if (*size < sizeof(T)) return NO_MEMORY; FlattenableUtils::write(*buffer, *size, value); return OK; } - template <class T, typename = std::enable_if_t<std::is_trivially_copyable_v<T>>> + template <class T, + typename = std::enable_if_t< + std::conjunction_v<std::is_trivially_copyable<T>, + std::negation<std::is_base_of<LightFlattenable<T>, T>>>>> static status_t unflatten(const void** buffer, size_t* size, T* value) { if (*size < sizeof(T)) return NO_MEMORY; FlattenableUtils::read(*buffer, *size, *value); diff --git a/libs/ui/tests/FlattenableHelpers_test.cpp b/libs/ui/tests/FlattenableHelpers_test.cpp index db32bc7596..44e20b504d 100644 --- a/libs/ui/tests/FlattenableHelpers_test.cpp +++ b/libs/ui/tests/FlattenableHelpers_test.cpp @@ -42,7 +42,7 @@ struct TestLightFlattenable : LightFlattenable<TestLightFlattenable> { } status_t unflatten(void const* buffer, size_t size) { - int value; + int32_t value; FlattenableUtils::read(buffer, size, value); ptr = std::make_unique<int32_t>(value); return OK; @@ -132,5 +132,66 @@ TEST_F(FlattenableHelpersTest, NullOptionalOfLightFlattenable) { ASSERT_FALSE(valueRead.has_value()); } +// If a struct is both trivially copyable and light flattenable we should treat it +// as LigthFlattenable. +TEST_F(FlattenableHelpersTest, TriviallyCopyableAndLightFlattenableIsFlattenedAsLightFlattenable) { + static constexpr int32_t kSizeTag = 1234567; + static constexpr int32_t kFlattenTag = 987654; + static constexpr int32_t kUnflattenTag = 5926582; + + struct LightFlattenableAndTriviallyCopyable + : LightFlattenable<LightFlattenableAndTriviallyCopyable> { + int32_t value; + + bool isFixedSize() const { return true; } + size_t getFlattenedSize() const { return kSizeTag; } + + status_t flatten(void* buffer, size_t size) const { + FlattenableUtils::write(buffer, size, kFlattenTag); + return OK; + } + + status_t unflatten(void const*, size_t) { + value = kUnflattenTag; + return OK; + } + }; + + { + // Verify that getFlattenedSize uses the LightFlattenable overload + LightFlattenableAndTriviallyCopyable foo; + EXPECT_EQ(kSizeTag, FlattenableHelpers::getFlattenedSize(foo)); + } + + { + // Verify that flatten uses the LightFlattenable overload + std::vector<int8_t> buffer(sizeof(int32_t)); + auto rawBuffer = reinterpret_cast<void*>(buffer.data()); + size_t size = buffer.size(); + LightFlattenableAndTriviallyCopyable foo; + ASSERT_EQ(OK, FlattenableHelpers::flatten(&rawBuffer, &size, foo)); + + auto rawReadBuffer = reinterpret_cast<const void*>(buffer.data()); + int32_t value; + FlattenableHelpers::unflatten(&rawReadBuffer, &size, &value); + EXPECT_EQ(kFlattenTag, value); + } + + { + // Verify that unflatten uses the LightFlattenable overload + std::vector<int8_t> buffer(sizeof(int32_t)); + auto rawBuffer = reinterpret_cast<void*>(buffer.data()); + size_t size = buffer.size(); + int32_t value = 4; + ASSERT_EQ(OK, FlattenableHelpers::flatten(&rawBuffer, &size, value)); + + auto rawReadBuffer = reinterpret_cast<const void*>(buffer.data()); + + LightFlattenableAndTriviallyCopyable foo; + FlattenableHelpers::unflatten(&rawReadBuffer, &size, &foo); + EXPECT_EQ(kUnflattenTag, foo.value); + } +} + } // namespace } // namespace android |