diff options
author | 2024-07-12 19:23:39 +0000 | |
---|---|---|
committer | 2024-07-12 19:23:39 +0000 | |
commit | e2f79abef85d9dfb3ffcc09e0f94c82607f16cf7 (patch) | |
tree | ab6f8d798f6f166f5deafe6ba7e00fc04c4dace2 | |
parent | 0e3c35aa0654058b5edd9d047741690a8e810042 (diff) | |
parent | 26743a54cad2aec2262f161bc8cc3e55ff20bc62 (diff) |
Merge "Delete code for legacy VR services." into main
214 files changed, 0 insertions, 38834 deletions
diff --git a/cmds/atrace/Android.bp b/cmds/atrace/Android.bp index 1c4e63e323..bc69b35aaa 100644 --- a/cmds/atrace/Android.bp +++ b/cmds/atrace/Android.bp @@ -33,7 +33,6 @@ cc_binary { "libcutils", "libz", "libbase", - "libpdx_default_transport", "android.hardware.atrace@1.0", ], diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp index 4160a72e83..888dc4ec0d 100644 --- a/cmds/atrace/atrace.cpp +++ b/cmds/atrace/atrace.cpp @@ -41,7 +41,6 @@ #include <android/hidl/manager/1.0/IServiceManager.h> #include <hidl/ServiceManagement.h> -#include <pdx/default_transport/service_utility.h> #include <utils/String8.h> #include <utils/Timers.h> #include <utils/Tokenizer.h> @@ -53,7 +52,6 @@ #include <android-base/stringprintf.h> using namespace android; -using pdx::default_transport::ServiceUtility; using hardware::hidl_vec; using hardware::hidl_string; using hardware::Return; @@ -72,7 +70,6 @@ const char* k_tracePreferSdkProperty = "debug.atrace.prefer_sdk"; const char* k_traceAppsNumberProperty = "debug.atrace.app_number"; const char* k_traceAppsPropertyTemplate = "debug.atrace.app_%d"; const char* k_coreServiceCategory = "core_services"; -const char* k_pdxServiceCategory = "pdx"; const char* k_coreServicesProp = "ro.atrace.core.services"; const char* kVendorCategoriesPath = "/vendor/etc/atrace/atrace_categories.txt"; @@ -131,7 +128,6 @@ static const TracingCategory k_categories[] = { { "nnapi", "NNAPI", ATRACE_TAG_NNAPI, { } }, { "rro", "Runtime Resource Overlay", ATRACE_TAG_RRO, { } }, { k_coreServiceCategory, "Core services", 0, { } }, - { k_pdxServiceCategory, "PDX services", 0, { } }, { "sched", "CPU Scheduling", 0, { { REQ, "events/sched/sched_switch/enable" }, { REQ, "events/sched/sched_wakeup/enable" }, @@ -299,7 +295,6 @@ static const char* g_debugAppCmdLine = ""; static const char* g_outputFile = nullptr; /* Global state */ -static bool g_tracePdx = false; static bool g_traceAborted = false; static bool g_categoryEnables[arraysize(k_categories)] = {}; static std::string g_traceFolder; @@ -456,10 +451,6 @@ static bool isCategorySupported(const TracingCategory& category) return !android::base::GetProperty(k_coreServicesProp, "").empty(); } - if (strcmp(category.name, k_pdxServiceCategory) == 0) { - return true; - } - bool ok = category.tags != 0; for (int i = 0; i < MAX_SYS_FILES; i++) { const char* path = category.sysfiles[i].path; @@ -818,11 +809,6 @@ static bool setUpUserspaceTracing() if (strcmp(k_categories[i].name, k_coreServiceCategory) == 0) { coreServicesTagEnabled = g_categoryEnables[i]; } - - // Set whether to poke PDX services in this session. - if (strcmp(k_categories[i].name, k_pdxServiceCategory) == 0) { - g_tracePdx = g_categoryEnables[i]; - } } std::string packageList(g_debugAppCmdLine); @@ -834,9 +820,6 @@ static bool setUpUserspaceTracing() } ok &= setAppCmdlineProperty(&packageList[0]); ok &= setTagsProperty(tags); - if (g_tracePdx) { - ok &= ServiceUtility::PokeServices(); - } return ok; } @@ -845,10 +828,6 @@ static void cleanUpUserspaceTracing() { setTagsProperty(0); clearAppProperties(); - - if (g_tracePdx) { - ServiceUtility::PokeServices(); - } } diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index b693e44ee4..7dcbbc04bf 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -309,9 +309,7 @@ cc_library_shared { header_libs: [ "jni_headers", - "libdvr_headers", "libgui_aidl_headers", - "libpdx_headers", ], afdo: true, diff --git a/libs/ui/include/ui/BufferHubDefs.h b/libs/ui/include/ui/BufferHubDefs.h deleted file mode 100644 index 10f274f569..0000000000 --- a/libs/ui/include/ui/BufferHubDefs.h +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_BUFFER_HUB_DEFS_H_ -#define ANDROID_BUFFER_HUB_DEFS_H_ - -#include <atomic> - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpacked" -// TODO(b/118893702): remove dependency once DvrNativeBufferMetadata moved out of libdvr -#include <dvr/dvr_api.h> -#pragma clang diagnostic pop - -namespace android { - -namespace BufferHubDefs { - -// Single buffer clients (up to 16) ownership signal. -// 32-bit atomic unsigned int. -// Each client takes 2 bits. The first bit locates in the first 16 bits of -// bufferState; the second bit locates in the last 16 bits of bufferState. -// Client states: -// Gained state 11. Exclusive write state. -// Posted state 10. -// Acquired state 01. Shared read state. -// Released state 00. -// -// MSB LSB -// | | -// v v -// [C15|...|C1|C0|C15| ... |C1|C0] - -// Maximum number of clients a buffer can have. -static constexpr int kMaxNumberOfClients = 16; - -// Definition of bit masks. -// MSB LSB -// | kHighBitsMask | kLowbitsMask | -// v v v -// [b31| ... |b16|b15| ... |b0] - -// The location of lower 16 bits in the 32-bit buffer state. -static constexpr uint32_t kLowbitsMask = (1U << kMaxNumberOfClients) - 1U; - -// The location of higher 16 bits in the 32-bit buffer state. -static constexpr uint32_t kHighBitsMask = ~kLowbitsMask; - -// The client bit mask of the first client. -static constexpr uint32_t kFirstClientBitMask = (1U << kMaxNumberOfClients) + 1U; - -// Returns true if any of the client is in gained state. -static inline bool isAnyClientGained(uint32_t state) { - uint32_t highBits = state >> kMaxNumberOfClients; - uint32_t lowBits = state & kLowbitsMask; - return highBits == lowBits && lowBits != 0U; -} - -// Returns true if the input client is in gained state. -static inline bool isClientGained(uint32_t state, uint32_t client_bit_mask) { - return state == client_bit_mask; -} - -// Returns true if any of the client is in posted state. -static inline bool isAnyClientPosted(uint32_t state) { - uint32_t highBits = state >> kMaxNumberOfClients; - uint32_t lowBits = state & kLowbitsMask; - uint32_t postedOrAcquired = highBits ^ lowBits; - return postedOrAcquired & highBits; -} - -// Returns true if the input client is in posted state. -static inline bool isClientPosted(uint32_t state, uint32_t client_bit_mask) { - uint32_t clientBits = state & client_bit_mask; - if (clientBits == 0U) return false; - uint32_t lowBits = clientBits & kLowbitsMask; - return lowBits == 0U; -} - -// Return true if any of the client is in acquired state. -static inline bool isAnyClientAcquired(uint32_t state) { - uint32_t highBits = state >> kMaxNumberOfClients; - uint32_t lowBits = state & kLowbitsMask; - uint32_t postedOrAcquired = highBits ^ lowBits; - return postedOrAcquired & lowBits; -} - -// Return true if the input client is in acquired state. -static inline bool isClientAcquired(uint32_t state, uint32_t client_bit_mask) { - uint32_t clientBits = state & client_bit_mask; - if (clientBits == 0U) return false; - uint32_t highBits = clientBits & kHighBitsMask; - return highBits == 0U; -} - -// Returns true if the input client is in released state. -static inline bool isClientReleased(uint32_t state, uint32_t client_bit_mask) { - return (state & client_bit_mask) == 0U; -} - -// Returns the next available buffer client's client_state_masks. -// @params union_bits. Union of all existing clients' client_state_masks. -static inline uint32_t findNextAvailableClientStateMask(uint32_t union_bits) { - uint32_t lowUnion = union_bits & kLowbitsMask; - if (lowUnion == kLowbitsMask) return 0U; - uint32_t incremented = lowUnion + 1U; - uint32_t difference = incremented ^ lowUnion; - uint32_t newLowBit = (difference + 1U) >> 1; - return newLowBit + (newLowBit << kMaxNumberOfClients); -} - -struct __attribute__((aligned(8))) MetadataHeader { - // Internal data format, which can be updated as long as the size, padding and field alignment - // of the struct is consistent within the same ABI. As this part is subject for future updates, - // it's not stable cross Android version, so don't have it visible from outside of the Android - // platform (include Apps and vendor HAL). - - // Every client takes up one bit from the higher 32 bits and one bit from the lower 32 bits in - // bufferState. - std::atomic<uint32_t> bufferState; - - // Every client takes up one bit in fenceState. Only the lower 32 bits are valid. The upper 32 - // bits are there for easier manipulation, but the value should be ignored. - std::atomic<uint32_t> fenceState; - - // Every client takes up one bit from the higher 32 bits and one bit from the lower 32 bits in - // activeClientsBitMask. - std::atomic<uint32_t> activeClientsBitMask; - - // Explicit padding 4 bytes. - uint32_t padding; - - // The index of the buffer queue where the buffer belongs to. - uint64_t queueIndex; - - // Public data format, which should be updated with caution. See more details in dvr_api.h - DvrNativeBufferMetadata metadata; -}; - -static_assert(sizeof(MetadataHeader) == 128, "Unexpected MetadataHeader size"); -static constexpr size_t kMetadataHeaderSize = sizeof(MetadataHeader); - -/** - * android.frameworks.bufferhub@1.0::BufferTraits.bufferInfo is an opaque handle. See - * https://cs.corp.google.com/android/frameworks/hardware/interfaces/bufferhub/1.0/types.hal for - * more details about android.frameworks.bufferhub@1.0::BufferTraits. - * - * This definition could be changed, but implementation of BufferHubService::buildBufferInfo - * (frameworks/native/services/bufferhub), VtsHalBufferHubV1_0TargetTest - * (frameworks/hardware/interfaces/bufferhub) and BufferHubBuffer::readBufferTraits (libui) will - * also need to be updated. - * - * It's definition should follow the following format: - * { - * NumFds = 2, - * NumInts = 3, - * data[0] = Ashmem fd for BufferHubMetadata, - * data[1] = event fd, - * data[2] = buffer id, - * data[3] = client state bit mask, - * data[4] = user metadata size, - * } - */ -static constexpr int kBufferInfoNumFds = 2; -static constexpr int kBufferInfoNumInts = 3; - -} // namespace BufferHubDefs - -} // namespace android - -#endif // ANDROID_BUFFER_HUB_DEFS_H_ diff --git a/libs/vr/.clang-format b/libs/vr/.clang-format deleted file mode 100644 index 04d7970bbe..0000000000 --- a/libs/vr/.clang-format +++ /dev/null @@ -1,5 +0,0 @@ -BasedOnStyle: Google -DerivePointerAlignment: false -PointerAlignment: Left -AllowShortIfStatementsOnASingleLine: false -AllowShortLoopsOnASingleLine: false diff --git a/libs/vr/Android.bp b/libs/vr/Android.bp deleted file mode 100644 index b308895faf..0000000000 --- a/libs/vr/Android.bp +++ /dev/null @@ -1,14 +0,0 @@ -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "frameworks_native_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - // SPDX-license-identifier-BSD - // legacy_notice - default_applicable_licenses: ["frameworks_native_license"], -} - -subdirs = [ - "*", -] diff --git a/libs/vr/CPPLINT.cfg b/libs/vr/CPPLINT.cfg deleted file mode 100644 index 87fb641c28..0000000000 --- a/libs/vr/CPPLINT.cfg +++ /dev/null @@ -1,2 +0,0 @@ -set noparent -filter=-build/include_order,-legal/copyright,-build/include,-build/c++11,+build/include_alpha diff --git a/libs/vr/OWNERS b/libs/vr/OWNERS deleted file mode 100644 index 098c80e557..0000000000 --- a/libs/vr/OWNERS +++ /dev/null @@ -1,4 +0,0 @@ -hendrikw@google.com -jwcai@google.com -steventhomas@google.com -patplunkett@google.com diff --git a/libs/vr/libbroadcastring/Android.bp b/libs/vr/libbroadcastring/Android.bp deleted file mode 100644 index e72ca74ba7..0000000000 --- a/libs/vr/libbroadcastring/Android.bp +++ /dev/null @@ -1,43 +0,0 @@ -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "frameworks_native_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["frameworks_native_license"], -} - -cc_library_static { - name: "libbroadcastring", - - cflags: [ - "-Wall", - "-Wextra", - "-Werror", - ], - export_include_dirs: ["include"], - shared_libs: [ - "libbase", - ], - export_shared_lib_headers: [ - "libbase", - ], -} - -cc_test { - name: "broadcast_ring_tests", - cflags: [ - "-Wall", - "-Wextra", - "-Werror", - ], - srcs: [ - "broadcast_ring_test.cc", - ], - static_libs: [ - "libbroadcastring", - ], - shared_libs: [ - "libbase", - ], -} diff --git a/libs/vr/libbroadcastring/broadcast_ring_test.cc b/libs/vr/libbroadcastring/broadcast_ring_test.cc deleted file mode 100644 index dfdd4ef0db..0000000000 --- a/libs/vr/libbroadcastring/broadcast_ring_test.cc +++ /dev/null @@ -1,866 +0,0 @@ -#include "libbroadcastring/broadcast_ring.h" - -#include <stdlib.h> -#include <memory> -#include <thread> // NOLINT -#include <sys/mman.h> - -#include <gtest/gtest.h> - -namespace android { -namespace dvr { -namespace { - -template <uint32_t N> -struct alignas(8) Aligned { - char v[N]; -}; - -template <uint32_t N> -struct alignas(8) Sized { - Sized() { Clear(); } - explicit Sized(char c) { Fill(c); } - char v[sizeof(Aligned<N>)]; - void Clear() { memset(v, 0, sizeof(v)); } - void Fill(char c) { memset(v, c, sizeof(v)); } - static Sized Pattern(uint8_t c) { - Sized sized; - for (size_t i = 0; i < sizeof(v); ++i) { - sized.v[i] = static_cast<char>(c + i); - } - return sized; - } - bool operator==(const Sized& right) const { - static_assert(sizeof(*this) == sizeof(v), "Size mismatch"); - return !memcmp(v, right.v, sizeof(v)); - } - template <typename SmallerSized> - SmallerSized Truncate() const { - SmallerSized val; - static_assert(sizeof(val.v) <= sizeof(v), "Cannot truncate to larger size"); - memcpy(val.v, v, sizeof(val.v)); - return val; - } -}; - -char FillChar(int val) { return static_cast<char>(val); } - -struct FakeMmap { - explicit FakeMmap(size_t size) : size(size), data(new char[size]) {} - size_t size; - std::unique_ptr<char[]> data; - void* mmap() { return static_cast<void*>(data.get()); } -}; - -template <typename Ring> -FakeMmap CreateRing(Ring* ring, uint32_t count) { - FakeMmap mmap(Ring::MemorySize(count)); - *ring = Ring::Create(mmap.mmap(), mmap.size, count); - return mmap; -} - -template <typename RecordType, bool StaticSize = false, - uint32_t StaticCount = 0, uint32_t MaxReserved = 1, - uint32_t MinAvailable = 0> -struct Traits { - using Record = RecordType; - static constexpr bool kUseStaticRecordSize = StaticSize; - static constexpr uint32_t kStaticRecordCount = StaticCount; - static constexpr uint32_t kMaxReservedRecords = MaxReserved; - static constexpr uint32_t kMinAvailableRecords = MinAvailable; - static constexpr uint32_t kMinRecordCount = MaxReserved + MinAvailable; -}; - -template <typename Record, bool StaticSize = false, uint32_t MaxReserved = 1, - uint32_t MinAvailable = 7> -struct TraitsDynamic - : public Traits<Record, StaticSize, 0, MaxReserved, MinAvailable> { - using Ring = BroadcastRing<Record, TraitsDynamic>; - static uint32_t MinCount() { return MaxReserved + MinAvailable; } -}; - -template <typename Record, uint32_t StaticCount = 1, bool StaticSize = true, - uint32_t MaxReserved = 1, uint32_t MinAvailable = 0> -struct TraitsStatic - : public Traits<Record, true, StaticCount, MaxReserved, MinAvailable> { - using Ring = BroadcastRing<Record, TraitsStatic>; - static uint32_t MinCount() { return StaticCount; } -}; - -using Dynamic_8_NxM = TraitsDynamic<Sized<8>>; -using Dynamic_16_NxM = TraitsDynamic<Sized<16>>; -using Dynamic_32_NxM = TraitsDynamic<Sized<32>>; -using Dynamic_32_32xM = TraitsDynamic<Sized<32>, true>; -using Dynamic_16_NxM_1plus0 = TraitsDynamic<Sized<16>, false, 1, 0>; -using Dynamic_16_NxM_1plus1 = TraitsDynamic<Sized<16>, false, 1, 1>; -using Dynamic_16_NxM_5plus11 = TraitsDynamic<Sized<16>, false, 5, 11>; -using Dynamic_256_NxM_1plus0 = TraitsDynamic<Sized<256>, false, 1, 0>; - -using Static_8_8x1 = TraitsStatic<Sized<8>, 1>; -using Static_8_8x16 = TraitsStatic<Sized<8>, 16>; -using Static_16_16x8 = TraitsStatic<Sized<16>, 8>; -using Static_16_16x16 = TraitsStatic<Sized<16>, 16>; -using Static_16_16x32 = TraitsStatic<Sized<16>, 32>; -using Static_32_Nx8 = TraitsStatic<Sized<32>, 8, false>; - -using TraitsList = ::testing::Types<Dynamic_8_NxM, // - Dynamic_16_NxM, // - Dynamic_32_NxM, // - Dynamic_32_32xM, // - Dynamic_16_NxM_1plus0, // - Dynamic_16_NxM_1plus1, // - Dynamic_16_NxM_5plus11, // - Dynamic_256_NxM_1plus0, // - Static_8_8x1, // - Static_8_8x16, // - Static_16_16x8, // - Static_16_16x16, // - Static_16_16x32, // - Static_32_Nx8>; - -} // namespace - -template <typename T> -class BroadcastRingTest : public ::testing::Test {}; - -TYPED_TEST_CASE(BroadcastRingTest, TraitsList); - -TYPED_TEST(BroadcastRingTest, Geometry) { - using Record = typename TypeParam::Record; - using Ring = typename TypeParam::Ring; - Ring ring; - auto mmap = CreateRing(&ring, Ring::Traits::MinCount()); - EXPECT_EQ(Ring::Traits::MinCount(), ring.record_count()); - EXPECT_EQ(sizeof(Record), ring.record_size()); -} - -TYPED_TEST(BroadcastRingTest, PutGet) { - using Record = typename TypeParam::Record; - using Ring = typename TypeParam::Ring; - Ring ring; - auto mmap = CreateRing(&ring, Ring::Traits::MinCount()); - const uint32_t oldest_sequence_at_start = ring.GetOldestSequence(); - const uint32_t next_sequence_at_start = ring.GetNextSequence(); - { - uint32_t sequence = oldest_sequence_at_start; - Record record; - EXPECT_FALSE(ring.Get(&sequence, &record)); - EXPECT_EQ(oldest_sequence_at_start, sequence); - EXPECT_EQ(Record(), record); - } - const Record original_record(0x1a); - ring.Put(original_record); - { - uint32_t sequence = next_sequence_at_start; - Record record; - EXPECT_TRUE(ring.Get(&sequence, &record)); - EXPECT_EQ(next_sequence_at_start, sequence); - EXPECT_EQ(original_record, record); - } - { - uint32_t sequence = next_sequence_at_start + 1; - Record record; - EXPECT_FALSE(ring.Get(&sequence, &record)); - EXPECT_EQ(next_sequence_at_start + 1, sequence); - EXPECT_EQ(Record(), record); - } -} - -TYPED_TEST(BroadcastRingTest, FillOnce) { - using Record = typename TypeParam::Record; - using Ring = typename TypeParam::Ring; - Ring ring; - auto mmap = CreateRing(&ring, Ring::Traits::MinCount()); - const uint32_t next_sequence_at_start = ring.GetNextSequence(); - for (uint32_t i = 0; i < ring.record_count(); ++i) - ring.Put(Record(FillChar(i))); - for (uint32_t i = 0; i < ring.record_count(); ++i) { - const uint32_t expected_sequence = next_sequence_at_start + i; - const Record expected_record(FillChar(i)); - { - uint32_t sequence = ring.GetOldestSequence() + i; - Record record; - EXPECT_TRUE(ring.Get(&sequence, &record)); - EXPECT_EQ(expected_sequence, sequence); - EXPECT_EQ(expected_record, record); - } - } - { - uint32_t sequence = ring.GetOldestSequence() + ring.record_count(); - Record record; - EXPECT_FALSE(ring.Get(&sequence, &record)); - } -} - -TYPED_TEST(BroadcastRingTest, FillTwice) { - using Record = typename TypeParam::Record; - using Ring = typename TypeParam::Ring; - Ring ring; - auto mmap = CreateRing(&ring, Ring::Traits::MinCount()); - const uint32_t next_sequence_at_start = ring.GetNextSequence(); - for (uint32_t i = 0; i < 2 * ring.record_count(); ++i) { - const Record newest_record(FillChar(i)); - ring.Put(newest_record); - - const uint32_t newest_sequence = next_sequence_at_start + i; - const uint32_t records_available = std::min(i + 1, ring.record_count()); - const uint32_t oldest_sequence = newest_sequence - records_available + 1; - EXPECT_EQ(newest_sequence, ring.GetNewestSequence()); - EXPECT_EQ(oldest_sequence, ring.GetOldestSequence()); - EXPECT_EQ(newest_sequence + 1, ring.GetNextSequence()); - - for (uint32_t j = 0; j < records_available; ++j) { - const uint32_t sequence_jth_newest = newest_sequence - j; - const Record record_jth_newest(FillChar(i - j)); - - { - uint32_t sequence = sequence_jth_newest; - Record record; - EXPECT_TRUE(ring.Get(&sequence, &record)); - EXPECT_EQ(sequence_jth_newest, sequence); - EXPECT_EQ(record_jth_newest, record); - } - - { - uint32_t sequence = sequence_jth_newest; - Record record; - EXPECT_TRUE(ring.GetNewest(&sequence, &record)); - EXPECT_EQ(newest_sequence, sequence); - EXPECT_EQ(newest_record, record); - } - } - - const Record oldest_record( - FillChar(i + (oldest_sequence - newest_sequence))); - const uint32_t sequence_0th_overwritten = oldest_sequence - 1; - const uint32_t sequence_0th_future = newest_sequence + 1; - const uint32_t sequence_1st_future = newest_sequence + 2; - - { - uint32_t sequence = sequence_0th_overwritten; - Record record; - EXPECT_TRUE(ring.Get(&sequence, &record)); - EXPECT_EQ(oldest_sequence, sequence); - EXPECT_EQ(oldest_record, record); - } - - { - uint32_t sequence = sequence_0th_overwritten; - Record record; - EXPECT_TRUE(ring.GetNewest(&sequence, &record)); - EXPECT_EQ(newest_sequence, sequence); - EXPECT_EQ(newest_record, record); - } - - { - uint32_t sequence = sequence_0th_future; - Record record; - EXPECT_FALSE(ring.Get(&sequence, &record)); - EXPECT_EQ(sequence_0th_future, sequence); - EXPECT_EQ(Record(), record); - } - - { - uint32_t sequence = sequence_0th_future; - Record record; - EXPECT_FALSE(ring.GetNewest(&sequence, &record)); - EXPECT_EQ(sequence_0th_future, sequence); - EXPECT_EQ(Record(), record); - } - - { - uint32_t sequence = sequence_1st_future; - Record record; - EXPECT_TRUE(ring.Get(&sequence, &record)); - EXPECT_EQ(oldest_sequence, sequence); - EXPECT_EQ(oldest_record, record); - } - - { - uint32_t sequence = sequence_1st_future; - Record record; - EXPECT_TRUE(ring.GetNewest(&sequence, &record)); - EXPECT_EQ(newest_sequence, sequence); - EXPECT_EQ(newest_record, record); - } - } -} - -TYPED_TEST(BroadcastRingTest, Import) { - using Record = typename TypeParam::Record; - using Ring = typename TypeParam::Ring; - Ring ring; - auto mmap = CreateRing(&ring, Ring::Traits::MinCount()); - - const uint32_t sequence_0 = ring.GetNextSequence(); - const uint32_t sequence_1 = ring.GetNextSequence() + 1; - const Record record_0 = Record::Pattern(0x00); - const Record record_1 = Record::Pattern(0x80); - ring.Put(record_0); - ring.Put(record_1); - - { - Ring imported_ring; - bool import_ok; - std::tie(imported_ring, import_ok) = Ring::Import(mmap.mmap(), mmap.size); - EXPECT_TRUE(import_ok); - EXPECT_EQ(ring.record_size(), imported_ring.record_size()); - EXPECT_EQ(ring.record_count(), imported_ring.record_count()); - - if (ring.record_count() != 1) { - uint32_t sequence = sequence_0; - Record imported_record; - EXPECT_TRUE(imported_ring.Get(&sequence, &imported_record)); - EXPECT_EQ(sequence_0, sequence); - EXPECT_EQ(record_0, imported_record); - } - - { - uint32_t sequence = sequence_1; - Record imported_record; - EXPECT_TRUE(imported_ring.Get(&sequence, &imported_record)); - EXPECT_EQ(sequence_1, sequence); - EXPECT_EQ(record_1, imported_record); - } - } -} - -TEST(BroadcastRingTest, ShouldFailImportIfStaticSizeMismatch) { - using OriginalRing = typename Static_16_16x16::Ring; - using RecordSizeMismatchRing = typename Static_8_8x16::Ring; - using RecordCountMismatchRing = typename Static_16_16x8::Ring; - - OriginalRing original_ring; - auto mmap = CreateRing(&original_ring, OriginalRing::Traits::MinCount()); - - { - using ImportedRing = RecordSizeMismatchRing; - ImportedRing imported_ring; - bool import_ok; - std::tie(imported_ring, import_ok) = - ImportedRing::Import(mmap.mmap(), mmap.size); - EXPECT_FALSE(import_ok); - auto mmap_imported = - CreateRing(&imported_ring, ImportedRing::Traits::MinCount()); - EXPECT_NE(original_ring.record_size(), imported_ring.record_size()); - EXPECT_EQ(original_ring.record_count(), imported_ring.record_count()); - } - - { - using ImportedRing = RecordCountMismatchRing; - ImportedRing imported_ring; - bool import_ok; - std::tie(imported_ring, import_ok) = - ImportedRing::Import(mmap.mmap(), mmap.size); - EXPECT_FALSE(import_ok); - auto mmap_imported = - CreateRing(&imported_ring, ImportedRing::Traits::MinCount()); - EXPECT_EQ(original_ring.record_size(), imported_ring.record_size()); - EXPECT_NE(original_ring.record_count(), imported_ring.record_count()); - } -} - -TEST(BroadcastRingTest, ShouldFailImportIfDynamicSizeGrows) { - using OriginalRing = typename Dynamic_8_NxM::Ring; - using RecordSizeGrowsRing = typename Dynamic_16_NxM::Ring; - - OriginalRing original_ring; - auto mmap = CreateRing(&original_ring, OriginalRing::Traits::MinCount()); - - { - using ImportedRing = RecordSizeGrowsRing; - ImportedRing imported_ring; - bool import_ok; - std::tie(imported_ring, import_ok) = - ImportedRing::Import(mmap.mmap(), mmap.size); - EXPECT_FALSE(import_ok); - auto mmap_imported = - CreateRing(&imported_ring, ImportedRing::Traits::MinCount()); - EXPECT_LT(original_ring.record_size(), imported_ring.record_size()); - EXPECT_EQ(original_ring.record_count(), imported_ring.record_count()); - } -} - -TEST(BroadcastRingTest, ShouldFailImportIfCountTooSmall) { - using OriginalRing = typename Dynamic_16_NxM_1plus0::Ring; - using MinCountRing = typename Dynamic_16_NxM_1plus1::Ring; - - OriginalRing original_ring; - auto mmap = CreateRing(&original_ring, OriginalRing::Traits::MinCount()); - - { - using ImportedRing = MinCountRing; - ImportedRing imported_ring; - bool import_ok; - std::tie(imported_ring, import_ok) = - ImportedRing::Import(mmap.mmap(), mmap.size); - EXPECT_FALSE(import_ok); - auto mmap_imported = - CreateRing(&imported_ring, ImportedRing::Traits::MinCount()); - EXPECT_EQ(original_ring.record_size(), imported_ring.record_size()); - EXPECT_LT(original_ring.record_count(), imported_ring.record_count()); - } -} - -TEST(BroadcastRingTest, ShouldFailImportIfMmapTooSmall) { - using OriginalRing = typename Dynamic_16_NxM::Ring; - - OriginalRing original_ring; - auto mmap = CreateRing(&original_ring, OriginalRing::Traits::MinCount()); - - { - using ImportedRing = OriginalRing; - ImportedRing imported_ring; - bool import_ok; - const size_t kMinSize = - ImportedRing::MemorySize(original_ring.record_count()); - std::tie(imported_ring, import_ok) = ImportedRing::Import(mmap.mmap(), 0); - EXPECT_FALSE(import_ok); - std::tie(imported_ring, import_ok) = - ImportedRing::Import(mmap.mmap(), kMinSize - 1); - EXPECT_FALSE(import_ok); - std::tie(imported_ring, import_ok) = - ImportedRing::Import(mmap.mmap(), kMinSize); - EXPECT_TRUE(import_ok); - EXPECT_EQ(original_ring.record_size(), imported_ring.record_size()); - EXPECT_EQ(original_ring.record_count(), imported_ring.record_count()); - } -} - -TEST(BroadcastRingTest, ShouldImportIfDynamicSizeShrinks) { - using OriginalRing = typename Dynamic_16_NxM::Ring; - using RecordSizeShrinksRing = typename Dynamic_8_NxM::Ring; - - OriginalRing original_ring; - auto mmap = CreateRing(&original_ring, OriginalRing::Traits::MinCount()); - - using OriginalRecord = typename OriginalRing::Record; - const uint32_t original_sequence_0 = original_ring.GetNextSequence(); - const uint32_t original_sequence_1 = original_ring.GetNextSequence() + 1; - const OriginalRecord original_record_0 = OriginalRecord::Pattern(0x00); - const OriginalRecord original_record_1 = OriginalRecord::Pattern(0x80); - original_ring.Put(original_record_0); - original_ring.Put(original_record_1); - - { - using ImportedRing = RecordSizeShrinksRing; - using ImportedRecord = typename ImportedRing::Record; - ImportedRing imported_ring; - bool import_ok; - std::tie(imported_ring, import_ok) = - ImportedRing::Import(mmap.mmap(), mmap.size); - EXPECT_TRUE(import_ok); - EXPECT_EQ(original_ring.record_size(), imported_ring.record_size()); - EXPECT_EQ(original_ring.record_count(), imported_ring.record_count()); - EXPECT_GT(sizeof(OriginalRecord), sizeof(ImportedRecord)); - - { - uint32_t sequence = original_sequence_0; - ImportedRecord shrunk_record; - EXPECT_TRUE(imported_ring.Get(&sequence, &shrunk_record)); - EXPECT_EQ(original_sequence_0, sequence); - EXPECT_EQ(original_record_0.Truncate<ImportedRecord>(), shrunk_record); - } - - { - uint32_t sequence = original_sequence_1; - ImportedRecord shrunk_record; - EXPECT_TRUE(imported_ring.Get(&sequence, &shrunk_record)); - EXPECT_EQ(original_sequence_1, sequence); - EXPECT_EQ(original_record_1.Truncate<ImportedRecord>(), shrunk_record); - } - } -} - -TEST(BroadcastRingTest, ShouldImportIfCompatibleDynamicToStatic) { - using OriginalRing = typename Dynamic_16_NxM::Ring; - using ImportedRing = typename Static_16_16x16::Ring; - using OriginalRecord = typename OriginalRing::Record; - using ImportedRecord = typename ImportedRing::Record; - using StaticRing = ImportedRing; - - OriginalRing original_ring; - auto mmap = CreateRing(&original_ring, StaticRing::Traits::MinCount()); - - const uint32_t original_sequence_0 = original_ring.GetNextSequence(); - const uint32_t original_sequence_1 = original_ring.GetNextSequence() + 1; - const OriginalRecord original_record_0 = OriginalRecord::Pattern(0x00); - const OriginalRecord original_record_1 = OriginalRecord::Pattern(0x80); - original_ring.Put(original_record_0); - original_ring.Put(original_record_1); - - { - ImportedRing imported_ring; - bool import_ok; - std::tie(imported_ring, import_ok) = - ImportedRing::Import(mmap.mmap(), mmap.size); - EXPECT_TRUE(import_ok); - EXPECT_EQ(original_ring.record_size(), imported_ring.record_size()); - EXPECT_EQ(original_ring.record_count(), imported_ring.record_count()); - - { - uint32_t sequence = original_sequence_0; - ImportedRecord imported_record; - EXPECT_TRUE(imported_ring.Get(&sequence, &imported_record)); - EXPECT_EQ(original_sequence_0, sequence); - EXPECT_EQ(original_record_0, imported_record); - } - - { - uint32_t sequence = original_sequence_1; - ImportedRecord imported_record; - EXPECT_TRUE(imported_ring.Get(&sequence, &imported_record)); - EXPECT_EQ(original_sequence_1, sequence); - EXPECT_EQ(original_record_1, imported_record); - } - } -} - -TEST(BroadcastRingTest, ShouldImportIfCompatibleStaticToDynamic) { - using OriginalRing = typename Static_16_16x16::Ring; - using ImportedRing = typename Dynamic_16_NxM::Ring; - using OriginalRecord = typename OriginalRing::Record; - using ImportedRecord = typename ImportedRing::Record; - using StaticRing = OriginalRing; - - OriginalRing original_ring; - auto mmap = CreateRing(&original_ring, StaticRing::Traits::MinCount()); - - const uint32_t original_sequence_0 = original_ring.GetNextSequence(); - const uint32_t original_sequence_1 = original_ring.GetNextSequence() + 1; - const OriginalRecord original_record_0 = OriginalRecord::Pattern(0x00); - const OriginalRecord original_record_1 = OriginalRecord::Pattern(0x80); - original_ring.Put(original_record_0); - original_ring.Put(original_record_1); - - { - ImportedRing imported_ring; - bool import_ok; - std::tie(imported_ring, import_ok) = - ImportedRing::Import(mmap.mmap(), mmap.size); - EXPECT_TRUE(import_ok); - EXPECT_EQ(original_ring.record_size(), imported_ring.record_size()); - EXPECT_EQ(original_ring.record_count(), imported_ring.record_count()); - - { - uint32_t sequence = original_sequence_0; - ImportedRecord imported_record; - EXPECT_TRUE(imported_ring.Get(&sequence, &imported_record)); - EXPECT_EQ(original_sequence_0, sequence); - EXPECT_EQ(original_record_0, imported_record); - } - - { - uint32_t sequence = original_sequence_1; - ImportedRecord imported_record; - EXPECT_TRUE(imported_ring.Get(&sequence, &imported_record)); - EXPECT_EQ(original_sequence_1, sequence); - EXPECT_EQ(original_record_1, imported_record); - } - } -} - -TEST(BroadcastRingTest, ShouldImportIfReadonlyMmap) { - using Ring = Dynamic_32_NxM::Ring; - using Record = Ring::Record; - - uint32_t record_count = Ring::Traits::MinCount(); - size_t ring_size = Ring::MemorySize(record_count); - - size_t page_size = sysconf(_SC_PAGESIZE); - size_t mmap_size = (ring_size + (page_size - 1)) & ~(page_size - 1); - ASSERT_GE(mmap_size, ring_size); - - void* mmap_base = mmap(nullptr, mmap_size, PROT_READ | PROT_WRITE, - MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); - ASSERT_NE(MAP_FAILED, mmap_base); - - Ring ring = Ring::Create(mmap_base, mmap_size, record_count); - for (uint32_t i = 0; i < record_count; ++i) ring.Put(Record(FillChar(i))); - - ASSERT_EQ(0, mprotect(mmap_base, mmap_size, PROT_READ)); - - { - Ring imported_ring; - bool import_ok; - std::tie(imported_ring, import_ok) = Ring::Import(mmap_base, mmap_size); - EXPECT_TRUE(import_ok); - EXPECT_EQ(ring.record_size(), imported_ring.record_size()); - EXPECT_EQ(ring.record_count(), imported_ring.record_count()); - - uint32_t oldest_sequence = imported_ring.GetOldestSequence(); - for (uint32_t i = 0; i < record_count; ++i) { - uint32_t sequence = oldest_sequence + i; - Record record; - EXPECT_TRUE(imported_ring.Get(&sequence, &record)); - EXPECT_EQ(Record(FillChar(i)), record); - } - } - - ASSERT_EQ(0, munmap(mmap_base, mmap_size)); -} - -TEST(BroadcastRingTest, ShouldDieIfPutReadonlyMmap) { - using Ring = Dynamic_32_NxM::Ring; - using Record = Ring::Record; - - uint32_t record_count = Ring::Traits::MinCount(); - size_t ring_size = Ring::MemorySize(record_count); - - size_t page_size = sysconf(_SC_PAGESIZE); - size_t mmap_size = (ring_size + (page_size - 1)) & ~(page_size - 1); - ASSERT_GE(mmap_size, ring_size); - - void* mmap_base = mmap(nullptr, mmap_size, PROT_READ | PROT_WRITE, - MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); - ASSERT_NE(MAP_FAILED, mmap_base); - - Ring ring = Ring::Create(mmap_base, mmap_size, record_count); - for (uint32_t i = 0; i < record_count; ++i) ring.Put(Record(FillChar(i))); - - ASSERT_EQ(0, mprotect(mmap_base, mmap_size, PROT_READ)); - - EXPECT_DEATH_IF_SUPPORTED({ ring.Put(Record(7)); }, ""); - - ASSERT_EQ(0, munmap(mmap_base, mmap_size)); -} - -TEST(BroadcastRingTest, ShouldDieIfCreationMmapTooSmall) { - using Ring = Dynamic_32_NxM::Ring; - using Record = Ring::Record; - - uint32_t record_count = Ring::Traits::MinCount(); - size_t ring_size = Ring::MemorySize(record_count); - FakeMmap mmap(ring_size); - - EXPECT_DEATH_IF_SUPPORTED({ - Ring ring = Ring::Create(mmap.mmap(), ring_size - 1, record_count); - }, ""); - - Ring ring = Ring::Create(mmap.mmap(), ring_size, record_count); - - ring.Put(Record(3)); - - { - uint32_t sequence = ring.GetNewestSequence(); - Record record; - EXPECT_TRUE(ring.Get(&sequence, &record)); - EXPECT_EQ(Record(3), record); - } -} - -TEST(BroadcastRingTest, ShouldDieIfCreationMmapMisaligned) { - using Ring = Static_8_8x1::Ring; - using Record = Ring::Record; - - constexpr int kAlign = Ring::mmap_alignment(); - constexpr int kMisalign = kAlign / 2; - size_t ring_size = Ring::MemorySize(); - std::unique_ptr<char[]> buf(new char[ring_size + kMisalign]); - - EXPECT_DEATH_IF_SUPPORTED( - { Ring ring = Ring::Create(buf.get() + kMisalign, ring_size); }, ""); - - Ring ring = Ring::Create(buf.get(), ring_size); - - ring.Put(Record(3)); - - { - uint32_t sequence = ring.GetNewestSequence(); - Record record; - EXPECT_TRUE(ring.Get(&sequence, &record)); - EXPECT_EQ(Record(3), record); - } -} - -template <typename Ring> -std::unique_ptr<std::thread> CopyTask(std::atomic<bool>* quit, void* in_base, - size_t in_size, void* out_base, - size_t out_size) { - return std::unique_ptr<std::thread>( - new std::thread([quit, in_base, in_size, out_base, out_size]() { - using Record = typename Ring::Record; - - bool import_ok; - Ring in_ring; - Ring out_ring; - std::tie(in_ring, import_ok) = Ring::Import(in_base, in_size); - ASSERT_TRUE(import_ok); - std::tie(out_ring, import_ok) = Ring::Import(out_base, out_size); - ASSERT_TRUE(import_ok); - - uint32_t sequence = in_ring.GetOldestSequence(); - while (!std::atomic_load_explicit(quit, std::memory_order_relaxed)) { - Record record; - if (in_ring.Get(&sequence, &record)) { - out_ring.Put(record); - sequence++; - } - } - })); -} - -TEST(BroadcastRingTest, ThreadedCopySingle) { - using Ring = Dynamic_32_NxM::Ring; - using Record = Ring::Record; - Ring in_ring; - auto in_mmap = CreateRing(&in_ring, Ring::Traits::MinCount()); - - Ring out_ring; - auto out_mmap = CreateRing(&out_ring, Ring::Traits::MinCount()); - - std::atomic<bool> quit(false); - std::unique_ptr<std::thread> copy_task = CopyTask<Ring>( - &quit, out_mmap.mmap(), out_mmap.size, in_mmap.mmap(), in_mmap.size); - - const Record out_record(0x1c); - out_ring.Put(out_record); - - uint32_t in_sequence = in_ring.GetOldestSequence(); - Record in_record; - while (!in_ring.Get(&in_sequence, &in_record)) { - // Do nothing. - } - - EXPECT_EQ(out_record, in_record); - std::atomic_store_explicit(&quit, true, std::memory_order_relaxed); - copy_task->join(); -} - -TEST(BroadcastRingTest, ThreadedCopyLossless) { - using Ring = Dynamic_32_NxM::Ring; - using Record = Ring::Record; - Ring in_ring; - auto in_mmap = CreateRing(&in_ring, Ring::Traits::MinCount()); - - Ring out_ring; - auto out_mmap = CreateRing(&out_ring, Ring::Traits::MinCount()); - - std::atomic<bool> quit(false); - std::unique_ptr<std::thread> copy_task = CopyTask<Ring>( - &quit, out_mmap.mmap(), out_mmap.size, in_mmap.mmap(), in_mmap.size); - - constexpr uint32_t kRecordsToProcess = 10000; - uint32_t out_records = 0; - uint32_t in_records = 0; - uint32_t in_sequence = in_ring.GetNextSequence(); - while (out_records < kRecordsToProcess || in_records < kRecordsToProcess) { - if (out_records < kRecordsToProcess && - out_records - in_records < out_ring.record_count()) { - const Record out_record(FillChar(out_records)); - out_ring.Put(out_record); - out_records++; - } - - Record in_record; - while (in_ring.Get(&in_sequence, &in_record)) { - EXPECT_EQ(Record(FillChar(in_records)), in_record); - in_records++; - in_sequence++; - } - } - - EXPECT_EQ(kRecordsToProcess, out_records); - EXPECT_EQ(kRecordsToProcess, in_records); - - std::atomic_store_explicit(&quit, true, std::memory_order_relaxed); - copy_task->join(); -} - -TEST(BroadcastRingTest, ThreadedCopyLossy) { - using Ring = Dynamic_32_NxM::Ring; - using Record = Ring::Record; - Ring in_ring; - auto in_mmap = CreateRing(&in_ring, Ring::Traits::MinCount()); - - Ring out_ring; - auto out_mmap = CreateRing(&out_ring, Ring::Traits::MinCount()); - - std::atomic<bool> quit(false); - std::unique_ptr<std::thread> copy_task = CopyTask<Ring>( - &quit, out_mmap.mmap(), out_mmap.size, in_mmap.mmap(), in_mmap.size); - - constexpr uint32_t kRecordsToProcess = 100000; - uint32_t out_records = 0; - uint32_t in_records = 0; - uint32_t in_sequence = in_ring.GetNextSequence(); - while (out_records < kRecordsToProcess) { - const Record out_record(FillChar(out_records)); - out_ring.Put(out_record); - out_records++; - - Record in_record; - if (in_ring.GetNewest(&in_sequence, &in_record)) { - EXPECT_EQ(Record(in_record.v[0]), in_record); - in_records++; - in_sequence++; - } - } - - EXPECT_EQ(kRecordsToProcess, out_records); - EXPECT_GE(kRecordsToProcess, in_records); - - std::atomic_store_explicit(&quit, true, std::memory_order_relaxed); - copy_task->join(); -} - -template <typename Ring> -std::unique_ptr<std::thread> CheckFillTask(std::atomic<bool>* quit, - void* in_base, size_t in_size) { - return std::unique_ptr<std::thread>( - new std::thread([quit, in_base, in_size]() { - using Record = typename Ring::Record; - - bool import_ok; - Ring in_ring; - std::tie(in_ring, import_ok) = Ring::Import(in_base, in_size); - ASSERT_TRUE(import_ok); - - uint32_t sequence = in_ring.GetOldestSequence(); - while (!std::atomic_load_explicit(quit, std::memory_order_relaxed)) { - Record record; - if (in_ring.Get(&sequence, &record)) { - ASSERT_EQ(Record(record.v[0]), record); - sequence++; - } - } - })); -} - -template <typename Ring> -void ThreadedOverwriteTorture() { - using Record = typename Ring::Record; - - // Maximize overwrites by having few records. - const int kMinRecordCount = 1; - const int kMaxRecordCount = 4; - - for (int count = kMinRecordCount; count <= kMaxRecordCount; count *= 2) { - Ring out_ring; - auto out_mmap = CreateRing(&out_ring, count); - - std::atomic<bool> quit(false); - std::unique_ptr<std::thread> check_task = - CheckFillTask<Ring>(&quit, out_mmap.mmap(), out_mmap.size); - - constexpr int kIterations = 10000; - for (int i = 0; i < kIterations; ++i) { - const Record record(FillChar(i)); - out_ring.Put(record); - } - - std::atomic_store_explicit(&quit, true, std::memory_order_relaxed); - check_task->join(); - } -} - -TEST(BroadcastRingTest, ThreadedOverwriteTortureSmall) { - ThreadedOverwriteTorture<Dynamic_16_NxM_1plus0::Ring>(); -} - -TEST(BroadcastRingTest, ThreadedOverwriteTortureLarge) { - ThreadedOverwriteTorture<Dynamic_256_NxM_1plus0::Ring>(); -} - -} // namespace dvr -} // namespace android diff --git a/libs/vr/libbroadcastring/include/libbroadcastring/broadcast_ring.h b/libs/vr/libbroadcastring/include/libbroadcastring/broadcast_ring.h deleted file mode 100644 index f2e5034879..0000000000 --- a/libs/vr/libbroadcastring/include/libbroadcastring/broadcast_ring.h +++ /dev/null @@ -1,692 +0,0 @@ -#ifndef ANDROID_DVR_BROADCAST_RING_H_ -#define ANDROID_DVR_BROADCAST_RING_H_ - -#include <inttypes.h> -#include <stddef.h> -#include <stdio.h> -#include <atomic> -#include <limits> -#include <tuple> -#include <type_traits> -#include <utility> - -#include "android-base/logging.h" - -#if ATOMIC_LONG_LOCK_FREE != 2 || ATOMIC_INT_LOCK_FREE != 2 -#error "This file requires lock free atomic uint32_t and long" -#endif - -namespace android { -namespace dvr { - -struct DefaultRingTraits { - // Set this to false to allow compatibly expanding the record size. - static constexpr bool kUseStaticRecordSize = false; - - // Set this to a nonzero value to fix the number of records in the ring. - static constexpr uint32_t kStaticRecordCount = 0; - - // Set this to the max number of records that can be written simultaneously. - static constexpr uint32_t kMaxReservedRecords = 1; - - // Set this to the min number of records that must be readable. - static constexpr uint32_t kMinAvailableRecords = 1; -}; - -// Nonblocking ring suitable for concurrent single-writer, multi-reader access. -// -// Readers never block the writer and thus this is a nondeterministically lossy -// transport in the absence of external synchronization. Don't use this as a -// transport when deterministic behavior is required. -// -// Readers may have a read-only mapping; each reader's state is a single local -// sequence number. -// -// The implementation takes care to avoid data races on record access. -// Inconsistent data can only be returned if at least 2^32 records are written -// during the read-side critical section. -// -// In addition, both readers and the writer are careful to avoid accesses -// outside the bounds of the mmap area passed in during initialization even if -// there is a misbehaving or malicious task with write access to the mmap area. -// -// When dynamic record size is enabled, readers use the record size in the ring -// header when indexing the ring, so that it is possible to extend the record -// type without breaking the read-side ABI. -// -// Avoid calling Put() in a tight loop; there should be significantly more time -// between successive puts than it takes to read one record from memory to -// ensure Get() completes quickly. This requirement should not be difficult to -// achieve for most practical uses; 4kB puts at 10,000Hz is well below the -// scaling limit on current mobile chips. -// -// Example Writer Usage: -// -// using Record = MyRecordType; -// using Ring = BroadcastRing<Record>; -// -// uint32_t record_count = kMyDesiredCount; -// uint32_t ring_size = Ring::MemorySize(record_count); -// -// size_t page_size = sysconf(_SC_PAGESIZE); -// uint32_t mmap_size = (ring_size + (page_size - 1)) & ~(page_size - 1); -// -// // Allocate & map via your preferred mechanism, e.g. -// int fd = open("/dev/shm/ring_test", O_CREAT|O_RDWR|O_CLOEXEC, 0600); -// CHECK(fd >= 0); -// CHECK(!ftruncate(fd, ring_size)); -// void *mmap_base = mmap(nullptr, mmap_size, PROT_READ|PROT_WRITE, -// MAP_SHARED, fd, 0); -// CHECK(mmap_base != MAP_FAILED); -// close(fd); -// -// Ring ring = Ring::Create(mmap_base, mmap_size, record_count); -// -// while (!done) -// ring.Put(BuildNextRecordBlocking()); -// -// CHECK(!munmap(mmap_base, mmap_size)); -// -// Example Reader Usage: -// -// using Record = MyRecordType; -// using Ring = BroadcastRing<Record>; -// -// // Map via your preferred mechanism, e.g. -// int fd = open("/dev/shm/ring_test", O_RDONLY|O_CLOEXEC); -// CHECK(fd >= 0); -// struct stat st; -// CHECK(!fstat(fd, &st)); -// size_t mmap_size = st.st_size; -// void *mmap_base = mmap(nullptr, mmap_size, PROT_READ, -// MAP_SHARED, fd, 0); -// CHECK(mmap_base != MAP_FAILED); -// close(fd); -// -// Ring ring; -// bool import_ok; -// std::tie(ring, import_ok) = Ring::Import(mmap_base, mmap_size); -// CHECK(import_ok); -// -// uint32_t sequence; -// -// // Choose starting point (using "0" is unpredictable but not dangerous) -// sequence = ring.GetOldestSequence(); // The oldest available -// sequence = ring.GetNewestSequence(); // The newest available -// sequence = ring.GetNextSequence(); // The next one produced -// -// while (!done) { -// Record record; -// -// if (you_want_to_process_all_available_records) { -// while (ring.Get(&sequence, &record)) { -// ProcessRecord(sequence, record); -// sequence++; -// } -// } else if (you_want_to_skip_to_the_newest_record) { -// if (ring.GetNewest(&sequence, &record)) { -// ProcessRecord(sequence, record); -// sequence++; -// } -// } -// -// DoSomethingExpensiveOrBlocking(); -// } -// -// CHECK(!munmap(mmap_base, mmap_size)); -// -template <typename RecordType, typename BaseTraits = DefaultRingTraits> -class BroadcastRing { - public: - using Record = RecordType; - struct Traits : public BaseTraits { - // Must have enough space for writers, plus enough space for readers. - static constexpr int kMinRecordCount = - BaseTraits::kMaxReservedRecords + BaseTraits::kMinAvailableRecords; - - // Count of zero means dynamic, non-zero means static. - static constexpr bool kUseStaticRecordCount = - (BaseTraits::kStaticRecordCount != 0); - - // If both record size and count are static then the overall size is too. - static constexpr bool kIsStaticSize = - BaseTraits::kUseStaticRecordSize && kUseStaticRecordCount; - }; - - static constexpr bool IsPowerOfTwo(uint32_t size) { - return (size & (size - 1)) == 0; - } - - // Sanity check the options provided in Traits. - static_assert(Traits::kMinRecordCount >= 1, "Min record count too small"); - static_assert(!Traits::kUseStaticRecordCount || - Traits::kStaticRecordCount >= Traits::kMinRecordCount, - "Static record count is too small"); - static_assert(!Traits::kStaticRecordCount || - IsPowerOfTwo(Traits::kStaticRecordCount), - "Static record count is not a power of two"); - static_assert(std::is_standard_layout<Record>::value, - "Record type must be standard layout"); - - BroadcastRing() {} - - // Creates a new ring at |mmap| with |record_count| records. - // - // There must be at least |MemorySize(record_count)| bytes of space already - // allocated at |mmap|. The ring does not take ownership. - static BroadcastRing Create(void* mmap, size_t mmap_size, - uint32_t record_count) { - BroadcastRing ring(mmap); - CHECK(ring.ValidateGeometry(mmap_size, sizeof(Record), record_count)); - ring.InitializeHeader(sizeof(Record), record_count); - return ring; - } - - // Creates a new ring at |mmap|. - // - // There must be at least |MemorySize()| bytes of space already allocated at - // |mmap|. The ring does not take ownership. - static BroadcastRing Create(void* mmap, size_t mmap_size) { - return Create(mmap, mmap_size, - Traits::kUseStaticRecordCount - ? Traits::kStaticRecordCount - : BroadcastRing::GetRecordCount(mmap_size)); - } - - // Imports an existing ring at |mmap|. - // - // Import may fail if the ring parameters in the mmap header are not sensible. - // In this case the returned boolean is false; make sure to check this value. - static std::tuple<BroadcastRing, bool> Import(void* mmap, size_t mmap_size) { - BroadcastRing ring(mmap); - uint32_t record_size = 0; - uint32_t record_count = 0; - if (mmap_size >= sizeof(Header)) { - record_size = std::atomic_load_explicit(&ring.header_mmap()->record_size, - std::memory_order_relaxed); - record_count = std::atomic_load_explicit( - &ring.header_mmap()->record_count, std::memory_order_relaxed); - } - bool ok = ring.ValidateGeometry(mmap_size, record_size, record_count); - return std::make_tuple(ring, ok); - } - - ~BroadcastRing() {} - - // Calculates the space necessary for a ring of size |record_count|. - // - // Use this function for dynamically sized rings. - static constexpr size_t MemorySize(uint32_t record_count) { - return sizeof(Header) + sizeof(Record) * record_count; - } - - // Calculates the space necessary for a statically sized ring. - // - // Use this function for statically sized rings. - static constexpr size_t MemorySize() { - static_assert( - Traits::kUseStaticRecordCount, - "Wrong MemorySize() function called for dynamic record count"); - return MemorySize(Traits::kStaticRecordCount); - } - - static uint32_t NextPowerOf2(uint32_t n) { - if (n == 0) - return 0; - n -= 1; - n |= n >> 16; - n |= n >> 8; - n |= n >> 4; - n |= n >> 2; - n |= n >> 1; - return n + 1; - } - - // Gets the biggest power of 2 record count that can fit into this mmap. - // - // The header size has been taken into account. - static uint32_t GetRecordCount(size_t mmap_size) { - if (mmap_size <= sizeof(Header)) { - return 0; - } - uint32_t count = - static_cast<uint32_t>((mmap_size - sizeof(Header)) / sizeof(Record)); - return IsPowerOfTwo(count) ? count : (NextPowerOf2(count) / 2); - } - - // Writes a record to the ring. - // - // The oldest record is overwritten unless the ring is not already full. - void Put(const Record& record) { - const int kRecordCount = 1; - Reserve(kRecordCount); - Geometry geometry = GetGeometry(); - PutRecordInternal(&record, record_mmap_writer(geometry.tail_index)); - Publish(kRecordCount); - } - - // Gets sequence number of the oldest currently available record. - uint32_t GetOldestSequence() const { - return std::atomic_load_explicit(&header_mmap()->head, - std::memory_order_relaxed); - } - - // Gets sequence number of the first future record. - // - // If the returned value is passed to Get() and there is no concurrent Put(), - // Get() will return false. - uint32_t GetNextSequence() const { - return std::atomic_load_explicit(&header_mmap()->tail, - std::memory_order_relaxed); - } - - // Gets sequence number of the newest currently available record. - uint32_t GetNewestSequence() const { return GetNextSequence() - 1; } - - // Copies the oldest available record with sequence at least |*sequence| to - // |record|. - // - // Returns false if there is no recent enough record available. - // - // Updates |*sequence| with the sequence number of the record returned. To get - // the following record, increment this number by one. - // - // This function synchronizes with two other operations: - // - // (1) Load-Acquire of |tail| - // - // Together with the store-release in Publish(), this load-acquire - // ensures each store to a record in PutRecordInternal() happens-before - // any corresponding load in GetRecordInternal(). - // - // i.e. the stores for the records with sequence numbers < |tail| have - // completed from our perspective - // - // (2) Acquire Fence between record access & final load of |head| - // - // Together with the release fence in Reserve(), this ensures that if - // GetRecordInternal() loads a value stored in some execution of - // PutRecordInternal(), then the store of |head| in the Reserve() that - // preceeded it happens-before our final load of |head|. - // - // i.e. if we read a record with sequence number >= |final_head| then - // no later store to that record has completed from our perspective - bool Get(uint32_t* sequence /*inout*/, Record* record /*out*/) const { - for (;;) { - uint32_t tail = std::atomic_load_explicit(&header_mmap()->tail, - std::memory_order_acquire); - uint32_t head = std::atomic_load_explicit(&header_mmap()->head, - std::memory_order_relaxed); - - if (tail - head > record_count()) - continue; // Concurrent modification; re-try. - - if (*sequence - head > tail - head) - *sequence = head; // Out of window, skip forward to first available. - - if (*sequence == tail) return false; // No new records available. - - Geometry geometry = - CalculateGeometry(record_count(), record_size(), *sequence, tail); - - // Compute address explicitly in case record_size > sizeof(Record). - RecordStorage* record_storage = record_mmap_reader(geometry.head_index); - - GetRecordInternal(record_storage, record); - - // NB: It is not sufficient to change this to a load-acquire of |head|. - std::atomic_thread_fence(std::memory_order_acquire); - - uint32_t final_head = std::atomic_load_explicit( - &header_mmap()->head, std::memory_order_relaxed); - - if (final_head - head > *sequence - head) - continue; // Concurrent modification; re-try. - - // Note: Combining the above 4 comparisons gives: - // 0 <= final_head - head <= sequence - head < tail - head <= record_count - // - // We can also write this as: - // head <=* final_head <=* sequence <* tail <=* head + record_count - // - // where <* orders by difference from head: x <* y if x - head < y - head. - // This agrees with the order of sequence updates during "put" operations. - return true; - } - } - - // Copies the newest available record with sequence at least |*sequence| to - // |record|. - // - // Returns false if there is no recent enough record available. - // - // Updates |*sequence| with the sequence number of the record returned. To get - // the following record, increment this number by one. - bool GetNewest(uint32_t* sequence, Record* record) const { - uint32_t newest_sequence = GetNewestSequence(); - if (*sequence == newest_sequence + 1) return false; - *sequence = newest_sequence; - return Get(sequence, record); - } - - // Returns true if this instance has been created or imported. - bool is_valid() const { return !!data_.mmap; } - - uint32_t record_count() const { return record_count_internal(); } - uint32_t record_size() const { return record_size_internal(); } - static constexpr uint32_t mmap_alignment() { return alignof(Mmap); } - - private: - struct Header { - // Record size for reading out of the ring. Writers always write the full - // length; readers may need to read a prefix of each record. - std::atomic<uint32_t> record_size; - - // Number of records in the ring. - std::atomic<uint32_t> record_count; - - // Readable region is [head % record_count, tail % record_count). - // - // The region in [tail % record_count, head % record_count) was either never - // populated or is being updated. - // - // These are sequences numbers, not indexes - indexes should be computed - // with a modulus. - // - // To ensure consistency: - // - // (1) Writes advance |head| past any updated records before writing to - // them, and advance |tail| after they are written. - // (2) Readers check |tail| before reading data and |head| after, - // making sure to discard any data that was written to concurrently. - std::atomic<uint32_t> head; - std::atomic<uint32_t> tail; - }; - - // Store using the standard word size. - using StorageType = long; // NOLINT - - // Always require 8 byte alignment so that the same record sizes are legal on - // 32 and 64 bit builds. - static constexpr size_t kRecordAlignment = 8; - static_assert(kRecordAlignment % sizeof(StorageType) == 0, - "Bad record alignment"); - - struct RecordStorage { - // This is accessed with relaxed atomics to prevent data races on the - // contained data, which would be undefined behavior. - std::atomic<StorageType> data[sizeof(Record) / sizeof(StorageType)]; - }; - - static_assert(sizeof(StorageType) * - std::extent<decltype(RecordStorage::data)>() == - sizeof(Record), - "Record length must be a multiple of sizeof(StorageType)"); - - struct Geometry { - // Static geometry. - uint32_t record_count; - uint32_t record_size; - - // Copy of atomic sequence counts. - uint32_t head; - uint32_t tail; - - // First index of readable region. - uint32_t head_index; - - // First index of writable region. - uint32_t tail_index; - - // Number of records in readable region. - uint32_t count; - - // Number of records in writable region. - uint32_t space; - }; - - // Mmap area layout. - // - // Readers should not index directly into |records| as this is not valid when - // dynamic record sizes are used; use record_mmap_reader() instead. - struct Mmap { - Header header; - RecordStorage records[]; - }; - - static_assert(std::is_standard_layout<Mmap>::value, - "Mmap must be standard layout"); - static_assert(sizeof(std::atomic<uint32_t>) == sizeof(uint32_t), - "Lockless atomics contain extra state"); - static_assert(sizeof(std::atomic<StorageType>) == sizeof(StorageType), - "Lockless atomics contain extra state"); - - explicit BroadcastRing(void* mmap) { - CHECK_EQ(0U, reinterpret_cast<uintptr_t>(mmap) % alignof(Mmap)); - data_.mmap = reinterpret_cast<Mmap*>(mmap); - } - - // Initializes the mmap area header for a new ring. - void InitializeHeader(uint32_t record_size, uint32_t record_count) { - constexpr uint32_t kInitialSequence = -256; // Force an early wrap. - std::atomic_store_explicit(&header_mmap()->record_size, record_size, - std::memory_order_relaxed); - std::atomic_store_explicit(&header_mmap()->record_count, record_count, - std::memory_order_relaxed); - std::atomic_store_explicit(&header_mmap()->head, kInitialSequence, - std::memory_order_relaxed); - std::atomic_store_explicit(&header_mmap()->tail, kInitialSequence, - std::memory_order_relaxed); - } - - // Validates ring geometry. - // - // Ring geometry is validated carefully on import and then cached. This allows - // us to avoid out-of-range accesses even if the parameters in the header are - // later changed. - bool ValidateGeometry(size_t mmap_size, uint32_t header_record_size, - uint32_t header_record_count) { - set_record_size(header_record_size); - set_record_count(header_record_count); - - if (record_size() != header_record_size) return false; - if (record_count() != header_record_count) return false; - if (record_count() < Traits::kMinRecordCount) return false; - if (record_size() < sizeof(Record)) return false; - if (record_size() % kRecordAlignment != 0) return false; - if (!IsPowerOfTwo(record_count())) return false; - - size_t memory_size = record_count() * record_size(); - if (memory_size / record_size() != record_count()) return false; - if (memory_size + sizeof(Header) < memory_size) return false; - if (memory_size + sizeof(Header) > mmap_size) return false; - - return true; - } - - // Copies a record into the ring. - // - // This is done with relaxed atomics because otherwise it is racy according to - // the C++ memory model. This is very low overhead once optimized. - static inline void PutRecordInternal(const Record* in, RecordStorage* out) { - StorageType data[sizeof(Record) / sizeof(StorageType)]; - memcpy(data, in, sizeof(*in)); - for (size_t i = 0; i < std::extent<decltype(data)>(); ++i) { - std::atomic_store_explicit(&out->data[i], data[i], - std::memory_order_relaxed); - } - } - - // Copies a record out of the ring. - // - // This is done with relaxed atomics because otherwise it is racy according to - // the C++ memory model. This is very low overhead once optimized. - static inline void GetRecordInternal(RecordStorage* in, Record* out) { - StorageType data[sizeof(Record) / sizeof(StorageType)]; - for (size_t i = 0; i < std::extent<decltype(data)>(); ++i) { - data[i] = - std::atomic_load_explicit(&in->data[i], std::memory_order_relaxed); - } - memcpy(out, &data, sizeof(*out)); - } - - // Converts a record's sequence number into a storage index. - static uint32_t SequenceToIndex(uint32_t sequence, uint32_t record_count) { - return sequence & (record_count - 1); - } - - // Computes readable & writable ranges from ring parameters. - static Geometry CalculateGeometry(uint32_t record_count, uint32_t record_size, - uint32_t head, uint32_t tail) { - Geometry geometry; - geometry.record_count = record_count; - geometry.record_size = record_size; - DCHECK_EQ(0U, geometry.record_size % kRecordAlignment); - geometry.head = head; - geometry.tail = tail; - geometry.head_index = SequenceToIndex(head, record_count); - geometry.tail_index = SequenceToIndex(tail, record_count); - geometry.count = geometry.tail - geometry.head; - DCHECK_LE(geometry.count, record_count); - geometry.space = geometry.record_count - geometry.count; - return geometry; - } - - // Gets the current ring readable & writable regions. - // - // This this is always safe from the writing thread since it is the only - // thread allowed to update the header. - Geometry GetGeometry() const { - return CalculateGeometry( - record_count(), record_size(), - std::atomic_load_explicit(&header_mmap()->head, - std::memory_order_relaxed), - std::atomic_load_explicit(&header_mmap()->tail, - std::memory_order_relaxed)); - } - - // Makes space for at least |reserve_count| records. - // - // There is nothing to prevent overwriting records that have concurrent - // readers. We do however ensure that this situation can be detected: the - // fence ensures the |head| update will be the first update seen by readers, - // and readers check this value after reading and discard data that may have - // been concurrently modified. - void Reserve(uint32_t reserve_count) { - Geometry geometry = GetGeometry(); - DCHECK_LE(reserve_count, Traits::kMaxReservedRecords); - uint32_t needed = - (geometry.space >= reserve_count ? 0 : reserve_count - geometry.space); - - std::atomic_store_explicit(&header_mmap()->head, geometry.head + needed, - std::memory_order_relaxed); - - // NB: It is not sufficient to change this to a store-release of |head|. - std::atomic_thread_fence(std::memory_order_release); - } - - // Makes |publish_count| records visible to readers. - // - // Space must have been reserved by a previous call to Reserve(). - void Publish(uint32_t publish_count) { - Geometry geometry = GetGeometry(); - DCHECK_LE(publish_count, geometry.space); - std::atomic_store_explicit(&header_mmap()->tail, - geometry.tail + publish_count, - std::memory_order_release); - } - - // Helpers to compute addresses in mmap area. - Mmap* mmap() const { return data_.mmap; } - Header* header_mmap() const { return &data_.mmap->header; } - RecordStorage* record_mmap_writer(uint32_t index) const { - DCHECK_EQ(sizeof(Record), record_size()); - return &data_.mmap->records[index]; - } - RecordStorage* record_mmap_reader(uint32_t index) const { - if (Traits::kUseStaticRecordSize) { - return &data_.mmap->records[index]; - } else { - // Calculate the location of a record in the ring without assuming that - // sizeof(Record) == record_size. - return reinterpret_cast<RecordStorage*>( - reinterpret_cast<char*>(data_.mmap->records) + index * record_size()); - } - } - - // The following horrifying template gunk enables us to store just the mmap - // base pointer for compile-time statically sized rings. Dynamically sized - // rings also store the validated copy of the record size & count. - // - // This boils down to: use a compile time constant if available, and otherwise - // load the value that was validated on import from a member variable. - template <typename T = Traits> - typename std::enable_if<T::kUseStaticRecordSize, uint32_t>::type - record_size_internal() const { - return sizeof(Record); - } - - template <typename T = Traits> - typename std::enable_if<!T::kUseStaticRecordSize, uint32_t>::type - record_size_internal() const { - return data_.record_size; - } - - template <typename T = Traits> - typename std::enable_if<T::kUseStaticRecordSize, void>::type set_record_size( - uint32_t /*record_size*/) {} - - template <typename T = Traits> - typename std::enable_if<!T::kUseStaticRecordSize, void>::type set_record_size( - uint32_t record_size) { - data_.record_size = record_size; - } - - template <typename T = Traits> - typename std::enable_if<T::kUseStaticRecordCount, uint32_t>::type - record_count_internal() const { - return Traits::kStaticRecordCount; - } - - template <typename T = Traits> - typename std::enable_if<!T::kUseStaticRecordCount, uint32_t>::type - record_count_internal() const { - return data_.record_count; - } - - template <typename T = Traits> - typename std::enable_if<T::kUseStaticRecordCount, void>::type - set_record_count(uint32_t /*record_count*/) const {} - - template <typename T = Traits> - typename std::enable_if<!T::kUseStaticRecordCount, void>::type - set_record_count(uint32_t record_count) { - data_.record_count = record_count; - } - - // Data we need to store for statically sized rings. - struct DataStaticSize { - Mmap* mmap = nullptr; - }; - - // Data we need to store for dynamically sized rings. - struct DataDynamicSize { - Mmap* mmap = nullptr; - - // These are cached to make sure misbehaving writers cannot cause - // out-of-bounds memory accesses by updating the values in the mmap header. - uint32_t record_size = 0; - uint32_t record_count = 0; - }; - - using DataStaticOrDynamic = - typename std::conditional<Traits::kIsStaticSize, DataStaticSize, - DataDynamicSize>::type; - - DataStaticOrDynamic data_; -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_BROADCAST_RING_H_ diff --git a/libs/vr/libbufferhub/Android.bp b/libs/vr/libbufferhub/Android.bp deleted file mode 100644 index 583ad1dd94..0000000000 --- a/libs/vr/libbufferhub/Android.bp +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (C) 2016 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "frameworks_native_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["frameworks_native_license"], -} - -cc_library_headers { - name: "libbufferhub_headers", - export_include_dirs: ["include"], - vendor_available: true, // TODO(b/112338314): Does shouldn't be available to vendor. - apex_available: [ - "//apex_available:platform", - "com.android.media", - "com.android.media.swcodec", - ], - min_sdk_version: "29", -} - -sourceFiles = [ - "buffer_hub_base.cpp", - "buffer_hub_rpc.cpp", - "consumer_buffer.cpp", - "ion_buffer.cpp", - "producer_buffer.cpp", -] - -sharedLibraries = [ - "libbase", - "libcutils", - "liblog", - "libui", - "libutils", - "libpdx_default_transport", -] - -headerLibraries = [ - "libbufferhub_headers", - "libdvr_headers", - "libnativebase_headers", -] - -cc_library { - srcs: sourceFiles, - cflags: [ - "-DLOG_TAG=\"libbufferhub\"", - "-DTRACE=0", - "-DATRACE_TAG=ATRACE_TAG_GRAPHICS", - "-Wall", - "-Werror", - ], - shared_libs: sharedLibraries, - header_libs: headerLibraries, - name: "libbufferhub", - export_header_lib_headers: [ - "libbufferhub_headers", - "libnativebase_headers", - ], -} - -cc_test { - srcs: ["buffer_hub-test.cpp"], - static_libs: ["libbufferhub"], - shared_libs: sharedLibraries, - header_libs: headerLibraries, - name: "buffer_hub-test", -} diff --git a/libs/vr/libbufferhub/buffer_hub-test.cpp b/libs/vr/libbufferhub/buffer_hub-test.cpp deleted file mode 100644 index 27ab0242ad..0000000000 --- a/libs/vr/libbufferhub/buffer_hub-test.cpp +++ /dev/null @@ -1,906 +0,0 @@ -#include <gtest/gtest.h> -#include <poll.h> -#include <private/dvr/bufferhub_rpc.h> -#include <private/dvr/consumer_buffer.h> -#include <private/dvr/producer_buffer.h> -#include <sys/epoll.h> -#include <sys/eventfd.h> -#include <ui/BufferHubDefs.h> - -#include <mutex> -#include <thread> - -namespace { -#define RETRY_EINTR(fnc_call) \ - ([&]() -> decltype(fnc_call) { \ - decltype(fnc_call) result; \ - do { \ - result = (fnc_call); \ - } while (result == -1 && errno == EINTR); \ - return result; \ - })() - -using android::BufferHubDefs::isAnyClientAcquired; -using android::BufferHubDefs::isAnyClientGained; -using android::BufferHubDefs::isAnyClientPosted; -using android::BufferHubDefs::isClientAcquired; -using android::BufferHubDefs::isClientPosted; -using android::BufferHubDefs::isClientReleased; -using android::BufferHubDefs::kFirstClientBitMask; -using android::dvr::ConsumerBuffer; -using android::dvr::ProducerBuffer; -using android::pdx::LocalHandle; -using android::pdx::Status; -using LibBufferHubTest = ::testing::Test; - -const int kWidth = 640; -const int kHeight = 480; -const int kFormat = HAL_PIXEL_FORMAT_RGBA_8888; -const int kUsage = 0; -// Maximum number of consumers for the buffer that only has one producer in the -// test. -const size_t kMaxConsumerCount = - android::BufferHubDefs::kMaxNumberOfClients - 1; -const int kPollTimeoutMs = 100; - -// Helper function to poll the eventfd in BufferHubBase. -template <class BufferHubBase> -int PollBufferEvent(const std::unique_ptr<BufferHubBase>& buffer, - int timeout_ms = kPollTimeoutMs) { - pollfd p = {buffer->event_fd(), POLLIN, 0}; - return poll(&p, 1, timeout_ms); -} - -} // namespace - -TEST_F(LibBufferHubTest, TestBasicUsage) { - std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create( - kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t)); - ASSERT_TRUE(p.get() != nullptr); - std::unique_ptr<ConsumerBuffer> c1 = - ConsumerBuffer::Import(p->CreateConsumer()); - ASSERT_TRUE(c1.get() != nullptr); - // Check that consumers can spawn other consumers. - std::unique_ptr<ConsumerBuffer> c2 = - ConsumerBuffer::Import(c1->CreateConsumer()); - ASSERT_TRUE(c2.get() != nullptr); - - // Checks the state masks of client p, c1 and c2. - EXPECT_EQ(p->client_state_mask(), kFirstClientBitMask); - EXPECT_EQ(c1->client_state_mask(), kFirstClientBitMask << 1); - EXPECT_EQ(c2->client_state_mask(), kFirstClientBitMask << 2); - - // Initial state: producer not available, consumers not available. - EXPECT_EQ(0, RETRY_EINTR(PollBufferEvent(p))); - EXPECT_EQ(0, RETRY_EINTR(PollBufferEvent(c1))); - EXPECT_EQ(0, RETRY_EINTR(PollBufferEvent(c2))); - - EXPECT_EQ(0, p->GainAsync()); - EXPECT_EQ(0, p->Post(LocalHandle())); - - // New state: producer not available, consumers available. - EXPECT_EQ(0, RETRY_EINTR(PollBufferEvent(p))); - EXPECT_EQ(1, RETRY_EINTR(PollBufferEvent(c1))); - EXPECT_EQ(1, RETRY_EINTR(PollBufferEvent(c2))); - - LocalHandle fence; - EXPECT_EQ(0, c1->Acquire(&fence)); - EXPECT_EQ(0, RETRY_EINTR(PollBufferEvent(c1))); - EXPECT_EQ(1, RETRY_EINTR(PollBufferEvent(c2))); - - EXPECT_EQ(0, c2->Acquire(&fence)); - EXPECT_EQ(0, RETRY_EINTR(PollBufferEvent(c2))); - EXPECT_EQ(0, RETRY_EINTR(PollBufferEvent(c1))); - - EXPECT_EQ(0, c1->Release(LocalHandle())); - EXPECT_EQ(0, RETRY_EINTR(PollBufferEvent(p))); - EXPECT_EQ(0, c2->Discard()); - EXPECT_EQ(1, RETRY_EINTR(PollBufferEvent(p))); - - EXPECT_EQ(0, p->Gain(&fence)); - EXPECT_EQ(0, RETRY_EINTR(PollBufferEvent(p))); - EXPECT_EQ(0, RETRY_EINTR(PollBufferEvent(c1))); - EXPECT_EQ(0, RETRY_EINTR(PollBufferEvent(c2))); -} - -TEST_F(LibBufferHubTest, TestEpoll) { - std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create( - kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t)); - ASSERT_TRUE(p.get() != nullptr); - std::unique_ptr<ConsumerBuffer> c = - ConsumerBuffer::Import(p->CreateConsumer()); - ASSERT_TRUE(c.get() != nullptr); - - LocalHandle epoll_fd{epoll_create1(EPOLL_CLOEXEC)}; - ASSERT_TRUE(epoll_fd.IsValid()); - - epoll_event event; - std::array<epoll_event, 64> events; - - auto event_sources = p->GetEventSources(); - ASSERT_LT(event_sources.size(), events.size()); - - for (const auto& event_source : event_sources) { - event = {.events = event_source.event_mask | EPOLLET, - .data = {.fd = p->event_fd()}}; - ASSERT_EQ(0, epoll_ctl(epoll_fd.Get(), EPOLL_CTL_ADD, event_source.event_fd, - &event)); - } - - event_sources = c->GetEventSources(); - ASSERT_LT(event_sources.size(), events.size()); - - for (const auto& event_source : event_sources) { - event = {.events = event_source.event_mask | EPOLLET, - .data = {.fd = c->event_fd()}}; - ASSERT_EQ(0, epoll_ctl(epoll_fd.Get(), EPOLL_CTL_ADD, event_source.event_fd, - &event)); - } - - // No events should be signaled initially. - ASSERT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 0)); - - // Gain and post the producer and check for consumer signal. - EXPECT_EQ(0, p->GainAsync()); - EXPECT_EQ(0, p->Post({})); - ASSERT_EQ(1, epoll_wait(epoll_fd.Get(), events.data(), events.size(), - kPollTimeoutMs)); - ASSERT_TRUE(events[0].events & EPOLLIN); - ASSERT_EQ(c->event_fd(), events[0].data.fd); - - // Save the event bits to translate later. - event = events[0]; - - // Check for events again. Edge-triggered mode should prevent any. - EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), - kPollTimeoutMs)); - EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), - kPollTimeoutMs)); - EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), - kPollTimeoutMs)); - EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), - kPollTimeoutMs)); - - // Translate the events. - auto event_status = c->GetEventMask(event.events); - ASSERT_TRUE(event_status); - ASSERT_TRUE(event_status.get() & EPOLLIN); - - // Check for events again. Edge-triggered mode should prevent any. - EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), - kPollTimeoutMs)); -} - -TEST_F(LibBufferHubTest, TestStateMask) { - std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create( - kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t)); - ASSERT_TRUE(p.get() != nullptr); - - // It's ok to create up to kMaxConsumerCount consumer buffers. - uint32_t client_state_masks = p->client_state_mask(); - std::array<std::unique_ptr<ConsumerBuffer>, kMaxConsumerCount> cs; - for (size_t i = 0; i < kMaxConsumerCount; i++) { - cs[i] = ConsumerBuffer::Import(p->CreateConsumer()); - ASSERT_TRUE(cs[i].get() != nullptr); - // Expect all buffers have unique state mask. - EXPECT_EQ(client_state_masks & cs[i]->client_state_mask(), 0U); - client_state_masks |= cs[i]->client_state_mask(); - } - EXPECT_EQ(client_state_masks, ~0U); - - // The 64th creation will fail with out-of-memory error. - auto state = p->CreateConsumer(); - EXPECT_EQ(state.error(), E2BIG); - - // Release any consumer should allow us to re-create. - for (size_t i = 0; i < kMaxConsumerCount; i++) { - client_state_masks &= ~cs[i]->client_state_mask(); - cs[i] = nullptr; - cs[i] = ConsumerBuffer::Import(p->CreateConsumer()); - ASSERT_TRUE(cs[i].get() != nullptr); - // The released state mask will be reused. - EXPECT_EQ(client_state_masks & cs[i]->client_state_mask(), 0U); - client_state_masks |= cs[i]->client_state_mask(); - } -} - -TEST_F(LibBufferHubTest, TestStateTransitions) { - std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create( - kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t)); - ASSERT_TRUE(p.get() != nullptr); - std::unique_ptr<ConsumerBuffer> c = - ConsumerBuffer::Import(p->CreateConsumer()); - ASSERT_TRUE(c.get() != nullptr); - - LocalHandle fence; - EXPECT_EQ(0, p->GainAsync()); - - // Acquire in gained state should fail. - EXPECT_EQ(-EBUSY, c->Acquire(&fence)); - - // Post in gained state should succeed. - EXPECT_EQ(0, p->Post(LocalHandle())); - - // Post and gain in posted state should fail. - EXPECT_EQ(-EBUSY, p->Post(LocalHandle())); - EXPECT_EQ(-EBUSY, p->Gain(&fence)); - - // Acquire in posted state should succeed. - EXPECT_EQ(0, c->Acquire(&fence)); - - // Acquire, post, and gain in acquired state should fail. - EXPECT_EQ(-EBUSY, c->Acquire(&fence)); - EXPECT_EQ(-EBUSY, p->Post(LocalHandle())); - EXPECT_EQ(-EBUSY, p->Gain(&fence)); - - // Release in acquired state should succeed. - EXPECT_EQ(0, c->Release(LocalHandle())); - EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(p))); - - // Acquire and post in released state should fail. - EXPECT_EQ(-EBUSY, c->Acquire(&fence)); - EXPECT_EQ(-EBUSY, p->Post(LocalHandle())); - - // Gain in released state should succeed. - EXPECT_EQ(0, p->Gain(&fence)); - - // Acquire in gained state should fail. - EXPECT_EQ(-EBUSY, c->Acquire(&fence)); -} - -TEST_F(LibBufferHubTest, TestAsyncStateTransitions) { - std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create( - kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t)); - ASSERT_TRUE(p.get() != nullptr); - std::unique_ptr<ConsumerBuffer> c = - ConsumerBuffer::Import(p->CreateConsumer()); - ASSERT_TRUE(c.get() != nullptr); - - DvrNativeBufferMetadata metadata; - LocalHandle invalid_fence; - EXPECT_EQ(0, p->GainAsync()); - - // Acquire in gained state should fail. - EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence)); - EXPECT_FALSE(invalid_fence.IsValid()); - EXPECT_FALSE(invalid_fence.IsValid()); - - // Post in gained state should succeed. - EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence)); - EXPECT_EQ(p->buffer_state(), c->buffer_state()); - EXPECT_TRUE(isAnyClientPosted(p->buffer_state())); - - // Post and gain in posted state should fail. - EXPECT_EQ(-EBUSY, p->PostAsync(&metadata, invalid_fence)); - EXPECT_EQ(-EBUSY, p->GainAsync(&metadata, &invalid_fence)); - EXPECT_FALSE(invalid_fence.IsValid()); - - // Acquire in posted state should succeed. - EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(c))); - EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence)); - EXPECT_FALSE(invalid_fence.IsValid()); - EXPECT_EQ(p->buffer_state(), c->buffer_state()); - EXPECT_TRUE(isAnyClientAcquired(p->buffer_state())); - - // Acquire, post, and gain in acquired state should fail. - EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence)); - EXPECT_FALSE(invalid_fence.IsValid()); - EXPECT_EQ(-EBUSY, p->PostAsync(&metadata, invalid_fence)); - EXPECT_EQ(-EBUSY, p->GainAsync(&metadata, &invalid_fence)); - EXPECT_FALSE(invalid_fence.IsValid()); - - // Release in acquired state should succeed. - EXPECT_EQ(0, c->ReleaseAsync(&metadata, invalid_fence)); - EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(p))); - EXPECT_EQ(p->buffer_state(), c->buffer_state()); - EXPECT_TRUE(p->is_released()); - - // Acquire and post in released state should fail. - EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence)); - EXPECT_FALSE(invalid_fence.IsValid()); - EXPECT_EQ(-EBUSY, p->PostAsync(&metadata, invalid_fence)); - - // Gain in released state should succeed. - EXPECT_EQ(0, p->GainAsync(&metadata, &invalid_fence)); - EXPECT_FALSE(invalid_fence.IsValid()); - EXPECT_EQ(p->buffer_state(), c->buffer_state()); - EXPECT_TRUE(isAnyClientGained(p->buffer_state())); - - // Acquire and gain in gained state should fail. - EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence)); - EXPECT_FALSE(invalid_fence.IsValid()); -} - -TEST_F(LibBufferHubTest, TestGainTwiceByTheSameProducer) { - std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create( - kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t)); - ASSERT_TRUE(p.get() != nullptr); - - ASSERT_EQ(0, p->GainAsync()); - ASSERT_EQ(0, p->GainAsync()); -} - -TEST_F(LibBufferHubTest, TestGainPostedBuffer) { - std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create( - kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t)); - ASSERT_TRUE(p.get() != nullptr); - std::unique_ptr<ConsumerBuffer> c = - ConsumerBuffer::Import(p->CreateConsumer()); - ASSERT_TRUE(c.get() != nullptr); - ASSERT_EQ(0, p->GainAsync()); - ASSERT_EQ(0, p->Post(LocalHandle())); - ASSERT_TRUE(isAnyClientPosted(p->buffer_state())); - - // Gain in posted state should only succeed with gain_posted_buffer = true. - LocalHandle invalid_fence; - EXPECT_EQ(-EBUSY, p->Gain(&invalid_fence, false)); - EXPECT_EQ(0, p->Gain(&invalid_fence, true)); -} - -TEST_F(LibBufferHubTest, TestGainPostedBufferAsync) { - std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create( - kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t)); - ASSERT_TRUE(p.get() != nullptr); - std::unique_ptr<ConsumerBuffer> c = - ConsumerBuffer::Import(p->CreateConsumer()); - ASSERT_TRUE(c.get() != nullptr); - ASSERT_EQ(0, p->GainAsync()); - ASSERT_EQ(0, p->Post(LocalHandle())); - ASSERT_TRUE(isAnyClientPosted(p->buffer_state())); - - // GainAsync in posted state should only succeed with gain_posted_buffer - // equals true. - DvrNativeBufferMetadata metadata; - LocalHandle invalid_fence; - EXPECT_EQ(-EBUSY, p->GainAsync(&metadata, &invalid_fence, false)); - EXPECT_EQ(0, p->GainAsync(&metadata, &invalid_fence, true)); -} - -TEST_F(LibBufferHubTest, TestGainPostedBuffer_noConsumer) { - std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create( - kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t)); - ASSERT_TRUE(p.get() != nullptr); - ASSERT_EQ(0, p->GainAsync()); - ASSERT_EQ(0, p->Post(LocalHandle())); - // Producer state bit is in released state after post, other clients shall be - // in posted state although there is no consumer of this buffer yet. - ASSERT_TRUE(isClientReleased(p->buffer_state(), p->client_state_mask())); - ASSERT_TRUE(p->is_released()); - ASSERT_TRUE(isAnyClientPosted(p->buffer_state())); - - // Gain in released state should succeed. - LocalHandle invalid_fence; - EXPECT_EQ(0, p->Gain(&invalid_fence, false)); -} - -TEST_F(LibBufferHubTest, TestMaxConsumers) { - std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create( - kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t)); - ASSERT_TRUE(p.get() != nullptr); - uint32_t producer_state_mask = p->client_state_mask(); - - std::array<std::unique_ptr<ConsumerBuffer>, kMaxConsumerCount> cs; - for (size_t i = 0; i < kMaxConsumerCount; ++i) { - cs[i] = ConsumerBuffer::Import(p->CreateConsumer()); - ASSERT_TRUE(cs[i].get() != nullptr); - EXPECT_TRUE(cs[i]->is_released()); - EXPECT_NE(producer_state_mask, cs[i]->client_state_mask()); - } - - EXPECT_EQ(0, p->GainAsync()); - DvrNativeBufferMetadata metadata; - LocalHandle invalid_fence; - - // Post the producer should trigger all consumers to be available. - EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence)); - EXPECT_TRUE(isClientReleased(p->buffer_state(), p->client_state_mask())); - for (size_t i = 0; i < kMaxConsumerCount; ++i) { - EXPECT_TRUE( - isClientPosted(cs[i]->buffer_state(), cs[i]->client_state_mask())); - EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(cs[i]))); - EXPECT_EQ(0, cs[i]->AcquireAsync(&metadata, &invalid_fence)); - EXPECT_TRUE( - isClientAcquired(p->buffer_state(), cs[i]->client_state_mask())); - } - - // All consumers have to release before the buffer is considered to be - // released. - for (size_t i = 0; i < kMaxConsumerCount; i++) { - EXPECT_FALSE(p->is_released()); - EXPECT_EQ(0, cs[i]->ReleaseAsync(&metadata, invalid_fence)); - } - - EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(p))); - EXPECT_TRUE(p->is_released()); - - // Buffer state cross all clients must be consistent. - for (size_t i = 0; i < kMaxConsumerCount; i++) { - EXPECT_EQ(p->buffer_state(), cs[i]->buffer_state()); - } -} - -TEST_F(LibBufferHubTest, TestCreateConsumerWhenBufferGained) { - std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create( - kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t)); - ASSERT_TRUE(p.get() != nullptr); - EXPECT_EQ(0, p->GainAsync()); - EXPECT_TRUE(isAnyClientGained(p->buffer_state())); - - std::unique_ptr<ConsumerBuffer> c = - ConsumerBuffer::Import(p->CreateConsumer()); - ASSERT_TRUE(c.get() != nullptr); - EXPECT_TRUE(isAnyClientGained(c->buffer_state())); - - DvrNativeBufferMetadata metadata; - LocalHandle invalid_fence; - - // Post the gained buffer should signal already created consumer. - EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence)); - EXPECT_TRUE(isAnyClientPosted(p->buffer_state())); - EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(c))); - EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence)); - EXPECT_TRUE(isAnyClientAcquired(c->buffer_state())); -} - -TEST_F(LibBufferHubTest, TestCreateTheFirstConsumerAfterPostingBuffer) { - std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create( - kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t)); - ASSERT_TRUE(p.get() != nullptr); - EXPECT_EQ(0, p->GainAsync()); - EXPECT_TRUE(isAnyClientGained(p->buffer_state())); - - DvrNativeBufferMetadata metadata; - LocalHandle invalid_fence; - - // Post the gained buffer before any consumer gets created. - EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence)); - EXPECT_TRUE(p->is_released()); - EXPECT_EQ(0, RETRY_EINTR(PollBufferEvent(p))); - - // Newly created consumer will be signalled for the posted buffer although it - // is created after producer posting. - std::unique_ptr<ConsumerBuffer> c = - ConsumerBuffer::Import(p->CreateConsumer()); - ASSERT_TRUE(c.get() != nullptr); - EXPECT_TRUE(isClientPosted(c->buffer_state(), c->client_state_mask())); - EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence)); -} - -TEST_F(LibBufferHubTest, TestCreateConsumerWhenBufferReleased) { - std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create( - kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t)); - ASSERT_TRUE(p.get() != nullptr); - - std::unique_ptr<ConsumerBuffer> c1 = - ConsumerBuffer::Import(p->CreateConsumer()); - ASSERT_TRUE(c1.get() != nullptr); - - EXPECT_EQ(0, p->GainAsync()); - DvrNativeBufferMetadata metadata; - LocalHandle invalid_fence; - - // Post, acquire, and release the buffer.. - EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence)); - EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(c1))); - EXPECT_EQ(0, c1->AcquireAsync(&metadata, &invalid_fence)); - EXPECT_EQ(0, c1->ReleaseAsync(&metadata, invalid_fence)); - - // Note that the next PDX call is on the producer channel, which may be - // executed before Release impulse gets executed by bufferhubd. Thus, here we - // need to wait until the releasd is confirmed before creating another - // consumer. - EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(p))); - EXPECT_TRUE(p->is_released()); - - // Create another consumer immediately after the release, should not make the - // buffer un-released. - std::unique_ptr<ConsumerBuffer> c2 = - ConsumerBuffer::Import(p->CreateConsumer()); - ASSERT_TRUE(c2.get() != nullptr); - - EXPECT_TRUE(p->is_released()); - EXPECT_EQ(0, p->GainAsync(&metadata, &invalid_fence)); - EXPECT_TRUE(isAnyClientGained(p->buffer_state())); -} - -TEST_F(LibBufferHubTest, TestWithCustomMetadata) { - struct Metadata { - int64_t field1; - int64_t field2; - }; - std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create( - kWidth, kHeight, kFormat, kUsage, sizeof(Metadata)); - ASSERT_TRUE(p.get() != nullptr); - std::unique_ptr<ConsumerBuffer> c = - ConsumerBuffer::Import(p->CreateConsumer()); - ASSERT_TRUE(c.get() != nullptr); - EXPECT_EQ(0, p->GainAsync()); - Metadata m = {1, 3}; - EXPECT_EQ(0, p->Post(LocalHandle(), &m, sizeof(Metadata))); - EXPECT_LE(0, RETRY_EINTR(PollBufferEvent(c))); - LocalHandle fence; - Metadata m2 = {}; - EXPECT_EQ(0, c->Acquire(&fence, &m2, sizeof(m2))); - EXPECT_EQ(m.field1, m2.field1); - EXPECT_EQ(m.field2, m2.field2); - EXPECT_EQ(0, c->Release(LocalHandle())); - EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(p, /*timeout_ms=*/0))); -} - -TEST_F(LibBufferHubTest, TestPostWithWrongMetaSize) { - struct Metadata { - int64_t field1; - int64_t field2; - }; - struct OverSizedMetadata { - int64_t field1; - int64_t field2; - int64_t field3; - }; - std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create( - kWidth, kHeight, kFormat, kUsage, sizeof(Metadata)); - ASSERT_TRUE(p.get() != nullptr); - std::unique_ptr<ConsumerBuffer> c = - ConsumerBuffer::Import(p->CreateConsumer()); - ASSERT_TRUE(c.get() != nullptr); - EXPECT_EQ(0, p->GainAsync()); - - // It is illegal to post metadata larger than originally requested during - // buffer allocation. - OverSizedMetadata evil_meta = {}; - EXPECT_NE(0, p->Post(LocalHandle(), &evil_meta, sizeof(OverSizedMetadata))); - EXPECT_GE(0, RETRY_EINTR(PollBufferEvent(c))); - - // It is ok to post metadata smaller than originally requested during - // buffer allocation. - EXPECT_EQ(0, p->Post(LocalHandle())); -} - -TEST_F(LibBufferHubTest, TestAcquireWithWrongMetaSize) { - struct Metadata { - int64_t field1; - int64_t field2; - }; - struct OverSizedMetadata { - int64_t field1; - int64_t field2; - int64_t field3; - }; - std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create( - kWidth, kHeight, kFormat, kUsage, sizeof(Metadata)); - ASSERT_TRUE(p.get() != nullptr); - std::unique_ptr<ConsumerBuffer> c = - ConsumerBuffer::Import(p->CreateConsumer()); - ASSERT_TRUE(c.get() != nullptr); - EXPECT_EQ(0, p->GainAsync()); - - Metadata m = {1, 3}; - EXPECT_EQ(0, p->Post(LocalHandle(), &m, sizeof(m))); - - LocalHandle fence; - int64_t sequence; - OverSizedMetadata e; - - // It is illegal to acquire metadata larger than originally requested during - // buffer allocation. - EXPECT_NE(0, c->Acquire(&fence, &e, sizeof(e))); - - // It is ok to acquire metadata smaller than originally requested during - // buffer allocation. - EXPECT_EQ(0, c->Acquire(&fence, &sequence, sizeof(sequence))); - EXPECT_EQ(m.field1, sequence); -} - -TEST_F(LibBufferHubTest, TestAcquireWithNoMeta) { - std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create( - kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t)); - ASSERT_TRUE(p.get() != nullptr); - std::unique_ptr<ConsumerBuffer> c = - ConsumerBuffer::Import(p->CreateConsumer()); - ASSERT_TRUE(c.get() != nullptr); - EXPECT_EQ(0, p->GainAsync()); - - int64_t sequence = 3; - EXPECT_EQ(0, p->Post(LocalHandle(), &sequence, sizeof(sequence))); - - LocalHandle fence; - EXPECT_EQ(0, c->Acquire(&fence)); -} - -TEST_F(LibBufferHubTest, TestWithNoMeta) { - std::unique_ptr<ProducerBuffer> p = - ProducerBuffer::Create(kWidth, kHeight, kFormat, kUsage); - ASSERT_TRUE(p.get() != nullptr); - std::unique_ptr<ConsumerBuffer> c = - ConsumerBuffer::Import(p->CreateConsumer()); - ASSERT_TRUE(c.get() != nullptr); - EXPECT_EQ(0, p->GainAsync()); - - LocalHandle fence; - - EXPECT_EQ(0, p->Post(LocalHandle())); - EXPECT_EQ(0, c->Acquire(&fence)); -} - -TEST_F(LibBufferHubTest, TestFailureToPostMetaFromABufferWithoutMeta) { - std::unique_ptr<ProducerBuffer> p = - ProducerBuffer::Create(kWidth, kHeight, kFormat, kUsage); - ASSERT_TRUE(p.get() != nullptr); - std::unique_ptr<ConsumerBuffer> c = - ConsumerBuffer::Import(p->CreateConsumer()); - ASSERT_TRUE(c.get() != nullptr); - EXPECT_EQ(0, p->GainAsync()); - - int64_t sequence = 3; - EXPECT_NE(0, p->Post(LocalHandle(), &sequence, sizeof(sequence))); -} - -namespace { - -int PollFd(int fd, int timeout_ms) { - pollfd p = {fd, POLLIN, 0}; - return poll(&p, 1, timeout_ms); -} - -} // namespace - -TEST_F(LibBufferHubTest, TestAcquireFence) { - std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create( - kWidth, kHeight, kFormat, kUsage, /*metadata_size=*/0); - ASSERT_TRUE(p.get() != nullptr); - std::unique_ptr<ConsumerBuffer> c = - ConsumerBuffer::Import(p->CreateConsumer()); - ASSERT_TRUE(c.get() != nullptr); - EXPECT_EQ(0, p->GainAsync()); - - DvrNativeBufferMetadata meta; - LocalHandle f1(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK)); - - // Post with unsignaled fence. - EXPECT_EQ(0, p->PostAsync(&meta, f1)); - - // Should acquire a valid fence. - LocalHandle f2; - EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(c))); - EXPECT_EQ(0, c->AcquireAsync(&meta, &f2)); - EXPECT_TRUE(f2.IsValid()); - // The original fence and acquired fence should have different fd number. - EXPECT_NE(f1.Get(), f2.Get()); - EXPECT_GE(0, PollFd(f2.Get(), 0)); - - // Signal the original fence will trigger the new fence. - eventfd_write(f1.Get(), 1); - // Now the original FD has been signaled. - EXPECT_LT(0, PollFd(f2.Get(), kPollTimeoutMs)); - - // Release the consumer with an invalid fence. - EXPECT_EQ(0, c->ReleaseAsync(&meta, LocalHandle())); - - // Should gain an invalid fence. - LocalHandle f3; - EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(p))); - EXPECT_EQ(0, p->GainAsync(&meta, &f3)); - EXPECT_FALSE(f3.IsValid()); - - // Post with a signaled fence. - EXPECT_EQ(0, p->PostAsync(&meta, f1)); - - // Should acquire a valid fence and it's already signalled. - LocalHandle f4; - EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(c))); - EXPECT_EQ(0, c->AcquireAsync(&meta, &f4)); - EXPECT_TRUE(f4.IsValid()); - EXPECT_LT(0, PollFd(f4.Get(), kPollTimeoutMs)); - - // Release with an unsignalled fence and signal it immediately after release - // without producer gainning. - LocalHandle f5(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK)); - EXPECT_EQ(0, c->ReleaseAsync(&meta, f5)); - eventfd_write(f5.Get(), 1); - - // Should gain a valid fence, which is already signaled. - LocalHandle f6; - EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(p))); - EXPECT_EQ(0, p->GainAsync(&meta, &f6)); - EXPECT_TRUE(f6.IsValid()); - EXPECT_LT(0, PollFd(f6.Get(), kPollTimeoutMs)); -} - -TEST_F(LibBufferHubTest, TestOrphanedAcquire) { - std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create( - kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t)); - ASSERT_TRUE(p.get() != nullptr); - std::unique_ptr<ConsumerBuffer> c1 = - ConsumerBuffer::Import(p->CreateConsumer()); - ASSERT_TRUE(c1.get() != nullptr); - const uint32_t client_state_mask1 = c1->client_state_mask(); - - EXPECT_EQ(0, p->GainAsync()); - DvrNativeBufferMetadata meta; - EXPECT_EQ(0, p->PostAsync(&meta, LocalHandle())); - - LocalHandle fence; - EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(c1))); - EXPECT_EQ(0, c1->AcquireAsync(&meta, &fence)); - - // Destroy the consumer who has acquired but not released the buffer. - c1 = nullptr; - - // The buffer is now available for the producer to gain. - EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(p))); - - // Newly added consumer is not able to acquire the buffer. - std::unique_ptr<ConsumerBuffer> c2 = - ConsumerBuffer::Import(p->CreateConsumer()); - ASSERT_TRUE(c2.get() != nullptr); - const uint32_t client_state_mask2 = c2->client_state_mask(); - EXPECT_NE(client_state_mask1, client_state_mask2); - EXPECT_EQ(0, RETRY_EINTR(PollBufferEvent(c2))); - EXPECT_EQ(-EBUSY, c2->AcquireAsync(&meta, &fence)); - - // Producer should be able to gain. - EXPECT_EQ(0, p->GainAsync(&meta, &fence, false)); -} - -TEST_F(LibBufferHubTest, TestAcquireLastPosted) { - std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create( - kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t)); - ASSERT_TRUE(p.get() != nullptr); - std::unique_ptr<ConsumerBuffer> c1 = - ConsumerBuffer::Import(p->CreateConsumer()); - ASSERT_TRUE(c1.get() != nullptr); - const uint32_t client_state_mask1 = c1->client_state_mask(); - - EXPECT_EQ(0, p->GainAsync()); - DvrNativeBufferMetadata meta; - EXPECT_EQ(0, p->PostAsync(&meta, LocalHandle())); - EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(c1))); - - // c2 is created when the buffer is in posted state. buffer state for c1 is - // posted. Thus, c2 should be automatically set to posted and able to acquire. - std::unique_ptr<ConsumerBuffer> c2 = - ConsumerBuffer::Import(p->CreateConsumer()); - ASSERT_TRUE(c2.get() != nullptr); - const uint32_t client_state_mask2 = c2->client_state_mask(); - EXPECT_NE(client_state_mask1, client_state_mask2); - EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(c2))); - LocalHandle invalid_fence; - EXPECT_EQ(0, c2->AcquireAsync(&meta, &invalid_fence)); - - EXPECT_EQ(0, c1->AcquireAsync(&meta, &invalid_fence)); - - // c3 is created when the buffer is in acquired state. buffer state for c1 and - // c2 are acquired. Thus, c3 should be automatically set to posted and able to - // acquire. - std::unique_ptr<ConsumerBuffer> c3 = - ConsumerBuffer::Import(p->CreateConsumer()); - ASSERT_TRUE(c3.get() != nullptr); - const uint32_t client_state_mask3 = c3->client_state_mask(); - EXPECT_NE(client_state_mask1, client_state_mask3); - EXPECT_NE(client_state_mask2, client_state_mask3); - EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(c3))); - EXPECT_EQ(0, c3->AcquireAsync(&meta, &invalid_fence)); - - // Releasing c2 and c3 in normal ways. - EXPECT_EQ(0, c2->Release(LocalHandle())); - EXPECT_EQ(0, c3->ReleaseAsync(&meta, LocalHandle())); - - // Destroy the c1 who has not released the buffer. - c1 = nullptr; - - // The buffer is now available for the producer to gain. - EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(p))); - - // C4 is created in released state. Thus, it cannot gain the just posted - // buffer. - std::unique_ptr<ConsumerBuffer> c4 = - ConsumerBuffer::Import(p->CreateConsumer()); - ASSERT_TRUE(c4.get() != nullptr); - const uint32_t client_state_mask4 = c4->client_state_mask(); - EXPECT_NE(client_state_mask3, client_state_mask4); - EXPECT_GE(0, RETRY_EINTR(PollBufferEvent(c3))); - EXPECT_EQ(-EBUSY, c3->AcquireAsync(&meta, &invalid_fence)); - - // Producer should be able to gain. - EXPECT_EQ(0, p->GainAsync(&meta, &invalid_fence)); -} - -TEST_F(LibBufferHubTest, TestDetachBufferFromProducer) { - // TODO(b/112338294) rewrite test after migration - return; - - /* std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create( - kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t)); - std::unique_ptr<ConsumerBuffer> c = - ConsumerBuffer::Import(p->CreateConsumer()); - ASSERT_TRUE(p.get() != nullptr); - ASSERT_TRUE(c.get() != nullptr); - - DvrNativeBufferMetadata metadata; - LocalHandle invalid_fence; - int p_id = p->id(); - - // Detach in posted state should fail. - EXPECT_EQ(0, p->GainAsync()); - EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence)); - EXPECT_GT(RETRY_EINTR(PollBufferEvent(c)), 0); - auto s1 = p->Detach(); - EXPECT_FALSE(s1); - - // Detach in acquired state should fail. - EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence)); - s1 = p->Detach(); - EXPECT_FALSE(s1); - - // Detach in released state should fail. - EXPECT_EQ(0, c->ReleaseAsync(&metadata, invalid_fence)); - EXPECT_GT(RETRY_EINTR(PollBufferEvent(p)), 0); - s1 = p->Detach(); - EXPECT_FALSE(s1); - - // Detach in gained state should succeed. - EXPECT_EQ(0, p->GainAsync(&metadata, &invalid_fence)); - s1 = p->Detach(); - EXPECT_TRUE(s1); - - LocalChannelHandle handle = s1.take(); - EXPECT_TRUE(handle.valid()); - - // Both producer and consumer should have hangup. - EXPECT_GT(RETRY_EINTR(PollBufferEvent(p)), 0); - auto s2 = p->GetEventMask(POLLHUP); - EXPECT_TRUE(s2); - EXPECT_EQ(s2.get(), POLLHUP); - - EXPECT_GT(RETRY_EINTR(PollBufferEvent(c)), 0); - s2 = p->GetEventMask(POLLHUP); - EXPECT_TRUE(s2); - EXPECT_EQ(s2.get(), POLLHUP); - - auto s3 = p->CreateConsumer(); - EXPECT_FALSE(s3); - // Note that here the expected error code is EOPNOTSUPP as the socket towards - // ProducerChannel has been teared down. - EXPECT_EQ(s3.error(), EOPNOTSUPP); - - s3 = c->CreateConsumer(); - EXPECT_FALSE(s3); - // Note that here the expected error code is EPIPE returned from - // ConsumerChannel::HandleMessage as the socket is still open but the producer - // is gone. - EXPECT_EQ(s3.error(), EPIPE); - - // Detached buffer handle can be use to construct a new BufferHubBuffer - // object. - auto d = BufferHubBuffer::Import(std::move(handle)); - EXPECT_FALSE(handle.valid()); - EXPECT_TRUE(d->IsConnected()); - EXPECT_TRUE(d->IsValid()); - - EXPECT_EQ(d->id(), p_id); */ -} - -TEST_F(LibBufferHubTest, TestDetach) { - // TODO(b/112338294) rewrite test after migration - return; - - /* std::unique_ptr<ProducerBuffer> p1 = ProducerBuffer::Create( - kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t)); - ASSERT_TRUE(p1.get() != nullptr); - int p1_id = p1->id(); - - // Detached the producer from gained state. - EXPECT_EQ(0, p1->GainAsync()); - auto status_or_handle = p1->Detach(); - EXPECT_TRUE(status_or_handle.ok()); - LocalChannelHandle h1 = status_or_handle.take(); - EXPECT_TRUE(h1.valid()); - - // Detached buffer handle can be use to construct a new BufferHubBuffer - // object. - auto b1 = BufferHubBuffer::Import(std::move(h1)); - EXPECT_FALSE(h1.valid()); - EXPECT_TRUE(b1->IsValid()); - int b1_id = b1->id(); - EXPECT_EQ(b1_id, p1_id); */ -} diff --git a/libs/vr/libbufferhub/buffer_hub_base.cpp b/libs/vr/libbufferhub/buffer_hub_base.cpp deleted file mode 100644 index 17930b4405..0000000000 --- a/libs/vr/libbufferhub/buffer_hub_base.cpp +++ /dev/null @@ -1,216 +0,0 @@ -#include <poll.h> -#include <sys/epoll.h> - -#include <pdx/default_transport/client_channel.h> -#include <pdx/default_transport/client_channel_factory.h> -#include <private/dvr/buffer_hub_base.h> - -using android::pdx::LocalChannelHandle; -using android::pdx::LocalHandle; -using android::pdx::Status; -using android::pdx::default_transport::ClientChannel; -using android::pdx::default_transport::ClientChannelFactory; - -namespace android { -namespace dvr { - -BufferHubBase::BufferHubBase(LocalChannelHandle channel_handle) - : Client{pdx::default_transport::ClientChannel::Create( - std::move(channel_handle))}, - id_(-1), - cid_(-1) {} -BufferHubBase::BufferHubBase(const std::string& endpoint_path) - : Client{pdx::default_transport::ClientChannelFactory::Create( - endpoint_path)}, - id_(-1), - cid_(-1) {} - -BufferHubBase::~BufferHubBase() { - // buffer_state and fence_state are not reset here. They will be used to - // clean up epoll fd if necessary in ProducerChannel::RemoveConsumer method. - if (metadata_header_ != nullptr) { - metadata_buffer_.Unlock(); - } -} - -Status<LocalChannelHandle> BufferHubBase::CreateConsumer() { - Status<LocalChannelHandle> status = - InvokeRemoteMethod<BufferHubRPC::NewConsumer>(); - ALOGE_IF(!status, - "BufferHub::CreateConsumer: Failed to create consumer channel: %s", - status.GetErrorMessage().c_str()); - return status; -} - -int BufferHubBase::ImportBuffer() { - ATRACE_NAME("BufferHubBase::ImportBuffer"); - - Status<BufferDescription<LocalHandle>> status = - InvokeRemoteMethod<BufferHubRPC::GetBuffer>(); - if (!status) { - ALOGE("BufferHubBase::ImportBuffer: Failed to get buffer: %s", - status.GetErrorMessage().c_str()); - return -status.error(); - } else if (status.get().id() < 0) { - ALOGE("BufferHubBase::ImportBuffer: Received an invalid id!"); - return -EIO; - } - - auto buffer_desc = status.take(); - - // Stash the buffer id to replace the value in id_. - const int new_id = buffer_desc.id(); - - // Import the buffer. - IonBuffer ion_buffer; - ALOGD_IF(TRACE, "BufferHubBase::ImportBuffer: id=%d.", buffer_desc.id()); - - if (const int ret = buffer_desc.ImportBuffer(&ion_buffer)) - return ret; - - // Import the metadata. - IonBuffer metadata_buffer; - if (const int ret = buffer_desc.ImportMetadata(&metadata_buffer)) { - ALOGE("Failed to import metadata buffer, error=%d", ret); - return ret; - } - size_t metadata_buf_size = metadata_buffer.width(); - if (metadata_buf_size < BufferHubDefs::kMetadataHeaderSize) { - ALOGE("BufferHubBase::ImportBuffer: metadata buffer too small: %zu", - metadata_buf_size); - return -ENOMEM; - } - - // If all imports succee, replace the previous buffer and id. - buffer_ = std::move(ion_buffer); - metadata_buffer_ = std::move(metadata_buffer); - metadata_buf_size_ = metadata_buf_size; - user_metadata_size_ = metadata_buf_size_ - BufferHubDefs::kMetadataHeaderSize; - - void* metadata_ptr = nullptr; - if (const int ret = - metadata_buffer_.Lock(BufferHubDefs::kMetadataUsage, /*x=*/0, - /*y=*/0, metadata_buf_size_, - /*height=*/1, &metadata_ptr)) { - ALOGE("BufferHubBase::ImportBuffer: Failed to lock metadata."); - return ret; - } - - // Set up shared fences. - shared_acquire_fence_ = buffer_desc.take_acquire_fence(); - shared_release_fence_ = buffer_desc.take_release_fence(); - if (!shared_acquire_fence_ || !shared_release_fence_) { - ALOGE("BufferHubBase::ImportBuffer: Failed to import shared fences."); - return -EIO; - } - - metadata_header_ = - reinterpret_cast<BufferHubDefs::MetadataHeader*>(metadata_ptr); - if (user_metadata_size_) { - user_metadata_ptr_ = - reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(metadata_ptr) + - BufferHubDefs::kMetadataHeaderSize); - } else { - user_metadata_ptr_ = nullptr; - } - - id_ = new_id; - cid_ = buffer_desc.buffer_cid(); - client_state_mask_ = buffer_desc.client_state_mask(); - - // Note that here the buffer_state, fence_state and active_clients_bit_mask - // are mapped from shared memory as an atomic object. The std::atomic's - // constructor will not be called so that the original value stored in the - // memory region will be preserved. - buffer_state_ = &metadata_header_->bufferState; - ALOGD_IF(TRACE, - "BufferHubBase::ImportBuffer: id=%d, buffer_state=%" PRIx32 ".", - id(), buffer_state_->load(std::memory_order_acquire)); - fence_state_ = &metadata_header_->fenceState; - ALOGD_IF(TRACE, - "BufferHubBase::ImportBuffer: id=%d, fence_state=%" PRIx32 ".", id(), - fence_state_->load(std::memory_order_acquire)); - active_clients_bit_mask_ = &metadata_header_->activeClientsBitMask; - ALOGD_IF( - TRACE, - "BufferHubBase::ImportBuffer: id=%d, active_clients_bit_mask=%" PRIx32 - ".", - id(), active_clients_bit_mask_->load(std::memory_order_acquire)); - - return 0; -} - -int BufferHubBase::CheckMetadata(size_t user_metadata_size) const { - if (user_metadata_size && !user_metadata_ptr_) { - ALOGE("BufferHubBase::CheckMetadata: doesn't support custom metadata."); - return -EINVAL; - } - if (user_metadata_size > user_metadata_size_) { - ALOGE("BufferHubBase::CheckMetadata: too big: %zu, maximum: %zu.", - user_metadata_size, user_metadata_size_); - return -E2BIG; - } - return 0; -} - -int BufferHubBase::UpdateSharedFence(const LocalHandle& new_fence, - const LocalHandle& shared_fence) { - if (pending_fence_fd_.Get() != new_fence.Get()) { - // First, replace the old fd if there was already one. Skipping if the new - // one is the same as the old. - if (pending_fence_fd_.IsValid()) { - const int ret = epoll_ctl(shared_fence.Get(), EPOLL_CTL_DEL, - pending_fence_fd_.Get(), nullptr); - ALOGW_IF(ret, - "BufferHubBase::UpdateSharedFence: failed to remove old fence " - "fd from epoll set, error: %s.", - strerror(errno)); - } - - if (new_fence.IsValid()) { - // If ready fence is valid, we put that into the epoll set. - epoll_event event; - event.events = EPOLLIN; - event.data.u32 = client_state_mask(); - pending_fence_fd_ = new_fence.Duplicate(); - if (epoll_ctl(shared_fence.Get(), EPOLL_CTL_ADD, pending_fence_fd_.Get(), - &event) < 0) { - const int error = errno; - ALOGE( - "BufferHubBase::UpdateSharedFence: failed to add new fence fd " - "into epoll set, error: %s.", - strerror(error)); - return -error; - } - // Set bit in fence state to indicate that there is a fence from this - // producer or consumer. - fence_state_->fetch_or(client_state_mask()); - } else { - // Unset bit in fence state to indicate that there is no fence, so that - // when consumer to acquire or producer to acquire, it knows no need to - // check fence for this buffer. - fence_state_->fetch_and(~client_state_mask()); - } - } - - return 0; -} - -int BufferHubBase::Lock(int usage, int x, int y, int width, int height, - void** address) { - return buffer_.Lock(usage, x, y, width, height, address); -} - -int BufferHubBase::Unlock() { return buffer_.Unlock(); } - -int BufferHubBase::GetBlobReadWritePointer(size_t size, void** addr) { - int width = static_cast<int>(size); - int height = 1; - int ret = Lock(usage(), 0, 0, width, height, addr); - if (ret == 0) - Unlock(); - return ret; -} - -} // namespace dvr -} // namespace android diff --git a/libs/vr/libbufferhub/buffer_hub_rpc.cpp b/libs/vr/libbufferhub/buffer_hub_rpc.cpp deleted file mode 100644 index 9a67faa8aa..0000000000 --- a/libs/vr/libbufferhub/buffer_hub_rpc.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "include/private/dvr/bufferhub_rpc.h" - -namespace android { -namespace dvr { - -constexpr char BufferHubRPC::kClientPath[]; - -} // namespace dvr -} // namespace android diff --git a/libs/vr/libbufferhub/consumer_buffer.cpp b/libs/vr/libbufferhub/consumer_buffer.cpp deleted file mode 100644 index 7823e36d3d..0000000000 --- a/libs/vr/libbufferhub/consumer_buffer.cpp +++ /dev/null @@ -1,201 +0,0 @@ -#include <private/dvr/consumer_buffer.h> - -using android::pdx::LocalChannelHandle; -using android::pdx::LocalHandle; -using android::pdx::Status; - -namespace android { -namespace dvr { - -ConsumerBuffer::ConsumerBuffer(LocalChannelHandle channel) - : BASE(std::move(channel)) { - const int ret = ImportBuffer(); - if (ret < 0) { - ALOGE("ConsumerBuffer::ConsumerBuffer: Failed to import buffer: %s", - strerror(-ret)); - Close(ret); - } -} - -std::unique_ptr<ConsumerBuffer> ConsumerBuffer::Import( - LocalChannelHandle channel) { - ATRACE_NAME("ConsumerBuffer::Import"); - ALOGD_IF(TRACE, "ConsumerBuffer::Import: channel=%d", channel.value()); - return ConsumerBuffer::Create(std::move(channel)); -} - -std::unique_ptr<ConsumerBuffer> ConsumerBuffer::Import( - Status<LocalChannelHandle> status) { - return Import(status ? status.take() - : LocalChannelHandle{nullptr, -status.error()}); -} - -int ConsumerBuffer::LocalAcquire(DvrNativeBufferMetadata* out_meta, - LocalHandle* out_fence) { - if (!out_meta) - return -EINVAL; - - // The buffer can be acquired iff the buffer state for this client is posted. - uint32_t current_buffer_state = - buffer_state_->load(std::memory_order_acquire); - if (!BufferHubDefs::isClientPosted(current_buffer_state, - client_state_mask())) { - ALOGE( - "%s: Failed to acquire the buffer. The buffer is not posted, id=%d " - "state=%" PRIx32 " client_state_mask=%" PRIx32 ".", - __FUNCTION__, id(), current_buffer_state, client_state_mask()); - return -EBUSY; - } - - // Change the buffer state for this consumer from posted to acquired. - uint32_t updated_buffer_state = current_buffer_state ^ client_state_mask(); - while (!buffer_state_->compare_exchange_weak( - current_buffer_state, updated_buffer_state, std::memory_order_acq_rel, - std::memory_order_acquire)) { - if (!BufferHubDefs::isClientPosted(current_buffer_state, - client_state_mask())) { - ALOGE( - "%s: Failed to acquire the buffer. The buffer is no longer posted, " - "id=%d state=%" PRIx32 " client_state_mask=%" PRIx32 ".", - __FUNCTION__, id(), current_buffer_state, client_state_mask()); - return -EBUSY; - } - // The failure of compare_exchange_weak updates current_buffer_state. - updated_buffer_state = current_buffer_state ^ client_state_mask(); - } - - // Copy the canonical metadata. - void* metadata_ptr = reinterpret_cast<void*>(&metadata_header_->metadata); - memcpy(out_meta, metadata_ptr, sizeof(DvrNativeBufferMetadata)); - // Fill in the user_metadata_ptr in address space of the local process. - if (out_meta->user_metadata_size) { - out_meta->user_metadata_ptr = - reinterpret_cast<uint64_t>(user_metadata_ptr_); - } else { - out_meta->user_metadata_ptr = 0; - } - - uint32_t fence_state = fence_state_->load(std::memory_order_acquire); - // If there is an acquire fence from producer, we need to return it. - // The producer state bit mask is kFirstClientBitMask for now. - if (fence_state & BufferHubDefs::kFirstClientBitMask) { - *out_fence = shared_acquire_fence_.Duplicate(); - } - - return 0; -} - -int ConsumerBuffer::Acquire(LocalHandle* ready_fence) { - return Acquire(ready_fence, nullptr, 0); -} - -int ConsumerBuffer::Acquire(LocalHandle* ready_fence, void* meta, - size_t user_metadata_size) { - ATRACE_NAME("ConsumerBuffer::Acquire"); - - if (const int error = CheckMetadata(user_metadata_size)) - return error; - - DvrNativeBufferMetadata canonical_meta; - if (const int error = LocalAcquire(&canonical_meta, ready_fence)) - return error; - - if (meta && user_metadata_size) { - void* metadata_src = - reinterpret_cast<void*>(canonical_meta.user_metadata_ptr); - if (metadata_src) { - memcpy(meta, metadata_src, user_metadata_size); - } else { - ALOGW("ConsumerBuffer::Acquire: no user-defined metadata."); - } - } - - auto status = InvokeRemoteMethod<BufferHubRPC::ConsumerAcquire>(); - if (!status) - return -status.error(); - return 0; -} - -int ConsumerBuffer::AcquireAsync(DvrNativeBufferMetadata* out_meta, - LocalHandle* out_fence) { - ATRACE_NAME("ConsumerBuffer::AcquireAsync"); - - if (const int error = LocalAcquire(out_meta, out_fence)) - return error; - - auto status = SendImpulse(BufferHubRPC::ConsumerAcquire::Opcode); - if (!status) - return -status.error(); - return 0; -} - -int ConsumerBuffer::LocalRelease(const DvrNativeBufferMetadata* meta, - const LocalHandle& release_fence) { - if (const int error = CheckMetadata(meta->user_metadata_size)) - return error; - - // Set the buffer state of this client to released if it is not already in - // released state. - uint32_t current_buffer_state = - buffer_state_->load(std::memory_order_acquire); - if (BufferHubDefs::isClientReleased(current_buffer_state, - client_state_mask())) { - return 0; - } - uint32_t updated_buffer_state = current_buffer_state & (~client_state_mask()); - while (!buffer_state_->compare_exchange_weak( - current_buffer_state, updated_buffer_state, std::memory_order_acq_rel, - std::memory_order_acquire)) { - // The failure of compare_exchange_weak updates current_buffer_state. - updated_buffer_state = current_buffer_state & (~client_state_mask()); - } - - // On release, only the user requested metadata is copied back into the shared - // memory for metadata. Since there are multiple consumers, it doesn't make - // sense to send the canonical metadata back to the producer. However, one of - // the consumer can still choose to write up to user_metadata_size bytes of - // data into user_metadata_ptr. - if (meta->user_metadata_ptr && meta->user_metadata_size) { - void* metadata_src = reinterpret_cast<void*>(meta->user_metadata_ptr); - memcpy(user_metadata_ptr_, metadata_src, meta->user_metadata_size); - } - - // Send out the release fence through the shared epoll fd. Note that during - // releasing the producer is not expected to be polling on the fence. - if (const int error = UpdateSharedFence(release_fence, shared_release_fence_)) - return error; - - return 0; -} - -int ConsumerBuffer::Release(const LocalHandle& release_fence) { - ATRACE_NAME("ConsumerBuffer::Release"); - - DvrNativeBufferMetadata meta; - if (const int error = LocalRelease(&meta, release_fence)) - return error; - - return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ConsumerRelease>( - BorrowedFence(release_fence.Borrow()))); -} - -int ConsumerBuffer::ReleaseAsync() { - DvrNativeBufferMetadata meta; - return ReleaseAsync(&meta, LocalHandle()); -} - -int ConsumerBuffer::ReleaseAsync(const DvrNativeBufferMetadata* meta, - const LocalHandle& release_fence) { - ATRACE_NAME("ConsumerBuffer::ReleaseAsync"); - - if (const int error = LocalRelease(meta, release_fence)) - return error; - - return ReturnStatusOrError( - SendImpulse(BufferHubRPC::ConsumerRelease::Opcode)); -} - -int ConsumerBuffer::Discard() { return Release(LocalHandle()); } - -} // namespace dvr -} // namespace android diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h deleted file mode 100644 index 8a490d9983..0000000000 --- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h +++ /dev/null @@ -1,169 +0,0 @@ -#ifndef ANDROID_DVR_BUFFER_HUB_BASE_H_ -#define ANDROID_DVR_BUFFER_HUB_BASE_H_ - -#include <vector> - -#include <private/dvr/bufferhub_rpc.h> - -namespace android { -namespace dvr { - -// Base class of two types of BufferHub clients: dvr::ProducerBuffer and -// dvr::ConsumerBuffer. -class BufferHubBase : public pdx::Client { - public: - using LocalHandle = pdx::LocalHandle; - using LocalChannelHandle = pdx::LocalChannelHandle; - template <typename T> - using Status = pdx::Status<T>; - - // Create a new consumer channel that is attached to the producer. Returns - // a file descriptor for the new channel or a negative error code. - Status<LocalChannelHandle> CreateConsumer(); - - // Gets a blob buffer that was created with ProducerBuffer::CreateBlob. - // Locking and Unlocking is handled internally. There's no need to Unlock - // after calling this method. - int GetBlobReadWritePointer(size_t size, void** addr); - - // Returns a dup'd file descriptor for accessing the blob shared memory. The - // caller takes ownership of the file descriptor and must close it or pass on - // ownership. Some GPU API extensions can take file descriptors to bind shared - // memory gralloc buffers to GPU buffer objects. - LocalHandle GetBlobFd() const { - // Current GPU vendor puts the buffer allocation in one FD. If we change GPU - // vendors and this is the wrong fd, late-latching and EDS will very clearly - // stop working and we will need to correct this. The alternative is to use - // a GL context in the pose service to allocate this buffer or to use the - // ION API directly instead of gralloc. - return LocalHandle(dup(native_handle()->data[0])); - } - - using Client::event_fd; - - Status<int> GetEventMask(int events) { - if (auto* client_channel = GetChannel()) { - return client_channel->GetEventMask(events); - } else { - return pdx::ErrorStatus(EINVAL); - } - } - - std::vector<pdx::ClientChannel::EventSource> GetEventSources() const { - if (auto* client_channel = GetChannel()) { - return client_channel->GetEventSources(); - } else { - return {}; - } - } - - native_handle_t* native_handle() const { - return const_cast<native_handle_t*>(buffer_.handle()); - } - - IonBuffer* buffer() { return &buffer_; } - const IonBuffer* buffer() const { return &buffer_; } - - // Gets ID of the buffer client. All BufferHub clients derived from the same - // buffer in bufferhubd share the same buffer id. - int id() const { return id_; } - - // Gets the channel id of the buffer client. Each BufferHub client has its - // system unique channel id. - int cid() const { return cid_; } - - // Returns the buffer buffer state. - uint32_t buffer_state() { - return buffer_state_->load(std::memory_order_acquire); - }; - - // Returns whether the buffer is already released by all current clients. - bool is_released() { - return (buffer_state() & - active_clients_bit_mask_->load(std::memory_order_acquire)) == 0; - } - - // A state mask which is unique to a buffer hub client among all its siblings - // sharing the same concrete graphic buffer. - uint32_t client_state_mask() const { return client_state_mask_; } - - // The following methods return settings of the first buffer. Currently, - // it is only possible to create multi-buffer BufferHubBases with the same - // settings. - uint32_t width() const { return buffer_.width(); } - uint32_t height() const { return buffer_.height(); } - uint32_t stride() const { return buffer_.stride(); } - uint32_t format() const { return buffer_.format(); } - uint32_t usage() const { return buffer_.usage(); } - uint32_t layer_count() const { return buffer_.layer_count(); } - - uint64_t GetQueueIndex() const { return metadata_header_->queueIndex; } - void SetQueueIndex(uint64_t index) { metadata_header_->queueIndex = index; } - - protected: - explicit BufferHubBase(LocalChannelHandle channel); - explicit BufferHubBase(const std::string& endpoint_path); - virtual ~BufferHubBase(); - - // Initialization helper. - int ImportBuffer(); - - // Check invalid metadata operation. Returns 0 if requested metadata is valid. - int CheckMetadata(size_t user_metadata_size) const; - - // Send out the new fence by updating the shared fence (shared_release_fence - // for producer and shared_acquire_fence for consumer). Note that during this - // should only be used in LocalPost() or LocalRelease, and the shared fence - // shouldn't be poll'ed by the other end. - int UpdateSharedFence(const LocalHandle& new_fence, - const LocalHandle& shared_fence); - - // Locks the area specified by (x, y, width, height) for a specific usage. If - // the usage is software then |addr| will be updated to point to the address - // of the buffer in virtual memory. The caller should only access/modify the - // pixels in the specified area. anything else is undefined behavior. - int Lock(int usage, int x, int y, int width, int height, void** addr); - - // Must be called after Lock() when the caller has finished changing the - // buffer. - int Unlock(); - - // IonBuffer that is shared between bufferhubd, producer, and consumers. - size_t metadata_buf_size_{0}; - size_t user_metadata_size_{0}; - BufferHubDefs::MetadataHeader* metadata_header_ = nullptr; - void* user_metadata_ptr_ = nullptr; - std::atomic<uint32_t>* buffer_state_ = nullptr; - std::atomic<uint32_t>* fence_state_ = nullptr; - std::atomic<uint32_t>* active_clients_bit_mask_ = nullptr; - - LocalHandle shared_acquire_fence_; - LocalHandle shared_release_fence_; - - // A local fence fd that holds the ownership of the fence fd on Post (for - // producer) and Release (for consumer). - LocalHandle pending_fence_fd_; - - private: - BufferHubBase(const BufferHubBase&) = delete; - void operator=(const BufferHubBase&) = delete; - - // Global id for the buffer that is consistent across processes. It is meant - // for logging and debugging purposes only and should not be used for lookup - // or any other functional purpose as a security precaution. - int id_; - - // Channel id. - int cid_; - - // Client bit mask which indicates the locations of this client object in the - // buffer_state_. - uint32_t client_state_mask_{0U}; - IonBuffer buffer_; - IonBuffer metadata_buffer_; -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_BUFFER_HUB_BASE_H_ diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h deleted file mode 100644 index e610e18849..0000000000 --- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h +++ /dev/null @@ -1,164 +0,0 @@ -#ifndef ANDROID_DVR_BUFFER_HUB_DEFS_H_ -#define ANDROID_DVR_BUFFER_HUB_DEFS_H_ - -#include <dvr/dvr_api.h> -#include <hardware/gralloc.h> -#include <pdx/channel_handle.h> -#include <pdx/file_handle.h> -#include <pdx/rpc/remote_method.h> -#include <pdx/rpc/serializable.h> -#include <private/dvr/native_handle_wrapper.h> -#include <ui/BufferHubDefs.h> - -namespace android { -namespace dvr { - -namespace BufferHubDefs { - -static constexpr uint32_t kMetadataFormat = HAL_PIXEL_FORMAT_BLOB; -static constexpr uint32_t kMetadataUsage = - GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN; - -// See more details in libs/ui/include/ui/BufferHubDefs.h -static constexpr int kMaxNumberOfClients = - android::BufferHubDefs::kMaxNumberOfClients; -static constexpr uint32_t kLowbitsMask = android::BufferHubDefs::kLowbitsMask; -static constexpr uint32_t kHighBitsMask = android::BufferHubDefs::kHighBitsMask; -static constexpr uint32_t kFirstClientBitMask = - android::BufferHubDefs::kFirstClientBitMask; - -static inline bool isAnyClientGained(uint32_t state) { - return android::BufferHubDefs::isAnyClientGained(state); -} - -static inline bool isClientGained(uint32_t state, uint32_t client_bit_mask) { - return android::BufferHubDefs::isClientGained(state, client_bit_mask); -} - -static inline bool isAnyClientPosted(uint32_t state) { - return android::BufferHubDefs::isAnyClientPosted(state); -} - -static inline bool isClientPosted(uint32_t state, uint32_t client_bit_mask) { - return android::BufferHubDefs::isClientPosted(state, client_bit_mask); -} - -static inline bool isAnyClientAcquired(uint32_t state) { - return android::BufferHubDefs::isAnyClientAcquired(state); -} - -static inline bool isClientAcquired(uint32_t state, uint32_t client_bit_mask) { - return android::BufferHubDefs::isClientAcquired(state, client_bit_mask); -} - -static inline bool isClientReleased(uint32_t state, uint32_t client_bit_mask) { - return android::BufferHubDefs::isClientReleased(state, client_bit_mask); -} - -// Returns the next available buffer client's client_state_masks. -// @params union_bits. Union of all existing clients' client_state_masks. -static inline uint32_t findNextAvailableClientStateMask(uint32_t union_bits) { - return android::BufferHubDefs::findNextAvailableClientStateMask(union_bits); -} - -using MetadataHeader = android::BufferHubDefs::MetadataHeader; -static constexpr size_t kMetadataHeaderSize = - android::BufferHubDefs::kMetadataHeaderSize; - -} // namespace BufferHubDefs - -template <typename FileHandleType> -class BufferTraits { - public: - BufferTraits() = default; - BufferTraits(const native_handle_t* buffer_handle, - const FileHandleType& metadata_handle, int id, - uint32_t client_state_mask, uint64_t metadata_size, - uint32_t width, uint32_t height, uint32_t layer_count, - uint32_t format, uint64_t usage, uint32_t stride, - const FileHandleType& acquire_fence_fd, - const FileHandleType& release_fence_fd) - : id_(id), - client_state_mask_(client_state_mask), - metadata_size_(metadata_size), - width_(width), - height_(height), - layer_count_(layer_count), - format_(format), - usage_(usage), - stride_(stride), - buffer_handle_(buffer_handle), - metadata_handle_(metadata_handle.Borrow()), - acquire_fence_fd_(acquire_fence_fd.Borrow()), - release_fence_fd_(release_fence_fd.Borrow()) {} - - BufferTraits(BufferTraits&& other) = default; - BufferTraits& operator=(BufferTraits&& other) = default; - - // ID of the buffer client. All BufferHubBuffer clients derived from the same - // buffer in bufferhubd share the same buffer id. - int id() const { return id_; } - - // State mask of the buffer client. Each BufferHubBuffer client backed by the - // same buffer channel has uniqued state bit among its siblings. For a - // producer buffer the bit must be kFirstClientBitMask; for a consumer the bit - // must be one of the kConsumerStateMask. - uint32_t client_state_mask() const { return client_state_mask_; } - uint64_t metadata_size() const { return metadata_size_; } - - uint32_t width() { return width_; } - uint32_t height() { return height_; } - uint32_t layer_count() { return layer_count_; } - uint32_t format() { return format_; } - uint64_t usage() { return usage_; } - uint32_t stride() { return stride_; } - - const NativeHandleWrapper<FileHandleType>& buffer_handle() const { - return buffer_handle_; - } - - NativeHandleWrapper<FileHandleType> take_buffer_handle() { - return std::move(buffer_handle_); - } - FileHandleType take_metadata_handle() { return std::move(metadata_handle_); } - FileHandleType take_acquire_fence() { return std::move(acquire_fence_fd_); } - FileHandleType take_release_fence() { return std::move(release_fence_fd_); } - - private: - // BufferHub specific traits. - int id_ = -1; - uint32_t client_state_mask_; - uint64_t metadata_size_; - - // Traits for a GraphicBuffer. - uint32_t width_; - uint32_t height_; - uint32_t layer_count_; - uint32_t format_; - uint64_t usage_; - uint32_t stride_; - - // Native handle for the graphic buffer. - NativeHandleWrapper<FileHandleType> buffer_handle_; - - // File handle of an ashmem that holds buffer metadata. - FileHandleType metadata_handle_; - - // Pamameters for shared fences. - FileHandleType acquire_fence_fd_; - FileHandleType release_fence_fd_; - - PDX_SERIALIZABLE_MEMBERS(BufferTraits<FileHandleType>, id_, - client_state_mask_, metadata_size_, stride_, width_, - height_, layer_count_, format_, usage_, - buffer_handle_, metadata_handle_, acquire_fence_fd_, - release_fence_fd_); - - BufferTraits(const BufferTraits&) = delete; - void operator=(const BufferTraits&) = delete; -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_BUFFER_HUB_DEFS_H_ diff --git a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h deleted file mode 100644 index f1cd0b4adc..0000000000 --- a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h +++ /dev/null @@ -1,377 +0,0 @@ -#ifndef ANDROID_DVR_BUFFERHUB_RPC_H_ -#define ANDROID_DVR_BUFFERHUB_RPC_H_ - -#include "buffer_hub_defs.h" - -#include <cutils/native_handle.h> -#include <ui/BufferQueueDefs.h> - -#include <pdx/channel_handle.h> -#include <pdx/file_handle.h> -#include <pdx/rpc/remote_method.h> -#include <pdx/rpc/serializable.h> -#include <private/dvr/ion_buffer.h> - -namespace android { -namespace dvr { - -template <typename FileHandleType> -class NativeBufferHandle { - public: - NativeBufferHandle() { Clear(); } - NativeBufferHandle(const IonBuffer& buffer, int id) - : id_(id), - stride_(buffer.stride()), - width_(buffer.width()), - height_(buffer.height()), - layer_count_(buffer.layer_count()), - format_(buffer.format()), - usage_(buffer.usage()) { - // Populate the fd and int vectors: native_handle->data[] is an array of fds - // followed by an array of opaque ints. - const int fd_count = buffer.handle()->numFds; - const int int_count = buffer.handle()->numInts; - for (int i = 0; i < fd_count; i++) { - fds_.emplace_back(FileHandleType::AsDuplicate(buffer.handle()->data[i])); - } - for (int i = 0; i < int_count; i++) { - opaque_ints_.push_back(buffer.handle()->data[fd_count + i]); - } - } - NativeBufferHandle(NativeBufferHandle&& other) noexcept = default; - NativeBufferHandle& operator=(NativeBufferHandle&& other) noexcept = default; - - // Imports the native handle into the given IonBuffer instance. - int Import(IonBuffer* buffer) { - // This is annoying, but we need to convert the vector of FileHandles into a - // vector of ints for the Import API. - std::vector<int> fd_ints; - for (const auto& fd : fds_) - fd_ints.push_back(fd.Get()); - - const int ret = - buffer->Import(fd_ints.data(), fd_ints.size(), opaque_ints_.data(), - opaque_ints_.size(), width_, height_, layer_count_, - stride_, format_, usage_); - if (ret < 0) - return ret; - - // Import succeeded, release the file handles which are now owned by the - // IonBuffer and clear members. - for (auto& fd : fds_) - fd.Release(); - opaque_ints_.clear(); - Clear(); - - return 0; - } - - int id() const { return id_; } - size_t IntCount() const { return opaque_ints_.size(); } - size_t FdCount() const { return fds_.size(); } - - private: - int id_; - uint32_t stride_; - uint32_t width_; - uint32_t height_; - uint32_t layer_count_; - uint32_t format_; - uint64_t usage_; - std::vector<int> opaque_ints_; - std::vector<FileHandleType> fds_; - - void Clear() { - id_ = -1; - stride_ = width_ = height_ = format_ = usage_ = 0; - } - - PDX_SERIALIZABLE_MEMBERS(NativeBufferHandle<FileHandleType>, id_, stride_, - width_, height_, layer_count_, format_, usage_, - opaque_ints_, fds_); - - NativeBufferHandle(const NativeBufferHandle&) = delete; - void operator=(const NativeBufferHandle&) = delete; -}; - -template <typename FileHandleType> -class BufferDescription { - public: - BufferDescription() = default; - BufferDescription(const IonBuffer& buffer, const IonBuffer& metadata, int id, - int buffer_cid, uint32_t client_state_mask, - const FileHandleType& acquire_fence_fd, - const FileHandleType& release_fence_fd) - : id_(id), - buffer_cid_(buffer_cid), - client_state_mask_(client_state_mask), - buffer_(buffer, id), - metadata_(metadata, id), - acquire_fence_fd_(acquire_fence_fd.Borrow()), - release_fence_fd_(release_fence_fd.Borrow()) {} - - BufferDescription(BufferDescription&& other) noexcept = default; - BufferDescription& operator=(BufferDescription&& other) noexcept = default; - - // ID of the buffer client. All BufferHub clients derived from the same buffer - // in bufferhubd share the same buffer id. - int id() const { return id_; } - - // Channel ID of the buffer client. Each BufferHub client has its system - // unique channel id. - int buffer_cid() const { return buffer_cid_; } - - // State mask of the buffer client. Each BufferHub client backed by the - // same buffer channel has uniqued state bit among its siblings. - uint32_t client_state_mask() const { return client_state_mask_; } - FileHandleType take_acquire_fence() { return std::move(acquire_fence_fd_); } - FileHandleType take_release_fence() { return std::move(release_fence_fd_); } - - int ImportBuffer(IonBuffer* buffer) { return buffer_.Import(buffer); } - int ImportMetadata(IonBuffer* metadata) { return metadata_.Import(metadata); } - - private: - int id_{-1}; - int buffer_cid_{-1}; - uint32_t client_state_mask_{0U}; - // Two IonBuffers: one for the graphic buffer and one for metadata. - NativeBufferHandle<FileHandleType> buffer_; - NativeBufferHandle<FileHandleType> metadata_; - - // Pamameters for shared fences. - FileHandleType acquire_fence_fd_; - FileHandleType release_fence_fd_; - - PDX_SERIALIZABLE_MEMBERS(BufferDescription<FileHandleType>, id_, buffer_cid_, - client_state_mask_, buffer_, metadata_, - acquire_fence_fd_, release_fence_fd_); - - BufferDescription(const BufferDescription&) = delete; - void operator=(const BufferDescription&) = delete; -}; - -using BorrowedNativeBufferHandle = NativeBufferHandle<pdx::BorrowedHandle>; -using LocalNativeBufferHandle = NativeBufferHandle<pdx::LocalHandle>; - -template <typename FileHandleType> -class FenceHandle { - public: - FenceHandle() = default; - explicit FenceHandle(int fence) : fence_{fence} {} - explicit FenceHandle(FileHandleType&& fence) : fence_{std::move(fence)} {} - FenceHandle(FenceHandle&&) noexcept = default; - FenceHandle& operator=(FenceHandle&&) noexcept = default; - - explicit operator bool() const { return fence_.IsValid(); } - - const FileHandleType& get() const { fence_; } - FileHandleType&& take() { return std::move(fence_); } - - int get_fd() const { return fence_.Get(); } - void close() { fence_.Close(); } - - FenceHandle<pdx::BorrowedHandle> borrow() const { - return FenceHandle<pdx::BorrowedHandle>(fence_.Borrow()); - } - - private: - FileHandleType fence_; - - PDX_SERIALIZABLE_MEMBERS(FenceHandle<FileHandleType>, fence_); - - FenceHandle(const FenceHandle&) = delete; - void operator=(const FenceHandle&) = delete; -}; - -using LocalFence = FenceHandle<pdx::LocalHandle>; -using BorrowedFence = FenceHandle<pdx::BorrowedHandle>; - -struct ProducerQueueConfig { - // Whether the buffer queue is operating in Async mode. - // From GVR's perspective of view, this means a buffer can be acquired - // asynchronously by the compositor. - // From Android Surface's perspective of view, this is equivalent to - // IGraphicBufferProducer's async mode. When in async mode, a producer - // will never block even if consumer is running slow. - bool is_async; - - // Default buffer width that is set during ProducerQueue's creation. - uint32_t default_width; - - // Default buffer height that is set during ProducerQueue's creation. - uint32_t default_height; - - // Default buffer format that is set during ProducerQueue's creation. - uint32_t default_format; - - // Size of the meta data associated with all the buffers allocated from the - // queue. - size_t user_metadata_size; - - private: - PDX_SERIALIZABLE_MEMBERS(ProducerQueueConfig, is_async, default_width, - default_height, default_format, user_metadata_size); -}; - -class ProducerQueueConfigBuilder { - public: - // Build a ProducerQueueConfig object. - ProducerQueueConfig Build() { - return {is_async_, default_width_, default_height_, default_format_, - user_metadata_size_}; - } - - ProducerQueueConfigBuilder& SetIsAsync(bool is_async) { - is_async_ = is_async; - return *this; - } - - ProducerQueueConfigBuilder& SetDefaultWidth(uint32_t width) { - default_width_ = width; - return *this; - } - - ProducerQueueConfigBuilder& SetDefaultHeight(uint32_t height) { - default_height_ = height; - return *this; - } - - ProducerQueueConfigBuilder& SetDefaultFormat(uint32_t format) { - default_format_ = format; - return *this; - } - - template <typename Meta> - ProducerQueueConfigBuilder& SetMetadata() { - user_metadata_size_ = sizeof(Meta); - return *this; - } - - ProducerQueueConfigBuilder& SetMetadataSize(size_t user_metadata_size) { - user_metadata_size_ = user_metadata_size; - return *this; - } - - private: - bool is_async_{false}; - uint32_t default_width_{1}; - uint32_t default_height_{1}; - uint32_t default_format_{1}; // PIXEL_FORMAT_RGBA_8888 - size_t user_metadata_size_{0}; -}; - -// Explicit specializations of ProducerQueueConfigBuilder::Build for void -// metadata type. -template <> -inline ProducerQueueConfigBuilder& -ProducerQueueConfigBuilder::SetMetadata<void>() { - user_metadata_size_ = 0; - return *this; -} - -struct QueueInfo { - ProducerQueueConfig producer_config; - int id; - - private: - PDX_SERIALIZABLE_MEMBERS(QueueInfo, producer_config, id); -}; - -struct UsagePolicy { - uint64_t usage_set_mask{0}; - uint64_t usage_clear_mask{0}; - uint64_t usage_deny_set_mask{0}; - uint64_t usage_deny_clear_mask{0}; - - private: - PDX_SERIALIZABLE_MEMBERS(UsagePolicy, usage_set_mask, usage_clear_mask, - usage_deny_set_mask, usage_deny_clear_mask); -}; - -// BufferHub Service RPC interface. Defines the endpoints, op codes, and method -// type signatures supported by bufferhubd. -struct BufferHubRPC { - // Service path. - static constexpr char kClientPath[] = "system/buffer_hub/client"; - - // |BufferHubQueue| will keep track of at most this value of buffers. - // Attempts at runtime to increase the number of buffers past this - // will fail. Note that the value is in sync with |android::BufferQueue|, so - // that slot id can be shared between |android::dvr::BufferHubQueueProducer| - // and |android::BufferQueueProducer| which both implements the same - // interface: |android::IGraphicBufferProducer|. - static constexpr size_t kMaxQueueCapacity = - android::BufferQueueDefs::NUM_BUFFER_SLOTS; - - // Op codes. - enum { - kOpCreateBuffer = 0, - kOpGetBuffer, - kOpNewConsumer, - kOpProducerPost, - kOpProducerGain, - kOpConsumerAcquire, - kOpConsumerRelease, - kOpConsumerBufferDetach, - kOpCreateProducerQueue, - kOpCreateConsumerQueue, - kOpGetQueueInfo, - kOpProducerQueueAllocateBuffers, - kOpProducerQueueInsertBuffer, - kOpProducerQueueRemoveBuffer, - kOpConsumerQueueImportBuffers, - // TODO(b/77153033): Separate all those RPC operations into subclasses. - }; - - // Aliases. - using LocalChannelHandle = pdx::LocalChannelHandle; - using LocalHandle = pdx::LocalHandle; - using Void = pdx::rpc::Void; - - // Methods. - PDX_REMOTE_METHOD(CreateBuffer, kOpCreateBuffer, - void(uint32_t width, uint32_t height, uint32_t format, - uint64_t usage, size_t user_metadata_size)); - PDX_REMOTE_METHOD(GetBuffer, kOpGetBuffer, - BufferDescription<LocalHandle>(Void)); - PDX_REMOTE_METHOD(NewConsumer, kOpNewConsumer, LocalChannelHandle(Void)); - PDX_REMOTE_METHOD(ProducerPost, kOpProducerPost, - void(LocalFence acquire_fence)); - PDX_REMOTE_METHOD(ProducerGain, kOpProducerGain, LocalFence(Void)); - PDX_REMOTE_METHOD(ConsumerAcquire, kOpConsumerAcquire, LocalFence(Void)); - PDX_REMOTE_METHOD(ConsumerRelease, kOpConsumerRelease, - void(LocalFence release_fence)); - - // Detaches a ConsumerBuffer from an existing producer/consumer set. Can only - // be called when the consumer is the only consumer and it has exclusive - // access to the buffer (i.e. in the acquired'ed state). On the successful - // return of the IPC call, a new DetachedBufferChannel handle will be returned - // and all existing producer and consumer channels will be closed. Further - // IPCs towards those channels will return error. - PDX_REMOTE_METHOD(ConsumerBufferDetach, kOpConsumerBufferDetach, - LocalChannelHandle(Void)); - - // Buffer Queue Methods. - PDX_REMOTE_METHOD(CreateProducerQueue, kOpCreateProducerQueue, - QueueInfo(const ProducerQueueConfig& producer_config, - const UsagePolicy& usage_policy)); - PDX_REMOTE_METHOD(CreateConsumerQueue, kOpCreateConsumerQueue, - LocalChannelHandle(bool silent_queue)); - PDX_REMOTE_METHOD(GetQueueInfo, kOpGetQueueInfo, QueueInfo(Void)); - PDX_REMOTE_METHOD(ProducerQueueAllocateBuffers, - kOpProducerQueueAllocateBuffers, - std::vector<std::pair<LocalChannelHandle, size_t>>( - uint32_t width, uint32_t height, uint32_t layer_count, - uint32_t format, uint64_t usage, size_t buffer_count)); - PDX_REMOTE_METHOD(ProducerQueueInsertBuffer, kOpProducerQueueInsertBuffer, - size_t(int buffer_cid)); - PDX_REMOTE_METHOD(ProducerQueueRemoveBuffer, kOpProducerQueueRemoveBuffer, - void(size_t slot)); - PDX_REMOTE_METHOD(ConsumerQueueImportBuffers, kOpConsumerQueueImportBuffers, - std::vector<std::pair<LocalChannelHandle, size_t>>(Void)); -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_BUFFERHUB_RPC_H_ diff --git a/libs/vr/libbufferhub/include/private/dvr/consumer_buffer.h b/libs/vr/libbufferhub/include/private/dvr/consumer_buffer.h deleted file mode 100644 index 726f0350b0..0000000000 --- a/libs/vr/libbufferhub/include/private/dvr/consumer_buffer.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef ANDROID_DVR_CONSUMER_BUFFER_H_ -#define ANDROID_DVR_CONSUMER_BUFFER_H_ - -#include <private/dvr/buffer_hub_base.h> - -namespace android { -namespace dvr { - -// This is a connection to a producer buffer, which can be located in another -// application. When that buffer is Post()ed, this fd will be signaled and -// Acquire allows read access. The user is responsible for making sure that -// Acquire is called with the correct metadata structure. The only guarantee the -// API currently provides is that an Acquire() with metadata of the wrong size -// will fail. -class ConsumerBuffer : public pdx::ClientBase<ConsumerBuffer, BufferHubBase> { - public: - // This call assumes ownership of |fd|. - static std::unique_ptr<ConsumerBuffer> Import(LocalChannelHandle channel); - static std::unique_ptr<ConsumerBuffer> Import( - Status<LocalChannelHandle> status); - - // Attempt to retrieve a post event from buffer hub. If successful, - // |ready_fence| will be set to a fence to wait on until the buffer is ready. - // This call will only succeed after the fd is signalled. This call may be - // performed as an alternative to the Acquire() with metadata. In such cases - // the metadata is not read. - // - // This returns zero or negative unix error code. - int Acquire(LocalHandle* ready_fence); - - // Attempt to retrieve a post event from buffer hub. If successful, - // |ready_fence| is set to a fence signaling that the contents of the buffer - // are available. This call will only succeed if the buffer is in the posted - // state. - // Returns zero on success, or a negative errno code otherwise. - int Acquire(LocalHandle* ready_fence, void* meta, size_t user_metadata_size); - - // Asynchronously acquires a bufer. - int AcquireAsync(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence); - - // Releases the buffer from any buffer state. If the fence is valid the fence - // determines the buffer usage, otherwise the buffer is released immediately. - // This returns zero or a negative unix error code. - int Release(const LocalHandle& release_fence); - int ReleaseAsync(); - - // Asynchronously releases a buffer. Similar to the synchronous version above, - // except that it does not wait for BufferHub to reply with success or error. - // The fence and metadata are passed to consumer via shared fd and shared - // memory. - int ReleaseAsync(const DvrNativeBufferMetadata* meta, - const LocalHandle& release_fence); - - // May be called after or instead of Acquire to indicate that the consumer - // does not need to access the buffer this cycle. This returns zero or a - // negative unix error code. - int Discard(); - - private: - friend BASE; - - explicit ConsumerBuffer(LocalChannelHandle channel); - - // Local state transition helpers. - int LocalAcquire(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence); - int LocalRelease(const DvrNativeBufferMetadata* meta, - const LocalHandle& release_fence); -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_CONSUMER_BUFFER_H_ diff --git a/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h b/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h deleted file mode 100644 index ed38e7f448..0000000000 --- a/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef ANDROID_DVR_ION_BUFFER_H_ -#define ANDROID_DVR_ION_BUFFER_H_ - -#include <hardware/gralloc.h> -#include <log/log.h> -#include <ui/GraphicBuffer.h> - -namespace android { -namespace dvr { - -// IonBuffer is an abstraction of Ion/Gralloc buffers. -class IonBuffer { - public: - IonBuffer(); - IonBuffer(uint32_t width, uint32_t height, uint32_t format, uint64_t usage); - IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height, - uint32_t stride, uint32_t format, uint64_t usage); - IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height, - uint32_t layer_count, uint32_t stride, uint32_t format, - uint64_t usage); - ~IonBuffer(); - - IonBuffer(IonBuffer&& other) noexcept; - IonBuffer& operator=(IonBuffer&& other) noexcept; - - // Returns check this IonBuffer holds a valid Gralloc buffer. - bool IsValid() const { return buffer_ && buffer_->initCheck() == OK; } - - // Frees the underlying native handle and leaves the instance initialized to - // empty. - void FreeHandle(); - - // Allocates a new native handle with the given parameters, freeing the - // previous native handle if necessary. Returns 0 on success or a negative - // errno code otherwise. If allocation fails the previous native handle is - // left intact. - int Alloc(uint32_t width, uint32_t height, uint32_t layer_count, - uint32_t format, uint64_t usage); - - // Resets the underlying native handle and parameters, freeing the previous - // native handle if necessary. - void Reset(buffer_handle_t handle, uint32_t width, uint32_t height, - uint32_t layer_count, uint32_t stride, uint32_t format, - uint64_t usage); - - // Like Reset but also registers the native handle, which is necessary for - // native handles received over IPC. Returns 0 on success or a negative errno - // code otherwise. If import fails the previous native handle is left intact. - int Import(buffer_handle_t handle, uint32_t width, uint32_t height, - uint32_t layer_count, uint32_t stride, uint32_t format, - uint64_t usage); - - // Like Reset but imports a native handle from raw fd and int arrays. Returns - // 0 on success or a negative errno code otherwise. If import fails the - // previous native handle is left intact. - int Import(const int* fd_array, int fd_count, const int* int_array, - int int_count, uint32_t width, uint32_t height, - uint32_t layer_count, uint32_t stride, uint32_t format, - uint64_t usage); - - // Duplicates the native handle underlying |other| and then imports it. This - // is useful for creating multiple, independent views of the same Ion/Gralloc - // buffer. Returns 0 on success or a negative errno code otherwise. If - // duplication or import fail the previous native handle is left intact. - int Duplicate(const IonBuffer* other); - - int Lock(uint32_t usage, int x, int y, int width, int height, void** address); - int LockYUV(uint32_t usage, int x, int y, int width, int height, - struct android_ycbcr* yuv); - int Unlock(); - - sp<GraphicBuffer>& buffer() { return buffer_; } - const sp<GraphicBuffer>& buffer() const { return buffer_; } - buffer_handle_t handle() const { - return buffer_.get() ? buffer_->handle : nullptr; - } - uint32_t width() const { return buffer_.get() ? buffer_->getWidth() : 0; } - uint32_t height() const { return buffer_.get() ? buffer_->getHeight() : 0; } - uint32_t layer_count() const { - return buffer_.get() ? buffer_->getLayerCount() : 0; - } - uint32_t stride() const { return buffer_.get() ? buffer_->getStride() : 0; } - uint32_t format() const { - return buffer_.get() ? buffer_->getPixelFormat() : 0; - } - uint64_t usage() const { - return buffer_.get() ? static_cast<uint64_t>(buffer_->getUsage()) : 0; - } - - private: - sp<GraphicBuffer> buffer_; - - IonBuffer(const IonBuffer&) = delete; - void operator=(const IonBuffer&) = delete; -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_ION_BUFFER_H_ diff --git a/libs/vr/libbufferhub/include/private/dvr/native_handle_wrapper.h b/libs/vr/libbufferhub/include/private/dvr/native_handle_wrapper.h deleted file mode 100644 index a5c6ca238a..0000000000 --- a/libs/vr/libbufferhub/include/private/dvr/native_handle_wrapper.h +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef ANDROID_DVR_NATIVE_HANDLE_WRAPPER_H_ -#define ANDROID_DVR_NATIVE_HANDLE_WRAPPER_H_ - -#include <cutils/native_handle.h> -#include <log/log.h> -#include <pdx/rpc/serializable.h> - -#include <vector> - -namespace android { -namespace dvr { - -// A PDX-friendly wrapper to maintain the life cycle of a native_handle_t -// object. -// -// See https://source.android.com/devices/architecture/hidl/types#handle_t for -// more information about native_handle_t. -template <typename FileHandleType> -class NativeHandleWrapper { - public: - NativeHandleWrapper() = default; - NativeHandleWrapper(NativeHandleWrapper&& other) = default; - NativeHandleWrapper& operator=(NativeHandleWrapper&& other) = default; - - // Create a new NativeHandleWrapper by duplicating the handle. - explicit NativeHandleWrapper(const native_handle_t* handle) { - const int fd_count = handle->numFds; - const int int_count = handle->numInts; - - // Populate the fd and int vectors: native_handle->data[] is an array of fds - // followed by an array of opaque ints. - for (int i = 0; i < fd_count; i++) { - fds_.emplace_back(FileHandleType::AsDuplicate(handle->data[i])); - } - for (int i = 0; i < int_count; i++) { - ints_.push_back(handle->data[fd_count + i]); - } - } - - size_t int_count() const { return ints_.size(); } - size_t fd_count() const { return fds_.size(); } - bool IsValid() const { return ints_.size() != 0 || fds_.size() != 0; } - - // Duplicate a native handle from the wrapper. - native_handle_t* DuplicateHandle() const { - if (!IsValid()) { - return nullptr; - } - - // numFds + numInts ints. - std::vector<FileHandleType> fds; - for (const auto& fd : fds_) { - if (!fd.IsValid()) { - return nullptr; - } - fds.emplace_back(fd.Duplicate()); - } - - return FromFdsAndInts(std::move(fds), ints_); - } - - // Takes the native handle out of the wrapper. - native_handle_t* TakeHandle() { - if (!IsValid()) { - return nullptr; - } - - return FromFdsAndInts(std::move(fds_), std::move(ints_)); - } - - private: - NativeHandleWrapper(const NativeHandleWrapper&) = delete; - void operator=(const NativeHandleWrapper&) = delete; - - static native_handle_t* FromFdsAndInts(std::vector<FileHandleType> fds, - std::vector<int> ints) { - native_handle_t* handle = native_handle_create(fds.size(), ints.size()); - if (!handle) { - ALOGE("NativeHandleWrapper::TakeHandle: Failed to create new handle."); - return nullptr; - } - - // numFds + numInts ints. - for (int i = 0; i < handle->numFds; i++) { - handle->data[i] = fds[i].Release(); - } - memcpy(&handle->data[handle->numFds], ints.data(), - sizeof(int) * handle->numInts); - - return handle; - } - - std::vector<int> ints_; - std::vector<FileHandleType> fds_; - - PDX_SERIALIZABLE_MEMBERS(NativeHandleWrapper<FileHandleType>, ints_, fds_); -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_NATIVE_HANDLE_WRAPPER_H_ diff --git a/libs/vr/libbufferhub/include/private/dvr/producer_buffer.h b/libs/vr/libbufferhub/include/private/dvr/producer_buffer.h deleted file mode 100644 index 7ec345c4b5..0000000000 --- a/libs/vr/libbufferhub/include/private/dvr/producer_buffer.h +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef ANDROID_DVR_PRODUCER_BUFFER_H_ -#define ANDROID_DVR_PRODUCER_BUFFER_H_ - -#include <private/dvr/buffer_hub_base.h> - -namespace android { -namespace dvr { - -// This represents a writable buffer. Calling Post notifies all clients and -// makes the buffer read-only. Call Gain to acquire write access. A buffer -// may have many consumers. -// -// The user of ProducerBuffer is responsible with making sure that the Post() is -// done with the correct metadata type and size. The user is also responsible -// for making sure that remote ends (ConsumerBuffers) are also using the correct -// metadata when acquiring the buffer. The API guarantees that a Post() with a -// metadata of wrong size will fail. However, it currently does not do any -// type checking. -// The API also assumes that metadata is a serializable type (plain old data). -class ProducerBuffer : public pdx::ClientBase<ProducerBuffer, BufferHubBase> { - public: - // Imports a bufferhub producer channel, assuming ownership of its handle. - static std::unique_ptr<ProducerBuffer> Import(LocalChannelHandle channel); - static std::unique_ptr<ProducerBuffer> Import( - Status<LocalChannelHandle> status); - - // Asynchronously posts a buffer. The fence and metadata are passed to - // consumer via shared fd and shared memory. - int PostAsync(const DvrNativeBufferMetadata* meta, - const LocalHandle& ready_fence); - - // Post this buffer, passing |ready_fence| to the consumers. The bytes in - // |meta| are passed unaltered to the consumers. The producer must not modify - // the buffer until it is re-gained. - // This returns zero or a negative unix error code. - int Post(const LocalHandle& ready_fence, const void* meta, - size_t user_metadata_size); - - int Post(const LocalHandle& ready_fence) { - return Post(ready_fence, nullptr, 0); - } - - // Attempt to re-gain the buffer for writing. If |release_fence| is valid, it - // must be waited on before using the buffer. If it is not valid then the - // buffer is free for immediate use. This call will succeed if the buffer - // is in the released state, or in posted state and gain_posted_buffer is - // true. - // - // @param release_fence output fence. - // @param gain_posted_buffer whether to gain posted buffer or not. - // @return This returns zero or a negative unix error code. - int Gain(LocalHandle* release_fence, bool gain_posted_buffer = false); - - // Asynchronously marks a released buffer as gained. This method is similar to - // the synchronous version above, except that it does not wait for BufferHub - // to acknowledge success or failure. Because of the asynchronous nature of - // the underlying message, no error is returned if this method is called when - // the buffer is in an incorrect state. Returns zero if sending the message - // succeeded, or a negative errno code if local error check fails. - // TODO(b/112007999): gain_posted_buffer true is only used to prevent - // libdvrtracking from starving when there are non-responding clients. This - // gain_posted_buffer param can be removed once libdvrtracking start to use - // the new AHardwareBuffer API. - int GainAsync(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence, - bool gain_posted_buffer = false); - int GainAsync(); - - // Detaches a ProducerBuffer from an existing producer/consumer set. Can only - // be called when a producer buffer has exclusive access to the buffer (i.e. - // in the gain'ed state). On the successful return of the IPC call, a new - // LocalChannelHandle representing a detached buffer will be returned and all - // existing producer and consumer channels will be closed. Further IPCs - // towards those channels will return error. - Status<LocalChannelHandle> Detach(); - - private: - friend BASE; - - // Constructors are automatically exposed through ProducerBuffer::Create(...) - // static template methods inherited from ClientBase, which take the same - // arguments as the constructors. - - // Constructs a buffer with the given geometry and parameters. - ProducerBuffer(uint32_t width, uint32_t height, uint32_t format, - uint64_t usage, size_t metadata_size = 0); - - // Constructs a blob (flat) buffer with the given usage flags. - ProducerBuffer(uint64_t usage, size_t size); - - // Imports the given file handle to a producer channel, taking ownership. - explicit ProducerBuffer(LocalChannelHandle channel); - - // Local state transition helpers. - int LocalGain(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence, - bool gain_posted_buffer = false); - int LocalPost(const DvrNativeBufferMetadata* meta, - const LocalHandle& ready_fence); -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_PRODUCER_BUFFER_H_ diff --git a/libs/vr/libbufferhub/ion_buffer.cpp b/libs/vr/libbufferhub/ion_buffer.cpp deleted file mode 100644 index 196541010e..0000000000 --- a/libs/vr/libbufferhub/ion_buffer.cpp +++ /dev/null @@ -1,240 +0,0 @@ -#include <private/dvr/ion_buffer.h> - -#include <log/log.h> -#define ATRACE_TAG ATRACE_TAG_GRAPHICS -#include <utils/Trace.h> - -#include <mutex> - -namespace { - -constexpr uint32_t kDefaultGraphicBufferLayerCount = 1; - -} // anonymous namespace - -namespace android { -namespace dvr { - -IonBuffer::IonBuffer() : IonBuffer(nullptr, 0, 0, 0, 0, 0, 0) {} - -IonBuffer::IonBuffer(uint32_t width, uint32_t height, uint32_t format, - uint64_t usage) - : IonBuffer() { - Alloc(width, height, kDefaultGraphicBufferLayerCount, format, usage); -} - -IonBuffer::IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height, - uint32_t stride, uint32_t format, uint64_t usage) - : IonBuffer(handle, width, height, kDefaultGraphicBufferLayerCount, stride, - format, usage) {} - -IonBuffer::IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height, - uint32_t layer_count, uint32_t stride, uint32_t format, - uint64_t usage) - : buffer_(nullptr) { - ALOGD_IF(TRACE, - "IonBuffer::IonBuffer: handle=%p width=%u height=%u layer_count=%u " - "stride=%u format=%u usage=%" PRIx64, - handle, width, height, layer_count, stride, format, usage); - if (handle != 0) { - Import(handle, width, height, layer_count, stride, format, usage); - } -} - -IonBuffer::~IonBuffer() { - ALOGD_IF(TRACE, - "IonBuffer::~IonBuffer: handle=%p width=%u height=%u stride=%u " - "format=%u usage=%" PRIx64, - handle(), width(), height(), stride(), format(), usage()); - FreeHandle(); -} - -IonBuffer::IonBuffer(IonBuffer&& other) noexcept : IonBuffer() { - *this = std::move(other); -} - -IonBuffer& IonBuffer::operator=(IonBuffer&& other) noexcept { - ALOGD_IF(TRACE, "IonBuffer::operator=: handle_=%p other.handle_=%p", handle(), - other.handle()); - - if (this != &other) { - buffer_ = other.buffer_; - other.FreeHandle(); - } - return *this; -} - -void IonBuffer::FreeHandle() { - if (buffer_.get()) { - // GraphicBuffer unregisters and cleans up the handle if needed - buffer_ = nullptr; - } -} - -int IonBuffer::Alloc(uint32_t width, uint32_t height, uint32_t layer_count, - uint32_t format, uint64_t usage) { - ALOGD_IF(TRACE, - "IonBuffer::Alloc: width=%u height=%u layer_count=%u format=%u " - "usage=%" PRIx64, width, height, layer_count, format, usage); - - sp<GraphicBuffer> buffer = - new GraphicBuffer(width, height, format, layer_count, usage); - if (buffer->initCheck() != OK) { - ALOGE("IonBuffer::Aloc: Failed to allocate buffer"); - return -EINVAL; - } else { - buffer_ = buffer; - return 0; - } -} - -void IonBuffer::Reset(buffer_handle_t handle, uint32_t width, uint32_t height, - uint32_t layer_count, uint32_t stride, uint32_t format, - uint64_t usage) { - ALOGD_IF(TRACE, - "IonBuffer::Reset: handle=%p width=%u height=%u layer_count=%u " - "stride=%u format=%u usage=%" PRIx64, - handle, width, height, layer_count, stride, format, usage); - Import(handle, width, height, layer_count, stride, format, usage); -} - -int IonBuffer::Import(buffer_handle_t handle, uint32_t width, uint32_t height, - uint32_t layer_count, uint32_t stride, uint32_t format, - uint64_t usage) { - ATRACE_NAME("IonBuffer::Import1"); - ALOGD_IF(TRACE, - "IonBuffer::Import: handle=%p width=%u height=%u layer_count=%u " - "stride=%u format=%u usage=%" PRIx64, - handle, width, height, layer_count, stride, format, usage); - FreeHandle(); - sp<GraphicBuffer> buffer = - new GraphicBuffer(handle, GraphicBuffer::TAKE_UNREGISTERED_HANDLE, width, - height, format, layer_count, usage, stride); - if (buffer->initCheck() != OK) { - ALOGE("IonBuffer::Import: Failed to import buffer"); - return -EINVAL; - } else { - buffer_ = buffer; - return 0; - } -} - -int IonBuffer::Import(const int* fd_array, int fd_count, const int* int_array, - int int_count, uint32_t width, uint32_t height, - uint32_t layer_count, uint32_t stride, uint32_t format, - uint64_t usage) { - ATRACE_NAME("IonBuffer::Import2"); - ALOGD_IF(TRACE, - "IonBuffer::Import: fd_count=%d int_count=%d width=%u height=%u " - "layer_count=%u stride=%u format=%u usage=%" PRIx64, - fd_count, int_count, width, height, layer_count, stride, format, - usage); - - if (fd_count < 0 || int_count < 0) { - ALOGE("IonBuffer::Import: invalid arguments."); - return -EINVAL; - } - - native_handle_t* handle = native_handle_create(fd_count, int_count); - if (!handle) { - ALOGE("IonBuffer::Import: failed to create new native handle."); - return -ENOMEM; - } - - // Copy fd_array into the first part of handle->data and int_array right - // after it. - memcpy(handle->data, fd_array, sizeof(int) * fd_count); - memcpy(handle->data + fd_count, int_array, sizeof(int) * int_count); - - const int ret = - Import(handle, width, height, layer_count, stride, format, usage); - if (ret < 0) { - ALOGE("IonBuffer::Import: failed to import raw native handle: %s", - strerror(-ret)); - native_handle_close(handle); - native_handle_delete(handle); - } - - return ret; -} - -int IonBuffer::Duplicate(const IonBuffer* other) { - if (!other->handle()) - return -EINVAL; - - const int fd_count = other->handle()->numFds; - const int int_count = other->handle()->numInts; - - if (fd_count < 0 || int_count < 0) - return -EINVAL; - - native_handle_t* handle = native_handle_create(fd_count, int_count); - if (!handle) { - ALOGE("IonBuffer::Duplicate: Failed to create new native handle."); - return -ENOMEM; - } - - // Duplicate the file descriptors from the other native handle. - for (int i = 0; i < fd_count; i++) - handle->data[i] = dup(other->handle()->data[i]); - - // Copy the ints after the file descriptors. - memcpy(handle->data + fd_count, other->handle()->data + fd_count, - sizeof(int) * int_count); - - const int ret = - Import(handle, other->width(), other->height(), other->layer_count(), - other->stride(), other->format(), other->usage()); - if (ret < 0) { - ALOGE("IonBuffer::Duplicate: Failed to import duplicate native handle: %s", - strerror(-ret)); - native_handle_close(handle); - native_handle_delete(handle); - } - - return ret; -} - -int IonBuffer::Lock(uint32_t usage, int x, int y, int width, int height, - void** address) { - ATRACE_NAME("IonBuffer::Lock"); - ALOGD_IF(TRACE, - "IonBuffer::Lock: handle=%p usage=%d x=%d y=%d width=%d height=%d " - "address=%p", - handle(), usage, x, y, width, height, address); - - status_t err = - buffer_->lock(usage, Rect(x, y, x + width, y + height), address); - if (err != OK) - return -EINVAL; - else - return 0; -} - -int IonBuffer::LockYUV(uint32_t usage, int x, int y, int width, int height, - struct android_ycbcr* yuv) { - ATRACE_NAME("IonBuffer::LockYUV"); - ALOGD_IF(TRACE, - "IonBuffer::Lock: handle=%p usage=%d x=%d y=%d width=%d height=%d", - handle(), usage, x, y, width, height); - - status_t err = - buffer_->lockYCbCr(usage, Rect(x, y, x + width, y + height), yuv); - if (err != OK) - return -EINVAL; - else - return 0; -} - -int IonBuffer::Unlock() { - ATRACE_NAME("IonBuffer::Unlock"); - ALOGD_IF(TRACE, "IonBuffer::Unlock: handle=%p", handle()); - - status_t err = buffer_->unlock(); - if (err != OK) - return -EINVAL; - else - return 0; -} -} // namespace dvr -} // namespace android diff --git a/libs/vr/libbufferhub/producer_buffer.cpp b/libs/vr/libbufferhub/producer_buffer.cpp deleted file mode 100644 index aa9d07282b..0000000000 --- a/libs/vr/libbufferhub/producer_buffer.cpp +++ /dev/null @@ -1,296 +0,0 @@ -#include <private/dvr/producer_buffer.h> - -using android::pdx::LocalChannelHandle; -using android::pdx::LocalHandle; -using android::pdx::Status; - -namespace android { -namespace dvr { - -ProducerBuffer::ProducerBuffer(uint32_t width, uint32_t height, uint32_t format, - uint64_t usage, size_t user_metadata_size) - : BASE(BufferHubRPC::kClientPath) { - ATRACE_NAME("ProducerBuffer::ProducerBuffer"); - ALOGD_IF(TRACE, - "ProducerBuffer::ProducerBuffer: fd=%d width=%u height=%u format=%u " - "usage=%" PRIx64 " user_metadata_size=%zu", - event_fd(), width, height, format, usage, user_metadata_size); - - auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>( - width, height, format, usage, user_metadata_size); - if (!status) { - ALOGE( - "ProducerBuffer::ProducerBuffer: Failed to create producer buffer: %s", - status.GetErrorMessage().c_str()); - Close(-status.error()); - return; - } - - const int ret = ImportBuffer(); - if (ret < 0) { - ALOGE( - "ProducerBuffer::ProducerBuffer: Failed to import producer buffer: %s", - strerror(-ret)); - Close(ret); - } -} - -ProducerBuffer::ProducerBuffer(uint64_t usage, size_t size) - : BASE(BufferHubRPC::kClientPath) { - ATRACE_NAME("ProducerBuffer::ProducerBuffer"); - ALOGD_IF(TRACE, "ProducerBuffer::ProducerBuffer: usage=%" PRIx64 " size=%zu", - usage, size); - const int width = static_cast<int>(size); - const int height = 1; - const int format = HAL_PIXEL_FORMAT_BLOB; - const size_t user_metadata_size = 0; - - auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>( - width, height, format, usage, user_metadata_size); - if (!status) { - ALOGE("ProducerBuffer::ProducerBuffer: Failed to create blob: %s", - status.GetErrorMessage().c_str()); - Close(-status.error()); - return; - } - - const int ret = ImportBuffer(); - if (ret < 0) { - ALOGE( - "ProducerBuffer::ProducerBuffer: Failed to import producer buffer: %s", - strerror(-ret)); - Close(ret); - } -} - -ProducerBuffer::ProducerBuffer(LocalChannelHandle channel) - : BASE(std::move(channel)) { - const int ret = ImportBuffer(); - if (ret < 0) { - ALOGE( - "ProducerBuffer::ProducerBuffer: Failed to import producer buffer: %s", - strerror(-ret)); - Close(ret); - } -} - -int ProducerBuffer::LocalPost(const DvrNativeBufferMetadata* meta, - const LocalHandle& ready_fence) { - if (const int error = CheckMetadata(meta->user_metadata_size)) - return error; - - // The buffer can be posted iff the buffer state for this client is gained. - uint32_t current_buffer_state = - buffer_state_->load(std::memory_order_acquire); - if (!BufferHubDefs::isClientGained(current_buffer_state, - client_state_mask())) { - ALOGE("%s: not gained, id=%d state=%" PRIx32 ".", __FUNCTION__, id(), - current_buffer_state); - return -EBUSY; - } - - // Set the producer client buffer state to released, that of all other clients - // (both existing and non-existing clients) to posted. - uint32_t updated_buffer_state = - (~client_state_mask()) & BufferHubDefs::kHighBitsMask; - while (!buffer_state_->compare_exchange_weak( - current_buffer_state, updated_buffer_state, std::memory_order_acq_rel, - std::memory_order_acquire)) { - if (!BufferHubDefs::isClientGained(current_buffer_state, - client_state_mask())) { - ALOGE( - "%s: Failed to post the buffer. The buffer is no longer gained, " - "id=%d state=%" PRIx32 ".", - __FUNCTION__, id(), current_buffer_state); - return -EBUSY; - } - } - - // Copy the canonical metadata. - void* metadata_ptr = reinterpret_cast<void*>(&metadata_header_->metadata); - memcpy(metadata_ptr, meta, sizeof(DvrNativeBufferMetadata)); - // Copy extra user requested metadata. - if (meta->user_metadata_ptr && meta->user_metadata_size) { - void* metadata_src = reinterpret_cast<void*>(meta->user_metadata_ptr); - memcpy(user_metadata_ptr_, metadata_src, meta->user_metadata_size); - } - - // Send out the acquire fence through the shared epoll fd. Note that during - // posting no consumer is not expected to be polling on the fence. - if (const int error = UpdateSharedFence(ready_fence, shared_acquire_fence_)) - return error; - - return 0; -} - -int ProducerBuffer::Post(const LocalHandle& ready_fence, const void* meta, - size_t user_metadata_size) { - ATRACE_NAME("ProducerBuffer::Post"); - - // Populate cononical metadata for posting. - DvrNativeBufferMetadata canonical_meta; - canonical_meta.user_metadata_ptr = reinterpret_cast<uint64_t>(meta); - canonical_meta.user_metadata_size = user_metadata_size; - - if (const int error = LocalPost(&canonical_meta, ready_fence)) - return error; - - return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ProducerPost>( - BorrowedFence(ready_fence.Borrow()))); -} - -int ProducerBuffer::PostAsync(const DvrNativeBufferMetadata* meta, - const LocalHandle& ready_fence) { - ATRACE_NAME("ProducerBuffer::PostAsync"); - - if (const int error = LocalPost(meta, ready_fence)) - return error; - - return ReturnStatusOrError(SendImpulse(BufferHubRPC::ProducerPost::Opcode)); -} - -int ProducerBuffer::LocalGain(DvrNativeBufferMetadata* out_meta, - LocalHandle* out_fence, bool gain_posted_buffer) { - if (!out_meta) - return -EINVAL; - - uint32_t current_buffer_state = - buffer_state_->load(std::memory_order_acquire); - ALOGD_IF(TRACE, "%s: buffer=%d, state=%" PRIx32 ".", __FUNCTION__, id(), - current_buffer_state); - - if (BufferHubDefs::isClientGained(current_buffer_state, - client_state_mask())) { - ALOGV("%s: already gained id=%d.", __FUNCTION__, id()); - return 0; - } - if (BufferHubDefs::isAnyClientAcquired(current_buffer_state) || - BufferHubDefs::isAnyClientGained(current_buffer_state) || - (BufferHubDefs::isAnyClientPosted( - current_buffer_state & - active_clients_bit_mask_->load(std::memory_order_acquire)) && - !gain_posted_buffer)) { - ALOGE("%s: not released id=%d state=%" PRIx32 ".", __FUNCTION__, id(), - current_buffer_state); - return -EBUSY; - } - // Change the buffer state to gained state. - uint32_t updated_buffer_state = client_state_mask(); - while (!buffer_state_->compare_exchange_weak( - current_buffer_state, updated_buffer_state, std::memory_order_acq_rel, - std::memory_order_acquire)) { - if (BufferHubDefs::isAnyClientAcquired(current_buffer_state) || - BufferHubDefs::isAnyClientGained(current_buffer_state) || - (BufferHubDefs::isAnyClientPosted( - current_buffer_state & - active_clients_bit_mask_->load(std::memory_order_acquire)) && - !gain_posted_buffer)) { - ALOGE( - "%s: Failed to gain the buffer. The buffer is no longer released. " - "id=%d state=%" PRIx32 ".", - __FUNCTION__, id(), current_buffer_state); - return -EBUSY; - } - } - - // Canonical metadata is undefined on Gain. Except for user_metadata and - // release_fence_mask. Fill in the user_metadata_ptr in address space of the - // local process. - if (metadata_header_->metadata.user_metadata_size && user_metadata_ptr_) { - out_meta->user_metadata_size = - metadata_header_->metadata.user_metadata_size; - out_meta->user_metadata_ptr = - reinterpret_cast<uint64_t>(user_metadata_ptr_); - } else { - out_meta->user_metadata_size = 0; - out_meta->user_metadata_ptr = 0; - } - - uint32_t current_fence_state = fence_state_->load(std::memory_order_acquire); - uint32_t current_active_clients_bit_mask = - active_clients_bit_mask_->load(std::memory_order_acquire); - // If there are release fence(s) from consumer(s), we need to return it to the - // consumer(s). - // TODO(b/112007999) add an atomic variable in metadata header in shared - // memory to indicate which client is the last producer of the buffer. - // Currently, assume the first client is the only producer to the buffer. - if (current_fence_state & current_active_clients_bit_mask & - (~BufferHubDefs::kFirstClientBitMask)) { - *out_fence = shared_release_fence_.Duplicate(); - out_meta->release_fence_mask = current_fence_state & - current_active_clients_bit_mask & - (~BufferHubDefs::kFirstClientBitMask); - } - - return 0; -} - -int ProducerBuffer::Gain(LocalHandle* release_fence, bool gain_posted_buffer) { - ATRACE_NAME("ProducerBuffer::Gain"); - - DvrNativeBufferMetadata meta; - if (const int error = LocalGain(&meta, release_fence, gain_posted_buffer)) - return error; - - auto status = InvokeRemoteMethod<BufferHubRPC::ProducerGain>(); - if (!status) - return -status.error(); - return 0; -} - -int ProducerBuffer::GainAsync(DvrNativeBufferMetadata* out_meta, - LocalHandle* release_fence, - bool gain_posted_buffer) { - ATRACE_NAME("ProducerBuffer::GainAsync"); - - if (const int error = LocalGain(out_meta, release_fence, gain_posted_buffer)) - return error; - - return ReturnStatusOrError(SendImpulse(BufferHubRPC::ProducerGain::Opcode)); -} - -int ProducerBuffer::GainAsync() { - DvrNativeBufferMetadata meta; - LocalHandle fence; - return GainAsync(&meta, &fence); -} - -std::unique_ptr<ProducerBuffer> ProducerBuffer::Import( - LocalChannelHandle channel) { - ALOGD_IF(TRACE, "ProducerBuffer::Import: channel=%d", channel.value()); - return ProducerBuffer::Create(std::move(channel)); -} - -std::unique_ptr<ProducerBuffer> ProducerBuffer::Import( - Status<LocalChannelHandle> status) { - return Import(status ? status.take() - : LocalChannelHandle{nullptr, -status.error()}); -} - -Status<LocalChannelHandle> ProducerBuffer::Detach() { - // TODO(b/112338294) remove after migrate producer buffer to binder - ALOGW("ProducerBuffer::Detach: not supported operation during migration"); - return {}; - - // TODO(b/112338294) Keep here for reference. Remove it after new logic is - // written. - /* uint32_t buffer_state = buffer_state_->load(std::memory_order_acquire); - if (!BufferHubDefs::isClientGained( - buffer_state, BufferHubDefs::kFirstClientStateMask)) { - // Can only detach a ProducerBuffer when it's in gained state. - ALOGW("ProducerBuffer::Detach: The buffer (id=%d, state=0x%" PRIx32 - ") is not in gained state.", - id(), buffer_state); - return {}; - } - - Status<LocalChannelHandle> status = - InvokeRemoteMethod<BufferHubRPC::ProducerBufferDetach>(); - ALOGE_IF(!status, - "ProducerBuffer::Detach: Failed to detach buffer (id=%d): %s.", id(), - status.GetErrorMessage().c_str()); - return status; */ -} - -} // namespace dvr -} // namespace android diff --git a/libs/vr/libdvr/Android.bp b/libs/vr/libdvr/Android.bp deleted file mode 100644 index 9dbeacba94..0000000000 --- a/libs/vr/libdvr/Android.bp +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (C) 2017 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - - -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "frameworks_native_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["frameworks_native_license"], -} - -cc_library_headers { - name: "libdvr_headers", - export_include_dirs: ["include"], - vendor_available: true, - apex_available: [ - "//apex_available:platform", - "com.android.media", - "com.android.media.swcodec", - ], - min_sdk_version: "29", -} diff --git a/libs/vr/libdvr/include/CPPLINT.cfg b/libs/vr/libdvr/include/CPPLINT.cfg deleted file mode 100644 index 2f8a3c018c..0000000000 --- a/libs/vr/libdvr/include/CPPLINT.cfg +++ /dev/null @@ -1 +0,0 @@ -filter=-build/header_guard diff --git a/libs/vr/libdvr/include/dvr/dvr_api.h b/libs/vr/libdvr/include/dvr/dvr_api.h deleted file mode 100644 index b7abb99559..0000000000 --- a/libs/vr/libdvr/include/dvr/dvr_api.h +++ /dev/null @@ -1,503 +0,0 @@ -#ifndef ANDROID_DVR_API_H_ -#define ANDROID_DVR_API_H_ - -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> -#include <unistd.h> -#include <cstdio> - -#include <dvr/dvr_display_types.h> -#include <dvr/dvr_hardware_composer_types.h> -#include <dvr/dvr_pose.h> -#include <dvr/dvr_tracking_types.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __GNUC__ -#define ALIGNED_DVR_STRUCT(x) __attribute__((packed, aligned(x))) -#else -#define ALIGNED_DVR_STRUCT(x) -#endif - -typedef struct ANativeWindow ANativeWindow; - -typedef struct DvrPoseAsync DvrPoseAsync; - -typedef uint64_t DvrSurfaceUpdateFlags; -typedef struct DvrDisplayManager DvrDisplayManager; -typedef struct DvrSurfaceState DvrSurfaceState; -typedef struct DvrPoseClient DvrPoseClient; -typedef struct DvrPoseDataCaptureRequest DvrPoseDataCaptureRequest; -typedef struct DvrVSyncClient DvrVSyncClient; -typedef struct DvrVirtualTouchpad DvrVirtualTouchpad; - -typedef struct DvrBuffer DvrBuffer; -typedef struct DvrWriteBuffer DvrWriteBuffer; -typedef struct DvrReadBuffer DvrReadBuffer; -typedef struct AHardwareBuffer AHardwareBuffer; - -typedef struct DvrReadBufferQueue DvrReadBufferQueue; -typedef struct DvrWriteBufferQueue DvrWriteBufferQueue; -typedef struct DvrNativeBufferMetadata DvrNativeBufferMetadata; - -typedef struct DvrSurface DvrSurface; -typedef uint64_t DvrSurfaceAttributeType; -typedef int32_t DvrSurfaceAttributeKey; -typedef int32_t DvrGlobalBufferKey; - -typedef struct DvrSurfaceAttributeValue DvrSurfaceAttributeValue; -typedef struct DvrSurfaceAttribute DvrSurfaceAttribute; - -typedef struct DvrReadBuffer DvrReadBuffer; -typedef struct DvrTrackingCamera DvrTrackingCamera; -typedef struct DvrTrackingFeatureExtractor DvrTrackingFeatureExtractor; -typedef struct DvrTrackingSensors DvrTrackingSensors; -typedef struct DvrWriteBufferQueue DvrWriteBufferQueue; - -// Note: To avoid breaking others during active development, only modify this -// struct by appending elements to the end. -// If you do feel we should to re-arrange or remove elements, please make a -// note of it, and wait until we're about to finalize for an API release to do -// so. -typedef struct DvrNativeDisplayMetrics { - uint32_t display_width; - uint32_t display_height; - uint32_t display_x_dpi; - uint32_t display_y_dpi; - uint32_t vsync_period_ns; -} DvrNativeDisplayMetrics; - -// native_handle contains the fds for the underlying ION allocations inside -// the gralloc buffer. This is needed temporarily while GPU vendors work on -// better support for AHardwareBuffer via glBindSharedBuffer APIs. See -// b/37207909. For now we can declare the native_handle struct where it is -// used for GPU late latching. See cutils/native_handle.h for the struct layout. -struct native_handle; - -// Device metrics data type enums. -enum { - // Request the device lens metrics protobuf. This matches cardboard protos. - DVR_CONFIGURATION_DATA_LENS_METRICS = 0, - // Request the device metrics protobuf. - DVR_CONFIGURATION_DATA_DEVICE_METRICS = 1, - // Request the per device configuration data file. - DVR_CONFIGURATION_DATA_DEVICE_CONFIG = 2, - // Request the edid data for the display. - DVR_CONFIGURATION_DATA_DEVICE_EDID = 3, -}; - -// dvr_display_manager.h -typedef int (*DvrDisplayManagerCreatePtr)(DvrDisplayManager** client_out); -typedef void (*DvrDisplayManagerDestroyPtr)(DvrDisplayManager* client); -typedef int (*DvrDisplayManagerGetEventFdPtr)(DvrDisplayManager* client); -typedef int (*DvrDisplayManagerTranslateEpollEventMaskPtr)( - DvrDisplayManager* client, int in_events, int* out_events); -typedef int (*DvrDisplayManagerGetSurfaceStatePtr)( - DvrDisplayManager* client, DvrSurfaceState* surface_state); -typedef int (*DvrDisplayManagerGetReadBufferQueuePtr)( - DvrDisplayManager* client, int surface_id, int queue_id, - DvrReadBufferQueue** queue_out); -typedef int (*DvrConfigurationDataGetPtr)(int config_type, uint8_t** data, - size_t* data_size); -typedef void (*DvrConfigurationDataDestroyPtr)(uint8_t* data); -typedef int (*DvrSurfaceStateCreatePtr)(DvrSurfaceState** surface_state); -typedef void (*DvrSurfaceStateDestroyPtr)(DvrSurfaceState* surface_state); -typedef int (*DvrSurfaceStateGetSurfaceCountPtr)(DvrSurfaceState* surface_state, - size_t* count_out); -typedef int (*DvrSurfaceStateGetUpdateFlagsPtr)( - DvrSurfaceState* surface_state, size_t surface_index, - DvrSurfaceUpdateFlags* flags_out); -typedef int (*DvrSurfaceStateGetSurfaceIdPtr)(DvrSurfaceState* surface_state, - size_t surface_index, - int* surface_id_out); -typedef int (*DvrSurfaceStateGetProcessIdPtr)(DvrSurfaceState* surface_state, - size_t surface_index, - int* process_id_out); -typedef int (*DvrSurfaceStateGetQueueCountPtr)(DvrSurfaceState* surface_state, - size_t surface_index, - size_t* count_out); -typedef ssize_t (*DvrSurfaceStateGetQueueIdsPtr)(DvrSurfaceState* surface_state, - size_t surface_index, - int* queue_ids, - size_t max_count); -typedef int (*DvrSurfaceStateGetZOrderPtr)(DvrSurfaceState* surface_state, - size_t surface_index, - int* z_order_out); -typedef int (*DvrSurfaceStateGetVisiblePtr)(DvrSurfaceState* surface_state, - size_t surface_index, - bool* visible_out); -typedef int (*DvrSurfaceStateGetAttributeCountPtr)( - DvrSurfaceState* surface_state, size_t surface_index, size_t* count_out); -typedef ssize_t (*DvrSurfaceStateGetAttributesPtr)( - DvrSurfaceState* surface_state, size_t surface_index, - DvrSurfaceAttribute* attributes, size_t max_attribute_count); - -// dvr_buffer.h -typedef void (*DvrWriteBufferCreateEmptyPtr)(DvrWriteBuffer** write_buffer_out); -typedef void (*DvrWriteBufferDestroyPtr)(DvrWriteBuffer* write_buffer); -typedef int (*DvrWriteBufferIsValidPtr)(DvrWriteBuffer* write_buffer); -typedef int (*DvrWriteBufferClearPtr)(DvrWriteBuffer* write_buffer); -typedef int (*DvrWriteBufferGetIdPtr)(DvrWriteBuffer* write_buffer); -typedef int (*DvrWriteBufferGetAHardwareBufferPtr)( - DvrWriteBuffer* write_buffer, AHardwareBuffer** hardware_buffer); -typedef int (*DvrWriteBufferPostPtr)(DvrWriteBuffer* write_buffer, - int ready_fence_fd, const void* meta, - size_t meta_size_bytes); -typedef int (*DvrWriteBufferGainPtr)(DvrWriteBuffer* write_buffer, - int* release_fence_fd); -typedef int (*DvrWriteBufferGainAsyncPtr)(DvrWriteBuffer* write_buffer); -typedef const struct native_handle* (*DvrWriteBufferGetNativeHandlePtr)( - DvrWriteBuffer* write_buffer); - -typedef void (*DvrReadBufferCreateEmptyPtr)(DvrReadBuffer** read_buffer_out); -typedef void (*DvrReadBufferDestroyPtr)(DvrReadBuffer* read_buffer); -typedef int (*DvrReadBufferIsValidPtr)(DvrReadBuffer* read_buffer); -typedef int (*DvrReadBufferClearPtr)(DvrReadBuffer* read_buffer); -typedef int (*DvrReadBufferGetIdPtr)(DvrReadBuffer* read_buffer); -typedef int (*DvrReadBufferGetAHardwareBufferPtr)( - DvrReadBuffer* read_buffer, AHardwareBuffer** hardware_buffer); -typedef int (*DvrReadBufferAcquirePtr)(DvrReadBuffer* read_buffer, - int* ready_fence_fd, void* meta, - size_t meta_size_bytes); -typedef int (*DvrReadBufferReleasePtr)(DvrReadBuffer* read_buffer, - int release_fence_fd); -typedef int (*DvrReadBufferReleaseAsyncPtr)(DvrReadBuffer* read_buffer); -typedef const struct native_handle* (*DvrReadBufferGetNativeHandlePtr)( - DvrReadBuffer* read_buffer); - -typedef void (*DvrBufferDestroyPtr)(DvrBuffer* buffer); -typedef int (*DvrBufferGetAHardwareBufferPtr)( - DvrBuffer* buffer, AHardwareBuffer** hardware_buffer); -typedef int (*DvrBufferGlobalLayoutVersionGetPtr)(); -typedef const struct native_handle* (*DvrBufferGetNativeHandlePtr)( - DvrBuffer* buffer); - -// dvr_buffer_queue.h -typedef int (*DvrWriteBufferQueueCreatePtr)(uint32_t width, uint32_t height, - uint32_t format, - uint32_t layer_count, - uint64_t usage, size_t capacity, - size_t metadata_size, - DvrWriteBufferQueue** queue_out); -typedef void (*DvrWriteBufferQueueDestroyPtr)(DvrWriteBufferQueue* write_queue); -typedef ssize_t (*DvrWriteBufferQueueGetCapacityPtr)( - DvrWriteBufferQueue* write_queue); -typedef int (*DvrWriteBufferQueueGetIdPtr)(DvrWriteBufferQueue* write_queue); -typedef int (*DvrWriteBufferQueueGetExternalSurfacePtr)( - DvrWriteBufferQueue* write_queue, ANativeWindow** out_window); -typedef int (*DvrWriteBufferQueueGetANativeWindowPtr)( - DvrWriteBufferQueue* write_queue, ANativeWindow** out_window); -typedef int (*DvrWriteBufferQueueCreateReadQueuePtr)( - DvrWriteBufferQueue* write_queue, DvrReadBufferQueue** out_read_queue); -typedef int (*DvrWriteBufferQueueDequeuePtr)(DvrWriteBufferQueue* write_queue, - int timeout, - DvrWriteBuffer* out_buffer, - int* out_fence_fd); -typedef int (*DvrWriteBufferQueueGainBufferPtr)( - DvrWriteBufferQueue* write_queue, int timeout, - DvrWriteBuffer** out_write_buffer, DvrNativeBufferMetadata* out_meta, - int* out_fence_fd); -typedef int (*DvrWriteBufferQueuePostBufferPtr)( - DvrWriteBufferQueue* write_queue, DvrWriteBuffer* write_buffer, - const DvrNativeBufferMetadata* meta, int ready_fence_fd); -typedef int (*DvrWriteBufferQueueResizeBufferPtr)( - DvrWriteBufferQueue* write_queue, uint32_t width, uint32_t height); -typedef void (*DvrReadBufferQueueDestroyPtr)(DvrReadBufferQueue* read_queue); -typedef ssize_t (*DvrReadBufferQueueGetCapacityPtr)( - DvrReadBufferQueue* read_queue); -typedef int (*DvrReadBufferQueueGetIdPtr)(DvrReadBufferQueue* read_queue); -typedef int (*DvrReadBufferQueueGetEventFdPtr)(DvrReadBufferQueue* read_queue); -typedef int (*DvrReadBufferQueueCreateReadQueuePtr)( - DvrReadBufferQueue* read_queue, DvrReadBufferQueue** out_read_queue); -typedef int (*DvrReadBufferQueueDequeuePtr)(DvrReadBufferQueue* read_queue, - int timeout, - DvrReadBuffer* out_buffer, - int* out_fence_fd, void* out_meta, - size_t meta_size_bytes); -typedef int (*DvrReadBufferQueueAcquireBufferPtr)( - DvrReadBufferQueue* read_queue, int timeout, - DvrReadBuffer** out_read_buffer, DvrNativeBufferMetadata* out_meta, - int* out_fence_fd); -typedef int (*DvrReadBufferQueueReleaseBufferPtr)( - DvrReadBufferQueue* read_queue, DvrReadBuffer* read_buffer, - const DvrNativeBufferMetadata* meta, int release_fence_fd); -typedef void (*DvrReadBufferQueueBufferAvailableCallback)(void* context); -typedef int (*DvrReadBufferQueueSetBufferAvailableCallbackPtr)( - DvrReadBufferQueue* read_queue, - DvrReadBufferQueueBufferAvailableCallback callback, void* context); -typedef void (*DvrReadBufferQueueBufferRemovedCallback)(DvrReadBuffer* buffer, - void* context); -typedef int (*DvrReadBufferQueueSetBufferRemovedCallbackPtr)( - DvrReadBufferQueue* read_queue, - DvrReadBufferQueueBufferRemovedCallback callback, void* context); -typedef int (*DvrReadBufferQueueHandleEventsPtr)( - DvrReadBufferQueue* read_queue); - -// dvr_surface.h -typedef int (*DvrSetupGlobalBufferPtr)(DvrGlobalBufferKey key, size_t size, - uint64_t usage, DvrBuffer** buffer_out); -typedef int (*DvrDeleteGlobalBufferPtr)(DvrGlobalBufferKey key); -typedef int (*DvrGetGlobalBufferPtr)(DvrGlobalBufferKey key, - DvrBuffer** out_buffer); -typedef int (*DvrSurfaceCreatePtr)(const DvrSurfaceAttribute* attributes, - size_t attribute_count, - DvrSurface** surface_out); -typedef void (*DvrSurfaceDestroyPtr)(DvrSurface* surface); -typedef int (*DvrSurfaceGetIdPtr)(DvrSurface* surface); -typedef int (*DvrSurfaceSetAttributesPtr)(DvrSurface* surface, - const DvrSurfaceAttribute* attributes, - size_t attribute_count); -typedef int (*DvrSurfaceCreateWriteBufferQueuePtr)( - DvrSurface* surface, uint32_t width, uint32_t height, uint32_t format, - uint32_t layer_count, uint64_t usage, size_t capacity, size_t metadata_size, - DvrWriteBufferQueue** queue_out); -typedef int (*DvrGetNativeDisplayMetricsPtr)(size_t sizeof_metrics, - DvrNativeDisplayMetrics* metrics); - -// dvr_vsync.h -typedef int (*DvrVSyncClientCreatePtr)(DvrVSyncClient** client_out); -typedef void (*DvrVSyncClientDestroyPtr)(DvrVSyncClient* client); -typedef int (*DvrVSyncClientGetSchedInfoPtr)(DvrVSyncClient* client, - int64_t* vsync_period_ns, - int64_t* next_timestamp_ns, - uint32_t* next_vsync_count); - -// libs/vr/libvrsensor/include/dvr/pose_client.h -typedef DvrPoseClient* (*DvrPoseClientCreatePtr)(); -typedef void (*DvrPoseClientDestroyPtr)(DvrPoseClient* client); -typedef int (*DvrPoseClientGetPtr)(DvrPoseClient* client, uint32_t vsync_count, - DvrPoseAsync* out_pose); -typedef uint32_t (*DvrPoseClientGetVsyncCountPtr)(DvrPoseClient* client); -typedef int (*DvrPoseClientGetControllerPtr)(DvrPoseClient* client, - int32_t controller_id, - uint32_t vsync_count, - DvrPoseAsync* out_pose); -typedef int (*DvrPoseClientSensorsEnablePtr)(DvrPoseClient* client, - bool enabled); -typedef int (*DvrPoseClientDataCapturePtr)(DvrPoseClient* client, - const DvrPoseDataCaptureRequest* request); -typedef int (*DvrPoseClientDataReaderDestroyPtr)(DvrPoseClient* client, - uint64_t data_type); - -// dvr_pose.h -typedef int (*DvrPoseClientGetDataReaderPtr)(DvrPoseClient* client, - uint64_t data_type, - DvrReadBufferQueue** read_queue); - -// services/vr/virtual_touchpad/include/dvr/virtual_touchpad_client.h - -// Touchpad IDs for *Touch*() and *ButtonState*() calls. -enum { - DVR_VIRTUAL_TOUCHPAD_PRIMARY = 0, - DVR_VIRTUAL_TOUCHPAD_VIRTUAL = 1, -}; -typedef DvrVirtualTouchpad* (*DvrVirtualTouchpadCreatePtr)(); -typedef void (*DvrVirtualTouchpadDestroyPtr)(DvrVirtualTouchpad* client); -typedef int (*DvrVirtualTouchpadAttachPtr)(DvrVirtualTouchpad* client); -typedef int (*DvrVirtualTouchpadDetachPtr)(DvrVirtualTouchpad* client); -typedef int (*DvrVirtualTouchpadTouchPtr)(DvrVirtualTouchpad* client, - int touchpad, float x, float y, - float pressure); -typedef int (*DvrVirtualTouchpadButtonStatePtr)(DvrVirtualTouchpad* client, - int touchpad, int buttons); -typedef int (*DvrVirtualTouchpadScrollPtr)(DvrVirtualTouchpad* client, - int touchpad, float x, float y); - -// dvr_hardware_composer_client.h -typedef struct DvrHwcClient DvrHwcClient; -typedef struct DvrHwcFrame DvrHwcFrame; -typedef int (*DvrHwcOnFrameCallback)(void* client_state, DvrHwcFrame* frame); -typedef DvrHwcClient* (*DvrHwcClientCreatePtr)(DvrHwcOnFrameCallback callback, - void* client_state); -typedef void (*DvrHwcClientDestroyPtr)(DvrHwcClient* client); -typedef void (*DvrHwcFrameDestroyPtr)(DvrHwcFrame* frame); -typedef DvrHwcDisplay (*DvrHwcFrameGetDisplayIdPtr)(DvrHwcFrame* frame); -typedef int32_t (*DvrHwcFrameGetDisplayWidthPtr)(DvrHwcFrame* frame); -typedef int32_t (*DvrHwcFrameGetDisplayHeightPtr)(DvrHwcFrame* frame); -typedef bool (*DvrHwcFrameGetDisplayRemovedPtr)(DvrHwcFrame* frame); -typedef size_t (*DvrHwcFrameGetLayerCountPtr)(DvrHwcFrame* frame); -typedef DvrHwcLayer (*DvrHwcFrameGetLayerIdPtr)(DvrHwcFrame* frame, - size_t layer_index); -typedef uint32_t (*DvrHwcFrameGetActiveConfigPtr)(DvrHwcFrame* frame); -typedef uint32_t (*DvrHwcFrameGetColorModePtr)(DvrHwcFrame* frame); -typedef void (*DvrHwcFrameGetColorTransformPtr)(DvrHwcFrame* frame, - float* out_matrix, - int32_t* out_hint); -typedef uint32_t (*DvrHwcFrameGetPowerModePtr)(DvrHwcFrame* frame); -typedef uint32_t (*DvrHwcFrameGetVsyncEnabledPtr)(DvrHwcFrame* frame); -typedef AHardwareBuffer* (*DvrHwcFrameGetLayerBufferPtr)(DvrHwcFrame* frame, - size_t layer_index); -typedef int (*DvrHwcFrameGetLayerFencePtr)(DvrHwcFrame* frame, - size_t layer_index); -typedef DvrHwcRecti (*DvrHwcFrameGetLayerDisplayFramePtr)(DvrHwcFrame* frame, - size_t layer_index); -typedef DvrHwcRectf (*DvrHwcFrameGetLayerCropPtr)(DvrHwcFrame* frame, - size_t layer_index); -typedef DvrHwcBlendMode (*DvrHwcFrameGetLayerBlendModePtr)(DvrHwcFrame* frame, - size_t layer_index); -typedef float (*DvrHwcFrameGetLayerAlphaPtr)(DvrHwcFrame* frame, - size_t layer_index); -typedef uint32_t (*DvrHwcFrameGetLayerTypePtr)(DvrHwcFrame* frame, - size_t layer_index); -typedef uint32_t (*DvrHwcFrameGetLayerApplicationIdPtr)(DvrHwcFrame* frame, - size_t layer_index); -typedef uint32_t (*DvrHwcFrameGetLayerZOrderPtr)(DvrHwcFrame* frame, - size_t layer_index); - -typedef void (*DvrHwcFrameGetLayerCursorPtr)(DvrHwcFrame* frame, - size_t layer_index, int32_t* out_x, - int32_t* out_y); - -typedef uint32_t (*DvrHwcFrameGetLayerTransformPtr)(DvrHwcFrame* frame, - size_t layer_index); - -typedef uint32_t (*DvrHwcFrameGetLayerDataspacePtr)(DvrHwcFrame* frame, - size_t layer_index); - -typedef uint32_t (*DvrHwcFrameGetLayerColorPtr)(DvrHwcFrame* frame, - size_t layer_index); - -typedef uint32_t (*DvrHwcFrameGetLayerNumVisibleRegionsPtr)(DvrHwcFrame* frame, - size_t layer_index); -typedef DvrHwcRecti (*DvrHwcFrameGetLayerVisibleRegionPtr)(DvrHwcFrame* frame, - size_t layer_index, - size_t index); - -typedef uint32_t (*DvrHwcFrameGetLayerNumDamagedRegionsPtr)(DvrHwcFrame* frame, - size_t layer_index); -typedef DvrHwcRecti (*DvrHwcFrameGetLayerDamagedRegionPtr)(DvrHwcFrame* frame, - size_t layer_index, - size_t index); - -// dvr_performance.h -typedef int (*DvrPerformanceSetSchedulerPolicyPtr)( - pid_t task_id, const char* scheduler_policy); - -// dvr_tracking.h -typedef int (*DvrTrackingCameraCreatePtr)(DvrTrackingCamera** out_camera); -typedef void (*DvrTrackingCameraDestroyPtr)(DvrTrackingCamera* camera); -typedef int (*DvrTrackingCameraStartPtr)(DvrTrackingCamera* camera, - DvrWriteBufferQueue* write_queue); -typedef int (*DvrTrackingCameraStopPtr)(DvrTrackingCamera* camera); - -typedef int (*DvrTrackingFeatureExtractorCreatePtr)( - DvrTrackingFeatureExtractor** out_extractor); -typedef void (*DvrTrackingFeatureExtractorDestroyPtr)( - DvrTrackingFeatureExtractor* extractor); -typedef void (*DvrTrackingFeatureCallback)(void* context, - const DvrTrackingFeatures* event); -typedef int (*DvrTrackingFeatureExtractorStartPtr)( - DvrTrackingFeatureExtractor* extractor, - DvrTrackingFeatureCallback callback, void* context); -typedef int (*DvrTrackingFeatureExtractorStopPtr)( - DvrTrackingFeatureExtractor* extractor); -typedef int (*DvrTrackingFeatureExtractorProcessBufferPtr)( - DvrTrackingFeatureExtractor* extractor, DvrReadBuffer* buffer, - const DvrTrackingBufferMetadata* metadata, bool* out_skipped); - -typedef void (*DvrTrackingSensorEventCallback)(void* context, - DvrTrackingSensorEvent* event); -typedef int (*DvrTrackingSensorsCreatePtr)(DvrTrackingSensors** out_sensors, - const char* mode); -typedef void (*DvrTrackingSensorsDestroyPtr)(DvrTrackingSensors* sensors); -typedef int (*DvrTrackingSensorsStartPtr)( - DvrTrackingSensors* sensors, DvrTrackingSensorEventCallback callback, - void* context); -typedef int (*DvrTrackingSensorsStopPtr)(DvrTrackingSensors* sensors); - -// The buffer metadata that an Android Surface (a.k.a. ANativeWindow) -// will populate. A DvrWriteBufferQueue must be created with this metadata iff -// ANativeWindow access is needed. Please do not remove, modify, or reorder -// existing data members. If new fields need to be added, please take extra care -// to make sure that new data field is padded properly the size of the struct -// stays same. -// TODO(b/118893702): move the definition to libnativewindow or libui -struct ALIGNED_DVR_STRUCT(8) DvrNativeBufferMetadata { -#ifdef __cplusplus - DvrNativeBufferMetadata() - : timestamp(0), - is_auto_timestamp(0), - dataspace(0), - crop_left(0), - crop_top(0), - crop_right(0), - crop_bottom(0), - scaling_mode(0), - transform(0), - index(0), - user_metadata_size(0), - user_metadata_ptr(0), - release_fence_mask(0), - reserved{0} {} -#endif - // Timestamp of the frame. - int64_t timestamp; - - // Whether the buffer is using auto timestamp. - int32_t is_auto_timestamp; - - // Must be one of the HAL_DATASPACE_XXX value defined in system/graphics.h - int32_t dataspace; - - // Crop extracted from an ACrop or android::Crop object. - int32_t crop_left; - int32_t crop_top; - int32_t crop_right; - int32_t crop_bottom; - - // Must be one of the NATIVE_WINDOW_SCALING_MODE_XXX value defined in - // system/window.h. - int32_t scaling_mode; - - // Must be one of the ANATIVEWINDOW_TRANSFORM_XXX value defined in - // android/native_window.h - int32_t transform; - - // The index of the frame. - int64_t index; - - // Size of additional metadata requested by user. - uint64_t user_metadata_size; - - // Raw memory address of the additional user defined metadata. Only valid when - // user_metadata_size is non-zero. - uint64_t user_metadata_ptr; - - // Only applicable for metadata retrieved from GainAsync. This indicates which - // consumer has pending fence that producer should epoll on. - uint32_t release_fence_mask; - - // Reserved bytes for so that the struct is forward compatible and padding to - // 104 bytes so the size is a multiple of 8. - int32_t reserved[9]; -}; - -#ifdef __cplusplus -// Warning: DvrNativeBufferMetadata is part of the DVR API and changing its size -// will cause compatiblity issues between different DVR API releases. -static_assert(sizeof(DvrNativeBufferMetadata) == 104, - "Unexpected size for DvrNativeBufferMetadata"); -#endif - -struct DvrApi_v1 { -// Defines an API entry for V1 (no version suffix). -#define DVR_V1_API_ENTRY(name) Dvr##name##Ptr name -#define DVR_V1_API_ENTRY_DEPRECATED(name) Dvr##name##Ptr name - -#include "dvr_api_entries.h" - -// Undefine macro definitions to play nice with Google3 style rules. -#undef DVR_V1_API_ENTRY -#undef DVR_V1_API_ENTRY_DEPRECATED -}; - -int dvrGetApi(void* api, size_t struct_size, int version); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // ANDROID_DVR_API_H_ diff --git a/libs/vr/libdvr/include/dvr/dvr_api_entries.h b/libs/vr/libdvr/include/dvr/dvr_api_entries.h deleted file mode 100644 index 3006b61b81..0000000000 --- a/libs/vr/libdvr/include/dvr/dvr_api_entries.h +++ /dev/null @@ -1,200 +0,0 @@ -// dvr_api_entries.h -// -// Defines the DVR platform library API entries. -// -// Do not include this header directly. - -#ifndef DVR_V1_API_ENTRY -#error Do not include this header directly. -#endif - -#ifndef DVR_V1_API_ENTRY_DEPRECATED -#error Do not include this header directly. -#endif - -// Do not delete this line: BEGIN CODEGEN OUTPUT -// Display manager client -DVR_V1_API_ENTRY(DisplayManagerCreate); -DVR_V1_API_ENTRY(DisplayManagerDestroy); -DVR_V1_API_ENTRY(DisplayManagerGetEventFd); -DVR_V1_API_ENTRY(DisplayManagerTranslateEpollEventMask); -DVR_V1_API_ENTRY(DisplayManagerGetSurfaceState); -DVR_V1_API_ENTRY(DisplayManagerGetReadBufferQueue); -DVR_V1_API_ENTRY(ConfigurationDataGet); -DVR_V1_API_ENTRY(ConfigurationDataDestroy); -DVR_V1_API_ENTRY(SurfaceStateCreate); -DVR_V1_API_ENTRY(SurfaceStateDestroy); -DVR_V1_API_ENTRY(SurfaceStateGetSurfaceCount); -DVR_V1_API_ENTRY(SurfaceStateGetUpdateFlags); -DVR_V1_API_ENTRY(SurfaceStateGetSurfaceId); -DVR_V1_API_ENTRY(SurfaceStateGetProcessId); -DVR_V1_API_ENTRY(SurfaceStateGetQueueCount); -DVR_V1_API_ENTRY(SurfaceStateGetQueueIds); -DVR_V1_API_ENTRY(SurfaceStateGetZOrder); -DVR_V1_API_ENTRY(SurfaceStateGetVisible); -DVR_V1_API_ENTRY(SurfaceStateGetAttributeCount); -DVR_V1_API_ENTRY(SurfaceStateGetAttributes); - -// Write buffer -DVR_V1_API_ENTRY_DEPRECATED(WriteBufferCreateEmpty); -DVR_V1_API_ENTRY(WriteBufferDestroy); -DVR_V1_API_ENTRY(WriteBufferIsValid); -DVR_V1_API_ENTRY_DEPRECATED(WriteBufferClear); -DVR_V1_API_ENTRY(WriteBufferGetId); -DVR_V1_API_ENTRY(WriteBufferGetAHardwareBuffer); -DVR_V1_API_ENTRY_DEPRECATED(WriteBufferPost); -DVR_V1_API_ENTRY_DEPRECATED(WriteBufferGain); -DVR_V1_API_ENTRY_DEPRECATED(WriteBufferGainAsync); -DVR_V1_API_ENTRY_DEPRECATED(WriteBufferGetNativeHandle); - -// Read buffer -DVR_V1_API_ENTRY_DEPRECATED(ReadBufferCreateEmpty); -DVR_V1_API_ENTRY(ReadBufferDestroy); -DVR_V1_API_ENTRY(ReadBufferIsValid); -DVR_V1_API_ENTRY_DEPRECATED(ReadBufferClear); -DVR_V1_API_ENTRY(ReadBufferGetId); -DVR_V1_API_ENTRY(ReadBufferGetAHardwareBuffer); -DVR_V1_API_ENTRY_DEPRECATED(ReadBufferAcquire); -DVR_V1_API_ENTRY_DEPRECATED(ReadBufferRelease); -DVR_V1_API_ENTRY_DEPRECATED(ReadBufferReleaseAsync); -DVR_V1_API_ENTRY_DEPRECATED(ReadBufferGetNativeHandle); - -// Buffer -DVR_V1_API_ENTRY(BufferDestroy); -DVR_V1_API_ENTRY(BufferGetAHardwareBuffer); -DVR_V1_API_ENTRY_DEPRECATED(BufferGetNativeHandle); -DVR_V1_API_ENTRY(BufferGlobalLayoutVersionGet); - -// Write buffer queue -DVR_V1_API_ENTRY(WriteBufferQueueDestroy); -DVR_V1_API_ENTRY(WriteBufferQueueGetCapacity); -DVR_V1_API_ENTRY(WriteBufferQueueGetId); -DVR_V1_API_ENTRY_DEPRECATED(WriteBufferQueueGetExternalSurface); -DVR_V1_API_ENTRY(WriteBufferQueueCreateReadQueue); -DVR_V1_API_ENTRY_DEPRECATED(WriteBufferQueueDequeue); -DVR_V1_API_ENTRY(WriteBufferQueueResizeBuffer); - -// Read buffer queue -DVR_V1_API_ENTRY(ReadBufferQueueDestroy); -DVR_V1_API_ENTRY(ReadBufferQueueGetCapacity); -DVR_V1_API_ENTRY(ReadBufferQueueGetId); -DVR_V1_API_ENTRY(ReadBufferQueueCreateReadQueue); -DVR_V1_API_ENTRY_DEPRECATED(ReadBufferQueueDequeue); -DVR_V1_API_ENTRY(ReadBufferQueueSetBufferAvailableCallback); -DVR_V1_API_ENTRY(ReadBufferQueueSetBufferRemovedCallback); -DVR_V1_API_ENTRY(ReadBufferQueueHandleEvents); - -// V-Sync client -DVR_V1_API_ENTRY_DEPRECATED(VSyncClientCreate); -DVR_V1_API_ENTRY_DEPRECATED(VSyncClientDestroy); -DVR_V1_API_ENTRY_DEPRECATED(VSyncClientGetSchedInfo); - -// Display surface -DVR_V1_API_ENTRY(SurfaceCreate); -DVR_V1_API_ENTRY(SurfaceDestroy); -DVR_V1_API_ENTRY(SurfaceGetId); -DVR_V1_API_ENTRY(SurfaceSetAttributes); -DVR_V1_API_ENTRY(SurfaceCreateWriteBufferQueue); -DVR_V1_API_ENTRY(SetupGlobalBuffer); -DVR_V1_API_ENTRY(DeleteGlobalBuffer); -DVR_V1_API_ENTRY(GetGlobalBuffer); - -// Pose client -DVR_V1_API_ENTRY(PoseClientCreate); -DVR_V1_API_ENTRY(PoseClientDestroy); -DVR_V1_API_ENTRY(PoseClientGet); -DVR_V1_API_ENTRY(PoseClientGetVsyncCount); -DVR_V1_API_ENTRY(PoseClientGetController); - -// Virtual touchpad client -DVR_V1_API_ENTRY(VirtualTouchpadCreate); -DVR_V1_API_ENTRY(VirtualTouchpadDestroy); -DVR_V1_API_ENTRY(VirtualTouchpadAttach); -DVR_V1_API_ENTRY(VirtualTouchpadDetach); -DVR_V1_API_ENTRY(VirtualTouchpadTouch); -DVR_V1_API_ENTRY(VirtualTouchpadButtonState); - -// VR HWComposer client -DVR_V1_API_ENTRY(HwcClientCreate); -DVR_V1_API_ENTRY(HwcClientDestroy); -DVR_V1_API_ENTRY(HwcFrameDestroy); -DVR_V1_API_ENTRY(HwcFrameGetDisplayId); -DVR_V1_API_ENTRY(HwcFrameGetDisplayWidth); -DVR_V1_API_ENTRY(HwcFrameGetDisplayHeight); -DVR_V1_API_ENTRY(HwcFrameGetDisplayRemoved); -DVR_V1_API_ENTRY(HwcFrameGetActiveConfig); -DVR_V1_API_ENTRY(HwcFrameGetColorMode); -DVR_V1_API_ENTRY(HwcFrameGetColorTransform); -DVR_V1_API_ENTRY(HwcFrameGetPowerMode); -DVR_V1_API_ENTRY(HwcFrameGetVsyncEnabled); -DVR_V1_API_ENTRY(HwcFrameGetLayerCount); -DVR_V1_API_ENTRY(HwcFrameGetLayerId); -DVR_V1_API_ENTRY(HwcFrameGetLayerBuffer); -DVR_V1_API_ENTRY(HwcFrameGetLayerFence); -DVR_V1_API_ENTRY(HwcFrameGetLayerDisplayFrame); -DVR_V1_API_ENTRY(HwcFrameGetLayerCrop); -DVR_V1_API_ENTRY(HwcFrameGetLayerBlendMode); -DVR_V1_API_ENTRY(HwcFrameGetLayerAlpha); -DVR_V1_API_ENTRY(HwcFrameGetLayerType); -DVR_V1_API_ENTRY(HwcFrameGetLayerApplicationId); -DVR_V1_API_ENTRY(HwcFrameGetLayerZOrder); -DVR_V1_API_ENTRY(HwcFrameGetLayerCursor); -DVR_V1_API_ENTRY(HwcFrameGetLayerTransform); -DVR_V1_API_ENTRY(HwcFrameGetLayerDataspace); -DVR_V1_API_ENTRY(HwcFrameGetLayerColor); -DVR_V1_API_ENTRY(HwcFrameGetLayerNumVisibleRegions); -DVR_V1_API_ENTRY(HwcFrameGetLayerVisibleRegion); -DVR_V1_API_ENTRY(HwcFrameGetLayerNumDamagedRegions); -DVR_V1_API_ENTRY(HwcFrameGetLayerDamagedRegion); - -// New entries added at the end to allow the DVR platform library API -// to be updated before updating VrCore. - -// Virtual touchpad client -DVR_V1_API_ENTRY(VirtualTouchpadScroll); - -// Read the native display metrics from the hardware composer -DVR_V1_API_ENTRY(GetNativeDisplayMetrics); - -// Performance -DVR_V1_API_ENTRY(PerformanceSetSchedulerPolicy); - -// Pose client -DVR_V1_API_ENTRY(PoseClientSensorsEnable); - -// Read buffer queue -DVR_V1_API_ENTRY(ReadBufferQueueGetEventFd); - -// Create write buffer queue locally -DVR_V1_API_ENTRY(WriteBufferQueueCreate); - -// Gets an ANativeWindow from DvrWriteBufferQueue. -DVR_V1_API_ENTRY(WriteBufferQueueGetANativeWindow); - -// Dvr{Read,Write}BufferQueue API for asynchronous IPC. -DVR_V1_API_ENTRY(WriteBufferQueueGainBuffer); -DVR_V1_API_ENTRY(WriteBufferQueuePostBuffer); -DVR_V1_API_ENTRY(ReadBufferQueueAcquireBuffer); -DVR_V1_API_ENTRY(ReadBufferQueueReleaseBuffer); - -// Pose client -DVR_V1_API_ENTRY(PoseClientGetDataReader); -DVR_V1_API_ENTRY(PoseClientDataCapture); -DVR_V1_API_ENTRY(PoseClientDataReaderDestroy); - -// Tracking -DVR_V1_API_ENTRY(TrackingCameraCreate); -DVR_V1_API_ENTRY(TrackingCameraDestroy); -DVR_V1_API_ENTRY(TrackingCameraStart); -DVR_V1_API_ENTRY(TrackingCameraStop); - -DVR_V1_API_ENTRY(TrackingFeatureExtractorCreate); -DVR_V1_API_ENTRY(TrackingFeatureExtractorDestroy); -DVR_V1_API_ENTRY(TrackingFeatureExtractorStart); -DVR_V1_API_ENTRY(TrackingFeatureExtractorStop); -DVR_V1_API_ENTRY(TrackingFeatureExtractorProcessBuffer); - -DVR_V1_API_ENTRY(TrackingSensorsCreate); -DVR_V1_API_ENTRY(TrackingSensorsDestroy); -DVR_V1_API_ENTRY(TrackingSensorsStart); -DVR_V1_API_ENTRY(TrackingSensorsStop); diff --git a/libs/vr/libdvr/include/dvr/dvr_buffer.h b/libs/vr/libdvr/include/dvr/dvr_buffer.h deleted file mode 100644 index 4234844c0f..0000000000 --- a/libs/vr/libdvr/include/dvr/dvr_buffer.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef ANDROID_DVR_BUFFER_H_ -#define ANDROID_DVR_BUFFER_H_ - -#include <stdbool.h> -#include <stdint.h> -#include <sys/cdefs.h> -#include <memory> - -__BEGIN_DECLS - -typedef struct DvrWriteBuffer DvrWriteBuffer; -typedef struct DvrReadBuffer DvrReadBuffer; -typedef struct DvrBuffer DvrBuffer; -typedef struct AHardwareBuffer AHardwareBuffer; -struct native_handle; - -// Destroys the write buffer. -void dvrWriteBufferDestroy(DvrWriteBuffer* write_buffer); - -// Returns 1 if the given write buffer object contains a buffer, 0 otherwise. -int dvrWriteBufferIsValid(DvrWriteBuffer* write_buffer); - -// Returns the global BufferHub id of this buffer. -int dvrWriteBufferGetId(DvrWriteBuffer* write_buffer); - -// Returns an AHardwareBuffer for the underlying buffer. -// Caller must call AHardwareBuffer_release on hardware_buffer. -int dvrWriteBufferGetAHardwareBuffer(DvrWriteBuffer* write_buffer, - AHardwareBuffer** hardware_buffer); - -// Destroys the read buffer. -void dvrReadBufferDestroy(DvrReadBuffer* read_buffer); - -// Returns 1 if the given write buffer object contains a buffer, 0 otherwise. -int dvrReadBufferIsValid(DvrReadBuffer* read_buffer); - -// Returns the global BufferHub id of this buffer. -int dvrReadBufferGetId(DvrReadBuffer* read_buffer); - -// Returns an AHardwareBuffer for the underlying buffer. -// Caller must call AHardwareBuffer_release on hardware_buffer. -int dvrReadBufferGetAHardwareBuffer(DvrReadBuffer* read_buffer, - AHardwareBuffer** hardware_buffer); - -// Destroys the buffer. -void dvrBufferDestroy(DvrBuffer* buffer); - -// Gets an AHardwareBuffer from the buffer. -// Caller must call AHardwareBuffer_release on hardware_buffer. -int dvrBufferGetAHardwareBuffer(DvrBuffer* buffer, - AHardwareBuffer** hardware_buffer); - -// Retrieve the shared buffer layout version defined in dvr_shared_buffers.h. -int dvrBufferGlobalLayoutVersionGet(); - -__END_DECLS - -#endif // ANDROID_DVR_BUFFER_H_ diff --git a/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h b/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h deleted file mode 100644 index ac789daf3d..0000000000 --- a/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h +++ /dev/null @@ -1,263 +0,0 @@ -#ifndef ANDROID_DVR_BUFFER_QUEUE_H_ -#define ANDROID_DVR_BUFFER_QUEUE_H_ - -#include <sys/cdefs.h> - -#include <dvr/dvr_buffer.h> - -__BEGIN_DECLS - -typedef struct ANativeWindow ANativeWindow; - -typedef struct DvrWriteBufferQueue DvrWriteBufferQueue; -typedef struct DvrReadBufferQueue DvrReadBufferQueue; - -// Creates a write buffer queue to be used locally. -// -// Note that this API is mostly for testing purpose. For now there is no -// mechanism to send a DvrWriteBufferQueue cross process. Use -// dvrSurfaceCreateWriteBufferQueue if cross-process buffer transport is -// intended. -// -// @param width The width of the buffers that this queue will produce. -// @param height The height of buffers that this queue will produce. -// @param format The format of the buffers that this queue will produce. This -// must be one of the AHARDWAREBUFFER_FORMAT_XXX enums. -// @param layer_count The number of layers of the buffers that this queue will -// produce. -// @param usage The usage of the buffers that this queue will produce. This -// must a combination of the AHARDWAREBUFFER_USAGE_XXX flags. -// @param capacity The number of buffer that this queue will allocate. Note that -// all buffers will be allocated on create. Currently, the number of buffers -// is the queue cannot be changed after creation though DVR API. However, -// ANativeWindow can choose to reallocate, attach, or detach buffers from -// a DvrWriteBufferQueue through Android platform logic. -// @param metadata_size The size of metadata in bytes. -// @param out_write_queue The pointer of a DvrWriteBufferQueue will be filled -// here if the method call succeeds. The metadata size must match -// the metadata size in dvrWriteBufferPost/dvrReadBufferAcquire. -// @return Zero on success, or negative error code. -int dvrWriteBufferQueueCreate(uint32_t width, uint32_t height, uint32_t format, - uint32_t layer_count, uint64_t usage, - size_t capacity, size_t metadata_size, - DvrWriteBufferQueue** out_write_queue); - -// Destroy a write buffer queue. -// -// @param write_queue The DvrWriteBufferQueue of interest. -void dvrWriteBufferQueueDestroy(DvrWriteBufferQueue* write_queue); - -// Get the total number of buffers in a write buffer queue. -// -// @param write_queue The DvrWriteBufferQueue of interest. -// @return The capacity on success; or negative error code. -ssize_t dvrWriteBufferQueueGetCapacity(DvrWriteBufferQueue* write_queue); - -// Get the system unique queue id of a write buffer queue. -// -// @param write_queue The DvrWriteBufferQueue of interest. -// @return Queue id on success; or negative error code. -int dvrWriteBufferQueueGetId(DvrWriteBufferQueue* write_queue); - -// Gets an ANativeWindow backed by the DvrWriteBufferQueue -// -// Can be casted to a Java Surface using ANativeWindow_toSurface NDK API. Note -// that the native window is lazily created at the first time |GetNativeWindow| -// is called, and the created ANativeWindow will be cached so that multiple -// calls to this method will return the same object. Also note that this method -// does not acquire an additional reference to the ANativeWindow returned, don't -// call ANativeWindow_release on it. -// -// @param write_queue The DvrWriteBufferQueue of interest. -// @param out_window The pointer of an ANativeWindow will be filled here if -// the method call succeeds. -// @return Zero on success; or -EINVAL if this DvrWriteBufferQueue does not -// support being used as an android Surface. -int dvrWriteBufferQueueGetANativeWindow(DvrWriteBufferQueue* write_queue, - ANativeWindow** out_window); - -// Create a read buffer queue from an existing write buffer queue. -// -// @param write_queue The DvrWriteBufferQueue of interest. -// @param out_read_queue The pointer of a DvrReadBufferQueue will be filled here -// if the method call succeeds. -// @return Zero on success, or negative error code. -int dvrWriteBufferQueueCreateReadQueue(DvrWriteBufferQueue* write_queue, - DvrReadBufferQueue** out_read_queue); - -// Gains a buffer to write into. -// -// @param write_queue The DvrWriteBufferQueue to gain buffer from. -// @param timeout Specifies the number of milliseconds that the method will -// block. Specifying a timeout of -1 causes it to block indefinitely, -// while specifying a timeout equal to zero cause it to return immediately, -// even if no buffers are available. -// @param out_buffer A targeting DvrWriteBuffer object to hold the output of the -// dequeue operation. -// @param out_meta A DvrNativeBufferMetadata object populated by the -// corresponding dvrReadBufferQueueReleaseBuffer API. -// @param out_fence_fd A sync fence fd defined in NDK's sync.h API, which -// signals the release of underlying buffer. The producer should wait until -// this fence clears before writing data into it. -// @return Zero on success, or negative error code. -int dvrWriteBufferQueueGainBuffer(DvrWriteBufferQueue* write_queue, int timeout, - DvrWriteBuffer** out_write_buffer, - DvrNativeBufferMetadata* out_meta, - int* out_fence_fd); - -// Posts a buffer and signals its readiness to be read from. -// -// @param write_queue The DvrWriteBufferQueue to post buffer into. -// @param write_buffer The buffer to be posted. -// @param meta The buffer metadata describing the buffer. -// @param ready_fence_fd A sync fence fd defined in NDK's sync.h API, which -// signals the readdiness of underlying buffer. When a valid fence gets -// passed in, the consumer will wait the fence to be ready before it starts -// to ready from the buffer. -// @return Zero on success, or negative error code. -int dvrWriteBufferQueuePostBuffer(DvrWriteBufferQueue* write_queue, - DvrWriteBuffer* write_buffer, - const DvrNativeBufferMetadata* meta, - int ready_fence_fd); - -// Overrides buffer dimension with new width and height. -// -// After the call successfully returns, each |dvrWriteBufferQueueDequeue| call -// will return buffer with newly assigned |width| and |height|. When necessary, -// old buffer will be removed from the buffer queue and replaced with new buffer -// matching the new buffer size. -// -// @param write_queue The DvrWriteBufferQueue of interest. -// @param width Desired width, cannot be Zero. -// @param height Desired height, cannot be Zero. -// @return Zero on success, or negative error code. -int dvrWriteBufferQueueResizeBuffer(DvrWriteBufferQueue* write_queue, - uint32_t width, uint32_t height); - -// Destroy a read buffer queue. -// -// @param read_queue The DvrReadBufferQueue of interest. -void dvrReadBufferQueueDestroy(DvrReadBufferQueue* read_queue); - -// Get the total number of buffers in a read buffer queue. -// -// @param read_queue The DvrReadBufferQueue of interest. -// @return The capacity on success; or negative error code. -ssize_t dvrReadBufferQueueGetCapacity(DvrReadBufferQueue* read_queue); - -// Get the system unique queue id of a read buffer queue. -// -// @param read_queue The DvrReadBufferQueue of interest. -// @return Queue id on success; or negative error code. -int dvrReadBufferQueueGetId(DvrReadBufferQueue* read_queue); - -// Get the event fd that signals when queue updates occur. -// -// Use ReadBufferQueueHandleEvents to trigger registered event callbacks. -// -// @param read_queue The DvrReadBufferQueue of interest. -// @return Fd on success; or negative error code. -int dvrReadBufferQueueGetEventFd(DvrReadBufferQueue* read_queue); - -// Create a read buffer queue from an existing read buffer queue. -// -// @param read_queue The DvrReadBufferQueue of interest. -// @param out_read_queue The pointer of a DvrReadBufferQueue will be filled here -// if the method call succeeds. -// @return Zero on success, or negative error code. -int dvrReadBufferQueueCreateReadQueue(DvrReadBufferQueue* read_queue, - DvrReadBufferQueue** out_read_queue); - -// Dequeues a buffer to read from. -// -// @param read_queue The DvrReadBufferQueue to acquire buffer from. -// @param timeout Specifies the number of milliseconds that the method will -// block. Specifying a timeout of -1 causes it to block indefinitely, -// while specifying a timeout equal to zero cause it to return immediately, -// even if no buffers are available. -// @param out_buffer A targeting DvrReadBuffer object to hold the output of the -// dequeue operation. Must be created by |dvrReadBufferCreateEmpty|. -// @param out_meta A DvrNativeBufferMetadata object populated by the -// corresponding dvrWriteBufferQueuePostBuffer API. -// @param out_fence_fd A sync fence fd defined in NDK's sync.h API, which -// signals the release of underlying buffer. The consumer should wait until -// this fence clears before reading data from it. -// @return Zero on success, or negative error code. -int dvrReadBufferQueueAcquireBuffer(DvrReadBufferQueue* read_queue, int timeout, - DvrReadBuffer** out_read_buffer, - DvrNativeBufferMetadata* out_meta, - int* out_fence_fd); - -// Releases a buffer and signals its readiness to be written into. -// -// @param read_queue The DvrReadBufferQueue to release buffer into. -// @param read_buffer The buffer to be released. -// @param meta The buffer metadata describing the buffer. -// @param release_fence_fd A sync fence fd defined in NDK's sync.h API, which -// signals the readdiness of underlying buffer. When a valid fence gets -// passed in, the producer will wait the fence to be ready before it starts -// to write into the buffer again. -// @return Zero on success, or negative error code. -int dvrReadBufferQueueReleaseBuffer(DvrReadBufferQueue* read_queue, - DvrReadBuffer* read_buffer, - const DvrNativeBufferMetadata* meta, - int release_fence_fd); - -// Callback function which will be called when a buffer is avaiable. -// -// Note that there is no guarantee of thread safety and on which thread the -// callback will be fired. -// -// @param context User provided opaque pointer. -typedef void (*DvrReadBufferQueueBufferAvailableCallback)(void* context); - -// Set buffer avaiable callback. -// -// @param read_queue The DvrReadBufferQueue of interest. -// @param callback The callback function. Set this to NULL if caller no longer -// needs to listen to new buffer available events. -// @param context User provided opaque pointer, will be passed back during -// callback. The caller is responsible for ensuring the validity of the -// context through the life cycle of the DvrReadBufferQueue. -// @return Zero on success, or negative error code. -int dvrReadBufferQueueSetBufferAvailableCallback( - DvrReadBufferQueue* read_queue, - DvrReadBufferQueueBufferAvailableCallback callback, void* context); - -// Callback function which will be called when a buffer is about to be removed. -// -// Note that there is no guarantee of thread safety and on which thread the -// callback will be fired. -// -// @param buffer The buffer being removed. Once the callbacks returns, this -// buffer will be dereferenced from the buffer queue. If user has ever -// cached other DvrReadBuffer/AHardwareBuffer/EglImageKHR objects derived -// from this buffer, it's the user's responsibility to clean them up. -// Note that the ownership of the read buffer is not passed to this -// callback, so it should call dvrReadBufferDestroy on the buffer. -// @param context User provided opaque pointer. -typedef void (*DvrReadBufferQueueBufferRemovedCallback)(DvrReadBuffer* buffer, - void* context); - -// Set buffer removed callback. -// -// @param read_queue The DvrReadBufferQueue of interest. -// @param callback The callback function. Set this to NULL if caller no longer -// needs to listen to buffer removed events. -// @param context User provided opaque pointer, will be passed back during -// callback. The caller is responsible for ensuring the validity of the -// context through the life cycle of the DvrReadBufferQueue. -// @return Zero on success, or negative error code. -int dvrReadBufferQueueSetBufferRemovedCallback( - DvrReadBufferQueue* read_queue, - DvrReadBufferQueueBufferRemovedCallback callback, void* context); - -// Handle all pending events on the read queue. -// -// @param read_queue The DvrReadBufferQueue of interest. -// @return Zero on success, or negative error code. -int dvrReadBufferQueueHandleEvents(DvrReadBufferQueue* read_queue); - -__END_DECLS - -#endif // ANDROID_DVR_BUFFER_QUEUE_H_ diff --git a/libs/vr/libdvr/include/dvr/dvr_config.h b/libs/vr/libdvr/include/dvr/dvr_config.h deleted file mode 100644 index 3d2c0668da..0000000000 --- a/libs/vr/libdvr/include/dvr/dvr_config.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef ANDROID_DVR_CONFIG_H -#define ANDROID_DVR_CONFIG_H - -// This header is shared by VrCore and Android and must be kept in sync. - -#include <stdint.h> -#include <sys/cdefs.h> - -__BEGIN_DECLS - -// This is a shared memory buffer for passing config data from VrCore to -// libvrflinger in SurfaceFlinger. -struct __attribute__((packed, aligned(16))) DvrConfig { - // Offset before vsync to submit frames to hardware composer. - int32_t frame_post_offset_ns{4000000}; - - // If the number of pending fences goes over this count at the point when we - // are about to submit a new frame to HWC, we will drop the frame. This - // should be a signal that the display driver has begun queuing frames. Note - // that with smart displays (with RAM), the fence is signaled earlier than - // the next vsync, at the point when the DMA to the display completes. - // Currently we use a smart display and the EDS timing coincides with zero - // pending fences, so this is 0. - int32_t allowed_pending_fence_count{0}; - - // New fields should always be added to the end for backwards compat. - - // Reserved padding to 16 bytes. - uint8_t pad[8]; -}; - -__END_DECLS - -#endif // ANDROID_DVR_CONFIG_H diff --git a/libs/vr/libdvr/include/dvr/dvr_configuration_data.h b/libs/vr/libdvr/include/dvr/dvr_configuration_data.h deleted file mode 100644 index 22a509f6eb..0000000000 --- a/libs/vr/libdvr/include/dvr/dvr_configuration_data.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef DVR_CONFIGURATION_DATA_H_ -#define DVR_CONFIGURATION_DATA_H_ - -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> -#include <sys/cdefs.h> - -#include <dvr/dvr_display_types.h> -#include <dvr/dvr_surface.h> - -__BEGIN_DECLS - -// Loads device configuration data of DVR_CONFIGURATION_DATA_*. -// @return 0 on success. Otherwise returns a negative error value. -int dvrConfigurationDataGet(int config_type, - uint8_t** data, size_t* data_size); - -// Destroy the configuration data returned from dvrGetConfigurationData. -void dvrConfigurationDataDestroy(uint8_t* data); - -__END_DECLS - -#endif // DVR_CONFIGURATION_DATA_H_ diff --git a/libs/vr/libdvr/include/dvr/dvr_deleter.h b/libs/vr/libdvr/include/dvr/dvr_deleter.h deleted file mode 100644 index fe59d1ffba..0000000000 --- a/libs/vr/libdvr/include/dvr/dvr_deleter.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef ANDROID_DVR_DELETER_H_ -#define ANDROID_DVR_DELETER_H_ - -#include <sys/cdefs.h> - -#include <memory> - -// Header-only C++ helper to delete opaque DVR objects. - -__BEGIN_DECLS - -// Use forward declarations to avoid dependency on other headers. -typedef struct DvrBuffer DvrBuffer; -typedef struct DvrReadBuffer DvrReadBuffer; -typedef struct DvrWriteBuffer DvrWriteBuffer; -typedef struct DvrReadBufferQueue DvrReadBufferQueue; -typedef struct DvrWriteBufferQueue DvrWriteBufferQueue; -typedef struct DvrDisplayManager DvrDisplayManager; -typedef struct DvrSurfaceState DvrSurfaceState; -typedef struct DvrSurface DvrSurface; -typedef struct DvrHwcClient DvrHwcClient; -typedef struct DvrHwcFrame DvrHwcFrame; - -void dvrBufferDestroy(DvrBuffer* buffer); -void dvrReadBufferDestroy(DvrReadBuffer* read_buffer); -void dvrWriteBufferDestroy(DvrWriteBuffer* write_buffer); -void dvrReadBufferQueueDestroy(DvrReadBufferQueue* read_queue); -void dvrWriteBufferQueueDestroy(DvrWriteBufferQueue* write_queue); -void dvrDisplayManagerDestroy(DvrDisplayManager* client); -void dvrSurfaceStateDestroy(DvrSurfaceState* surface_state); -void dvrSurfaceDestroy(DvrSurface* surface); -void dvrHwcClientDestroy(DvrHwcClient* client); -void dvrHwcFrameDestroy(DvrHwcFrame* frame); - -__END_DECLS - -// Avoid errors if this header is included in C code. -#if defined(__cplusplus) - -namespace android { -namespace dvr { - -// Universal DVR object deleter. May be passed to smart pointer types to handle -// deletion of DVR API objects. -struct DvrObjectDeleter { - void operator()(DvrBuffer* p) { dvrBufferDestroy(p); } - void operator()(DvrReadBuffer* p) { dvrReadBufferDestroy(p); } - void operator()(DvrWriteBuffer* p) { dvrWriteBufferDestroy(p); } - void operator()(DvrReadBufferQueue* p) { dvrReadBufferQueueDestroy(p); } - void operator()(DvrWriteBufferQueue* p) { dvrWriteBufferQueueDestroy(p); } - void operator()(DvrDisplayManager* p) { dvrDisplayManagerDestroy(p); } - void operator()(DvrSurfaceState* p) { dvrSurfaceStateDestroy(p); } - void operator()(DvrSurface* p) { dvrSurfaceDestroy(p); } - void operator()(DvrHwcClient* p) { dvrHwcClientDestroy(p); } - void operator()(DvrHwcFrame* p) { dvrHwcFrameDestroy(p); } -}; - -// Helper to define unique pointers for DVR object types. -template <typename T> -using MakeUniqueDvrPointer = std::unique_ptr<T, DvrObjectDeleter>; - -// Unique pointer types for DVR objects. -using UniqueDvrBuffer = MakeUniqueDvrPointer<DvrBuffer>; -using UniqueDvrReadBuffer = MakeUniqueDvrPointer<DvrReadBuffer>; -using UniqueDvrWriteBuffer = MakeUniqueDvrPointer<DvrWriteBuffer>; -using UniqueDvrReadBufferQueue = MakeUniqueDvrPointer<DvrReadBufferQueue>; -using UniqueDvrWriteBufferQueue = MakeUniqueDvrPointer<DvrWriteBufferQueue>; -using UniqueDvrDisplayManager = MakeUniqueDvrPointer<DvrDisplayManager>; -using UniqueDvrSurfaceState = MakeUniqueDvrPointer<DvrSurfaceState>; -using UniqueDvrSurface = MakeUniqueDvrPointer<DvrSurface>; -using UniqueDvrHwcClient = MakeUniqueDvrPointer<DvrHwcClient>; -using UniqueDvrHwcFrame = MakeUniqueDvrPointer<DvrHwcFrame>; - -// TODO(eieio): Add an adapter for std::shared_ptr that injects the deleter into -// the relevant constructors. - -} // namespace dvr -} // namespace android - -#endif // defined(__cplusplus) - -#endif // ANDROID_DVR_DELETER_H_ diff --git a/libs/vr/libdvr/include/dvr/dvr_display_manager.h b/libs/vr/libdvr/include/dvr/dvr_display_manager.h deleted file mode 100644 index f910d610f5..0000000000 --- a/libs/vr/libdvr/include/dvr/dvr_display_manager.h +++ /dev/null @@ -1,133 +0,0 @@ -#ifndef ANDROID_DVR_DISPLAY_MANAGER_H_ -#define ANDROID_DVR_DISPLAY_MANAGER_H_ - -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> -#include <sys/cdefs.h> - -#include <dvr/dvr_display_types.h> -#include <dvr/dvr_surface.h> - -__BEGIN_DECLS - -typedef struct DvrBuffer DvrBuffer; -typedef struct DvrDisplayManager DvrDisplayManager; -typedef struct DvrSurfaceState DvrSurfaceState; -typedef struct DvrReadBufferQueue DvrReadBufferQueue; - -typedef uint64_t DvrSurfaceUpdateFlags; - -// Attempts to connect to the display manager service. -// @return 0 on success. Otherwise returns a negative error value. -int dvrDisplayManagerCreate(DvrDisplayManager** client_out); - -// Destroys the display manager client object. -void dvrDisplayManagerDestroy(DvrDisplayManager* client); - -// Returns an fd used to signal when surface updates occur. Note that depending -// on the underlying transport, only a subset of the real event bits may be -// supported. Use dvrDisplayManagerClientTranslateEpollEventMask to get the real -// event flags. -// @return the fd on success. Otherwise returns a negative error value. -int dvrDisplayManagerGetEventFd(DvrDisplayManager* client); - -// @param in_events pass in the epoll revents that were initially returned by -// poll/epoll. -// @param on success, this value will be overwritten with the true poll/epoll -// values. -// @return 0 on success. Otherwise returns a negative error value. -int dvrDisplayManagerTranslateEpollEventMask(DvrDisplayManager* client, - int in_events, int* out_events); - -// Queries the display manager service for the current state of the display -// surfaces and stores the results in the given surface state object. -// @return 0 on success. Otherwise returns a negative error value. -int dvrDisplayManagerGetSurfaceState(DvrDisplayManager* client, - DvrSurfaceState* surface_state); - -// Gets a read buffer queue from the surface |surface_id| named |queue_id|. Each -// call returns a different read buffer queue connected to the same write buffer -// queue. Callers should cache these instead of requesting new ones when -// possible. -int dvrDisplayManagerGetReadBufferQueue(DvrDisplayManager* client, - int surface_id, int queue_id, - DvrReadBufferQueue** queue_out); - -// Creates a new surface state object. This object may be used to receive the -// results of a surface state query. More than one state object may be created -// to keep multiple snapshots, if desired. -// @return 0 on success. Otherwise returns a negative error value. -int dvrSurfaceStateCreate(DvrSurfaceState** surface_state); - -// Destorys the surface state object. -void dvrSurfaceStateDestroy(DvrSurfaceState* surface_state); - -// Writes the number of surfaces described in the state object into |count_out|. -// @return 0 on success. Otherwise returns a negative error value. -int dvrSurfaceStateGetSurfaceCount(DvrSurfaceState* surface_state, - size_t* count_out); - -// Returns the update flags for the surface at |surface_index| in the state -// object. The flags may be used to determine what changes, if any, occurred to -// the surface since the last state update. -// @return 0 on success. Otherwise returns a negative error value. -int dvrSurfaceStateGetUpdateFlags(DvrSurfaceState* surface_state, - size_t surface_index, - DvrSurfaceUpdateFlags* flags_out); - -// Returns the unique identifier of surface at |surface_index| in the state -// object. The identifier may be used to distinguish between surfaces. -// @return 0 on success. Otherwise returns a negative error value. -int dvrSurfaceStateGetSurfaceId(DvrSurfaceState* surface_state, - size_t surface_index, int* surface_id_out); - -// Returns the process id of surface at |surface_index| in the state object. -// @return 0 on success. Otherwise returns a negative error value. -int dvrSurfaceStateGetProcessId(DvrSurfaceState* surface_state, - size_t surface_index, int* process_id_out); - -// Writes the number of queues in the surface at |surface_index| in the state -// object into |count_out|. -// @return 0 on success. Otherwise returns a negative error value. -int dvrSurfaceStateGetQueueCount(DvrSurfaceState* surface_state, - size_t surface_index, size_t* count_out); - -// Returns up to |max_count| queue ids for the queues belonging to the surface -// at |surface_index| in the state object. -// @return The number of queue ids written on success. Otherwise returns a -// negative error value. -ssize_t dvrSurfaceStateGetQueueIds(DvrSurfaceState* surface_state, - size_t surface_index, int* queue_ids, - size_t max_count); - -// Writes the z-order of the surface at |surface_index| in surface state object -// into |z_order_out|. -// @return 0 on success. Otherwise returns a negative error value. -int dvrSurfaceStateGetZOrder(DvrSurfaceState* surface_state, - size_t surface_index, int* z_order_out); - -// Writes the visible state of the surface at |surface_index| in the surface -// state object into |visible_out|. -// @return 0 on success. Otherwise it returns a negative error value. -int dvrSurfaceStateGetVisible(DvrSurfaceState* surface_state, - size_t surface_index, bool* visible_out); - -// Writes the number of attributes on the surface at |surface_index| in the -// state object into |count_out|. -// @return 0 on success. Otherwise it returns a negative error value. -int dvrSurfaceStateGetAttributeCount(DvrSurfaceState* surface_state, - size_t surface_index, size_t* count_out); - -// Writes the list of attribute key/value pairs for the surface at -// |surface_index| in the surface state object into |attributes|. -// @return The number of attributes written on success. Otherwise returns a -// negative error value. -ssize_t dvrSurfaceStateGetAttributes(DvrSurfaceState* surface_state, - size_t surface_index, - DvrSurfaceAttribute* attributes, - size_t max_count); - -__END_DECLS - -#endif // ANDROID_DVR_DISPLAY_MANAGER_H_ diff --git a/libs/vr/libdvr/include/dvr/dvr_display_types.h b/libs/vr/libdvr/include/dvr/dvr_display_types.h deleted file mode 100644 index fd69843292..0000000000 --- a/libs/vr/libdvr/include/dvr/dvr_display_types.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef ANDROID_DVR_DISPLAY_TYPES_H_ -#define ANDROID_DVR_DISPLAY_TYPES_H_ - -#include <sys/cdefs.h> - -__BEGIN_DECLS - -// Define types used in pose buffer fields. These types have atomicity -// guarantees that are useful in lock-free shared memory ring buffers. -#ifdef __ARM_NEON -#include <arm_neon.h> -#else -#ifndef __FLOAT32X4T_86 -#define __FLOAT32X4T_86 -typedef float float32x4_t __attribute__((__vector_size__(16))); -typedef struct float32x4x4_t { float32x4_t val[4]; } float32x4x4_t; -#endif -#endif - -// VrFlinger display manager surface state snapshots per surface flags -// indicating what changed since the last snapshot. -enum { - // No changes. - DVR_SURFACE_UPDATE_FLAGS_NONE = 0, - // This surface is new. - DVR_SURFACE_UPDATE_FLAGS_NEW_SURFACE = (1 << 0), - // Buffer queues added/removed. - DVR_SURFACE_UPDATE_FLAGS_BUFFERS_CHANGED = (1 << 1), - // Visibility/z-order changed. - DVR_SURFACE_UPDATE_FLAGS_VISIBILITY_CHANGED = (1 << 2), - // Generic attributes changed. - DVR_SURFACE_UPDATE_FLAGS_ATTRIBUTES_CHANGED = (1 << 3), -}; - -// Surface attribute keys. VrFlinger defines keys in the negative integer space. -// The compositor is free to use keys in the positive integer space for -// implementation-defined purposes. -enum { - // DIRECT: bool - // Determines whether a direct surface is created (compositor output) or an - // application surface. Defaults to false (application surface). May only be - // set to true by a process with either UID=root or UID validated with - // IsTrustedUid() (VrCore). - DVR_SURFACE_ATTRIBUTE_DIRECT = -3, - // Z_ORDER: int32_t - // Interpreted by VrFlinger only on direct surfaces to order the corresponding - // hardware layers. More positive values render on top of more negative - // values. - DVR_SURFACE_ATTRIBUTE_Z_ORDER = -2, - // VISIBLE: bool - // Interpreted by VrFlinger only on direct surfaces to determine whether a - // surface is assigned to a hardware layer or ignored. - DVR_SURFACE_ATTRIBUTE_VISIBLE = -1, - // INVALID - // Invalid key. No attributes should have this key. - DVR_SURFACE_ATTRIBUTE_INVALID = 0, - // FIRST_USER_KEY - // VrFlinger ingores any keys with this value or greater, passing them to the - // compositor through surface state query results. - DVR_SURFACE_ATTRIBUTE_FIRST_USER_KEY = 1, -}; - -__END_DECLS - -#endif // ANDROID_DVR_DISPLAY_TYPES_H_ diff --git a/libs/vr/libdvr/include/dvr/dvr_hardware_composer_client.h b/libs/vr/libdvr/include/dvr/dvr_hardware_composer_client.h deleted file mode 100644 index 0ba76e267d..0000000000 --- a/libs/vr/libdvr/include/dvr/dvr_hardware_composer_client.h +++ /dev/null @@ -1,199 +0,0 @@ -#ifndef ANDROID_DVR_HARDWARE_COMPOSER_CLIENT_H -#define ANDROID_DVR_HARDWARE_COMPOSER_CLIENT_H - -#include <dvr/dvr_hardware_composer_types.h> -#include <stdbool.h> - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct AHardwareBuffer AHardwareBuffer; -typedef struct DvrHwcClient DvrHwcClient; -typedef struct DvrHwcFrame DvrHwcFrame; - -// Called when a new frame has arrived. -// -// @param client_state Pointer to client state passed in |dvrHwcCreateClient()|. -// @param frame New frame. Owned by the client. -// @return fence FD for the release of the last frame. -typedef int(*DvrHwcOnFrameCallback)(void* client_state, DvrHwcFrame* frame); - -// @param callback Called when a new frame is available. -// @param client_state Pointer to client state passed back in the callback. -DvrHwcClient* dvrHwcClientCreate(DvrHwcOnFrameCallback callback, - void* client_state); - -// Called to free the DvrHwcClient pointer. -void dvrHwcClientDestroy(DvrHwcClient* client); - -// Called to free the frame information. -// @param frame Pointer for the valid frame used for the query. -void dvrHwcFrameDestroy(DvrHwcFrame* frame); - -// @param frame Pointer for the valid frame used for the query. -// @return Identifier for the display associated by the frame. -DvrHwcDisplay dvrHwcFrameGetDisplayId(DvrHwcFrame* frame); - -// @param frame Pointer for the valid frame used for the query. -// @return width of the physical display associated with |frame|. This does not -// take into account any orientation changes. -int32_t dvrHwcFrameGetDisplayWidth(DvrHwcFrame* frame); - -// @param frame Pointer for the valid frame used for the query. -// @return height of the physical display associated with |frame|. This does not -// take into account any orientation changes. -int32_t dvrHwcFrameGetDisplayHeight(DvrHwcFrame* frame); - -// @param frame Pointer for the valid frame used for the query. -// @return True if the display has been removed. In this case the current frame -// does not contain any valid layers to display. It is a signal to clean up any -// display related state. -bool dvrHwcFrameGetDisplayRemoved(DvrHwcFrame* frame); - -// @param frame Pointer for the valid frame used for the query. -// @return Number of layers in the frame. -size_t dvrHwcFrameGetLayerCount(DvrHwcFrame* frame); - -// @param frame Pointer for the valid frame used for the query. -// @return The ID of the currently active display configuration. -uint32_t dvrHwcFrameGetActiveConfig(DvrHwcFrame* frame); - -// @param frame Pointer for the valid frame used for the query. -// @return The ID of the current color mode. See HAL_COLOR_MODE_* for valid -// values. -uint32_t dvrHwcFrameGetColorMode(DvrHwcFrame* frame); - -// @param frame Pointer for the valid frame used for the query. -// @param out_matrix Output parameter for a float[16] array which will be filled -// with the color transform matrix. -// @param out_hint Output parameter which will contain the color transform hint. -// See HAL_COLOR_TRANSFORM_* for valid values. -void dvrHwcFrameGetColorTransform(DvrHwcFrame* frame, float* out_matrix, - int32_t* out_hint); - -// @param frame Pointer for the valid frame used for the query. -// @return The current power mode for the display. See HWC2_POWER_MODE_* for -// valid values. -uint32_t dvrHwcFrameGetPowerMode(DvrHwcFrame* frame); - -// @param frame Pointer for the valid frame used for the query. -// @return The current state of vsync. See HWC2_VSYNC_* for valid values. -uint32_t dvrHwcFrameGetVsyncEnabled(DvrHwcFrame* frame); - -// @param frame Pointer for the valid frame used for the query. -// @param layer_index The index of the layer in the frame. -// @return A unique ID for the layer. -DvrHwcLayer dvrHwcFrameGetLayerId(DvrHwcFrame* frame, size_t layer_index); - -// Return the graphic buffer associated with the layer at |layer_index| in -// |frame|. -// -// @param frame Pointer for the valid frame used for the query. -// @param layer_index The index of the layer in the frame. -// @return Graphic buffer. Caller owns the buffer and is responsible for freeing -// it. (see AHardwareBuffer_release()) -AHardwareBuffer* dvrHwcFrameGetLayerBuffer(DvrHwcFrame* frame, - size_t layer_index); - -// Returns the fence FD for the layer at index |layer_index| in |frame|. -// -// @param frame Pointer for the valid frame used for the query. -// @param layer_index The index of the layer in the frame. -// @return Fence FD. Caller owns the FD and is responsible for closing it. -int dvrHwcFrameGetLayerFence(DvrHwcFrame* frame, size_t layer_index); - -// @param frame Pointer for the valid frame used for the query. -// @param layer_index The index of the layer in the frame. -// @return describing the portion of the display covered by the layer. Will -// not exceed the display dimensions. -DvrHwcRecti dvrHwcFrameGetLayerDisplayFrame(DvrHwcFrame* frame, - size_t layer_index); - -// @param frame Pointer for the valid frame used for the query. -// @param layer_index The index of the layer in the frame. -// @return describing the portion of the layer that will fill the display -// frame. Will not exceed the layer dimensions. -DvrHwcRectf dvrHwcFrameGetLayerCrop(DvrHwcFrame* frame, size_t layer_index); - -// @param frame Pointer for the valid frame used for the query. -// @param layer_index The index of the layer in the frame. -// @return The blend mode of the layer. -DvrHwcBlendMode dvrHwcFrameGetLayerBlendMode(DvrHwcFrame* frame, - size_t layer_index); - -// @param frame Pointer for the valid frame used for the query. -// @param layer_index The index of the layer in the frame. -// @return The alpha value to be applied to the whole layer. Will be in the -// [0.0, 1.0] range. -float dvrHwcFrameGetLayerAlpha(DvrHwcFrame* frame, size_t layer_index); - -// @param frame Pointer for the valid frame used for the query. -// @param layer_index The index of the layer in the frame. -// @return The type of the layer assigned by the window manager. -uint32_t dvrHwcFrameGetLayerType(DvrHwcFrame* frame, size_t layer_index); - -// @param frame Pointer for the valid frame used for the query. -// @param layer_index The index of the layer in the frame. -// @return The application id the layer belongs to. -uint32_t dvrHwcFrameGetLayerApplicationId(DvrHwcFrame* frame, - size_t layer_index); - -// @param frame Pointer for the valid frame used for the query. -// @param layer_index The index of the layer in the frame. -// @return The z-order for the layer. -uint32_t dvrHwcFrameGetLayerZOrder(DvrHwcFrame* frame, size_t layer_index); - -// @param frame Pointer for the valid frame used for the query. -// @param layer_index The index of the layer in the frame. -// @param out_x Output parameter for the x coordinate of the cursor location. -// @param out_y Output parameter for the y coordinate of the cursor location. -void dvrHwcFrameGetLayerCursor(DvrHwcFrame* frame, size_t layer_index, - int32_t* out_x, int32_t* out_y); - -// @param frame Pointer for the valid frame used for the query. -// @param layer_index The index of the layer in the frame. -// @return The transformation that needs to be applied to the layer before -// presenting it. See DVR_HWC_TRANSFORM_* for valid values. -uint32_t dvrHwcFrameGetLayerTransform(DvrHwcFrame* frame, size_t layer_index); - -// @param frame Pointer for the valid frame used for the query. -// @param layer_index The index of the layer in the frame. -// @return The dataspace which represents how the pixel values should be -// interpreted. See HAL_DATASPACE_* for valid values. -uint32_t dvrHwcFrameGetLayerDataspace(DvrHwcFrame* frame, size_t layer_index); - -// @param frame Pointer for the valid frame used for the query. -// @param layer_index The index of the layer in the frame. -// @return The color of the layer if layer composition is SOLID_COLOR. -uint32_t dvrHwcFrameGetLayerColor(DvrHwcFrame* frame, size_t layer_index); - -// @param frame Pointer for the valid frame used for the query. -// @param layer_index The index of the layer in the frame. -// @return The number of visible regions. -uint32_t dvrHwcFrameGetLayerNumVisibleRegions(DvrHwcFrame* frame, - size_t layer_index); -// @param frame Pointer for the valid frame used for the query. -// @param layer_index The index of the layer in the frame. -// @param index The index of the visible region for the layer. -// @return The rectangle describing the visible region. -DvrHwcRecti dvrHwcFrameGetLayerVisibleRegion(DvrHwcFrame* frame, - size_t layer_index, size_t index); - -// @param frame Pointer for the valid frame used for the query. -// @param layer_index The index of the layer in the frame. -// @return The number of damanged regions. -uint32_t dvrHwcFrameGetLayerNumDamagedRegions(DvrHwcFrame* frame, - size_t layer_index); - -// @param frame Pointer for the valid frame used for the query. -// @param layer_index The index of the layer in the frame. -// @param index The index of the damanged region for the layer. -// @return The rectangle describing the damaged region. -DvrHwcRecti dvrHwcFrameGetLayerDamagedRegion(DvrHwcFrame* frame, - size_t layer_index, size_t index); -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // ANDROID_DVR_HARDWARE_COMPOSER_CLIENT_H diff --git a/libs/vr/libdvr/include/dvr/dvr_hardware_composer_types.h b/libs/vr/libdvr/include/dvr/dvr_hardware_composer_types.h deleted file mode 100644 index 1d5eda614b..0000000000 --- a/libs/vr/libdvr/include/dvr/dvr_hardware_composer_types.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef ANDROID_VR_HARDWARE_COMPOSER_DEFS_H -#define ANDROID_VR_HARDWARE_COMPOSER_DEFS_H - -#include <inttypes.h> - -#ifdef __cplusplus -extern "C" { -#endif - -// NOTE: These definitions must match the ones in -// //hardware/libhardware/include/hardware/hwcomposer2.h. They are used by the -// client side which does not have access to hwc2 headers. -enum DvrHwcBlendMode { - DVR_HWC_BLEND_MODE_INVALID = 0, - DVR_HWC_BLEND_MODE_NONE = 1, - DVR_HWC_BLEND_MODE_PREMULTIPLIED = 2, - DVR_HWC_BLEND_MODE_COVERAGE = 3, -}; - -enum DvrHwcComposition { - DVR_HWC_COMPOSITION_INVALID = 0, - DVR_HWC_COMPOSITION_CLIENT = 1, - DVR_HWC_COMPOSITION_DEVICE = 2, - DVR_HWC_COMPOSITION_SOLID_COLOR = 3, - DVR_HWC_COMPOSITION_CURSOR = 4, - DVR_HWC_COMPOSITION_SIDEBAND = 5, -}; - -enum DvrHwcTransform { - DVR_HWC_TRANSFORM_NONE = 0, - DVR_HWC_TRANSFORM_FLIP_H = 1, - DVR_HWC_TRANSFORM_FLIP_V = 2, - DVR_HWC_TRANSFORM_ROT_90 = 4, - DVR_HWC_TRANSFORM_ROT_180 = 3, - DVR_HWC_TRANSFORM_ROT_270 = 7, -}; - -typedef uint64_t DvrHwcDisplay; -typedef uint64_t DvrHwcLayer; - -struct DvrHwcRecti { - int32_t left; - int32_t top; - int32_t right; - int32_t bottom; -}; - -struct DvrHwcRectf { - float left; - float top; - float right; - float bottom; -}; - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // ANDROID_DVR_HARDWARE_COMPOSER_DEFS_H diff --git a/libs/vr/libdvr/include/dvr/dvr_performance.h b/libs/vr/libdvr/include/dvr/dvr_performance.h deleted file mode 100644 index 5df35ad9d9..0000000000 --- a/libs/vr/libdvr/include/dvr/dvr_performance.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef ANDROID_DVR_PERFORMANCE_H_ -#define ANDROID_DVR_PERFORMANCE_H_ - -#include <stddef.h> -#include <unistd.h> - -__BEGIN_DECLS - -/// Sets the scheduler policy for a task. -/// -/// Sets the scheduler policy for a task to the class described by a semantic -/// string. -/// -/// Supported policies are device-specific. -/// -/// @param task_id The task id of task to set the policy for. When task_id is 0 -/// the current task id is substituted. -/// @param scheduler_policy NULL-terminated ASCII string containing the desired -/// scheduler policy. -/// @returns Returns 0 on success or a negative errno error code on error. -int dvrPerformanceSetSchedulerPolicy(pid_t task_id, const char* scheduler_policy); - -__END_DECLS - -#endif // ANDROID_DVR_PERFORMANCE_H_ - diff --git a/libs/vr/libdvr/include/dvr/dvr_pose.h b/libs/vr/libdvr/include/dvr/dvr_pose.h deleted file mode 100644 index 87527515b4..0000000000 --- a/libs/vr/libdvr/include/dvr/dvr_pose.h +++ /dev/null @@ -1,154 +0,0 @@ -#ifndef ANDROID_DVR_PUBLIC_POSE_H_ -#define ANDROID_DVR_PUBLIC_POSE_H_ - -#include <stdint.h> -#include <sys/cdefs.h> - -__BEGIN_DECLS - -#ifdef __ARM_NEON -#include <arm_neon.h> -#else -#ifndef __FLOAT32X4T_86 -#define __FLOAT32X4T_86 -typedef float float32x4_t __attribute__((__vector_size__(16))); -#endif -#endif - -typedef struct DvrPoseClient DvrPoseClient; -typedef struct DvrReadBufferQueue DvrReadBufferQueue; - -// Represents an estimated pose, accessed asynchronously through a shared ring -// buffer. No assumptions should be made about the data in padding space. -// The size of this struct is 128 bytes. -typedef struct __attribute__((packed, aligned(16))) DvrPoseAsync { - // Left eye head-from-start orientation quaternion x,y,z,w. - float32x4_t orientation; - // Left eye head-from-start position x,y,z,pad in meters. - float32x4_t position; - // Right eye head-from-start orientation quaternion x,y,z,w. - float32x4_t right_orientation; - // Right eye head-from-start position x,y,z,pad in meters. - float32x4_t right_position; - // Start-space angular velocity x,y,z,pad in radians per second. - float32x4_t angular_velocity; - // Start-space positional velocity x,y,z,pad in meters per second. - float32x4_t velocity; - // Timestamp of when this pose is predicted for, typically halfway through - // scanout. - int64_t timestamp_ns; - // Bitmask of DVR_POSE_FLAG_* constants that apply to this pose. - // - // If DVR_POSE_FLAG_INVALID is set, the pose is indeterminate. - uint64_t flags; - // Reserved padding to 128 bytes. - uint8_t pad[16]; -} DvrPoseAsync; - -enum { - DVR_POSE_FLAG_INVALID = (1ULL << 0), // This pose is invalid. - DVR_POSE_FLAG_INITIALIZING = (1ULL << 1), // The pose delivered during - // initialization and it may not be - // correct. - DVR_POSE_FLAG_3DOF = - (1ULL << 2), // This pose is derived from 3Dof sensors. If - // this is not set, pose is derived using - // 3Dof and 6Dof sensors. - DVR_POSE_FLAG_FLOOR_HEIGHT_INVALID = - (1ULL << 3), // If set the floor height is invalid. - - // Bits that indicate the tracking system state. - DVR_POSE_FLAG_SERVICE_EXCEPTION = (1ULL << 32), - DVR_POSE_FLAG_FISHEYE_OVER_EXPOSED = (1ULL << 33), - DVR_POSE_FLAG_FISHEYE_UNDER_EXPOSED = (1ULL << 34), - DVR_POSE_FLAG_COLOR_OVER_EXPOSED = (1ULL << 35), - DVR_POSE_FLAG_COLOR_UNDER_EXPOSED = (1ULL << 36), - DVR_POSE_FLAG_TOO_FEW_FEATURES_TRACKED = (1ULL << 37) -}; - -// Represents a sensor pose sample. -typedef struct __attribute__((packed, aligned(16))) DvrPose { - // Head-from-start orientation quaternion x,y,z,w. - float32x4_t orientation; - - // The angular velocity where the x,y,z is the rotation axis and the - // magnitude is the radians / second in the same coordinate frame as - // orientation. - float32x4_t angular_velocity; - - // Head-from-start position x,y,z,pad in meters. - float32x4_t position; - - // In meters / second in the same coordinate frame as position. - float32x4_t velocity; - - // In meters / second ^ 2 in the same coordinate frame as position. - float32x4_t acceleration; - - // Timestamp for the measurement in nanoseconds. - int64_t timestamp_ns; - - // The combination of flags above. - uint64_t flags; - - // The current floor height. May be updated at a lower cadence than pose. - float floor_height; - - // Padding to 112 bytes so the size is a multiple of 16. - uint8_t padding[12]; -} DvrPose; - -// Represents a data type that can be streamed from pose service. -enum { - DVR_POSE_RAW_DATA_STEREO_IMAGE = (1ULL << 0), - DVR_POSE_RAW_DATA_POINT_CLOUD = (1ULL << 1), - DVR_POSE_RAW_DATA_FEATURES = (1ULL << 2), - - // Always last. - DVR_POSE_RAW_DATA_COUNT = (1ULL << 3), -}; - -// A request to retrieve data from the pose service. Expects that a buffer -// queue has been initialized through dvrPoseClientGetDataReader(). -typedef struct DvrPoseDataCaptureRequest { - // The type of data to capture. Refer to enum DVR_POSE_RAW_DATA_* for types. - uint64_t data_type; - // The sample interval. This can be used to skip samples. For example, a - // value of 5 will capture every fifth frame and discard the 4 frames in - // between. Set to 1 to capture all frames. - uint32_t sample_interval; - // The length of time to capture samples in milliseconds. Set to 0 to capture - // indefinitely. - uint32_t capture_time_ms; - // Reserved fields. - uint32_t reserved0; - uint32_t reserved1; - uint32_t reserved2; - uint32_t reserved3; - uint32_t reserved4; -} DvrPoseDataCaptureRequest; - -// Gets a read buffer queue for the data type |data_type|. Each call returns a -// different read buffer queue connected to the same write buffer queue. A -// separate write buffer queue exists for each |data_type|. -// -// PoseService supports a single consumer per write buffer queue. The consumer -// is expected to hold a single DvrReadBufferQueue at a time. Callers should -// cache these instead of requesting new ones when possible. If the consumer -// disconnects from the queue, it can regain a read buffer queue for the same -// producer by calling this function. -// -// For data_type DVR_POSE_RAW_DATA_STEREO_IMAGE, each buffer consists of two -// images formatted as a AHARDWAREBUFFER_FORMAT_BLOB, where height is 1 and -// width is the total size of both images. The size of an individual image can -// be found in the metadata struct DvrNativeBufferMetadata, where width is -// |crop_right| and height is |crop_bottom|/2. Each image is contiguous in -// memory with stride equal to width. -int dvrPoseClientGetDataReader(DvrPoseClient* client, uint64_t data_type, - DvrReadBufferQueue** queue_out); - -// TODO(b/65067592): Move pose api's from pose_client.h to here. - -__END_DECLS - -#endif // ANDROID_DVR_PUBLIC_POSE_H_ diff --git a/libs/vr/libdvr/include/dvr/dvr_shared_buffers.h b/libs/vr/libdvr/include/dvr/dvr_shared_buffers.h deleted file mode 100644 index 63c73855f4..0000000000 --- a/libs/vr/libdvr/include/dvr/dvr_shared_buffers.h +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef ANDROID_DVR_SHARED_BUFFERS_H_ -#define ANDROID_DVR_SHARED_BUFFERS_H_ - -#include <dvr/dvr_config.h> -#include <dvr/dvr_pose.h> -#include <dvr/dvr_vsync.h> -#include <libbroadcastring/broadcast_ring.h> - -// This header is shared by VrCore and Android and must be kept in sync. -namespace android { -namespace dvr { - -// Increment when the layout for the buffers change. -enum : uint32_t { kSharedBufferLayoutVersion = 2 }; - -// Note: These buffers will be mapped from various system processes as well -// as VrCore and the application processes in a r/w manner. -// -// Therefore it is possible for the application to mess with the contents of -// these buffers. -// -// While using them, assume garbage memory: Your logic must not crash or lead -// to execution of unsafe code as a function of the contents of these buffers. - -// Sanity check for basic type sizes. -static_assert(sizeof(DvrPoseAsync) == 128, "Unexpected size for DvrPoseAsync"); -static_assert(sizeof(DvrPose) == 112, "Unexpected size for DvrPose"); -static_assert(sizeof(DvrVsync) == 32, "Unexpected size for DvrVsync"); -static_assert(sizeof(DvrConfig) == 16, "Unexpected size for DvrConfig"); - -// A helper class that provides compile time sized traits for the BroadcastRing. -template <class DvrType, size_t StaticCount> -class DvrRingBufferTraits { - public: - using Record = DvrType; - static constexpr bool kUseStaticRecordSize = false; - static constexpr uint32_t kStaticRecordCount = StaticCount; - static constexpr int kMaxReservedRecords = 1; - static constexpr int kMinAvailableRecords = 1; -}; - -// Traits classes. -using DvrPoseTraits = DvrRingBufferTraits<DvrPose, 0>; -using DvrVsyncTraits = DvrRingBufferTraits<DvrVsync, 2>; -using DvrConfigTraits = DvrRingBufferTraits<DvrConfig, 2>; - -// The broadcast ring classes that will expose the data. -using DvrPoseRing = BroadcastRing<DvrPose, DvrPoseTraits>; -using DvrVsyncRing = BroadcastRing<DvrVsync, DvrVsyncTraits>; -using DvrConfigRing = BroadcastRing<DvrConfig, DvrConfigTraits>; - -// This is a shared memory buffer for passing pose data estimated at vsyncs. -// -// This will be primarily used for late latching and EDS where we bind this -// buffer in a shader and extract the right vsync-predicted pose. -struct __attribute__((packed, aligned(16))) DvrVsyncPoseBuffer { - enum : int { - // The number vsync predicted poses to keep in the ring buffer. - // Must be a power of 2. - kSize = 8, - kIndexMask = kSize - 1, - - // The number of vsyncs (from the current vsync) we predict in vsync buffer. - // The other poses are left alone. - kMinFutureCount = 4 - }; - - // The vsync predicted poses. - // The pose for the vsync n is: - // vsync_poses[n % kSize] - // - // This buffer is unsynchronized: It is possible to get torn reads as the - // sensor service updates the predictions as new sensor measurements come - // in. In particular, it is possible to get the position and an updated - // orientation while reading. - DvrPoseAsync vsync_poses[kSize]; - - // The latest sensor pose for GPU usage. - DvrPose current_pose; - - // Current vsync_count (where sensord is writing poses from). - uint32_t vsync_count; - - // For 16 byte alignment. - uint8_t padding[12]; -}; - -static_assert(sizeof(DvrVsyncPoseBuffer) == 1152, - "Unexpected size for DvrVsyncPoseBuffer"); - -// The keys for the dvr global buffers. -enum DvrGlobalBuffers : int32_t { - kVsyncPoseBuffer = 1, - kVsyncBuffer = 2, - kSensorPoseBuffer = 3, - kVrFlingerConfigBufferKey = 4 -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_SHARED_BUFFERS_H_ diff --git a/libs/vr/libdvr/include/dvr/dvr_surface.h b/libs/vr/libdvr/include/dvr/dvr_surface.h deleted file mode 100644 index 74a68a16ee..0000000000 --- a/libs/vr/libdvr/include/dvr/dvr_surface.h +++ /dev/null @@ -1,113 +0,0 @@ -#ifndef ANDROID_DVR_SURFACE_H_ -#define ANDROID_DVR_SURFACE_H_ - -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> -#include <sys/cdefs.h> - -#include <dvr/dvr_api.h> -#include <dvr/dvr_buffer.h> -#include <dvr/dvr_buffer_queue.h> -#include <dvr/dvr_display_types.h> - -__BEGIN_DECLS - -// Attribute types. The values are one-hot encoded to support singluar types or -// masks of supported types. -enum { - DVR_SURFACE_ATTRIBUTE_TYPE_NONE = 0, - DVR_SURFACE_ATTRIBUTE_TYPE_INT32 = (1 << 0), - DVR_SURFACE_ATTRIBUTE_TYPE_INT64 = (1 << 1), - DVR_SURFACE_ATTRIBUTE_TYPE_BOOL = (1 << 2), - DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT = (1 << 3), - DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT2 = (1 << 4), - DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT3 = (1 << 5), - DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT4 = (1 << 6), - DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT8 = (1 << 7), - DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT16 = (1 << 8), -}; - -typedef uint64_t DvrSurfaceAttributeType; -typedef int32_t DvrSurfaceAttributeKey; - -typedef struct DvrSurfaceAttributeValue { - DvrSurfaceAttributeType type; - union { - int32_t int32_value; - int64_t int64_value; - bool bool_value; - float float_value; - float float2_value[2]; - float float3_value[3]; - float float4_value[4]; - float float8_value[8]; - float float16_value[16]; - }; -} DvrSurfaceAttributeValue; - -typedef struct DvrSurfaceAttribute { - DvrSurfaceAttributeKey key; - DvrSurfaceAttributeValue value; -} DvrSurfaceAttribute; - -// Creates a new display surface with the given attributes. -// @return 0 on success. Otherwise returns a negative error value. -int dvrSurfaceCreate(const DvrSurfaceAttribute* attributes, - size_t attribute_count, DvrSurface** surface_out); - -// Destroys the display surface. -void dvrSurfaceDestroy(DvrSurface* surface); - -// Gets the DisplayService global id for this surface. -int dvrSurfaceGetId(DvrSurface* surface); - -// Sets attributes on the given display surface. -// @return 0 on success. Otherwise returns a negative error value. -int dvrSurfaceSetAttributes(DvrSurface* surface, - const DvrSurfaceAttribute* attributes, - size_t attribute_count); - -// Creates a new write-side buffer queue on the given surface. Direct surfaces -// may only have one queue, the latest call replacing any prior queue. Replaced -// queues are still referenced and should be destryoed using the queue destroy -// API. -// @return 0 on success. Otherwise returns a negative error value. -int dvrSurfaceCreateWriteBufferQueue(DvrSurface* surface, uint32_t width, - uint32_t height, uint32_t format, - uint32_t layer_count, uint64_t usage, - size_t capacity, size_t metadata_size, - DvrWriteBufferQueue** queue_out); - -// Sets up a named buffer for shared memory data transfer between display -// clients and the system. Protected API that may only be called with sufficient -// privilege. -// @return 0 on success. Otherwise returns a negative error value. -int dvrSetupGlobalBuffer(DvrGlobalBufferKey key, size_t size, uint64_t usage, - DvrBuffer** buffer_out); - -// Deletes a named buffer. WARNING: This is dangerous because any existing -// clients of this buffer will not be notified and will remain attached to -// the old buffer. This is useful for tests, but probably not for production -// code. -// @return 0 on success. Otherwise returns a negative error value. -int dvrDeleteGlobalBuffer(DvrGlobalBufferKey key); - -// Get a global buffer from the display service. -// @return 0 on success. Otherwise returns a negative error value. -int dvrGetGlobalBuffer(DvrGlobalBufferKey key, DvrBuffer** out_buffer); - -// Read the native device display metrics as reported by the hardware composer. -// This is useful as otherwise the device metrics are only reported as -// relative to the current device orientation. -// @param sizeof_metrics the size of the passed in metrics struct. This is used -// to ensure we don't break each other during active development. -// @param metrics on success holds the retrieved device metrics. -// @return 0 on success. Otherwise returns a negative error value (typically -// this means the display service is not available). -int dvrGetNativeDisplayMetrics(size_t metrics_struct_size, - DvrNativeDisplayMetrics* metrics); - -__END_DECLS - -#endif // ANDROID_DVR_SURFACE_H_ diff --git a/libs/vr/libdvr/include/dvr/dvr_tracking.h b/libs/vr/libdvr/include/dvr/dvr_tracking.h deleted file mode 100644 index 5e388f391a..0000000000 --- a/libs/vr/libdvr/include/dvr/dvr_tracking.h +++ /dev/null @@ -1,185 +0,0 @@ -#ifndef ANDROID_DVR_TRACKING_H_ -#define ANDROID_DVR_TRACKING_H_ - -#include <stdint.h> -#include <sys/cdefs.h> - -#include <dvr/dvr_tracking_types.h> - -__BEGIN_DECLS - -typedef struct DvrReadBuffer DvrReadBuffer; -typedef struct DvrTrackingCamera DvrTrackingCamera; -typedef struct DvrTrackingFeatureExtractor DvrTrackingFeatureExtractor; -typedef struct DvrTrackingSensors DvrTrackingSensors; -typedef struct DvrWriteBufferQueue DvrWriteBufferQueue; - -// The callback for DvrTrackingFeatureExtractor that will deliver the feature -// events. This callback is passed to dvrTrackingFeatureExtractorStart. -typedef void (*DvrTrackingFeatureCallback)(void* context, - const DvrTrackingFeatures* event); - -// The callback for DvrTrackingSensors session that will deliver the events. -// This callback is passed to dvrTrackingSensorsStart. -typedef void (*DvrTrackingSensorEventCallback)(void* context, - DvrTrackingSensorEvent* event); - -// Creates a DvrTrackingCamera session. -// -// On creation, the session is not in operating mode. Client code must call -// dvrTrackingCameraStart to bootstrap the underlying camera stack. -// -// There is no plan to expose camera configuration through this API. All camera -// parameters are determined by the system optimized for better tracking -// results. See b/78662281 for detailed deprecation plan of this API and the -// Stage 2 of VR tracking data source refactoring. -// -// @param out_camera The pointer of a DvrTrackingCamera will be filled here if -// the method call succeeds. -// @return Zero on success, or negative error code. -int dvrTrackingCameraCreate(DvrTrackingCamera** out_camera); - -// Destroys a DvrTrackingCamera handle. -// -// @param camera The DvrTrackingCamera of interest. -void dvrTrackingCameraDestroy(DvrTrackingCamera* camera); - -// Starts the DvrTrackingCamera. -// -// On successful return, all DvrReadBufferQueue's associated with the given -// write_queue will start to receive buffers from the camera stack. Note that -// clients of this API should not assume the buffer dimension, format, and/or -// usage of the outcoming buffers, as they are governed by the underlying camera -// logic. Also note that it's the client's responsibility to consume buffers -// from DvrReadBufferQueue on time and return them back to the producer; -// otherwise the camera stack might be blocked. -// -// @param camera The DvrTrackingCamera of interest. -// @param write_queue A DvrWriteBufferQueue that the camera stack can use to -// populate the buffer into. The queue must be empty and the camera stack -// will request buffer allocation with proper buffer dimension, format, and -// usage. Note that the write queue must be created with user_metadata_size -// set to sizeof(DvrTrackingBufferMetadata). On success, the write_queue -// handle will become invalid and the ownership of the queue handle will be -// transferred into the camera; otherwise, the write_queue handle will keep -// untouched and the caller still has the ownership. -// @return Zero on success, or negative error code. -int dvrTrackingCameraStart(DvrTrackingCamera* camera, - DvrWriteBufferQueue* write_queue); - -// Stops the DvrTrackingCamera. -// -// On successful return, the DvrWriteBufferQueue set during -// dvrTrackingCameraStart will stop getting new buffers from the camera stack. -// -// @param camera The DvrTrackingCamera of interest. -// @return Zero on success, or negative error code. -int dvrTrackingCameraStop(DvrTrackingCamera* camera); - -// Creates a DvrTrackingSensors session. -// -// This will initialize but not start device sensors (gyro / accel). Upon -// successfull creation, the clients can call dvrTrackingSensorsStart to start -// receiving sensor events. -// -// @param out_sensors The pointer of a DvrTrackingSensors will be filled here if -// the method call succeeds. -// @param mode The sensor mode. -// mode="ndk": Use the Android NDK. -// mode="direct": Use direct mode sensors (lower latency). -// @return Zero on success, or negative error code. -int dvrTrackingSensorsCreate(DvrTrackingSensors** out_sensors, - const char* mode); - -// Destroys a DvrTrackingSensors session. -// -// @param sensors The DvrTrackingSensors struct to destroy. -void dvrTrackingSensorsDestroy(DvrTrackingSensors* sensors); - -// Starts the tracking sensor session. -// -// This will start the device sensors and start pumping the feature and sensor -// events as they arrive. -// -// @param client A tracking client created by dvrTrackingSensorsCreate. -// @param context A client supplied pointer that will be passed to the callback. -// @param callback A callback that will receive the sensor events on an -// arbitrary thread. -// @return Zero on success, or negative error code. -int dvrTrackingSensorsStart(DvrTrackingSensors* sensors, - DvrTrackingSensorEventCallback callback, - void* context); - -// Stops a DvrTrackingSensors session. -// -// This will stop the device sensors. dvrTrackingSensorsStart can be called to -// restart them again. -// -// @param client A tracking client created by dvrTrackingClientCreate. -// @return Zero on success, or negative error code. -int dvrTrackingSensorsStop(DvrTrackingSensors* sensors); - -// Creates a tracking feature extractor. -// -// This will initialize but not start the feature extraction session. Upon -// successful creation, the client can call dvrTrackingFeatureExtractorStart to -// start receiving features. -// -// @param out_extractor The pointer of a DvrTrackingFeatureExtractor will be -// filled here if the method call succeeds. -int dvrTrackingFeatureExtractorCreate( - DvrTrackingFeatureExtractor** out_extractor); - -// Destroys a tracking feature extractor. -// -// @param extractor The DvrTrackingFeatureExtractor to destroy. -void dvrTrackingFeatureExtractorDestroy(DvrTrackingFeatureExtractor* extractor); - -// Starts the tracking feature extractor. -// -// This will start the extractor and start pumping the output feature events to -// the registered callback. Note that this method will create one or more -// threads to handle feature processing. -// -// @param extractor The DvrTrackingFeatureExtractor to destroy. -int dvrTrackingFeatureExtractorStart(DvrTrackingFeatureExtractor* extractor, - DvrTrackingFeatureCallback callback, - void* context); - -// Stops the tracking feature extractor. -// -// This will stop the extractor session and clean up all internal resourcse -// related to this extractor. On succssful return, all internal therad started -// by dvrTrackingFeatureExtractorStart should be stopped. -// -// @param extractor The DvrTrackingFeatureExtractor to destroy. -int dvrTrackingFeatureExtractorStop(DvrTrackingFeatureExtractor* extractor); - -// Processes one buffer to extract features from. -// -// The buffer will be sent over to DSP for feature extraction. Once the process -// is done, the processing thread will invoke DvrTrackingFeatureCallback with -// newly extracted features. Note that not all buffers will be processed, as the -// underlying DSP can only process buffers at a certain framerate. If a buffer -// needs to be skipped, out_skipped filed will be set to true. Also note that -// for successfully processed stereo buffer, two callbacks (one for each eye) -// will be fired. -// -// @param extractor The DvrTrackingFeatureExtractor to destroy. -// @param buffer The buffer to extract features from. Note that the buffer must -// be in acquired state for the buffer to be processed. Also note that the -// buffer will be released back to its producer on successful return of the -// method. -// @param metadata The metadata associated with the buffer. Should be populated -// by DvrTrackingCamera session as user defined metadata. -// @param out_skipped On successful return, the field will be set to true iff -// the buffer was skipped; and false iff the buffer was processed. This -// field is optional and nullptr can be passed here to ignore the field. -// @return Zero on success, or negative error code. -int dvrTrackingFeatureExtractorProcessBuffer( - DvrTrackingFeatureExtractor* extractor, DvrReadBuffer* buffer, - const DvrTrackingBufferMetadata* metadata, bool* out_skipped); - -__END_DECLS - -#endif // ANDROID_DVR_TRACKING_H_ diff --git a/libs/vr/libdvr/include/dvr/dvr_tracking_types.h b/libs/vr/libdvr/include/dvr/dvr_tracking_types.h deleted file mode 100644 index 81310d2303..0000000000 --- a/libs/vr/libdvr/include/dvr/dvr_tracking_types.h +++ /dev/null @@ -1,104 +0,0 @@ -#ifndef ANDROID_DVR_TRACKING_TYPES_H_ -#define ANDROID_DVR_TRACKING_TYPES_H_ - -#include <stdint.h> -#include <sys/cdefs.h> - -__BEGIN_DECLS - -typedef struct DvrTrackingBufferMetadata { - // Specifies the source of this image. - uint32_t camera_mask; - // Specifies the memory format of this image. - uint32_t format; - /// The width of the image data. - uint32_t width; - /// The height of the image data. - uint32_t height; - /// The number of bytes per scanline of image data. - uint32_t stride; - /// The frame number of this image. - int32_t frame_number; - /// The timestamp of this image in nanoseconds. Taken in the middle of the - /// exposure interval. - int64_t timestamp_ns; - // This is the timestamp for recording when the system using the HAL - // received the callback. It will not be populated by the HAL. - int64_t callback_timestamp_ns; - /// The exposure duration of this image in nanoseconds. - int64_t exposure_duration_ns; -} DvrTrackingBufferMetadata; - -// Represents a set of features extracted from a camera frame. Note that this -// should be in sync with TangoHalCallbacks defined in tango-hal.h. -typedef struct DvrTrackingFeatures { - // Specifies the source of the features. - uint32_t camera_mask; - - // This is unused. - uint32_t unused; - - // The timestamp in nanoseconds from the image that generated the features. - // Taken in the middle of the exposure interval. - int64_t timestamp_ns; - - // This is the timestamp for recording when the system using the HAL - // received the callback. It will not be populated by the HAL. - int64_t callback_timestamp_ns; - - // The frame number from the image that generated the features. - int64_t frame_number; - - // The number of features. - int count; - - // An array of 2D image points for each feature in the current image. - // This is sub-pixel refined extremum location at the fine resolution. - float (*positions)[2]; - - // The id of these measurements. - int32_t* ids; - - // The feature descriptors. - uint64_t (*descriptors)[8]; - - // Laplacian scores for each feature. - float* scores; - - // Is this feature a minimum or maximum in the Laplacian image. - // 0 if the feature is a maximum, 1 if it is a minimum. - int32_t* is_minimum; - - // This corresponds to the sub-pixel index of the laplacian image - // that the extremum was found. - float* scales; - - // Computed orientation of keypoint as part of FREAK extraction, except - // it's represented in radians and measured anti-clockwise. - float* angles; - - // Edge scores for each feature. - float* edge_scores; -} DvrTrackingFeatures; - -// Represents a sensor event. -typedef struct DvrTrackingSensorEvent { - // The sensor type. - int32_t sensor; - - // Event type. - int32_t type; - - // This is the timestamp recorded from the device. Taken in the middle - // of the integration interval and adjusted for any low pass filtering. - int64_t timestamp_ns; - - // The event data. - float x; - float y; - float z; -} DvrTrackingSensorEvent; - -__END_DECLS - -#endif // ANDROID_DVR_TRACKING_TYPES_H_ diff --git a/libs/vr/libdvr/include/dvr/dvr_vsync.h b/libs/vr/libdvr/include/dvr/dvr_vsync.h deleted file mode 100644 index 498bb5cc6e..0000000000 --- a/libs/vr/libdvr/include/dvr/dvr_vsync.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef ANDROID_DVR_VSYNC_H_ -#define ANDROID_DVR_VSYNC_H_ - -#include <stdint.h> -#include <sys/cdefs.h> - -__BEGIN_DECLS - -// Represents a vsync sample. The size of this struct is 32 bytes. -typedef struct __attribute__((packed, aligned(16))) DvrVsync { - // The timestamp for the last vsync in nanoseconds. - uint64_t vsync_timestamp_ns; - - // The index of the last vsync. - uint32_t vsync_count; - - // Scan out for the left eye = vsync_timestamp_ns + vsync_left_eye_offset_ns. - int32_t vsync_left_eye_offset_ns; - - // Scan out for the right eye = vsync_timestamp_ns + vsync_right_eye_offset_ns - int32_t vsync_right_eye_offset_ns; - - // The period of a vsync in nanoseconds. - uint32_t vsync_period_ns; - - // Padding to 32 bytes so the size is a multiple of 16. - uint8_t padding[8]; -} DvrVsync; - -__END_DECLS - -#endif // ANDROID_DVR_VSYNC_H_ diff --git a/libs/vr/libdvrcommon/Android.bp b/libs/vr/libdvrcommon/Android.bp deleted file mode 100644 index fe4dfc792a..0000000000 --- a/libs/vr/libdvrcommon/Android.bp +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright (C) 2016 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "frameworks_native_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["frameworks_native_license"], -} - -localIncludeFiles = [ - "include", -] - -sharedLibraries = [ - "libbase", - "libcutils", - "liblog", - "libutils", - "libEGL", - "libGLESv2", - "libui", - "libgui", - "libhardware", - "libpdx_default_transport", -] - -staticLibraries = ["libbroadcastring"] - -headerLibraries = [ - "libeigen", -] - -cc_library { - local_include_dirs: localIncludeFiles, - - cflags: [ - "-DLOG_TAG=\"libdvrcommon\"", - "-DTRACE=0", - "-Wall", - "-Werror", - ], - export_include_dirs: localIncludeFiles, - - header_libs: headerLibraries, - export_header_lib_headers: headerLibraries, - - name: "libdvrcommon", -} - -testFiles = [ - "tests/numeric_test.cpp", - "tests/pose_test.cpp", -] - -cc_test { - name: "libdvrcommon_test", - - srcs: testFiles, - cflags: [ - "-Wall", - "-Werror", - "-Wno-unused-parameter", - ], - - shared_libs: sharedLibraries, - - static_libs: [ - "libgmock_main", - "libgmock", - "libgtest", - "libdvrcommon", - ] + staticLibraries, -} diff --git a/libs/vr/libdvrcommon/include/private/dvr/benchmark.h b/libs/vr/libdvrcommon/include/private/dvr/benchmark.h deleted file mode 100644 index 7eeab16030..0000000000 --- a/libs/vr/libdvrcommon/include/private/dvr/benchmark.h +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef ANDROID_DVR_BENCHMARK_H_ -#define ANDROID_DVR_BENCHMARK_H_ - -#include <stdio.h> -#include <time.h> - -#include <cutils/trace.h> - -#include <private/dvr/clock_ns.h> - -// Set benchmark traces, using Android systrace. -// -// The simplest one-parameter version of btrace automatically sets the -// timestamp with the system clock. The other versions can optionally set the -// timestamp manually, or pass additional data to be written to the log line. -// -// Example: -// Btrace("Start execution"); -// ... code to benchmark ... -// Btrace("End execution"); -// -// Use compute_benchmarks.py -// with the trace path "Start execution,End execution", -// to report the elapsed time between the two calls. -// -// Btrace will either output to standard atrace, or to a file if specified. -// The versions BtraceData also allow an int64_t to be included in the trace. - -// Btrace without data payload. -static inline void Btrace(const char* name, int64_t nanoseconds_monotonic); -static inline void Btrace(const char* name); -static inline void Btrace(FILE* file, const char* name, - int64_t nanoseconds_monotonic); -static inline void Btrace(FILE* file, const char* name); - -// Btrace with data payload. -static inline void BtraceData(const char* name, int64_t nanoseconds_monotonic, - int64_t data); -static inline void BtraceData(const char* name, int64_t data); -static inline void BtraceData(FILE* file, const char* name, - int64_t nanoseconds_monotonic, int64_t data); -static inline void BtraceData(FILE* file, const char* name, int64_t data); - -static inline void Btrace(const char* name, int64_t nanoseconds_monotonic) { - const int kLogMessageLength = 256; - char log_message[kLogMessageLength]; - snprintf(log_message, kLogMessageLength, "#btrace#%s", name); - atrace_int64(ATRACE_TAG_WEBVIEW, log_message, nanoseconds_monotonic); -} - -static inline void Btrace(const char* name) { - Btrace(name, android::dvr::GetSystemClockNs()); -} - -static inline void Btrace(FILE* file, const char* name, - int64_t nanoseconds_monotonic) { - fprintf(file, "#btrace#%s|%" PRId64 "\n", name, nanoseconds_monotonic); -} - -static inline void Btrace(FILE* file, const char* name) { - Btrace(file, name, android::dvr::GetSystemClockNs()); -} - -static inline void BtraceData(const char* name, int64_t nanoseconds_monotonic, - int64_t data) { - const int kLogMessageLength = 256; - char log_message[kLogMessageLength]; - snprintf(log_message, kLogMessageLength, "#btrace#%s|%" PRId64, name, data); - atrace_int64(ATRACE_TAG_WEBVIEW, log_message, nanoseconds_monotonic); -} - -static inline void BtraceData(const char* name, int64_t data) { - BtraceData(name, android::dvr::GetSystemClockNs(), data); -} - -static inline void BtraceData(FILE* file, const char* name, - int64_t nanoseconds_monotonic, int64_t data) { - fprintf(file, "#btrace#%s|%" PRId64 "|%" PRId64 "\n", name, data, - nanoseconds_monotonic); -} - -static inline void BtraceData(FILE* file, const char* name, int64_t data) { - BtraceData(file, name, android::dvr::GetSystemClockNs(), data); -} - -#endif // ANDROID_DVR_BENCHMARK_H_ diff --git a/libs/vr/libdvrcommon/include/private/dvr/clock_ns.h b/libs/vr/libdvrcommon/include/private/dvr/clock_ns.h deleted file mode 100644 index 8e777edf6d..0000000000 --- a/libs/vr/libdvrcommon/include/private/dvr/clock_ns.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef ANDROID_DVR_CLOCK_NS_H_ -#define ANDROID_DVR_CLOCK_NS_H_ - -#include <stdint.h> -#include <time.h> - -namespace android { -namespace dvr { - -constexpr int64_t kNanosPerSecond = 1000000000ll; - -// Returns the standard Dream OS monotonic system time that corresponds with all -// timestamps found in Dream OS APIs. -static inline timespec GetSystemClock() { - timespec t; - clock_gettime(CLOCK_MONOTONIC, &t); - return t; -} - -static inline timespec GetSystemClockRaw() { - timespec t; - clock_gettime(CLOCK_MONOTONIC_RAW, &t); - return t; -} - -static inline int64_t GetSystemClockNs() { - timespec t = GetSystemClock(); - int64_t ns = kNanosPerSecond * (int64_t)t.tv_sec + (int64_t)t.tv_nsec; - return ns; -} - -static inline int64_t GetSystemClockRawNs() { - timespec t = GetSystemClockRaw(); - int64_t ns = kNanosPerSecond * (int64_t)t.tv_sec + (int64_t)t.tv_nsec; - return ns; -} - -static inline double NsToSec(int64_t nanoseconds) { - return nanoseconds / static_cast<double>(kNanosPerSecond); -} - -static inline double GetSystemClockSec() { return NsToSec(GetSystemClockNs()); } - -static inline double GetSystemClockMs() { return GetSystemClockSec() * 1000.0; } - -// Converts a nanosecond timestamp to a timespec. Based on the kernel function -// of the same name. -static inline timespec NsToTimespec(int64_t ns) { - timespec t; - int32_t remainder; - - t.tv_sec = ns / kNanosPerSecond; - remainder = ns % kNanosPerSecond; - if (remainder < 0) { - t.tv_nsec--; - remainder += kNanosPerSecond; - } - t.tv_nsec = remainder; - - return t; -} - -// Timestamp comparison functions that handle wrapping values correctly. -static inline bool TimestampLT(int64_t a, int64_t b) { - return static_cast<int64_t>(static_cast<uint64_t>(a) - - static_cast<uint64_t>(b)) < 0; -} -static inline bool TimestampLE(int64_t a, int64_t b) { - return static_cast<int64_t>(static_cast<uint64_t>(a) - - static_cast<uint64_t>(b)) <= 0; -} -static inline bool TimestampGT(int64_t a, int64_t b) { - return static_cast<int64_t>(static_cast<uint64_t>(a) - - static_cast<uint64_t>(b)) > 0; -} -static inline bool TimestampGE(int64_t a, int64_t b) { - return static_cast<int64_t>(static_cast<uint64_t>(a) - - static_cast<uint64_t>(b)) >= 0; -} - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_CLOCK_NS_H_ diff --git a/libs/vr/libdvrcommon/include/private/dvr/debug.h b/libs/vr/libdvrcommon/include/private/dvr/debug.h deleted file mode 100644 index c31a385ffb..0000000000 --- a/libs/vr/libdvrcommon/include/private/dvr/debug.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef ANDROID_DVR_DEBUG_H_ -#define ANDROID_DVR_DEBUG_H_ - -#include <GLES3/gl3.h> -#include <math.h> - -#include <log/log.h> - -#ifndef NDEBUG -#define CHECK_GL() \ - do { \ - const GLenum err = glGetError(); \ - if (err != GL_NO_ERROR) { \ - ALOGE("OpenGL error %d", err); \ - } \ - } while (0) - -#define CHECK_GL_FBO() \ - do { \ - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); \ - switch (status) { \ - case GL_FRAMEBUFFER_COMPLETE: \ - break; \ - case GL_FRAMEBUFFER_UNSUPPORTED: \ - ALOGE("GL_FRAMEBUFFER_UNSUPPORTED"); \ - break; \ - default: \ - ALOGE("FBO user error: %d", status); \ - break; \ - } \ - } while (0) -#else -#define CHECK_GL() -#define CHECK_GL_FBO() -#endif - -#endif // ANDROID_DVR_DEBUG_H_ diff --git a/libs/vr/libdvrcommon/include/private/dvr/eigen.h b/libs/vr/libdvrcommon/include/private/dvr/eigen.h deleted file mode 100644 index defaf583c4..0000000000 --- a/libs/vr/libdvrcommon/include/private/dvr/eigen.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef ANDROID_DVR_EIGEN_H_ -#define ANDROID_DVR_EIGEN_H_ - -#include <Eigen/Core> -#include <Eigen/Geometry> - -namespace Eigen { - -// Eigen doesn't take advantage of C++ template typedefs, but we can -template <class T, int N> -using Vector = Matrix<T, N, 1>; - -template <class T> -using Vector2 = Vector<T, 2>; - -template <class T> -using Vector3 = Vector<T, 3>; - -template <class T> -using Vector4 = Vector<T, 4>; - -template <class T, int N> -using RowVector = Matrix<T, 1, N>; - -template <class T> -using RowVector2 = RowVector<T, 2>; - -template <class T> -using RowVector3 = RowVector<T, 3>; - -template <class T> -using RowVector4 = RowVector<T, 4>; - -// In Eigen, the type you should be using for transformation matrices is the -// `Transform` class, instead of a raw `Matrix`. -// The `Projective` option means this will not make any assumptions about the -// last row of the object, making this suitable for use as general OpenGL -// projection matrices (which is the most common use-case). The one caveat -// is that in order to apply this transformation to non-homogeneous vectors -// (e.g., vec3), you must use the `.linear()` method to get the affine part of -// the matrix. -// -// Example: -// mat4 transform; -// vec3 position; -// vec3 transformed = transform.linear() * position; -// -// Note, the use of N-1 is because the parameter passed to Eigen is the ambient -// dimension of the transformation, not the size of the matrix iself. -// However graphics programmers sometimes get upset when they see a 3 next -// to a matrix when they expect a 4, so I'm hoping this will avoid that. -template <class T, int N> -using AffineMatrix = Transform<T, N-1, Projective>; - -} // namespace Eigen - -#endif // ANDROID_DVR_EIGEN_H_ diff --git a/libs/vr/libdvrcommon/include/private/dvr/field_of_view.h b/libs/vr/libdvrcommon/include/private/dvr/field_of_view.h deleted file mode 100644 index d0ee69c770..0000000000 --- a/libs/vr/libdvrcommon/include/private/dvr/field_of_view.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef ANDROID_DVR_FIELD_OF_VIEW_H_ -#define ANDROID_DVR_FIELD_OF_VIEW_H_ - -#include <cmath> - -#include <private/dvr/eigen.h> - -namespace android { -namespace dvr { - -// Encapsulates a generalized, asymmetric field of view with four half angles. -// Each half angle denotes the angle between the corresponding frustum plane. -// Together with a near and far plane, a FieldOfView forms the frustum of an -// off-axis perspective projection. -class FieldOfView { - public: - // The default constructor sets an angle of 0 (in any unit) for all four - // half-angles. - FieldOfView() : left_(0.0f), right_(0.0f), bottom_(0.0f), top_(0.0f) {} - - // Constructs a FieldOfView from four angles. - FieldOfView(float left, float right, float bottom, float top) - : left_(left), right_(right), bottom_(bottom), top_(top) {} - - explicit FieldOfView(const float* fov) - : FieldOfView(fov[0], fov[1], fov[2], fov[3]) {} - - // Accessors for all four half-angles. - float GetLeft() const { return left_; } - float GetRight() const { return right_; } - float GetBottom() const { return bottom_; } - float GetTop() const { return top_; } - - // Setters for all four half-angles. - void SetLeft(float left) { left_ = left; } - void SetRight(float right) { right_ = right; } - void SetBottom(float bottom) { bottom_ = bottom; } - void SetTop(float top) { top_ = top; } - - Eigen::AffineMatrix<float, 4> GetProjectionMatrix(float z_near, - float z_far) const { - float x_left = -std::tan(left_) * z_near; - float x_right = std::tan(right_) * z_near; - float y_bottom = -std::tan(bottom_) * z_near; - float y_top = std::tan(top_) * z_near; - - float zero = 0.0f; - if (x_left == x_right || y_bottom == y_top || z_near == z_far || - z_near <= zero || z_far <= zero) { - return Eigen::AffineMatrix<float, 4>::Identity(); - } - - float x = (2 * z_near) / (x_right - x_left); - float y = (2 * z_near) / (y_top - y_bottom); - float a = (x_right + x_left) / (x_right - x_left); - float b = (y_top + y_bottom) / (y_top - y_bottom); - float c = (z_near + z_far) / (z_near - z_far); - float d = (2 * z_near * z_far) / (z_near - z_far); - - // Note: Eigen matrix initialization syntax is always 'column-major' - // even if the storage is row-major. Or in other words, just write the - // matrix like you'd see in a math textbook. - Eigen::AffineMatrix<float, 4> result; - result.matrix() << x, 0, a, 0, - 0, y, b, 0, - 0, 0, c, d, - 0, 0, -1, 0; - return result; - } - - static FieldOfView FromProjectionMatrix( - const Eigen::AffineMatrix<float, 4>& m) { - // Compute tangents. - float tan_vert_fov = 1.0f / m(1, 1); - float tan_horz_fov = 1.0f / m(0, 0); - float t = (m(1, 2) + 1.0f) * tan_vert_fov; - float b = (m(1, 2) - 1.0f) * tan_vert_fov; - float l = (m(0, 2) - 1.0f) * tan_horz_fov; - float r = (m(0, 2) + 1.0f) * tan_horz_fov; - - return FieldOfView(std::atan(-l), std::atan(r), std::atan(-b), - std::atan(t)); - } - - private: - float left_; - float right_; - float bottom_; - float top_; -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_FIELD_OF_VIEW_H_ diff --git a/libs/vr/libdvrcommon/include/private/dvr/log_helpers.h b/libs/vr/libdvrcommon/include/private/dvr/log_helpers.h deleted file mode 100644 index 12ef622aaa..0000000000 --- a/libs/vr/libdvrcommon/include/private/dvr/log_helpers.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef ANDROID_DVR_LOG_HELPERS_H_ -#define ANDROID_DVR_LOG_HELPERS_H_ - -#include <iomanip> -#include <ostream> - -#include <private/dvr/eigen.h> -#include <private/dvr/field_of_view.h> - -namespace android { -namespace dvr { - -template <typename T> -inline std::ostream& operator<<(std::ostream& out, - const Eigen::Vector<T, 2>& vec) { - return out << "vec2(" << vec.x() << ',' << vec.y() << ')'; -} - -template <typename T> -inline std::ostream& operator<<(std::ostream& out, - const Eigen::Vector<T, 3>& vec) { - return out << "vec3(" << vec.x() << ',' << vec.y() << ',' << vec.z() << ')'; -} - -template <typename T> -inline std::ostream& operator<<(std::ostream& out, - const Eigen::Vector<T, 4>& vec) { - return out << "vec4(" << vec.x() << ',' << vec.y() << ',' << vec.z() << ',' - << vec.w() << ')'; -} - -template <typename T> -inline std::ostream& operator<<(std::ostream& out, - const Eigen::AffineMatrix<T, 4>& mat) { - out << std::setfill(' ') << std::setprecision(4) << std::fixed - << std::showpos; - out << "\nmat4["; - out << std::setw(10) << mat(0, 0) << " " << std::setw(10) << mat(0, 1) << " " - << std::setw(10) << mat(0, 2) << " " << std::setw(10) << mat(0, 3); - out << "]\n ["; - out << std::setw(10) << mat(1, 0) << " " << std::setw(10) << mat(1, 1) << " " - << std::setw(10) << mat(1, 2) << " " << std::setw(10) << mat(1, 3); - out << "]\n ["; - out << std::setw(10) << mat(2, 0) << " " << std::setw(10) << mat(2, 1) << " " - << std::setw(10) << mat(2, 2) << " " << std::setw(10) << mat(2, 3); - out << "]\n ["; - out << std::setw(10) << mat(3, 0) << " " << std::setw(10) << mat(3, 1) << " " - << std::setw(10) << mat(3, 2) << " " << std::setw(10) << mat(3, 3); - out << "]\n"; - - return out; -} - -inline std::ostream& operator<<(std::ostream& out, const FieldOfView& fov) { - return out << "fov(" << (fov.GetLeft() * 180.0f / M_PI) << ',' - << (fov.GetRight() * 180.0f / M_PI) << ',' - << (fov.GetBottom() * 180.0f / M_PI) << ',' - << (fov.GetTop() * 180.0f / M_PI) << ')'; -} - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_LOG_HELPERS_H_ diff --git a/libs/vr/libdvrcommon/include/private/dvr/matrix_helpers.h b/libs/vr/libdvrcommon/include/private/dvr/matrix_helpers.h deleted file mode 100644 index aef7146e22..0000000000 --- a/libs/vr/libdvrcommon/include/private/dvr/matrix_helpers.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef ANDROID_DVR_MATRIX_HELPERS_H_ -#define ANDROID_DVR_MATRIX_HELPERS_H_ - -#include <private/dvr/eigen.h> -#include <private/dvr/types.h> - -namespace android { -namespace dvr { - -// A helper function for creating a mat4 directly. -inline mat4 MakeMat4(float m00, float m01, float m02, float m03, float m10, - float m11, float m12, float m13, float m20, float m21, - float m22, float m23, float m30, float m31, float m32, - float m33) { - Eigen::Matrix4f matrix; - - matrix << m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, - m31, m32, m33; - - return mat4(matrix); -} - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_LOG_HELPERS_H_ diff --git a/libs/vr/libdvrcommon/include/private/dvr/numeric.h b/libs/vr/libdvrcommon/include/private/dvr/numeric.h deleted file mode 100644 index 45458939c7..0000000000 --- a/libs/vr/libdvrcommon/include/private/dvr/numeric.h +++ /dev/null @@ -1,175 +0,0 @@ -#ifndef ANDROID_DVR_NUMERIC_H_ -#define ANDROID_DVR_NUMERIC_H_ - -#include <cmath> -#include <limits> -#include <random> -#include <type_traits> - -#include <private/dvr/eigen.h> -#include <private/dvr/types.h> - -namespace android { -namespace dvr { - -template <typename FT> -static inline FT ToDeg(FT f) { - return f * static_cast<FT>(180.0 / M_PI); -} - -template <typename FT> -static inline FT ToRad(FT f) { - return f * static_cast<FT>(M_PI / 180.0); -} - -// Adjusts `x` to the periodic range `[lo, hi]` (to normalize angle values -// for example). -template <typename T> -T NormalizePeriodicRange(T x, T lo, T hi) { - T range_size = hi - lo; - - while (x < lo) { - x += range_size; - } - - while (x > hi) { - x -= range_size; - } - - return x; -} - -// Normalizes a measurement in radians. -// @param x the angle to be normalized -// @param centre the point around which to normalize the range -// @return the value of x, normalized to the range [centre - 180, centre + 180] -template <typename T> -T NormalizeDegrees(T x, T centre = static_cast<T>(180.0)) { - return NormalizePeriodicRange(x, centre - static_cast<T>(180.0), - centre + static_cast<T>(180.0)); -} - -// Normalizes a measurement in radians. -// @param x the angle to be normalized -// @param centre the point around which to normalize the range -// @return the value of x, normalized to the range -// [centre - M_PI, centre + M_PI] -// @remark the centre parameter is to make it possible to specify a different -// periodic range. This is useful if you are planning on comparing two -// angles close to 0 or M_PI, so that one might not accidentally end -// up on the other side of the range -template <typename T> -T NormalizeRadians(T x, T centre = static_cast<T>(M_PI)) { - return NormalizePeriodicRange(x, centre - static_cast<T>(M_PI), - centre + static_cast<T>(M_PI)); -} - -static inline vec2i Round(const vec2& v) { - return vec2i(roundf(v.x()), roundf(v.y())); -} - -static inline vec2i Scale(const vec2i& v, float scale) { - return vec2i(roundf(static_cast<float>(v.x()) * scale), - roundf(static_cast<float>(v.y()) * scale)); -} - -// Re-maps `x` from `[lba,uba]` to `[lbb,ubb]`. -template <typename T> -T ConvertRange(T x, T lba, T uba, T lbb, T ubb) { - return (((x - lba) * (ubb - lbb)) / (uba - lba)) + lbb; -} - -template <typename R1, typename R2> -static inline vec2 MapPoint(const vec2& pt, const R1& from, const R2& to) { - vec2 normalized((pt - vec2(from.p1)).array() / vec2(from.GetSize()).array()); - return (normalized * vec2(to.GetSize())) + vec2(to.p1); -} - -template <typename T> -inline bool IsZero(const T& v, - const T& tol = std::numeric_limits<T>::epsilon()) { - return std::abs(v) <= tol; -} - -template <typename T> -inline bool IsEqual(const T& a, const T& b, - const T& tol = std::numeric_limits<T>::epsilon()) { - return std::abs(b - a) <= tol; -} - -template <typename T> -T Square(const T& x) { - return x * x; -} - -template <typename T> -T RandomInRange(T lo, T hi, - typename - std::enable_if<std::is_floating_point<T>::value>::type* = 0) { - std::random_device rd; - std::mt19937 gen(rd()); - std::uniform_real_distribution<T> distro(lo, hi); - return distro(gen); -} - -template <typename T> -T RandomInRange(T lo, T hi, - typename - std::enable_if<std::is_integral<T>::value>::type* = 0) { - std::random_device rd; - std::mt19937 gen(rd()); - std::uniform_int_distribution<T> distro(lo, hi); - return distro(gen); -} - -template <typename Derived1, typename Derived2> -Derived1 RandomInRange( - const Eigen::MatrixBase<Derived1>& lo, - const Eigen::MatrixBase<Derived2>& hi) { - EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Derived1, Derived2); - - Derived1 result = Eigen::MatrixBase<Derived1>::Zero(); - - for (int row = 0; row < result.rows(); ++row) { - for (int col = 0; col < result.cols(); ++col) { - result(row, col) = RandomInRange(lo(row, col), hi(row, col)); - } - } - - return result; -} - -template <typename T> -T RandomRange(T x) { - return RandomInRange(-x, x); -} - -template <typename T> -T Clamp(T x, T lo, T hi) { - return std::min(std::max(x, lo), hi); -} - -inline mat3 ScaleMatrix(const vec2& scale_xy) { - return mat3(Eigen::Scaling(scale_xy[0], scale_xy[1], 1.0f)); -} - -inline mat3 TranslationMatrix(const vec2& translation) { - return mat3(Eigen::Translation2f(translation)); -} - -inline mat4 TranslationMatrix(const vec3& translation) { - return mat4(Eigen::Translation3f(translation)); -} - -inline vec2 TransformPoint(const mat3& m, const vec2& p) { - return m.linear() * p + m.translation(); -} - -inline vec2 TransformVector(const mat3& m, const vec2& p) { - return m.linear() * p; -} - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_NUMERIC_H_ diff --git a/libs/vr/libdvrcommon/include/private/dvr/ortho.h b/libs/vr/libdvrcommon/include/private/dvr/ortho.h deleted file mode 100644 index fc0bce3792..0000000000 --- a/libs/vr/libdvrcommon/include/private/dvr/ortho.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef ANDROID_DVR_ORTHO_H_ -#define ANDROID_DVR_ORTHO_H_ - -#include <private/dvr/types.h> - -namespace android { -namespace dvr { - -template <class T> -Eigen::AffineMatrix<T, 4> OrthoMatrix(T left, T right, T bottom, T top, - T znear, T zfar) { - Eigen::AffineMatrix<T, 4> result; - const T t2 = static_cast<T>(2); - const T a = t2 / (right - left); - const T b = t2 / (top - bottom); - const T c = t2 / (zfar - znear); - const T xoff = -(right + left) / (right - left); - const T yoff = -(top + bottom) / (top - bottom); - const T zoff = -(zfar + znear) / (zfar - znear); - const T t1 = static_cast<T>(1); - result.matrix() << a, 0, 0, xoff, - 0, b, 0, yoff, - 0, 0, c, zoff, - 0, 0, 0, t1; - return result; -} - -} // namespace android -} // namespace dvr - -#endif // ANDROID_DVR_ORTHO_H_ diff --git a/libs/vr/libdvrcommon/include/private/dvr/pose.h b/libs/vr/libdvrcommon/include/private/dvr/pose.h deleted file mode 100644 index 97944e8928..0000000000 --- a/libs/vr/libdvrcommon/include/private/dvr/pose.h +++ /dev/null @@ -1,118 +0,0 @@ -#ifndef ANDROID_DVR_POSE_H_ -#define ANDROID_DVR_POSE_H_ - -#include <private/dvr/eigen.h> - -namespace android { -namespace dvr { - -// Encapsulates a 3D pose (rotation and position). -// -// @tparam T Data type for storing the position coordinate and rotation -// quaternion. -template <typename T> -class Pose { - public: - // Creates identity pose. - Pose() - : rotation_(Eigen::Quaternion<T>::Identity()), - position_(Eigen::Vector3<T>::Zero()) {} - - // Initializes a pose with given rotation and position. - // - // rotation Initial rotation. - // position Initial position. - Pose(Eigen::Quaternion<T> rotation, Eigen::Vector3<T> position) - : rotation_(rotation), position_(position) {} - - void Invert() { - rotation_ = rotation_.inverse(); - position_ = rotation_ * -position_; - } - - Pose Inverse() const { - Pose result(*this); - result.Invert(); - return result; - } - - // Compute the composition of this pose with another, storing the result - // in the current object - void ComposeInPlace(const Pose& other) { - position_ = position_ + rotation_ * other.position_; - rotation_ = rotation_ * other.rotation_; - } - - // Computes the composition of this pose with another, and returns the result - Pose Compose(const Pose& other) const { - Pose result(*this); - result.ComposeInPlace(other); - return result; - } - - Eigen::Vector3<T> TransformPoint(const Eigen::Vector3<T>& v) const { - return rotation_ * v + position_; - } - - Eigen::Vector3<T> Transform(const Eigen::Vector3<T>& v) const { - return rotation_ * v; - } - - Pose& operator*=(const Pose& other) { - ComposeInPlace(other); - return *this; - } - - Pose operator*(const Pose& other) const { return Compose(other); } - - // Gets the rotation of the 3D pose. - Eigen::Quaternion<T> GetRotation() const { return rotation_; } - - // Gets the position of the 3D pose. - Eigen::Vector3<T> GetPosition() const { return position_; } - - // Sets the rotation of the 3D pose. - void SetRotation(Eigen::Quaternion<T> rotation) { rotation_ = rotation; } - - // Sets the position of the 3D pose. - void SetPosition(Eigen::Vector3<T> position) { position_ = position; } - - // Gets a 4x4 matrix representing a transform from the reference space (that - // the rotation and position of the pose are relative to) to the object space. - Eigen::AffineMatrix<T, 4> GetObjectFromReferenceMatrix() const; - - // Gets a 4x4 matrix representing a transform from the object space to the - // reference space (that the rotation and position of the pose are relative - // to). - Eigen::AffineMatrix<T, 4> GetReferenceFromObjectMatrix() const; - - private: - Eigen::Quaternion<T> rotation_; - Eigen::Vector3<T> position_; -}; - -template <typename T> -Eigen::AffineMatrix<T, 4> Pose<T>::GetObjectFromReferenceMatrix() const { - // The transfrom from the reference is the inverse of the pose. - Eigen::AffineMatrix<T, 4> matrix(rotation_.inverse().toRotationMatrix()); - return matrix.translate(-position_); -} - -template <typename T> -Eigen::AffineMatrix<T, 4> Pose<T>::GetReferenceFromObjectMatrix() const { - // The transfrom to the reference. - Eigen::AffineMatrix<T, 4> matrix(rotation_.toRotationMatrix()); - return matrix.pretranslate(position_); -} - -//------------------------------------------------------------------------------ -// Type-specific typedefs. -//------------------------------------------------------------------------------ - -using Posef = Pose<float>; -using Posed = Pose<double>; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_POSE_H_ diff --git a/libs/vr/libdvrcommon/include/private/dvr/range.h b/libs/vr/libdvrcommon/include/private/dvr/range.h deleted file mode 100644 index 1d06c96ec5..0000000000 --- a/libs/vr/libdvrcommon/include/private/dvr/range.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef ANDROID_DVR_RANGE_H_ -#define ANDROID_DVR_RANGE_H_ - -#include <private/dvr/eigen.h> - -namespace android { -namespace dvr { - -// TODO(skiazyk): Replace all instances of this with Eigen::AlignedBox - -// Container of two points that define a 2D range. -template <class T, int d> -struct Range { - // Construct an uninitialized Range. - Range() {} - Range(Eigen::Vector<T, d> p1, Eigen::Vector<T, d> p2) : p1(p1), p2(p2) {} - - static Range<T, d> FromSize(Eigen::Vector<T, d> p1, - Eigen::Vector<T, d> size) { - return Range<T, d>(p1, p1 + size); - } - - bool operator==(const Range<T, d>& rhs) const { - return p1 == rhs.p1 && p2 == rhs.p2; - } - - Eigen::Vector<T, d> GetMinPoint() const { return p1; } - - Eigen::Vector<T, d> GetMaxPoint() const { return p2; } - - Eigen::Vector<T, d> GetSize() const { return p2 - p1; } - - Eigen::Vector<T, d> p1; - Eigen::Vector<T, d> p2; -}; - -typedef Range<int, 2> Range2i; -typedef Range<float, 2> Range2f; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_RANGE_H_ diff --git a/libs/vr/libdvrcommon/include/private/dvr/ring_buffer.h b/libs/vr/libdvrcommon/include/private/dvr/ring_buffer.h deleted file mode 100644 index 18242411b9..0000000000 --- a/libs/vr/libdvrcommon/include/private/dvr/ring_buffer.h +++ /dev/null @@ -1,99 +0,0 @@ -#ifndef ANDROID_DVR_RING_BUFFER_H_ -#define ANDROID_DVR_RING_BUFFER_H_ - -#include <utility> -#include <vector> - -namespace android { -namespace dvr { - -// A simple ring buffer implementation. -// -// A vector works but you either have to keep track of start_ and size_ yourself -// or erase() from the front which is inefficient. -// -// A deque works but the common usage pattern of Append() PopFront() Append() -// PopFront() looks like it allocates each time size goes from 0 --> 1, which we -// don't want. This class allocates only once. -template <typename T> -class RingBuffer { - public: - RingBuffer() { Reset(0); } - - explicit RingBuffer(size_t capacity) { Reset(capacity); } - - RingBuffer(const RingBuffer& other) = default; - RingBuffer(RingBuffer&& other) noexcept = default; - RingBuffer& operator=(const RingBuffer& other) = default; - RingBuffer& operator=(RingBuffer&& other) noexcept = default; - - void Append(const T& val) { - if (IsFull()) - PopFront(); - Get(size_) = val; - size_++; - } - - void Append(T&& val) { - if (IsFull()) - PopFront(); - Get(size_) = std::move(val); - size_++; - } - - bool IsEmpty() const { return size_ == 0; } - - bool IsFull() const { return size_ == buffer_.size(); } - - size_t GetSize() const { return size_; } - - size_t GetCapacity() const { return buffer_.size(); } - - T& Get(size_t i) { return buffer_[(start_ + i) % buffer_.size()]; } - - const T& Get(size_t i) const { - return buffer_[(start_ + i) % buffer_.size()]; - } - - const T& Back() const { return Get(size_ - 1); } - - T& Back() { return Get(size_ - 1); } - - const T& Front() const { return Get(0); } - - T& Front() { return Get(0); } - - void PopBack() { - if (size_ != 0) { - Get(size_ - 1) = T(); - size_--; - } - } - - void PopFront() { - if (size_ != 0) { - Get(0) = T(); - start_ = (start_ + 1) % buffer_.size(); - size_--; - } - } - - void Clear() { Reset(GetCapacity()); } - - void Reset(size_t capacity) { - start_ = size_ = 0; - buffer_.clear(); - buffer_.resize(capacity); - } - - private: - // Ideally we'd allocate our own memory and use placement new to instantiate - // instances of T instead of using a vector, but the vector is simpler. - std::vector<T> buffer_; - size_t start_, size_; -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_RING_BUFFER_H_ diff --git a/libs/vr/libdvrcommon/include/private/dvr/test/test_macros.h b/libs/vr/libdvrcommon/include/private/dvr/test/test_macros.h deleted file mode 100644 index 6048652f92..0000000000 --- a/libs/vr/libdvrcommon/include/private/dvr/test/test_macros.h +++ /dev/null @@ -1,124 +0,0 @@ -#ifndef LIBS_VR_LIBDVRCOMMON_INCLUDE_PRIVATE_DVR_TEST_TEST_MACROS_H_ -#define LIBS_VR_LIBDVRCOMMON_INCLUDE_PRIVATE_DVR_TEST_TEST_MACROS_H_ - -#include <gtest/gtest.h> - -#include <cmath> - -#include <private/dvr/numeric.h> - -namespace android { -namespace dvr { - -template <int N, typename A, typename B, typename T> -::testing::AssertionResult CmpArrayLikeFloatEq( - const char* expectedStr, const char* actualStr, const char* toleranceStr, - const A& expected, const B& actual, const T& tolerance) { - for (int i = 0; i < N; ++i) { - if (!IsEqual(expected[i], actual[i], tolerance)) { - return ::testing::AssertionFailure() - << "\"" << expectedStr << "\" and \"" << actualStr - << "\" differ at element " << i << " by at least " << tolerance - << " : " - << " Expected \"" << expected[i] << "\", was \"" << actual[i] - << "\"."; - } - } - - return ::testing::AssertionSuccess(); -} - -template <int N, typename A, typename B, typename T> -::testing::AssertionResult CmpMatrixLikeFloatEq( - const char* expectedStr, const char* actualStr, const char* toleranceStr, - const A& expected, const B& actual, const T& tolerance) { - for (int r = 0; r < N; ++r) { - for (int c = 0; c < N; ++c) { - if (!IsEqual(expected(r, c), actual(r, c), tolerance)) { - return ::testing::AssertionFailure() - << "\"" << expectedStr << "\" and \"" << actualStr - << "\" differ at (" << r << "," << c << ")" - << " by at least " << tolerance << " : " - << " Expected \"" << expected(r, c) << "\", was \"" - << actual(r, c) << "\"."; - } - } - } - - return ::testing::AssertionSuccess(); -} - -template <int N, typename A, typename B, typename T> -::testing::AssertionResult CmpArrayLikeFloatNe( - const char* expectedStr, const char* actualStr, const char* toleranceStr, - const A& expected, const B& actual, const T& tolerance) { - for (int i = 0; i < N; ++i) { - if (!IsEqual(expected[i], actual[i], tolerance)) { - return ::testing::AssertionSuccess(); - } - } - - ::testing::Message message; - message << "Expected \"" << expectedStr - << "\" to differ from provided value \"" << actualStr - << "\" by at least " << tolerance << "."; - - return ::testing::AssertionFailure(message); -} - -template <int N, typename A, typename B, typename T> -::testing::AssertionResult CmpMatrixLikeFloatNe( - const char* expectedStr, const char* actualStr, const char* toleranceStr, - const A& expected, const B& actual, const T& tolerance) { - for (int r = 0; r < N; ++r) { - for (int c = 0; c < N; ++c) { - if (!IsEqual(expected(r, c), actual(r, c), tolerance)) { - return ::testing::AssertionSuccess(); - } - } - } - - ::testing::Message message; - message << "Expected \"" << expectedStr - << "\" to differ from provided value \"" << actualStr - << "\" by at least " << tolerance << "."; - - return ::testing::AssertionFailure(message); -} - -} // namespace dvr -} // namespace android - -#define EXPECT_VEC3_NEAR(expected, actual, tol) \ - EXPECT_PRED_FORMAT3(android::dvr::CmpArrayLikeFloatEq<3>, expected, actual, \ - tol) - -#define EXPECT_VEC3_NOT_NEAR(expected, actual, tol) \ - EXPECT_PRED_FORMAT3(android::dvr::CmpArrayLikeFloatNe<3>, expected, actual, \ - tol) - -#define EXPECT_QUAT_NEAR(expected, actual, tol) \ - EXPECT_PRED_FORMAT3(android::dvr::CmpArrayLikeFloatEq<3>, expected.coeffs(), \ - actual.coeffs(), tol) - -#define EXPECT_QUAT_NOT_NEAR(expected, actual, tol) \ - EXPECT_PRED_FORMAT3(android::dvr::CmpArrayLikeFloatNe<3>, expected.coeffs(), \ - actual.coeffs(), tol) - -#define EXPECT_MAT4_NEAR(expected, actual, tol) \ - EXPECT_PRED_FORMAT3(android::dvr::CmpMatrixLikeFloatEq<4>, expected, actual, \ - tol) - -#define EXPECT_MAT4_NOT_NEAR(expected, actual, tol) \ - EXPECT_PRED_FORMAT3(android::dvr::CmpMatrixLikeFloatNe<4>, expected, actual, \ - tol) - -#define EXPECT_MAT3_NEAR(expected, actual, tol) \ - EXPECT_PRED_FORMAT3(android::dvr \ - : CmpMatrixLikeFloatEq<3>, expected, actual, tol) - -#define EXPECT_MAT3_NOT_NEAR(expected, actual, tol) \ - EXPECT_PRED_FORMAT3(android::dvr::CmpMatrixLikeFloatNe<3>, expected, actual, \ - tol) - -#endif // LIBS_VR_LIBDVRCOMMON_INCLUDE_PRIVATE_DVR_TEST_TEST_MACROS_H_ diff --git a/libs/vr/libdvrcommon/include/private/dvr/types.h b/libs/vr/libdvrcommon/include/private/dvr/types.h deleted file mode 100644 index 1fa54afe92..0000000000 --- a/libs/vr/libdvrcommon/include/private/dvr/types.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef ANDROID_DVR_TYPES_H_ -#define ANDROID_DVR_TYPES_H_ - -// All basic types used by VR code. - -#include <private/dvr/eigen.h> -#include <private/dvr/field_of_view.h> -#include <private/dvr/pose.h> -#include <private/dvr/range.h> - -namespace android { -namespace dvr { - -enum RgbColorChannel { kRed, kGreen, kBlue }; - -// EyeType: 0 for left, 1 for right. -enum EyeType { kLeftEye = 0, kRightEye = 1 }; - -// In the context of VR, vector types are used as much as base types. - -using vec2f = Eigen::Vector2f; -using vec2d = Eigen::Vector2d; -using vec2i = Eigen::Vector2i; -using vec2 = vec2f; - -using vec3f = Eigen::Vector3f; -using vec3d = Eigen::Vector3d; -using vec3i = Eigen::Vector3i; -using vec3 = vec3f; - -using vec4f = Eigen::Vector4f; -using vec4d = Eigen::Vector4d; -using vec4i = Eigen::Vector4i; -using vec4 = vec4f; - -using mat3f = Eigen::AffineMatrix<float, 3>; -using mat3d = Eigen::AffineMatrix<double, 3>; -using mat3 = mat3f; - -using mat4f = Eigen::AffineMatrix<float, 4>; -using mat4d = Eigen::AffineMatrix<double, 4>; -using mat4 = mat4f; - -using quatf = Eigen::Quaternionf; -using quatd = Eigen::Quaterniond; -using quat = quatf; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_TYPES_H_ diff --git a/libs/vr/libdvrcommon/tests/numeric_test.cpp b/libs/vr/libdvrcommon/tests/numeric_test.cpp deleted file mode 100644 index 1ee1447703..0000000000 --- a/libs/vr/libdvrcommon/tests/numeric_test.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include <gtest/gtest.h> - -#include <private/dvr/numeric.h> - -using TestTypes = ::testing::Types<float, double, int>; - -using android::dvr::RandomInRange; - -template <typename T> -class NumericTest : public ::testing::TestWithParam<T> { - public: - using FT = T; -}; - -TYPED_TEST_CASE(NumericTest, TestTypes); - -TYPED_TEST(NumericTest, RandomInRange) { - using FT = typename TestFixture::FT; - - const int kNumTrials = 50; - const FT kLowRange = static_cast<FT>(-100); - const FT kHighRange = static_cast<FT>(100); - - for (int i = 0; i < kNumTrials; ++i) { - FT value = RandomInRange(kLowRange, kHighRange); - - EXPECT_LE(kLowRange, value); - EXPECT_GE(kHighRange, value); - } -} - -TEST(RandomInRange, TestIntVersion) { - // This checks specifically that the function does not always give the lo - // value (this was previously a bug) - - const int kNumTrials = 50; - const int kLowRange = -100; - const int kHighRange = 100; - - for (int i = 0; i < kNumTrials; ++i) { - int value = RandomInRange(kLowRange, kHighRange); - - if (value != kLowRange) { - SUCCEED(); - return; - } - } - - FAIL() << "Did not produce a value other than the range minimum for " - << "integers."; -} - -TEST(RandomInRange, TestVectorVersion) { - Eigen::Vector3d lo(-3.0, -4.0, -5.0); - Eigen::Vector3d hi(5.0, 4.0, 3.0); - - const int kNumTrials = 50; - - for (int i = 0; i < kNumTrials; ++i) { - Eigen::Vector3d result = RandomInRange(lo, hi); - - for (int j = 0; j < 3; ++j) { - EXPECT_LE(lo[j], result[j]); - EXPECT_GE(hi[j], result[j]); - } - } -} diff --git a/libs/vr/libdvrcommon/tests/pose_test.cpp b/libs/vr/libdvrcommon/tests/pose_test.cpp deleted file mode 100644 index aa1896da15..0000000000 --- a/libs/vr/libdvrcommon/tests/pose_test.cpp +++ /dev/null @@ -1,154 +0,0 @@ -#include <gtest/gtest.h> - -#include <private/dvr/eigen.h> -#include <private/dvr/pose.h> -#include <private/dvr/test/test_macros.h> - -using PoseTypes = ::testing::Types<float, double>; - -template <class T> -class PoseTest : public ::testing::TestWithParam<T> { - public: - using FT = T; - using Pose_t = android::dvr::Pose<FT>; - using quat_t = Eigen::Quaternion<FT>; - using vec3_t = Eigen::Vector3<FT>; - using mat4_t = Eigen::AffineMatrix<FT, 4>; -}; - -TYPED_TEST_CASE(PoseTest, PoseTypes); - -// Check that the two matrix methods are inverses of each other -TYPED_TEST(PoseTest, SelfInverse) { - using quat_t = typename TestFixture::quat_t; - using vec3_t = typename TestFixture::vec3_t; - using Pose_t = typename TestFixture::Pose_t; - using mat4_t = typename TestFixture::mat4_t; - using FT = typename TestFixture::FT; - - const auto tolerance = FT(0.0001); - - const quat_t initial_rotation(Eigen::AngleAxis<FT>( - FT(M_PI / 3.0), vec3_t(FT(3.0), FT(4.0), FT(5.0)).normalized())); - const vec3_t initial_position = vec3_t(FT(2.0), FT(10.0), FT(-4.0)); - const Pose_t initial_pose(initial_rotation, initial_position); - - auto result_pose = initial_pose.GetReferenceFromObjectMatrix() * - initial_pose.GetObjectFromReferenceMatrix(); - - EXPECT_MAT4_NEAR(result_pose, mat4_t::Identity(), tolerance); -} - -TYPED_TEST(PoseTest, TransformPoint) { - using quat_t = typename TestFixture::quat_t; - using vec3_t = typename TestFixture::vec3_t; - using Pose_t = typename TestFixture::Pose_t; - using FT = typename TestFixture::FT; - - const auto tolerance = FT(0.0001); - - const quat_t pose_rotation( - Eigen::AngleAxis<FT>(FT(M_PI / 2.0), vec3_t(FT(0.0), FT(0.0), FT(1.0)))); - const auto pose_position = vec3_t(FT(1.0), FT(1.0), FT(2.0)); - - const Pose_t test_pose(pose_rotation, pose_position); - - for (int axis = 0; axis < 3; ++axis) { - vec3_t start_position = vec3_t::Zero(); - start_position[axis] = FT(1.0); - const vec3_t expected_transformed = - (pose_rotation * start_position) + pose_position; - const vec3_t actual_transformed = test_pose.TransformPoint(start_position); - EXPECT_VEC3_NEAR(expected_transformed, actual_transformed, tolerance); - } -} - -TYPED_TEST(PoseTest, TransformVector) { - using quat_t = typename TestFixture::quat_t; - using vec3_t = typename TestFixture::vec3_t; - using Pose_t = typename TestFixture::Pose_t; - using FT = typename TestFixture::FT; - - const auto tolerance = FT(0.0001); - - const quat_t pose_rotation(Eigen::AngleAxis<FT>( - FT(M_PI / 6.0), vec3_t(FT(3.0), FT(4.0), FT(5.0)).normalized())); - - const auto pose_position = vec3_t(FT(500.0), FT(-500.0), FT(300.0)); - - const Pose_t test_pose(pose_rotation, pose_position); - - for (int axis = 0; axis < 3; ++axis) { - vec3_t start_position = vec3_t::Zero(); - start_position[axis] = FT(1.0); - const vec3_t expected_rotated = pose_rotation * start_position; - const vec3_t actual_rotated = test_pose.Transform(start_position); - EXPECT_VEC3_NEAR(expected_rotated, actual_rotated, tolerance); - } -} - -TYPED_TEST(PoseTest, Composition) { - using quat_t = typename TestFixture::quat_t; - using Pose_t = typename TestFixture::Pose_t; - using vec3_t = typename TestFixture::vec3_t; - using FT = typename TestFixture::FT; - - const auto tolerance = FT(0.0001); - - const quat_t first_rotation( - Eigen::AngleAxis<FT>(FT(M_PI / 2.0), vec3_t(FT(0.0), FT(0.0), FT(1.0)))); - const auto first_offset = vec3_t(FT(-3.0), FT(2.0), FT(-1.0)); - const quat_t second_rotation(Eigen::AngleAxis<FT>( - FT(M_PI / 3.0), vec3_t(FT(1.0), FT(-1.0), FT(0.0)).normalized())); - const auto second_offset = vec3_t(FT(6.0), FT(-7.0), FT(-8.0)); - - const Pose_t first_pose(first_rotation, first_offset); - const Pose_t second_pose(second_rotation, second_offset); - - const auto combined_pose(second_pose.Compose(first_pose)); - - for (int axis = 0; axis < 3; ++axis) { - vec3_t start_position = vec3_t::Zero(); - start_position[axis] = FT(1.0); - const vec3_t expected_transformed = - second_pose.TransformPoint(first_pose.TransformPoint(start_position)); - const vec3_t actual_transformed = - combined_pose.TransformPoint(start_position); - EXPECT_VEC3_NEAR(expected_transformed, actual_transformed, tolerance); - } -} - -TYPED_TEST(PoseTest, Inverse) { - using quat_t = typename TestFixture::quat_t; - using vec3_t = typename TestFixture::vec3_t; - using Pose_t = typename TestFixture::Pose_t; - using FT = typename TestFixture::FT; - - const auto tolerance = FT(0.0001); - - const quat_t pose_rotation(Eigen::AngleAxis<FT>( - FT(M_PI / 2.0), vec3_t(FT(4.0), FT(-2.0), FT(-1.0)).normalized())); - const auto pose_position = vec3_t(FT(-1.0), FT(2.0), FT(-4.0)); - - Pose_t pose(pose_rotation, pose_position); - const Pose_t pose_inverse = pose.Inverse(); - - for (int axis = 0; axis < 3; ++axis) { - vec3_t start_position = vec3_t::Zero(); - start_position[axis] = FT(1.0); - const vec3_t transformed = pose.Transform(start_position); - const vec3_t inverted = pose_inverse.Transform(transformed); - EXPECT_VEC3_NEAR(start_position, inverted, tolerance); - } - - Pose_t nullified_pose[2] = { - pose.Compose(pose_inverse), pose_inverse.Compose(pose), - }; - - for (int i = 0; i < 2; ++i) { - EXPECT_QUAT_NEAR(quat_t::Identity(), nullified_pose[i].GetRotation(), - tolerance); - EXPECT_VEC3_NEAR(vec3_t::Zero(), nullified_pose[i].GetPosition(), - tolerance); - } -} diff --git a/libs/vr/libpdx/Android.bp b/libs/vr/libpdx/Android.bp deleted file mode 100644 index c95603bcf7..0000000000 --- a/libs/vr/libpdx/Android.bp +++ /dev/null @@ -1,85 +0,0 @@ -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "frameworks_native_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["frameworks_native_license"], -} - -cc_library_headers { - name: "libpdx_headers", - export_include_dirs: ["private"], - vendor_available: true, - min_sdk_version: "29", -} - -cc_library_static { - name: "libpdx", - cflags: [ - "-Wall", - "-Wextra", - "-Werror", - "-DLOG_TAG=\"libpdx\"", - "-DTRACE=0", - ], - header_libs: ["libpdx_headers"], - export_header_lib_headers: ["libpdx_headers"], - srcs: [ - "client.cpp", - "service.cpp", - "service_dispatcher.cpp", - "status.cpp", - ], - shared_libs: [ - "libbinder", - "libcutils", - "libutils", - "liblog", - ], -} - -cc_test { - name: "pdx_tests", - cflags: [ - "-Wall", - "-Wextra", - "-Werror", - ], - srcs: [ - "client_tests.cpp", - "mock_tests.cpp", - "serialization_tests.cpp", - "service_tests.cpp", - "status_tests.cpp", - "thread_local_buffer_tests.cpp", - "variant_tests.cpp", - ], - static_libs: [ - "libcutils", - "libgmock", - "libpdx", - "liblog", - "libutils", - ], - shared_libs: [ - "libvndksupport", - ], -} - -// Code analysis target. -cc_test { - name: "pdx_encoder_performance_test", - cflags: [ - "-Wall", - "-Wextra", - "-Werror", - "-O2", - ], - srcs: [ - "encoder_performance_test.cpp", - ], - static_libs: [ - "libpdx", - ], -} diff --git a/libs/vr/libpdx/client.cpp b/libs/vr/libpdx/client.cpp deleted file mode 100644 index 3c66a40a1b..0000000000 --- a/libs/vr/libpdx/client.cpp +++ /dev/null @@ -1,290 +0,0 @@ -#include "pdx/client.h" - -#include <log/log.h> - -#include <pdx/trace.h> - -namespace android { -namespace pdx { - -void Client::EnableAutoReconnect(int64_t reconnect_timeout_ms) { - if (channel_factory_) { - reconnect_timeout_ms_ = reconnect_timeout_ms; - auto_reconnect_enabled_ = true; - } -} - -void Client::DisableAutoReconnect() { auto_reconnect_enabled_ = false; } - -bool Client::IsConnected() const { return channel_.get() != nullptr; } - -Status<void> Client::CheckReconnect() { - Status<void> ret; - bool was_disconnected = !IsConnected(); - if (auto_reconnect_enabled_ && was_disconnected && channel_factory_) { - auto status = channel_factory_->Connect(reconnect_timeout_ms_); - if (!status) { - error_ = -status.error(); - ret.SetError(status.error()); - return ret; - } - channel_ = status.take(); - } - - if (!IsConnected()) { - ret.SetError(ESHUTDOWN); - } else { - // Call the subclass OnConnect handler. The subclass may choose to close the - // connection in the handler, in which case error_ will be non-zero. - if (was_disconnected) - OnConnect(); - if (!IsConnected()) - ret.SetError(-error_); - else - ret.SetValue(); - } - - return ret; -} - -bool Client::NeedToDisconnectChannel(int error) const { - return error == ESHUTDOWN && auto_reconnect_enabled_; -} - -void Client::CheckDisconnect(int error) { - if (NeedToDisconnectChannel(error)) - Close(error); -} - -Client::Client(std::unique_ptr<ClientChannel> channel) - : channel_{std::move(channel)} {} - -Client::Client(std::unique_ptr<ClientChannelFactory> channel_factory, - int64_t timeout_ms) - : channel_factory_{std::move(channel_factory)} { - auto status = channel_factory_->Connect(timeout_ms); - if (!status) { - ALOGE("Client::Client: Failed to connect to service because: %s", - status.GetErrorMessage().c_str()); - error_ = -status.error(); - } else { - channel_ = status.take(); - } -} - -bool Client::IsInitialized() const { - return IsConnected() || (channel_factory_ && auto_reconnect_enabled_); -} - -void Client::OnConnect() {} - -int Client::error() const { return error_; } - -Status<void> Client::SendImpulse(int opcode) { - PDX_TRACE_NAME("Client::SendImpulse"); - - auto status = CheckReconnect(); - if (!status) - return status; - - status = channel_->SendImpulse(opcode, nullptr, 0); - CheckDisconnect(status); - return status; -} - -Status<void> Client::SendImpulse(int opcode, const void* buffer, - size_t length) { - PDX_TRACE_NAME("Client::SendImpulse"); - - auto status = CheckReconnect(); - if (!status) - return status; - - status = channel_->SendImpulse(opcode, buffer, length); - CheckDisconnect(status); - return status; -} - -void Client::Close(int error) { - channel_.reset(); - // Normalize error codes to negative integer space. - error_ = error <= 0 ? error : -error; -} - -int Client::event_fd() const { - return IsConnected() ? channel_->event_fd() : -1; -} - -LocalChannelHandle& Client::GetChannelHandle() { - return channel_->GetChannelHandle(); -} - -const LocalChannelHandle& Client::GetChannelHandle() const { - return channel_->GetChannelHandle(); -} - -///////////////////////////// Transaction implementation ////////////////////// - -Transaction::Transaction(Client& client) : client_{client} {} - -Transaction::~Transaction() { - if (state_allocated_ && client_.GetChannel()) - client_.GetChannel()->FreeTransactionState(state_); -} - -bool Transaction::EnsureStateAllocated() { - if (!state_allocated_ && client_.GetChannel()) { - state_ = client_.GetChannel()->AllocateTransactionState(); - state_allocated_ = true; - } - return state_allocated_; -} - -void Transaction::SendTransaction(int opcode, Status<void>* ret, - const iovec* send_vector, size_t send_count, - const iovec* receive_vector, - size_t receive_count) { - *ret = client_.CheckReconnect(); - if (!*ret) - return; - - if (!EnsureStateAllocated()) { - ret->SetError(ESHUTDOWN); - return; - } - - auto status = client_.GetChannel()->SendWithInt( - state_, opcode, send_vector, send_count, receive_vector, receive_count); - - if (status) { - ret->SetValue(); - } else { - ret->SetError(status.error()); - } - CheckDisconnect(status); -} - -void Transaction::SendTransaction(int opcode, Status<int>* ret, - const iovec* send_vector, size_t send_count, - const iovec* receive_vector, - size_t receive_count) { - auto status = client_.CheckReconnect(); - if (!status) { - ret->SetError(status.error()); - return; - } - - if (!EnsureStateAllocated()) { - ret->SetError(ESHUTDOWN); - return; - } - - *ret = client_.GetChannel()->SendWithInt( - state_, opcode, send_vector, send_count, receive_vector, receive_count); - - CheckDisconnect(*ret); -} - -void Transaction::SendTransaction(int opcode, Status<LocalHandle>* ret, - const iovec* send_vector, size_t send_count, - const iovec* receive_vector, - size_t receive_count) { - auto status = client_.CheckReconnect(); - if (!status) { - ret->SetError(status.error()); - return; - } - - if (!EnsureStateAllocated()) { - ret->SetError(ESHUTDOWN); - return; - } - - *ret = client_.GetChannel()->SendWithFileHandle( - state_, opcode, send_vector, send_count, receive_vector, receive_count); - - CheckDisconnect(*ret); -} - -void Transaction::SendTransaction(int opcode, Status<LocalChannelHandle>* ret, - const iovec* send_vector, size_t send_count, - const iovec* receive_vector, - size_t receive_count) { - auto status = client_.CheckReconnect(); - if (!status) { - ret->SetError(status.error()); - return; - } - - if (!EnsureStateAllocated()) { - ret->SetError(ESHUTDOWN); - return; - } - - *ret = client_.GetChannel()->SendWithChannelHandle( - state_, opcode, send_vector, send_count, receive_vector, receive_count); - - CheckDisconnect(*ret); -} - -Status<FileReference> Transaction::PushFileHandle(const LocalHandle& handle) { - if (client_.CheckReconnect() && EnsureStateAllocated()) - return client_.GetChannel()->PushFileHandle(state_, handle); - return ErrorStatus{ESHUTDOWN}; -} - -Status<FileReference> Transaction::PushFileHandle( - const BorrowedHandle& handle) { - if (client_.CheckReconnect() && EnsureStateAllocated()) - return client_.GetChannel()->PushFileHandle(state_, handle); - return ErrorStatus{ESHUTDOWN}; -} - -Status<FileReference> Transaction::PushFileHandle(const RemoteHandle& handle) { - return handle.Get(); -} - -Status<ChannelReference> Transaction::PushChannelHandle( - const LocalChannelHandle& handle) { - if (client_.CheckReconnect() && EnsureStateAllocated()) - return client_.GetChannel()->PushChannelHandle(state_, handle); - return ErrorStatus{ESHUTDOWN}; -} - -Status<ChannelReference> Transaction::PushChannelHandle( - const BorrowedChannelHandle& handle) { - if (client_.CheckReconnect() && EnsureStateAllocated()) - return client_.GetChannel()->PushChannelHandle(state_, handle); - return ErrorStatus{ESHUTDOWN}; -} - -Status<ChannelReference> Transaction::PushChannelHandle( - const RemoteChannelHandle& handle) { - return handle.value(); -} - -bool Transaction::GetFileHandle(FileReference ref, LocalHandle* handle) { - return client_.CheckReconnect() && EnsureStateAllocated() && - client_.GetChannel()->GetFileHandle(state_, ref, handle); -} - -bool Transaction::GetChannelHandle(ChannelReference ref, - LocalChannelHandle* handle) { - return client_.CheckReconnect() && EnsureStateAllocated() && - client_.GetChannel()->GetChannelHandle(state_, ref, handle); -} - -void Transaction::CheckDisconnect(int error) { - if (client_.NeedToDisconnectChannel(error)) { - if (state_allocated_) { - if (client_.GetChannel()) - client_.GetChannel()->FreeTransactionState(state_); - state_ = nullptr; - state_allocated_ = false; - } - client_.Close(error); - } -} - -} // namespace pdx -} // namespace android diff --git a/libs/vr/libpdx/client_tests.cpp b/libs/vr/libpdx/client_tests.cpp deleted file mode 100644 index 99ccc698c4..0000000000 --- a/libs/vr/libpdx/client_tests.cpp +++ /dev/null @@ -1,567 +0,0 @@ -#include <pdx/client.h> - -#include <gmock/gmock.h> -#include <sys/eventfd.h> - -#include <pdx/mock_client_channel.h> -#include <pdx/mock_client_channel_factory.h> -#include <pdx/rpc/remote_method.h> - -using android::pdx::BorrowedChannelHandle; -using android::pdx::BorrowedHandle; -using android::pdx::ClientBase; -using android::pdx::ClientChannel; -using android::pdx::ClientChannelFactory; -using android::pdx::ErrorStatus; -using android::pdx::LocalChannelHandle; -using android::pdx::LocalHandle; -using android::pdx::MockClientChannel; -using android::pdx::MockClientChannelFactory; -using android::pdx::RemoteChannelHandle; -using android::pdx::RemoteHandle; -using android::pdx::Status; -using android::pdx::Transaction; -using android::pdx::rpc::Void; - -using testing::A; -using testing::AnyNumber; -using testing::ByMove; -using testing::Invoke; -using testing::Ne; -using testing::Return; -using testing::_; - -namespace { - -inline void* IntToPtr(intptr_t addr) { return reinterpret_cast<void*>(addr); } -inline const void* IntToConstPtr(intptr_t addr) { - return reinterpret_cast<const void*>(addr); -} - -struct TestInterface final { - // Op codes. - enum { - kOpAdd = 0, - kOpSendFile, - kOpGetFile, - kOpPushChannel, - }; - - // Methods. - PDX_REMOTE_METHOD(Add, kOpAdd, int(int, int)); - PDX_REMOTE_METHOD(SendFile, kOpSendFile, void(const LocalHandle& fd)); - PDX_REMOTE_METHOD(GetFile, kOpGetFile, LocalHandle(const std::string&, int)); - PDX_REMOTE_METHOD(PushChannel, kOpPushChannel, LocalChannelHandle(Void)); - - PDX_REMOTE_API(API, Add, SendFile, GetFile, PushChannel); -}; - -class SimpleClient : public ClientBase<SimpleClient> { - public: - explicit SimpleClient(std::unique_ptr<ClientChannel> channel) - : BASE{std::move(channel)} {} - SimpleClient(std::unique_ptr<ClientChannelFactory> channel_factory, - int64_t timeout_ms) - : BASE{std::move(channel_factory), timeout_ms} { - EnableAutoReconnect(timeout_ms); - } - - using BASE::SendImpulse; - using BASE::InvokeRemoteMethod; - using BASE::InvokeRemoteMethodInPlace; - using BASE::Close; - using BASE::IsConnected; - using BASE::EnableAutoReconnect; - using BASE::DisableAutoReconnect; - using BASE::event_fd; - using BASE::GetChannel; - - MOCK_METHOD0(OnConnect, void()); -}; - -class FailingClient : public ClientBase<FailingClient> { - public: - explicit FailingClient(std::unique_ptr<ClientChannel> channel, int error_code) - : BASE{std::move(channel)} { - Close(error_code); - } -}; - -class ClientChannelTest : public testing::Test { - public: - ClientChannelTest() - : client_{SimpleClient::Create( - std::make_unique<testing::StrictMock<MockClientChannel>>())} {} - - MockClientChannel* mock_channel() { - return static_cast<MockClientChannel*>(client_->GetChannel()); - } - - std::unique_ptr<SimpleClient> client_; -}; - -class ClientChannelFactoryTest : public testing::Test { - public: - ClientChannelFactoryTest() { - auto factory = - std::make_unique<testing::NiceMock<MockClientChannelFactory>>(); - ON_CALL(*factory, Connect(kTimeout)) - .WillByDefault(Invoke(this, &ClientChannelFactoryTest::OnConnect)); - client_ = SimpleClient::Create(std::move(factory), kTimeout); - } - - MockClientChannel* mock_channel() { - return static_cast<MockClientChannel*>(client_->GetChannel()); - } - - Status<std::unique_ptr<ClientChannel>> OnConnect(int64_t /*timeout_ms*/) { - if (on_connect_error_) - return ErrorStatus(on_connect_error_); - std::unique_ptr<MockClientChannel> channel = - std::make_unique<testing::StrictMock<MockClientChannel>>(); - if (on_connect_callback_) - on_connect_callback_(channel.get()); - return Status<std::unique_ptr<ClientChannel>>{std::move(channel)}; - } - - void OnConnectCallback(std::function<void(MockClientChannel*)> callback) { - on_connect_callback_ = callback; - } - void SetOnConnectError(int error) { on_connect_error_ = error; } - void ResetOnConnectError() { on_connect_error_ = 0; } - - constexpr static int64_t kTimeout = 123; - std::unique_ptr<SimpleClient> client_; - std::function<void(MockClientChannel*)> on_connect_callback_; - int on_connect_error_{0}; -}; - -constexpr int64_t ClientChannelFactoryTest::kTimeout; - -class ClientTransactionTest : public ClientChannelTest { - public: - ClientTransactionTest() : transaction_{*client_} {} - - Transaction transaction_; -}; - -} // anonymous namespace - -TEST_F(ClientChannelTest, IsInitialized) { - ASSERT_NE(client_.get(), nullptr); - EXPECT_TRUE(client_->IsInitialized()); - EXPECT_TRUE(client_->IsConnected()); -} - -TEST_F(ClientChannelTest, CloseOnConstruction) { - FailingClient failed_client1{std::make_unique<MockClientChannel>(), EACCES}; - ASSERT_FALSE(failed_client1.IsInitialized()); - EXPECT_EQ(-EACCES, failed_client1.error()); - - FailingClient failed_client2{std::make_unique<MockClientChannel>(), -EACCES}; - ASSERT_FALSE(failed_client2.IsInitialized()); - EXPECT_EQ(-EACCES, failed_client2.error()); - - auto failed_client3 = - FailingClient::Create(std::make_unique<MockClientChannel>(), EIO); - ASSERT_EQ(failed_client3.get(), nullptr); -} - -TEST_F(ClientChannelTest, IsConnected) { - EXPECT_TRUE(client_->IsConnected()); - EXPECT_EQ(0, client_->error()); - client_->Close(-EINVAL); - EXPECT_FALSE(client_->IsConnected()); - EXPECT_EQ(-EINVAL, client_->error()); -} - -TEST_F(ClientChannelTest, event_fd) { - EXPECT_CALL(*mock_channel(), event_fd()).WillOnce(Return(12)); - EXPECT_EQ(12, client_->event_fd()); -} - -TEST_F(ClientChannelTest, SendImpulse) { - EXPECT_CALL(*mock_channel(), SendImpulse(123, nullptr, 0)) - .WillOnce(Return(Status<void>{})); - EXPECT_TRUE(client_->SendImpulse(123)); - - EXPECT_CALL(*mock_channel(), SendImpulse(17, nullptr, 0)) - .WillOnce(Return(ErrorStatus{EIO})); - auto status = client_->SendImpulse(17); - ASSERT_FALSE(status); - EXPECT_EQ(EIO, status.error()); - - const void* const kTestPtr = IntToConstPtr(1234); - EXPECT_CALL(*mock_channel(), SendImpulse(1, kTestPtr, 17)) - .WillOnce(Return(Status<void>{})); - EXPECT_TRUE(client_->SendImpulse(1, kTestPtr, 17)); -} - -TEST_F(ClientChannelTest, InvokeRemoteMethodNullTransactionState) { - EXPECT_CALL(*mock_channel(), AllocateTransactionState()) - .WillOnce(Return(nullptr)); - EXPECT_CALL(*mock_channel(), - SendWithInt(nullptr, TestInterface::kOpAdd, _, _, nullptr, 0)) - .WillOnce(Return(9)); - EXPECT_CALL(*mock_channel(), FreeTransactionState(nullptr)); - EXPECT_TRUE(client_->InvokeRemoteMethod<TestInterface::Add>(4, 5)); -} - -TEST_F(ClientChannelTest, InvokeRemoteMethodAddSuccess) { - void* const kTransactionState = IntToPtr(123); - EXPECT_CALL(*mock_channel(), AllocateTransactionState()) - .WillOnce(Return(kTransactionState)); - EXPECT_CALL( - *mock_channel(), - SendWithInt(kTransactionState, TestInterface::kOpAdd, _, _, nullptr, 0)) - .WillOnce(Return(3)); - EXPECT_CALL(*mock_channel(), FreeTransactionState(kTransactionState)); - Status<int> status = client_->InvokeRemoteMethod<TestInterface::Add>(1, 2); - ASSERT_TRUE(status); - EXPECT_EQ(3, status.get()); -} - -TEST_F(ClientChannelTest, InvokeRemoteMethodAddFailure) { - void* const kTransactionState = IntToPtr(123); - EXPECT_CALL(*mock_channel(), AllocateTransactionState()) - .WillOnce(Return(kTransactionState)); - EXPECT_CALL( - *mock_channel(), - SendWithInt(kTransactionState, TestInterface::kOpAdd, _, _, nullptr, 0)) - .WillOnce(Return(ErrorStatus{EIO})); - EXPECT_CALL(*mock_channel(), FreeTransactionState(kTransactionState)); - Status<int> status = client_->InvokeRemoteMethod<TestInterface::Add>(1, 2); - ASSERT_FALSE(status); - EXPECT_EQ(EIO, status.error()); -} - -TEST_F(ClientChannelTest, InvokeRemoteMethodGetFileSuccess) { - void* const kTransactionState = IntToPtr(123); - int fd = eventfd(0, 0); - EXPECT_CALL(*mock_channel(), AllocateTransactionState()) - .WillOnce(Return(kTransactionState)); - EXPECT_CALL(*mock_channel(), - SendWithFileHandle(kTransactionState, TestInterface::kOpGetFile, - _, _, nullptr, 0)) - .WillOnce(Return(ByMove(LocalHandle{fd}))); - EXPECT_CALL(*mock_channel(), FreeTransactionState(kTransactionState)); - Status<LocalHandle> status = - client_->InvokeRemoteMethod<TestInterface::GetFile>(); - ASSERT_TRUE(status); - EXPECT_EQ(fd, status.get().Get()); -} - -TEST_F(ClientChannelTest, InvokeRemoteMethodGetFileFailure) { - void* const kTransactionState = IntToPtr(123); - EXPECT_CALL(*mock_channel(), AllocateTransactionState()) - .WillOnce(Return(kTransactionState)); - EXPECT_CALL(*mock_channel(), - SendWithFileHandle(kTransactionState, TestInterface::kOpGetFile, - _, _, nullptr, 0)) - .WillOnce(Return(ByMove(ErrorStatus{EACCES}))); - EXPECT_CALL(*mock_channel(), FreeTransactionState(kTransactionState)); - Status<LocalHandle> status = - client_->InvokeRemoteMethod<TestInterface::GetFile>("file", 0); - ASSERT_FALSE(status); - EXPECT_EQ(EACCES, status.error()); -} - -TEST_F(ClientChannelTest, InvokeRemoteMethodPushChannelSuccess) { - void* const kTransactionState = IntToPtr(123); - const int32_t kHandleValue = 17; - EXPECT_CALL(*mock_channel(), AllocateTransactionState()) - .WillOnce(Return(kTransactionState)); - EXPECT_CALL( - *mock_channel(), - SendWithChannelHandle(kTransactionState, TestInterface::kOpPushChannel, _, - _, nullptr, 0)) - .WillOnce(Return(ByMove(LocalChannelHandle{nullptr, kHandleValue}))); - EXPECT_CALL(*mock_channel(), FreeTransactionState(kTransactionState)); - Status<LocalChannelHandle> status = - client_->InvokeRemoteMethod<TestInterface::PushChannel>(); - ASSERT_TRUE(status); - EXPECT_EQ(kHandleValue, status.get().value()); -} - -TEST_F(ClientChannelTest, InvokeRemoteMethodPushChannelFailure) { - void* const kTransactionState = IntToPtr(123); - EXPECT_CALL(*mock_channel(), AllocateTransactionState()) - .WillOnce(Return(kTransactionState)); - EXPECT_CALL( - *mock_channel(), - SendWithChannelHandle(kTransactionState, TestInterface::kOpPushChannel, _, - _, nullptr, 0)) - .WillOnce(Return(ByMove(ErrorStatus{EACCES}))); - EXPECT_CALL(*mock_channel(), FreeTransactionState(kTransactionState)); - Status<LocalChannelHandle> status = - client_->InvokeRemoteMethod<TestInterface::PushChannel>(); - ASSERT_FALSE(status); - EXPECT_EQ(EACCES, status.error()); -} - -TEST_F(ClientChannelTest, InvokeRemoteMethodSendFileSuccess) { - void* const kTransactionState = IntToPtr(123); - LocalHandle fd{eventfd(0, 0)}; - EXPECT_CALL(*mock_channel(), AllocateTransactionState()) - .WillOnce(Return(kTransactionState)); - EXPECT_CALL(*mock_channel(), - PushFileHandle(kTransactionState, A<const LocalHandle&>())) - .WillOnce(Return(1)); - EXPECT_CALL(*mock_channel(), - SendWithInt(kTransactionState, TestInterface::kOpSendFile, _, _, - nullptr, 0)) - .WillOnce(Return(0)); - EXPECT_CALL(*mock_channel(), FreeTransactionState(kTransactionState)); - EXPECT_TRUE(client_->InvokeRemoteMethod<TestInterface::SendFile>(fd)); -} - -TEST_F(ClientChannelTest, InvokeRemoteMethodSendFileFailure) { - void* const kTransactionState = IntToPtr(123); - LocalHandle fd{eventfd(0, 0)}; - EXPECT_CALL(*mock_channel(), AllocateTransactionState()) - .WillOnce(Return(kTransactionState)); - EXPECT_CALL(*mock_channel(), - PushFileHandle(kTransactionState, A<const LocalHandle&>())) - .WillOnce(Return(1)); - EXPECT_CALL(*mock_channel(), - SendWithInt(kTransactionState, TestInterface::kOpSendFile, _, _, - nullptr, 0)) - .WillOnce(Return(ErrorStatus{EACCES})); - EXPECT_CALL(*mock_channel(), FreeTransactionState(kTransactionState)); - EXPECT_FALSE(client_->InvokeRemoteMethod<TestInterface::SendFile>(fd)); -} - -TEST_F(ClientChannelFactoryTest, IsInitialized) { - ASSERT_NE(client_.get(), nullptr); - EXPECT_TRUE(client_->IsInitialized()); - EXPECT_TRUE(client_->IsConnected()); -} - -TEST_F(ClientChannelFactoryTest, NotConnectedButInitialized) { - auto factory = - std::make_unique<testing::NiceMock<MockClientChannelFactory>>(); - EXPECT_CALL(*factory, Connect(kTimeout)) - .WillOnce(Return(ByMove(ErrorStatus(ESHUTDOWN)))) - .WillOnce(Invoke(this, &ClientChannelFactoryTest::OnConnect)); - client_ = SimpleClient::Create(std::move(factory), kTimeout); - ASSERT_NE(client_.get(), nullptr); - EXPECT_TRUE(client_->IsInitialized()); - EXPECT_FALSE(client_->IsConnected()); - client_->DisableAutoReconnect(); - ASSERT_FALSE(client_->SendImpulse(17)); - EXPECT_FALSE(client_->IsConnected()); - client_->EnableAutoReconnect(kTimeout); - EXPECT_CALL(*client_, OnConnect()); - OnConnectCallback([](auto* mock) { - EXPECT_CALL(*mock, SendImpulse(17, nullptr, 0)) - .WillOnce(Return(Status<void>{})); - }); - ASSERT_TRUE(client_->SendImpulse(17)); - EXPECT_TRUE(client_->IsConnected()); -} - -TEST_F(ClientChannelFactoryTest, CheckDisconnect) { - EXPECT_CALL(*mock_channel(), SendImpulse(17, nullptr, 0)) - .WillOnce(Return(ErrorStatus{ESHUTDOWN})); - ASSERT_FALSE(client_->SendImpulse(17)); - EXPECT_FALSE(client_->IsConnected()); - EXPECT_EQ(-ESHUTDOWN, client_->error()); -} - -TEST_F(ClientChannelFactoryTest, CheckReconnect) { - client_->Close(ESHUTDOWN); - ASSERT_FALSE(client_->IsConnected()); - - EXPECT_CALL(*client_, OnConnect()); - OnConnectCallback([](auto* mock) { - EXPECT_CALL(*mock, SendImpulse(17, nullptr, 0)) - .WillOnce(Return(Status<void>{})); - }); - ASSERT_TRUE(client_->SendImpulse(17)); - EXPECT_TRUE(client_->IsConnected()); -} - -TEST_F(ClientChannelFactoryTest, CloseOnConnect) { - client_->Close(ESHUTDOWN); - - EXPECT_CALL(*client_, OnConnect()).WillOnce(Invoke([this] { - client_->Close(EIO); - })); - auto status = client_->SendImpulse(17); - ASSERT_FALSE(status); - EXPECT_EQ(EIO, status.error()); - EXPECT_FALSE(client_->IsConnected()); - EXPECT_EQ(-EIO, client_->error()); -} - -TEST_F(ClientChannelFactoryTest, DisableAutoReconnect) { - client_->Close(EIO); - ASSERT_FALSE(client_->IsConnected()); - client_->DisableAutoReconnect(); - auto status = client_->SendImpulse(17); - ASSERT_FALSE(status); - EXPECT_EQ(ESHUTDOWN, status.error()); - EXPECT_FALSE(client_->IsConnected()); - client_->EnableAutoReconnect(kTimeout); - EXPECT_CALL(*client_, OnConnect()); - OnConnectCallback([](auto* mock) { - EXPECT_CALL(*mock, SendImpulse(17, nullptr, 0)) - .WillOnce(Return(Status<void>{})); - }); - ASSERT_TRUE(client_->SendImpulse(17)); - EXPECT_TRUE(client_->IsConnected()); -} - -TEST_F(ClientTransactionTest, SendNoData) { - void* const kTransactionState = IntToPtr(123); - EXPECT_CALL(*mock_channel(), AllocateTransactionState()) - .WillOnce(Return(kTransactionState)); - EXPECT_CALL(*mock_channel(), FreeTransactionState(kTransactionState)); - EXPECT_CALL(*mock_channel(), - SendWithInt(kTransactionState, 1, nullptr, 0, nullptr, 0)) - .WillOnce(Return(0)); - EXPECT_TRUE(transaction_.Send<void>(1)); - EXPECT_CALL(*mock_channel(), - SendWithFileHandle(kTransactionState, 2, nullptr, 0, nullptr, 0)) - .WillOnce(Return(ByMove(LocalHandle{-1}))); - EXPECT_TRUE(transaction_.Send<LocalHandle>(2)); - EXPECT_CALL(*mock_channel(), SendWithChannelHandle(kTransactionState, 3, - nullptr, 0, nullptr, 0)) - .WillOnce(Return(ByMove(LocalChannelHandle{nullptr, 1}))); - EXPECT_TRUE(transaction_.Send<LocalChannelHandle>(3)); -} - -TEST_F(ClientTransactionTest, SendNoState) { - EXPECT_CALL(*mock_channel(), AllocateTransactionState()) - .WillOnce(Return(nullptr)); - EXPECT_CALL(*mock_channel(), SendWithInt(nullptr, 1, nullptr, 0, nullptr, 0)) - .WillOnce(Return(0)); - EXPECT_CALL(*mock_channel(), FreeTransactionState(nullptr)); - EXPECT_TRUE(transaction_.Send<void>(1)); -} - -TEST_F(ClientTransactionTest, SendBuffers) { - const void* const kSendBuffer = IntToConstPtr(123); - const size_t kSendSize = 12; - void* const kReceiveBuffer = IntToPtr(456); - const size_t kReceiveSize = 34; - - EXPECT_CALL(*mock_channel(), AllocateTransactionState()) - .WillOnce(Return(nullptr)); - EXPECT_CALL(*mock_channel(), FreeTransactionState(nullptr)); - - EXPECT_CALL(*mock_channel(), SendWithInt(nullptr, 1, nullptr, 0, nullptr, 0)) - .WillOnce(Return(0)); - EXPECT_TRUE(transaction_.Send<void>(1, nullptr, 0, nullptr, 0)); - - EXPECT_CALL(*mock_channel(), - SendWithInt(nullptr, 2, Ne(nullptr), 1, nullptr, 0)) - .WillOnce(Return(0)); - EXPECT_TRUE(transaction_.Send<void>(2, kSendBuffer, kSendSize, nullptr, 0)); - - EXPECT_CALL(*mock_channel(), SendWithInt(nullptr, 3, nullptr, 0, nullptr, 0)) - .WillOnce(Return(0)); - EXPECT_TRUE(transaction_.Send<void>(3, kSendBuffer, 0, nullptr, 0)); - - EXPECT_CALL(*mock_channel(), - SendWithInt(nullptr, 4, nullptr, 0, Ne(nullptr), 1)) - .WillOnce(Return(0)); - EXPECT_TRUE( - transaction_.Send<void>(4, nullptr, 0, kReceiveBuffer, kReceiveSize)); - - EXPECT_CALL(*mock_channel(), SendWithInt(nullptr, 5, nullptr, 0, nullptr, 0)) - .WillOnce(Return(0)); - EXPECT_TRUE(transaction_.Send<void>(5, nullptr, 0, kReceiveBuffer, 0)); - - EXPECT_CALL(*mock_channel(), - SendWithInt(nullptr, 5, Ne(nullptr), 1, Ne(nullptr), 1)) - .WillOnce(Return(0)); - EXPECT_TRUE(transaction_.Send<void>(5, kSendBuffer, kSendSize, kReceiveBuffer, - kReceiveSize)); -} - -TEST_F(ClientTransactionTest, SendVector) { - iovec send[3] = {}; - iovec recv[4] = {}; - - EXPECT_CALL(*mock_channel(), AllocateTransactionState()) - .WillOnce(Return(nullptr)); - EXPECT_CALL(*mock_channel(), FreeTransactionState(nullptr)); - - EXPECT_CALL(*mock_channel(), SendWithInt(nullptr, 1, nullptr, 0, nullptr, 0)) - .WillOnce(Return(0)); - EXPECT_TRUE(transaction_.SendVector<void>(1, nullptr, 0, nullptr, 0)); - - EXPECT_CALL(*mock_channel(), SendWithInt(nullptr, 2, send, 3, recv, 4)) - .WillOnce(Return(0)); - EXPECT_TRUE(transaction_.SendVector<void>(2, send, 3, recv, 4)); - - EXPECT_CALL(*mock_channel(), SendWithInt(nullptr, 3, send, 3, nullptr, 0)) - .WillOnce(Return(0)); - EXPECT_TRUE(transaction_.SendVector<void>(3, send, nullptr)); - - EXPECT_CALL(*mock_channel(), SendWithInt(nullptr, 4, nullptr, 0, recv, 4)) - .WillOnce(Return(0)); - EXPECT_TRUE(transaction_.SendVector<void>(4, nullptr, recv)); - - EXPECT_CALL(*mock_channel(), SendWithInt(nullptr, 5, send, 3, recv, 4)) - .WillOnce(Return(0)); - EXPECT_TRUE(transaction_.SendVector<void>(5, send, recv)); -} - -TEST_F(ClientTransactionTest, PushHandle) { - void* const kTransactionState = IntToPtr(123); - EXPECT_CALL(*mock_channel(), AllocateTransactionState()) - .WillOnce(Return(kTransactionState)); - EXPECT_CALL(*mock_channel(), FreeTransactionState(kTransactionState)); - - EXPECT_CALL(*mock_channel(), - PushFileHandle(kTransactionState, A<const LocalHandle&>())) - .WillOnce(Return(1)); - EXPECT_EQ(1, transaction_.PushFileHandle(LocalHandle{-1}).get()); - - EXPECT_CALL(*mock_channel(), - PushFileHandle(kTransactionState, A<const BorrowedHandle&>())) - .WillOnce(Return(2)); - EXPECT_EQ(2, transaction_.PushFileHandle(BorrowedHandle{-1}).get()); - - EXPECT_EQ(3, transaction_.PushFileHandle(RemoteHandle{3}).get()); - - EXPECT_CALL( - *mock_channel(), - PushChannelHandle(kTransactionState, A<const LocalChannelHandle&>())) - .WillOnce(Return(11)); - EXPECT_EQ( - 11, transaction_.PushChannelHandle(LocalChannelHandle{nullptr, 1}).get()); - - EXPECT_CALL( - *mock_channel(), - PushChannelHandle(kTransactionState, A<const BorrowedChannelHandle&>())) - .WillOnce(Return(12)); - EXPECT_EQ(12, transaction_.PushChannelHandle(BorrowedChannelHandle{2}).get()); - - EXPECT_EQ(13, transaction_.PushChannelHandle(RemoteChannelHandle{13}).get()); -} - -TEST_F(ClientTransactionTest, GetHandle) { - void* const kTransactionState = IntToPtr(123); - EXPECT_CALL(*mock_channel(), AllocateTransactionState()) - .WillOnce(Return(kTransactionState)); - EXPECT_CALL(*mock_channel(), FreeTransactionState(kTransactionState)); - - EXPECT_CALL(*mock_channel(), GetFileHandle(kTransactionState, 1, _)) - .WillOnce(Return(false)) - .WillOnce(Return(true)); - - LocalHandle file_handle; - EXPECT_FALSE(transaction_.GetFileHandle(1, &file_handle)); - EXPECT_TRUE(transaction_.GetFileHandle(1, &file_handle)); - - EXPECT_CALL(*mock_channel(), GetChannelHandle(kTransactionState, 2, _)) - .WillOnce(Return(false)) - .WillOnce(Return(true)); - - LocalChannelHandle channel_handle; - EXPECT_FALSE(transaction_.GetChannelHandle(2, &channel_handle)); - EXPECT_TRUE(transaction_.GetChannelHandle(2, &channel_handle)); -} diff --git a/libs/vr/libpdx/encoder_performance_test.cpp b/libs/vr/libpdx/encoder_performance_test.cpp deleted file mode 100644 index 7b477c4ce2..0000000000 --- a/libs/vr/libpdx/encoder_performance_test.cpp +++ /dev/null @@ -1,515 +0,0 @@ -#include <errno.h> -#include <fcntl.h> -#include <time.h> -#include <unistd.h> - -#include <chrono> -#include <iomanip> -#include <iostream> -#include <vector> - -#include <pdx/rpc/argument_encoder.h> -#include <pdx/rpc/message_buffer.h> -#include <pdx/rpc/payload.h> -#include <pdx/utility.h> - -using namespace android::pdx::rpc; -using namespace android::pdx; -using std::placeholders::_1; -using std::placeholders::_2; -using std::placeholders::_3; -using std::placeholders::_4; -using std::placeholders::_5; -using std::placeholders::_6; - -namespace { - -constexpr size_t kMaxStaticBufferSize = 20480; - -// Provide numpunct facet that formats numbers with ',' as thousands separators. -class CommaNumPunct : public std::numpunct<char> { - protected: - char do_thousands_sep() const override { return ','; } - std::string do_grouping() const override { return "\03"; } -}; - -class TestPayload : public MessagePayload<SendBuffer>, - public MessageWriter, - public MessageReader, - public NoOpResourceMapper { - public: - // MessageWriter - void* GetNextWriteBufferSection(size_t size) override { - const size_t section_offset = Size(); - Extend(size); - return Data() + section_offset; - } - - OutputResourceMapper* GetOutputResourceMapper() override { return this; } - - // MessageReader - BufferSection GetNextReadBufferSection() override { - return {&*ConstCursor(), &*ConstEnd()}; - } - - void ConsumeReadBufferSectionData(const void* new_start) override { - std::advance(ConstCursor(), PointerDistance(new_start, &*ConstCursor())); - } - - InputResourceMapper* GetInputResourceMapper() override { return this; } -}; - -class StaticBuffer : public MessageWriter, - public MessageReader, - public NoOpResourceMapper { - public: - void Clear() { - read_ptr_ = buffer_; - write_ptr_ = 0; - } - void Rewind() { read_ptr_ = buffer_; } - - // MessageWriter - void* GetNextWriteBufferSection(size_t size) override { - void* ptr = buffer_ + write_ptr_; - write_ptr_ += size; - return ptr; - } - - OutputResourceMapper* GetOutputResourceMapper() override { return this; } - - // MessageReader - BufferSection GetNextReadBufferSection() override { - return {read_ptr_, std::end(buffer_)}; - } - - void ConsumeReadBufferSectionData(const void* new_start) override { - read_ptr_ = static_cast<const uint8_t*>(new_start); - } - - InputResourceMapper* GetInputResourceMapper() override { return this; } - - private: - uint8_t buffer_[kMaxStaticBufferSize]; - const uint8_t* read_ptr_{buffer_}; - size_t write_ptr_{0}; -}; - -// Simple callback function to clear/reset the input/output buffers for -// serialization. Using raw function pointer here instead of std::function to -// minimize the overhead of invocation in the tight test loop over millions of -// iterations. -using ResetFunc = void(void*); - -// Serialization test function signature, used by the TestRunner. -using SerializeTestSignature = std::chrono::nanoseconds(MessageWriter* writer, - size_t iterations, - ResetFunc* write_reset, - void* reset_data); - -// Deserialization test function signature, used by the TestRunner. -using DeserializeTestSignature = std::chrono::nanoseconds( - MessageReader* reader, MessageWriter* writer, size_t iterations, - ResetFunc* read_reset, ResetFunc* write_reset, void* reset_data); - -// Generic serialization test runner method. Takes the |value| of type T and -// serializes it into the output buffer represented by |writer|. -template <typename T> -std::chrono::nanoseconds SerializeTestRunner(MessageWriter* writer, - size_t iterations, - ResetFunc* write_reset, - void* reset_data, const T& value) { - auto start = std::chrono::high_resolution_clock::now(); - for (size_t i = 0; i < iterations; i++) { - write_reset(reset_data); - Serialize(value, writer); - } - auto stop = std::chrono::high_resolution_clock::now(); - return stop - start; -} - -// Generic deserialization test runner method. Takes the |value| of type T and -// temporarily serializes it into the output buffer, then repeatedly -// deserializes the data back from that buffer. -template <typename T> -std::chrono::nanoseconds DeserializeTestRunner( - MessageReader* reader, MessageWriter* writer, size_t iterations, - ResetFunc* read_reset, ResetFunc* write_reset, void* reset_data, - const T& value) { - write_reset(reset_data); - Serialize(value, writer); - T output_data; - auto start = std::chrono::high_resolution_clock::now(); - for (size_t i = 0; i < iterations; i++) { - read_reset(reset_data); - Deserialize(&output_data, reader); - } - auto stop = std::chrono::high_resolution_clock::now(); - if (output_data != value) - return start - stop; // Return negative value to indicate error. - return stop - start; -} - -// Special version of SerializeTestRunner that doesn't perform any serialization -// but does all the same setup steps and moves data of size |data_size| into -// the output buffer. Useful to determine the baseline to calculate time used -// just for serialization layer. -std::chrono::nanoseconds SerializeBaseTest(MessageWriter* writer, - size_t iterations, - ResetFunc* write_reset, - void* reset_data, size_t data_size) { - std::vector<uint8_t> fake_data(data_size); - auto start = std::chrono::high_resolution_clock::now(); - for (size_t i = 0; i < iterations; i++) { - write_reset(reset_data); - memcpy(writer->GetNextWriteBufferSection(fake_data.size()), - fake_data.data(), fake_data.size()); - } - auto stop = std::chrono::high_resolution_clock::now(); - return stop - start; -} - -// Special version of DeserializeTestRunner that doesn't perform any -// deserialization but invokes Rewind on the input buffer repeatedly. -// Useful to determine the baseline to calculate time used just for -// deserialization layer. -std::chrono::nanoseconds DeserializeBaseTest( - MessageReader* reader, MessageWriter* writer, size_t iterations, - ResetFunc* read_reset, ResetFunc* write_reset, void* reset_data, - size_t data_size) { - std::vector<uint8_t> fake_data(data_size); - write_reset(reset_data); - memcpy(writer->GetNextWriteBufferSection(fake_data.size()), fake_data.data(), - fake_data.size()); - auto start = std::chrono::high_resolution_clock::now(); - for (size_t i = 0; i < iterations; i++) { - read_reset(reset_data); - auto section = reader->GetNextReadBufferSection(); - memcpy(fake_data.data(), section.first, fake_data.size()); - reader->ConsumeReadBufferSectionData( - AdvancePointer(section.first, fake_data.size())); - } - auto stop = std::chrono::high_resolution_clock::now(); - return stop - start; -} - -// The main class that accumulates individual tests to be executed. -class TestRunner { - public: - struct BufferInfo { - BufferInfo(const std::string& buffer_name, MessageReader* reader, - MessageWriter* writer, ResetFunc* read_reset_func, - ResetFunc* write_reset_func, void* reset_data) - : name{buffer_name}, - reader{reader}, - writer{writer}, - read_reset_func{read_reset_func}, - write_reset_func{write_reset_func}, - reset_data{reset_data} {} - std::string name; - MessageReader* reader; - MessageWriter* writer; - ResetFunc* read_reset_func; - ResetFunc* write_reset_func; - void* reset_data; - }; - - void AddTestFunc(const std::string& name, - std::function<SerializeTestSignature> serialize_test, - std::function<DeserializeTestSignature> deserialize_test, - size_t data_size) { - tests_.emplace_back(name, std::move(serialize_test), - std::move(deserialize_test), data_size); - } - - template <typename T> - void AddSerializationTest(const std::string& name, T&& value) { - const size_t data_size = GetSerializedSize(value); - auto serialize_test = - std::bind(static_cast<std::chrono::nanoseconds (*)( - MessageWriter*, size_t, ResetFunc*, void*, const T&)>( - &SerializeTestRunner), - _1, _2, _3, _4, std::forward<T>(value)); - tests_.emplace_back(name, std::move(serialize_test), - std::function<DeserializeTestSignature>{}, data_size); - } - - template <typename T> - void AddDeserializationTest(const std::string& name, T&& value) { - const size_t data_size = GetSerializedSize(value); - auto deserialize_test = - std::bind(static_cast<std::chrono::nanoseconds (*)( - MessageReader*, MessageWriter*, size_t, ResetFunc*, - ResetFunc*, void*, const T&)>(&DeserializeTestRunner), - _1, _2, _3, _4, _5, _6, std::forward<T>(value)); - tests_.emplace_back(name, std::function<SerializeTestSignature>{}, - std::move(deserialize_test), data_size); - } - - template <typename T> - void AddTest(const std::string& name, T&& value) { - const size_t data_size = GetSerializedSize(value); - if (data_size > kMaxStaticBufferSize) { - std::cerr << "Test '" << name << "' requires " << data_size - << " bytes in the serialization buffer but only " - << kMaxStaticBufferSize << " are available." << std::endl; - exit(1); - } - auto serialize_test = - std::bind(static_cast<std::chrono::nanoseconds (*)( - MessageWriter*, size_t, ResetFunc*, void*, const T&)>( - &SerializeTestRunner), - _1, _2, _3, _4, value); - auto deserialize_test = - std::bind(static_cast<std::chrono::nanoseconds (*)( - MessageReader*, MessageWriter*, size_t, ResetFunc*, - ResetFunc*, void*, const T&)>(&DeserializeTestRunner), - _1, _2, _3, _4, _5, _6, std::forward<T>(value)); - tests_.emplace_back(name, std::move(serialize_test), - std::move(deserialize_test), data_size); - } - - std::string CenterString(std::string text, size_t column_width) { - if (text.size() < column_width) { - text = std::string((column_width - text.size()) / 2, ' ') + text; - } - return text; - } - - void RunTests(size_t iteration_count, - const std::vector<BufferInfo>& buffers) { - using float_seconds = std::chrono::duration<double>; - const std::string name_column_separator = " : "; - const std::string buffer_column_separator = " || "; - const std::string buffer_timing_column_separator = " | "; - const size_t data_size_column_width = 6; - const size_t time_column_width = 9; - const size_t qps_column_width = 18; - const size_t buffer_column_width = time_column_width + - buffer_timing_column_separator.size() + - qps_column_width; - - auto compare_name_length = [](const TestEntry& t1, const TestEntry& t2) { - return t1.name.size() < t2.name.size(); - }; - auto test_with_longest_name = - std::max_element(tests_.begin(), tests_.end(), compare_name_length); - size_t name_column_width = test_with_longest_name->name.size(); - - size_t total_width = - name_column_width + name_column_separator.size() + - data_size_column_width + buffer_column_separator.size() + - buffers.size() * (buffer_column_width + buffer_column_separator.size()); - - const std::string dbl_separator(total_width, '='); - const std::string separator(total_width, '-'); - - auto print_header = [&](const std::string& header) { - std::cout << dbl_separator << std::endl; - std::stringstream ss; - ss.imbue(std::locale(ss.getloc(), new CommaNumPunct)); - ss << header << " (" << iteration_count << " iterations)"; - std::cout << CenterString(ss.str(), total_width) << std::endl; - std::cout << dbl_separator << std::endl; - std::cout << std::setw(name_column_width) << "Test Name" << std::left - << name_column_separator << std::setw(data_size_column_width) - << CenterString("Size", data_size_column_width) - << buffer_column_separator; - for (const auto& buffer_info : buffers) { - std::cout << std::setw(buffer_column_width) - << CenterString(buffer_info.name, buffer_column_width) - << buffer_column_separator; - } - std::cout << std::endl; - std::cout << std::setw(name_column_width) << "" << name_column_separator - << std::setw(data_size_column_width) - << CenterString("bytes", data_size_column_width) - << buffer_column_separator << std::left; - for (size_t i = 0; i < buffers.size(); i++) { - std::cout << std::setw(time_column_width) - << CenterString("Time, s", time_column_width) - << buffer_timing_column_separator - << std::setw(qps_column_width) - << CenterString("QPS", qps_column_width) - << buffer_column_separator; - } - std::cout << std::right << std::endl; - std::cout << separator << std::endl; - }; - - print_header("Serialization benchmarks"); - for (const auto& test : tests_) { - if (test.serialize_test) { - std::cout << std::setw(name_column_width) << test.name << " : " - << std::setw(data_size_column_width) << test.data_size - << buffer_column_separator; - for (const auto& buffer_info : buffers) { - auto seconds = - std::chrono::duration_cast<float_seconds>(test.serialize_test( - buffer_info.writer, iteration_count, - buffer_info.write_reset_func, buffer_info.reset_data)); - double qps = iteration_count / seconds.count(); - std::cout << std::fixed << std::setprecision(3) - << std::setw(time_column_width) << seconds.count() - << buffer_timing_column_separator - << std::setw(qps_column_width) << qps - << buffer_column_separator; - } - std::cout << std::endl; - } - } - - print_header("Deserialization benchmarks"); - for (const auto& test : tests_) { - if (test.deserialize_test) { - std::cout << std::setw(name_column_width) << test.name << " : " - << std::setw(data_size_column_width) << test.data_size - << buffer_column_separator; - for (const auto& buffer_info : buffers) { - auto seconds = - std::chrono::duration_cast<float_seconds>(test.deserialize_test( - buffer_info.reader, buffer_info.writer, iteration_count, - buffer_info.read_reset_func, buffer_info.write_reset_func, - buffer_info.reset_data)); - double qps = iteration_count / seconds.count(); - std::cout << std::fixed << std::setprecision(3) - << std::setw(time_column_width) << seconds.count() - << buffer_timing_column_separator - << std::setw(qps_column_width) << qps - << buffer_column_separator; - } - std::cout << std::endl; - } - } - std::cout << dbl_separator << std::endl; - } - - private: - struct TestEntry { - TestEntry(const std::string& test_name, - std::function<SerializeTestSignature> serialize_test, - std::function<DeserializeTestSignature> deserialize_test, - size_t data_size) - : name{test_name}, - serialize_test{std::move(serialize_test)}, - deserialize_test{std::move(deserialize_test)}, - data_size{data_size} {} - std::string name; - std::function<SerializeTestSignature> serialize_test; - std::function<DeserializeTestSignature> deserialize_test; - size_t data_size; - }; - - std::vector<TestEntry> tests_; -}; - -std::string GenerateContainerName(const std::string& type, size_t count) { - std::stringstream ss; - ss << type << "(" << count << ")"; - return ss.str(); -} - -} // anonymous namespace - -int main(int /*argc*/, char** /*argv*/) { - const size_t iteration_count = 10000000; // 10M iterations. - TestRunner test_runner; - std::cout.imbue(std::locale(std::cout.getloc(), new CommaNumPunct)); - - // Baseline tests to figure out the overhead of buffer resizing and data - // transfers. - for (size_t len : {0, 1, 9, 66, 259}) { - auto serialize_base_test = - std::bind(&SerializeBaseTest, _1, _2, _3, _4, len); - auto deserialize_base_test = - std::bind(&DeserializeBaseTest, _1, _2, _3, _4, _5, _6, len); - test_runner.AddTestFunc("--Baseline--", std::move(serialize_base_test), - std::move(deserialize_base_test), len); - } - - // Individual serialization/deserialization tests. - test_runner.AddTest("bool", true); - test_runner.AddTest("int32_t", 12); - - for (size_t len : {0, 1, 8, 64, 256}) { - test_runner.AddTest(GenerateContainerName("string", len), - std::string(len, '*')); - } - // Serialization is too slow to handle such large strings, add this test for - // deserialization only. - test_runner.AddDeserializationTest(GenerateContainerName("string", 10240), - std::string(10240, '*')); - - for (size_t len : {0, 1, 8, 64, 256}) { - std::vector<int32_t> int_vector(len); - std::iota(int_vector.begin(), int_vector.end(), 0); - test_runner.AddTest(GenerateContainerName("vector<int32_t>", len), - std::move(int_vector)); - } - - std::vector<std::string> vector_of_strings = { - "012345678901234567890123456789", "012345678901234567890123456789", - "012345678901234567890123456789", "012345678901234567890123456789", - "012345678901234567890123456789", - }; - test_runner.AddTest( - GenerateContainerName("vector<string>", vector_of_strings.size()), - std::move(vector_of_strings)); - - test_runner.AddTest("tuple<int, bool, string, double>", - std::make_tuple(123, true, std::string{"foobar"}, 1.1)); - - for (size_t len : {0, 1, 8, 64}) { - std::map<int, std::string> test_map; - for (size_t i = 0; i < len; i++) - test_map.emplace(i, std::to_string(i)); - test_runner.AddTest(GenerateContainerName("map<int, string>", len), - std::move(test_map)); - } - - for (size_t len : {0, 1, 8, 64}) { - std::unordered_map<int, std::string> test_map; - for (size_t i = 0; i < len; i++) - test_map.emplace(i, std::to_string(i)); - test_runner.AddTest( - GenerateContainerName("unordered_map<int, string>", len), - std::move(test_map)); - } - - // BufferWrapper can't be used with deserialization tests right now because - // it requires external buffer to be filled in, which is not available. - std::vector<std::vector<uint8_t>> data_buffers; - for (size_t len : {0, 1, 8, 64, 256}) { - data_buffers.emplace_back(len); - test_runner.AddSerializationTest( - GenerateContainerName("BufferWrapper<uint8_t*>", len), - BufferWrapper<uint8_t*>(data_buffers.back().data(), - data_buffers.back().size())); - } - - // Various backing buffers to run the tests on. - std::vector<TestRunner::BufferInfo> buffers; - - Payload buffer; - buffers.emplace_back("Non-TLS Buffer", &buffer, &buffer, - [](void* ptr) { static_cast<Payload*>(ptr)->Rewind(); }, - [](void* ptr) { static_cast<Payload*>(ptr)->Clear(); }, - &buffer); - - TestPayload tls_buffer; - buffers.emplace_back( - "TLS Buffer", &tls_buffer, &tls_buffer, - [](void* ptr) { static_cast<TestPayload*>(ptr)->Rewind(); }, - [](void* ptr) { static_cast<TestPayload*>(ptr)->Clear(); }, &tls_buffer); - - StaticBuffer static_buffer; - buffers.emplace_back( - "Static Buffer", &static_buffer, &static_buffer, - [](void* ptr) { static_cast<StaticBuffer*>(ptr)->Rewind(); }, - [](void* ptr) { static_cast<StaticBuffer*>(ptr)->Clear(); }, - &static_buffer); - - // Finally, run all the tests. - test_runner.RunTests(iteration_count, buffers); - return 0; -} diff --git a/libs/vr/libpdx/fuzz/Android.bp b/libs/vr/libpdx/fuzz/Android.bp deleted file mode 100644 index ac831ceda0..0000000000 --- a/libs/vr/libpdx/fuzz/Android.bp +++ /dev/null @@ -1,68 +0,0 @@ -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "frameworks_native_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["frameworks_native_license"], -} - -cc_fuzz { - name: "libpdx_service_dispatcher_fuzzer", - srcs: [ - "service_dispatcher_fuzzer.cpp", - ], - cflags: [ - "-Wall", - "-Wextra", - "-Werror", - ], - static_libs: [ - "libpdx", - ], - shared_libs: [ - "libutils", - "liblog", - "libcutils", - ], -} - -cc_fuzz { - name: "libpdx_message_fuzzer", - srcs: [ - "message_fuzzer.cpp", - ], - cflags: [ - "-Wall", - "-Wextra", - "-Werror", - ], - static_libs: [ - "libpdx", - ], - shared_libs: [ - "libutils", - "liblog", - "libcutils", - ], -} - -cc_fuzz { - name: "libpdx_serialization_fuzzer", - srcs: [ - "serialization_fuzzer.cpp", - ], - cflags: [ - "-Wall", - "-Wextra", - "-Werror", - ], - static_libs: [ - "libpdx", - ], - shared_libs: [ - "libutils", - "liblog", - "libcutils", - ], -} diff --git a/libs/vr/libpdx/fuzz/helpers.h b/libs/vr/libpdx/fuzz/helpers.h deleted file mode 100644 index 83ec4096f6..0000000000 --- a/libs/vr/libpdx/fuzz/helpers.h +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Copyright 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -// Authors: corbin.souffrant@leviathansecurity.com -// brian.balling@leviathansecurity.com - -#ifndef LEV_FUZZERS_LIBPDX_HELPERS_H_ -#define LEV_FUZZERS_LIBPDX_HELPERS_H_ - -#define UNUSED(expr) \ - do { \ - (void)(expr); \ - } while (0) - -#include <fuzzer/FuzzedDataProvider.h> -#include <pdx/client.h> -#include <pdx/service.h> -#include <pdx/service_dispatcher.h> -#include <pdx/service_endpoint.h> -#include <sys/eventfd.h> -#include <memory> -#include <vector> - -using namespace android::pdx; - -// Vector of operations we can call in the dispatcher. -static const std::vector<std::function<void( - const std::unique_ptr<ServiceDispatcher>&, FuzzedDataProvider*)>> - dispatcher_operations = { - [](const std::unique_ptr<ServiceDispatcher>& dispatcher, - FuzzedDataProvider*) -> void { dispatcher->EnterDispatchLoop(); }, - [](const std::unique_ptr<ServiceDispatcher>& dispatcher, - FuzzedDataProvider*) -> void { dispatcher->ReceiveAndDispatch(); }, - [](const std::unique_ptr<ServiceDispatcher>& dispatcher, - FuzzedDataProvider* fdp) -> void { - dispatcher->ReceiveAndDispatch(fdp->ConsumeIntegral<int>()); - }}; - -// Most of the fuzzing occurs within the endpoint, which is derived from an -// abstract class. So we are returning garbage data for most functions besides -// the ones we added or need to actually use. -class FuzzEndpoint : public Endpoint { - public: - explicit FuzzEndpoint(FuzzedDataProvider* fdp) { - _fdp = fdp; - _epoll_fd = eventfd(0, 0); - } - - ~FuzzEndpoint() { close(_epoll_fd); } - - // Returns an fd that can be used with epoll() to wait for incoming messages - // from this endpoint. - int epoll_fd() const { return _epoll_fd; } - - // Associates a Service instance with an endpoint by setting the service - // context pointer to the address of the Service. Only one Service may be - // associated with a given endpoint. - Status<void> SetService(Service* service) { - _service = service; - return Status<void>(0); - } - - // Set the channel context for the given channel. - Status<void> SetChannel(int channel_id, Channel* channel) { - UNUSED(channel_id); - _channel = std::shared_ptr<Channel>(channel); - return Status<void>(0); - } - - // Receives a message on the given endpoint file descriptor. - // This is called by the dispatcher to determine what operations - // to make, so we are fuzzing the response. - Status<void> MessageReceive(Message* message) { - // Create a randomized MessageInfo struct. - MessageInfo info; - eventfd_t wakeup_val = 0; - info.pid = _fdp->ConsumeIntegral<int>(); - info.tid = _fdp->ConsumeIntegral<int>(); - info.cid = _fdp->ConsumeIntegral<int>(); - info.mid = _fdp->ConsumeIntegral<int>(); - info.euid = _fdp->ConsumeIntegral<int>(); - info.egid = _fdp->ConsumeIntegral<int>(); - info.op = _fdp->ConsumeIntegral<int32_t>(); - info.flags = _fdp->ConsumeIntegral<uint32_t>(); - info.service = _service; - info.channel = _channel.get(); - info.send_len = _fdp->ConsumeIntegral<size_t>(); - info.recv_len = _fdp->ConsumeIntegral<size_t>(); - info.fd_count = _fdp->ConsumeIntegral<size_t>(); - if (_fdp->remaining_bytes() >= 32) { - std::vector<uint8_t> impulse_vec = _fdp->ConsumeBytes<uint8_t>(32); - memcpy(info.impulse, impulse_vec.data(), 32); - } - - *message = Message(info); - eventfd_read(_epoll_fd, &wakeup_val); - - return Status<void>(); - } - - // Returns a tag that uniquely identifies a specific underlying IPC - // transport. - uint32_t GetIpcTag() const { return 0; } - - // Close a channel, signaling the client file object and freeing the channel - // id. Once closed, the client side of the channel always returns the error - // ESHUTDOWN and signals the poll/epoll events POLLHUP and POLLFREE. - Status<void> CloseChannel(int channel_id) { - UNUSED(channel_id); - return Status<void>(); - } - - // Update the event bits for the given channel (given by id), using the - // given clear and set masks. - Status<void> ModifyChannelEvents(int channel_id, int clear_mask, - int set_mask) { - UNUSED(channel_id); - UNUSED(clear_mask); - UNUSED(set_mask); - return Status<void>(); - } - - // Create a new channel and push it as a file descriptor to the process - // sending the |message|. |flags| may be set to O_NONBLOCK and/or - // O_CLOEXEC to control the initial behavior of the new file descriptor (the - // sending process may change these later using fcntl()). The internal - // Channel instance associated with this channel is set to |channel|, - // which may be nullptr. The new channel id allocated for this channel is - // returned in |channel_id|, which may also be nullptr if not needed. - Status<RemoteChannelHandle> PushChannel(Message* message, int flags, - Channel* channel, int* channel_id) { - UNUSED(message); - UNUSED(flags); - UNUSED(channel); - UNUSED(channel_id); - return Status<RemoteChannelHandle>(); - } - - // Check whether the |ref| is a reference to a channel to the service - // represented by the |endpoint|. If the channel reference in question is - // valid, the Channel object is returned in |channel| when non-nullptr and - // the channel ID is returned through the Status object. - Status<int> CheckChannel(const Message* message, ChannelReference ref, - Channel** channel) { - UNUSED(message); - UNUSED(ref); - UNUSED(channel); - return Status<int>(); - } - - // Replies to the message with a return code. - Status<void> MessageReply(Message* message, int return_code) { - UNUSED(message); - UNUSED(return_code); - return Status<void>(); - } - - // Replies to the message with a file descriptor. - Status<void> MessageReplyFd(Message* message, unsigned int push_fd) { - UNUSED(message); - UNUSED(push_fd); - return Status<void>(); - } - - // Replies to the message with a local channel handle. - Status<void> MessageReplyChannelHandle(Message* message, - const LocalChannelHandle& handle) { - UNUSED(message); - UNUSED(handle); - return Status<void>(); - } - - // Replies to the message with a borrowed local channel handle. - Status<void> MessageReplyChannelHandle(Message* message, - const BorrowedChannelHandle& handle) { - UNUSED(message); - UNUSED(handle); - return Status<void>(); - } - - // Replies to the message with a remote channel handle. - Status<void> MessageReplyChannelHandle(Message* message, - const RemoteChannelHandle& handle) { - UNUSED(message); - UNUSED(handle); - return Status<void>(); - } - - // Reads message data into an array of memory buffers. - Status<size_t> ReadMessageData(Message* message, const iovec* vector, - size_t vector_length) { - UNUSED(message); - UNUSED(vector); - UNUSED(vector_length); - return Status<size_t>(); - } - - // Sends reply data for message. - Status<size_t> WriteMessageData(Message* message, const iovec* vector, - size_t vector_length) { - UNUSED(message); - UNUSED(vector); - UNUSED(vector_length); - return Status<size_t>(); - } - - // Records a file descriptor into the message buffer and returns the - // remapped reference to be sent to the remote process. - Status<FileReference> PushFileHandle(Message* message, - const LocalHandle& handle) { - UNUSED(message); - UNUSED(handle); - return Status<FileReference>(); - } - - Status<FileReference> PushFileHandle(Message* message, - const BorrowedHandle& handle) { - UNUSED(message); - UNUSED(handle); - return Status<FileReference>(); - } - - Status<FileReference> PushFileHandle(Message* message, - const RemoteHandle& handle) { - UNUSED(message); - UNUSED(handle); - return Status<FileReference>(); - } - - Status<ChannelReference> PushChannelHandle(Message* message, - const LocalChannelHandle& handle) { - UNUSED(message); - UNUSED(handle); - return Status<ChannelReference>(); - } - - Status<ChannelReference> PushChannelHandle( - Message* message, const BorrowedChannelHandle& handle) { - UNUSED(message); - UNUSED(handle); - return Status<ChannelReference>(); - } - - Status<ChannelReference> PushChannelHandle( - Message* message, const RemoteChannelHandle& handle) { - UNUSED(message); - UNUSED(handle); - return Status<ChannelReference>(); - } - - // Obtains a file descriptor/channel handle from a message for the given - // reference. - LocalHandle GetFileHandle(Message* message, FileReference ref) const { - UNUSED(message); - UNUSED(ref); - return LocalHandle(); - } - - LocalChannelHandle GetChannelHandle(Message* message, - ChannelReference ref) const { - UNUSED(message); - UNUSED(ref); - return LocalChannelHandle(); - } - - // Transport-specific message state management. - void* AllocateMessageState() { return nullptr; } - - void FreeMessageState(void* state) { UNUSED(state); } - - // Cancels the endpoint, unblocking any receiver threads waiting for a - // message. - Status<void> Cancel() { return Status<void>(); } - - private: - FuzzedDataProvider* _fdp; - std::shared_ptr<Channel> _channel; - Service* _service; - int _epoll_fd; -}; - -#endif // LEV_FUZZERS_LIBPDX_HELPERS_H_ diff --git a/libs/vr/libpdx/fuzz/message_fuzzer.cpp b/libs/vr/libpdx/fuzz/message_fuzzer.cpp deleted file mode 100644 index b627045ab6..0000000000 --- a/libs/vr/libpdx/fuzz/message_fuzzer.cpp +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -// Authors: corbin.souffrant@leviathansecurity.com -// brian.balling@leviathansecurity.com - -#include <fuzzer/FuzzedDataProvider.h> -#include <helpers.h> -#include <pdx/client_channel.h> -#include <pdx/service.h> -#include <pdx/service_dispatcher.h> -#include <stddef.h> -#include <stdint.h> -#include <sys/eventfd.h> -#include <thread> - -using namespace android::pdx; - -// Fuzzer for Message object functions. -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - FuzzedDataProvider fdp = FuzzedDataProvider(data, size); - - FuzzEndpoint* endpoint = new FuzzEndpoint(&fdp); - std::shared_ptr<Service> service( - new Service("FuzzService", std::unique_ptr<Endpoint>(endpoint))); - std::shared_ptr<Channel> channel(nullptr); - - // Generate a random Message object to call functions in. - MessageInfo info; - info.pid = fdp.ConsumeIntegral<int>(); - info.tid = fdp.ConsumeIntegral<int>(); - info.cid = fdp.ConsumeIntegral<int>(); - info.mid = fdp.ConsumeIntegral<int>(); - info.euid = fdp.ConsumeIntegral<int>(); - info.egid = fdp.ConsumeIntegral<int>(); - info.op = fdp.ConsumeIntegral<int32_t>(); - info.flags = fdp.ConsumeIntegral<uint32_t>(); - info.service = service.get(); - info.channel = channel.get(); - info.send_len = fdp.ConsumeIntegral<size_t>(); - info.recv_len = fdp.ConsumeIntegral<size_t>(); - info.fd_count = fdp.ConsumeIntegral<size_t>(); - if (fdp.remaining_bytes() >= 32) { - std::vector<uint8_t> impulse_vec = fdp.ConsumeBytes<uint8_t>(32); - memcpy(info.impulse, impulse_vec.data(), 32); - } - - Message message = Message(info); - - // A bunch of getters that probably won't do much, but might as well - // get coverage, while we are here. - message.GetProcessId(); - message.GetThreadId(); - message.GetEffectiveUserId(); - message.GetEffectiveGroupId(); - message.GetChannelId(); - message.GetMessageId(); - message.GetOp(); - message.GetFlags(); - message.GetSendLength(); - message.GetReceiveLength(); - message.GetFileDescriptorCount(); - message.ImpulseEnd(); - message.replied(); - message.IsChannelExpired(); - message.IsServiceExpired(); - message.GetState(); - message.GetState(); - - // Some misc. functions. - unsigned int fd = fdp.ConsumeIntegral<unsigned int>(); - int clear_mask = fdp.ConsumeIntegral<int>(); - int set_mask = fdp.ConsumeIntegral<int>(); - Status<void> status = {}; - message.ModifyChannelEvents(clear_mask, set_mask); - - // Fuzz the handle functions. - LocalHandle l_handle = {}; - BorrowedHandle b_handle = {}; - RemoteHandle r_handle = {}; - LocalChannelHandle lc_handle = {}; - BorrowedChannelHandle bc_handle = {}; - RemoteChannelHandle rc_handle = {}; - FileReference f_ref = fdp.ConsumeIntegral<int32_t>(); - ChannelReference c_ref = fdp.ConsumeIntegral<int32_t>(); - - // These don't actually modify any state in the Message or params. - // They can be called in any order. - message.PushFileHandle(b_handle); - message.PushFileHandle(r_handle); - message.PushChannelHandle(lc_handle); - message.PushChannelHandle(bc_handle); - message.PushChannelHandle(rc_handle); - message.GetFileHandle(f_ref, &l_handle); - message.GetChannelHandle(c_ref, &lc_handle); - - // Can only reply once, pick at random. - switch (fdp.ConsumeIntegral<uint8_t>()) { - case 0: - message.ReplyFileDescriptor(fd); - break; - case 1: - message.Reply(status); - break; - case 2: - message.Reply(l_handle); - break; - case 3: - message.Reply(b_handle); - break; - case 4: - message.Reply(r_handle); - break; - case 5: - message.Reply(lc_handle); - break; - case 6: - message.Reply(bc_handle); - break; - case 7: - message.Reply(rc_handle); - } - - // Fuzz the channel functions. - int flags = fdp.ConsumeIntegral<int>(); - int channel_id = 0; - message.PushChannel(flags, channel, &channel_id); - message.CheckChannel(service.get(), c_ref, &channel); - message.CheckChannel(c_ref, &channel); - message.PushChannel(service.get(), flags, channel, &channel_id); - size_t iovec_size = sizeof(iovec); - struct iovec* iovecs = nullptr; - - // Fuzz the read/write functions. Needs at least one iovec, plus one byte. - if (fdp.remaining_bytes() >= iovec_size + 1) { - std::vector<uint8_t> tmp_vec = fdp.ConsumeBytes<uint8_t>(iovec_size); - struct iovec* vector = reinterpret_cast<struct iovec*>(tmp_vec.data()); - std::vector<uint8_t> tmp_buf = - fdp.ConsumeBytes<uint8_t>(fdp.remaining_bytes()); - void* buf = reinterpret_cast<void*>(tmp_buf.data()); - size_t buf_size = fdp.ConsumeIntegral<size_t>(); - - // Capping num_vecs to 1024 so it doesn't allocate too much memory. - size_t num_vecs = fdp.ConsumeIntegralInRange<size_t>(0, 1024); - - if (num_vecs > 0) - iovecs = new struct iovec[num_vecs]; - for (size_t i = 0; i < num_vecs; i++) { - iovecs[i] = *vector; - } - - message.ReadAll(vector, buf_size); - message.WriteAll(buf, buf_size); - message.ReadVectorAll(vector, num_vecs); - message.WriteVectorAll(vector, num_vecs); - message.ReadVector(vector, buf_size); - message.WriteVector(vector, buf_size); - } - - if (iovecs != nullptr) - delete[] iovecs; - return 0; -} diff --git a/libs/vr/libpdx/fuzz/serialization_fuzzer.cpp b/libs/vr/libpdx/fuzz/serialization_fuzzer.cpp deleted file mode 100644 index f5c5a5a4c4..0000000000 --- a/libs/vr/libpdx/fuzz/serialization_fuzzer.cpp +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Copyright 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -// Authors: corbin.souffrant@leviathansecurity.com -// brian.balling@leviathansecurity.com - -#include <errno.h> -#include <fcntl.h> -#include <unistd.h> - -#include <memory> -#include <string> -#include <thread> -#include <utility> - -#include <fuzzer/FuzzedDataProvider.h> -#include <pdx/rpc/argument_encoder.h> -#include <pdx/rpc/array_wrapper.h> -#include <pdx/rpc/default_initialization_allocator.h> -#include <pdx/rpc/payload.h> -#include <pdx/rpc/serializable.h> -#include <pdx/rpc/serialization.h> -#include <pdx/rpc/string_wrapper.h> -#include <pdx/utility.h> - -using namespace android::pdx; -using namespace android::pdx::rpc; - -struct FuzzType { - int a; - float b; - std::string c; - - FuzzType() {} - FuzzType(int a, float b, const std::string& c) : a(a), b(b), c(c) {} - - private: - PDX_SERIALIZABLE_MEMBERS(FuzzType, a, b, c); -}; - -// Fuzzer for Serialization operations, this is mostly just lifted from the -// existing test cases to use fuzzed values as inputs. -void FuzzSerializeDeserialize(const uint8_t* data, size_t size) { - FuzzedDataProvider fdp = FuzzedDataProvider(data, size); - Payload result; - - // Currently, only fuzzing subset of types. In the future, may want - // to add more difficult to generate types like array, map, enum, etc... - bool b_val = fdp.ConsumeBool(); - uint8_t u8_val = fdp.ConsumeIntegral<uint8_t>(); - uint16_t u16_val = fdp.ConsumeIntegral<uint16_t>(); - uint32_t u32_val = fdp.ConsumeIntegral<uint32_t>(); - uint64_t u64_val = fdp.ConsumeIntegral<uint64_t>(); - int8_t i8_val = fdp.ConsumeIntegral<int8_t>(); - int16_t i16_val = fdp.ConsumeIntegral<uint16_t>(); - int32_t i32_val = fdp.ConsumeIntegral<uint32_t>(); - int64_t i64_val = fdp.ConsumeIntegral<uint64_t>(); - float f_val = fdp.ConsumeFloatingPoint<float>(); - double d_val = fdp.ConsumeFloatingPoint<double>(); - std::string s_val = fdp.ConsumeRandomLengthString(fdp.remaining_bytes()); - std::vector<uint8_t> vec_val = - fdp.ConsumeBytes<uint8_t>(fdp.remaining_bytes()); - FuzzType t1_val{reinterpret_cast<int>(i32_val), f_val, s_val}; - - // Types need to be individually fuzzed because code path changes depending - // on which type is being serialized/deserialized. - Serialize(b_val, &result); - Deserialize(&b_val, &result); - Serialize(u8_val, &result); - Deserialize(&u8_val, &result); - Serialize(u16_val, &result); - Deserialize(&u16_val, &result); - Serialize(u32_val, &result); - Deserialize(&u32_val, &result); - Serialize(u64_val, &result); - Deserialize(&u64_val, &result); - Serialize(i8_val, &result); - Deserialize(&i8_val, &result); - Serialize(i16_val, &result); - Deserialize(&i16_val, &result); - Serialize(i32_val, &result); - Deserialize(&i32_val, &result); - Serialize(i64_val, &result); - Deserialize(&i64_val, &result); - Serialize(f_val, &result); - Deserialize(&f_val, &result); - Serialize(d_val, &result); - Deserialize(&d_val, &result); - Serialize(s_val, &result); - Deserialize(&s_val, &result); - Serialize(WrapString(s_val), &result); - Deserialize(&s_val, &result); - Serialize(vec_val, &result); - Deserialize(&vec_val, &result); - Serialize(t1_val, &result); - Deserialize(&t1_val, &result); -} - -void FuzzDeserializeUint8(const uint8_t* data, size_t size) { - FuzzedDataProvider fdp = FuzzedDataProvider(data, size); - Payload buffer = {ENCODING_TYPE_UINT8, fdp.ConsumeIntegral<uint8_t>()}; - std::uint8_t result; - Deserialize(&result, &buffer); -} - -void FuzzDeserializeUint16(const uint8_t* data, size_t size) { - FuzzedDataProvider fdp = FuzzedDataProvider(data, size); - Payload buffer = {ENCODING_TYPE_UINT16, fdp.ConsumeIntegral<uint8_t>(), - fdp.ConsumeIntegral<uint8_t>()}; - std::uint16_t result; - Deserialize(&result, &buffer); -} - -void FuzzDeserializeUint32(const uint8_t* data, size_t size) { - FuzzedDataProvider fdp = FuzzedDataProvider(data, size); - Payload buffer = {ENCODING_TYPE_UINT32, fdp.ConsumeIntegral<uint8_t>(), - fdp.ConsumeIntegral<uint8_t>(), - fdp.ConsumeIntegral<uint8_t>(), - fdp.ConsumeIntegral<uint8_t>()}; - std::uint32_t result; - Deserialize(&result, &buffer); -} - -void FuzzDeserializeUint64(const uint8_t* data, size_t size) { - FuzzedDataProvider fdp = FuzzedDataProvider(data, size); - Payload buffer = { - ENCODING_TYPE_UINT64, fdp.ConsumeIntegral<uint8_t>(), - fdp.ConsumeIntegral<uint8_t>(), fdp.ConsumeIntegral<uint8_t>(), - fdp.ConsumeIntegral<uint8_t>(), fdp.ConsumeIntegral<uint8_t>(), - fdp.ConsumeIntegral<uint8_t>(), fdp.ConsumeIntegral<uint8_t>(), - fdp.ConsumeIntegral<uint8_t>()}; - std::uint64_t result; - Deserialize(&result, &buffer); -} - -void FuzzDeserializeInt8(const uint8_t* data, size_t size) { - FuzzedDataProvider fdp = FuzzedDataProvider(data, size); - Payload buffer = {ENCODING_TYPE_INT8, fdp.ConsumeIntegral<uint8_t>()}; - std::int8_t result; - Deserialize(&result, &buffer); -} - -void FuzzDeserializeInt16(const uint8_t* data, size_t size) { - FuzzedDataProvider fdp = FuzzedDataProvider(data, size); - Payload buffer = {ENCODING_TYPE_INT16, fdp.ConsumeIntegral<uint8_t>(), - fdp.ConsumeIntegral<uint8_t>()}; - std::int16_t result; - Deserialize(&result, &buffer); -} - -void FuzzDeserializeInt32(const uint8_t* data, size_t size) { - FuzzedDataProvider fdp = FuzzedDataProvider(data, size); - Payload buffer = {ENCODING_TYPE_INT32, fdp.ConsumeIntegral<uint8_t>(), - fdp.ConsumeIntegral<uint8_t>(), - fdp.ConsumeIntegral<uint8_t>(), - fdp.ConsumeIntegral<uint8_t>()}; - std::int32_t result; - Deserialize(&result, &buffer); -} - -void FuzzDeserializeInt64(const uint8_t* data, size_t size) { - FuzzedDataProvider fdp = FuzzedDataProvider(data, size); - Payload buffer = {ENCODING_TYPE_INT64, - fdp.ConsumeIntegral<uint8_t>(), - fdp.ConsumeIntegral<uint8_t>(), - fdp.ConsumeIntegral<uint8_t>(), - fdp.ConsumeIntegral<uint8_t>(), - fdp.ConsumeIntegral<uint8_t>(), - fdp.ConsumeIntegral<uint8_t>(), - fdp.ConsumeIntegral<uint8_t>(), - fdp.ConsumeIntegral<uint8_t>()}; - std::int64_t result; - Deserialize(&result, &buffer); -} - -void FuzzDeserializeFloat32(const uint8_t* data, size_t size) { - FuzzedDataProvider fdp = FuzzedDataProvider(data, size); - Payload buffer = {ENCODING_TYPE_FLOAT32, fdp.ConsumeIntegral<uint8_t>(), - fdp.ConsumeIntegral<uint8_t>(), - fdp.ConsumeIntegral<uint8_t>(), - fdp.ConsumeIntegral<uint8_t>()}; - float floatResult; - Deserialize(&floatResult, &buffer); - - buffer.Rewind(); - double doubleResult; - Deserialize(&doubleResult, &buffer); -} - -void FuzzDeserializeFloat64(const uint8_t* data, size_t size) { - FuzzedDataProvider fdp = FuzzedDataProvider(data, size); - Payload buffer = { - ENCODING_TYPE_FLOAT64, fdp.ConsumeIntegral<uint8_t>(), - fdp.ConsumeIntegral<uint8_t>(), fdp.ConsumeIntegral<uint8_t>(), - fdp.ConsumeIntegral<uint8_t>(), fdp.ConsumeIntegral<uint8_t>(), - fdp.ConsumeIntegral<uint8_t>(), fdp.ConsumeIntegral<uint8_t>(), - fdp.ConsumeIntegral<uint8_t>()}; - double result; - Deserialize(&result, &buffer); -} - -void FuzzDeserializeFixstr(const uint8_t* data, size_t size) { - FuzzedDataProvider fdp = FuzzedDataProvider(data, size); - std::string s_val = fdp.ConsumeRemainingBytesAsString(); - Payload buffer = {ENCODING_TYPE_FIXSTR_MAX}; - for (std::string::iterator iter = s_val.begin(); iter != s_val.end(); - iter++) { - buffer.Append(1, *iter); - } - std::string result; - Deserialize(&result, &buffer); -} - -void FuzzDeserializeFixmap(const uint8_t* data, size_t size) { - FuzzedDataProvider fdp = FuzzedDataProvider(data, size); - Payload buffer = {ENCODING_TYPE_FIXMAP_MAX}; - // Fill the map with the fuzzed data, not attempting to - // make a valid map - while (fdp.remaining_bytes() > 0) { - buffer.Append(1, fdp.ConsumeIntegral<uint8_t>()); - } - - std::map<std::uint32_t, std::uint32_t> result; - Deserialize(&result, &buffer); - - buffer.Rewind(); - std::unordered_map<std::uint32_t, std::uint32_t> unorderedResult; - Deserialize(&unorderedResult, &buffer); -} - -void FuzzDeserializeVariant(const uint8_t* data, size_t size) { - FuzzedDataProvider fdp = FuzzedDataProvider(data, size); - Payload buffer = {ENCODING_TYPE_INT16, - ENCODING_TYPE_FLOAT32, - ENCODING_TYPE_FIXSTR_MAX, - fdp.ConsumeIntegral<uint8_t>(), - fdp.ConsumeIntegral<uint8_t>(), - fdp.ConsumeIntegral<uint8_t>(), - fdp.ConsumeIntegral<uint8_t>(), - fdp.ConsumeIntegral<uint8_t>(), - fdp.ConsumeIntegral<uint8_t>(), - fdp.ConsumeIntegral<uint8_t>(), - fdp.ConsumeIntegral<uint8_t>()}; - // Add the rest of the data as a string - std::string s_val = fdp.ConsumeRemainingBytesAsString(); - for (std::string::iterator iter = s_val.begin(); iter != s_val.end(); - iter++) { - buffer.Append(1, *iter); - } - Variant<int, float, std::string> result; - Deserialize(&result, &buffer); -} - -// Attempts to deserialize fuzzed data as various types -void FuzzDeserialize(const uint8_t* data, size_t size) { - FuzzDeserializeUint8(data, size); - FuzzDeserializeUint16(data, size); - FuzzDeserializeUint32(data, size); - FuzzDeserializeUint64(data, size); - FuzzDeserializeInt8(data, size); - FuzzDeserializeInt16(data, size); - FuzzDeserializeInt32(data, size); - FuzzDeserializeInt64(data, size); - FuzzDeserializeFloat32(data, size); - FuzzDeserializeFloat64(data, size); - FuzzDeserializeFixstr(data, size); - FuzzDeserializeFixmap(data, size); - FuzzDeserializeVariant(data, size); -} - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - FuzzSerializeDeserialize(data, size); - FuzzDeserialize(data, size); - - return 0; -} diff --git a/libs/vr/libpdx/fuzz/service_dispatcher_fuzzer.cpp b/libs/vr/libpdx/fuzz/service_dispatcher_fuzzer.cpp deleted file mode 100644 index 3a3bfd9bcf..0000000000 --- a/libs/vr/libpdx/fuzz/service_dispatcher_fuzzer.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -// Authors: corbin.souffrant@leviathansecurity.com -// brian.balling@leviathansecurity.com - -#include <fuzzer/FuzzedDataProvider.h> -#include <helpers.h> -#include <pdx/client_channel.h> -#include <pdx/service.h> -#include <pdx/service_dispatcher.h> -#include <stddef.h> -#include <stdint.h> -#include <sys/eventfd.h> -#include <thread> - -using namespace android::pdx; - -// Dispatch fuzzer entry point. This fuzzer creates a ServiceDispatcher -// and creates an endpoint that returns fuzzed messages that are passed -// to the ReceiveAndDispatch and DispatchLoop functions. -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - eventfd_t wakeup_val = 1; - FuzzedDataProvider fdp = FuzzedDataProvider(data, size); - - // Endpoint is only used to be immediately wrapped as a unique_ptr, - // so it is ok to be using a raw ptr and new here without freeing. - FuzzEndpoint* endpoint = new FuzzEndpoint(&fdp); - std::unique_ptr<ServiceDispatcher> dispatcher = ServiceDispatcher::Create(); - std::shared_ptr<Channel> channel(nullptr); - std::shared_ptr<Client> client(nullptr); - std::shared_ptr<Service> service( - new Service("FuzzService", std::unique_ptr<Endpoint>(endpoint))); - - service->SetChannel(0, std::shared_ptr<Channel>(channel)); - dispatcher->AddService(service); - - // Dispatcher blocks, so needs to run in its own thread. - std::thread run_dispatcher([&]() { - uint8_t opt = 0; - - // Right now the only operations block, so the while loop is pointless - // but leaving it in, just in case that ever changes. - while (fdp.remaining_bytes() > sizeof(MessageInfo)) { - opt = fdp.ConsumeIntegral<uint8_t>() % dispatcher_operations.size(); - dispatcher_operations[opt](dispatcher, &fdp); - } - }); - - // Continuously wake up the epoll so the dispatcher can run. - while (fdp.remaining_bytes() > sizeof(MessageInfo)) { - eventfd_write(endpoint->epoll_fd(), wakeup_val); - } - - // Cleanup the dispatcher and thread. - dispatcher->SetCanceled(true); - if (run_dispatcher.joinable()) - run_dispatcher.join(); - dispatcher->RemoveService(service); - - return 0; -} diff --git a/libs/vr/libpdx/mock_tests.cpp b/libs/vr/libpdx/mock_tests.cpp deleted file mode 100644 index 4143837cb4..0000000000 --- a/libs/vr/libpdx/mock_tests.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include <gtest/gtest.h> -#include <pdx/mock_client_channel.h> -#include <pdx/mock_client_channel_factory.h> -#include <pdx/mock_message_reader.h> -#include <pdx/mock_message_writer.h> -#include <pdx/mock_service_endpoint.h> - -TEST(MockTypes, Instantiation) { - // Make sure all our interfaces are mocked out properly and mock instances - // can be created. - android::pdx::MockClientChannel client_channel; - android::pdx::MockClientChannelFactory client_channel_factory; - android::pdx::MockInputResourceMapper input_resource_mapper; - android::pdx::MockMessageReader message_reader; - android::pdx::MockOutputResourceMapper output_resource_mapper; - android::pdx::MockMessageWriter message_writer; - android::pdx::MockEndpoint endpoint; -} diff --git a/libs/vr/libpdx/private/pdx/channel_handle.h b/libs/vr/libpdx/private/pdx/channel_handle.h deleted file mode 100644 index bd04305184..0000000000 --- a/libs/vr/libpdx/private/pdx/channel_handle.h +++ /dev/null @@ -1,123 +0,0 @@ -#ifndef ANDROID_PDX_CHANNEL_HANDLE_H_ -#define ANDROID_PDX_CHANNEL_HANDLE_H_ - -#include <cstdint> -#include <type_traits> - -namespace android { -namespace pdx { - -enum class ChannelHandleMode { - Local, - Borrowed, - Remote, -}; - -class ChannelManagerInterface { - public: - virtual void CloseHandle(std::int32_t handle) = 0; - - protected: - // Nobody should be allowed to delete the instance of channel manager - // through this interface. - virtual ~ChannelManagerInterface() = default; -}; - -class ChannelHandleBase { - public: - ChannelHandleBase() = default; - explicit ChannelHandleBase(const int32_t& value) : value_{value} {} - - ChannelHandleBase(const ChannelHandleBase&) = delete; - ChannelHandleBase& operator=(const ChannelHandleBase&) = delete; - - std::int32_t value() const { return value_; } - bool valid() const { return value_ >= 0; } - explicit operator bool() const { return valid(); } - - void Close() { value_ = kEmptyHandle; } - - protected: - // Must not be used by itself. Must be derived from. - ~ChannelHandleBase() = default; - enum : std::int32_t { kEmptyHandle = -1 }; - - std::int32_t value_{kEmptyHandle}; -}; - -template <ChannelHandleMode Mode> -class ChannelHandle : public ChannelHandleBase { - public: - ChannelHandle() = default; - using ChannelHandleBase::ChannelHandleBase; - ChannelHandle(ChannelHandle&& other) noexcept : ChannelHandleBase{other.value_} { - other.value_ = kEmptyHandle; - } - ~ChannelHandle() = default; - - ChannelHandle Duplicate() const { return ChannelHandle{value_}; } - - ChannelHandle& operator=(ChannelHandle&& other) noexcept { - value_ = other.value_; - other.value_ = kEmptyHandle; - return *this; - } -}; - -template <> -class ChannelHandle<ChannelHandleMode::Local> : public ChannelHandleBase { - public: - ChannelHandle() = default; - ChannelHandle(ChannelManagerInterface* manager, int32_t value) - : ChannelHandleBase{value}, manager_{manager} {} - - ChannelHandle(const ChannelHandle&) = delete; - ChannelHandle& operator=(const ChannelHandle&) = delete; - - ChannelHandle(ChannelHandle&& other) noexcept - : ChannelHandleBase{other.value_}, manager_{other.manager_} { - other.manager_ = nullptr; - other.value_ = kEmptyHandle; - } - - ChannelHandle& operator=(ChannelHandle&& other) noexcept { - value_ = other.value_; - manager_ = other.manager_; - other.value_ = kEmptyHandle; - other.manager_ = nullptr; - return *this; - } - - ~ChannelHandle() { - if (manager_) - manager_->CloseHandle(value_); - } - - ChannelHandle<ChannelHandleMode::Borrowed> Borrow() const { - return ChannelHandle<ChannelHandleMode::Borrowed>{value_}; - } - - void Close() { - if (manager_) - manager_->CloseHandle(value_); - manager_ = nullptr; - value_ = kEmptyHandle; - } - - private: - ChannelManagerInterface* manager_{nullptr}; -}; - -using LocalChannelHandle = ChannelHandle<ChannelHandleMode::Local>; -using BorrowedChannelHandle = ChannelHandle<ChannelHandleMode::Borrowed>; -using RemoteChannelHandle = ChannelHandle<ChannelHandleMode::Remote>; - -// ChannelReference is a 32 bit integer used in IPC serialization to be -// transferred across processes. You can convert this value to a local channel -// handle by calling Transaction.GetChannelHandle(). -using ChannelReference = int32_t; - -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_CHANNEL_HANDLE_H_ diff --git a/libs/vr/libpdx/private/pdx/channel_parcelable.h b/libs/vr/libpdx/private/pdx/channel_parcelable.h deleted file mode 100644 index 59ef9d3119..0000000000 --- a/libs/vr/libpdx/private/pdx/channel_parcelable.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef ANDROID_PDX_CHANNEL_PARCELABLE_H_ -#define ANDROID_PDX_CHANNEL_PARCELABLE_H_ - -#include <binder/Parcelable.h> -#include <pdx/channel_handle.h> - -namespace android { -namespace pdx { - -/** - * A parcelable object holds all necessary objects to recreate a ClientChannel. - * In addition to the android::Parcelable interface, this interface exposees - * more PDX-related interface. - */ -class ChannelParcelable : public Parcelable { - public: - virtual ~ChannelParcelable() = default; - - // Returns whether the parcelable object holds a valid client channel. - virtual bool IsValid() const = 0; - - // Returns a channel handle constructed from this parcelable object and takes - // the ownership of all resources from the parcelable object. In another word, - // the parcelable object will become invalid after TakeChannelHandle returns. - virtual LocalChannelHandle TakeChannelHandle() = 0; -}; - -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_CHANNEL_PARCELABLE_H_ diff --git a/libs/vr/libpdx/private/pdx/client.h b/libs/vr/libpdx/private/pdx/client.h deleted file mode 100644 index 7e2d55c8fe..0000000000 --- a/libs/vr/libpdx/private/pdx/client.h +++ /dev/null @@ -1,302 +0,0 @@ -#ifndef ANDROID_PDX_CLIENT_H_ -#define ANDROID_PDX_CLIENT_H_ - -#include <errno.h> -#include <sys/types.h> - -#include <memory> -#include <string> -#include <type_traits> - -#include <pdx/channel_handle.h> -#include <pdx/client_channel.h> -#include <pdx/client_channel_factory.h> -#include <pdx/file_handle.h> -#include <pdx/message_reader.h> -#include <pdx/message_writer.h> -#include <pdx/rpc/remote_method_type.h> -#include <pdx/status.h> - -namespace android { -namespace pdx { - -class Transaction; - -/* - * Base class of client-side service API classes. - */ -class Client { - public: - static const int64_t kInfiniteTimeout = -1; - - virtual ~Client() = default; - - /* - * Returns true if the Client instance successfully initialized, false - * otherwise. Subclasses that can fail to initialize must override this and - * AND their initialization result with this base class method's result. - * - * This method is not intended to perform initialization, only to report - * the status of the initialization. - */ - virtual bool IsInitialized() const; - - /* - * Returns the error code describing the Client initialization failure, or 0 - * if there was no failure. - */ - int error() const; - - // Returns a reference to IPC channel handle. - LocalChannelHandle& GetChannelHandle(); - const LocalChannelHandle& GetChannelHandle() const; - - protected: - friend Transaction; - explicit Client(std::unique_ptr<ClientChannel> channel); - explicit Client(std::unique_ptr<ClientChannelFactory> channel_factory, - int64_t timeout_ms = kInfiniteTimeout); - - /* - * Called by Client::Connect() after successfully connecting to the service - * endpoint. Subclasses may override this method to perform additional setup, - * including sending messages to complete the connection process. - * - * Subclasses may call Client::Close() within this method to terminate the - * connection; Client::Connect() returns the negated error passed to - * Client::Close() when this happens. - */ - virtual void OnConnect(); - - enum : size_t { MAX_IMPULSE_LENGTH = sizeof(uint64_t) * 4 }; - - Status<void> SendImpulse(int opcode); - Status<void> SendImpulse(int opcode, const void* buffer, size_t length); - - /* - * Remote method call API using pdx::rpc serialization. - * Include pdx/rpc/remote_method.h to use these methods. - */ - template <typename RemoteMethodType, typename... Args> - Status<typename RemoteMethodType::Return> InvokeRemoteMethod(Args&&... args); - - template <typename RemoteMethodType, typename ReturnType, typename... Args> - Status<void> InvokeRemoteMethodInPlace(ReturnType* return_value, - Args&&... args); - - /* - * Close the endpoint file descriptor and optionally indicate an error, which - * may be retrieved through error(). Subclasses may use this in their - * constructor to signal failure during initialization or at other times - * during operation. - */ - void Close(int error); - - /* - * Returns true if the client is connected to the service, false otherwise. - */ - bool IsConnected() const; - - /* - * Enables auto-reconnect with the given timeout. Use kInfiniteTimeout (-1) - * for no timeout. Auto-reconnect can only be enabled if the Client class - * was constructed with a ClientChannelFactory. - */ - void EnableAutoReconnect(int64_t reconnect_timeout_ms); - - /* - * Disables auto-reconnect. - */ - void DisableAutoReconnect(); - - /* - * Returns an fd that the client may use to check/wait for asynchronous - * notifications to the channel. It is implementation dependent how the - * transport backend handles this feature, however all implementations must - * support at least POLLIN/EPOLLIN/readable. - * - * For uses that require more than one type of event, use - * ClientChannel::GetEventMask() to distinguish between events. - */ - int event_fd() const; - - /* - * Returns the underlying ClientChannel object. - */ - ClientChannel* GetChannel() const { return channel_.get(); } - std::unique_ptr<ClientChannel>&& TakeChannel() { return std::move(channel_); } - - private: - Client(const Client&) = delete; - void operator=(const Client&) = delete; - - Status<void> CheckReconnect(); - bool NeedToDisconnectChannel(int error) const; - void CheckDisconnect(int error); - - template <typename T> - inline void CheckDisconnect(const Status<T>& status) { - if (!status) - CheckDisconnect(status.error()); - } - - std::unique_ptr<ClientChannel> channel_; - int error_{0}; - - // Reconnection state. - std::unique_ptr<ClientChannelFactory> channel_factory_; - int64_t reconnect_timeout_ms_{0}; - bool auto_reconnect_enabled_{false}; -}; - -/* - * Utility template base class for client-side service API classes. Handles - * initialization checks during allocation and automatically cleans up on - * failure. - * - * @tparam T Type of the class extending this one. - * @tparam C Client class to wrap. Defaults to the Client class. - */ -template <typename T, typename ParentClient = Client> -class ClientBase : public ParentClient { - public: - // Type of the client this class wraps. - using ClientType = ParentClient; - - static_assert(std::is_base_of<Client, ParentClient>::value, - "The provided parent client is not a Client subclass."); - - /* - * Allocates a new instance of the superclass and checks for successful - * initialization. - * - * The variadic arguments must expand to match one of type T's constructors - * and are passed through unchanged. If a timeout is desired, subclasses are - * responsible for passing this through to the appropriate ClientBase - * constructor. - * - * Returns a unique_ptr to the new instance on success, or an empty unique_ptr - * otherwise. - */ - template <typename... Args> - static inline std::unique_ptr<T> Create(Args&&... args) { - std::unique_ptr<T> client(new T(std::forward<Args>(args)...)); - if (client->IsInitialized()) - return client; - else - return nullptr; - } - - protected: - /* - * Type of the base class. Useful for referencing the base class type and - * constructor in subclasses. Subclasses with non-public constructors - * must declare BASE a friend. - */ - using BASE = ClientBase<T, ParentClient>; - - /* - * Type of the unique_ptr deleter. Useful for friend declarations. - */ - using deleter_type = typename std::unique_ptr<T>::deleter_type; - - using ParentClient::ParentClient; -}; - -class Transaction final : public OutputResourceMapper, - public InputResourceMapper { - public: - explicit Transaction(Client& client); - ~Transaction(); - - template <typename T> - Status<T> Send(int opcode) { - return SendVector<T>(opcode, nullptr, 0, nullptr, 0); - } - - template <typename T> - Status<T> Send(int opcode, const void* send_buffer, size_t send_length, - void* receive_buffer, size_t receive_length) { - const bool send = (send_buffer && send_length); - const bool receive = (receive_buffer && receive_length); - const iovec send_vector = {const_cast<void*>(send_buffer), send_length}; - const iovec receive_vector = {receive_buffer, receive_length}; - return SendVector<T>(opcode, send ? &send_vector : nullptr, send ? 1 : 0, - receive ? &receive_vector : nullptr, receive ? 1 : 0); - } - - template <typename T> - Status<T> SendVector(int opcode, const iovec* send_vector, size_t send_count, - const iovec* receive_vector, size_t receive_count) { - Status<T> ret; - SendTransaction(opcode, &ret, send_vector, send_count, receive_vector, - receive_count); - return ret; - } - - template <typename T, size_t send_count, size_t receive_count> - Status<T> SendVector(int opcode, const iovec (&send_vector)[send_count], - const iovec (&receive_vector)[receive_count]) { - return SendVector<T>(opcode, send_vector, send_count, receive_vector, - receive_count); - } - - template <typename T, size_t send_count> - Status<T> SendVector(int opcode, const iovec (&send_vector)[send_count], - std::nullptr_t) { - return SendVector<T>(opcode, send_vector, send_count, nullptr, 0); - } - - template <typename T, size_t receive_count> - Status<T> SendVector(int opcode, std::nullptr_t, - const iovec (&receive_vector)[receive_count]) { - return SendVector<T>(opcode, nullptr, 0, receive_vector, receive_count); - } - - // OutputResourceMapper - Status<FileReference> PushFileHandle(const LocalHandle& handle) override; - Status<FileReference> PushFileHandle(const BorrowedHandle& handle) override; - Status<FileReference> PushFileHandle(const RemoteHandle& handle) override; - Status<ChannelReference> PushChannelHandle( - const LocalChannelHandle& handle) override; - Status<ChannelReference> PushChannelHandle( - const BorrowedChannelHandle& handle) override; - Status<ChannelReference> PushChannelHandle( - const RemoteChannelHandle& handle) override; - - // InputResourceMapper - bool GetFileHandle(FileReference ref, LocalHandle* handle) override; - bool GetChannelHandle(ChannelReference ref, - LocalChannelHandle* handle) override; - - private: - bool EnsureStateAllocated(); - void SendTransaction(int opcode, Status<void>* ret, const iovec* send_vector, - size_t send_count, const iovec* receive_vector, - size_t receive_count); - void SendTransaction(int opcode, Status<int>* ret, const iovec* send_vector, - size_t send_count, const iovec* receive_vector, - size_t receive_count); - void SendTransaction(int opcode, Status<LocalHandle>* ret, - const iovec* send_vector, size_t send_count, - const iovec* receive_vector, size_t receive_count); - void SendTransaction(int opcode, Status<LocalChannelHandle>* ret, - const iovec* send_vector, size_t send_count, - const iovec* receive_vector, size_t receive_count); - void CheckDisconnect(int error); - - template <typename T> - inline void CheckDisconnect(const Status<T>& status) { - if (!status) - CheckDisconnect(status.error()); - } - - Client& client_; - void* state_{nullptr}; - bool state_allocated_{false}; -}; - -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_CLIENT_H_ diff --git a/libs/vr/libpdx/private/pdx/client_channel.h b/libs/vr/libpdx/private/pdx/client_channel.h deleted file mode 100644 index f33a60e881..0000000000 --- a/libs/vr/libpdx/private/pdx/client_channel.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef ANDROID_PDX_CLIENT_CHANNEL_H_ -#define ANDROID_PDX_CLIENT_CHANNEL_H_ - -#include <vector> - -#include <pdx/channel_handle.h> -#include <pdx/channel_parcelable.h> -#include <pdx/file_handle.h> -#include <pdx/status.h> - -struct iovec; - -namespace android { -namespace pdx { - -class ClientChannel { - public: - virtual ~ClientChannel() = default; - - // Returns a tag that uniquely identifies a specific underlying IPC transport. - virtual uint32_t GetIpcTag() const = 0; - - virtual int event_fd() const = 0; - virtual Status<int> GetEventMask(int events) = 0; - - struct EventSource { - int event_fd; - int event_mask; - }; - - // Returns a set of event-generating fds with and event mask for each. These - // fds are owned by the ClientChannel and must never be closed by the caller. - virtual std::vector<EventSource> GetEventSources() const = 0; - - virtual LocalChannelHandle& GetChannelHandle() = 0; - virtual const LocalChannelHandle& GetChannelHandle() const = 0; - virtual void* AllocateTransactionState() = 0; - virtual void FreeTransactionState(void* state) = 0; - - virtual Status<void> SendImpulse(int opcode, const void* buffer, - size_t length) = 0; - - virtual Status<int> SendWithInt(void* transaction_state, int opcode, - const iovec* send_vector, size_t send_count, - const iovec* receive_vector, - size_t receive_count) = 0; - virtual Status<LocalHandle> SendWithFileHandle( - void* transaction_state, int opcode, const iovec* send_vector, - size_t send_count, const iovec* receive_vector, size_t receive_count) = 0; - virtual Status<LocalChannelHandle> SendWithChannelHandle( - void* transaction_state, int opcode, const iovec* send_vector, - size_t send_count, const iovec* receive_vector, size_t receive_count) = 0; - - virtual FileReference PushFileHandle(void* transaction_state, - const LocalHandle& handle) = 0; - virtual FileReference PushFileHandle(void* transaction_state, - const BorrowedHandle& handle) = 0; - virtual ChannelReference PushChannelHandle( - void* transaction_state, const LocalChannelHandle& handle) = 0; - virtual ChannelReference PushChannelHandle( - void* transaction_state, const BorrowedChannelHandle& handle) = 0; - virtual bool GetFileHandle(void* transaction_state, FileReference ref, - LocalHandle* handle) const = 0; - virtual bool GetChannelHandle(void* transaction_state, ChannelReference ref, - LocalChannelHandle* handle) const = 0; - - // Returns the internal state of the channel as a parcelable object. The - // ClientChannel is invalidated however, the channel is kept alive by the - // parcelable object and may be transferred to another process. - virtual std::unique_ptr<ChannelParcelable> TakeChannelParcelable() = 0; -}; - -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_CLIENT_CHANNEL_H_ diff --git a/libs/vr/libpdx/private/pdx/client_channel_factory.h b/libs/vr/libpdx/private/pdx/client_channel_factory.h deleted file mode 100644 index a82ab70be3..0000000000 --- a/libs/vr/libpdx/private/pdx/client_channel_factory.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef ANDROID_PDX_CLIENT_CHANNEL_FACTORY_H_ -#define ANDROID_PDX_CLIENT_CHANNEL_FACTORY_H_ - -#include <pdx/client_channel.h> -#include <pdx/status.h> - -namespace android { -namespace pdx { - -class ClientChannelFactory { - public: - virtual ~ClientChannelFactory() = default; - - virtual Status<std::unique_ptr<ClientChannel>> Connect( - int64_t timeout_ms) const = 0; -}; - -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_CLIENT_CHANNEL_FACTORY_H_ diff --git a/libs/vr/libpdx/private/pdx/file_handle.h b/libs/vr/libpdx/private/pdx/file_handle.h deleted file mode 100644 index fed1529c78..0000000000 --- a/libs/vr/libpdx/private/pdx/file_handle.h +++ /dev/null @@ -1,141 +0,0 @@ -#ifndef ANDROID_PDX_FILE_HANDLE_H_ -#define ANDROID_PDX_FILE_HANDLE_H_ - -#include <fcntl.h> -#include <unistd.h> - -#include <string> - -namespace android { -namespace pdx { - -enum class FileHandleMode { - Local, - Remote, - Borrowed, -}; - -// Manages ownership, sharing, and lifetime of file descriptors. -template <FileHandleMode Mode> -class FileHandle { - public: - static constexpr int kEmptyFileHandle = -1; - - // Constructs an empty FileHandle object. - FileHandle() : fd_(kEmptyFileHandle) {} - - // Constructs a FileHandle from an integer file descriptor and takes - // ownership. - explicit FileHandle(int fd) : fd_(fd) {} - - // Constructs a FileHandle by opening |path|. The arguments follow the - // semantics of open(). - FileHandle(const std::string& path, int flags, mode_t mode = 0) { - fd_ = open(path.c_str(), flags, mode); - } - - // Constructs a FileHandle by opening |path| relative to |dir_fd|, following - // the semantics of openat(). - FileHandle(const int directory_fd, const std::string& path, int flags, - mode_t mode = 0) { - fd_ = openat(directory_fd, path.c_str(), flags, mode); - } - - // Move constructor that assumes ownership of the file descriptor, leaving the - // other FileHandle object empty. - FileHandle(FileHandle&& other) noexcept { - fd_ = other.fd_; - other.fd_ = kEmptyFileHandle; - } - - // Returns a FileHandle as a duplicate handle of |fd|. Borrowed handles and - // handles in remote handle space are not duplicated. - static FileHandle AsDuplicate(const int fd) { - if (Mode == FileHandleMode::Local) - return FileHandle(dup(fd)); - else - return FileHandle(fd); - } - - // Destructor closes the file descriptor when non-empty. - ~FileHandle() { Close(); } - - // Move assignment operator that assumes ownership of the underlying file - // descriptor, leaving the other FileHandle object empty. - FileHandle& operator=(FileHandle&& other) noexcept { - if (this != &other) { - Reset(other.fd_); - other.fd_ = kEmptyFileHandle; - } - return *this; - } - - // Resets the underlying file handle to |fd|. - void Reset(int fd) { - Close(); - fd_ = fd; - } - - // Closes the underlying file descriptor when non-empty. - void Close() { - if (IsValid() && Mode == FileHandleMode::Local) - close(fd_); - fd_ = kEmptyFileHandle; - } - - // Return the internal fd, passing ownership to the caller. - int Release() { - int release_fd = fd_; - fd_ = kEmptyFileHandle; - return release_fd; - } - - // Duplicates the underlying file descriptor and returns a FileHandle that - // owns the new file descriptor. File descriptors are not duplicated when Mode - // is Remote or Borrowed. - FileHandle Duplicate() const { - return FileHandle(Mode == FileHandleMode::Local ? dup(fd_) : fd_); - } - - FileHandle<FileHandleMode::Borrowed> Borrow() const { - return FileHandle<FileHandleMode::Borrowed>(Get()); - } - - // Gets the underlying file descriptor value. - int Get() const { return fd_; } - bool IsValid() const { return fd_ >= 0; } - explicit operator bool() const { return IsValid(); } - - private: - int fd_; - - FileHandle(const FileHandle&) = delete; - void operator=(const FileHandle&) = delete; -}; - -// Alias for a file handle in the local process' handle space. -using LocalHandle = FileHandle<FileHandleMode::Local>; - -// Alias for a file handle in another process' handle space. Handles returned -// from pushing a file object or channel must be stored in this type of handle -// class, which doesn't close the underlying file descriptor. The underlying -// file descriptor in this wrapper should not be passed to close() because doing -// so would close an unrelated file descriptor in the local handle space. -using RemoteHandle = FileHandle<FileHandleMode::Remote>; - -// Alias for borrowed handles in the local process' handle space. A borrowed -// file handle is not close() because this wrapper does not own the underlying -// file descriptor. Care must be take to ensure that a borrowed file handle -// remains valid during use. -using BorrowedHandle = FileHandle<FileHandleMode::Borrowed>; - -// FileReference is a 16 bit integer used in IPC serialization to be -// transferred across processes. You can convert this value to a local file -// handle by calling Transaction.GetFileHandle() on client side and -// Message.GetFileHandle() on service side. -using FileReference = int16_t; - -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_FILE_HANDLE_H_ diff --git a/libs/vr/libpdx/private/pdx/message_reader.h b/libs/vr/libpdx/private/pdx/message_reader.h deleted file mode 100644 index bc280cffd7..0000000000 --- a/libs/vr/libpdx/private/pdx/message_reader.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef ANDROID_PDX_MESSAGE_READER_H_ -#define ANDROID_PDX_MESSAGE_READER_H_ - -#include <memory> - -#include <pdx/channel_handle.h> -#include <pdx/file_handle.h> - -namespace android { -namespace pdx { - -class InputResourceMapper { - public: - virtual bool GetFileHandle(FileReference ref, LocalHandle* handle) = 0; - virtual bool GetChannelHandle(ChannelReference ref, - LocalChannelHandle* handle) = 0; - - protected: - virtual ~InputResourceMapper() = default; -}; - -class MessageReader { - public: - // Pointers to start/end of the region in the read buffer. - using BufferSection = std::pair<const void*, const void*>; - - virtual BufferSection GetNextReadBufferSection() = 0; - virtual void ConsumeReadBufferSectionData(const void* new_start) = 0; - virtual InputResourceMapper* GetInputResourceMapper() = 0; - - protected: - virtual ~MessageReader() = default; -}; - -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_MESSAGE_READER_H_ diff --git a/libs/vr/libpdx/private/pdx/message_writer.h b/libs/vr/libpdx/private/pdx/message_writer.h deleted file mode 100644 index 4a101d6806..0000000000 --- a/libs/vr/libpdx/private/pdx/message_writer.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef ANDROID_PDX_MESSAGE_WRITER_H_ -#define ANDROID_PDX_MESSAGE_WRITER_H_ - -#include <pdx/channel_handle.h> -#include <pdx/file_handle.h> -#include <pdx/status.h> - -namespace android { -namespace pdx { - -class OutputResourceMapper { - public: - virtual Status<FileReference> PushFileHandle(const LocalHandle& handle) = 0; - virtual Status<FileReference> PushFileHandle( - const BorrowedHandle& handle) = 0; - virtual Status<FileReference> PushFileHandle(const RemoteHandle& handle) = 0; - virtual Status<ChannelReference> PushChannelHandle( - const LocalChannelHandle& handle) = 0; - virtual Status<ChannelReference> PushChannelHandle( - const BorrowedChannelHandle& handle) = 0; - virtual Status<ChannelReference> PushChannelHandle( - const RemoteChannelHandle& handle) = 0; - - protected: - virtual ~OutputResourceMapper() = default; -}; - -class MessageWriter { - public: - virtual void* GetNextWriteBufferSection(size_t size) = 0; - virtual OutputResourceMapper* GetOutputResourceMapper() = 0; - - protected: - virtual ~MessageWriter() = default; -}; - -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_MESSAGE_WRITER_H_ diff --git a/libs/vr/libpdx/private/pdx/mock_client_channel.h b/libs/vr/libpdx/private/pdx/mock_client_channel.h deleted file mode 100644 index b1a12996c5..0000000000 --- a/libs/vr/libpdx/private/pdx/mock_client_channel.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef ANDROID_PDX_MOCK_CLIENT_CHANNEL_H_ -#define ANDROID_PDX_MOCK_CLIENT_CHANNEL_H_ - -#include <gmock/gmock.h> -#include <pdx/client_channel.h> - -namespace android { -namespace pdx { - -class MockClientChannel : public ClientChannel { - public: - MOCK_CONST_METHOD0(GetIpcTag, uint32_t()); - MOCK_CONST_METHOD0(event_fd, int()); - MOCK_CONST_METHOD0(GetEventSources, std::vector<EventSource>()); - MOCK_METHOD1(GetEventMask, Status<int>(int)); - MOCK_METHOD0(GetChannelHandle, LocalChannelHandle&()); - MOCK_CONST_METHOD0(GetChannelHandle, const LocalChannelHandle&()); - MOCK_METHOD0(AllocateTransactionState, void*()); - MOCK_METHOD1(FreeTransactionState, void(void* state)); - MOCK_METHOD3(SendImpulse, - Status<void>(int opcode, const void* buffer, size_t length)); - MOCK_METHOD6(SendWithInt, - Status<int>(void* transaction_state, int opcode, - const iovec* send_vector, size_t send_count, - const iovec* receive_vector, size_t receive_count)); - MOCK_METHOD6(SendWithFileHandle, - Status<LocalHandle>(void* transaction_state, int opcode, - const iovec* send_vector, size_t send_count, - const iovec* receive_vector, - size_t receive_count)); - MOCK_METHOD6(SendWithChannelHandle, - Status<LocalChannelHandle>(void* transaction_state, int opcode, - const iovec* send_vector, - size_t send_count, - const iovec* receive_vector, - size_t receive_count)); - MOCK_METHOD2(PushFileHandle, FileReference(void* transaction_state, - const LocalHandle& handle)); - MOCK_METHOD2(PushFileHandle, FileReference(void* transaction_state, - const BorrowedHandle& handle)); - MOCK_METHOD2(PushChannelHandle, - ChannelReference(void* transaction_state, - const LocalChannelHandle& handle)); - MOCK_METHOD2(PushChannelHandle, - ChannelReference(void* transaction_state, - const BorrowedChannelHandle& handle)); - MOCK_CONST_METHOD3(GetFileHandle, - bool(void* transaction_state, FileReference ref, - LocalHandle* handle)); - MOCK_CONST_METHOD3(GetChannelHandle, - bool(void* transaction_state, ChannelReference ref, - LocalChannelHandle* handle)); - MOCK_METHOD0(TakeChannelParcelable, std::unique_ptr<ChannelParcelable>()); -}; - -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_MOCK_CLIENT_CHANNEL_H_ diff --git a/libs/vr/libpdx/private/pdx/mock_client_channel_factory.h b/libs/vr/libpdx/private/pdx/mock_client_channel_factory.h deleted file mode 100644 index 0190f5e458..0000000000 --- a/libs/vr/libpdx/private/pdx/mock_client_channel_factory.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef ANDROID_PDX_MOCK_CLIENT_CHANNEL_FACTORY_H_ -#define ANDROID_PDX_MOCK_CLIENT_CHANNEL_FACTORY_H_ - -#include <gmock/gmock.h> -#include <pdx/client_channel_factory.h> - -namespace android { -namespace pdx { - -class MockClientChannelFactory : public ClientChannelFactory { - public: - MOCK_CONST_METHOD1( - Connect, Status<std::unique_ptr<ClientChannel>>(int64_t timeout_ms)); -}; - -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_MOCK_CLIENT_CHANNEL_FACTORY_H_ diff --git a/libs/vr/libpdx/private/pdx/mock_message_reader.h b/libs/vr/libpdx/private/pdx/mock_message_reader.h deleted file mode 100644 index 85e96ef993..0000000000 --- a/libs/vr/libpdx/private/pdx/mock_message_reader.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef ANDROID_PDX_MOCK_MESSAGE_READER_H_ -#define ANDROID_PDX_MOCK_MESSAGE_READER_H_ - -#include <gmock/gmock.h> -#include <pdx/message_reader.h> - -namespace android { -namespace pdx { - -class MockInputResourceMapper : public InputResourceMapper { - public: - MOCK_METHOD2(GetFileHandle, bool(FileReference ref, LocalHandle* handle)); - MOCK_METHOD2(GetChannelHandle, - bool(ChannelReference ref, LocalChannelHandle* handle)); -}; - -class MockMessageReader : public MessageReader { - public: - MOCK_METHOD0(GetNextReadBufferSection, BufferSection()); - MOCK_METHOD1(ConsumeReadBufferSectionData, void(const void* new_start)); - MOCK_METHOD0(GetInputResourceMapper, InputResourceMapper*()); -}; - -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_MOCK_MESSAGE_READER_H_ diff --git a/libs/vr/libpdx/private/pdx/mock_message_writer.h b/libs/vr/libpdx/private/pdx/mock_message_writer.h deleted file mode 100644 index e06e5bbc2b..0000000000 --- a/libs/vr/libpdx/private/pdx/mock_message_writer.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef ANDROID_PDX_MOCK_MESSAGE_WRITER_H_ -#define ANDROID_PDX_MOCK_MESSAGE_WRITER_H_ - -#include <gmock/gmock.h> -#include <pdx/message_writer.h> - -namespace android { -namespace pdx { - -class MockOutputResourceMapper : public OutputResourceMapper { - public: - MOCK_METHOD1(PushFileHandle, - Status<FileReference>(const LocalHandle& handle)); - MOCK_METHOD1(PushFileHandle, - Status<FileReference>(const BorrowedHandle& handle)); - MOCK_METHOD1(PushFileHandle, - Status<FileReference>(const RemoteHandle& handle)); - MOCK_METHOD1(PushChannelHandle, - Status<ChannelReference>(const LocalChannelHandle& handle)); - MOCK_METHOD1(PushChannelHandle, - Status<ChannelReference>(const BorrowedChannelHandle& handle)); - MOCK_METHOD1(PushChannelHandle, - Status<ChannelReference>(const RemoteChannelHandle& handle)); -}; - -class MockMessageWriter : public MessageWriter { - public: - MOCK_METHOD1(GetNextWriteBufferSection, void*(size_t size)); - MOCK_METHOD0(GetOutputResourceMapper, OutputResourceMapper*()); -}; - -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_MOCK_MESSAGE_WRITER_H_ diff --git a/libs/vr/libpdx/private/pdx/mock_service_endpoint.h b/libs/vr/libpdx/private/pdx/mock_service_endpoint.h deleted file mode 100644 index 7f829e70d0..0000000000 --- a/libs/vr/libpdx/private/pdx/mock_service_endpoint.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef ANDROID_PDX_MOCK_ENDPOINT_H_ -#define ANDROID_PDX_MOCK_ENDPOINT_H_ - -#include <gmock/gmock.h> -#include <pdx/service_endpoint.h> - -namespace android { -namespace pdx { - -class MockEndpoint : public Endpoint { - public: - MOCK_CONST_METHOD0(GetIpcTag, uint32_t()); - MOCK_METHOD1(SetService, Status<void>(Service* service)); - MOCK_METHOD2(SetChannel, Status<void>(int channel_id, Channel* channel)); - MOCK_METHOD1(CloseChannel, Status<void>(int channel_id)); - MOCK_METHOD3(ModifyChannelEvents, - Status<void>(int channel_id, int clear_mask, int set_mask)); - MOCK_METHOD4(PushChannel, - Status<RemoteChannelHandle>(Message* message, int flags, - Channel* channel, int* channel_id)); - MOCK_METHOD3(CheckChannel, - Status<int>(const Message* message, ChannelReference ref, - Channel** channel)); - MOCK_METHOD1(MessageReceive, Status<void>(Message* message)); - MOCK_METHOD2(MessageReply, Status<void>(Message* message, int return_code)); - MOCK_METHOD2(MessageReplyFd, - Status<void>(Message* message, unsigned int push_fd)); - MOCK_METHOD2(MessageReplyChannelHandle, - Status<void>(Message* message, - const LocalChannelHandle& handle)); - MOCK_METHOD2(MessageReplyChannelHandle, - Status<void>(Message* message, - const BorrowedChannelHandle& handle)); - MOCK_METHOD2(MessageReplyChannelHandle, - Status<void>(Message* message, - const RemoteChannelHandle& handle)); - MOCK_METHOD3(ReadMessageData, - Status<size_t>(Message* message, const iovec* vector, - size_t vector_length)); - MOCK_METHOD3(WriteMessageData, - Status<size_t>(Message* message, const iovec* vector, - size_t vector_length)); - MOCK_METHOD2(PushFileHandle, - Status<FileReference>(Message* message, - const LocalHandle& handle)); - MOCK_METHOD2(PushFileHandle, - Status<FileReference>(Message* message, - const BorrowedHandle& handle)); - MOCK_METHOD2(PushFileHandle, - Status<FileReference>(Message* message, - const RemoteHandle& handle)); - MOCK_METHOD2(PushChannelHandle, - Status<ChannelReference>(Message* message, - const LocalChannelHandle& handle)); - MOCK_METHOD2(PushChannelHandle, - Status<ChannelReference>(Message* message, - const BorrowedChannelHandle& handle)); - MOCK_METHOD2(PushChannelHandle, - Status<ChannelReference>(Message* message, - const RemoteChannelHandle& handle)); - MOCK_CONST_METHOD2(GetFileHandle, - LocalHandle(Message* message, FileReference ref)); - MOCK_CONST_METHOD2(GetChannelHandle, - LocalChannelHandle(Message* message, - ChannelReference ref)); - MOCK_METHOD0(AllocateMessageState, void*()); - MOCK_METHOD1(FreeMessageState, void(void* state)); - MOCK_METHOD0(Cancel, Status<void>()); - MOCK_CONST_METHOD0(epoll_fd, int()); -}; - -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_MOCK_ENDPOINT_H_ diff --git a/libs/vr/libpdx/private/pdx/rpc/argument_encoder.h b/libs/vr/libpdx/private/pdx/rpc/argument_encoder.h deleted file mode 100644 index e0062845a5..0000000000 --- a/libs/vr/libpdx/private/pdx/rpc/argument_encoder.h +++ /dev/null @@ -1,184 +0,0 @@ -#ifndef ANDROID_PDX_RPC_ARGUMENT_ENCODER_H_ -#define ANDROID_PDX_RPC_ARGUMENT_ENCODER_H_ - -#include <cstdint> -#include <tuple> -#include <type_traits> - -#include <pdx/rpc/serialization.h> -#include <pdx/service.h> - -namespace android { -namespace pdx { -namespace rpc { - -// Provides automatic serialization of argument lists and return -// values by analyzing the supplied function signature types. -// Examples: -// ArgumentEncoder<int(int, float)> encoder(writer); -// encoder.EncodeArguments(1, 1.0); - -template <typename T> -class ArgumentEncoder; - -// Specialization of ArgumentEncoder for void return types. -template <typename... Args> -class ArgumentEncoder<void(Args...)> { - public: - explicit ArgumentEncoder(MessageWriter* writer) : writer_{writer} {} - - // Serializes the arguments as a tuple. - void EncodeArguments(Args... args) { - Serialize(std::forward_as_tuple(args...), writer_); - } - - private: - MessageWriter* writer_; -}; - -// Specialization of ArgumentEncoder for non-void return types. -template <typename Return, typename... Args> -class ArgumentEncoder<Return(Args...)> { - public: - // Simplified types with reference and cv removed. - using ReturnType = typename std::decay<Return>::type; - - explicit ArgumentEncoder(MessageWriter* writer) : writer_{writer} {} - - // Serializes the arguments as a tuple. - void EncodeArguments(Args... args) { - Serialize(std::forward_as_tuple(args...), writer_); - } - - // Serializes the return value for rvalue references. - void EncodeReturn(const ReturnType& return_value) { - Serialize(return_value, writer_); - } - - private: - MessageWriter* writer_; -}; - -// Utility to build an ArgumentEncoder from a function pointer and a message -// writer. -template <typename Return, typename... Args> -inline ArgumentEncoder<Return(Args...)> MakeArgumentEncoder( - Return (*)(Args...), MessageWriter* writer) { - return ArgumentEncoder<Return(Args...)>(writer); -} - -// Utility to build an ArgumentEncoder from a method pointer and a message -// writer. -template <typename Class, typename Return, typename... Args> -inline ArgumentEncoder<Return(Args...)> MakeArgumentEncoder( - Return (Class::*)(Args...), MessageWriter* writer) { - return ArgumentEncoder<Return(Args...)>(writer); -} - -// Utility to build an ArgumentEncoder from a const method pointer and a -// message writer. -template <typename Class, typename Return, typename... Args> -inline ArgumentEncoder<Return(Args...)> MakeArgumentEncoder( - Return (Class::*)(Args...) const, MessageWriter* writer) { - return ArgumentEncoder<Return(Args...)>(writer); -} - -// Utility to build an ArgumentEncoder from a function type and a message -// writer. -template <typename Signature> -inline ArgumentEncoder<Signature> MakeArgumentEncoder(MessageWriter* writer) { - return ArgumentEncoder<Signature>(writer); -} - -////////////////////////////////////////////////////////////////////////////// -// Provides automatic deserialization of argument lists and return -// values by analyzing the supplied function signature types. -// Examples: -// auto decoder = MakeArgumentDecoder<std::string(void)>(reader); -// ErrorType error = decoder.DecodeReturn(&return_value); - -template <typename T> -class ArgumentDecoder; - -// Specialization of ArgumentDecoder for void return types. -template <typename... Args> -class ArgumentDecoder<void(Args...)> { - public: - // Simplified types with reference and cv removed. - using ArgsTupleType = std::tuple<typename std::decay<Args>::type...>; - - explicit ArgumentDecoder(MessageReader* reader) : reader_{reader} {} - - // Deserializes arguments into a tuple. - ArgsTupleType DecodeArguments(ErrorType* error) { - ArgsTupleType value; - *error = Deserialize(&value, reader_); - return value; - } - - private: - MessageReader* reader_; -}; - -// Specialization of ArgumentDecoder for non-void return types. -template <typename Return, typename... Args> -class ArgumentDecoder<Return(Args...)> { - public: - // Simplified types with reference and cv removed. - using ArgsTupleType = std::tuple<typename std::decay<Args>::type...>; - using ReturnType = typename std::decay<Return>::type; - - explicit ArgumentDecoder(MessageReader* reader) : reader_{reader} {} - - // Deserializes arguments into a tuple. - ArgsTupleType DecodeArguments(ErrorType* error) { - ArgsTupleType value; - *error = Deserialize(&value, reader_); - return value; - } - - // Deserializes the return value. - ErrorType DecodeReturn(ReturnType* value) { - return Deserialize(value, reader_); - } - - private: - MessageReader* reader_; -}; - -// Utility to build an ArgumentDecoder from a function pointer and a message -// reader. -template <typename Return, typename... Args> -inline ArgumentDecoder<Return(Args...)> MakeArgumentDecoder( - Return (*)(Args...), MessageReader* reader) { - return ArgumentDecoder<Return(Args...)>(reader); -} - -// Utility to build an ArgumentDecoder from a method pointer and a message -// reader. -template <typename Class, typename Return, typename... Args> -inline ArgumentDecoder<Return(Args...)> MakeArgumentDecoder( - Return (Class::*)(Args...), MessageReader* reader) { - return ArgumentDecoder<Return(Args...)>(reader); -} - -// Utility to build an ArgumentDecoder from a const method pointer and a -// message reader. -template <typename Class, typename Return, typename... Args> -inline ArgumentDecoder<Return(Args...)> MakeArgumentDecoder( - Return (Class::*)(Args...) const, MessageReader* reader) { - return ArgumentDecoder<Return(Args...)>(reader); -} - -// Utility to build an ArgumentDecoder from a function type and a message -// reader. -template <typename Signature> -inline ArgumentDecoder<Signature> MakeArgumentDecoder(MessageReader* reader) { - return ArgumentDecoder<Signature>(reader); -} - -} // namespace rpc -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_RPC_ARGUMENT_ENCODER_H_ diff --git a/libs/vr/libpdx/private/pdx/rpc/array_wrapper.h b/libs/vr/libpdx/private/pdx/rpc/array_wrapper.h deleted file mode 100644 index d835c57a44..0000000000 --- a/libs/vr/libpdx/private/pdx/rpc/array_wrapper.h +++ /dev/null @@ -1,111 +0,0 @@ -#ifndef ANDROID_PDX_RPC_ARRAY_WRAPPER_H_ -#define ANDROID_PDX_RPC_ARRAY_WRAPPER_H_ - -#include <cstddef> -#include <memory> -#include <type_traits> -#include <vector> - -namespace android { -namespace pdx { -namespace rpc { - -// Wrapper class for C array buffers, providing an interface suitable for -// SerializeObject and DeserializeObject. This class serializes to the same -// format as std::vector, and may be substituted for std::vector during -// serialization and deserialization. This substitution makes handling of C -// arrays more efficient by avoiding unnecessary copies when remote method -// signatures specify std::vector arguments or return values. -template <typename T> -class ArrayWrapper { - public: - // Define types in the style of STL containers to support STL operators. - typedef T value_type; - typedef std::size_t size_type; - typedef T& reference; - typedef const T& const_reference; - typedef T* pointer; - typedef const T* const_pointer; - - ArrayWrapper() : buffer_(nullptr), capacity_(0), end_(0) {} - - ArrayWrapper(pointer buffer, size_type capacity, size_type size) - : buffer_(&buffer[0]), - capacity_(capacity), - end_(capacity < size ? capacity : size) {} - - ArrayWrapper(pointer buffer, size_type size) - : ArrayWrapper(buffer, size, size) {} - - ArrayWrapper(const ArrayWrapper& other) { *this = other; } - - ArrayWrapper(ArrayWrapper&& other) noexcept { *this = std::move(other); } - - ArrayWrapper& operator=(const ArrayWrapper& other) { - if (&other == this) { - return *this; - } else { - buffer_ = other.buffer_; - capacity_ = other.capacity_; - end_ = other.end_; - } - - return *this; - } - - ArrayWrapper& operator=(ArrayWrapper&& other) noexcept { - if (&other == this) { - return *this; - } else { - buffer_ = other.buffer_; - capacity_ = other.capacity_; - end_ = other.end_; - other.buffer_ = nullptr; - other.capacity_ = 0; - other.end_ = 0; - } - - return *this; - } - - pointer data() { return buffer_; } - const_pointer data() const { return buffer_; } - - pointer begin() { return &buffer_[0]; } - pointer end() { return &buffer_[end_]; } - const_pointer begin() const { return &buffer_[0]; } - const_pointer end() const { return &buffer_[end_]; } - - size_type size() const { return end_; } - size_type max_size() const { return capacity_; } - size_type capacity() const { return capacity_; } - - // Moves the end marker to |size|, clamping the end marker to the max capacity - // of the underlying array. This method does not change the size of the - // underlying array. - void resize(size_type size) { - if (size <= capacity_) - end_ = size; - else - end_ = capacity_; - } - - reference operator[](size_type pos) { return buffer_[pos]; } - const_reference operator[](size_type pos) const { return buffer_[pos]; } - - private: - pointer buffer_; - size_type capacity_; - size_type end_; -}; - -template <typename T, typename SizeType = std::size_t> -ArrayWrapper<T> WrapArray(T* buffer, SizeType size) { - return ArrayWrapper<T>(buffer, size); -} - -} // namespace rpc -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_RPC_ARRAY_WRAPPER_H_ diff --git a/libs/vr/libpdx/private/pdx/rpc/buffer_wrapper.h b/libs/vr/libpdx/private/pdx/rpc/buffer_wrapper.h deleted file mode 100644 index 43184ddd29..0000000000 --- a/libs/vr/libpdx/private/pdx/rpc/buffer_wrapper.h +++ /dev/null @@ -1,177 +0,0 @@ -#ifndef ANDROID_PDX_RPC_BUFFER_WRAPPER_H_ -#define ANDROID_PDX_RPC_BUFFER_WRAPPER_H_ - -#include <cstddef> -#include <memory> -#include <type_traits> -#include <vector> - -namespace android { -namespace pdx { -namespace rpc { - -// Wrapper class for buffers, providing an interface suitable for -// SerializeObject and DeserializeObject. This class supports serialization of -// buffers as raw bytes. -template <typename T> -class BufferWrapper; - -template <typename T> -class BufferWrapper<T*> { - public: - // Define types in the style of STL containers to support STL operators. - typedef T value_type; - typedef std::size_t size_type; - typedef T& reference; - typedef const T& const_reference; - typedef T* pointer; - typedef const T* const_pointer; - - BufferWrapper() : buffer_(nullptr), capacity_(0), end_(0) {} - - BufferWrapper(pointer buffer, size_type capacity, size_type size) - : buffer_(&buffer[0]), - capacity_(capacity), - end_(capacity < size ? capacity : size) {} - - BufferWrapper(pointer buffer, size_type size) - : BufferWrapper(buffer, size, size) {} - - BufferWrapper(const BufferWrapper& other) { *this = other; } - - BufferWrapper(BufferWrapper&& other) noexcept { *this = std::move(other); } - - BufferWrapper& operator=(const BufferWrapper& other) { - if (&other == this) { - return *this; - } else { - buffer_ = other.buffer_; - capacity_ = other.capacity_; - end_ = other.end_; - } - - return *this; - } - - BufferWrapper& operator=(BufferWrapper&& other) noexcept { - if (&other == this) { - return *this; - } else { - buffer_ = other.buffer_; - capacity_ = other.capacity_; - end_ = other.end_; - other.buffer_ = nullptr; - other.capacity_ = 0; - other.end_ = 0; - } - - return *this; - } - - pointer data() { return buffer_; } - const_pointer data() const { return buffer_; } - - pointer begin() { return &buffer_[0]; } - pointer end() { return &buffer_[end_]; } - const_pointer begin() const { return &buffer_[0]; } - const_pointer end() const { return &buffer_[end_]; } - - size_type size() const { return end_; } - size_type max_size() const { return capacity_; } - size_type capacity() const { return capacity_; } - - void resize(size_type size) { - if (size <= capacity_) - end_ = size; - else - end_ = capacity_; - } - - reference operator[](size_type pos) { return buffer_[pos]; } - const_reference operator[](size_type pos) const { return buffer_[pos]; } - - private: - pointer buffer_; - size_type capacity_; - size_type end_; -}; - -template <typename T, typename Allocator> -class BufferWrapper<std::vector<T, Allocator>> { - public: - using BufferType = typename std::vector<T, Allocator>; - using value_type = typename BufferType::value_type; - using size_type = typename BufferType::size_type; - using reference = typename BufferType::reference; - using const_reference = typename BufferType::const_reference; - using pointer = typename BufferType::pointer; - using const_pointer = typename BufferType::const_pointer; - using iterator = typename BufferType::iterator; - using const_iterator = typename BufferType::const_iterator; - - BufferWrapper() {} - explicit BufferWrapper(const BufferType& buffer) : buffer_(buffer) {} - BufferWrapper(const BufferType& buffer, const Allocator& allocator) - : buffer_(buffer, allocator) {} - explicit BufferWrapper(BufferType&& buffer) : buffer_(std::move(buffer)) {} - BufferWrapper(BufferType&& buffer, const Allocator& allocator) - : buffer_(std::move(buffer), allocator) {} - BufferWrapper(const BufferWrapper&) = default; - BufferWrapper(BufferWrapper&&) noexcept = default; - BufferWrapper& operator=(const BufferWrapper&) = default; - BufferWrapper& operator=(BufferWrapper&&) noexcept = default; - - pointer data() { return buffer_.data(); } - const_pointer data() const { return buffer_.data(); } - - iterator begin() { return buffer_.begin(); } - iterator end() { return buffer_.end(); } - const_iterator begin() const { return buffer_.begin(); } - const_iterator end() const { return buffer_.end(); } - - size_type size() const { return buffer_.size(); } - size_type max_size() const { return buffer_.capacity(); } - size_type capacity() const { return buffer_.capacity(); } - - void resize(size_type size) { buffer_.resize(size); } - void reserve(size_type size) { buffer_.reserve(size); } - - reference operator[](size_type pos) { return buffer_[pos]; } - const_reference operator[](size_type pos) const { return buffer_[pos]; } - - BufferType& buffer() { return buffer_; } - const BufferType& buffer() const { return buffer_; } - - private: - BufferType buffer_; -}; - -template <typename T, typename SizeType = std::size_t> -BufferWrapper<T*> WrapBuffer(T* buffer, SizeType size) { - return BufferWrapper<T*>(buffer, size); -} - -template <typename SizeType = std::size_t> -BufferWrapper<std::uint8_t*> WrapBuffer(void* buffer, SizeType size) { - return BufferWrapper<std::uint8_t*>(static_cast<std::uint8_t*>(buffer), size); -} - -template <typename SizeType = std::size_t> -BufferWrapper<const std::uint8_t*> WrapBuffer(const void* buffer, - SizeType size) { - return BufferWrapper<const std::uint8_t*>( - static_cast<const std::uint8_t*>(buffer), size); -} - -template <typename T, typename Allocator = std::allocator<T>> -BufferWrapper<std::vector<T, Allocator>> WrapBuffer( - std::vector<T, Allocator>&& buffer) { - return BufferWrapper<std::vector<T, Allocator>>( - std::forward<std::vector<T, Allocator>>(buffer)); -} - -} // namespace rpc -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_RPC_BUFFER_WRAPPER_H_ diff --git a/libs/vr/libpdx/private/pdx/rpc/copy_cv_reference.h b/libs/vr/libpdx/private/pdx/rpc/copy_cv_reference.h deleted file mode 100644 index 5ce34f8f9c..0000000000 --- a/libs/vr/libpdx/private/pdx/rpc/copy_cv_reference.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef ANDROID_PDX_RPC_COPY_CV_REFERENCE_H_ -#define ANDROID_PDX_RPC_COPY_CV_REFERENCE_H_ - -#include <type_traits> - -namespace android { -namespace pdx { -namespace rpc { - -// Copies const, void, and reference qualifiers from type T to type U, such that -// the new type U' carries the same cv-reference qualifiers as T, with the same -// underlying type as U. -template <typename T, typename U> -class CopyCVReference { - private: - using R = typename std::remove_reference<T>::type; - using U1 = - typename std::conditional<std::is_const<R>::value, - typename std::add_const<U>::type, U>::type; - using U2 = - typename std::conditional<std::is_volatile<R>::value, - typename std::add_volatile<U1>::type, U1>::type; - using U3 = - typename std::conditional<std::is_lvalue_reference<T>::value, - typename std::add_lvalue_reference<U2>::type, - U2>::type; - using U4 = - typename std::conditional<std::is_rvalue_reference<T>::value, - typename std::add_rvalue_reference<U3>::type, - U3>::type; - - public: - using Type = U4; -}; - -template <typename T, typename U> -using CopyCVReferenceType = typename CopyCVReference<T, U>::Type; - -} // namespace rpc -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_RPC_COPY_CV_REFERENCE_H_ diff --git a/libs/vr/libpdx/private/pdx/rpc/default_initialization_allocator.h b/libs/vr/libpdx/private/pdx/rpc/default_initialization_allocator.h deleted file mode 100644 index b6e298084e..0000000000 --- a/libs/vr/libpdx/private/pdx/rpc/default_initialization_allocator.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef ANDROID_PDX_RPC_DEFAULT_INITIALIZATION_ALLOCATOR_H_ -#define ANDROID_PDX_RPC_DEFAULT_INITIALIZATION_ALLOCATOR_H_ - -#include <memory> - -namespace android { -namespace pdx { -namespace rpc { - -// Allocator adaptor that interposes construct() calls to convert value -// initialization into default initialization. All standard containers -// value-initialize their elements when constructed with a single size_type -// argument or when grown by a call to resize. This allocator avoids potentially -// costly value-initialization in these situations for value types that are -// default constructible. As a consequence, elements of non-class types are left -// uninitialized; this is desirable when using std::vector as a resizable -// buffer, for example. -template <typename T, typename Allocator = std::allocator<T>> -class DefaultInitializationAllocator : public Allocator { - typedef std::allocator_traits<Allocator> AllocatorTraits; - - public: - template <typename U> - struct rebind { - using other = DefaultInitializationAllocator< - U, typename AllocatorTraits::template rebind_alloc<U>>; - }; - - using Allocator::Allocator; - - template <typename U> - void construct(U* pointer) noexcept( - std::is_nothrow_default_constructible<U>::value) { - ::new (static_cast<void*>(pointer)) U; - } - template <typename U, typename... Args> - void construct(U* pointer, Args&&... args) { - AllocatorTraits::construct(static_cast<Allocator&>(*this), pointer, - std::forward<Args>(args)...); - } -}; - -} // namespace rpc -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_RPC_DEFAULT_INITIALIZATION_ALLOCATOR_H_ diff --git a/libs/vr/libpdx/private/pdx/rpc/encoding.h b/libs/vr/libpdx/private/pdx/rpc/encoding.h deleted file mode 100644 index f51d807f5b..0000000000 --- a/libs/vr/libpdx/private/pdx/rpc/encoding.h +++ /dev/null @@ -1,616 +0,0 @@ -#ifndef ANDROID_PDX_RPC_ENCODING_H_ -#define ANDROID_PDX_RPC_ENCODING_H_ - -#include <array> -#include <cstdint> -#include <cstring> -#include <map> -#include <numeric> -#include <string> -#include <tuple> -#include <unordered_map> -#include <vector> - -#include <pdx/channel_handle.h> -#include <pdx/file_handle.h> - -#include "array_wrapper.h" -#include "buffer_wrapper.h" -#include "string_wrapper.h" -#include "variant.h" - -namespace android { -namespace pdx { -namespace rpc { - -// This library uses a subset, or profile, of MessagePack (http://msgpack.org) -// to encode supported data types during serialization and to verify the -// expected data types during deserialization. One notable deviation from the -// MessagePack specification is that little-endian byte order is used for -// multi-byte numeric types to avoid unnecessary conversion on nearly all -// relevant architectures. -// -// Some data types, integers for example, support multiple encoding strategies. -// This library attempts to optimize for space based on the value of such types. -// However, during decode all valid encodings for a given type are accepted. - -// Prefix byte for type encodings. This is the complete list of prefix bytes -// from the MessagePack specification, even though not all types are used by -// this library. -enum EncodingPrefix { - ENCODING_TYPE_POSITIVE_FIXINT = 0x00, - ENCODING_TYPE_POSITIVE_FIXINT_MIN = 0x00, - ENCODING_TYPE_POSITIVE_FIXINT_MAX = 0x7f, - ENCODING_TYPE_POSITIVE_FIXINT_MASK = 0x7f, - ENCODING_TYPE_FIXMAP = 0x80, - ENCODING_TYPE_FIXMAP_MIN = 0x80, - ENCODING_TYPE_FIXMAP_MAX = 0x8f, - ENCODING_TYPE_FIXMAP_MASK = 0x0f, - ENCODING_TYPE_FIXARRAY = 0x90, - ENCODING_TYPE_FIXARRAY_MIN = 0x90, - ENCODING_TYPE_FIXARRAY_MAX = 0x9f, - ENCODING_TYPE_FIXARRAY_MASK = 0x0f, - ENCODING_TYPE_FIXSTR = 0xa0, - ENCODING_TYPE_FIXSTR_MIN = 0xa0, - ENCODING_TYPE_FIXSTR_MAX = 0xbf, - ENCODING_TYPE_FIXSTR_MASK = 0x1f, - ENCODING_TYPE_NIL = 0xc0, - ENCODING_TYPE_RESERVED = 0xc1, - ENCODING_TYPE_FALSE = 0xc2, - ENCODING_TYPE_TRUE = 0xc3, - ENCODING_TYPE_BIN8 = 0xc4, - ENCODING_TYPE_BIN16 = 0xc5, - ENCODING_TYPE_BIN32 = 0xc6, - ENCODING_TYPE_EXT8 = 0xc7, - ENCODING_TYPE_EXT16 = 0xc8, - ENCODING_TYPE_EXT32 = 0xc9, - ENCODING_TYPE_FLOAT32 = 0xca, - ENCODING_TYPE_FLOAT64 = 0xcb, - ENCODING_TYPE_UINT8 = 0xcc, - ENCODING_TYPE_UINT16 = 0xcd, - ENCODING_TYPE_UINT32 = 0xce, - ENCODING_TYPE_UINT64 = 0xcf, - ENCODING_TYPE_INT8 = 0xd0, - ENCODING_TYPE_INT16 = 0xd1, - ENCODING_TYPE_INT32 = 0xd2, - ENCODING_TYPE_INT64 = 0xd3, - ENCODING_TYPE_FIXEXT1 = 0xd4, - ENCODING_TYPE_FIXEXT2 = 0xd5, - ENCODING_TYPE_FIXEXT4 = 0xd6, - ENCODING_TYPE_FIXEXT8 = 0xd7, - ENCODING_TYPE_FIXEXT16 = 0xd8, - ENCODING_TYPE_STR8 = 0xd9, - ENCODING_TYPE_STR16 = 0xda, - ENCODING_TYPE_STR32 = 0xdb, - ENCODING_TYPE_ARRAY16 = 0xdc, - ENCODING_TYPE_ARRAY32 = 0xdd, - ENCODING_TYPE_MAP16 = 0xde, - ENCODING_TYPE_MAP32 = 0xdf, - ENCODING_TYPE_NEGATIVE_FIXINT = 0xe0, - ENCODING_TYPE_NEGATIVE_FIXINT_MIN = 0xe0, - ENCODING_TYPE_NEGATIVE_FIXINT_MAX = 0xff, -}; - -// Base encoding classes grouping multi-strategy encodings. -enum EncodingClass { - ENCODING_CLASS_BOOL, - ENCODING_CLASS_NIL, - ENCODING_CLASS_INT, - ENCODING_CLASS_UINT, - ENCODING_CLASS_FLOAT, - ENCODING_CLASS_ARRAY, - ENCODING_CLASS_MAP, - ENCODING_CLASS_STRING, - ENCODING_CLASS_BINARY, - ENCODING_CLASS_EXTENSION, -}; - -// Encoding prefixes are unsigned bytes. -typedef std::uint8_t EncodingType; - -// Extension encoding types defined by this library. -enum EncodingExtType : int8_t { - ENCODING_EXT_TYPE_FILE_DESCRIPTOR, - ENCODING_EXT_TYPE_CHANNEL_HANDLE, -}; - -// Encoding predicates. Determines whether the given encoding is of a specific -// type. -inline constexpr bool IsFixintEncoding(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_POSITIVE_FIXINT_MIN ... ENCODING_TYPE_POSITIVE_FIXINT_MAX: - case ENCODING_TYPE_NEGATIVE_FIXINT_MIN ... ENCODING_TYPE_NEGATIVE_FIXINT_MAX: - return true; - default: - return false; - } -} - -inline constexpr bool IsUnsignedFixintEncoding(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_POSITIVE_FIXINT_MIN ... ENCODING_TYPE_POSITIVE_FIXINT_MAX: - return true; - default: - return false; - } -} - -inline constexpr bool IsInt8Encoding(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_POSITIVE_FIXINT_MIN ... ENCODING_TYPE_POSITIVE_FIXINT_MAX: - case ENCODING_TYPE_NEGATIVE_FIXINT_MIN ... ENCODING_TYPE_NEGATIVE_FIXINT_MAX: - case ENCODING_TYPE_INT8: - return true; - default: - return false; - } -} - -inline constexpr bool IsUInt8Encoding(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_POSITIVE_FIXINT_MIN ... ENCODING_TYPE_POSITIVE_FIXINT_MAX: - case ENCODING_TYPE_UINT8: - return true; - default: - return false; - } -} - -inline constexpr bool IsInt16Encoding(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_POSITIVE_FIXINT_MIN ... ENCODING_TYPE_POSITIVE_FIXINT_MAX: - case ENCODING_TYPE_NEGATIVE_FIXINT_MIN ... ENCODING_TYPE_NEGATIVE_FIXINT_MAX: - case ENCODING_TYPE_INT8: - case ENCODING_TYPE_INT16: - return true; - default: - return false; - } -} - -inline constexpr bool IsUInt16Encoding(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_POSITIVE_FIXINT_MIN ... ENCODING_TYPE_POSITIVE_FIXINT_MAX: - case ENCODING_TYPE_UINT8: - case ENCODING_TYPE_UINT16: - return true; - default: - return false; - } -} - -inline constexpr bool IsInt32Encoding(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_POSITIVE_FIXINT_MIN ... ENCODING_TYPE_POSITIVE_FIXINT_MAX: - case ENCODING_TYPE_NEGATIVE_FIXINT_MIN ... ENCODING_TYPE_NEGATIVE_FIXINT_MAX: - case ENCODING_TYPE_INT8: - case ENCODING_TYPE_INT16: - case ENCODING_TYPE_INT32: - return true; - default: - return false; - } -} - -inline constexpr bool IsUInt32Encoding(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_POSITIVE_FIXINT_MIN ... ENCODING_TYPE_POSITIVE_FIXINT_MAX: - case ENCODING_TYPE_UINT8: - case ENCODING_TYPE_UINT16: - case ENCODING_TYPE_UINT32: - return true; - default: - return false; - } -} - -inline constexpr bool IsInt64Encoding(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_POSITIVE_FIXINT_MIN ... ENCODING_TYPE_POSITIVE_FIXINT_MAX: - case ENCODING_TYPE_NEGATIVE_FIXINT_MIN ... ENCODING_TYPE_NEGATIVE_FIXINT_MAX: - case ENCODING_TYPE_INT8: - case ENCODING_TYPE_INT16: - case ENCODING_TYPE_INT32: - case ENCODING_TYPE_INT64: - return true; - default: - return false; - } -} - -inline constexpr bool IsUInt64Encoding(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_POSITIVE_FIXINT_MIN ... ENCODING_TYPE_POSITIVE_FIXINT_MAX: - case ENCODING_TYPE_UINT8: - case ENCODING_TYPE_UINT16: - case ENCODING_TYPE_UINT32: - case ENCODING_TYPE_UINT64: - return true; - default: - return false; - } -} - -inline constexpr bool IsFixmapEncoding(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_FIXMAP_MIN ... ENCODING_TYPE_FIXMAP_MAX: - return true; - default: - return false; - } -} - -inline constexpr bool IsFixarrayEncoding(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_FIXARRAY_MIN ... ENCODING_TYPE_FIXARRAY_MAX: - return true; - default: - return false; - } -} - -inline constexpr bool IsFixstrEncoding(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_FIXSTR_MIN ... ENCODING_TYPE_FIXSTR_MAX: - return true; - default: - return false; - } -} - -inline constexpr bool IsFixextEncoding(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_FIXEXT1: - case ENCODING_TYPE_FIXEXT2: - case ENCODING_TYPE_FIXEXT4: - case ENCODING_TYPE_FIXEXT8: - case ENCODING_TYPE_FIXEXT16: - return true; - default: - return false; - } -} - -inline constexpr bool IsFloat32Encoding(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_FLOAT32: - return true; - default: - return false; - } -} - -inline constexpr bool IsFloat64Encoding(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_FLOAT32: - case ENCODING_TYPE_FLOAT64: - return true; - default: - return false; - } -} - -inline constexpr bool IsBoolEncoding(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_FALSE: - case ENCODING_TYPE_TRUE: - return true; - default: - return false; - } -} - -inline constexpr std::size_t GetFixstrSize(EncodingType encoding) { - return encoding & ENCODING_TYPE_FIXSTR_MASK; -} - -inline constexpr std::size_t GetFixarraySize(EncodingType encoding) { - return encoding & ENCODING_TYPE_FIXARRAY_MASK; -} - -inline constexpr std::size_t GetFixmapSize(EncodingType encoding) { - return encoding & ENCODING_TYPE_FIXMAP_MASK; -} - -inline constexpr std::size_t GetFixextSize(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_FIXEXT1: - return 1; - case ENCODING_TYPE_FIXEXT2: - return 2; - case ENCODING_TYPE_FIXEXT4: - return 4; - case ENCODING_TYPE_FIXEXT8: - return 8; - case ENCODING_TYPE_FIXEXT16: - return 16; - default: - return 0; // Invalid fixext size. - } -} - -// Gets the size of the encoding in bytes, not including external payload data. -inline constexpr std::size_t GetEncodingSize(EncodingType encoding) { - switch (encoding) { - // Encoding is fully contained within the type value. - case ENCODING_TYPE_POSITIVE_FIXINT_MIN ... ENCODING_TYPE_POSITIVE_FIXINT_MAX: - case ENCODING_TYPE_NEGATIVE_FIXINT_MIN ... ENCODING_TYPE_NEGATIVE_FIXINT_MAX: - case ENCODING_TYPE_FIXMAP_MIN ... ENCODING_TYPE_FIXMAP_MAX: - case ENCODING_TYPE_FIXARRAY_MIN ... ENCODING_TYPE_FIXARRAY_MAX: - case ENCODING_TYPE_FIXSTR_MIN ... ENCODING_TYPE_FIXSTR_MAX: - case ENCODING_TYPE_NIL: - case ENCODING_TYPE_RESERVED: - case ENCODING_TYPE_FALSE: - case ENCODING_TYPE_TRUE: - return 1; - - // Encoding type followed by one-byte size or immediate value. - case ENCODING_TYPE_BIN8: - case ENCODING_TYPE_EXT8: - case ENCODING_TYPE_UINT8: - case ENCODING_TYPE_INT8: - case ENCODING_TYPE_STR8: - // Encoding type followed by one-byte extension type. - case ENCODING_TYPE_FIXEXT1: - case ENCODING_TYPE_FIXEXT2: - case ENCODING_TYPE_FIXEXT4: - case ENCODING_TYPE_FIXEXT8: - case ENCODING_TYPE_FIXEXT16: - return 2; - - // Encoding type followed by two-byte size or immediate value. - case ENCODING_TYPE_BIN16: - case ENCODING_TYPE_EXT16: - case ENCODING_TYPE_UINT16: - case ENCODING_TYPE_INT16: - case ENCODING_TYPE_STR16: - case ENCODING_TYPE_ARRAY16: - case ENCODING_TYPE_MAP16: - return 3; - - // Encoding type followed by four-byte size or immediate value. - case ENCODING_TYPE_BIN32: - case ENCODING_TYPE_EXT32: - case ENCODING_TYPE_FLOAT32: - case ENCODING_TYPE_UINT32: - case ENCODING_TYPE_INT32: - case ENCODING_TYPE_STR32: - case ENCODING_TYPE_ARRAY32: - case ENCODING_TYPE_MAP32: - return 5; - - // Encoding type followed by eight-byte immediate value. - case ENCODING_TYPE_FLOAT64: - case ENCODING_TYPE_UINT64: - case ENCODING_TYPE_INT64: - return 9; - - default: - return 0; - } -} - -// Encoding for standard types. Each supported data type has an associated -// encoding or set of encodings. These functions determine the MessagePack -// encoding based on the data type, value, and size of their arguments. - -inline constexpr EncodingType EncodeArrayType(std::size_t size) { - if (size < (1U << 4)) - return ENCODING_TYPE_FIXARRAY | (size & ENCODING_TYPE_FIXARRAY_MASK); - else if (size < (1U << 16)) - return ENCODING_TYPE_ARRAY16; - else - return ENCODING_TYPE_ARRAY32; -} - -inline constexpr EncodingType EncodeMapType(std::size_t size) { - if (size < (1U << 4)) - return ENCODING_TYPE_FIXMAP | (size & ENCODING_TYPE_FIXMAP_MASK); - else if (size < (1U << 16)) - return ENCODING_TYPE_MAP16; - else - return ENCODING_TYPE_MAP32; -} - -inline constexpr EncodingType EncodeStringType(std::size_t size) { - if (size < (1U << 5)) - return ENCODING_TYPE_FIXSTR | (size & ENCODING_TYPE_FIXSTR_MASK); - else if (size < (1U << 8)) - return ENCODING_TYPE_STR8; - else if (size < (1U << 16)) - return ENCODING_TYPE_STR16; - else - return ENCODING_TYPE_STR32; -} - -inline constexpr EncodingType EncodeBinType(std::size_t size) { - if (size < (1U << 8)) - return ENCODING_TYPE_BIN8; - else if (size < (1U << 16)) - return ENCODING_TYPE_BIN16; - else - return ENCODING_TYPE_BIN32; -} - -inline EncodingType EncodeType(const EmptyVariant& /*empty*/) { - return ENCODING_TYPE_NIL; -} - -// Variant is encoded as a single-element map, with the type index as the key. -template <typename... Types> -inline EncodingType EncodeType(const Variant<Types...>& /*variant*/) { - return EncodeMapType(1); -} - -template <typename T> -inline constexpr EncodingType EncodeType(const StringWrapper<T>& value) { - return EncodeStringType(value.length()); -} - -inline constexpr EncodingType EncodeType(const std::string& value) { - return EncodeStringType(value.length()); -} - -template <typename T, std::size_t Size> -inline constexpr EncodingType EncodeType(const std::array<T, Size>& /*value*/) { - return EncodeArrayType(Size); -} - -template <typename T> -inline constexpr EncodingType EncodeType(const ArrayWrapper<T>& value) { - return EncodeArrayType(value.size()); -} - -template <typename T, typename Allocator> -inline constexpr EncodingType EncodeType( - const std::vector<T, Allocator>& value) { - return EncodeArrayType(value.size()); -} - -template <typename Key, typename T, typename Compare, typename Allocator> -inline constexpr EncodingType EncodeType( - const std::map<Key, T, Compare, Allocator>& value) { - return EncodeMapType(value.size()); -} - -template <typename Key, typename T, typename Hash, typename KeyEqual, - typename Allocator> -inline constexpr EncodingType EncodeType( - const std::unordered_map<Key, T, Hash, KeyEqual, Allocator>& value) { - return EncodeMapType(value.size()); -} - -template <typename T> -inline constexpr EncodingType EncodeType(const BufferWrapper<T>& value) { - // BIN size is in bytes. - return EncodeBinType(value.size() * - sizeof(typename BufferWrapper<T>::value_type)); -} - -template <typename T, typename U> -inline constexpr EncodingType EncodeType(const std::pair<T, U>& /*value*/) { - return EncodeArrayType(2); -} - -template <typename... T> -inline constexpr EncodingType EncodeType(const std::tuple<T...>& /*value*/) { - return EncodeArrayType(sizeof...(T)); -} - -// FileHandle is encoded as a FIXEXT2 with a type code for "FileDescriptor" -// and a signed 16-bit index into the pushed fd array. Empty file descriptor -// have an array index of -1. -template <FileHandleMode Mode> -inline constexpr EncodingType EncodeType(const FileHandle<Mode>& /*fd*/) { - return ENCODING_TYPE_FIXEXT2; -} - -// ChannelHandle is encoded as a FIXEXT4 with a type of -// ENCODING_EXT_TYPE_CHANNEL_HANDLE and a signed 32-bit value representing -// a client channel in a remote process. Empty handle has a value of -1. -template <ChannelHandleMode Mode> -inline constexpr EncodingType EncodeType( - const ChannelHandle<Mode>& /*handle*/) { - return ENCODING_TYPE_FIXEXT4; -} - -inline constexpr EncodingType EncodeType(const bool& value) { - return value ? ENCODING_TYPE_TRUE : ENCODING_TYPE_FALSE; -} - -// Type 'char' is a little bit special in that it is distinct from 'signed char' -// and 'unsigned char'. Treating it as an unsigned 8-bit value is safe for -// encoding purposes and nicely handles 7-bit ASCII encodings as FIXINT. -inline constexpr EncodingType EncodeType(const char& value) { - if (value < static_cast<char>(1 << 7)) - return value; - else - return ENCODING_TYPE_UINT8; -} - -inline constexpr EncodingType EncodeType(const uint8_t& value) { - if (value < (1U << 7)) - return value; - else - return ENCODING_TYPE_UINT8; -} -inline constexpr EncodingType EncodeType(const int8_t& value) { - if (value >= -32) - return value; - else - return ENCODING_TYPE_INT8; -} -inline constexpr EncodingType EncodeType(const uint16_t& value) { - if (value < (1U << 7)) - return static_cast<EncodingType>(value); - else if (value < (1U << 8)) - return ENCODING_TYPE_UINT8; - else - return ENCODING_TYPE_UINT16; -} -inline constexpr EncodingType EncodeType(const int16_t& value) { - if (value >= -32 && value <= 127) - return static_cast<EncodingType>(value); - else if (value >= -128 && value <= 127) - return ENCODING_TYPE_INT8; - else - return ENCODING_TYPE_INT16; -} -inline constexpr EncodingType EncodeType(const uint32_t& value) { - if (value < (1U << 7)) - return static_cast<EncodingType>(value); - else if (value < (1U << 8)) - return ENCODING_TYPE_UINT8; - else if (value < (1U << 16)) - return ENCODING_TYPE_UINT16; - else - return ENCODING_TYPE_UINT32; -} -inline constexpr EncodingType EncodeType(const int32_t& value) { - if (value >= -32 && value <= 127) - return static_cast<EncodingType>(value); - else if (value >= -128 && value <= 127) - return ENCODING_TYPE_INT8; - else if (value >= -32768 && value <= 32767) - return ENCODING_TYPE_INT16; - else - return ENCODING_TYPE_INT32; -} -inline constexpr EncodingType EncodeType(const uint64_t& value) { - if (value < (1ULL << 7)) - return static_cast<EncodingType>(value); - else if (value < (1ULL << 8)) - return ENCODING_TYPE_UINT8; - else if (value < (1ULL << 16)) - return ENCODING_TYPE_UINT16; - else if (value < (1ULL << 32)) - return ENCODING_TYPE_UINT32; - else - return ENCODING_TYPE_UINT64; -} -inline constexpr EncodingType EncodeType(const int64_t& value) { - if (value >= -32 && value <= 127) - return static_cast<EncodingType>(value); - else if (value >= -128 && value <= 127) // Effectively [-128, -32). - return ENCODING_TYPE_INT8; - else if (value >= -32768 && value <= 32767) - return ENCODING_TYPE_INT16; - else if (value >= -2147483648 && value <= 2147483647) - return ENCODING_TYPE_INT32; - else - return ENCODING_TYPE_INT64; -} - -inline constexpr EncodingType EncodeType(const float& /*value*/) { - return ENCODING_TYPE_FLOAT32; -} - -inline constexpr EncodingType EncodeType(const double& /*value*/) { - return ENCODING_TYPE_FLOAT64; -} - -} // namespace rpc -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_RPC_ENCODING_H_ diff --git a/libs/vr/libpdx/private/pdx/rpc/enumeration.h b/libs/vr/libpdx/private/pdx/rpc/enumeration.h deleted file mode 100644 index 7a35d31b22..0000000000 --- a/libs/vr/libpdx/private/pdx/rpc/enumeration.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef ANDROID_PDX_RPC_ENUMERATION_H_ -#define ANDROID_PDX_RPC_ENUMERATION_H_ - -#include <pdx/rpc/sequence.h> - -namespace android { -namespace pdx { -namespace rpc { - -// Utility for manipulating lists of types. Provides operations to lookup an -// element by type or index. - -namespace detail { - -// Helper type that captures type and index for each element of a type -// enumeration. -template <std::size_t I, typename T> -struct IndexedElement { - using Type = T; - static constexpr std::size_t Index = I; -}; - -// Helper type that captures an IndexSequence and corresponding list of types. -template <typename Is, typename... Ts> -struct ElementIndexer; - -// Partial specialization that generates an instantiation of IndexElement<I, T> -// for each element of a type enumeration using inheritance. Once a type -// enumeration is instantiated this way the compiler is able to deduce either I -// or T from the other using the method below. -template <std::size_t... Is, typename... Ts> -struct ElementIndexer<IndexSequence<Is...>, Ts...> : IndexedElement<Is, Ts>... { -}; - -// Helper function that causes the compiler to deduce an IndexedElement<I, T> -// given T. -template <typename T, std::size_t I> -static IndexedElement<I, T> SelectElementByType(IndexedElement<I, T>); - -// Helper function that causes the compiler to deduce an IndexedElement<I, T> -// given I. -template <std::size_t I, typename T> -static IndexedElement<I, T> SelectElementByIndex(IndexedElement<I, T>); - -} // namespace detail - -// Deduces the IndexedElement<I, T> given T and a type sequence Ts. This may be -// used to determine the index of T within Ts at compile time. -template <typename T, typename... Ts> -using ElementForType = decltype(detail::SelectElementByType<T>( - detail::ElementIndexer<typename IndexSequenceFor<Ts...>::type, Ts...>{})); - -// Deduces the IndexedElement<I, T> given I and a type sequence Ts. This may be -// used to determine the type of the element at index I within Ts at compile -// time. Tuple operations may also be used to accomplish the same task, however -// this implementation is provided here for symmetry. -template <std::size_t I, typename... Ts> -using ElementForIndex = decltype(detail::SelectElementByIndex<I>( - detail::ElementIndexer<typename IndexSequenceFor<Ts...>::type, Ts...>{})); - -} // namespace rpc -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_RPC_ENUMERATION_H_ diff --git a/libs/vr/libpdx/private/pdx/rpc/find_replace.h b/libs/vr/libpdx/private/pdx/rpc/find_replace.h deleted file mode 100644 index b4b086bd05..0000000000 --- a/libs/vr/libpdx/private/pdx/rpc/find_replace.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef ANDROID_PDX_RPC_FIND_REPLACE_H_ -#define ANDROID_PDX_RPC_FIND_REPLACE_H_ - -#include <type_traits> - -#include <pdx/rpc/copy_cv_reference.h> - -namespace android { -namespace pdx { -namespace rpc { - -// Utility class to capture types to find and replace. -template <typename Find, typename Replace> -struct FindReplace; - -template <typename T, typename U> -using IsSameBaseType = typename std::is_same<typename std::decay<T>::type, - typename std::decay<U>::type>; - -// Replaces the type Subject with type Replace if type Subject is the same type -// as type Find, excluding cv-reference qualifiers in the match. -template <typename Find, typename Replace, typename Subject> -using ReplaceType = - typename std::conditional<IsSameBaseType<Find, Subject>::value, - CopyCVReferenceType<Subject, Replace>, - Subject>::type; - -// Determines whether the type Find (excluding cv-reference qualifiers) is in -// the given parameter pack. -template <typename Find, typename... Types> -struct ContainsType : std::true_type {}; - -template <typename Find, typename First, typename... Rest> -struct ContainsType<Find, First, Rest...> - : std::conditional<IsSameBaseType<Find, First>::value, std::true_type, - ContainsType<Find, Rest...>>::type {}; - -template <typename Find> -struct ContainsType<Find> : std::false_type {}; - -} // namespace rpc -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_RPC_FIND_REPLACE_H_ diff --git a/libs/vr/libpdx/private/pdx/rpc/function_traits.h b/libs/vr/libpdx/private/pdx/rpc/function_traits.h deleted file mode 100644 index 7641b0a7c1..0000000000 --- a/libs/vr/libpdx/private/pdx/rpc/function_traits.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef ANDROID_PDX_RPC_FUNCTION_TRAITS_H_ -#define ANDROID_PDX_RPC_FUNCTION_TRAITS_H_ - -#include <type_traits> - -#include <pdx/rpc/type_operators.h> - -namespace android { -namespace pdx { -namespace rpc { - -// Utility type to capture return and argument types of a function signature. -// Examples: -// typedef SignatureType<int(int)> SignatureType; -// using SignatureType = SignatureType<int(int)>; -template <typename T> -using SignatureType = T; - -// Utility class to extract return and argument types from function types. -// Provides nested types for return value, arguments, and full signature. Also -// provides accessor types for individual arguments, argument-arity, and type -// substitution. -template <typename T> -struct FunctionTraits; - -template <typename Return_, typename... Args_> -struct FunctionTraits<Return_(Args_...)> { - using Return = Return_; - using Args = std::tuple<Args_...>; - using Signature = SignatureType<Return_(Args_...)>; - - enum : std::size_t { Arity = sizeof...(Args_) }; - - template <std::size_t Index> - using Arg = typename std::tuple_element<Index, Args>::type; - - template <typename... Params> - using RewriteArgs = - SignatureType<Return_(ConditionalRewrite<Args_, Params>...)>; - - template <typename ReturnType, typename... Params> - using RewriteSignature = - SignatureType<ConditionalRewrite<Return_, ReturnType>( - ConditionalRewrite<Args_, Params>...)>; - - template <template <typename> class Wrapper, typename ReturnType, - typename... Params> - using RewriteSignatureWrapReturn = - SignatureType<Wrapper<ConditionalRewrite<Return_, ReturnType>>( - ConditionalRewrite<Args_, Params>...)>; - - template <typename ReturnType> - using RewriteReturn = - SignatureType<ConditionalRewrite<Return_, ReturnType>(Args_...)>; -}; - -} // namespace rpc -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_RPC_FUNCTION_TRAITS_H_ diff --git a/libs/vr/libpdx/private/pdx/rpc/macros.h b/libs/vr/libpdx/private/pdx/rpc/macros.h deleted file mode 100644 index 99325b5d65..0000000000 --- a/libs/vr/libpdx/private/pdx/rpc/macros.h +++ /dev/null @@ -1,148 +0,0 @@ -#ifndef ANDROID_PDX_RPC_MACROS_H_ -#define ANDROID_PDX_RPC_MACROS_H_ - -// Macros to apply other macros over all elements in a list. -// -// For example, for a macro A(x) and B(x, y): -// - FOR_EACH(A, 1, 2, 3) -> A(1) A(2) A(3). -// - FOR_EACH_BINARY(B, z, 1, 2, 3) -> B(z, 1) B(z, 2) B(z, 3) -// - FOR_EACH_LIST(A, 1, 2, 3) -> A(1), B(2), C(3) -// - FOR_EACH_BINARY_LIST(B, z, 1, 2, 3) -> B(z, 1), B(z, 2), B(z, 3) -// -// Empty lists are supported and will produce no output. - -// Recursive expansion macros. -#define _PDX_EXPAND0(...) __VA_ARGS__ -#define _PDX_EXPAND1(...) _PDX_EXPAND0(_PDX_EXPAND0(_PDX_EXPAND0(__VA_ARGS__))) -#define _PDX_EXPAND2(...) _PDX_EXPAND1(_PDX_EXPAND1(_PDX_EXPAND1(__VA_ARGS__))) -#define _PDX_EXPAND3(...) _PDX_EXPAND2(_PDX_EXPAND2(_PDX_EXPAND2(__VA_ARGS__))) -#define _PDX_EXPAND4(...) _PDX_EXPAND3(_PDX_EXPAND3(_PDX_EXPAND3(__VA_ARGS__))) -#define _PDX_EXPAND(...) _PDX_EXPAND4(_PDX_EXPAND4(_PDX_EXPAND4(__VA_ARGS__))) - -// Required to workaround a bug in the VC++ preprocessor. -#define _PDX_INDIRECT_EXPAND(macro, args) macro args - -// Defines a step separation for macro expansion. -#define _PDX_SEPARATOR - -// Clears any remaining contents wrapped in parentheses. -#define _PDX_CLEAR(...) - -// Introduces a first stub argument and _PDX_CLEAR as second argument. -#define _PDX_CLEAR_IF_LAST() _, _PDX_CLEAR - -// Returns the first argument of a list. -#define _PDX_FIRST_ARG(first, ...) first - -// Returns the second argument of a list. -#define _PDX_SECOND_ARG(_, second, ...) second - -// Expands the arguments and introduces a separator. -#define _PDX_EXPAND_NEXT_FUNC(_, next_func, ...) \ - _PDX_INDIRECT_EXPAND(_PDX_SECOND_ARG, (_, next_func)) \ - _PDX_SEPARATOR - -// Returns next_func if the next element is not (), or _PDX_CLEAR -// otherwise. -// -// _PDX_CLEAR_IF_LAST inserts an extra first stub argument if peek is (). -#define _PDX_NEXT_FUNC(next_element, next_func) \ - _PDX_EXPAND_NEXT_FUNC(_PDX_CLEAR_IF_LAST next_element, next_func) - -// Macros for the unary version of PDX_FOR_EACH. - -// Applies the unary macro. Duplicated for macro recursive expansion. -#define _PDX_APPLY_1(macro, head, next, ...) \ - macro(head) _PDX_NEXT_FUNC(next, _PDX_APPLY_2)(macro, next, __VA_ARGS__) - -// Applies the unary macro. Duplicated for macro recursive expansion. -#define _PDX_APPLY_2(macro, head, next, ...) \ - macro(head) _PDX_NEXT_FUNC(next, _PDX_APPLY_1)(macro, next, __VA_ARGS__) - -// Stops expansion if __VA_ARGS__ is empty, calling _PDX_APPLY_1 -// otherwise. -#define _PDX_HANDLE_EMPTY_ARGS(macro, ...) \ - _PDX_NEXT_FUNC(_PDX_FIRST_ARG(__VA_ARGS__()), _PDX_APPLY_1) \ - (macro, __VA_ARGS__, ()) - -// Applies a unary macro over all the elements in a list. -#define PDX_FOR_EACH(macro, ...) \ - _PDX_EXPAND(_PDX_HANDLE_EMPTY_ARGS(macro, __VA_ARGS__)) - -// Applies the unary macro at the end of a list. Duplicated for macro recursive -// expansion. -#define _PDX_APPLY_LIST_1(macro, head, next, ...) \ - , macro(head) \ - _PDX_NEXT_FUNC(next, _PDX_APPLY_LIST_2)(macro, next, __VA_ARGS__) - -// Applies the unary macro at the end of a list. Duplicated for macro recursive -// expansion. -#define _PDX_APPLY_LIST_2(macro, head, next, ...) \ - , macro(head) \ - _PDX_NEXT_FUNC(next, _PDX_APPLY_LIST_1)(macro, next, __VA_ARGS__) - -// Applies the unary macro at the start of a list. -#define _PDX_APPLY_LIST_0(macro, head, next, ...) \ - macro(head) _PDX_NEXT_FUNC(next, _PDX_APPLY_LIST_1)(macro, next, __VA_ARGS__) - -// Stops expansion if __VA_ARGS__ is empty, calling _PDX_APPLY_LIST_0 -// otherwise. -#define _PDX_HANDLE_EMPTY_LIST(macro, ...) \ - _PDX_NEXT_FUNC(_PDX_FIRST_ARG(__VA_ARGS__()), _PDX_APPLY_LIST_0) \ - (macro, __VA_ARGS__, ()) - -// Applies a unary macro over all the elements in a list. -#define PDX_FOR_EACH_LIST(macro, ...) \ - _PDX_EXPAND(_PDX_HANDLE_EMPTY_LIST(macro, __VA_ARGS__)) - -// Macros for the binary version of PDX_FOR_EACH. - -// Applies the binary macro. Duplicated for macro recursive expansion. -#define _PDX_APPLY_BINARY_1(macro, arg, head, next, ...) \ - macro(arg, head) \ - _PDX_NEXT_FUNC(next, _PDX_APPLY_BINARY_2)(macro, arg, next, __VA_ARGS__) - -// Applies the binary macro. Duplicated for macro recursive expansion. -#define _PDX_APPLY_BINARY_2(macro, arg, head, next, ...) \ - macro(arg, head) \ - _PDX_NEXT_FUNC(next, _PDX_APPLY_BINARY_1)(macro, arg, next, __VA_ARGS__) - -// Version of _PDX_HANDLE_EMPTY_ARGS that takes 1 fixed argument for a -// binary macro. -#define _PDX_HANDLE_EMPTY_ARGS_BINARY(macro, arg, ...) \ - _PDX_NEXT_FUNC(_PDX_FIRST_ARG(__VA_ARGS__()), _PDX_APPLY_BINARY_1) \ - (macro, arg, __VA_ARGS__, ()) - -// Applies a binary macro over all the elements in a list and a given argument. -#define PDX_FOR_EACH_BINARY(macro, arg, ...) \ - _PDX_EXPAND(_PDX_HANDLE_EMPTY_ARGS_BINARY(macro, arg, __VA_ARGS__)) - -// Applies the binary macro at the end of a list. Duplicated for macro recursive -// expansion. -#define _PDX_APPLY_BINARY_LIST_1(macro, arg, head, next, ...) \ - , macro(arg, head) _PDX_NEXT_FUNC(next, _PDX_APPLY_BINARY_LIST_2)( \ - macro, arg, next, __VA_ARGS__) - -// Applies the binary macro at the end of a list. Duplicated for macro recursive -// expansion. -#define _PDX_APPLY_BINARY_LIST_2(macro, arg, head, next, ...) \ - , macro(arg, head) _PDX_NEXT_FUNC(next, _PDX_APPLY_BINARY_LIST_1)( \ - macro, arg, next, __VA_ARGS__) - -// Applies the binary macro at the start of a list. Duplicated for macro -// recursive expansion. -#define _PDX_APPLY_BINARY_LIST_0(macro, arg, head, next, ...) \ - macro(arg, head) _PDX_NEXT_FUNC(next, _PDX_APPLY_BINARY_LIST_1)( \ - macro, arg, next, __VA_ARGS__) - -// Version of _PDX_HANDLE_EMPTY_LIST that takes 1 fixed argument for a -// binary macro. -#define _PDX_HANDLE_EMPTY_LIST_BINARY(macro, arg, ...) \ - _PDX_NEXT_FUNC(_PDX_FIRST_ARG(__VA_ARGS__()), _PDX_APPLY_BINARY_LIST_0) \ - (macro, arg, __VA_ARGS__, ()) - -// Applies a binary macro over all the elements in a list and a given argument. -#define PDX_FOR_EACH_BINARY_LIST(macro, arg, ...) \ - _PDX_EXPAND(_PDX_HANDLE_EMPTY_LIST_BINARY(macro, arg, __VA_ARGS__)) - -#endif // ANDROID_PDX_RPC_MACROS_H_ diff --git a/libs/vr/libpdx/private/pdx/rpc/message_buffer.h b/libs/vr/libpdx/private/pdx/rpc/message_buffer.h deleted file mode 100644 index ba4e86e0de..0000000000 --- a/libs/vr/libpdx/private/pdx/rpc/message_buffer.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef ANDROID_PDX_RPC_MESSAGE_BUFFER_H_ -#define ANDROID_PDX_RPC_MESSAGE_BUFFER_H_ - -#include <pdx/rpc/thread_local_buffer.h> - -namespace android { -namespace pdx { -namespace rpc { - -// Utility type for thread-local buffers, providing suitable defaults for most -// situations. Independent thread-local buffers may be created by using -// different types for Slot -- ThreadLocalSlot, ThreadLocalTypedSlot and -// ThreadLocalIndexedSlot provide utilities for building these types. -template <typename Slot, std::size_t Capacity = 4096, typename T = std::uint8_t, - typename Allocator = DefaultInitializationAllocator<T>> -using MessageBuffer = ThreadLocalBuffer<T, Allocator, Capacity, Slot>; - -} // namespace rpc -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_RPC_MESSAGE_BUFFER_H_ diff --git a/libs/vr/libpdx/private/pdx/rpc/payload.h b/libs/vr/libpdx/private/pdx/rpc/payload.h deleted file mode 100644 index d2df14fbde..0000000000 --- a/libs/vr/libpdx/private/pdx/rpc/payload.h +++ /dev/null @@ -1,158 +0,0 @@ -#ifndef ANDROID_PDX_RPC_PAYLOAD_H_ -#define ANDROID_PDX_RPC_PAYLOAD_H_ - -#include <iterator> - -#include <pdx/client.h> -#include <pdx/rpc/message_buffer.h> -#include <pdx/service.h> - -namespace android { -namespace pdx { -namespace rpc { - -// Implements the payload interface, required by Serialize/Deserialize, on top -// of a thread-local MessageBuffer. -template <typename Slot> -class MessagePayload { - public: - using BufferType = typename MessageBuffer<Slot>::BufferType; - using ValueType = typename MessageBuffer<Slot>::ValueType; - - // Constructs a MessagePayload with an empty TLS buffer. - MessagePayload() - : buffer_(MessageBuffer<Slot>::GetEmptyBuffer()), - cursor_(buffer_.begin()), - const_cursor_(buffer_.cbegin()) {} - - // Returns a reference to the cursor iterator to be used during serialization - // into the underlying MessageBuffer. - typename BufferType::iterator& Cursor() { return cursor_; } - - // Returns a reference to the const cursor iterator at the beginning of the - // underlying MessageBuffer. - typename BufferType::const_iterator& ConstCursor() { return const_cursor_; } - - // Returns a const iterator marking the end of the underlying MessageBuffer. - typename BufferType::const_iterator ConstEnd() { return buffer_.cend(); } - - // Resizes the underlying MessageBuffer and sets the cursor to the beginning. - void Resize(std::size_t size) { - buffer_.resize(size); - cursor_ = buffer_.begin(); - const_cursor_ = buffer_.cbegin(); - } - - // Resets the read cursor so that data can be read from the buffer again. - void Rewind() { const_cursor_ = buffer_.cbegin(); } - - // Adds |size| bytes to the size of the underlying MessageBuffer and positions - // the cursor at the beginning of the extended region. - void Extend(std::size_t size) { - const std::size_t offset = buffer_.size(); - buffer_.resize(offset + size); - cursor_ = buffer_.begin() + offset; - const_cursor_ = buffer_.cbegin() + offset; - } - - // Clears the underlying MessageBuffer and sets the cursor to the beginning. - void Clear() { - buffer_.clear(); - cursor_ = buffer_.begin(); - const_cursor_ = buffer_.cbegin(); - } - - ValueType* Data() { return buffer_.data(); } - const ValueType* Data() const { return buffer_.data(); } - std::size_t Size() const { return buffer_.size(); } - std::size_t Capacity() const { return buffer_.capacity(); } - - private: - BufferType& buffer_; - typename BufferType::iterator cursor_; - typename BufferType::const_iterator const_cursor_; - - MessagePayload(const MessagePayload<Slot>&) = delete; - void operator=(const MessagePayload<Slot>&) = delete; -}; - -// Implements the payload interface for service-side RPCs. Handles translating -// between remote and local handle spaces automatically. -template <typename Slot> -class ServicePayload : public MessagePayload<Slot>, - public MessageWriter, - public MessageReader { - public: - explicit ServicePayload(Message& message) : message_(message) {} - - // MessageWriter - void* GetNextWriteBufferSection(size_t size) override { - this->Extend(size); - return &*this->Cursor(); - } - - OutputResourceMapper* GetOutputResourceMapper() override { return &message_; } - - // MessageReader - BufferSection GetNextReadBufferSection() override { - return {&*this->ConstCursor(), &*this->ConstEnd()}; - } - - void ConsumeReadBufferSectionData(const void* new_start) override { - std::advance(this->ConstCursor(), - PointerDistance(new_start, &*this->ConstCursor())); - } - - InputResourceMapper* GetInputResourceMapper() override { return &message_; } - - private: - Message& message_; -}; - -// Implements the payload interface for client-side RPCs. Handles gathering file -// handles to be sent over IPC automatically. -template <typename Slot> -class ClientPayload : public MessagePayload<Slot>, - public MessageWriter, - public MessageReader { - public: - using ContainerType = - MessageBuffer<ThreadLocalTypeSlot<ClientPayload<Slot>>, 1024u, int>; - using BufferType = typename ContainerType::BufferType; - - explicit ClientPayload(Transaction& transaction) - : transaction_{transaction} {} - - // MessageWriter - void* GetNextWriteBufferSection(size_t size) override { - this->Extend(size); - return &*this->Cursor(); - } - - OutputResourceMapper* GetOutputResourceMapper() override { - return &transaction_; - } - - // MessageReader - BufferSection GetNextReadBufferSection() override { - return {&*this->ConstCursor(), &*this->ConstEnd()}; - } - - void ConsumeReadBufferSectionData(const void* new_start) override { - std::advance(this->ConstCursor(), - PointerDistance(new_start, &*this->ConstCursor())); - } - - InputResourceMapper* GetInputResourceMapper() override { - return &transaction_; - } - - private: - Transaction& transaction_; -}; - -} // namespace rpc -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_RPC_PAYLOAD_H_ diff --git a/libs/vr/libpdx/private/pdx/rpc/pointer_wrapper.h b/libs/vr/libpdx/private/pdx/rpc/pointer_wrapper.h deleted file mode 100644 index 88868fe0e2..0000000000 --- a/libs/vr/libpdx/private/pdx/rpc/pointer_wrapper.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef ANDROID_PDX_RPC_POINTER_WRAPPER_H_ -#define ANDROID_PDX_RPC_POINTER_WRAPPER_H_ - -namespace android { -namespace pdx { -namespace rpc { - -// Wrapper class for pointers to any serializable type. This class is used by -// serialization/deserialization to handle pointers to objects that are to be -// serialized or deserialized. -template <typename T> -class PointerWrapper { - public: - using BaseType = T; - - explicit PointerWrapper(T* pointer) : pointer_(pointer) {} - PointerWrapper(const PointerWrapper&) = default; - PointerWrapper(PointerWrapper&&) noexcept = default; - PointerWrapper& operator=(const PointerWrapper&) = default; - PointerWrapper& operator=(PointerWrapper&&) noexcept = default; - - T& Dereference() { return *pointer_; } - const T& Dereference() const { return *pointer_; } - - private: - T* pointer_; -}; - -template <typename T> -PointerWrapper<T> WrapPointer(T* pointer) { - return PointerWrapper<T>(pointer); -} - -} // namespace rpc -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_RPC_POINTER_WRAPPER_H_ diff --git a/libs/vr/libpdx/private/pdx/rpc/remote_method.h b/libs/vr/libpdx/private/pdx/rpc/remote_method.h deleted file mode 100644 index 505c63b1bf..0000000000 --- a/libs/vr/libpdx/private/pdx/rpc/remote_method.h +++ /dev/null @@ -1,473 +0,0 @@ -#ifndef ANDROID_PDX_RPC_REMOTE_METHOD_H_ -#define ANDROID_PDX_RPC_REMOTE_METHOD_H_ - -#include <tuple> -#include <type_traits> - -#include <pdx/client.h> -#include <pdx/rpc/argument_encoder.h> -#include <pdx/rpc/message_buffer.h> -#include <pdx/rpc/payload.h> -#include <pdx/rpc/remote_method_type.h> -#include <pdx/service.h> -#include <pdx/status.h> - -namespace android { -namespace pdx { -namespace rpc { - -#ifdef __clang__ -// Stand-in type to avoid Clang compiler bug. Clang currently has a bug where -// performing parameter pack expansion for arguments with empty packs causes a -// compiler crash. Provide a substitute void type and specializations/overloads -// of CheckArgumentTypes and DispatchRemoteMethod to work around this problem. -struct Void {}; - -// Evaluates to true if the method type is <any>(Void), false otherwise. -template <typename RemoteMethodType> -using IsVoidMethod = typename std::integral_constant< - bool, RemoteMethodType::Traits::Arity == 1 && - std::is_same<typename RemoteMethodType::Traits::template Arg<0>, - Void>::value>; - -// Utility to determine if a method is of type <any>(Void). -template <typename RemoteMethodType> -using EnableIfVoidMethod = - typename std::enable_if<IsVoidMethod<RemoteMethodType>::value>::type; - -// Utility to determine if a method is not of type <any>(Void). -template <typename RemoteMethodType> -using EnableIfNotVoidMethod = - typename std::enable_if<!IsVoidMethod<RemoteMethodType>::value>::type; - -#else -// GCC works fine with void argument types, always enable the regular -// implementation of DispatchRemoteMethod. -using Void = void; -template <typename RemoteMethodType> -using EnableIfVoidMethod = void; -template <typename RemoteMethodType> -using EnableIfNotVoidMethod = void; -#endif - -// Helper type trait to specialize InvokeRemoteMethods for return types that -// can be obtained directly from Transaction::Send<T>() without deserializing -// reply payload. -template <typename T> -struct IsDirectReturn : std::false_type {}; - -template <> -struct IsDirectReturn<void> : std::true_type {}; - -template <> -struct IsDirectReturn<int> : std::true_type {}; - -template <> -struct IsDirectReturn<LocalHandle> : std::true_type {}; - -template <> -struct IsDirectReturn<LocalChannelHandle> : std::true_type {}; - -template <typename Return, typename Type = void> -using EnableIfDirectReturn = - typename std::enable_if<IsDirectReturn<Return>::value, Type>::type; - -template <typename Return, typename Type = void> -using EnableIfNotDirectReturn = - typename std::enable_if<!IsDirectReturn<Return>::value, Type>::type; - -// Utility class to invoke a method with arguments packed in a tuple. -template <typename Class, typename T> -class UnpackArguments; - -// Utility class to invoke a method with arguments packed in a tuple. -template <typename Class, typename Return, typename... Args> -class UnpackArguments<Class, Return(Args...)> { - public: - using ArgsTupleType = std::tuple<typename std::decay<Args>::type...>; - using MethodType = Return (Class::*)(Message&, Args...); - - UnpackArguments(Class& instance, MethodType method, Message& message, - ArgsTupleType& parameters) - : instance_(instance), - method_(method), - message_(message), - parameters_(parameters) {} - - // Invokes method_ on intance_ with the packed arguments from parameters_. - Return Invoke() { - constexpr auto Arity = sizeof...(Args); - return static_cast<Return>(InvokeHelper(MakeIndexSequence<Arity>{})); - } - - private: - Class& instance_; - MethodType method_; - Message& message_; - ArgsTupleType& parameters_; - - template <std::size_t... Index> - Return InvokeHelper(IndexSequence<Index...>) { - return static_cast<Return>((instance_.*method_)( - message_, - std::get<Index>(std::forward<ArgsTupleType>(parameters_))...)); - } - - UnpackArguments(const UnpackArguments&) = delete; - void operator=(const UnpackArguments&) = delete; -}; - -// Returns an error code from a remote method to the client. May be called -// either during dispatch of the remote method handler or at a later time if the -// message is moved for delayed response. -inline void RemoteMethodError(Message& message, int error_code) { - const auto status = message.ReplyError(error_code); - ALOGE_IF(!status, "RemoteMethodError: Failed to reply to message: %s", - status.GetErrorMessage().c_str()); -} - -// Returns a value from a remote method to the client. The usual method to -// return a value during dispatch of a remote method is to simply use a return -// statement in the handler. If the message is moved however, these methods may -// be used to return a value at a later time, outside of initial dispatch. - -// Overload for direct return types. -template <typename RemoteMethodType, typename Return> -EnableIfDirectReturn<typename RemoteMethodType::Return> RemoteMethodReturn( - Message& message, const Return& return_value) { - const auto status = message.Reply(return_value); - ALOGE_IF(!status, "RemoteMethodReturn: Failed to reply to message: %s", - status.GetErrorMessage().c_str()); -} - -// Overload for non-direct return types. -template <typename RemoteMethodType, typename Return> -EnableIfNotDirectReturn<typename RemoteMethodType::Return> RemoteMethodReturn( - Message& message, const Return& return_value) { - using Signature = typename RemoteMethodType::template RewriteReturn<Return>; - rpc::ServicePayload<ReplyBuffer> payload(message); - MakeArgumentEncoder<Signature>(&payload).EncodeReturn(return_value); - - auto ret = message.WriteAll(payload.Data(), payload.Size()); - auto status = message.Reply(ret); - ALOGE_IF(!status, "RemoteMethodReturn: Failed to reply to message: %s", - status.GetErrorMessage().c_str()); -} - -// Overload for Status<void> return types. -template <typename RemoteMethodType> -void RemoteMethodReturn(Message& message, const Status<void>& return_value) { - if (return_value) - RemoteMethodReturn<RemoteMethodType>(message, 0); - else - RemoteMethodError(message, return_value.error()); -} - -// Overload for Status<T> return types. This overload forwards the underlying -// value or error within the Status<T>. -template <typename RemoteMethodType, typename Return> -void RemoteMethodReturn(Message& message, const Status<Return>& return_value) { - if (return_value) - RemoteMethodReturn<RemoteMethodType, Return>(message, return_value.get()); - else - RemoteMethodError(message, return_value.error()); -} - -// Dispatches a method by deserializing arguments from the given Message, with -// compile-time interface check. Overload for void return types. -template <typename RemoteMethodType, typename Class, typename... Args, - typename = EnableIfNotVoidMethod<RemoteMethodType>> -void DispatchRemoteMethod(Class& instance, - void (Class::*method)(Message&, Args...), - Message& message, - std::size_t max_capacity = InitialBufferCapacity) { - using Signature = typename RemoteMethodType::template RewriteArgs<Args...>; - rpc::ServicePayload<ReceiveBuffer> payload(message); - payload.Resize(max_capacity); - - Status<size_t> read_status = message.Read(payload.Data(), payload.Size()); - if (!read_status) { - RemoteMethodError(message, read_status.error()); - return; - } - - payload.Resize(read_status.get()); - - ErrorType error; - auto decoder = MakeArgumentDecoder<Signature>(&payload); - auto arguments = decoder.DecodeArguments(&error); - if (error) { - RemoteMethodError(message, EIO); - return; - } - - UnpackArguments<Class, Signature>(instance, method, message, arguments) - .Invoke(); - // Return to the caller unless the message was moved. - if (message) - RemoteMethodReturn<RemoteMethodType>(message, 0); -} - -// Dispatches a method by deserializing arguments from the given Message, with -// compile-time interface signature check. Overload for generic return types. -template <typename RemoteMethodType, typename Class, typename Return, - typename... Args, typename = EnableIfNotVoidMethod<RemoteMethodType>> -void DispatchRemoteMethod(Class& instance, - Return (Class::*method)(Message&, Args...), - Message& message, - std::size_t max_capacity = InitialBufferCapacity) { - using Signature = - typename RemoteMethodType::template RewriteSignature<Return, Args...>; - rpc::ServicePayload<ReceiveBuffer> payload(message); - payload.Resize(max_capacity); - - Status<size_t> read_status = message.Read(payload.Data(), payload.Size()); - if (!read_status) { - RemoteMethodError(message, read_status.error()); - return; - } - - payload.Resize(read_status.get()); - - ErrorType error; - auto decoder = MakeArgumentDecoder<Signature>(&payload); - auto arguments = decoder.DecodeArguments(&error); - if (error) { - RemoteMethodError(message, EIO); - return; - } - - auto return_value = - UnpackArguments<Class, Signature>(instance, method, message, arguments) - .Invoke(); - // Return the value to the caller unless the message was moved. - if (message) - RemoteMethodReturn<RemoteMethodType>(message, return_value); -} - -// Dispatches a method by deserializing arguments from the given Message, with -// compile-time interface signature check. Overload for Status<T> return types. -template <typename RemoteMethodType, typename Class, typename Return, - typename... Args, typename = EnableIfNotVoidMethod<RemoteMethodType>> -void DispatchRemoteMethod(Class& instance, - Status<Return> (Class::*method)(Message&, Args...), - Message& message, - std::size_t max_capacity = InitialBufferCapacity) { - using Signature = - typename RemoteMethodType::template RewriteSignature<Return, Args...>; - using InvokeSignature = - typename RemoteMethodType::template RewriteSignatureWrapReturn< - Status, Return, Args...>; - rpc::ServicePayload<ReceiveBuffer> payload(message); - payload.Resize(max_capacity); - - Status<size_t> read_status = message.Read(payload.Data(), payload.Size()); - if (!read_status) { - RemoteMethodError(message, read_status.error()); - return; - } - - payload.Resize(read_status.get()); - - ErrorType error; - auto decoder = MakeArgumentDecoder<Signature>(&payload); - auto arguments = decoder.DecodeArguments(&error); - if (error) { - RemoteMethodError(message, EIO); - return; - } - - auto return_value = UnpackArguments<Class, InvokeSignature>( - instance, method, message, arguments) - .Invoke(); - // Return the value to the caller unless the message was moved. - if (message) - RemoteMethodReturn<RemoteMethodType>(message, return_value); -} - -#ifdef __clang__ -// Overloads to handle Void argument type without exploding clang. - -// Overload for void return type. -template <typename RemoteMethodType, typename Class, - typename = EnableIfVoidMethod<RemoteMethodType>> -void DispatchRemoteMethod(Class& instance, void (Class::*method)(Message&), - Message& message) { - (instance.*method)(message); - // Return to the caller unless the message was moved. - if (message) - RemoteMethodReturn<RemoteMethodType>(message, 0); -} - -// Overload for generic return type. -template <typename RemoteMethodType, typename Class, typename Return, - typename = EnableIfVoidMethod<RemoteMethodType>> -void DispatchRemoteMethod(Class& instance, Return (Class::*method)(Message&), - Message& message) { - auto return_value = (instance.*method)(message); - // Return the value to the caller unless the message was moved. - if (message) - RemoteMethodReturn<RemoteMethodType>(message, return_value); -} - -// Overload for Status<T> return type. -template <typename RemoteMethodType, typename Class, typename Return, - typename = EnableIfVoidMethod<RemoteMethodType>> -void DispatchRemoteMethod(Class& instance, - Status<Return> (Class::*method)(Message&), - Message& message) { - auto return_value = (instance.*method)(message); - // Return the value to the caller unless the message was moved. - if (message) - RemoteMethodReturn<RemoteMethodType>(message, return_value); -} -#endif - -} // namespace rpc - -// Definitions for template methods declared in pdx/client.h. - -template <int Opcode, typename T> -struct CheckArgumentTypes; - -template <int Opcode, typename Return, typename... Args> -struct CheckArgumentTypes<Opcode, Return(Args...)> { - template <typename R> - static typename rpc::EnableIfDirectReturn<R, Status<R>> Invoke(Client& client, - Args... args) { - Transaction trans{client}; - rpc::ClientPayload<rpc::SendBuffer> payload{trans}; - rpc::MakeArgumentEncoder<Return(Args...)>(&payload).EncodeArguments( - std::forward<Args>(args)...); - return trans.Send<R>(Opcode, payload.Data(), payload.Size(), nullptr, 0); - } - - template <typename R> - static typename rpc::EnableIfNotDirectReturn<R, Status<R>> Invoke( - Client& client, Args... args) { - Transaction trans{client}; - - rpc::ClientPayload<rpc::SendBuffer> send_payload{trans}; - rpc::MakeArgumentEncoder<Return(Args...)>(&send_payload) - .EncodeArguments(std::forward<Args>(args)...); - - rpc::ClientPayload<rpc::ReplyBuffer> reply_payload{trans}; - reply_payload.Resize(reply_payload.Capacity()); - - Status<R> result; - auto status = - trans.Send<void>(Opcode, send_payload.Data(), send_payload.Size(), - reply_payload.Data(), reply_payload.Size()); - if (!status) { - result.SetError(status.error()); - } else { - R return_value; - rpc::ErrorType error = - rpc::MakeArgumentDecoder<Return(Args...)>(&reply_payload) - .DecodeReturn(&return_value); - - switch (error.error_code()) { - case rpc::ErrorCode::NO_ERROR: - result.SetValue(std::move(return_value)); - break; - - // This error is returned when ArrayWrapper/StringWrapper is too - // small to receive the payload. - case rpc::ErrorCode::INSUFFICIENT_DESTINATION_SIZE: - result.SetError(ENOBUFS); - break; - - default: - result.SetError(EIO); - break; - } - } - return result; - } - - template <typename R> - static typename rpc::EnableIfDirectReturn<R, Status<void>> InvokeInPlace( - Client& client, R* return_value, Args... args) { - Transaction trans{client}; - - rpc::ClientPayload<rpc::SendBuffer> send_payload{trans}; - rpc::MakeArgumentEncoder<Return(Args...)>(&send_payload) - .EncodeArguments(std::forward<Args>(args)...); - - Status<void> result; - auto status = trans.Send<R>(Opcode, send_payload.Data(), - send_payload.Size(), nullptr, 0); - if (status) { - *return_value = status.take(); - result.SetValue(); - } else { - result.SetError(status.error()); - } - return result; - } - - template <typename R> - static typename rpc::EnableIfNotDirectReturn<R, Status<void>> InvokeInPlace( - Client& client, R* return_value, Args... args) { - Transaction trans{client}; - - rpc::ClientPayload<rpc::SendBuffer> send_payload{trans}; - rpc::MakeArgumentEncoder<Return(Args...)>(&send_payload) - .EncodeArguments(std::forward<Args>(args)...); - - rpc::ClientPayload<rpc::ReplyBuffer> reply_payload{trans}; - reply_payload.Resize(reply_payload.Capacity()); - - auto result = - trans.Send<void>(Opcode, send_payload.Data(), send_payload.Size(), - reply_payload.Data(), reply_payload.Size()); - if (result) { - rpc::ErrorType error = - rpc::MakeArgumentDecoder<Return(Args...)>(&reply_payload) - .DecodeReturn(return_value); - - switch (error.error_code()) { - case rpc::ErrorCode::NO_ERROR: - result.SetValue(); - break; - - // This error is returned when ArrayWrapper/StringWrapper is too - // small to receive the payload. - case rpc::ErrorCode::INSUFFICIENT_DESTINATION_SIZE: - result.SetError(ENOBUFS); - break; - - default: - result.SetError(EIO); - break; - } - } - return result; - } -}; - -// Invokes the remote method with opcode and signature described by -// |RemoteMethodType|. -template <typename RemoteMethodType, typename... Args> -Status<typename RemoteMethodType::Return> Client::InvokeRemoteMethod( - Args&&... args) { - return CheckArgumentTypes< - RemoteMethodType::Opcode, - typename RemoteMethodType::template RewriteArgs<Args...>>:: - template Invoke<typename RemoteMethodType::Return>( - *this, std::forward<Args>(args)...); -} - -template <typename RemoteMethodType, typename Return, typename... Args> -Status<void> Client::InvokeRemoteMethodInPlace(Return* return_value, - Args&&... args) { - return CheckArgumentTypes< - RemoteMethodType::Opcode, - typename RemoteMethodType::template RewriteSignature<Return, Args...>>:: - template InvokeInPlace(*this, return_value, std::forward<Args>(args)...); -} - -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_RPC_REMOTE_METHOD_H_ diff --git a/libs/vr/libpdx/private/pdx/rpc/remote_method_type.h b/libs/vr/libpdx/private/pdx/rpc/remote_method_type.h deleted file mode 100644 index cf9a189e60..0000000000 --- a/libs/vr/libpdx/private/pdx/rpc/remote_method_type.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef ANDROID_PDX_RPC_REMOTE_METHOD_TYPE_H_ -#define ANDROID_PDX_RPC_REMOTE_METHOD_TYPE_H_ - -#include <cstddef> -#include <tuple> -#include <type_traits> - -#include <pdx/rpc/enumeration.h> -#include <pdx/rpc/function_traits.h> - -namespace android { -namespace pdx { -namespace rpc { - -// Utility class binding a remote method opcode to its function signature. -// Describes the interface between RPC clients and services for a single method. -template <int Opcode_, typename Signature_> -struct RemoteMethodType { - typedef FunctionTraits<Signature_> Traits; - - enum : int { Opcode = Opcode_ }; - - typedef typename Traits::Signature Signature; - typedef typename Traits::Return Return; - typedef typename Traits::Args Args; - - template <typename... Params> - using RewriteArgs = typename Traits::template RewriteArgs<Params...>; - - template <typename ReturnType, typename... Params> - using RewriteSignature = - typename Traits::template RewriteSignature<ReturnType, Params...>; - - template <template <typename> class Wrapper, typename ReturnType, - typename... Params> - using RewriteSignatureWrapReturn = - typename Traits::template RewriteSignatureWrapReturn<Wrapper, ReturnType, - Params...>; - - template <typename ReturnType> - using RewriteReturn = typename Traits::template RewriteReturn<ReturnType>; -}; - -// Utility class representing a set of related RemoteMethodTypes. Describes the -// interface between RPC clients and services as a set of methods. -template <typename... MethodTypes> -struct RemoteAPI { - typedef std::tuple<MethodTypes...> Methods; - enum : std::size_t { Length = sizeof...(MethodTypes) }; - - template <std::size_t Index> - using Method = typename std::tuple_element<Index, Methods>::type; - - template <typename MethodType> - static constexpr std::size_t MethodIndex() { - return ElementForType<MethodType, MethodTypes...>::Index; - } -}; - -// Macro to simplify defining remote method signatures. Remote method signatures -// are specified by defining a RemoteMethodType for each remote method. -#define PDX_REMOTE_METHOD(name, opcode, ... /*signature*/) \ - using name = ::android::pdx::rpc::RemoteMethodType<opcode, __VA_ARGS__> - -// Macro to simplify defining a set of remote method signatures. -#define PDX_REMOTE_API(name, ... /*methods*/) \ - using name = ::android::pdx::rpc::RemoteAPI<__VA_ARGS__> - -} // namespace rpc -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_RPC_REMOTE_METHOD_TYPE_H_ diff --git a/libs/vr/libpdx/private/pdx/rpc/sequence.h b/libs/vr/libpdx/private/pdx/rpc/sequence.h deleted file mode 100644 index 5fd898a846..0000000000 --- a/libs/vr/libpdx/private/pdx/rpc/sequence.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef ANDROID_PDX_RPC_SEQUENCE_H_ -#define ANDROID_PDX_RPC_SEQUENCE_H_ - -#include <cstdint> - -namespace android { -namespace pdx { -namespace rpc { - -// Provides a C++11 implementation of C++14 index_sequence and -// make_index_sequence for compatibility with common compilers. This -// implementation may be conditionally replaced with compiler-provided versions -// when C++14 support is available. - -// Utility to capture a sequence of unsigned indices. -template <std::size_t... I> -struct IndexSequence { - using type = IndexSequence; - using value_type = std::size_t; - static constexpr std::size_t size() { return sizeof...(I); } -}; - -namespace detail { - -// Helper class to merge and renumber sequence parts in log N instantiations. -template <typename S1, typename S2> -struct MergeSequencesAndRenumber; - -template <std::size_t... I1, std::size_t... I2> -struct MergeSequencesAndRenumber<IndexSequence<I1...>, IndexSequence<I2...>> - : IndexSequence<I1..., (sizeof...(I1) + I2)...> {}; - -} // namespace detail - -// Utility to build an IndexSequence with N indices. -template <std::size_t N> -struct MakeIndexSequence : detail::MergeSequencesAndRenumber< - typename MakeIndexSequence<N / 2>::type, - typename MakeIndexSequence<N - N / 2>::type> {}; - -// Identity sequences. -template <> -struct MakeIndexSequence<0> : IndexSequence<> {}; -template <> -struct MakeIndexSequence<1> : IndexSequence<0> {}; - -// Utility to build an IndexSequence with indices for each element of a -// parameter pack. -template <typename... T> -using IndexSequenceFor = MakeIndexSequence<sizeof...(T)>; - -} // namespace rpc -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_RPC_SEQUENCE_H_ diff --git a/libs/vr/libpdx/private/pdx/rpc/serializable.h b/libs/vr/libpdx/private/pdx/rpc/serializable.h deleted file mode 100644 index 04a4352268..0000000000 --- a/libs/vr/libpdx/private/pdx/rpc/serializable.h +++ /dev/null @@ -1,150 +0,0 @@ -#ifndef ANDROID_PDX_RPC_SERIALIZABLE_H_ -#define ANDROID_PDX_RPC_SERIALIZABLE_H_ - -#include <cstddef> -#include <string> -#include <tuple> - -#include <pdx/message_reader.h> -#include <pdx/message_writer.h> - -#include "macros.h" -#include "serialization.h" - -namespace android { -namespace pdx { -namespace rpc { - -// This file provides utilities to define serializable types for communication -// between clients and services. Supporting efficient, typed communication -// protocols is the primary goal, NOT providing a general-purpose solution for -// all your C++ serialization needs. Features that are not aligned to the goals -// are not supported, such as static/const member serialization and serializable -// types with virtual methods (requiring a virtual destructor). - -// Captures the type and value of a pointer to member. Pointer to members are -// essentially compile-time constant offsets that can be stored in the type -// system without adding to the size of the structures they describe. This -// library uses this property to implement a limited form of reflection for -// serialization/deserialization functions. -template <typename T, T> -struct MemberPointer; - -template <typename Type, typename Class, Type Class::*Pointer> -struct MemberPointer<Type Class::*, Pointer> { - // Type of the member pointer this type represents. - using PointerType = Type Class::*; - - // Resolves a pointer to member with the given instance, yielding a - // reference to the member in that instance. - static Type& Resolve(Class& instance) { return (instance.*Pointer); } - static const Type& Resolve(const Class& instance) { - return (instance.*Pointer); - } -}; - -// Describes a set of members to be serialized/deserialized by this library. The -// parameter pack MemberPointers takes a list of MemberPointer types that -// describe each member to participate in serialization/deserialization. -template <typename T, typename... MemberPointers> -struct SerializableMembersType { - using Type = T; - - // The number of member pointers described by this type. - enum : std::size_t { MemberCount = sizeof...(MemberPointers) }; - - // The member pointers described by this type. - using Members = std::tuple<MemberPointers...>; - - // Accessor for individual member pointer types. - template <std::size_t Index> - using At = typename std::tuple_element<Index, Members>::type; -}; - -// Classes must do the following to correctly define a serializable type: -// 1. Define a type called "SerializableMembers" as a template instantiation -// of SerializableMembersType, describing the members of the class to -// participate in serialization (presumably all of them). Use the macro -// PDX_SERIALIZABLE_MEMBERS(...) below to aid the correct type -// definition. This type should be private to prevent leaking member -// access information. -// 2. Make SerializableTraits and HasSerilizableMembers types a friend of -// the class. The macro PDX_SERIALIZABLE_MEMEBRS(...) takes care of -// this automatically. -// 3. Define a public default constructor, if necessary. Deserialization -// requires instances to be default-constructible. -// -// Example usage: -// class MySerializableType : public AnotherBaseType { -// public: -// MySerializableType(); -// ... -// private: -// int a; -// string b; -// PDX_SERIALIZABLE_MEMBERS(MySerializableType, a, b); -// }; -// -// Note that const and static member serialization is not supported. - -template <typename T> -class SerializableTraits { - public: - // Gets the serialized size of type T. - static std::size_t GetSerializedSize(const T& value) { - return GetEncodingSize(EncodeArrayType(SerializableMembers::MemberCount)) + - GetMembersSize<SerializableMembers>(value); - } - - // Serializes type T. - static void SerializeObject(const T& value, MessageWriter* writer, - void*& buffer) { - SerializeArrayEncoding(EncodeArrayType(SerializableMembers::MemberCount), - SerializableMembers::MemberCount, buffer); - SerializeMembers<SerializableMembers>(value, writer, buffer); - } - - // Deserializes type T. - static ErrorType DeserializeObject(T* value, MessageReader* reader, - const void*& start, const void* end) { - EncodingType encoding; - std::size_t size; - - if (const auto error = - DeserializeArrayType(&encoding, &size, reader, start, end)) { - return error; - } else if (size != SerializableMembers::MemberCount) { - return ErrorCode::UNEXPECTED_TYPE_SIZE; - } else { - return DeserializeMembers<SerializableMembers>(value, reader, start, end); - } - } - - private: - using SerializableMembers = typename T::SerializableMembers; -}; - -// Utility macro to define a MemberPointer type for a member name. -#define PDX_MEMBER_POINTER(type, member) \ - ::android::pdx::rpc::MemberPointer<decltype(&type::member), &type::member> - -// Defines a list of MemberPointer types given a list of member names. -#define PDX_MEMBERS(type, ... /*members*/) \ - PDX_FOR_EACH_BINARY_LIST(PDX_MEMBER_POINTER, type, __VA_ARGS__) - -// Defines the serializable members of a type given a list of member names and -// befriends SerializableTraits and HasSerializableMembers for the class. This -// macro handles requirements #1 and #2 above. -#define PDX_SERIALIZABLE_MEMBERS(type, ... /*members*/) \ - template <typename T> \ - friend class ::android::pdx::rpc::SerializableTraits; \ - template <typename, typename> \ - friend struct ::android::pdx::rpc::HasSerializableMembers; \ - using SerializableMembers = ::android::pdx::rpc::SerializableMembersType< \ - type, PDX_MEMBERS(type, __VA_ARGS__)> - -} // namespace rpc -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_RPC_SERIALIZABLE_H_ diff --git a/libs/vr/libpdx/private/pdx/rpc/serialization.h b/libs/vr/libpdx/private/pdx/rpc/serialization.h deleted file mode 100644 index 914ea66a9c..0000000000 --- a/libs/vr/libpdx/private/pdx/rpc/serialization.h +++ /dev/null @@ -1,2000 +0,0 @@ -#ifndef ANDROID_PDX_RPC_SERIALIZATION_H_ -#define ANDROID_PDX_RPC_SERIALIZATION_H_ - -#include <cstdint> -#include <cstring> -#include <iterator> -#include <map> -#include <numeric> -#include <sstream> -#include <string> -#include <tuple> -#include <type_traits> -#include <unordered_map> -#include <utility> -#include <vector> - -#include <pdx/channel_handle.h> -#include <pdx/file_handle.h> -#include <pdx/message_reader.h> -#include <pdx/message_writer.h> -#include <pdx/trace.h> -#include <pdx/utility.h> - -#include "array_wrapper.h" -#include "default_initialization_allocator.h" -#include "encoding.h" -#include "pointer_wrapper.h" -#include "string_wrapper.h" -#include "variant.h" - -namespace android { -namespace pdx { -namespace rpc { - -// Automatic serialization/deserialization library based on MessagePack -// (http://msgpack.org). This library provides top level Serialize() and -// Deserialize() functions to encode/decode a variety of data types. -// -// The following data types are supported: -// * Standard signed integer types: int8_t, int16_t, int32_t, and int64_t. -// * Regular signed integer types equivalent to the standard types: -// signed char, short, int, long, and long long. -// * Standard unsigned integer types: uint8_t, uint16_t, uint32_t, and -// uint64_t. -// * Regular unsigned integer types equivalent to the standard types: -// unsigned char, unsigned short, unsigned int, unsigned long, -// and unsigned long long. -// * char without signed/unsigned qualifiers. -// * bool. -// * std::vector with value type of any supported type, including nesting. -// * std::string. -// * std::tuple with elements of any supported type, including nesting. -// * std::pair with elements of any supported type, including nesting. -// * std::map with keys and values of any supported type, including nesting. -// * std::unordered_map with keys and values of any supported type, including -// nesting. -// * std::array with values of any supported type, including nesting. -// * ArrayWrapper of any supported basic type. -// * BufferWrapper of any POD type. -// * StringWrapper of any supported char type. -// * User types with correctly defined SerializableMembers member type. -// -// Planned support for: -// * std::basic_string with all supported char types. - -// Counting template for managing template recursion. -template <std::size_t N> -struct Index {}; - -// Forward declaration of traits type to access types with a SerializedMembers -// member type. -template <typename T> -class SerializableTraits; - -template <typename T, typename... MemberPointers> -struct SerializableMembersType; - -// Utility to deduce the template type from a derived type. -template <template <typename...> class TT, typename... Ts> -std::true_type DeduceTemplateType(const TT<Ts...>*); -template <template <typename...> class TT> -std::false_type DeduceTemplateType(...); - -// Utility determining whether template type TT<...> is a base of type T. -template <template <typename...> class TT, typename T> -using IsTemplateBaseOf = decltype(DeduceTemplateType<TT>(std::declval<T*>())); - -// Utility type for SFINAE in HasHasSerializableMembers. -template <typename... Ts> -using TrySerializableMembersType = void; - -// Determines whether type T has a member type named SerializableMembers of -// template type SerializableMembersType. -template <typename, typename = void> -struct HasSerializableMembers : std::false_type {}; -template <typename T> -struct HasSerializableMembers< - T, TrySerializableMembersType<typename T::SerializableMembers>> - : std::integral_constant< - bool, IsTemplateBaseOf<SerializableMembersType, - typename T::SerializableMembers>::value> {}; - -// Utility to simplify overload enable expressions for types with correctly -// defined SerializableMembers. -template <typename T> -using EnableIfHasSerializableMembers = - typename std::enable_if<HasSerializableMembers<T>::value>::type; - -// Utility to simplify overload enable expressions for enum types. -template <typename T, typename ReturnType = void> -using EnableIfEnum = - typename std::enable_if<std::is_enum<T>::value, ReturnType>::type; - -/////////////////////////////////////////////////////////////////////////////// -// Error Reporting // -/////////////////////////////////////////////////////////////////////////////// - -// Error codes returned by the deserialization code. -enum class ErrorCode { - NO_ERROR = 0, - UNEXPECTED_ENCODING, - UNEXPECTED_TYPE_SIZE, - INSUFFICIENT_BUFFER, - INSUFFICIENT_DESTINATION_SIZE, - GET_FILE_DESCRIPTOR_FAILED, - GET_CHANNEL_HANDLE_FAILED, - INVALID_VARIANT_ELEMENT, -}; - -// Type for errors returned by the deserialization code. -class ErrorType { - public: - ErrorType() : error_code_(ErrorCode::NO_ERROR) {} - - // ErrorType constructor for generic error codes. Explicitly not explicit, - // implicit conversion from ErrorCode to ErrorType is desirable behavior. - // NOLINTNEXTLINE(google-explicit-constructor) - ErrorType(ErrorCode error_code) : error_code_(error_code) {} - - // ErrorType constructor for encoding type errors. - ErrorType(ErrorCode error_code, EncodingClass encoding_class, - EncodingType encoding_type) - : error_code_(error_code) { - unexpected_encoding_.encoding_class = encoding_class; - unexpected_encoding_.encoding_type = encoding_type; - } - - // Evaluates to true if the ErrorType represents an error. - explicit operator bool() const { return error_code_ != ErrorCode::NO_ERROR; } - - // NOLINTNEXTLINE(google-explicit-constructor) - operator ErrorCode() const { return error_code_; } - ErrorCode error_code() const { return error_code_; } - - // Accessors for extra info about unexpected encoding errors. - EncodingClass encoding_class() const { - return unexpected_encoding_.encoding_class; - } - EncodingType encoding_type() const { - return unexpected_encoding_.encoding_type; - } - - // NOLINTNEXTLINE(google-explicit-constructor) - operator std::string() const { - std::ostringstream stream; - - switch (error_code_) { - case ErrorCode::NO_ERROR: - return "NO_ERROR"; - case ErrorCode::UNEXPECTED_ENCODING: - stream << "UNEXPECTED_ENCODING: " << static_cast<int>(encoding_class()) - << ", " << static_cast<int>(encoding_type()); - return stream.str(); - case ErrorCode::UNEXPECTED_TYPE_SIZE: - return "UNEXPECTED_TYPE_SIZE"; - case ErrorCode::INSUFFICIENT_BUFFER: - return "INSUFFICIENT_BUFFER"; - case ErrorCode::INSUFFICIENT_DESTINATION_SIZE: - return "INSUFFICIENT_DESTINATION_SIZE"; - default: - return "[Unknown Error]"; - } - } - - private: - ErrorCode error_code_; - - // Union of extra information for different error code types. - union { - // UNEXPECTED_ENCODING. - struct { - EncodingClass encoding_class; - EncodingType encoding_type; - } unexpected_encoding_; - }; -}; - -/////////////////////////////////////////////////////////////////////////////// -// Object Size // -/////////////////////////////////////////////////////////////////////////////// - -inline constexpr std::size_t GetSerializedSize(const bool& b) { - return GetEncodingSize(EncodeType(b)); -} - -// Overloads of GetSerializedSize() for standard integer types. -inline constexpr std::size_t GetSerializedSize(const char& c) { - return GetEncodingSize(EncodeType(c)); -} -inline constexpr std::size_t GetSerializedSize(const std::uint8_t& i) { - return GetEncodingSize(EncodeType(i)); -} -inline constexpr std::size_t GetSerializedSize(const std::int8_t& i) { - return GetEncodingSize(EncodeType(i)); -} -inline constexpr std::size_t GetSerializedSize(const std::uint16_t& i) { - return GetEncodingSize(EncodeType(i)); -} -inline constexpr std::size_t GetSerializedSize(const std::int16_t& i) { - return GetEncodingSize(EncodeType(i)); -} -inline constexpr std::size_t GetSerializedSize(const std::uint32_t& i) { - return GetEncodingSize(EncodeType(i)); -} -inline constexpr std::size_t GetSerializedSize(const std::int32_t& i) { - return GetEncodingSize(EncodeType(i)); -} -inline constexpr std::size_t GetSerializedSize(const std::uint64_t& i) { - return GetEncodingSize(EncodeType(i)); -} -inline constexpr std::size_t GetSerializedSize(const std::int64_t& i) { - return GetEncodingSize(EncodeType(i)); -} - -inline constexpr std::size_t GetSerializedSize(const float& f) { - return GetEncodingSize(EncodeType(f)); -} -inline constexpr std::size_t GetSerializedSize(const double& d) { - return GetEncodingSize(EncodeType(d)); -} - -// Overload for enum types. -template <typename T> -inline EnableIfEnum<T, std::size_t> GetSerializedSize(T v) { - return GetSerializedSize(static_cast<std::underlying_type_t<T>>(v)); -} - -// Forward declaration for nested definitions. -inline std::size_t GetSerializedSize(const EmptyVariant&); -template <typename... Types> -inline std::size_t GetSerializedSize(const Variant<Types...>&); -template <typename T, typename Enabled = EnableIfHasSerializableMembers<T>> -inline constexpr std::size_t GetSerializedSize(const T&); -template <typename T> -inline constexpr std::size_t GetSerializedSize(const PointerWrapper<T>&); -inline constexpr std::size_t GetSerializedSize(const std::string&); -template <typename T> -inline constexpr std::size_t GetSerializedSize(const StringWrapper<T>&); -template <typename T> -inline constexpr std::size_t GetSerializedSize(const BufferWrapper<T>&); -template <FileHandleMode Mode> -inline constexpr std::size_t GetSerializedSize(const FileHandle<Mode>&); -template <ChannelHandleMode Mode> -inline constexpr std::size_t GetSerializedSize(const ChannelHandle<Mode>&); -template <typename T, typename Allocator> -inline std::size_t GetSerializedSize(const std::vector<T, Allocator>& v); -template <typename Key, typename T, typename Compare, typename Allocator> -inline std::size_t GetSerializedSize( - const std::map<Key, T, Compare, Allocator>& m); -template <typename Key, typename T, typename Hash, typename KeyEqual, - typename Allocator> -inline std::size_t GetSerializedSize( - const std::unordered_map<Key, T, Hash, KeyEqual, Allocator>&); -template <typename T> -inline std::size_t GetSerializedSize(const ArrayWrapper<T>&); -template <typename T, std::size_t Size> -inline std::size_t GetSerializedSize(const std::array<T, Size>& v); -template <typename T, typename U> -inline std::size_t GetSerializedSize(const std::pair<T, U>& p); -template <typename... T> -inline std::size_t GetSerializedSize(const std::tuple<T...>& tuple); - -// Overload for empty variant type. -inline std::size_t GetSerializedSize(const EmptyVariant& empty) { - return GetEncodingSize(EncodeType(empty)); -} - -// Overload for Variant types. -template <typename... Types> -inline std::size_t GetSerializedSize(const Variant<Types...>& variant) { - return GetEncodingSize(EncodeType(variant)) + - GetSerializedSize(variant.index()) + - variant.Visit( - [](const auto& value) { return GetSerializedSize(value); }); -} - -// Overload for structs/classes with SerializableMembers defined. -template <typename T, typename Enabled> -inline constexpr std::size_t GetSerializedSize(const T& value) { - return SerializableTraits<T>::GetSerializedSize(value); -} - -// Overload for PointerWrapper. -template <typename T> -inline constexpr std::size_t GetSerializedSize(const PointerWrapper<T>& p) { - return GetSerializedSize(p.Dereference()); -} - -// Overload for std::string. -inline constexpr std::size_t GetSerializedSize(const std::string& s) { - return GetEncodingSize(EncodeType(s)) + - s.length() * sizeof(std::string::value_type); -} - -// Overload for StringWrapper. -template <typename T> -inline constexpr std::size_t GetSerializedSize(const StringWrapper<T>& s) { - return GetEncodingSize(EncodeType(s)) + - s.length() * sizeof(typename StringWrapper<T>::value_type); -} - -// Overload for BufferWrapper types. -template <typename T> -inline constexpr std::size_t GetSerializedSize(const BufferWrapper<T>& b) { - return GetEncodingSize(EncodeType(b)) + - b.size() * sizeof(typename BufferWrapper<T>::value_type); -} - -// Overload for FileHandle. FileHandle is encoded as a FIXEXT2, with a type code -// of "FileHandle" and a signed 16-bit offset into the pushed fd array. Empty -// FileHandles are encoded with an array index of -1. -template <FileHandleMode Mode> -inline constexpr std::size_t GetSerializedSize(const FileHandle<Mode>& fd) { - return GetEncodingSize(EncodeType(fd)) + sizeof(std::int16_t); -} - -// Overload for ChannelHandle. ChannelHandle is encoded as a FIXEXT4, with a -// type code of "ChannelHandle" and a signed 32-bit offset into the pushed -// channel array. Empty ChannelHandles are encoded with an array index of -1. -template <ChannelHandleMode Mode> -inline constexpr std::size_t GetSerializedSize( - const ChannelHandle<Mode>& channel_handle) { - return GetEncodingSize(EncodeType(channel_handle)) + sizeof(std::int32_t); -} - -// Overload for standard vector types. -template <typename T, typename Allocator> -inline std::size_t GetSerializedSize(const std::vector<T, Allocator>& v) { - return std::accumulate(v.begin(), v.end(), GetEncodingSize(EncodeType(v)), - [](const std::size_t& sum, const T& object) { - return sum + GetSerializedSize(object); - }); -} - -// Overload for standard map types. -template <typename Key, typename T, typename Compare, typename Allocator> -inline std::size_t GetSerializedSize( - const std::map<Key, T, Compare, Allocator>& v) { - return std::accumulate( - v.begin(), v.end(), GetEncodingSize(EncodeType(v)), - [](const std::size_t& sum, const std::pair<Key, T>& object) { - return sum + GetSerializedSize(object.first) + - GetSerializedSize(object.second); - }); -} - -// Overload for standard unordered_map types. -template <typename Key, typename T, typename Hash, typename KeyEqual, - typename Allocator> -inline std::size_t GetSerializedSize( - const std::unordered_map<Key, T, Hash, KeyEqual, Allocator>& v) { - return std::accumulate( - v.begin(), v.end(), GetEncodingSize(EncodeType(v)), - [](const std::size_t& sum, const std::pair<Key, T>& object) { - return sum + GetSerializedSize(object.first) + - GetSerializedSize(object.second); - }); -} - -// Overload for ArrayWrapper types. -template <typename T> -inline std::size_t GetSerializedSize(const ArrayWrapper<T>& v) { - return std::accumulate(v.begin(), v.end(), GetEncodingSize(EncodeType(v)), - [](const std::size_t& sum, const T& object) { - return sum + GetSerializedSize(object); - }); -} - -// Overload for std::array types. -template <typename T, std::size_t Size> -inline std::size_t GetSerializedSize(const std::array<T, Size>& v) { - return std::accumulate(v.begin(), v.end(), GetEncodingSize(EncodeType(v)), - [](const std::size_t& sum, const T& object) { - return sum + GetSerializedSize(object); - }); -} - -// Overload for std::pair. -template <typename T, typename U> -inline std::size_t GetSerializedSize(const std::pair<T, U>& p) { - return GetEncodingSize(EncodeType(p)) + GetSerializedSize(p.first) + - GetSerializedSize(p.second); -} - -// Stops template recursion when the last tuple element is reached. -template <typename... T> -inline std::size_t GetTupleSize(const std::tuple<T...>&, Index<0>) { - return 0; -} - -// Gets the size of each element in a tuple recursively. -template <typename... T, std::size_t index> -inline std::size_t GetTupleSize(const std::tuple<T...>& tuple, Index<index>) { - return GetTupleSize(tuple, Index<index - 1>()) + - GetSerializedSize(std::get<index - 1>(tuple)); -} - -// Overload for tuple types. Gets the size of the tuple, recursing -// through the elements. -template <typename... T> -inline std::size_t GetSerializedSize(const std::tuple<T...>& tuple) { - return GetEncodingSize(EncodeType(tuple)) + - GetTupleSize(tuple, Index<sizeof...(T)>()); -} - -// Stops template recursion when the last member of a Serializable -// type is reached. -template <typename Members, typename T> -inline std::size_t GetMemberSize(const T&, Index<0>) { - return 0; -} - -// Gets the size of each member of a Serializable type recursively. -template <typename Members, typename T, std::size_t index> -inline std::size_t GetMemberSize(const T& object, Index<index>) { - return GetMemberSize<Members>(object, Index<index - 1>()) + - GetSerializedSize(Members::template At<index - 1>::Resolve(object)); -} - -// Gets the size of a type using the given SerializableMembersType -// type. -template <typename Members, typename T> -inline std::size_t GetMembersSize(const T& object) { - return GetMemberSize<Members>(object, Index<Members::MemberCount>()); -} - -/////////////////////////////////////////////////////////////////////////////// -// Object Serialization // -/////////////////////////////////////////////////////////////////////////////// - -// -// SerializeRaw() converts a primitive array or type into a raw byte string. -// These functions are named differently from SerializeObject() expressly to -// avoid catch-all specialization of that template, which can be difficult to -// detect otherwise. -// - -inline void WriteRawData(void*& dest, const void* src, size_t size) { - memcpy(dest, src, size); - dest = static_cast<uint8_t*>(dest) + size; -} - -// Serializes a primitive array into a raw byte string. -template <typename T, - typename = typename std::enable_if<std::is_pod<T>::value>::type> -inline void SerializeRaw(const T& value, void*& buffer) { - WriteRawData(buffer, &value, sizeof(value)); -} - -inline void SerializeEncoding(EncodingType encoding, void*& buffer) { - SerializeRaw(encoding, buffer); -} - -inline void SerializeType(const bool& value, void*& buffer) { - const EncodingType encoding = EncodeType(value); - SerializeEncoding(encoding, buffer); -} - -// Serializes the type code, extended type code, and size for -// extension types. -inline void SerializeExtEncoding(EncodingType encoding, - EncodingExtType ext_type, std::size_t size, - void*& buffer) { - SerializeEncoding(encoding, buffer); - if (encoding == ENCODING_TYPE_EXT8) { - std::uint8_t length = size; - SerializeRaw(length, buffer); - } else if (encoding == ENCODING_TYPE_EXT16) { - std::uint16_t length = size; - SerializeRaw(length, buffer); - } else if (encoding == ENCODING_TYPE_EXT32) { - std::uint32_t length = size; - SerializeRaw(length, buffer); - } else /* if (IsFixextEncoding(encoding) */ { - // Encoding byte contains the fixext length, nothing else to do. - } - SerializeRaw(ext_type, buffer); -} - -// Serializes the type code for file descriptor types. -template <FileHandleMode Mode> -inline void SerializeType(const FileHandle<Mode>& value, void*& buffer) { - SerializeExtEncoding(EncodeType(value), ENCODING_EXT_TYPE_FILE_DESCRIPTOR, 2, - buffer); -} - -// Serializes the type code for channel handle types. -template <ChannelHandleMode Mode> -inline void SerializeType(const ChannelHandle<Mode>& handle, void*& buffer) { - SerializeExtEncoding(EncodeType(handle), ENCODING_EXT_TYPE_CHANNEL_HANDLE, 4, - buffer); -} - -// Serializes type code for variant types. -template <typename... Types> -inline void SerializeType(const Variant<Types...>& value, void*& buffer) { - const EncodingType encoding = EncodeType(value); - SerializeEncoding(encoding, buffer); -} - -// Serializes the type code for string types. -template <typename StringType> -inline void SerializeStringType(const StringType& value, void*& buffer) { - const EncodingType encoding = EncodeType(value); - SerializeEncoding(encoding, buffer); - if (encoding == ENCODING_TYPE_STR8) { - std::uint8_t length = value.length(); - SerializeRaw(length, buffer); - } else if (encoding == ENCODING_TYPE_STR16) { - std::uint16_t length = value.length(); - SerializeRaw(length, buffer); - } else if (encoding == ENCODING_TYPE_STR32) { - std::uint32_t length = value.length(); - SerializeRaw(length, buffer); - } else /* if (IsFixstrEncoding(encoding) */ { - // Encoding byte contains the fixstr length, nothing else to do. - } -} - -// Serializes the type code for std::string and StringWrapper. These types are -// interchangeable and must serialize to the same format. -inline void SerializeType(const std::string& value, void*& buffer) { - SerializeStringType(value, buffer); -} -template <typename T> -inline void SerializeType(const StringWrapper<T>& value, void*& buffer) { - SerializeStringType(value, buffer); -} - -// Serializes the type code for bin types. -inline void SerializeBinEncoding(EncodingType encoding, std::size_t size, - void*& buffer) { - SerializeEncoding(encoding, buffer); - if (encoding == ENCODING_TYPE_BIN8) { - std::uint8_t length = size; - SerializeRaw(length, buffer); - } else if (encoding == ENCODING_TYPE_BIN16) { - std::uint16_t length = size; - SerializeRaw(length, buffer); - } else if (encoding == ENCODING_TYPE_BIN32) { - std::uint32_t length = size; - SerializeRaw(length, buffer); - } else { - // Invalid encoding for BIN type. - } -} - -// Serializes the type code for BufferWrapper types. -template <typename T> -inline void SerializeType(const BufferWrapper<T>& value, void*& buffer) { - const EncodingType encoding = EncodeType(value); - SerializeBinEncoding( - encoding, value.size() * sizeof(typename BufferWrapper<T>::value_type), - buffer); -} - -// Serializes the array encoding type and length. -inline void SerializeArrayEncoding(EncodingType encoding, std::size_t size, - void*& buffer) { - SerializeEncoding(encoding, buffer); - if (encoding == ENCODING_TYPE_ARRAY16) { - std::uint16_t length = size; - SerializeRaw(length, buffer); - } else if (encoding == ENCODING_TYPE_ARRAY32) { - std::uint32_t length = size; - SerializeRaw(length, buffer); - } else /* if (IsFixarrayEncoding(encoding) */ { - // Encoding byte contains the fixarray length, nothing else to do. - } -} - -// Serializes the map encoding type and length. -inline void SerializeMapEncoding(EncodingType encoding, std::size_t size, - void*& buffer) { - SerializeEncoding(encoding, buffer); - if (encoding == ENCODING_TYPE_MAP16) { - std::uint16_t length = size; - SerializeRaw(length, buffer); - } else if (encoding == ENCODING_TYPE_MAP32) { - std::uint32_t length = size; - SerializeRaw(length, buffer); - } else /* if (IsFixmapEncoding(encoding) */ { - // Encoding byte contains the fixmap length, nothing else to do. - } -} - -// Serializes the type code for array types. -template <typename ArrayType> -inline void SerializeArrayType(const ArrayType& value, std::size_t size, - void*& buffer) { - const EncodingType encoding = EncodeType(value); - SerializeArrayEncoding(encoding, size, buffer); -} - -// Serializes the type code for map types. -template <typename MapType> -inline void SerializeMapType(const MapType& value, std::size_t size, - void*& buffer) { - const EncodingType encoding = EncodeType(value); - SerializeMapEncoding(encoding, size, buffer); -} - -// Serializes the type code for std::vector and ArrayWrapper. These types are -// interchangeable and must serialize to the same format. -template <typename T, typename Allocator> -inline void SerializeType(const std::vector<T, Allocator>& value, - void*& buffer) { - SerializeArrayType(value, value.size(), buffer); -} -template <typename T> -inline void SerializeType(const ArrayWrapper<T>& value, void*& buffer) { - SerializeArrayType(value, value.size(), buffer); -} - -// Serializes the type code for std::array. This type serializes to the same -// format as std::vector and ArrayWrapper and is interchangeable in certain -// situations. -template <typename T, std::size_t Size> -inline void SerializeType(const std::array<T, Size>& value, void*& buffer) { - SerializeArrayType(value, Size, buffer); -} - -// Serializes the type code for std::map types. -template <typename Key, typename T, typename Compare, typename Allocator> -inline void SerializeType(const std::map<Key, T, Compare, Allocator>& value, - void*& buffer) { - SerializeMapType(value, value.size(), buffer); -} - -// Serializes the type code for std::unordered_map types. -template <typename Key, typename T, typename Hash, typename KeyEqual, - typename Allocator> -inline void SerializeType( - const std::unordered_map<Key, T, Hash, KeyEqual, Allocator>& value, - void*& buffer) { - SerializeMapType(value, value.size(), buffer); -} - -// Serializes the type code for std::pair types. -template <typename T, typename U> -inline void SerializeType(const std::pair<T, U>& value, void*& buffer) { - SerializeArrayType(value, 2, buffer); -} - -// Serializes the type code for std::tuple types. -template <typename... T> -inline void SerializeType(const std::tuple<T...>& value, void*& buffer) { - SerializeArrayType(value, sizeof...(T), buffer); -} - -// Specialization of SerializeObject for boolean type. -inline void SerializeObject(const bool& value, MessageWriter* /*writer*/, - void*& buffer) { - SerializeType(value, buffer); - // Encoding contains the boolean value, nothing else to do. -} - -// Overloads of SerializeObject for float and double types. -inline void SerializeObject(const float& value, MessageWriter* /*writer*/, - void*& buffer) { - const EncodingType encoding = EncodeType(value); - SerializeEncoding(encoding, buffer); - SerializeRaw(value, buffer); -} - -inline void SerializeObject(const double& value, MessageWriter* /*writer*/, - void*& buffer) { - const EncodingType encoding = EncodeType(value); - SerializeEncoding(encoding, buffer); - SerializeRaw(value, buffer); -} - -// Overloads of SerializeObject() for standard integer types. -inline void SerializeObject(const char& value, MessageWriter* /*writer*/, - void*& buffer) { - const EncodingType encoding = EncodeType(value); - SerializeEncoding(encoding, buffer); - if (encoding == ENCODING_TYPE_UINT8) { - SerializeRaw(value, buffer); - } else /* if (IsUnsignedFixintEncoding(encoding) */ { - // Encoding byte contains the value, nothing else to do. - } -} - -inline void SerializeObject(const int8_t& value, MessageWriter* /*writer*/, - void*& buffer) { - const EncodingType encoding = EncodeType(value); - SerializeEncoding(encoding, buffer); - if (encoding == ENCODING_TYPE_INT8) { - SerializeRaw(value, buffer); - } else /* if (IsFixintEncoding(encoding) */ { - // Encoding byte contains the value, nothing else to do. - } -} - -inline void SerializeObject(const uint8_t& value, MessageWriter* /*writer*/, - void*& buffer) { - const EncodingType encoding = EncodeType(value); - SerializeEncoding(encoding, buffer); - if (encoding == ENCODING_TYPE_UINT8) { - SerializeRaw(value, buffer); - } else /* if (IsUnsignedFixintEncoding(encoding) */ { - // Encoding byte contains the value, nothing else to do. - } -} - -inline void SerializeObject(const int16_t& value, MessageWriter* /*writer*/, - void*& buffer) { - const EncodingType encoding = EncodeType(value); - SerializeEncoding(encoding, buffer); - if (encoding == ENCODING_TYPE_INT8) { - const int8_t byte = value; - SerializeRaw(byte, buffer); - } else if (encoding == ENCODING_TYPE_INT16) { - SerializeRaw(value, buffer); - } else /* if (IsFixintEncoding(encoding) */ { - // Encoding byte contains the value, nothing else to do. - } -} - -inline void SerializeObject(const uint16_t& value, MessageWriter* /*writer*/, - void*& buffer) { - const EncodingType encoding = EncodeType(value); - SerializeEncoding(encoding, buffer); - if (encoding == ENCODING_TYPE_UINT8) { - const uint8_t byte = value; - SerializeRaw(byte, buffer); - } else if (encoding == ENCODING_TYPE_UINT16) { - SerializeRaw(value, buffer); - } else /* if (IsUnsignedFixintEncoding(encoding) */ { - // Encoding byte contains the value, nothing else to do. - } -} - -inline void SerializeObject(const int32_t& value, MessageWriter* /*writer*/, - void*& buffer) { - const EncodingType encoding = EncodeType(value); - SerializeEncoding(encoding, buffer); - if (encoding == ENCODING_TYPE_INT8) { - const int8_t byte = value; - SerializeRaw(byte, buffer); - } else if (encoding == ENCODING_TYPE_INT16) { - const int16_t half = value; - SerializeRaw(half, buffer); - } else if (encoding == ENCODING_TYPE_INT32) { - SerializeRaw(value, buffer); - } else /* if (IsFixintEncoding(encoding) */ { - // Encoding byte contains the value, nothing else to do. - } -} - -inline void SerializeObject(const uint32_t& value, MessageWriter* /*writer*/, - void*& buffer) { - const EncodingType encoding = EncodeType(value); - SerializeEncoding(encoding, buffer); - if (encoding == ENCODING_TYPE_UINT8) { - const uint8_t byte = value; - SerializeRaw(byte, buffer); - } else if (encoding == ENCODING_TYPE_UINT16) { - const uint16_t half = value; - SerializeRaw(half, buffer); - } else if (encoding == ENCODING_TYPE_UINT32) { - SerializeRaw(value, buffer); - } else /* if (IsUnsignedFixintEncoding(encoding) */ { - // Encoding byte contains the value, nothing else to do. - } -} - -inline void SerializeObject(const int64_t& value, MessageWriter* /*writer*/, - void*& buffer) { - const EncodingType encoding = EncodeType(value); - SerializeEncoding(encoding, buffer); - if (encoding == ENCODING_TYPE_INT8) { - const int8_t byte = value; - SerializeRaw(byte, buffer); - } else if (encoding == ENCODING_TYPE_INT16) { - const int16_t half = value; - SerializeRaw(half, buffer); - } else if (encoding == ENCODING_TYPE_INT32) { - const int32_t word = value; - SerializeRaw(word, buffer); - } else if (encoding == ENCODING_TYPE_INT64) { - SerializeRaw(value, buffer); - } else /* if (IsFixintEncoding(encoding) */ { - // Encoding byte contains the value, nothing else to do. - } -} - -inline void SerializeObject(const uint64_t& value, MessageWriter* /*writer*/, - void*& buffer) { - const EncodingType encoding = EncodeType(value); - SerializeEncoding(encoding, buffer); - if (encoding == ENCODING_TYPE_UINT8) { - const uint8_t byte = value; - SerializeRaw(byte, buffer); - } else if (encoding == ENCODING_TYPE_UINT16) { - const uint16_t half = value; - SerializeRaw(half, buffer); - } else if (encoding == ENCODING_TYPE_UINT32) { - const uint32_t word = value; - SerializeRaw(word, buffer); - } else if (encoding == ENCODING_TYPE_UINT64) { - SerializeRaw(value, buffer); - } else /* if (IsUnsignedFixintEncoding(encoding) */ { - // Encoding byte contains the value, nothing else to do. - } -} - -// Serialize enum types. -template <typename T> -inline EnableIfEnum<T> SerializeObject(const T& value, MessageWriter* writer, - void*& buffer) { - SerializeObject(static_cast<std::underlying_type_t<T>>(value), writer, - buffer); -} - -// Forward declaration for nested definitions. -inline void SerializeObject(const EmptyVariant&, MessageWriter*, void*&); -template <typename... Types> -inline void SerializeObject(const Variant<Types...>&, MessageWriter*, void*&); -template <typename T, typename Enabled = EnableIfHasSerializableMembers<T>> -inline void SerializeObject(const T&, MessageWriter*, void*&); -template <typename T> -inline void SerializeObject(const PointerWrapper<T>&, MessageWriter*, void*&); -template <FileHandleMode Mode> -inline void SerializeObject(const FileHandle<Mode>&, MessageWriter*, void*&); -template <ChannelHandleMode Mode> -inline void SerializeObject(const ChannelHandle<Mode>&, MessageWriter*, void*&); -template <typename T, typename Allocator> -inline void SerializeObject(const BufferWrapper<std::vector<T, Allocator>>&, MessageWriter*, void*&); -template <typename T> -inline void SerializeObject(const BufferWrapper<T*>&, MessageWriter*, void*&); -inline void SerializeObject(const std::string&, MessageWriter*, void*&); -template <typename T> -inline void SerializeObject(const StringWrapper<T>&, MessageWriter*, void*&); -template <typename T, typename Allocator> -inline void SerializeObject(const std::vector<T, Allocator>&, MessageWriter*, void*&); -template <typename T> -inline void SerializeObject(const ArrayWrapper<T>&, MessageWriter*, void*&); -template <typename T, std::size_t Size> -inline void SerializeObject(const std::array<T, Size>&, MessageWriter*, void*&); -template <typename Key, typename T, typename Compare, typename Allocator> -inline void SerializeObject(const std::map<Key, T, Compare, Allocator>&, MessageWriter*, void*&); -template <typename Key, typename T, typename Hash, typename KeyEqual, - typename Allocator> -inline void SerializeObject( - const std::unordered_map<Key, T, Hash, KeyEqual, Allocator>&, MessageWriter*, void*&); -template <typename T, typename U> -inline void SerializeObject(const std::pair<T, U>&, MessageWriter*, void*&); -template <typename... T> -inline void SerializeObject(const std::tuple<T...>&, MessageWriter*, void*&); - -// Overload for empty variant type. -inline void SerializeObject(const EmptyVariant& empty, - MessageWriter* /*writer*/, void*& buffer) { - const EncodingType encoding = EncodeType(empty); - SerializeEncoding(encoding, buffer); -} - -// Overload for Variant types. -template <typename... Types> -inline void SerializeObject(const Variant<Types...>& variant, - MessageWriter* writer, void*& buffer) { - SerializeType(variant, buffer); - SerializeObject(variant.index(), writer, buffer); - return variant.Visit([writer, &buffer](const auto& value) { - return SerializeObject(value, writer, buffer); - }); -} - -// Overload for serializable structure/class types. -template <typename T, typename Enabled> -inline void SerializeObject(const T& value, MessageWriter* writer, - void*& buffer) { - SerializableTraits<T>::SerializeObject(value, writer, buffer); -} - -// Serializes the payload of a PointerWrapper. -template <typename T> -inline void SerializeObject(const PointerWrapper<T>& pointer, - MessageWriter* writer, void*& buffer) { - SerializeObject(pointer.Dereference(), writer, buffer); -} - -// Serializes the payload of file descriptor types. -template <FileHandleMode Mode> -inline void SerializeObject(const FileHandle<Mode>& fd, MessageWriter* writer, - void*& buffer) { - SerializeType(fd, buffer); - const Status<FileReference> status = - writer->GetOutputResourceMapper()->PushFileHandle(fd); - FileReference value = status ? status.get() : -status.error(); - SerializeRaw(value, buffer); -} - -// Serializes the payload of channel handle types. -template <ChannelHandleMode Mode> -inline void SerializeObject(const ChannelHandle<Mode>& handle, - MessageWriter* writer, void*& buffer) { - SerializeType(handle, buffer); - const Status<ChannelReference> status = - writer->GetOutputResourceMapper()->PushChannelHandle(handle); - ChannelReference value = status ? status.get() : -status.error(); - SerializeRaw(value, buffer); -} - -// Serializes the payload of BufferWrapper types. -template <typename T, typename Allocator> -inline void SerializeObject(const BufferWrapper<std::vector<T, Allocator>>& b, - MessageWriter* /*writer*/, void*& buffer) { - const auto value_type_size = - sizeof(typename BufferWrapper<std::vector<T, Allocator>>::value_type); - SerializeType(b, buffer); - WriteRawData(buffer, b.data(), b.size() * value_type_size); -} -template <typename T> -inline void SerializeObject(const BufferWrapper<T*>& b, - MessageWriter* /*writer*/, void*& buffer) { - const auto value_type_size = sizeof(typename BufferWrapper<T*>::value_type); - SerializeType(b, buffer); - WriteRawData(buffer, b.data(), b.size() * value_type_size); -} - -// Serializes the payload of string types. -template <typename StringType> -inline void SerializeString(const StringType& s, void*& buffer) { - const auto value_type_size = sizeof(typename StringType::value_type); - SerializeType(s, buffer); - WriteRawData(buffer, s.data(), s.length() * value_type_size); -} - -// Overload of SerializeObject() for std::string and StringWrapper. These types -// are interchangeable and must serialize to the same format. -inline void SerializeObject(const std::string& s, MessageWriter* /*writer*/, - void*& buffer) { - SerializeString(s, buffer); -} -template <typename T> -inline void SerializeObject(const StringWrapper<T>& s, - MessageWriter* /*writer*/, void*& buffer) { - SerializeString(s, buffer); -} - -// Serializes the payload of array types. -template <typename ArrayType> -inline void SerializeArray(const ArrayType& v, MessageWriter* writer, - void*& buffer) { - SerializeType(v, buffer); - for (const auto& element : v) - SerializeObject(element, writer, buffer); -} - -// Serializes the payload for map types. -template <typename MapType> -inline void SerializeMap(const MapType& v, MessageWriter* writer, - void*& buffer) { - SerializeType(v, buffer); - for (const auto& element : v) { - SerializeObject(element.first, writer, buffer); - SerializeObject(element.second, writer, buffer); - } -} - -// Overload of SerializeObject() for std::vector and ArrayWrapper types. These -// types are interchangeable and must serialize to the same format. -template <typename T, typename Allocator> -inline void SerializeObject(const std::vector<T, Allocator>& v, - MessageWriter* writer, void*& buffer) { - SerializeArray(v, writer, buffer); -} -template <typename T> -inline void SerializeObject(const ArrayWrapper<T>& v, MessageWriter* writer, - void*& buffer) { - SerializeArray(v, writer, buffer); -} - -// Overload of SerializeObject() for std::array types. These types serialize to -// the same format at std::vector and ArrayWrapper and are interchangeable in -// certain situations. -template <typename T, std::size_t Size> -inline void SerializeObject(const std::array<T, Size>& v, MessageWriter* writer, - void*& buffer) { - SerializeArray(v, writer, buffer); -} - -// Overload of SerializeObject() for std::map types. -template <typename Key, typename T, typename Compare, typename Allocator> -inline void SerializeObject(const std::map<Key, T, Compare, Allocator>& v, - MessageWriter* writer, void*& buffer) { - SerializeMap(v, writer, buffer); -} - -// Overload of SerializeObject() for std::unordered_map types. -template <typename Key, typename T, typename Hash, typename KeyEqual, - typename Allocator> -inline void SerializeObject( - const std::unordered_map<Key, T, Hash, KeyEqual, Allocator>& v, - MessageWriter* writer, void*& buffer) { - SerializeMap(v, writer, buffer); -} - -// Overload of SerializeObject() for std:pair types. -template <typename T, typename U> -inline void SerializeObject(const std::pair<T, U>& pair, MessageWriter* writer, - void*& buffer) { - SerializeType(pair, buffer); - SerializeObject(pair.first, writer, buffer); - SerializeObject(pair.second, writer, buffer); -} - -// Stops template recursion when the last tuple element is reached. -template <typename... T> -inline void SerializeTuple(const std::tuple<T...>&, MessageWriter*, void*&, - Index<0>) {} - -// Serializes each element of a tuple recursively. -template <typename... T, std::size_t index> -inline void SerializeTuple(const std::tuple<T...>& tuple, MessageWriter* writer, - void*& buffer, Index<index>) { - SerializeTuple(tuple, writer, buffer, Index<index - 1>()); - SerializeObject(std::get<index - 1>(tuple), writer, buffer); -} - -// Overload of SerializeObject() for tuple types. -template <typename... T> -inline void SerializeObject(const std::tuple<T...>& tuple, - MessageWriter* writer, void*& buffer) { - SerializeType(tuple, buffer); - SerializeTuple(tuple, writer, buffer, Index<sizeof...(T)>()); -} - -// Stops template recursion when the last member pointer is reached. -template <typename Members, typename T> -inline void SerializeMember(const T&, MessageWriter*, void*&, Index<0>) {} - -// Serializes each member pointer recursively. -template <typename Members, typename T, std::size_t index> -inline void SerializeMember(const T& object, MessageWriter* writer, - void*& buffer, Index<index>) { - SerializeMember<Members>(object, writer, buffer, Index<index - 1>()); - SerializeObject(Members::template At<index - 1>::Resolve(object), writer, - buffer); -} - -// Serializes the members of a type using the given SerializableMembersType -// type. -template <typename Members, typename T> -inline void SerializeMembers(const T& object, MessageWriter* writer, - void*& buffer) { - SerializeMember<Members>(object, writer, buffer, - Index<Members::MemberCount>()); -} - -// Top level serialization function that replaces the buffer's contents. -template <typename T> -inline void Serialize(const T& object, MessageWriter* writer) { - PDX_TRACE_NAME("Serialize"); - const std::size_t size = GetSerializedSize(object); - - // Reserve the space needed for the object(s). - void* buffer = writer->GetNextWriteBufferSection(size); - SerializeObject(object, writer, buffer); -} - -/////////////////////////////////////////////////////////////////////////////// -// Object Deserialization // -/////////////////////////////////////////////////////////////////////////////// - -inline ErrorType ReadRawDataFromNextSection(void* dest, MessageReader* reader, - const void*& start, - const void*& end, size_t size) { - while (AdvancePointer(start, size) > end) { - auto remaining_size = PointerDistance(end, start); - if (remaining_size > 0) { - memcpy(dest, start, remaining_size); - dest = AdvancePointer(dest, remaining_size); - size -= remaining_size; - } - reader->ConsumeReadBufferSectionData(AdvancePointer(start, remaining_size)); - std::tie(start, end) = reader->GetNextReadBufferSection(); - if (start == end) - return ErrorCode::INSUFFICIENT_BUFFER; - } - memcpy(dest, start, size); - start = AdvancePointer(start, size); - return ErrorCode::NO_ERROR; -} - -inline ErrorType ReadRawData(void* dest, MessageReader* /*reader*/, - const void*& start, const void*& end, - size_t size) { - if (PDX_UNLIKELY(AdvancePointer(start, size) > end)) { - // TODO(avakulenko): Enabling reading from next sections of input buffer - // (using ReadRawDataFromNextSection) screws up clang compiler optimizations - // (probably inefficient inlining) making the whole deserialization - // code path about twice as slow. Investigate and enable more generic - // deserialization code, but right now we don't really need/support this - // scenario, so I keep this commented out for the time being... - - // return ReadRawDataFromNextSection(dest, reader, start, end, size); - return ErrorCode::INSUFFICIENT_BUFFER; - } - memcpy(dest, start, size); - start = AdvancePointer(start, size); - return ErrorCode::NO_ERROR; -} - -// Deserializes a primitive object from raw bytes. -template <typename T, - typename = typename std::enable_if<std::is_pod<T>::value>::type> -inline ErrorType DeserializeRaw(T* value, MessageReader* reader, - const void*& start, const void*& end) { - return ReadRawData(value, reader, start, end, sizeof(T)); -} - -// Utility to deserialize POD types when the serialized type is different -// (smaller) than the target real type. This happens when values are serialized -// into more compact encodings. -template <typename SerializedType, typename RealType> -ErrorType DeserializeValue(RealType* real_value, MessageReader* reader, - const void*& start, const void*& end) { - SerializedType serialized_value; - if (const auto error = - DeserializeRaw(&serialized_value, reader, start, end)) { - return error; - } else { - *real_value = serialized_value; - return ErrorCode::NO_ERROR; - } -} - -inline ErrorType DeserializeEncoding(EncodingType* encoding, - MessageReader* reader, const void*& start, - const void*& end) { - return DeserializeRaw(encoding, reader, start, end); -} - -// Overload to deserialize bool type. -inline ErrorType DeserializeObject(bool* value, MessageReader* reader, - const void*& start, const void*& end) { - EncodingType encoding; - if (const auto error = DeserializeEncoding(&encoding, reader, start, end)) { - return error; - } else if (IsBoolEncoding(encoding)) { - *value = (encoding == ENCODING_TYPE_TRUE); - return ErrorCode::NO_ERROR; - } else { - return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_BOOL, - encoding); - } -} - -// Specializations to deserialize float and double types. -inline ErrorType DeserializeObject(float* value, MessageReader* reader, - const void*& start, const void*& end) { - EncodingType encoding; - if (const auto error = DeserializeEncoding(&encoding, reader, start, end)) { - return error; - } else if (IsFloat32Encoding(encoding)) { - return DeserializeValue<float>(value, reader, start, end); - } else { - return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_FLOAT, - encoding); - } -} - -inline ErrorType DeserializeObject(double* value, MessageReader* reader, - const void*& start, const void*& end) { - EncodingType encoding; - if (const auto error = DeserializeEncoding(&encoding, reader, start, end)) { - return error; - } else if (IsFloat32Encoding(encoding)) { - return DeserializeValue<float>(value, reader, start, end); - } else if (IsFloat64Encoding(encoding)) { - return DeserializeValue<double>(value, reader, start, end); - } else { - return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_FLOAT, - encoding); - } -} - -// Specializations to deserialize standard integer types. -inline ErrorType DeserializeObject(char* value, MessageReader* reader, - const void*& start, const void*& end) { - EncodingType encoding; - if (const auto error = DeserializeEncoding(&encoding, reader, start, end)) { - return error; - } else if (IsUnsignedFixintEncoding(encoding)) { - *value = static_cast<char>(encoding); - return ErrorCode::NO_ERROR; - } else if (IsUInt8Encoding(encoding)) { - return DeserializeValue<char>(value, reader, start, end); - } else { - return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_UINT, - encoding); - } -} - -inline ErrorType DeserializeObject(std::int8_t* value, MessageReader* reader, - const void*& start, const void*& end) { - EncodingType encoding; - if (const auto error = DeserializeEncoding(&encoding, reader, start, end)) { - return error; - } else if (IsFixintEncoding(encoding)) { - *value = static_cast<std::int8_t>(encoding); - return ErrorCode::NO_ERROR; - } else if (IsInt8Encoding(encoding)) { - return DeserializeValue<std::int8_t>(value, reader, start, end); - } else { - return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_INT, - encoding); - } -} - -inline ErrorType DeserializeObject(std::uint8_t* value, MessageReader* reader, - const void*& start, const void*& end) { - EncodingType encoding; - if (const auto error = DeserializeEncoding(&encoding, reader, start, end)) { - return error; - } else if (IsUnsignedFixintEncoding(encoding)) { - *value = encoding; - return ErrorCode::NO_ERROR; - } else if (IsUInt8Encoding(encoding)) { - return DeserializeValue<std::uint8_t>(value, reader, start, end); - } else { - return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_UINT, - encoding); - } -} - -inline ErrorType DeserializeObject(std::int16_t* value, MessageReader* reader, - const void*& start, const void*& end) { - EncodingType encoding; - if (const auto error = DeserializeEncoding(&encoding, reader, start, end)) { - return error; - } else if (IsFixintEncoding(encoding)) { - *value = static_cast<std::int8_t>(encoding); - return ErrorCode::NO_ERROR; - } else if (IsInt8Encoding(encoding)) { - return DeserializeValue<std::int8_t>(value, reader, start, end); - } else if (IsInt16Encoding(encoding)) { - return DeserializeValue<std::int16_t>(value, reader, start, end); - } else { - return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_INT, - encoding); - } -} - -inline ErrorType DeserializeObject(std::uint16_t* value, MessageReader* reader, - const void*& start, const void*& end) { - EncodingType encoding; - if (const auto error = DeserializeEncoding(&encoding, reader, start, end)) { - return error; - } else if (IsUnsignedFixintEncoding(encoding)) { - *value = encoding; - return ErrorCode::NO_ERROR; - } else if (IsUInt8Encoding(encoding)) { - return DeserializeValue<std::uint8_t>(value, reader, start, end); - } else if (IsUInt16Encoding(encoding)) { - return DeserializeValue<std::uint16_t>(value, reader, start, end); - } else { - return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_UINT, - encoding); - } -} - -inline ErrorType DeserializeObject(std::int32_t* value, MessageReader* reader, - const void*& start, const void*& end) { - EncodingType encoding; - if (const auto error = DeserializeEncoding(&encoding, reader, start, end)) { - return error; - } else if (IsFixintEncoding(encoding)) { - *value = static_cast<std::int8_t>(encoding); - return ErrorCode::NO_ERROR; - } else if (IsInt8Encoding(encoding)) { - return DeserializeValue<std::int8_t>(value, reader, start, end); - } else if (IsInt16Encoding(encoding)) { - return DeserializeValue<std::int16_t>(value, reader, start, end); - } else if (IsInt32Encoding(encoding)) { - return DeserializeValue<std::int32_t>(value, reader, start, end); - } else { - return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_INT, - encoding); - } -} - -inline ErrorType DeserializeObject(std::uint32_t* value, MessageReader* reader, - const void*& start, const void*& end) { - EncodingType encoding; - if (const auto error = DeserializeEncoding(&encoding, reader, start, end)) { - return error; - } else if (IsUnsignedFixintEncoding(encoding)) { - *value = encoding; - return ErrorCode::NO_ERROR; - } else if (IsUInt8Encoding(encoding)) { - return DeserializeValue<std::uint8_t>(value, reader, start, end); - } else if (IsUInt16Encoding(encoding)) { - return DeserializeValue<std::uint16_t>(value, reader, start, end); - } else if (IsUInt32Encoding(encoding)) { - return DeserializeValue<std::uint32_t>(value, reader, start, end); - } else { - return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_UINT, - encoding); - } -} - -inline ErrorType DeserializeObject(std::int64_t* value, MessageReader* reader, - const void*& start, const void*& end) { - EncodingType encoding; - if (const auto error = DeserializeEncoding(&encoding, reader, start, end)) { - return error; - } else if (IsFixintEncoding(encoding)) { - *value = static_cast<std::int8_t>(encoding); - return ErrorCode::NO_ERROR; - } else if (IsInt8Encoding(encoding)) { - return DeserializeValue<std::int8_t>(value, reader, start, end); - } else if (IsInt16Encoding(encoding)) { - return DeserializeValue<std::int16_t>(value, reader, start, end); - } else if (IsInt32Encoding(encoding)) { - return DeserializeValue<std::int32_t>(value, reader, start, end); - } else if (IsInt64Encoding(encoding)) { - return DeserializeValue<std::int64_t>(value, reader, start, end); - } else { - return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_INT, - encoding); - } -} - -inline ErrorType DeserializeObject(std::uint64_t* value, MessageReader* reader, - const void*& start, const void*& end) { - EncodingType encoding; - if (const auto error = DeserializeEncoding(&encoding, reader, start, end)) { - return error; - } else if (IsUnsignedFixintEncoding(encoding)) { - *value = encoding; - return ErrorCode::NO_ERROR; - } else if (IsUInt8Encoding(encoding)) { - return DeserializeValue<std::uint8_t>(value, reader, start, end); - } else if (IsUInt16Encoding(encoding)) { - return DeserializeValue<std::uint16_t>(value, reader, start, end); - } else if (IsUInt32Encoding(encoding)) { - return DeserializeValue<std::uint32_t>(value, reader, start, end); - } else if (IsUInt64Encoding(encoding)) { - return DeserializeValue<std::uint64_t>(value, reader, start, end); - } else { - return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_UINT, - encoding); - } -} - -template <typename T> -inline EnableIfEnum<T, ErrorType> DeserializeObject(T* value, - MessageReader* reader, - const void*& start, - const void*& end) { - std::underlying_type_t<T> enum_value; - ErrorType error = DeserializeObject(&enum_value, reader, start, end); - if (!error) - *value = static_cast<T>(enum_value); - return error; -} - -// Forward declarations for nested definitions. -template <typename T, typename Enabled = EnableIfHasSerializableMembers<T>> -inline ErrorType DeserializeObject(T*, MessageReader*, const void*&, - const void*&); -template <typename T> -inline ErrorType DeserializeObject(PointerWrapper<T>*, MessageReader*, - const void*&, const void*&); -inline ErrorType DeserializeObject(LocalHandle*, MessageReader*, const void*&, - const void*&); -inline ErrorType DeserializeObject(LocalChannelHandle*, MessageReader*, - const void*&, const void*&); -template <typename T, typename Allocator> -inline ErrorType DeserializeObject(BufferWrapper<std::vector<T, Allocator>>*, - MessageReader*, const void*&, const void*&); -template <typename T> -inline ErrorType DeserializeObject(BufferWrapper<T*>*, MessageReader*, - const void*&, const void*&); -inline ErrorType DeserializeObject(std::string*, MessageReader*, const void*&, - const void*&); -template <typename T> -inline ErrorType DeserializeObject(StringWrapper<T>*, MessageReader*, - const void*&, const void*&); -template <typename T, typename U> -inline ErrorType DeserializeObject(std::pair<T, U>*, MessageReader*, - const void*&, const void*&); -template <typename... T> -inline ErrorType DeserializeObject(std::tuple<T...>*, MessageReader*, - const void*&, const void*&); -template <typename T, typename Allocator> -inline ErrorType DeserializeObject(std::vector<T, Allocator>*, MessageReader*, - const void*&, const void*&); -template <typename Key, typename T, typename Compare, typename Allocator> -inline ErrorType DeserializeObject(std::map<Key, T, Compare, Allocator>*, - MessageReader*, const void*&, const void*&); -template <typename Key, typename T, typename Hash, typename KeyEqual, - typename Allocator> -inline ErrorType DeserializeObject( - std::unordered_map<Key, T, Hash, KeyEqual, Allocator>*, MessageReader*, - const void*&, const void*&); -template <typename T> -inline ErrorType DeserializeObject(ArrayWrapper<T>*, MessageReader*, - const void*&, const void*&); -template <typename T, std::size_t Size> -inline ErrorType DeserializeObject(std::array<T, Size>*, MessageReader*, - const void*&, const void*&); -template <typename T, typename U> -inline ErrorType DeserializeObject(std::pair<T, U>*, MessageReader*, - const void*&, const void*&); -template <typename... T> -inline ErrorType DeserializeObject(std::tuple<T...>*, MessageReader*, - const void*&, const void*&); -inline ErrorType DeserializeObject(EmptyVariant*, - MessageReader*, const void*&, - const void*&); -template <typename... Types> -inline ErrorType DeserializeObject(Variant<Types...>*, - MessageReader*, const void*&, - const void*&); - -// Deserializes a Serializable type. -template <typename T, typename Enable> -inline ErrorType DeserializeObject(T* value, MessageReader* reader, - const void*& start, const void*& end) { - return SerializableTraits<T>::DeserializeObject(value, reader, start, end); -} - -// Deserializes a PointerWrapper. -template <typename T> -inline ErrorType DeserializeObject(PointerWrapper<T>* pointer, - MessageReader* reader, const void*& start, - const void*& end) { - return DeserializeObject(&pointer->Dereference(), reader, start, end); -} - -// Deserializes the type code and size for extension types. -inline ErrorType DeserializeExtType(EncodingType* encoding, - EncodingExtType* type, std::size_t* size, - MessageReader* reader, const void*& start, - const void*& end) { - if (const auto error = DeserializeEncoding(encoding, reader, start, end)) { - return error; - } else if (IsFixextEncoding(*encoding)) { - *size = GetFixextSize(*encoding); - } else if (*encoding == ENCODING_TYPE_EXT8) { - if (const auto error = - DeserializeValue<std::uint8_t>(size, reader, start, end)) - return error; - } else if (*encoding == ENCODING_TYPE_EXT16) { - if (const auto error = - DeserializeValue<std::uint16_t>(size, reader, start, end)) - return error; - } else if (*encoding == ENCODING_TYPE_EXT32) { - if (const auto error = - DeserializeValue<std::uint32_t>(size, reader, start, end)) - return error; - } else { - return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_EXTENSION, - *encoding); - } - - // The extension type code follows the encoding and size. - return DeserializeRaw(type, reader, start, end); -} - -// Deserializes a file handle and performs handle space translation, if -// required. -inline ErrorType DeserializeObject(LocalHandle* value, MessageReader* reader, - const void*& start, const void*& end) { - EncodingType encoding; - EncodingExtType type; - std::size_t size; - - if (const auto error = - DeserializeExtType(&encoding, &type, &size, reader, start, end)) { - return error; - } else if (size != 2) { - return ErrorType(ErrorCode::UNEXPECTED_TYPE_SIZE, ENCODING_CLASS_EXTENSION, - encoding); - } else if (type == ENCODING_EXT_TYPE_FILE_DESCRIPTOR) { - // Read the encoded file descriptor value. - FileReference ref; - if (const auto error = DeserializeRaw(&ref, reader, start, end)) { - return error; - } - - return reader->GetInputResourceMapper()->GetFileHandle(ref, value) - ? ErrorCode::NO_ERROR - : ErrorCode::GET_FILE_DESCRIPTOR_FAILED; - } else { - return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_EXTENSION, - encoding); - } -} - -inline ErrorType DeserializeObject(LocalChannelHandle* value, - MessageReader* reader, const void*& start, - const void*& end) { - EncodingType encoding; - EncodingExtType type; - std::size_t size; - - if (const auto error = - DeserializeExtType(&encoding, &type, &size, reader, start, end)) { - return error; - } else if (size != 4) { - return ErrorType(ErrorCode::UNEXPECTED_TYPE_SIZE, ENCODING_CLASS_EXTENSION, - encoding); - } else if (type == ENCODING_EXT_TYPE_CHANNEL_HANDLE) { - // Read the encoded channel handle value. - ChannelReference ref; - if (const auto error = DeserializeRaw(&ref, reader, start, end)) { - return error; - } - return reader->GetInputResourceMapper()->GetChannelHandle(ref, value) - ? ErrorCode::NO_ERROR - : ErrorCode::GET_CHANNEL_HANDLE_FAILED; - } else { - return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_EXTENSION, - encoding); - } -} - -// Deserializes the type code and size for bin types. -inline ErrorType DeserializeBinType(EncodingType* encoding, std::size_t* size, - MessageReader* reader, const void*& start, - const void*& end) { - if (const auto error = DeserializeEncoding(encoding, reader, start, end)) { - return error; - } else if (*encoding == ENCODING_TYPE_BIN8) { - return DeserializeValue<std::uint8_t>(size, reader, start, end); - } else if (*encoding == ENCODING_TYPE_BIN16) { - return DeserializeValue<std::uint16_t>(size, reader, start, end); - } else if (*encoding == ENCODING_TYPE_BIN32) { - return DeserializeValue<std::uint32_t>(size, reader, start, end); - } else { - return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_BINARY, - *encoding); - } -} - -// Overload of DeserializeObject() for BufferWrapper types. -template <typename T, typename Allocator> -inline ErrorType DeserializeObject( - BufferWrapper<std::vector<T, Allocator>>* value, MessageReader* reader, - const void*& start, const void*& end) { - const auto value_type_size = - sizeof(typename BufferWrapper<std::vector<T, Allocator>>::value_type); - EncodingType encoding; - std::size_t size; - - if (const auto error = - DeserializeBinType(&encoding, &size, reader, start, end)) - return error; - - // Try to resize the BufferWrapper to the size of the payload. - value->resize(size / value_type_size); - - if (size > value->size() * value_type_size || size % value_type_size != 0) { - return ErrorCode::INSUFFICIENT_DESTINATION_SIZE; - } else if (size == 0U) { - return ErrorCode::NO_ERROR; - } else { - return ReadRawData(value->data(), reader, start, end, size); - } -} -template <typename T> -inline ErrorType DeserializeObject(BufferWrapper<T*>* value, - MessageReader* reader, const void*& start, - const void*& end) { - const auto value_type_size = sizeof(typename BufferWrapper<T*>::value_type); - EncodingType encoding; - std::size_t size; - - if (const auto error = - DeserializeBinType(&encoding, &size, reader, start, end)) - return error; - - // Try to resize the BufferWrapper to the size of the payload. - value->resize(size / value_type_size); - - if (size > value->size() * value_type_size || size % value_type_size != 0) { - return ErrorCode::INSUFFICIENT_DESTINATION_SIZE; - } else if (size == 0U) { - return ErrorCode::NO_ERROR; - } else { - return ReadRawData(value->data(), reader, start, end, size); - } -} - -// Deserializes the type code and size for string types. -inline ErrorType DeserializeStringType(EncodingType* encoding, - std::size_t* size, MessageReader* reader, - const void*& start, const void*& end) { - if (const auto error = DeserializeEncoding(encoding, reader, start, end)) { - return error; - } else if (IsFixstrEncoding(*encoding)) { - *size = GetFixstrSize(*encoding); - return ErrorCode::NO_ERROR; - } else if (*encoding == ENCODING_TYPE_STR8) { - return DeserializeValue<std::uint8_t>(size, reader, start, end); - } else if (*encoding == ENCODING_TYPE_STR16) { - return DeserializeValue<std::uint16_t>(size, reader, start, end); - } else if (*encoding == ENCODING_TYPE_STR32) { - return DeserializeValue<std::uint32_t>(size, reader, start, end); - } else { - return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_STRING, - *encoding); - } -} - -// Overload of DeserializeObject() for std::string types. -inline ErrorType DeserializeObject(std::string* value, MessageReader* reader, - const void*& start, const void*& end) { - EncodingType encoding; - std::size_t size; - - if (const auto error = - DeserializeStringType(&encoding, &size, reader, start, end)) { - return error; - } else if (size == 0U) { - value->clear(); - return ErrorCode::NO_ERROR; - } else { - value->resize(size); - return ReadRawData(&(*value)[0], reader, start, end, size); - } -} - -// Overload of DeserializeObject() for StringWrapper types. -template <typename T> -inline ErrorType DeserializeObject(StringWrapper<T>* value, - MessageReader* reader, const void*& start, - const void*& end) { - const auto value_type_size = sizeof(typename StringWrapper<T>::value_type); - EncodingType encoding; - std::size_t size; - - if (const auto error = - DeserializeStringType(&encoding, &size, reader, start, end)) - return error; - - // Try to resize the StringWrapper to the size of the payload - // string. - value->resize(size / value_type_size); - - if (size > value->length() * value_type_size || size % value_type_size != 0) { - return ErrorCode::INSUFFICIENT_DESTINATION_SIZE; - } else if (size == 0U) { - return ErrorCode::NO_ERROR; - } else { - return ReadRawData(value->data(), reader, start, end, size); - } -} - -// Deserializes the type code and size of array types. -inline ErrorType DeserializeArrayType(EncodingType* encoding, std::size_t* size, - MessageReader* reader, const void*& start, - const void*& end) { - if (const auto error = DeserializeEncoding(encoding, reader, start, end)) { - return error; - } else if (IsFixarrayEncoding(*encoding)) { - *size = GetFixarraySize(*encoding); - return ErrorCode::NO_ERROR; - } else if (*encoding == ENCODING_TYPE_ARRAY16) { - return DeserializeValue<std::uint16_t>(size, reader, start, end); - } else if (*encoding == ENCODING_TYPE_ARRAY32) { - return DeserializeValue<std::uint32_t>(size, reader, start, end); - } else { - return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_ARRAY, - *encoding); - } -} - -// Deserializes the type code and size of map types. -inline ErrorType DeserializeMapType(EncodingType* encoding, std::size_t* size, - MessageReader* reader, const void*& start, - const void*& end) { - if (const auto error = DeserializeEncoding(encoding, reader, start, end)) { - return error; - } else if (IsFixmapEncoding(*encoding)) { - *size = GetFixmapSize(*encoding); - return ErrorCode::NO_ERROR; - } else if (*encoding == ENCODING_TYPE_MAP16) { - return DeserializeValue<std::uint16_t>(size, reader, start, end); - } else if (*encoding == ENCODING_TYPE_MAP32) { - return DeserializeValue<std::uint32_t>(size, reader, start, end); - } else { - return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_MAP, - *encoding); - } -} - -// Overload for std::vector types. -template <typename T, typename Allocator> -inline ErrorType DeserializeObject(std::vector<T, Allocator>* value, - MessageReader* reader, const void*& start, - const void*& end) { - EncodingType encoding; - std::size_t size; - - if (const auto error = - DeserializeArrayType(&encoding, &size, reader, start, end)) - return error; - - std::vector<T, Allocator> result(size); - for (std::size_t i = 0; i < size; i++) { - if (const auto error = DeserializeObject(&result[i], reader, start, end)) - return error; - } - - *value = std::move(result); - return ErrorCode::NO_ERROR; - -// TODO(eieio): Consider the benefits and trade offs of this alternative. -#if 0 - value->resize(size); - for (std::size_t i = 0; i < size; i++) { - if (const auto error = DeserializeObject(&(*value)[i], reader, start, end)) - return error; - } - return ErrorCode::NO_ERROR; -#endif -} - -// Deserializes an EmptyVariant value. -inline ErrorType DeserializeObject(EmptyVariant* /*empty*/, - MessageReader* reader, const void*& start, - const void*& end) { - EncodingType encoding; - - if (const auto error = DeserializeEncoding(&encoding, reader, start, end)) { - return error; - } else if (encoding != ENCODING_TYPE_NIL) { - return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_MAP, - encoding); - } else { - return ErrorCode::NO_ERROR; - } -} - -// Deserializes a Variant type. -template <typename... Types> -inline ErrorType DeserializeObject(Variant<Types...>* variant, - MessageReader* reader, const void*& start, - const void*& end) { - EncodingType encoding; - std::size_t size; - - if (const auto error = - DeserializeMapType(&encoding, &size, reader, start, end)) { - return error; - } - - if (size != 1) - return ErrorType(ErrorCode::UNEXPECTED_TYPE_SIZE, ENCODING_CLASS_MAP, - encoding); - - std::int32_t type; - if (const auto error = DeserializeObject(&type, reader, start, end)) { - return error; - } else if (type < Variant<Types...>::kEmptyIndex || - type >= static_cast<std::int32_t>(sizeof...(Types))) { - return ErrorCode::INVALID_VARIANT_ELEMENT; - } else { - variant->Become(type); - return variant->Visit([reader, &start, &end](auto&& value) { - return DeserializeObject(&value, reader, start, end); - }); - } -} - -// Deserializes map types. -template <typename MapType> -inline ErrorType DeserializeMap(MapType* value, MessageReader* reader, - const void*& start, const void*& end) { - EncodingType encoding; - std::size_t size; - - if (const auto error = - DeserializeMapType(&encoding, &size, reader, start, end)) - return error; - - MapType result; - for (std::size_t i = 0; i < size; i++) { - std::pair<typename MapType::key_type, typename MapType::mapped_type> - element; - if (const auto error = - DeserializeObject(&element.first, reader, start, end)) - return error; - if (const auto error = - DeserializeObject(&element.second, reader, start, end)) - return error; - result.emplace(std::move(element)); - } - - *value = std::move(result); - return ErrorCode::NO_ERROR; -} - -// Overload for std::map types. -template <typename Key, typename T, typename Compare, typename Allocator> -inline ErrorType DeserializeObject(std::map<Key, T, Compare, Allocator>* value, - MessageReader* reader, const void*& start, - const void*& end) { - return DeserializeMap(value, reader, start, end); -} - -// Overload for std::unordered_map types. -template <typename Key, typename T, typename Hash, typename KeyEqual, - typename Allocator> -inline ErrorType DeserializeObject( - std::unordered_map<Key, T, Hash, KeyEqual, Allocator>* value, - MessageReader* reader, const void*& start, const void*& end) { - return DeserializeMap(value, reader, start, end); -} - -// Overload for ArrayWrapper types. -template <typename T> -inline ErrorType DeserializeObject(ArrayWrapper<T>* value, - MessageReader* reader, const void*& start, - const void*& end) { - EncodingType encoding; - std::size_t size; - - if (const auto error = - DeserializeArrayType(&encoding, &size, reader, start, end)) { - return error; - } - - // Try to resize the wrapper. - value->resize(size); - - // Make sure there is enough space in the ArrayWrapper for the - // payload. - if (size > value->capacity()) - return ErrorCode::INSUFFICIENT_DESTINATION_SIZE; - - for (std::size_t i = 0; i < size; i++) { - if (const auto error = DeserializeObject(&(*value)[i], reader, start, end)) - return error; - } - - return ErrorCode::NO_ERROR; -} - -// Overload for std::array types. -template <typename T, std::size_t Size> -inline ErrorType DeserializeObject(std::array<T, Size>* value, - MessageReader* reader, const void*& start, - const void*& end) { - EncodingType encoding; - std::size_t size; - - if (const auto error = - DeserializeArrayType(&encoding, &size, reader, start, end)) { - return error; - } - - if (size != Size) - return ErrorCode::INSUFFICIENT_DESTINATION_SIZE; - - for (std::size_t i = 0; i < size; i++) { - if (const auto error = DeserializeObject(&(*value)[i], reader, start, end)) - return error; - } - - return ErrorCode::NO_ERROR; -} - -// Deserializes std::pair types. -template <typename T, typename U> -inline ErrorType DeserializeObject(std::pair<T, U>* value, - MessageReader* reader, const void*& start, - const void*& end) { - EncodingType encoding; - std::size_t size; - - if (const auto error = - DeserializeArrayType(&encoding, &size, reader, start, end)) { - return error; - } else if (size != 2) { - return ErrorCode::UNEXPECTED_TYPE_SIZE; - } else if (const auto error = - DeserializeObject(&value->first, reader, start, end)) { - return error; - } else if (const auto error = - DeserializeObject(&value->second, reader, start, end)) { - return error; - } else { - return ErrorCode::NO_ERROR; - } -} - -// Stops template recursion when the last tuple element is reached. -template <typename... T> -inline ErrorType DeserializeTuple(std::tuple<T...>*, MessageReader*, - const void*&, const void*, Index<0>) { - return ErrorCode::NO_ERROR; -} - -// Deserializes each element of a tuple recursively. -template <typename... T, std::size_t index> -inline ErrorType DeserializeTuple(std::tuple<T...>* tuple, - MessageReader* reader, const void*& start, - const void*& end, Index<index>) { - if (const auto error = - DeserializeTuple(tuple, reader, start, end, Index<index - 1>())) - return error; - else - return DeserializeObject(&std::get<index - 1>(*tuple), reader, start, end); -} - -// Overload for standard tuple types. -template <typename... T> -inline ErrorType DeserializeObject(std::tuple<T...>* value, - MessageReader* reader, const void*& start, - const void*& end) { - EncodingType encoding; - std::size_t size; - - if (const auto error = - DeserializeArrayType(&encoding, &size, reader, start, end)) { - return error; - } else if (size != sizeof...(T)) { - return ErrorCode::UNEXPECTED_TYPE_SIZE; - } else { - return DeserializeTuple(value, reader, start, end, Index<sizeof...(T)>()); - } -} - -// Stops template recursion when the last member of a Serializable type is -// reached. -template <typename Members, typename T> -inline ErrorType DeserializeMember(T*, MessageReader*, const void*&, - const void*, Index<0>) { - return ErrorCode::NO_ERROR; -} - -// Deserializes each member of a Serializable type recursively. -template <typename Members, typename T, std::size_t index> -inline ErrorType DeserializeMember(T* value, MessageReader* reader, - const void*& start, const void*& end, - Index<index>) { - if (const auto error = DeserializeMember<Members>(value, reader, start, end, - Index<index - 1>())) - return error; - else - return DeserializeObject(&Members::template At<index - 1>::Resolve(*value), - reader, start, end); -} - -// Deserializes the members of a Serializable type using the given -// SerializableMembersType type. -template <typename Members, typename T> -inline ErrorType DeserializeMembers(T* value, MessageReader* reader, - const void*& start, const void*& end) { - return DeserializeMember<Members>(value, reader, start, end, - Index<Members::MemberCount>()); -} - -// Top level deserialization function. -template <typename T> -inline ErrorType Deserialize(T* value, MessageReader* reader) { - PDX_TRACE_NAME("Deserialize"); - MessageReader::BufferSection section = reader->GetNextReadBufferSection(); - if (section.first == section.second) - return ErrorCode::INSUFFICIENT_BUFFER; - ErrorType error = - DeserializeObject(value, reader, section.first, section.second); - reader->ConsumeReadBufferSectionData(section.first); - return error; -} - -} // namespace rpc -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_RPC_SERIALIZATION_H_ diff --git a/libs/vr/libpdx/private/pdx/rpc/string_wrapper.h b/libs/vr/libpdx/private/pdx/rpc/string_wrapper.h deleted file mode 100644 index 371ed89fc9..0000000000 --- a/libs/vr/libpdx/private/pdx/rpc/string_wrapper.h +++ /dev/null @@ -1,129 +0,0 @@ -#ifndef ANDROID_PDX_RPC_STRING_WRAPPER_H_ -#define ANDROID_PDX_RPC_STRING_WRAPPER_H_ - -#include <cstddef> -#include <cstring> -#include <string> -#include <type_traits> - -namespace android { -namespace pdx { -namespace rpc { - -// Wrapper class for C string buffers, providing an interface suitable for -// SerializeObject and DeserializeObject. This class serializes to the same -// format as std::basic_string, and may be substituted for std::basic_string -// during serialization and deserialization. This substitution makes handling of -// C strings more efficient by avoiding unnecessary copies when remote method -// signatures specify std::basic_string arguments or return values. -template <typename CharT = std::string::value_type, - typename Traits = std::char_traits<std::remove_cv_t<CharT>>> -class StringWrapper { - public: - // Define types in the style of STL strings to support STL operators. - typedef Traits traits_type; - typedef CharT value_type; - typedef std::size_t size_type; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef value_type* pointer; - typedef const value_type* const_pointer; - - StringWrapper() : buffer_(nullptr), capacity_(0), end_(0) {} - - StringWrapper(pointer buffer, size_type capacity, size_type size) - : buffer_(&buffer[0]), - capacity_(capacity), - end_(capacity < size ? capacity : size) {} - - StringWrapper(pointer buffer, size_type size) - : StringWrapper(buffer, size, size) {} - - explicit StringWrapper(pointer buffer) - : StringWrapper(buffer, std::strlen(buffer)) {} - - StringWrapper(const StringWrapper& other) { *this = other; } - - StringWrapper(StringWrapper&& other) noexcept { *this = std::move(other); } - - StringWrapper& operator=(const StringWrapper& other) { - if (&other == this) { - return *this; - } else { - buffer_ = other.buffer_; - capacity_ = other.capacity_; - end_ = other.end_; - } - - return *this; - } - - StringWrapper& operator=(StringWrapper&& other) noexcept { - if (&other == this) { - return *this; - } else { - buffer_ = other.buffer_; - capacity_ = other.capacity_; - end_ = other.end_; - other.buffer_ = nullptr; - other.capacity_ = 0; - other.end_ = 0; - } - - return *this; - } - - pointer data() { return buffer_; } - const_pointer data() const { return buffer_; } - - pointer begin() { return &buffer_[0]; } - pointer end() { return &buffer_[end_]; } - const_pointer begin() const { return &buffer_[0]; } - const_pointer end() const { return &buffer_[end_]; } - - size_type size() const { return end_; } - size_type length() const { return end_; } - size_type max_size() const { return capacity_; } - size_type capacity() const { return capacity_; } - - void resize(size_type size) { - if (size <= capacity_) - end_ = size; - else - end_ = capacity_; - } - - reference operator[](size_type pos) { return buffer_[pos]; } - const_reference operator[](size_type pos) const { return buffer_[pos]; } - - private: - pointer buffer_; - size_type capacity_; - size_type end_; -}; - -// Utility functions that infer the underlying type of the string, simplifying -// the wrapper interface. - -// TODO(eieio): Wrapping std::basic_string is here for completeness, but is it -// useful? -template <typename T, typename... Any> -StringWrapper<const T> WrapString(const std::basic_string<T, Any...>& s) { - return StringWrapper<const T>(s.c_str(), s.length()); -} - -template <typename T, typename SizeType = std::size_t> -StringWrapper<T> WrapString(T* s, SizeType size) { - return StringWrapper<T>(s, size); -} - -template <typename T> -StringWrapper<T> WrapString(T* s) { - return StringWrapper<T>(s); -} - -} // namespace rpc -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_RPC_STRING_WRAPPER_H_ diff --git a/libs/vr/libpdx/private/pdx/rpc/thread_local_buffer.h b/libs/vr/libpdx/private/pdx/rpc/thread_local_buffer.h deleted file mode 100644 index e5ef2aa787..0000000000 --- a/libs/vr/libpdx/private/pdx/rpc/thread_local_buffer.h +++ /dev/null @@ -1,134 +0,0 @@ -#ifndef ANDROID_PDX_RPC_THREAD_LOCAL_BUFFER_H_ -#define ANDROID_PDX_RPC_THREAD_LOCAL_BUFFER_H_ - -#include <cstdint> -#include <memory> -#include <vector> - -#include <pdx/rpc/default_initialization_allocator.h> -#include <pdx/trace.h> - -namespace android { -namespace pdx { -namespace rpc { - -// Utility class to distinguish between different thread local entries or -// "slots" in the thread local variable table. Each slot is uniquely identified -// by (T,Index) and is independent of any other slot. -template <typename T, std::size_t Index> -struct ThreadLocalSlot; - -// Utility class to specify thread local slots using only a type. -template <typename T> -struct ThreadLocalTypeSlot; - -// Utility class to specify thread local slots using only an index. -template <std::size_t Index> -struct ThreadLocalIndexSlot; - -// Initial capacity of thread local buffer, unless otherwise specified. -constexpr std::size_t InitialBufferCapacity = 4096; - -// Thread local slots for buffers used by this library to send, receive, and -// reply to messages. -using SendBuffer = ThreadLocalIndexSlot<0>; -using ReceiveBuffer = ThreadLocalIndexSlot<1>; -using ReplyBuffer = ThreadLocalIndexSlot<2>; - -// Provides a simple interface to thread local buffers for large IPC messages. -// Slot provides multiple thread local slots for a given T, Allocator, Capacity -// combination. -template <typename T, typename Allocator = DefaultInitializationAllocator<T>, - std::size_t Capacity = InitialBufferCapacity, - typename Slot = ThreadLocalSlot<void, 0>> -class ThreadLocalBuffer { - public: - using BufferType = std::vector<T, Allocator>; - using ValueType = T; - - // Reserves |capacity| number of elements of capacity in the underlying - // buffer. Call this during startup to avoid allocation during use. - static void Reserve(std::size_t capacity) { - PDX_TRACE_NAME("ThreadLocalBuffer::Reserve"); - InitializeBuffer(capacity); - buffer_->reserve(capacity); - } - - // Resizes the buffer to |size| elements. - static void Resize(std::size_t size) { - PDX_TRACE_NAME("ThreadLocalBuffer::Resize"); - InitializeBuffer(size); - buffer_->resize(size); - } - - // Gets a reference to the underlying buffer after reserving |capacity| - // elements. The current size of the buffer is left intact. The returned - // reference is valid until FreeBuffer() is called. - static BufferType& GetBuffer(std::size_t capacity = Capacity) { - PDX_TRACE_NAME("ThreadLocalBuffer::GetBuffer"); - Reserve(capacity); - return *buffer_; - } - - // Gets a reference to the underlying buffer after reserving |Capacity| - // elements. The current size of the buffer is set to zero. The returned - // reference is valid until FreeBuffer() is called. - static BufferType& GetEmptyBuffer() { - PDX_TRACE_NAME("ThreadLocalBuffer::GetEmptyBuffer"); - Reserve(Capacity); - buffer_->clear(); - return *buffer_; - } - - // Gets a reference to the underlying buffer after resizing it to |size| - // elements. The returned reference is valid until FreeBuffer() is called. - static BufferType& GetSizedBuffer(std::size_t size = Capacity) { - PDX_TRACE_NAME("ThreadLocalBuffer::GetSizedBuffer"); - Resize(size); - return *buffer_; - } - - // Frees the underlying buffer. The buffer will be reallocated if any of the - // methods above are called. - static void FreeBuffer() { - if (buffer_) { - GetBufferGuard().reset(buffer_ = nullptr); - } - } - - private: - friend class ThreadLocalBufferTest; - - static void InitializeBuffer(std::size_t capacity) { - if (!buffer_) { - GetBufferGuard().reset(buffer_ = new BufferType(capacity)); - } - } - - // Work around performance issues with thread-local dynamic initialization - // semantics by using a normal pointer in parallel with a std::unique_ptr. The - // std::unique_ptr is never dereferenced, only assigned, to avoid the high - // cost of dynamic initialization checks, while still providing automatic - // cleanup. The normal pointer provides fast access to the buffer object. - // Never dereference buffer_guard or performance could be severely impacted - // by slow implementations of TLS dynamic initialization. - static thread_local BufferType* buffer_; - - static std::unique_ptr<BufferType>& GetBufferGuard() { - PDX_TRACE_NAME("ThreadLocalBuffer::GetBufferGuard"); - static thread_local std::unique_ptr<BufferType> buffer_guard; - return buffer_guard; - } -}; - -// Instantiation of the static ThreadLocalBuffer::buffer_ member. -template <typename T, typename Allocator, std::size_t Capacity, typename Slot> -thread_local - typename ThreadLocalBuffer<T, Allocator, Capacity, Slot>::BufferType* - ThreadLocalBuffer<T, Allocator, Capacity, Slot>::buffer_; - -} // namespace rpc -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_RPC_THREAD_LOCAL_BUFFER_H_ diff --git a/libs/vr/libpdx/private/pdx/rpc/type_operators.h b/libs/vr/libpdx/private/pdx/rpc/type_operators.h deleted file mode 100644 index 811bd8733c..0000000000 --- a/libs/vr/libpdx/private/pdx/rpc/type_operators.h +++ /dev/null @@ -1,195 +0,0 @@ -#ifndef ANDROID_PDX_RPC_TYPE_OPERATORS_H_ -#define ANDROID_PDX_RPC_TYPE_OPERATORS_H_ - -#include <array> -#include <map> -#include <type_traits> -#include <unordered_map> -#include <vector> - -#include <pdx/channel_handle.h> -#include <pdx/file_handle.h> -#include <pdx/rpc/array_wrapper.h> -#include <pdx/rpc/buffer_wrapper.h> -#include <pdx/rpc/copy_cv_reference.h> -#include <pdx/rpc/pointer_wrapper.h> -#include <pdx/rpc/string_wrapper.h> - -namespace android { -namespace pdx { -namespace rpc { - -// Simplifies type expressions. -template <typename T> -using Decay = typename std::decay<T>::type; - -// Compares the underlying type of A and B. -template <typename A, typename B> -using IsEquivalent = typename std::is_same<Decay<A>, Decay<B>>::type; - -// Logical AND over template parameter pack. -template <typename... T> -struct And : std::false_type {}; -template <typename A, typename B> -struct And<A, B> : std::integral_constant<bool, A::value && B::value> {}; -template <typename A, typename B, typename... Rest> -struct And<A, B, Rest...> : And<A, And<B, Rest...>> {}; - -// Determines whether A is convertible to B (serializes to the same format) -// using these rules: -// 1. std:vector<T, Any...> is convertible to ArrayWrapper<T>. -// 2. ArrayWrapper<T> is convertible to std:vector<T, Any...>. -// 3. std::basic_string<T, Any...> is convertible to StringWrapper<T>. -// 4. StringWrapper<T> is convertible to std::basic_string<T, Any...>. -// 5. BufferWrapper<T*> is convertible to BufferWrapper<std::vector<T, -// Any...>>. -// 6. BufferWrapper<std::vector<T, ...>> is convertible to BufferWrapper<T*>. -// 7. The value type T of A and B must match. - -// Compares A and B for convertibility. This base type determines convertibility -// by equivalence of the underlying types of A and B. Specializations of this -// type handle the rules for which complex types are convertible. -template <typename A, typename B> -struct IsConvertible : IsEquivalent<A, B> {}; - -// Compares TT<A, ...> and TT<B, ...>; these are convertible if A and B are -// convertible. -template <template <typename, typename...> class TT, typename A, typename B, - typename... AnyA, typename... AnyB> -struct IsConvertible<TT<A, AnyA...>, TT<B, AnyB...>> - : IsConvertible<Decay<A>, Decay<B>> {}; - -// Compares TT<KeyA, ValueA, ...> and TT<KeyB, ValueB, ...>; these are -// convertible if KeyA and KeyB are -// convertible and ValueA and ValueB are convertible. -template <template <typename, typename, typename...> class TT, typename KeyA, - typename ValueA, typename KeyB, typename ValueB, typename... AnyA, - typename... AnyB> -struct IsConvertible<TT<KeyA, ValueA, AnyA...>, TT<KeyB, ValueB, AnyB...>> - : And<IsConvertible<Decay<KeyA>, Decay<KeyB>>, - IsConvertible<Decay<ValueA>, Decay<ValueB>>> {}; - -// Compares two std::pairs to see if the corresponding elements are convertible. -template <typename A, typename B, typename C, typename D> -struct IsConvertible<std::pair<A, B>, std::pair<C, D>> - : And<IsConvertible<Decay<A>, Decay<C>>, - IsConvertible<Decay<B>, Decay<D>>> {}; - -// Compares std::pair with a two-element std::tuple to see if the corresponding -// elements are convertible. -template <typename A, typename B, typename C, typename D> -struct IsConvertible<std::pair<A, B>, std::tuple<C, D>> - : And<IsConvertible<Decay<A>, Decay<C>>, - IsConvertible<Decay<B>, Decay<D>>> {}; -template <typename A, typename B, typename C, typename D> -struct IsConvertible<std::tuple<A, B>, std::pair<C, D>> - : And<IsConvertible<Decay<A>, Decay<C>>, - IsConvertible<Decay<B>, Decay<D>>> {}; - -// Compares two std::tuples to see if the corresponding elements are -// convertible. -template <typename... A, typename... B> -struct IsConvertible<std::tuple<A...>, std::tuple<B...>> - : And<IsConvertible<Decay<A>, Decay<B>>...> {}; - -// Compares std::vector, std::array, and ArrayWrapper; these are convertible if -// the value types are convertible. -template <typename A, typename B, typename... Any> -struct IsConvertible<std::vector<A, Any...>, ArrayWrapper<B>> - : IsConvertible<Decay<A>, Decay<B>> {}; -template <typename A, typename B, typename... Any> -struct IsConvertible<ArrayWrapper<A>, std::vector<B, Any...>> - : IsConvertible<Decay<A>, Decay<B>> {}; -template <typename A, typename B, typename... Any, std::size_t Size> -struct IsConvertible<std::vector<A, Any...>, std::array<B, Size>> - : IsConvertible<Decay<A>, Decay<B>> {}; -template <typename A, typename B, typename... Any, std::size_t Size> -struct IsConvertible<std::array<A, Size>, std::vector<B, Any...>> - : IsConvertible<Decay<A>, Decay<B>> {}; -template <typename A, typename B, std::size_t Size> -struct IsConvertible<ArrayWrapper<A>, std::array<B, Size>> - : IsConvertible<Decay<A>, Decay<B>> {}; -template <typename A, typename B, std::size_t Size> -struct IsConvertible<std::array<A, Size>, ArrayWrapper<B>> - : IsConvertible<Decay<A>, Decay<B>> {}; - -// Compares std::map and std::unordered_map; these are convertible if the keys -// are convertible and the values are convertible. -template <typename KeyA, typename ValueA, typename KeyB, typename ValueB, - typename... AnyA, typename... AnyB> -struct IsConvertible<std::map<KeyA, ValueA, AnyA...>, - std::unordered_map<KeyB, ValueB, AnyB...>> - : And<IsConvertible<Decay<KeyA>, Decay<KeyB>>, - IsConvertible<Decay<ValueA>, Decay<ValueB>>> {}; -template <typename KeyA, typename ValueA, typename KeyB, typename ValueB, - typename... AnyA, typename... AnyB> -struct IsConvertible<std::unordered_map<KeyA, ValueA, AnyA...>, - std::map<KeyB, ValueB, AnyB...>> - : And<IsConvertible<Decay<KeyA>, Decay<KeyB>>, - IsConvertible<Decay<ValueA>, Decay<ValueB>>> {}; - -// Compares BufferWrapper<A*> and BufferWrapper<std::vector<B>>; these are -// convertible if A and B are equivalent. Allocator types are not relevant to -// convertibility. -template <typename A, typename B, typename Allocator> -struct IsConvertible<BufferWrapper<A*>, - BufferWrapper<std::vector<B, Allocator>>> - : IsEquivalent<A, B> {}; -template <typename A, typename B, typename Allocator> -struct IsConvertible<BufferWrapper<std::vector<A, Allocator>>, - BufferWrapper<B*>> : IsEquivalent<A, B> {}; -template <typename A, typename B, typename AllocatorA, typename AllocatorB> -struct IsConvertible<BufferWrapper<std::vector<A, AllocatorA>>, - BufferWrapper<std::vector<B, AllocatorB>>> - : IsEquivalent<A, B> {}; -template <typename A, typename B> -struct IsConvertible<BufferWrapper<A*>, BufferWrapper<B*>> - : IsEquivalent<A, B> {}; - -// Compares std::basic_string<A, ...> and StringWrapper<B>; these are -// convertible if A and B are equivalent. -template <typename A, typename B, typename... Any> -struct IsConvertible<std::basic_string<A, Any...>, StringWrapper<B>> - : IsEquivalent<A, B> {}; -template <typename A, typename B, typename... Any> -struct IsConvertible<StringWrapper<A>, std::basic_string<B, Any...>> - : IsEquivalent<A, B> {}; - -// Compares PointerWrapper<A> and B; these are convertible if A and B are -// convertible. -template <typename A, typename B> -struct IsConvertible<PointerWrapper<A>, B> : IsConvertible<Decay<A>, Decay<B>> { -}; -template <typename A, typename B> -struct IsConvertible<A, PointerWrapper<B>> : IsConvertible<Decay<A>, Decay<B>> { -}; - -// LocalHandle is convertible to RemoteHandle on the service side. This means -// that a RemoteHandle may be supplied by a service when the protocol calls for -// a LocalHandle return value. The other way around is not safe and can leak -// file descriptors. The ServicePayload class enforces this policy by only -// supporting RemoteHandle for pushed handles. -template <> -struct IsConvertible<LocalHandle, RemoteHandle> : std::true_type {}; -template <> -struct IsConvertible<LocalHandle, BorrowedHandle> : std::true_type {}; - -template <> -struct IsConvertible<LocalChannelHandle, RemoteChannelHandle> : std::true_type { -}; -template <> -struct IsConvertible<LocalChannelHandle, BorrowedChannelHandle> - : std::true_type {}; - -// Conditionally "rewrites" type A as type B, including cv-reference qualifiers, -// iff A is convertible to B. -template <typename A, typename B> -using ConditionalRewrite = - typename std::conditional<IsConvertible<Decay<A>, Decay<B>>::value, - CopyCVReferenceType<A, B>, A>::type; - -} // namespace rpc -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_RPC_TYPE_OPERATORS_H_ diff --git a/libs/vr/libpdx/private/pdx/rpc/variant.h b/libs/vr/libpdx/private/pdx/rpc/variant.h deleted file mode 100644 index a1292b0819..0000000000 --- a/libs/vr/libpdx/private/pdx/rpc/variant.h +++ /dev/null @@ -1,760 +0,0 @@ -#ifndef ANDROID_PDX_RPC_VARIANT_H_ -#define ANDROID_PDX_RPC_VARIANT_H_ - -#include <cstdint> -#include <tuple> -#include <type_traits> - -namespace android { -namespace pdx { -namespace rpc { - -// Type tag denoting an empty variant. -struct EmptyVariant {}; - -namespace detail { - -// Type for matching tagged overloads. -template <typename T> -struct TypeTag {}; - -// Determines the type of the I-th element of Types.... -template <std::size_t I, typename... Types> -using TypeForIndex = std::tuple_element_t<I, std::tuple<Types...>>; - -// Determines the type tag for the I-th element of Types.... -template <std::size_t I, typename... Types> -using TypeTagForIndex = TypeTag<TypeForIndex<I, Types...>>; - -// Similar to std::is_constructible except that it evaluates to false for bool -// construction from pointer types: this helps prevent subtle to bugs caused by -// assigning values that decay to pointers to Variants with bool elements. -// -// Here is an example of the problematic situation this trait avoids: -// -// Variant<int, bool> v; -// const int array[3] = {1, 2, 3}; -// v = array; // This is allowed by regular std::is_constructible. -// -template <typename...> -struct IsConstructible; -template <typename T, typename U> -struct IsConstructible<T, U> - : std::integral_constant<bool, - std::is_constructible<T, U>::value && - !(std::is_same<std::decay_t<T>, bool>::value && - std::is_pointer<std::decay_t<U>>::value)> {}; -template <typename T, typename... Args> -struct IsConstructible<T, Args...> : std::is_constructible<T, Args...> {}; - -// Enable if T(Args...) is well formed. -template <typename R, typename T, typename... Args> -using EnableIfConstructible = - typename std::enable_if<IsConstructible<T, Args...>::value, R>::type; -// Enable if T(Args...) is not well formed. -template <typename R, typename T, typename... Args> -using EnableIfNotConstructible = - typename std::enable_if<!IsConstructible<T, Args...>::value, R>::type; - -// Determines whether T is an element of Types...; -template <typename... Types> -struct HasType : std::false_type {}; -template <typename T, typename U> -struct HasType<T, U> : std::is_same<std::decay_t<T>, std::decay_t<U>> {}; -template <typename T, typename First, typename... Rest> -struct HasType<T, First, Rest...> - : std::integral_constant<bool, HasType<T, First>::value || - HasType<T, Rest...>::value> {}; - -// Defines set operations on a set of Types... -template <typename... Types> -struct Set { - // Default specialization catches the empty set, which is always a subset. - template <typename...> - struct IsSubset : std::true_type {}; - template <typename T> - struct IsSubset<T> : HasType<T, Types...> {}; - template <typename First, typename... Rest> - struct IsSubset<First, Rest...> - : std::integral_constant<bool, IsSubset<First>::value && - IsSubset<Rest...>::value> {}; -}; - -// Determines the number of elements of Types... that are constructible from -// From. -template <typename... Types> -struct ConstructibleCount; -template <typename From, typename To> -struct ConstructibleCount<From, To> - : std::integral_constant<std::size_t, IsConstructible<To, From>::value> {}; -template <typename From, typename First, typename... Rest> -struct ConstructibleCount<From, First, Rest...> - : std::integral_constant<std::size_t, - IsConstructible<First, From>::value + - ConstructibleCount<From, Rest...>::value> {}; - -// Enable if T is an element of Types... -template <typename R, typename T, typename... Types> -using EnableIfElement = - typename std::enable_if<HasType<T, Types...>::value, R>::type; -// Enable if T is not an element of Types... -template <typename R, typename T, typename... Types> -using EnableIfNotElement = - typename std::enable_if<!HasType<T, Types...>::value, R>::type; - -// Enable if T is convertible to an element of Types... T is considered -// convertible IIF a single element of Types... is assignable from T and T is -// not a direct element of Types... -template <typename R, typename T, typename... Types> -using EnableIfConvertible = - typename std::enable_if<!HasType<T, Types...>::value && - ConstructibleCount<T, Types...>::value == 1, - R>::type; - -// Enable if T is assignable to an element of Types... T is considered -// assignable IFF a single element of Types... is constructible from T or T is a -// direct element of Types.... Note that T is REQUIRED to be an element of -// Types... when multiple elements are constructible from T to prevent ambiguity -// in conversion. -template <typename R, typename T, typename... Types> -using EnableIfAssignable = - typename std::enable_if<HasType<T, Types...>::value || - ConstructibleCount<T, Types...>::value == 1, - R>::type; - -// Selects a type for SFINAE constructor selection. -template <bool CondA, typename SelectA, typename SelectB> -using Select = std::conditional_t<CondA, SelectA, SelectB>; - -// Recursive union type. -template <typename... Types> -union Union; - -// Specialization handling a singular type, terminating template recursion. -template <typename Type> -union Union<Type> { - Union() {} - ~Union() {} - - template <typename T> - Union(std::int32_t index, std::int32_t* index_out, TypeTag<Type>, T&& value) - : first_(std::forward<T>(value)) { - *index_out = index; - } - template <typename T, typename = EnableIfAssignable<void, T, Type>> - Union(std::int32_t index, std::int32_t* index_out, T&& value) - : first_(std::forward<T>(value)) { - *index_out = index; - } - Union(const Union& other, std::int32_t index) { - if (index == 0) - new (&first_) Type(other.first_); - } - Union(Union&& other, std::int32_t index) { - if (index == 0) - new (&first_) Type(std::move(other.first_)); - } - Union(const Union&) = delete; - Union(Union&&) = delete; - void operator=(const Union&) = delete; - void operator=(Union&&) = delete; - - Type& get(TypeTag<Type>) { return first_; } - const Type& get(TypeTag<Type>) const { return first_; } - EmptyVariant get(TypeTag<EmptyVariant>) const { return {}; } - constexpr std::int32_t index(TypeTag<Type>) const { return 0; } - - template <typename... Args> - std::int32_t Construct(TypeTag<Type>, Args&&... args) { - new (&first_) Type(std::forward<Args>(args)...); - return 0; - } - template <typename... Args> - EnableIfConstructible<std::int32_t, Type, Args...> Construct(Args&&... args) { - new (&first_) Type(std::forward<Args>(args)...); - return 0; - } - - void Destruct(std::int32_t target_index) { - if (target_index == index(TypeTag<Type>{})) { - (&get(TypeTag<Type>{}))->~Type(); - } - } - - template <typename T> - bool Assign(TypeTag<Type>, std::int32_t target_index, T&& value) { - if (target_index == 0) { - first_ = std::forward<T>(value); - return true; - } else { - return false; - } - } - template <typename T> - EnableIfConstructible<bool, Type, T> Assign(std::int32_t target_index, - T&& value) { - if (target_index == 0) { - first_ = std::forward<T>(value); - return true; - } else { - return false; - } - } - template <typename T> - EnableIfNotConstructible<bool, Type, T> Assign(std::int32_t /*target_index*/, - T&& /*value*/) { - return false; - } - - template <typename Op> - decltype(auto) Visit(std::int32_t target_index, Op&& op) { - if (target_index == index(TypeTag<Type>{})) - return std::forward<Op>(op)(get(TypeTag<Type>{})); - else - return std::forward<Op>(op)(get(TypeTag<EmptyVariant>{})); - } - template <typename Op> - decltype(auto) Visit(std::int32_t target_index, Op&& op) const { - if (target_index == index(TypeTag<Type>{})) - return std::forward<Op>(op)(get(TypeTag<Type>{})); - else - return std::forward<Op>(op)(get(TypeTag<EmptyVariant>{})); - } - - template <typename... Args> - bool Become(std::int32_t target_index, Args&&... args) { - if (target_index == index(TypeTag<Type>{})) { - Construct(TypeTag<Type>{}, std::forward<Args>(args)...); - return true; - } else { - return false; - } - } - - private: - Type first_; -}; - -// Specialization that recursively unions types from the paramater pack. -template <typename First, typename... Rest> -union Union<First, Rest...> { - Union() {} - ~Union() {} - - template <typename T> - Union(std::int32_t index, std::int32_t* index_out, TypeTag<First>, T&& value) - : first_(std::forward<T>(value)) { - *index_out = index; - } - template <typename T, typename U> - Union(std::int32_t index, std::int32_t* index_out, TypeTag<T>, U&& value) - : rest_(index + 1, index_out, TypeTag<T>{}, std::forward<U>(value)) {} - Union(const Union& other, std::int32_t index) { - if (index == 0) - new (&first_) First(other.first_); - else - new (&rest_) Union<Rest...>(other.rest_, index - 1); - } - Union(Union&& other, std::int32_t index) { - if (index == 0) - new (&first_) First(std::move(other.first_)); - else - new (&rest_) Union<Rest...>(std::move(other.rest_), index - 1); - } - Union(const Union&) = delete; - Union(Union&&) = delete; - void operator=(const Union&) = delete; - void operator=(Union&&) = delete; - - struct FirstType {}; - struct RestType {}; - template <typename T> - using SelectConstructor = - Select<ConstructibleCount<T, First>::value == 1, FirstType, RestType>; - - template <typename T> - Union(std::int32_t index, std::int32_t* index_out, T&& value) - : Union(index, index_out, std::forward<T>(value), - SelectConstructor<T>{}) {} - - template <typename T> - Union(std::int32_t index, std::int32_t* index_out, T&& value, FirstType) - : first_(std::forward<T>(value)) { - *index_out = index; - } - template <typename T> - Union(std::int32_t index, std::int32_t* index_out, T&& value, RestType) - : rest_(index + 1, index_out, std::forward<T>(value)) {} - - First& get(TypeTag<First>) { return first_; } - const First& get(TypeTag<First>) const { return first_; } - constexpr std::int32_t index(TypeTag<First>) const { return 0; } - - template <typename T> - T& get(TypeTag<T>) { - return rest_.get(TypeTag<T>{}); - } - template <typename T> - const T& get(TypeTag<T>) const { - return rest_.template get(TypeTag<T>{}); - } - template <typename T> - constexpr std::int32_t index(TypeTag<T>) const { - return 1 + rest_.index(TypeTag<T>{}); - } - - template <typename... Args> - std::int32_t Construct(TypeTag<First>, Args&&... args) { - new (&first_) First(std::forward<Args>(args)...); - return 0; - } - template <typename T, typename... Args> - std::int32_t Construct(TypeTag<T>, Args&&... args) { - return 1 + - rest_.template Construct(TypeTag<T>{}, std::forward<Args>(args)...); - } - - template <typename... Args> - EnableIfConstructible<std::int32_t, First, Args...> Construct( - Args&&... args) { - new (&first_) First(std::forward<Args>(args)...); - return 0; - } - template <typename... Args> - EnableIfNotConstructible<std::int32_t, First, Args...> Construct( - Args&&... args) { - return 1 + rest_.template Construct(std::forward<Args>(args)...); - } - - void Destruct(std::int32_t target_index) { - if (target_index == index(TypeTag<First>{})) { - (get(TypeTag<First>{})).~First(); - } else { - rest_.Destruct(target_index - 1); - } - } - - template <typename T> - bool Assign(TypeTag<First>, std::int32_t target_index, T&& value) { - if (target_index == 0) { - first_ = std::forward<T>(value); - return true; - } else { - return false; - } - } - template <typename T, typename U> - bool Assign(TypeTag<T>, std::int32_t target_index, U&& value) { - return rest_.Assign(TypeTag<T>{}, target_index - 1, std::forward<U>(value)); - } - template <typename T> - EnableIfConstructible<bool, First, T> Assign(std::int32_t target_index, - T&& value) { - if (target_index == 0) { - first_ = std::forward<T>(value); - return true; - } else { - return rest_.Assign(target_index - 1, std::forward<T>(value)); - } - } - template <typename T> - EnableIfNotConstructible<bool, First, T> Assign(std::int32_t target_index, - T&& value) { - return rest_.Assign(target_index - 1, std::forward<T>(value)); - } - - // Recursively traverses the union and calls Op on the active value when the - // active type is found. If the union is empty Op is called on EmptyVariant. - // TODO(eieio): This could be refactored into an array or jump table. It's - // unclear whether this would be more efficient for practical variant arity. - template <typename Op> - decltype(auto) Visit(std::int32_t target_index, Op&& op) { - if (target_index == index(TypeTag<First>{})) - return std::forward<Op>(op)(get(TypeTag<First>{})); - else - return rest_.Visit(target_index - 1, std::forward<Op>(op)); - } - template <typename Op> - decltype(auto) Visit(std::int32_t target_index, Op&& op) const { - if (target_index == index(TypeTag<First>{})) - return std::forward<Op>(op)(get(TypeTag<First>{})); - else - return rest_.Visit(target_index - 1, std::forward<Op>(op)); - } - - template <typename... Args> - bool Become(std::int32_t target_index, Args&&... args) { - if (target_index == index(TypeTag<First>{})) { - Construct(TypeTag<First>{}, std::forward<Args>(args)...); - return true; - } else { - return rest_.Become(target_index - 1, std::forward<Args>(args)...); - } - } - - private: - First first_; - Union<Rest...> rest_; -}; - -} // namespace detail - -// Variant is a type safe union that can store values of any of its element -// types. A Variant is different than std::tuple in that it only stores one type -// at a time or a special empty type. Variants are always default constructible -// to empty, even when none of the element types are default constructible. -template <typename... Types> -class Variant { - private: - // Convenience types. - template <typename T> - using TypeTag = detail::TypeTag<T>; - template <typename T> - using DecayedTypeTag = TypeTag<std::decay_t<T>>; - template <std::size_t I> - using TypeForIndex = detail::TypeForIndex<I, Types...>; - template <std::size_t I> - using TypeTagForIndex = detail::TypeTagForIndex<I, Types...>; - template <typename T> - using HasType = detail::HasType<T, Types...>; - template <typename R, typename T> - using EnableIfElement = detail::EnableIfElement<R, T, Types...>; - template <typename R, typename T> - using EnableIfConvertible = detail::EnableIfConvertible<R, T, Types...>; - template <typename R, typename T> - using EnableIfAssignable = detail::EnableIfAssignable<R, T, Types...>; - - struct Direct {}; - struct Convert {}; - template <typename T> - using SelectConstructor = detail::Select<HasType<T>::value, Direct, Convert>; - - // Constructs by type tag when T is an direct element of Types... - template <typename T> - explicit Variant(T&& value, Direct) - : value_(0, &index_, DecayedTypeTag<T>{}, std::forward<T>(value)) {} - // Conversion constructor when T is not a direct element of Types... - template <typename T> - explicit Variant(T&& value, Convert) - : value_(0, &index_, std::forward<T>(value)) {} - - public: - // Variants are default construcible, regardless of whether the elements are - // default constructible. Default consruction yields an empty Variant. - Variant() {} - explicit Variant(EmptyVariant) {} - ~Variant() { Destruct(); } - - Variant(const Variant& other) - : index_{other.index_}, value_{other.value_, other.index_} {} - Variant(Variant&& other) noexcept - : index_{other.index_}, value_{std::move(other.value_), other.index_} {} - -// Recent Clang versions has a regression that produces bogus -// unused-lambda-capture warning. Suppress the warning as a temporary -// workaround. http://b/71356631 -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-lambda-capture" - // Copy and move construction from Variant types. Each element of OtherTypes - // must be convertible to an element of Types. - template <typename... OtherTypes> - explicit Variant(const Variant<OtherTypes...>& other) { - other.Visit([this](const auto& value) { Construct(value); }); - } -#pragma clang diagnostic pop - - template <typename... OtherTypes> - explicit Variant(Variant<OtherTypes...>&& other) { - other.Visit([this](auto&& value) { Construct(std::move(value)); }); - } - - Variant& operator=(const Variant& other) { - other.Visit([this](const auto& value) { *this = value; }); - return *this; - } - Variant& operator=(Variant&& other) noexcept { - other.Visit([this](auto&& value) { *this = std::move(value); }); - return *this; - } - - // Construction from non-Variant types. - template <typename T, typename = EnableIfAssignable<void, T>> - explicit Variant(T&& value) - : Variant(std::forward<T>(value), SelectConstructor<T>{}) {} - - // Performs assignment from type T belonging to Types. This overload takes - // priority to prevent implicit conversion in cases where T is implicitly - // convertible to multiple elements of Types. - template <typename T> - EnableIfElement<Variant&, T> operator=(T&& value) { - Assign(DecayedTypeTag<T>{}, std::forward<T>(value)); - return *this; - } - - // Performs assignment from type T not belonging to Types. This overload - // matches in cases where conversion is the only viable option. - template <typename T> - EnableIfConvertible<Variant&, T> operator=(T&& value) { - Assign(std::forward<T>(value)); - return *this; - } - - // Handles assignment from the empty type. This overload supports assignment - // in visitors using generic lambdas. - Variant& operator=(EmptyVariant) { - Destruct(); - return *this; - } - - // Assignment from Variant types. Each element of OtherTypes must be - // convertible to an element of Types. Forwards through non-Variant assignment - // operators to apply conversion checks. - template <typename... OtherTypes> - Variant& operator=(const Variant<OtherTypes...>& other) { - other.Visit([this](const auto& value) { *this = value; }); - return *this; - } - template <typename... OtherTypes> - Variant& operator=(Variant<OtherTypes...>&& other) { - other.Visit([this](auto&& value) { *this = std::move(value); }); - return *this; - } - - // Becomes the target type, constructing a new element from the given - // arguments if necessary. No action is taken if the active element is already - // the target type. Otherwise the active element is destroyed and replaced by - // constructing an element of the new type using |Args|. An invalid target - // type index results in an empty Variant. - template <typename... Args> - void Become(std::int32_t target_index, Args&&... args) { - if (target_index != index()) { - Destruct(); - index_ = value_.Become(target_index, std::forward<Args>(args)...) - ? target_index - : kEmptyIndex; - } - } - - // Invokes |Op| on the active element. If the Variant is empty |Op| is invoked - // on EmptyVariant. - template <typename Op> - decltype(auto) Visit(Op&& op) { - return value_.Visit(index_, std::forward<Op>(op)); - } - template <typename Op> - decltype(auto) Visit(Op&& op) const { - return value_.Visit(index_, std::forward<Op>(op)); - } - - // Index returned when the Variant is empty. - enum : std::int32_t { kEmptyIndex = -1 }; - - // Returns the index of the given type. - template <typename T> - constexpr std::int32_t index_of() const { - static_assert(HasType<T>::value, "T is not an element type of Variant."); - return value_.index(DecayedTypeTag<T>{}); - } - - // Returns the index of the active type. If the Variant is empty -1 is - // returned. - std::int32_t index() const { return index_; } - - // Returns true if the given type is active, false otherwise. - template <typename T> - bool is() const { - static_assert(HasType<T>::value, "T is not an element type of Variant."); - return index() == index_of<T>(); - } - - // Returns true if the Variant is empty, false otherwise. - bool empty() const { return index() == kEmptyIndex; } - - // Element accessors. Returns a pointer to the active value if the given - // type/index is active, otherwise nullptr is returned. - template <typename T> - T* get() { - if (is<T>()) - return &value_.get(DecayedTypeTag<T>{}); - else - return nullptr; - } - template <typename T> - const T* get() const { - if (is<T>()) - return &value_.template get(DecayedTypeTag<T>{}); - else - return nullptr; - } - template <std::size_t I> - TypeForIndex<I>* get() { - if (is<TypeForIndex<I>>()) - return &value_.get(TypeTagForIndex<I>{}); - else - return nullptr; - } - template <std::size_t I> - const TypeForIndex<I>* get() const { - if (is<TypeForIndex<I>>()) - return &value_.template get(TypeTagForIndex<I>{}); - else - return nullptr; - } - - private: - std::int32_t index_ = kEmptyIndex; - detail::Union<std::decay_t<Types>...> value_; - - // Constructs an element from the given arguments and sets the Variant to the - // resulting type. - template <typename... Args> - void Construct(Args&&... args) { - index_ = value_.template Construct(std::forward<Args>(args)...); - } - void Construct(EmptyVariant) {} - - // Destroys the active element of the Variant. - void Destruct() { - value_.Destruct(index_); - index_ = kEmptyIndex; - } - - // Assigns the Variant when non-empty and the current type matches the target - // type, otherwise destroys the current value and constructs a element of the - // new type. Tagged assignment is used when T is an element of the Variant to - // prevent implicit conversion in cases where T is implicitly convertible to - // multiple element types. - template <typename T, typename U> - void Assign(TypeTag<T>, U&& value) { - if (!value_.template Assign(TypeTag<T>{}, index_, std::forward<U>(value))) { - Destruct(); - Construct(TypeTag<T>{}, std::forward<U>(value)); - } - } - template <typename T> - void Assign(T&& value) { - if (!value_.template Assign(index_, std::forward<T>(value))) { - Destruct(); - Construct(std::forward<T>(value)); - } - } -}; - -// Utility type to extract/convert values from a variant. This class simplifies -// conditional logic to get/move/swap/action values from a variant when one or -// more elements are compatible with the destination type. -// -// Example: -// Variant<int, bool, std::string> v(10); -// bool bool_value; -// if (IfAnyOf<int, bool>::Get(v, &bool_value)) { -// DoSomething(bool_value); -// } else { -// HandleInvalidType(); -// } -// IfAnyOf<int>::Call(v, [](const auto& value) { DoSomething(value); }); -// -template <typename... ValidTypes> -struct IfAnyOf { - // Calls Op on the underlying value of the variant and returns true when the - // variant is a valid type, otherwise does nothing and returns false. - template <typename Op, typename... Types> - static bool Call(Variant<Types...>* variant, Op&& op) { - static_assert( - detail::Set<Types...>::template IsSubset<ValidTypes...>::value, - "ValidTypes may only contain element types from the Variant."); - return variant->Visit(CallOp<Op>{std::forward<Op>(op)}); - } - template <typename Op, typename... Types> - static bool Call(const Variant<Types...>* variant, Op&& op) { - static_assert( - detail::Set<Types...>::template IsSubset<ValidTypes...>::value, - "ValidTypes may only contain element types from the Variant."); - return variant->Visit(CallOp<Op>{std::forward<Op>(op)}); - } - - // Gets/converts the underlying value of the variant to type T and returns - // true when the variant is a valid type, otherwise does nothing and returns - // false. - template <typename T, typename... Types> - static bool Get(const Variant<Types...>* variant, T* value_out) { - return Call(variant, - [value_out](const auto& value) { *value_out = value; }); - } - - // Moves the underlying value of the variant and returns true when the variant - // is a valid type, otherwise does nothing and returns false. - template <typename T, typename... Types> - static bool Take(Variant<Types...>* variant, T* value_out) { - return Call(variant, - [value_out](auto&& value) { *value_out = std::move(value); }); - } - - // Swaps the underlying value of the variant with |*value_out| and returns - // true when the variant is a valid type, otherwise does nothing and returns - // false. - template <typename T, typename... Types> - static bool Swap(Variant<Types...>* variant, T* value_out) { - return Call(variant, - [value_out](auto&& value) { std::swap(*value_out, value); }); - } - - private: - template <typename Op> - struct CallOp { - Op&& op; - template <typename U> - detail::EnableIfNotElement<bool, U, ValidTypes...> operator()(U&&) { - return false; - } - template <typename U> - detail::EnableIfElement<bool, U, ValidTypes...> operator()(const U& value) { - std::forward<Op>(op)(value); - return true; - } - template <typename U> - detail::EnableIfElement<bool, U, ValidTypes...> operator()(U&& value) { - std::forward<Op>(op)(std::forward<U>(value)); - return true; - } - }; -}; - -} // namespace rpc -} // namespace pdx -} // namespace android - -// Overloads of std::get<T> and std::get<I> for android::pdx::rpc::Variant. -namespace std { - -template <typename T, typename... Types> -inline T& get(::android::pdx::rpc::Variant<Types...>& v) { - return *v.template get<T>(); -} -template <typename T, typename... Types> -inline T&& get(::android::pdx::rpc::Variant<Types...>&& v) { - return std::move(*v.template get<T>()); -} -template <typename T, typename... Types> -inline const T& get(const ::android::pdx::rpc::Variant<Types...>& v) { - return *v.template get<T>(); -} -template <std::size_t I, typename... Types> -inline ::android::pdx::rpc::detail::TypeForIndex<I, Types...>& get( - ::android::pdx::rpc::Variant<Types...>& v) { - return *v.template get<I>(); -} -template <std::size_t I, typename... Types> -inline ::android::pdx::rpc::detail::TypeForIndex<I, Types...>&& get( - ::android::pdx::rpc::Variant<Types...>&& v) { - return std::move(*v.template get<I>()); -} -template <std::size_t I, typename... Types> -inline const ::android::pdx::rpc::detail::TypeForIndex<I, Types...>& get( - const ::android::pdx::rpc::Variant<Types...>& v) { - return *v.template get<I>(); -} - -} // namespace std - -#endif // ANDROID_PDX_RPC_VARIANT_H_ diff --git a/libs/vr/libpdx/private/pdx/service.h b/libs/vr/libpdx/private/pdx/service.h deleted file mode 100644 index f5a2d5edd6..0000000000 --- a/libs/vr/libpdx/private/pdx/service.h +++ /dev/null @@ -1,759 +0,0 @@ -#ifndef ANDROID_PDX_SERVICE_H_ -#define ANDROID_PDX_SERVICE_H_ - -#include <errno.h> -#include <log/log.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> - -#include <algorithm> -#include <memory> -#include <mutex> -#include <string> -#include <unordered_map> -#include <vector> - -#include "pdx/channel_handle.h" -#include "pdx/file_handle.h" -#include "pdx/message_reader.h" -#include "pdx/message_writer.h" -#include "pdx/service_endpoint.h" - -namespace android { -namespace pdx { - -class Service; - -namespace opcodes { - -/* - * Reserved message opcodes used by libpdx. The reserved opcodes start at the - * max positive signed integer for the system and go down. - * In contrast, service opcodes start at zero and go up. This scheme leaves - * most of the positive integer space for services, a tiny fraction of the - * positive integer space for the framework, and the entire negative integer - * space for the kernel. - */ -#define PDX_OPCODE(name, n) name = ((-1U >> 1) - (n)) // 0x7fff..ffff - n - -enum { - // System message sent when a new client channel is open. - CHANNEL_OPEN = -1, - // System message sent when a channel is closed. - CHANNEL_CLOSE = -2, - // Request the service to reload system properties. - PDX_OPCODE(REPORT_SYSPROP_CHANGE, 0), - // Request the service to dump state and return it in a text buffer. - PDX_OPCODE(DUMP_STATE, 1), -}; - -} // namespace opcodes - -/* - * Base class of service-side per-channel context classes. - */ -class Channel : public std::enable_shared_from_this<Channel> { - public: - Channel() {} - virtual ~Channel() {} - - /* - * Accessors to the pid of the last active client. - */ - pid_t GetActiveProcessId() const { return client_pid_; } - void SetActiveProcessId(pid_t pid) { client_pid_ = pid; } - - /* - * Utility to get a shared_ptr reference from the channel context pointer. - */ - static std::shared_ptr<Channel> GetFromMessageInfo(const MessageInfo& info); - - private: - pid_t client_pid_ = 0; -}; - -/* - * Message class represents an RPC message, and implicitly the blocked sender - * waiting for a response. Every message should get a reply, at some point - * (unless the endpoint is closed), to prevent clients from blocking - * indefinitely. In order to enforce this and prevent leaking message ids, - * Message automatically replies with an error to the client on destruction, - * unless one of two things happens: - * - * 1. The service calls one of the reply methods before the Message is - * destroyed. - * 2. The responsibility for the message is moved to another instance of - * Message, using either move construction or move assignment. - * - * The second case is useful for services that need to delay responding to a - * sender until a later time. In this situation the service can move the - * Message to another instance in a suitable data structure for later use. The - * moved-to Message then takes on the same behavior and responsibilities - * described above. - */ -class Message : public OutputResourceMapper, public InputResourceMapper { - public: - Message(); - explicit Message(const MessageInfo& info); - ~Message(); - - /* - * Message objects support move construction and assignment. - */ - Message(Message&& other) noexcept; - Message& operator=(Message&& other) noexcept; - - /* - * Read/write payload, in either single buffer or iovec form. - */ - Status<size_t> ReadVector(const iovec* vector, size_t vector_length); - Status<size_t> Read(void* buffer, size_t length); - Status<size_t> WriteVector(const iovec* vector, size_t vector_length); - Status<size_t> Write(const void* buffer, size_t length); - - template <size_t N> - inline Status<size_t> ReadVector(const iovec (&vector)[N]) { - return ReadVector(vector, N); - } - - template <size_t N> - inline Status<size_t> WriteVector(const iovec (&vector)[N]) { - return WriteVector(vector, N); - } - - // Helper functions to read/write all requested bytes, and return EIO if not - // all were read/written. - Status<void> ReadVectorAll(const iovec* vector, size_t vector_length); - Status<void> WriteVectorAll(const iovec* vector, size_t vector_length); - - inline Status<void> ReadAll(void* buffer, size_t length) { - Status<size_t> status = Read(buffer, length); - if (status && status.get() < length) - status.SetError(EIO); - Status<void> ret; - ret.PropagateError(status); - return ret; - } - inline Status<void> WriteAll(const void* buffer, size_t length) { - Status<size_t> status = Write(buffer, length); - if (status && status.get() < length) - status.SetError(EIO); - Status<void> ret; - ret.PropagateError(status); - return ret; - } - - template <size_t N> - inline Status<void> ReadVectorAll(const iovec (&vector)[N]) { - return ReadVectorAll(vector, N); - } - - template <size_t N> - inline Status<void> WriteVectorAll(const iovec (&vector)[N]) { - return WriteVectorAll(vector, N); - } - - // OutputResourceMapper - Status<FileReference> PushFileHandle(const LocalHandle& handle) override; - Status<FileReference> PushFileHandle(const BorrowedHandle& handle) override; - Status<FileReference> PushFileHandle(const RemoteHandle& handle) override; - Status<ChannelReference> PushChannelHandle( - const LocalChannelHandle& handle) override; - Status<ChannelReference> PushChannelHandle( - const BorrowedChannelHandle& handle) override; - Status<ChannelReference> PushChannelHandle( - const RemoteChannelHandle& handle) override; - - // InputResourceMapper - bool GetFileHandle(FileReference ref, LocalHandle* handle) override; - bool GetChannelHandle(ChannelReference ref, - LocalChannelHandle* handle) override; - - /* - * Various ways to reply to a message. - */ - Status<void> Reply(int return_code); - Status<void> ReplyError(unsigned int error); - Status<void> ReplyFileDescriptor(unsigned int fd); - Status<void> Reply(const LocalHandle& handle); - Status<void> Reply(const BorrowedHandle& handle); - Status<void> Reply(const RemoteHandle& handle); - Status<void> Reply(const LocalChannelHandle& handle); - Status<void> Reply(const BorrowedChannelHandle& handle); - Status<void> Reply(const RemoteChannelHandle& handle); - - template <typename T> - inline Status<void> Reply(const Status<T>& status) { - return status ? Reply(status.get()) : ReplyError(status.error()); - } - - inline Status<void> Reply(const Status<void>& status) { - return status ? Reply(0) : ReplyError(status.error()); - } - - /* - * Update the channel event bits with the given clear and set masks. - */ - Status<void> ModifyChannelEvents(int clear_mask, int set_mask); - - /* - * Create a new channel and push it as a file descriptor to the client. See - * Service::PushChannel() for a detail description of this method's operation. - */ - Status<RemoteChannelHandle> PushChannel( - int flags, const std::shared_ptr<Channel>& channel, int* channel_id); - - /* - * Create a new channel and push it as a file descriptor to the client. See - * Service::PushChannel() for a detail description of this method's operation. - */ - Status<RemoteChannelHandle> PushChannel( - Service* service, int flags, const std::shared_ptr<Channel>& channel, - int* channel_id); - - /* - * Check whether the |ref| is a reference to channel to this service. - * If the channel reference in question is valid, the Channel object is - * returned in |channel| when non-nullptr. - * - * Return values: - * channel_id - id of the channel if the |ref| is a valid reference to - * this service's channel. - * Errors: - * EOPNOTSUPP - the file descriptor is not a channel or is a channel to - * another service. - * EBADF - the file descriptor is invalid. - * FAULT - |channel_id| or |channel| are non-nullptr and point to invalid - * memory addresses. - * EINVAL - the value of |ref| is invalid or the message id for this - * message is no longer valid. - */ - Status<int> CheckChannel(ChannelReference ref, - std::shared_ptr<Channel>* channel) const; - - /* - * Overload of CheckChannel() that checks whether the channel reference is for - * a channel to the service |service|. - */ - Status<int> CheckChannel(const Service* service, ChannelReference ref, - std::shared_ptr<Channel>* channel) const; - - /* - * Overload of CheckChannel() that automatically converts to shared pointers - * to types derived from Channel. - */ - template <class C> - Status<int> CheckChannel(ChannelReference ref, - std::shared_ptr<C>* channel) const { - std::shared_ptr<Channel> base_pointer; - const Status<int> ret = - CheckChannel(ref, channel ? &base_pointer : nullptr); - if (channel) - *channel = std::static_pointer_cast<C>(base_pointer); - return ret; - } - - template <class C> - Status<int> CheckChannel(const Service* service, ChannelReference ref, - std::shared_ptr<C>* channel) const { - std::shared_ptr<Channel> base_pointer; - const Status<int> ret = - CheckChannel(service, ref, channel ? &base_pointer : nullptr); - if (channel) - *channel = std::static_pointer_cast<C>(base_pointer); - return ret; - } - - /* - * MessageInfo accessors. - */ - pid_t GetProcessId() const; - pid_t GetThreadId() const; - uid_t GetEffectiveUserId() const; - gid_t GetEffectiveGroupId() const; - int GetChannelId() const; - int GetMessageId() const; - int GetOp() const; - int GetFlags() const; - size_t GetSendLength() const; - size_t GetReceiveLength() const; - size_t GetFileDescriptorCount() const; - - /* - * Impulses are asynchronous and cannot be replied to. All impulses have this - * invalid message id. - */ - enum { IMPULSE_MESSAGE_ID = -1 }; - - /* - * Returns true if this Message describes an asynchronous "impulse" message. - */ - bool IsImpulse() const { return GetMessageId() == IMPULSE_MESSAGE_ID; } - - /* - * Returns a pointer to the impulse payload. Impulses are a maximum of 32 - * bytes in size and the start of the impulse payload is guaranteed to be - * 8-byte aligned. Use GetSendLength() to determine the payload size. - */ - const std::uint8_t* ImpulseBegin() const; - - /* - * Returns one byte past the end of the impulse payload, as conventional for - * STL iterators. - */ - const std::uint8_t* ImpulseEnd() const; - - /* - * Get/set the Channel object for the channel associated - * with this message. It is up to the caller to synchronize - * these in multi-threaded services. - */ - std::shared_ptr<Channel> GetChannel() const; - Status<void> SetChannel(const std::shared_ptr<Channel>& channnel); - - /* - * Get the Channel object for the channel associated with this message, - * automatically converted to the desired subclass of Channel. - */ - template <class C> - std::shared_ptr<C> GetChannel() const { - return std::static_pointer_cast<C>(GetChannel()); - } - - /* - * Gets the service this message was received on. Returns nullptr if the - * service was destroyed. - */ - std::shared_ptr<Service> GetService() const; - - /* - * Raw access to the MessageInfo for this message. - */ - const MessageInfo& GetInfo() const; - - bool replied() const { return replied_; } - bool IsChannelExpired() const { return channel_.expired(); } - bool IsServiceExpired() const { return service_.expired(); } - - /* - * Returns true if the message is non-empty; that is the message can be - * replied to using this instance. - */ - explicit operator bool() const { return !replied_; } - - const void* GetState() const { return state_; } - void* GetState() { return state_; } - - private: - friend class Service; - - Message(const Message&) = delete; - void operator=(const Message&) = delete; - void Destroy(); - - std::weak_ptr<Service> service_; - std::weak_ptr<Channel> channel_; - MessageInfo info_; - void* state_{nullptr}; - bool replied_; -}; - -// Base class for RPC services. -class Service : public std::enable_shared_from_this<Service> { - public: - Service(const std::string& name, std::unique_ptr<Endpoint> endpoint); - virtual ~Service(); - - /* - * Utility to get a shared_ptr reference from the service context pointer. - */ - static std::shared_ptr<Service> GetFromMessageInfo(const MessageInfo& info); - - /* - * Returns whether initialization was successful. Subclasses that override - * this must call this base method and AND the results with their own. This - * method is not intended to do any initialization work itself, only to - * signal success or failure. - */ - virtual bool IsInitialized() const; - - /* - * Called by defaultHandleMessage in response to a CHANNEL_OPEN message. - * This gives subclasses of Service a convenient hook to create per-channel - * context in the form of a Channel subclass. - * - * The Channel instance returned by this is used to set the channel context - * pointer for the channel that was just opened. - */ - virtual std::shared_ptr<Channel> OnChannelOpen(Message& message); - - /* - * Called by defaultHandleMessage in response to a CHANNEL_CLOSE message. - * This give subclasses of Service a convenient hook to clean up per-channel - * context. - */ - virtual void OnChannelClose(Message& message, - const std::shared_ptr<Channel>& channel); - - /* - * Set the channel context for the given channel. This keeps a reference to - * the Channel object until the channel is closed or another call replaces - * the current value. - */ - Status<void> SetChannel(int channel_id, - const std::shared_ptr<Channel>& channel); - - /* - * Get the channel context for the given channel id. This method should be - * used sparingly because of the performance characteristics of the underlying - * map; it is intended for limited, non-critical path access from outside of - * message dispatch. In most cases lookup by id should be unnecessary in a - * properly designed service; Message::GetChannel() should be used instead - * whenever an operation is in the context of a message. - * - * Again, if you lookup a channel context object for a service by id in a - * message handling path for the same service, you're probably doing something - * wrong. - */ - std::shared_ptr<Channel> GetChannel(int channel_id) const; - - /* - * Get a snapshot of the active channels for this service. This is the - * preferred way to access the set of channels because it avoids potential - * deadlocks and race conditions that may occur when operating on the channel - * map directly. However, it is more expensive than direct iteration because - * of dynamic memory allocation and shared pointer reference costs. - * - * Automatically converts returned items to shared pointers of the type - * std::shared_ptr<C>, where C is the subclass of Channel used by the service. - */ - template <class C> - std::vector<std::shared_ptr<C>> GetChannels() const { - std::lock_guard<std::mutex> autolock(channels_mutex_); - std::vector<std::shared_ptr<C>> items; - items.reserve(channels_.size()); - - for (const auto& pair : channels_) { - items.push_back(std::static_pointer_cast<C>(pair.second)); - } - - return items; - } - - /* - * Close a channel, signaling the client file object and freeing the channel - * id. Once closed, the client side of the channel always returns the error - * ESHUTDOWN and signals the poll/epoll events POLLHUP and POLLFREE. - * - * The internal reference to the Channel instance associated with the channel - * is removed, which may result in the Channel object being freed. - * - * OnChannelClosed is not called in response to this method call. - */ - Status<void> CloseChannel(int channel_id); - - /* - * Update the event bits for the given channel (given by id), using the - * given clear and set masks. - * - * This is useful for asynchronously signaling events that clients may be - * waiting for using select/poll/epoll. - */ - Status<void> ModifyChannelEvents(int channel_id, int clear_mask, - int set_mask); - - /* - * Create a new channel and push it as a file descriptor to the process - * sending the |message|. |flags| may be set to O_NONBLOCK and/or - * O_CLOEXEC to control the initial behavior of the new file descriptor (the - * sending process may change these later using fcntl()). The internal Channel - * instance associated with this channel is set to |channel|, which may be - * nullptr. The new channel id allocated for this channel is returned in - * |channel_id|, which may also be nullptr if not needed. - * - * On success, returns the remote channel handle for the new channel in the - * sending process' handle space. This MUST be returned to the sender via - * Message::Reply(), Message::Write(), or Message::WriteVector(). - * - * On error, returns an errno code describing the cause of the error. - * - * Service::OnChannelCreate() is not called in response to the creation of the - * new channel. - */ - Status<RemoteChannelHandle> PushChannel( - Message* message, int flags, const std::shared_ptr<Channel>& channel, - int* channel_id); - - /* - * Check whether the |ref| is a reference to a channel to this service. - * If the channel reference in question is valid, the Channel object is - * returned in |channel| when non-nullptr. - * - * Return values: - * channel_id - id of the channel if the channel reference. - * Errors: - * EOPNOTSUPP - the file descriptor is not a channel or is a channel to - * another service. - * EBADF - the file descriptor is invalid. - * FAULT - |channel_id| or |channel| are non-nullptr and point to invalid - * memory addresses. - * EINVAL - the value of |ref| is invalid or the message id for this - * message is no longer valid. - */ - Status<int> CheckChannel(const Message* message, ChannelReference ref, - std::shared_ptr<Channel>* channel) const; - - /* - * Overload of CheckChannel() that automatically converts to shared pointers - * of types derived from Channel. - */ - template <class C> - Status<int> CheckChannel(const Message* message, ChannelReference ref, - std::shared_ptr<C>* channel) const { - std::shared_ptr<Channel> base_pointer; - const Status<int> ret = - CheckChannel(message, ref, channel ? &base_pointer : nullptr); - if (channel) - *channel = std::static_pointer_cast<C>(base_pointer); - return ret; - } - - /* - * Handle a message. Subclasses override this to receive messages and decide - * how to dispatch them. - * - * The default implementation simply calls defaultHandleMessage(). - * Subclasses should call the same for any unrecognized message opcodes. - */ - virtual Status<void> HandleMessage(Message& message); - - /* - * Handle an asynchronous message. Subclasses override this to receive - * asynchronous "impulse" messages. Impulses have a limited-size payload that - * is transferred upfront with the message description. - */ - virtual void HandleImpulse(Message& impulse); - - /* - * The default message handler. It is important that all messages - * (eventually) get a reply. This method should be called by subclasses for - * any unrecognized opcodes or otherwise unhandled messages to prevent - * erroneous requests from blocking indefinitely. - * - * Provides default handling of CHANNEL_OPEN and CHANNEL_CLOSE, calling - * OnChannelOpen() and OnChannelClose(), respectively. - * - * For all other message opcodes, this method replies with ENOTSUP. - */ - Status<void> DefaultHandleMessage(Message& message); - - /* - * Called when system properties have changed. Subclasses should implement - * this method if they need to handle when system properties change. - */ - virtual void OnSysPropChange(); - - /* - * Get the endpoint for the service. - */ - Endpoint* endpoint() const { return endpoint_.get(); } - - /* - * Cancels the endpoint, unblocking any receiver threads waiting in - * ReceiveAndDispatch(). - */ - Status<void> Cancel(); - - /* - * Iterator type for Channel map iterators. - */ - using ChannelIterator = - std::unordered_map<int, std::shared_ptr<Channel>>::iterator; - - /* - * Iterates over the Channel map and performs the action given by |action| on - * each channel map item (const ChannelIterator::value_type). - * |channels_mutex_| is not held; it is the responsibility of the caller to - * ensure serialization between threads that modify or iterate over the - * Channel map. - */ - template <class A> - void ForEachChannelUnlocked(A action) const { - std::for_each(channels_.begin(), channels_.end(), action); - } - - /* - * Iterates over the Channel map and performs the action given by |action| on - * each channel map item (const ChannelIterator::value_type). - * |channels_mutex_| is held to serialize access to the map; care must be - * taken to avoid recursively acquiring the mutex, for example, by calling - * Service::{GetChannel,SetChannel,CloseChannel,PushChannel}() or - * Message::SetChannel() in the action. - */ - template <class A> - void ForEachChannel(A action) const { - std::lock_guard<std::mutex> autolock(channels_mutex_); - ForEachChannelUnlocked(action); - } - - /* - * Return true if a channel with the given ID exists in the Channel map. - */ - bool HasChannelId(int channel_id) const { - std::lock_guard<std::mutex> autolock(channels_mutex_); - return channels_.find(channel_id) != channels_.end(); - } - - /* - * Subclasses of Service may override this method to provide a text string - * describing the state of the service. This method is called by - * HandleSystemMessage in response to the standard - * DUMP_STATE message. The string returned to the dump state client is - * truncated to |max_length| and reflects the maximum size the client can - * handle. - */ - virtual std::string DumpState(size_t max_length); - - /* - * Receives a message on this Service instance's endpoint and dispatches it. - * If the endpoint is in blocking mode this call blocks until a message is - * received, a signal is delivered to this thread, or the service is canceled. - * If the endpoint is in non-blocking mode and a message is not pending this - * call returns immediately with ETIMEDOUT. - */ - Status<void> ReceiveAndDispatch(); - - private: - friend class Message; - - Status<void> HandleSystemMessage(Message& message); - - Service(const Service&); - void operator=(const Service&) = delete; - - const std::string name_; - std::unique_ptr<Endpoint> endpoint_; - - /* - * Maintains references to active channels. - */ - mutable std::mutex channels_mutex_; - std::unordered_map<int, std::shared_ptr<Channel>> channels_; -}; - -/* - * Utility base class for services. This template handles allocation and - * initialization checks, reducing boiler plate code. - */ -template <typename TYPE> -class ServiceBase : public Service { - public: - /* - * Static service allocation method that check for initialization errors. - * If errors are encountered these automatically clean up and return - * nullptr. - */ - template <typename... Args> - static inline std::shared_ptr<TYPE> Create(Args&&... args) { - std::shared_ptr<TYPE> service(new TYPE(std::forward<Args>(args)...)); - if (service->IsInitialized()) - return service; - else - return nullptr; - } - - protected: - /* - * Shorthand for subclasses to refer to this base, particularly - * to call the base class constructor. - */ - typedef ServiceBase<TYPE> BASE; - - ServiceBase(const std::string& name, std::unique_ptr<Endpoint> endpoint) - : Service(name, std::move(endpoint)) {} -}; - -#ifndef STRINGIFY -#define STRINGIFY2(s) #s -#define STRINGIFY(s) STRINGIFY2(s) -#endif - -#define PDX_ERROR_PREFIX "[" __FILE__ ":" STRINGIFY(__LINE__) "]" - -/* - * Macros for replying to messages. Error handling can be tedious; - * these macros make things a little cleaner. - */ -#define CHECK_ERROR(cond, error, fmt, ...) \ - do { \ - if ((cond)) { \ - ALOGE(fmt, ##__VA_ARGS__); \ - goto error; \ - } \ - } while (0) - -#define REPLY_ERROR(message, error, error_label) \ - do { \ - auto __status = message.ReplyError(error); \ - CHECK_ERROR(!__status, error_label, \ - PDX_ERROR_PREFIX " Failed to reply to message because: %s\n", \ - __status.GetErrorMessage().c_str()); \ - goto error_label; \ - } while (0) - -#define REPLY_ERROR_RETURN(message, error, ...) \ - do { \ - auto __status = message.ReplyError(error); \ - ALOGE_IF(!__status, \ - PDX_ERROR_PREFIX " Failed to reply to message because: %s", \ - __status.GetErrorMessage().c_str()); \ - return __VA_ARGS__; \ - } while (0) - -#define REPLY_MESSAGE(message, message_return_code, error_label) \ - do { \ - auto __status = message.Reply(message_return_code); \ - CHECK_ERROR(!__status, error_label, \ - PDX_ERROR_PREFIX " Failed to reply to message because: %s\n", \ - __status.GetErrorMessage().c_str()); \ - goto error_label; \ - } while (0) - -#define REPLY_SUCCESS(message, message_return_code, error_label) \ - REPLY_MESSAGE(message, message_return_code, error_label) - -#define REPLY_MESSAGE_RETURN(message, message_return_code, ...) \ - do { \ - auto __status = message.Reply(message_return_code); \ - ALOGE_IF(!__status, \ - PDX_ERROR_PREFIX " Failed to reply to message because: %s", \ - __status.GetErrorMessage().c_str()); \ - return __VA_ARGS__; \ - } while (0) - -#define REPLY_SUCCESS_RETURN(message, message_return_code, ...) \ - REPLY_MESSAGE_RETURN(message, message_return_code, __VA_ARGS__) - -#define REPLY_FD(message, push_fd, error_label) \ - do { \ - auto __status = message.ReplyFileDescriptor(push_fd); \ - CHECK_ERROR(!__status, error_label, \ - PDX_ERROR_PREFIX " Failed to reply to message because: %s\n", \ - __status.GetErrorMessage().c_str()); \ - goto error_label; \ - } while (0) - -#define REPLY_FD_RETURN(message, push_fd, ...) \ - do { \ - auto __status = message.ReplyFileDescriptor(push_fd); \ - ALOGE_IF(__status < 0, \ - PDX_ERROR_PREFIX " Failed to reply to message because: %s", \ - __status.GetErrorMessage().c_str()); \ - return __VA_ARGS__; \ - } while (0) - -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_SERVICE_H_ diff --git a/libs/vr/libpdx/private/pdx/service_dispatcher.h b/libs/vr/libpdx/private/pdx/service_dispatcher.h deleted file mode 100644 index bd27000dc9..0000000000 --- a/libs/vr/libpdx/private/pdx/service_dispatcher.h +++ /dev/null @@ -1,107 +0,0 @@ -#ifndef ANDROID_PDX_SERVICE_DISPATCHER_H_ -#define ANDROID_PDX_SERVICE_DISPATCHER_H_ - -#include <memory> -#include <mutex> -#include <unordered_map> -#include <vector> - -#include <pdx/file_handle.h> - -namespace android { -namespace pdx { - -class Service; - -/* - * ServiceDispatcher manages a list of Service instances and handles message - * reception and dispatch to the services. This makes repetitive dispatch tasks - * easier to implement. - */ -class ServiceDispatcher { - public: - // Get a new instance of ServiceDispatcher, or return nullptr if init failed. - static std::unique_ptr<ServiceDispatcher> Create(); - - ~ServiceDispatcher(); - - /* - * Adds a service to the list of services handled by this dispatcher. This - * will fail if any threads are blocked waiting for messages in this - * dispatcher. - * - * Returns 0 on success; -EEXIST if the service was already added. - */ - int AddService(const std::shared_ptr<Service>& service); - - /* - * Removes a service from this dispatcher. This will fail if any threads are - * blocked waiting for messages in this dispatcher. - * - * Returns 0 on success; -ENOENT if the service was not previously added; - * -EBUSY if there are threads in the dispatcher. - */ - int RemoveService(const std::shared_ptr<Service>& service); - - /* - * Receive and dispatch one set of messages. Multiple threads may enter this - * method to create an implicit thread pool, as described for - * enterDispatchLoop() below, however this method exits after one dispatch - * cycle, requiring an external loop. This is useful when other work needs - * to be done in the service dispatch loop. - */ - int ReceiveAndDispatch(); - - /* - * Same as above with timeout in milliseconds. A negative value means - * infinite timeout, while a value of 0 means return immediately if no - * messages are available to receive. - */ - int ReceiveAndDispatch(int timeout); - - /* - * Receive and dispatch messages until canceled. When more than one thread - * enters this method it creates an implicit thread pool to dispatch messages. - * Explicit thread pools may be created by using a single dispatch thread that - * hands Message instances (via move assignment) over to a queue of threads - * (or perhaps one of several) to handle. - */ - int EnterDispatchLoop(); - - /* - * Sets the canceled state of the dispatcher. When canceled is true, any - * threads blocked waiting for messages will return. This method waits until - * all dispatch threads have exited the dispatcher. - */ - void SetCanceled(bool cancel); - - /* - * Gets the canceled state of the dispatcher. - */ - bool IsCanceled() const; - - private: - ServiceDispatcher(); - - // Internal thread accounting. - int ThreadEnter(); - void ThreadExit(); - - std::mutex mutex_; - std::condition_variable condition_; - std::atomic<bool> canceled_{false}; - - std::vector<std::shared_ptr<Service>> services_; - - int thread_count_ = 0; - LocalHandle event_fd_; - LocalHandle epoll_fd_; - - ServiceDispatcher(const ServiceDispatcher&) = delete; - void operator=(const ServiceDispatcher&) = delete; -}; - -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_SERVICE_DISPATCHER_H_ diff --git a/libs/vr/libpdx/private/pdx/service_endpoint.h b/libs/vr/libpdx/private/pdx/service_endpoint.h deleted file mode 100644 index d58189499c..0000000000 --- a/libs/vr/libpdx/private/pdx/service_endpoint.h +++ /dev/null @@ -1,148 +0,0 @@ -#ifndef ANDROID_PDX_ENDPOINT_H_ -#define ANDROID_PDX_ENDPOINT_H_ - -#include <pdx/channel_handle.h> -#include <pdx/file_handle.h> -#include <pdx/status.h> - -struct iovec; - -namespace android { -namespace pdx { - -class Service; -class Channel; -class Message; - -struct MessageInfo { - int pid{0}; - int tid{0}; - int cid{0}; - int mid{0}; - int euid{0}; - int egid{0}; - int32_t op{0}; - uint32_t flags{0}; - Service* service{nullptr}; - Channel* channel{nullptr}; - size_t send_len{0}; - size_t recv_len{0}; - size_t fd_count{0}; - uint64_t impulse[4] = {}; -}; - -// Wrapper around transport endpoint. Abstracts the underlying transport APIs in -// a way, that the underlying IPC can be substituted for another technology -// without changing the Service, Client and Message classes of this library. -class Endpoint { - public: - virtual ~Endpoint() = default; - - // Returns a tag that uniquely identifies a specific underlying IPC transport. - virtual uint32_t GetIpcTag() const = 0; - - // Associates a Service instance with an endpoint by setting the service - // context pointer to the address of the Service. Only one Service may be - // associated with a given endpoint. - virtual Status<void> SetService(Service* service) = 0; - - // Set the channel context for the given channel. - virtual Status<void> SetChannel(int channel_id, Channel* channel) = 0; - - // Close a channel, signaling the client file object and freeing the channel - // id. Once closed, the client side of the channel always returns the error - // ESHUTDOWN and signals the poll/epoll events POLLHUP and POLLFREE. - virtual Status<void> CloseChannel(int channel_id) = 0; - - // Update the event bits for the given channel (given by id), using the - // given clear and set masks. - virtual Status<void> ModifyChannelEvents(int channel_id, int clear_mask, - int set_mask) = 0; - - // Create a new channel and push it as a file descriptor to the process - // sending the |message|. |flags| may be set to O_NONBLOCK and/or - // O_CLOEXEC to control the initial behavior of the new file descriptor (the - // sending process may change these later using fcntl()). The internal Channel - // instance associated with this channel is set to |channel|, which may be - // nullptr. The new channel id allocated for this channel is returned in - // |channel_id|, which may also be nullptr if not needed. - virtual Status<RemoteChannelHandle> PushChannel(Message* message, int flags, - Channel* channel, - int* channel_id) = 0; - - // Check whether the |ref| is a reference to a channel to the service - // represented by the |endpoint|. If the channel reference in question is - // valid, the Channel object is returned in |channel| when non-nullptr and - // the channel ID is returned through the Status object. - virtual Status<int> CheckChannel(const Message* message, ChannelReference ref, - Channel** channel) = 0; - - // Receives a message on the given endpoint file descriptor. - virtual Status<void> MessageReceive(Message* message) = 0; - - // Replies to the message with a return code. - virtual Status<void> MessageReply(Message* message, int return_code) = 0; - - // Replies to the message with a file descriptor. - virtual Status<void> MessageReplyFd(Message* message, - unsigned int push_fd) = 0; - - // Replies to the message with a local channel handle. - virtual Status<void> MessageReplyChannelHandle( - Message* message, const LocalChannelHandle& handle) = 0; - - // Replies to the message with a borrowed local channel handle. - virtual Status<void> MessageReplyChannelHandle( - Message* message, const BorrowedChannelHandle& handle) = 0; - - // Replies to the message with a remote channel handle. - virtual Status<void> MessageReplyChannelHandle( - Message* message, const RemoteChannelHandle& handle) = 0; - - // Reads message data into an array of memory buffers. - virtual Status<size_t> ReadMessageData(Message* message, const iovec* vector, - size_t vector_length) = 0; - - // Sends reply data for message. - virtual Status<size_t> WriteMessageData(Message* message, const iovec* vector, - size_t vector_length) = 0; - - // Records a file descriptor into the message buffer and returns the remapped - // reference to be sent to the remote process. - virtual Status<FileReference> PushFileHandle(Message* message, - const LocalHandle& handle) = 0; - virtual Status<FileReference> PushFileHandle( - Message* message, const BorrowedHandle& handle) = 0; - virtual Status<FileReference> PushFileHandle(Message* message, - const RemoteHandle& handle) = 0; - virtual Status<ChannelReference> PushChannelHandle( - Message* message, const LocalChannelHandle& handle) = 0; - virtual Status<ChannelReference> PushChannelHandle( - Message* message, const BorrowedChannelHandle& handle) = 0; - virtual Status<ChannelReference> PushChannelHandle( - Message* message, const RemoteChannelHandle& handle) = 0; - - // Obtains a file descriptor/channel handle from a message for the given - // reference. - virtual LocalHandle GetFileHandle(Message* message, - FileReference ref) const = 0; - virtual LocalChannelHandle GetChannelHandle(Message* message, - ChannelReference ref) const = 0; - - // Transport-specific message state management. - virtual void* AllocateMessageState() = 0; - virtual void FreeMessageState(void* state) = 0; - - // Cancels the endpoint, unblocking any receiver threads waiting for a - // message. - virtual Status<void> Cancel() = 0; - - // Returns an fd that can be used with epoll() to wait for incoming messages - // from this endpoint. - virtual int epoll_fd() const = 0; -}; - -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_ENDPOINT_H_ diff --git a/libs/vr/libpdx/private/pdx/status.h b/libs/vr/libpdx/private/pdx/status.h deleted file mode 100644 index 498dd6dfd9..0000000000 --- a/libs/vr/libpdx/private/pdx/status.h +++ /dev/null @@ -1,183 +0,0 @@ -#ifndef ANDROID_PDX_STATUS_H_ -#define ANDROID_PDX_STATUS_H_ - -#include <algorithm> -#include <memory> -#include <string> - -namespace android { -namespace pdx { - -// This is a helper class for constructing Status<T> with an error code. -struct ErrorStatus { - public: - // NOLINTNEXTLINE(google-explicit-constructor) - ErrorStatus(int error) : error_{error} {} - int error() const { return error_; } - - static std::string ErrorToString(int error_code); - - private: - int error_; -}; - -// Status<T> is a container class that can be used to return a value of type T -// or error code to the caller. -template <typename T> -class Status { - public: - // Default constructor so an empty Status object can be created. - Status() : error_{-1} {} - - // Value copy/move constructors. These are intentionally not marked as - // explicit to allow direct value returns from functions without having - // to explicitly wrap them into Status<T>(). - // NOLINTNEXTLINE(google-explicit-constructor) - Status(const T& value) : value_{value} {} - // NOLINTNEXTLINE(google-explicit-constructor) - Status(T&& value) : value_{std::move(value)} {} - - // Constructor for storing an error code inside the Status object. - // NOLINTNEXTLINE(google-explicit-constructor) - Status(const ErrorStatus& error_status) : error_{error_status.error()} {} - - // Copy/move constructors. Move constructor leaves |other| object in empty - // state. - Status(const Status& other) = default; - Status(Status&& other) noexcept - : value_{std::move(other.value_)}, error_{other.error_} { - other.error_ = -1; - } - - // Assignment operators. - Status& operator=(const Status& other) = default; - Status& operator=(Status&& other) noexcept { - error_ = other.error_; - value_ = std::move(other.value_); - other.error_ = -1; - T empty; - std::swap(other.value_, empty); - return *this; - } - - // Change the value/error code of the status object directly. - void SetValue(T value) { - error_ = 0; - value_ = std::move(value); - } - void SetError(int error) { - error_ = error; - T empty; - std::swap(value_, empty); - } - - // If |other| is in error state, copy the error code to this object. - // Returns true if error was propagated - template<typename U> - bool PropagateError(const Status<U>& other) { - if (!other.ok() && !other.empty()) { - SetError(other.error()); - return true; - } - return false; - } - - // Returns true if the status object contains valid value for type T. - // This means, the object is not empty and does not contain an error code. - bool ok() const { return error_ == 0; } - - // Checks if the object is empty (doesn't contain a valid value nor an error). - bool empty() const { return error_ < 0; } - - // Explicit bool conversion, equivalent to invoking ok(). - explicit operator bool() const { return ok(); } - - // Accessors for the value stored in Status. Calling when ok() is false leads - // to undefined behavior. - const T& get() const { return value_; } - T&& take() { - error_ = -1; - return std::move(value_); - } - - // Returns the error code stored in the object. These codes are positive - // non-zero values. - // Can be called only when an error is actually stored (that is, the object - // is not empty nor containing a valid value). - int error() const { return std::max(error_, 0); } - - // Returns the error code as ErrorStatus object. This is a helper method - // to aid in propagation of error codes between Status<T> of different types - // as in the following example: - // Status<int> foo() { - // Status<void> status = bar(); - // if(!status) - // return status.error_status(); - // return 12; - // } - inline ErrorStatus error_status() const { return ErrorStatus{error()}; } - - // Returns the error message associated with error code stored in the object. - // The message is the same as the string returned by strerror(status.error()). - // Can be called only when an error is actually stored (that is, the object - // is not empty nor containing a valid value). - std::string GetErrorMessage() const { - std::string message; - if (error_ > 0) - message = ErrorStatus::ErrorToString(error_); - return message; - } - - private: - T value_{}; - int error_{0}; -}; - -// Specialization for status containing no other value but the error code. -template <> -class Status<void> { - public: - Status() = default; - // NOLINTNEXTLINE(google-explicit-constructor) - Status(const ErrorStatus& error_status) : error_{error_status.error()} {} - void SetValue() { error_ = 0; } - void SetError(int error) { error_ = error; } - - template<typename U> - bool PropagateError(const Status<U>& other) { - if (!other.ok() && !other.empty()) { - SetError(other.error()); - return true; - } - return false; - } - - bool ok() const { return error_ == 0; } - bool empty() const { return false; } - explicit operator bool() const { return ok(); } - int error() const { return std::max(error_, 0); } - inline ErrorStatus error_status() const { return ErrorStatus{error()}; } - std::string GetErrorMessage() const { - std::string message; - if (error_ > 0) - message = ErrorStatus::ErrorToString(error_); - return message; - } - - private: - int error_{0}; -}; - -// TODO(avakulenko): Remove these function once all callers of it are gone. -inline int ReturnStatusOrError(const Status<void>& status) { - return status ? 0 : -status.error(); -} - -inline int ReturnStatusOrError(const Status<int>& status) { - return status ? status.get() : -status.error(); -} - -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_STATUS_H_ diff --git a/libs/vr/libpdx/private/pdx/trace.h b/libs/vr/libpdx/private/pdx/trace.h deleted file mode 100644 index c687fd6259..0000000000 --- a/libs/vr/libpdx/private/pdx/trace.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef ANDROID_PDX_TRACE_H_ -#define ANDROID_PDX_TRACE_H_ - -#include <array> - -#include <utils/Trace.h> - -// Enables internal tracing in libpdx. This is disabled by default to avoid -// spamming the trace buffers during normal trace activities. libpdx must be -// built with this set to true to enable internal tracing. -#ifndef PDX_LIB_TRACE_ENABLED -#define PDX_LIB_TRACE_ENABLED false -#endif - -namespace android { -namespace pdx { - -// Utility to generate scoped tracers with arguments. -class ScopedTraceArgs { - public: - template <typename... Args> - ScopedTraceArgs(uint64_t tag, const char* format, Args&&... args) - : tag_{tag} { - if (atrace_is_tag_enabled(tag_)) { - std::array<char, 1024> buffer; - snprintf(buffer.data(), buffer.size(), format, - std::forward<Args>(args)...); - atrace_begin(tag_, buffer.data()); - } - } - - ~ScopedTraceArgs() { atrace_end(tag_); } - - private: - uint64_t tag_; - - ScopedTraceArgs(const ScopedTraceArgs&) = delete; - void operator=(const ScopedTraceArgs&) = delete; -}; - -// Utility to generate scoped tracers. -class ScopedTrace { - public: - template <typename... Args> - ScopedTrace(uint64_t tag, bool enabled, const char* name) - : tag_{tag}, enabled_{enabled} { - if (enabled_) - atrace_begin(tag_, name); - } - - ~ScopedTrace() { - if (enabled_) - atrace_end(tag_); - } - - private: - uint64_t tag_; - bool enabled_; - - ScopedTrace(const ScopedTrace&) = delete; - void operator=(const ScopedTrace&) = delete; -}; - -} // namespace pdx -} // namespace android - -// Macro to define a scoped tracer with arguments. Uses PASTE(x, y) macro -// defined in utils/Trace.h. -#define PDX_TRACE_FORMAT(format, ...) \ - ::android::pdx::ScopedTraceArgs PASTE(__tracer, __LINE__) { \ - ATRACE_TAG, format, ##__VA_ARGS__ \ - } - -// TODO(eieio): Rename this to PDX_LIB_TRACE_NAME() for internal use by libpdx -// and rename internal uses inside the library. This version is only enabled -// when PDX_LIB_TRACE_ENABLED is true. -#define PDX_TRACE_NAME(name) \ - ::android::pdx::ScopedTrace PASTE(__tracer, __LINE__) { \ - ATRACE_TAG, PDX_LIB_TRACE_ENABLED, name \ - } - -#endif // ANDROID_PDX_TRACE_H_ diff --git a/libs/vr/libpdx/private/pdx/utility.h b/libs/vr/libpdx/private/pdx/utility.h deleted file mode 100644 index c9a0c21dc2..0000000000 --- a/libs/vr/libpdx/private/pdx/utility.h +++ /dev/null @@ -1,369 +0,0 @@ -#ifndef ANDROID_PDX_UTILITY_H_ -#define ANDROID_PDX_UTILITY_H_ - -#include <cstdint> -#include <cstdlib> -#include <iterator> - -#include <pdx/rpc/sequence.h> - -// Utilities for testing object serialization. - -namespace android { -namespace pdx { - -class ByteBuffer { - public: - using iterator = uint8_t*; - using const_iterator = const uint8_t*; - using size_type = size_t; - - ByteBuffer() = default; - ByteBuffer(const ByteBuffer& other) { - resize(other.size()); - if (other.size()) - memcpy(data_, other.data(), other.size()); - } - ~ByteBuffer() { std::free(data_); } - - ByteBuffer& operator=(const ByteBuffer& other) { - resize(other.size()); - if (other.size()) - memcpy(data_, other.data(), other.size()); - return *this; - } - - ByteBuffer& operator=(ByteBuffer&& other) noexcept { - std::swap(data_, other.data_); - std::swap(size_, other.size_); - std::swap(capacity_, other.capacity_); - other.clear(); - return *this; - } - - inline const uint8_t* data() const { return data_; } - inline uint8_t* data() { return data_; } - inline size_t size() const { return size_; } - inline size_t capacity() const { return capacity_; } - - iterator begin() { return data_; } - const_iterator begin() const { return data_; } - iterator end() { return data_ + size_; } - const_iterator end() const { return data_ + size_; } - - inline bool operator==(const ByteBuffer& other) const { - return size_ == other.size_ && - (size_ == 0 || memcmp(data_, other.data_, size_) == 0); - } - - inline bool operator!=(const ByteBuffer& other) const { - return !operator==(other); - } - - inline void reserve(size_t size) { - if (size <= capacity_) - return; - // Find next power of 2 (assuming the size is 32 bits for now). - size--; - size |= size >> 1; - size |= size >> 2; - size |= size >> 4; - size |= size >> 8; - size |= size >> 16; - size++; - void* new_data = data_ ? std::realloc(data_, size) : std::malloc(size); - // TODO(avakulenko): Check for allocation failures. - data_ = static_cast<uint8_t*>(new_data); - capacity_ = size; - } - - inline void resize(size_t size) { - reserve(size); - size_ = size; - } - - inline uint8_t* grow_by(size_t size_delta) { - size_t old_size = size_; - resize(old_size + size_delta); - return data_ + old_size; - } - - inline void clear() { size_ = 0; } - - private: - uint8_t* data_{nullptr}; - size_t size_{0}; - size_t capacity_{0}; -}; - -// Utility functions to increment/decrement void pointers to data buffers. -template <typename OFFSET_T> -inline const void* AdvancePointer(const void* ptr, OFFSET_T offset) { - return static_cast<const uint8_t*>(ptr) + offset; -} - -template <typename OFFSET_T> -inline void* AdvancePointer(void* ptr, OFFSET_T offset) { - return static_cast<uint8_t*>(ptr) + offset; -} - -inline ptrdiff_t PointerDistance(const void* end, const void* begin) { - return static_cast<const uint8_t*>(end) - static_cast<const uint8_t*>(begin); -} - -// Utility to build sequences of types. -template <typename, typename> -struct AppendTypeSequence; - -template <typename T, typename... S, template <typename...> class TT> -struct AppendTypeSequence<T, TT<S...>> { - using type = TT<S..., T>; -}; - -// Utility to generate repeated types. -template <typename T, std::size_t N, template <typename...> class TT> -struct RepeatedType { - using type = typename AppendTypeSequence< - T, typename RepeatedType<T, N - 1, TT>::type>::type; -}; - -template <typename T, template <typename...> class TT> -struct RepeatedType<T, 0, TT> { - using type = TT<>; -}; - -template <typename V, typename S> -inline V ReturnValueHelper(V value, S /*ignore*/) { - return value; -} - -template <typename R, typename V, size_t... S> -inline R GetNTupleHelper(V value, rpc::IndexSequence<S...>) { - return std::make_tuple(ReturnValueHelper(value, S)...); -} - -// Returns an N-tuple of type std::tuple<T,...T> containing |value| in each -// element. -template <size_t N, typename T, - typename R = typename RepeatedType<T, N, std::tuple>::type> -inline R GetNTuple(T value) { - return GetNTupleHelper<R>(value, rpc::MakeIndexSequence<N>{}); -} - -class NoOpOutputResourceMapper : public OutputResourceMapper { - public: - Status<FileReference> PushFileHandle(const LocalHandle& handle) override { - return handle.Get(); - } - - Status<FileReference> PushFileHandle(const BorrowedHandle& handle) override { - return handle.Get(); - } - - Status<FileReference> PushFileHandle(const RemoteHandle& handle) override { - return handle.Get(); - } - - Status<ChannelReference> PushChannelHandle( - const LocalChannelHandle& handle) override { - return handle.value(); - } - - Status<ChannelReference> PushChannelHandle( - const BorrowedChannelHandle& handle) override { - return handle.value(); - } - - Status<ChannelReference> PushChannelHandle( - const RemoteChannelHandle& handle) override { - return handle.value(); - } -}; - -class NoOpInputResourceMapper : public InputResourceMapper { - public: - bool GetFileHandle(FileReference ref, LocalHandle* handle) override { - *handle = LocalHandle{ref}; - return true; - } - - bool GetChannelHandle(ChannelReference ref, - LocalChannelHandle* handle) override { - *handle = LocalChannelHandle{nullptr, ref}; - return true; - } -}; - -class NoOpResourceMapper : public NoOpOutputResourceMapper, - public NoOpInputResourceMapper {}; - -// Simple implementation of the payload interface, required by -// Serialize/Deserialize. This is intended for test cases, where compatibility -// with std::vector is helpful. -class Payload : public MessageWriter, - public MessageReader, - public OutputResourceMapper { - public: - using BaseType = ByteBuffer; - using iterator = typename BaseType::iterator; - using const_iterator = typename BaseType::const_iterator; - using size_type = typename BaseType::size_type; - - Payload() = default; - explicit Payload(size_type count, uint8_t value = 0) { Append(count, value); } - Payload(const Payload& other) : buffer_(other.buffer_) {} - Payload(const std::initializer_list<uint8_t>& initializer) { - buffer_.resize(initializer.size()); - std::copy(initializer.begin(), initializer.end(), buffer_.begin()); - } - - Payload& operator=(const Payload& other) { - buffer_ = other.buffer_; - read_pos_ = 0; - return *this; - } - Payload& operator=(const std::initializer_list<uint8_t>& initializer) { - buffer_.resize(initializer.size()); - std::copy(initializer.begin(), initializer.end(), buffer_.begin()); - read_pos_ = 0; - return *this; - } - - // Compares Payload with Payload. - bool operator==(const Payload& other) const { - return buffer_ == other.buffer_; - } - bool operator!=(const Payload& other) const { - return buffer_ != other.buffer_; - } - - // Compares Payload with std::vector. - template <typename Type, typename AllocatorType> - typename std::enable_if<sizeof(Type) == sizeof(uint8_t), bool>::type - operator==(const std::vector<Type, AllocatorType>& other) const { - return buffer_.size() == other.size() && - memcmp(buffer_.data(), other.data(), other.size()) == 0; - } - template <typename Type, typename AllocatorType> - typename std::enable_if<sizeof(Type) == sizeof(uint8_t), bool>::type - operator!=(const std::vector<Type, AllocatorType>& other) const { - return !operator!=(other); - } - - iterator begin() { return buffer_.begin(); } - const_iterator begin() const { return buffer_.begin(); } - iterator end() { return buffer_.end(); } - const_iterator end() const { return buffer_.end(); } - - void Append(size_type count, uint8_t value) { - auto* data = buffer_.grow_by(count); - std::fill(data, data + count, value); - } - - void Clear() { - buffer_.clear(); - file_handles_.clear(); - read_pos_ = 0; - } - - void Rewind() { read_pos_ = 0; } - - uint8_t* Data() { return buffer_.data(); } - const uint8_t* Data() const { return buffer_.data(); } - size_type Size() const { return buffer_.size(); } - - // MessageWriter - void* GetNextWriteBufferSection(size_t size) override { - return buffer_.grow_by(size); - } - - OutputResourceMapper* GetOutputResourceMapper() override { return this; } - - // OutputResourceMapper - Status<FileReference> PushFileHandle(const LocalHandle& handle) override { - if (handle) { - const int ref = file_handles_.size(); - file_handles_.push_back(handle.Get()); - return ref; - } else { - return handle.Get(); - } - } - - Status<FileReference> PushFileHandle(const BorrowedHandle& handle) override { - if (handle) { - const int ref = file_handles_.size(); - file_handles_.push_back(handle.Get()); - return ref; - } else { - return handle.Get(); - } - } - - Status<FileReference> PushFileHandle(const RemoteHandle& handle) override { - return handle.Get(); - } - - Status<ChannelReference> PushChannelHandle( - const LocalChannelHandle& handle) override { - if (handle) { - const int ref = file_handles_.size(); - file_handles_.push_back(handle.value()); - return ref; - } else { - return handle.value(); - } - } - - Status<ChannelReference> PushChannelHandle( - const BorrowedChannelHandle& handle) override { - if (handle) { - const int ref = file_handles_.size(); - file_handles_.push_back(handle.value()); - return ref; - } else { - return handle.value(); - } - } - - Status<ChannelReference> PushChannelHandle( - const RemoteChannelHandle& handle) override { - return handle.value(); - } - - // MessageReader - BufferSection GetNextReadBufferSection() override { - return {buffer_.data() + read_pos_, &*buffer_.end()}; - } - - void ConsumeReadBufferSectionData(const void* new_start) override { - read_pos_ = PointerDistance(new_start, buffer_.data()); - } - - InputResourceMapper* GetInputResourceMapper() override { - return &input_resource_mapper_; - } - - const int* FdArray() const { return file_handles_.data(); } - std::size_t FdCount() const { return file_handles_.size(); } - - private: - NoOpInputResourceMapper input_resource_mapper_; - ByteBuffer buffer_; - std::vector<int> file_handles_; - size_t read_pos_{0}; -}; - -} // namespace pdx -} // namespace android - -// Helper macros for branch prediction hinting. -#ifdef __GNUC__ -#define PDX_LIKELY(x) __builtin_expect(!!(x), true) -#define PDX_UNLIKELY(x) __builtin_expect(!!(x), false) -#else -#define PDX_LIKELY(x) (x) -#define PDX_UNLIKELY(x) (x) -#endif - -#endif // ANDROID_PDX_UTILITY_H_ diff --git a/libs/vr/libpdx/serialization_tests.cpp b/libs/vr/libpdx/serialization_tests.cpp deleted file mode 100644 index ee800f699e..0000000000 --- a/libs/vr/libpdx/serialization_tests.cpp +++ /dev/null @@ -1,2505 +0,0 @@ -#include <errno.h> -#include <fcntl.h> -#include <unistd.h> - -#include <memory> -#include <string> -#include <thread> -#include <utility> - -#include <gtest/gtest.h> -#include <pdx/rpc/argument_encoder.h> -#include <pdx/rpc/array_wrapper.h> -#include <pdx/rpc/default_initialization_allocator.h> -#include <pdx/rpc/payload.h> -#include <pdx/rpc/serializable.h> -#include <pdx/rpc/serialization.h> -#include <pdx/rpc/string_wrapper.h> -#include <pdx/utility.h> - -using namespace android::pdx; -using namespace android::pdx::rpc; - -// Tests the serialization/deserialization of all supported types, verifying all -// reasonable boundary conditions for types with multiple encodings. -// -// NOTE: Sometimes this file uses the construct "var = decltype(var)({...})" -// instead of the equivalent "var = {...}" to construct vectors. This is to -// prevent clang-format from producing annoyingly vertical code from long -// initializers. - -// TODO(eieio): Automatically generate some of these tests? - -namespace { - -// Test data for serialization/deserialization of floats. -const float kZeroFloat = 0.0f; -const float kOneFloat = 1.0f; -const auto kZeroFloatBytes = reinterpret_cast<const std::uint8_t*>(&kZeroFloat); -const auto kOneFloatBytes = reinterpret_cast<const std::uint8_t*>(&kOneFloat); -const double kZeroDouble = 0.0; -const double kOneDouble = 1.0; -const auto kZeroDoubleBytes = - reinterpret_cast<const std::uint8_t*>(&kZeroDouble); -const auto kOneDoubleBytes = reinterpret_cast<const std::uint8_t*>(&kOneDouble); - -struct TestType { - enum class Foo { kFoo, kBar, kBaz }; - - int a; - float b; - std::string c; - Foo d; - - TestType() {} - TestType(int a, float b, const std::string& c, Foo d) - : a(a), b(b), c(c), d(d) {} - - // Make gtest expressions simpler by defining equality operator. This is not - // needed for serialization. - bool operator==(const TestType& other) const { - return a == other.a && b == other.b && c == other.c && d == other.d; - } - - private: - PDX_SERIALIZABLE_MEMBERS(TestType, a, b, c, d); -}; - -template <typename FileHandleType> -struct TestTemplateType { - FileHandleType fd; - - TestTemplateType() {} - explicit TestTemplateType(FileHandleType fd) : fd(std::move(fd)) {} - - bool operator==(const TestTemplateType& other) const { - return fd.Get() == other.fd.Get(); - } - - private: - PDX_SERIALIZABLE_MEMBERS(TestTemplateType<FileHandleType>, fd); -}; - -// Utilities to generate test maps and payloads. -template <typename MapType> -MapType MakeMap(std::size_t size) { - MapType result; - for (std::size_t i = 0; i < size; i++) { - result.emplace(i, i); - } - return result; -} - -template <typename MapType> -void InsertKeyValue(MessageWriter* writer, std::size_t size) { - MapType map; - for (std::size_t i = 0; i < size; i++) { - map.emplace(i, i); - } - for (const auto& element : map) { - Serialize(element.first, writer); - Serialize(element.second, writer); - } -} - -} // anonymous namespace - -TEST(SerializableTypes, Constructor) { - TestType tt(1, 2.0, "three", TestType::Foo::kBar); - EXPECT_EQ(1, tt.a); - EXPECT_EQ(2.0, tt.b); - EXPECT_EQ("three", tt.c); - EXPECT_EQ(TestType::Foo::kBar, tt.d); -} - -TEST(SerializationTest, bool) { - Payload result; - Payload expected; - bool value; - - // True. - value = true; - Serialize(value, &result); - expected = {ENCODING_TYPE_TRUE}; - EXPECT_EQ(expected, result); - result.Clear(); - - // False. - value = false; - Serialize(value, &result); - expected = {ENCODING_TYPE_FALSE}; - EXPECT_EQ(expected, result); - result.Clear(); -} - -TEST(SerializationTest, uint8_t) { - Payload result; - Payload expected; - uint8_t value; - - // Min FIXINT. - value = 0; - Serialize(value, &result); - expected = {ENCODING_TYPE_POSITIVE_FIXINT_MIN}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max FIXINT. - value = (1 << 7) - 1; - Serialize(value, &result); - expected = {ENCODING_TYPE_POSITIVE_FIXINT_MAX}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Min UINT8. - value = (1 << 7); - Serialize(value, &result); - expected = {ENCODING_TYPE_UINT8, (1 << 7)}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max UINT8. - value = 0xff; - Serialize(value, &result); - expected = {ENCODING_TYPE_UINT8, 0xff}; - EXPECT_EQ(expected, result); - result.Clear(); -} - -TEST(SerializationTest, uint16_t) { - Payload result; - Payload expected; - uint16_t value; - - // Min FIXINT. - value = 0; - Serialize(value, &result); - expected = {ENCODING_TYPE_POSITIVE_FIXINT_MIN}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max FIXINT. - value = (1 << 7) - 1; - Serialize(value, &result); - expected = {ENCODING_TYPE_POSITIVE_FIXINT_MAX}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Min UINT8. - value = (1 << 7); - Serialize(value, &result); - expected = {ENCODING_TYPE_UINT8, (1 << 7)}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max UINT8. - value = 0xff; - Serialize(value, &result); - expected = {ENCODING_TYPE_UINT8, 0xff}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Min UINT16. - value = (1 << 8); - Serialize(value, &result); - expected = {ENCODING_TYPE_UINT16, 0, 1}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max UINT16. - value = 0xffff; - Serialize(value, &result); - expected = {ENCODING_TYPE_UINT16, 0xff, 0xff}; - EXPECT_EQ(expected, result); - result.Clear(); -} - -TEST(SerializationTest, uint32_t) { - Payload result; - Payload expected; - uint32_t value; - - // Min FIXINT. - value = 0; - Serialize(value, &result); - expected = {ENCODING_TYPE_POSITIVE_FIXINT_MIN}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max FIXINT. - value = (1 << 7) - 1; - Serialize(value, &result); - expected = {ENCODING_TYPE_POSITIVE_FIXINT_MAX}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Min UINT8. - value = (1 << 7); - Serialize(value, &result); - expected = {ENCODING_TYPE_UINT8, (1 << 7)}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max UINT8. - value = 0xff; - Serialize(value, &result); - expected = {ENCODING_TYPE_UINT8, 0xff}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Min UINT16. - value = (1 << 8); - Serialize(value, &result); - expected = {ENCODING_TYPE_UINT16, 0, 1}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max UINT16. - value = 0xffff; - Serialize(value, &result); - expected = {ENCODING_TYPE_UINT16, 0xff, 0xff}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Min UINT32. - value = (1 << 16); - Serialize(value, &result); - expected = {ENCODING_TYPE_UINT32, 0, 0, 1, 0}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max UINT32. - value = 0xffffffff; - Serialize(value, &result); - expected = {ENCODING_TYPE_UINT32, 0xff, 0xff, 0xff, 0xff}; - EXPECT_EQ(expected, result); - result.Clear(); -} - -TEST(SerializationTest, uint64_t) { - Payload result; - Payload expected; - uint64_t value; - - // Min FIXINT. - value = 0; - Serialize(value, &result); - expected = {ENCODING_TYPE_POSITIVE_FIXINT_MIN}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max FIXINT. - value = (1 << 7) - 1; - Serialize(value, &result); - expected = {ENCODING_TYPE_POSITIVE_FIXINT_MAX}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Min UINT8. - value = (1 << 7); - Serialize(value, &result); - expected = {ENCODING_TYPE_UINT8, (1 << 7)}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max UINT8. - value = 0xff; - Serialize(value, &result); - expected = {ENCODING_TYPE_UINT8, 0xff}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Min UINT16. - value = (1 << 8); - Serialize(value, &result); - expected = {ENCODING_TYPE_UINT16, 0, 1}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max UINT16. - value = 0xffff; - Serialize(value, &result); - expected = {ENCODING_TYPE_UINT16, 0xff, 0xff}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Min UINT32. - value = (1 << 16); - Serialize(value, &result); - expected = {ENCODING_TYPE_UINT32, 0, 0, 1, 0}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max UINT32. - value = 0xffffffff; - Serialize(value, &result); - expected = {ENCODING_TYPE_UINT32, 0xff, 0xff, 0xff, 0xff}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Min UINT64. - value = (1ULL << 32); - Serialize(value, &result); - expected = {ENCODING_TYPE_UINT64, 0, 0, 0, 0, 1, 0, 0, 0}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max UINT64. - value = 0xffffffffffffffffULL; - Serialize(value, &result); - expected = { - ENCODING_TYPE_UINT64, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - EXPECT_EQ(expected, result); - result.Clear(); -} - -TEST(SerializationTest, int8_t) { - Payload result; - Payload expected; - int8_t value; - - // Min NEGATIVE FIXINT. - value = -32; - Serialize(value, &result); - expected = {ENCODING_TYPE_NEGATIVE_FIXINT_MIN}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max NEGATIVE FIXINT. - value = -1; - Serialize(value, &result); - expected = {ENCODING_TYPE_NEGATIVE_FIXINT_MAX}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Min FIXINT. - value = 0; - Serialize(value, &result); - expected = {ENCODING_TYPE_POSITIVE_FIXINT_MIN}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max FIXINT. - value = 127; - Serialize(value, &result); - expected = {ENCODING_TYPE_POSITIVE_FIXINT_MAX}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Min INT8. - value = -128; - Serialize(value, &result); - expected = {ENCODING_TYPE_INT8, 0x80}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max INT8. - value = -33; - Serialize(value, &result); - expected = {ENCODING_TYPE_INT8, 0xdf}; - EXPECT_EQ(expected, result); - result.Clear(); -} - -TEST(SerializationTest, int16_t) { - Payload result; - Payload expected; - int16_t value; - - // Min NEGATIVE FIXINT. - value = -32; - Serialize(value, &result); - expected = {ENCODING_TYPE_NEGATIVE_FIXINT_MIN}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max NEGATIVE FIXINT. - value = -1; - Serialize(value, &result); - expected = {ENCODING_TYPE_NEGATIVE_FIXINT_MAX}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Min FIXINT. - value = 0; - Serialize(value, &result); - expected = {ENCODING_TYPE_POSITIVE_FIXINT_MIN}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max FIXINT. - value = 127; - Serialize(value, &result); - expected = {ENCODING_TYPE_POSITIVE_FIXINT_MAX}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Min INT8. - value = -128; - Serialize(value, &result); - expected = {ENCODING_TYPE_INT8, 0x80}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max INT8. - value = -33; - Serialize(value, &result); - expected = {ENCODING_TYPE_INT8, 0xdf}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Min INT16. - value = -32768; - Serialize(value, &result); - expected = {ENCODING_TYPE_INT16, 0x00, 0x80}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max INT16. - value = 32767; - Serialize(value, &result); - expected = {ENCODING_TYPE_INT16, 0xff, 0x7f}; - EXPECT_EQ(expected, result); - result.Clear(); -} - -TEST(SerializationTest, int32_t) { - Payload result; - Payload expected; - int32_t value; - - // Min NEGATIVE FIXINT. - value = -32; - Serialize(value, &result); - expected = {ENCODING_TYPE_NEGATIVE_FIXINT_MIN}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max NEGATIVE FIXINT. - value = -1; - Serialize(value, &result); - expected = {ENCODING_TYPE_NEGATIVE_FIXINT_MAX}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Min FIXINT. - value = 0; - Serialize(value, &result); - expected = {ENCODING_TYPE_POSITIVE_FIXINT_MIN}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max FIXINT. - value = 127; - Serialize(value, &result); - expected = {ENCODING_TYPE_POSITIVE_FIXINT_MAX}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Min INT8. - value = -128; - Serialize(value, &result); - expected = {ENCODING_TYPE_INT8, 0x80}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max INT8. - value = -33; - Serialize(value, &result); - expected = {ENCODING_TYPE_INT8, 0xdf}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Min INT16. - value = -32768; - Serialize(value, &result); - expected = {ENCODING_TYPE_INT16, 0x00, 0x80}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max INT16. - value = 32767; - Serialize(value, &result); - expected = {ENCODING_TYPE_INT16, 0xff, 0x7f}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Min INT32. - value = -2147483648; - Serialize(value, &result); - expected = {ENCODING_TYPE_INT32, 0x00, 0x00, 0x00, 0x80}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max INT32. - value = 2147483647; - Serialize(value, &result); - expected = {ENCODING_TYPE_INT32, 0xff, 0xff, 0xff, 0x7f}; - EXPECT_EQ(expected, result); - result.Clear(); -} - -TEST(SerializationTest, int64_t) { - Payload result; - Payload expected; - int64_t value; - - // Min NEGATIVE FIXINT. - value = -32; - Serialize(value, &result); - expected = {ENCODING_TYPE_NEGATIVE_FIXINT_MIN}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max NEGATIVE FIXINT. - value = -1; - Serialize(value, &result); - expected = {ENCODING_TYPE_NEGATIVE_FIXINT_MAX}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Min FIXINT. - value = 0; - Serialize(value, &result); - expected = {ENCODING_TYPE_POSITIVE_FIXINT_MIN}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max FIXINT. - value = 127; - Serialize(value, &result); - expected = {ENCODING_TYPE_POSITIVE_FIXINT_MAX}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Min INT8. - value = -128; - Serialize(value, &result); - expected = {ENCODING_TYPE_INT8, 0x80}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max INT8. - value = -33; - Serialize(value, &result); - expected = {ENCODING_TYPE_INT8, 0xdf}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Min INT16. - value = -32768; - Serialize(value, &result); - expected = {ENCODING_TYPE_INT16, 0x00, 0x80}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max INT16. - value = 32767; - Serialize(value, &result); - expected = {ENCODING_TYPE_INT16, 0xff, 0x7f}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Min INT32. - value = -2147483648; - Serialize(value, &result); - expected = {ENCODING_TYPE_INT32, 0x00, 0x00, 0x00, 0x80}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max INT32. - value = 2147483647; - Serialize(value, &result); - expected = {ENCODING_TYPE_INT32, 0xff, 0xff, 0xff, 0x7f}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Min INT64. - value = -9223372036854775808ULL; - Serialize(value, &result); - expected = { - ENCODING_TYPE_INT64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max INT64. - value = 9223372036854775807ULL; - Serialize(value, &result); - expected = { - ENCODING_TYPE_INT64, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}; - EXPECT_EQ(expected, result); - result.Clear(); -} - -TEST(SerializationTest, float) { - Payload result; - Payload expected; - float value; - - value = 0.0f; - Serialize(value, &result); - expected = {ENCODING_TYPE_FLOAT32, kZeroFloatBytes[0], kZeroFloatBytes[1], - kZeroFloatBytes[2], kZeroFloatBytes[3]}; - EXPECT_EQ(expected, result); - result.Clear(); - - value = 1.0f; - Serialize(value, &result); - expected = {ENCODING_TYPE_FLOAT32, kOneFloatBytes[0], kOneFloatBytes[1], - kOneFloatBytes[2], kOneFloatBytes[3]}; - EXPECT_EQ(expected, result); - result.Clear(); -} - -TEST(SerializationTest, double) { - Payload result; - Payload expected; - double value; - - value = 0.0f; - Serialize(value, &result); - expected = {ENCODING_TYPE_FLOAT64, kZeroDoubleBytes[0], kZeroDoubleBytes[1], - kZeroDoubleBytes[2], kZeroDoubleBytes[3], kZeroDoubleBytes[4], - kZeroDoubleBytes[5], kZeroDoubleBytes[6], kZeroDoubleBytes[7]}; - EXPECT_EQ(expected, result); - result.Clear(); - - value = 1.0f; - Serialize(value, &result); - expected = {ENCODING_TYPE_FLOAT64, kOneDoubleBytes[0], kOneDoubleBytes[1], - kOneDoubleBytes[2], kOneDoubleBytes[3], kOneDoubleBytes[4], - kOneDoubleBytes[5], kOneDoubleBytes[6], kOneDoubleBytes[7]}; - EXPECT_EQ(expected, result); - result.Clear(); -} - -TEST(SerializationTest, Enum) { - Payload result; - Payload expected; - - enum Foo { kFoo, kBar, kBaz }; - Foo value = kBar; - Serialize(value, &result); - expected = {ENCODING_TYPE_POSITIVE_FIXINT_MIN + 1}; - EXPECT_EQ(expected, result); - result.Clear(); -} - -TEST(SerializationTest, EnumClass) { - Payload result; - Payload expected; - - enum class Foo { kFoo, kBar, kBaz }; - Foo value = Foo::kBaz; - Serialize(value, &result); - expected = {ENCODING_TYPE_POSITIVE_FIXINT_MIN + 2}; - EXPECT_EQ(expected, result); - result.Clear(); -} - -TEST(SerializationTest, LocalHandle) { - Payload result; - Payload expected; - LocalHandle fd1; - LocalHandle fd2; - - fd1 = LocalHandle(100); - Serialize(fd1, &result); - expected = {ENCODING_TYPE_FIXEXT2, ENCODING_EXT_TYPE_FILE_DESCRIPTOR, 0, 0}; - EXPECT_EQ(expected, result); - EXPECT_EQ(1u, result.FdCount()); - EXPECT_EQ(100, result.FdArray()[0]); - result.Clear(); - - fd2 = LocalHandle(200); - Serialize(std::forward_as_tuple(fd1, fd2), &result); - expected = decltype(expected)( - {ENCODING_TYPE_FIXARRAY_MIN + 2, ENCODING_TYPE_FIXEXT2, - ENCODING_EXT_TYPE_FILE_DESCRIPTOR, 0, 0, ENCODING_TYPE_FIXEXT2, - ENCODING_EXT_TYPE_FILE_DESCRIPTOR, 1, 0}); - EXPECT_EQ(expected, result); - EXPECT_EQ(2u, result.FdCount()); - EXPECT_EQ(100, result.FdArray()[0]); - EXPECT_EQ(200, result.FdArray()[1]); - result.Clear(); - - fd1.Release(); // Don't try to close fd 100. - fd2.Release(); // Don't try to close fd 200. - - fd1 = LocalHandle(-2); - Serialize(fd1, &result); - expected = {ENCODING_TYPE_FIXEXT2, ENCODING_EXT_TYPE_FILE_DESCRIPTOR, 0xfe, - 0xff}; - EXPECT_EQ(expected, result); - EXPECT_EQ(0u, result.FdCount()); - result.Clear(); -} - -TEST(SerializationTest, string) { - Payload result; - Payload expected; - std::string value; - - // Min FIXSTR. - value = ""; - Serialize(value, &result); - expected = {ENCODING_TYPE_FIXSTR_MIN}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max FIXSTR. - value = std::string((1 << 5) - 1, 'x'); - Serialize(value, &result); - expected = {ENCODING_TYPE_FIXSTR_MAX}; - expected.Append((1 << 5) - 1, 'x'); - EXPECT_EQ(expected, result); - result.Clear(); - - // Min STR8. - value = std::string((1 << 5), 'x'); - Serialize(value, &result); - expected = {ENCODING_TYPE_STR8, (1 << 5)}; - expected.Append((1 << 5), 'x'); - EXPECT_EQ(expected, result); - result.Clear(); - - // Max STR8. - value = std::string((1 << 8) - 1, 'x'); - Serialize(value, &result); - expected = {ENCODING_TYPE_STR8, (1 << 8) - 1}; - expected.Append((1 << 8) - 1, 'x'); - EXPECT_EQ(expected, result); - result.Clear(); - - // Min STR16. - value = std::string((1 << 8), 'x'); - Serialize(value, &result); - expected = {ENCODING_TYPE_STR16, 0x00, 0x01}; - expected.Append((1 << 8), 'x'); - EXPECT_EQ(expected, result); - result.Clear(); - - // Max STR16. - value = std::string((1 << 16) - 1, 'x'); - Serialize(value, &result); - expected = {ENCODING_TYPE_STR16, 0xff, 0xff}; - expected.Append((1 << 16) - 1, 'x'); - EXPECT_EQ(expected, result); - result.Clear(); - - // Min STR32. - value = std::string((1 << 16), 'x'); - Serialize(value, &result); - expected = {ENCODING_TYPE_STR32, 0x00, 0x00, 0x01, 0x00}; - expected.Append((1 << 16), 'x'); - EXPECT_EQ(expected, result); - result.Clear(); -} - -TEST(SerializationTest, StringWrapper) { - Payload result; - Payload expected; - std::string value; - - // Min FIXSTR. - value = ""; - Serialize(WrapString(value), &result); - expected = {ENCODING_TYPE_FIXSTR_MIN}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max FIXSTR. - value = std::string((1 << 5) - 1, 'x'); - Serialize(WrapString(value), &result); - expected = {ENCODING_TYPE_FIXSTR_MAX}; - expected.Append((1 << 5) - 1, 'x'); - EXPECT_EQ(expected, result); - result.Clear(); - - // Min STR8. - value = std::string((1 << 5), 'x'); - Serialize(WrapString(value), &result); - expected = {ENCODING_TYPE_STR8, (1 << 5)}; - expected.Append((1 << 5), 'x'); - EXPECT_EQ(expected, result); - result.Clear(); - - // Max STR8. - value = std::string((1 << 8) - 1, 'x'); - Serialize(WrapString(value), &result); - expected = {ENCODING_TYPE_STR8, (1 << 8) - 1}; - expected.Append((1 << 8) - 1, 'x'); - EXPECT_EQ(expected, result); - result.Clear(); - - // Min STR16. - value = std::string((1 << 8), 'x'); - Serialize(WrapString(value), &result); - expected = {ENCODING_TYPE_STR16, 0x00, 0x01}; - expected.Append((1 << 8), 'x'); - EXPECT_EQ(expected, result); - result.Clear(); - - // Max STR16. - value = std::string((1 << 16) - 1, 'x'); - Serialize(WrapString(value), &result); - expected = {ENCODING_TYPE_STR16, 0xff, 0xff}; - expected.Append((1 << 16) - 1, 'x'); - EXPECT_EQ(expected, result); - result.Clear(); - - // Min STR32. - value = std::string((1 << 16), 'x'); - Serialize(WrapString(value), &result); - expected = {ENCODING_TYPE_STR32, 0x00, 0x00, 0x01, 0x00}; - expected.Append((1 << 16), 'x'); - EXPECT_EQ(expected, result); - result.Clear(); -} - -TEST(SerializationTest, vector) { - Payload result; - Payload expected; - std::vector<uint8_t> value; - - // Min FIXARRAY. - value = {}; - Serialize(value, &result); - expected = {ENCODING_TYPE_FIXARRAY_MIN}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max FIXARRAY. - value = decltype(value)((1 << 4) - 1, 'x'); - Serialize(value, &result); - expected = {ENCODING_TYPE_FIXARRAY_MAX}; - expected.Append((1 << 4) - 1, 'x'); - EXPECT_EQ(expected, result); - result.Clear(); - - // Min ARRAY16. - value = decltype(value)((1 << 4), 'x'); - Serialize(value, &result); - expected = {ENCODING_TYPE_ARRAY16, 0x10, 0x00}; - expected.Append((1 << 4), 'x'); - EXPECT_EQ(expected, result); - result.Clear(); - - // Max ARRAY16. - value = decltype(value)((1 << 16) - 1, 'x'); - Serialize(value, &result); - expected = {ENCODING_TYPE_ARRAY16, 0xff, 0xff}; - expected.Append((1 << 16) - 1, 'x'); - EXPECT_EQ(expected, result); - result.Clear(); - - // Min ARRAY32. - value = decltype(value)((1 << 16), 'x'); - Serialize(value, &result); - expected = {ENCODING_TYPE_ARRAY32, 0x00, 0x00, 0x01, 0x00}; - expected.Append((1 << 16), 'x'); - EXPECT_EQ(expected, result); - result.Clear(); -} - -TEST(SerializationTest, map) { - Payload result; - Payload expected; - std::map<std::uint32_t, std::uint32_t> value; - - // Min FIXMAP. - value = {}; - Serialize(value, &result); - expected = {ENCODING_TYPE_FIXMAP_MIN}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max FIXMAP. - value = MakeMap<decltype(value)>((1 << 4) - 1); - Serialize(value, &result); - expected = {ENCODING_TYPE_FIXMAP_MAX}; - InsertKeyValue<decltype(value)>(&expected, (1 << 4) - 1); - EXPECT_EQ(expected, result); - result.Clear(); - - // Min MAP16. - value = MakeMap<decltype(value)>((1 << 4)); - Serialize(value, &result); - expected = {ENCODING_TYPE_MAP16, 0x10, 0x00}; - InsertKeyValue<decltype(value)>(&expected, (1 << 4)); - EXPECT_EQ(expected, result); - result.Clear(); - - // Max MAP16. - value = MakeMap<decltype(value)>((1 << 16) - 1); - Serialize(value, &result); - expected = {ENCODING_TYPE_MAP16, 0xff, 0xff}; - InsertKeyValue<decltype(value)>(&expected, (1 << 16) - 1); - EXPECT_EQ(expected, result); - result.Clear(); - - // Min MAP32. - value = MakeMap<decltype(value)>((1 << 16)); - Serialize(value, &result); - expected = {ENCODING_TYPE_MAP32, 0x00, 0x00, 0x01, 0x00}; - InsertKeyValue<decltype(value)>(&expected, (1 << 16)); - EXPECT_EQ(expected, result); - result.Clear(); -} - -TEST(SerializationTest, unordered_map) { - Payload result; - Payload expected; - std::unordered_map<std::uint32_t, std::uint32_t> value; - - // Min FIXMAP. - value = {}; - Serialize(value, &result); - expected = {ENCODING_TYPE_FIXMAP_MIN}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max FIXMAP. - value = MakeMap<decltype(value)>((1 << 4) - 1); - Serialize(value, &result); - expected = {ENCODING_TYPE_FIXMAP_MAX}; - InsertKeyValue<decltype(value)>(&expected, (1 << 4) - 1); - EXPECT_EQ(expected, result); - result.Clear(); - - // Min MAP16. - value = MakeMap<decltype(value)>((1 << 4)); - Serialize(value, &result); - expected = {ENCODING_TYPE_MAP16, 0x10, 0x00}; - InsertKeyValue<decltype(value)>(&expected, (1 << 4)); - EXPECT_EQ(expected, result); - result.Clear(); - - // Max MAP16. - value = MakeMap<decltype(value)>((1 << 16) - 1); - Serialize(value, &result); - expected = {ENCODING_TYPE_MAP16, 0xff, 0xff}; - InsertKeyValue<decltype(value)>(&expected, (1 << 16) - 1); - EXPECT_EQ(expected, result); - result.Clear(); - - // Min MAP32. - value = MakeMap<decltype(value)>((1 << 16)); - Serialize(value, &result); - expected = {ENCODING_TYPE_MAP32, 0x00, 0x00, 0x01, 0x00}; - InsertKeyValue<decltype(value)>(&expected, (1 << 16)); - EXPECT_EQ(expected, result); - result.Clear(); -} - -TEST(SerializationTest, array) { - Payload result; - Payload expected; - - // Min FIXARRAY. - std::array<std::uint8_t, 0> a0; - Serialize(a0, &result); - expected = {ENCODING_TYPE_FIXARRAY_MIN}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max FIXARRAY. - std::array<std::uint8_t, (1 << 4) - 1> a1; - for (auto& element : a1) - element = 'x'; - Serialize(a1, &result); - expected = {ENCODING_TYPE_FIXARRAY_MAX}; - expected.Append((1 << 4) - 1, 'x'); - EXPECT_EQ(expected, result); - result.Clear(); - - // Min ARRAY16. - std::array<std::uint8_t, (1 << 4)> a2; - for (auto& element : a2) - element = 'x'; - Serialize(a2, &result); - expected = {ENCODING_TYPE_ARRAY16, 0x10, 0x00}; - expected.Append((1 << 4), 'x'); - EXPECT_EQ(expected, result); - result.Clear(); - - // Max ARRAY16. - std::array<std::uint8_t, (1 << 16) - 1> a3; - for (auto& element : a3) - element = 'x'; - Serialize(a3, &result); - expected = {ENCODING_TYPE_ARRAY16, 0xff, 0xff}; - expected.Append((1 << 16) - 1, 'x'); - EXPECT_EQ(expected, result); - result.Clear(); - - // Min ARRAY32. - std::array<std::uint8_t, (1 << 16)> a4; - for (auto& element : a4) - element = 'x'; - Serialize(a4, &result); - expected = {ENCODING_TYPE_ARRAY32, 0x00, 0x00, 0x01, 0x00}; - expected.Append((1 << 16), 'x'); - EXPECT_EQ(expected, result); - result.Clear(); -} - -TEST(SerializationTest, ArrayWrapper) { - Payload result; - Payload expected; - std::vector<std::uint8_t, DefaultInitializationAllocator<std::uint8_t>> value; - ArrayWrapper<std::uint8_t> wrapper; - - // Min FIXARRAY. - value = {}; - Serialize(wrapper, &result); - expected = {ENCODING_TYPE_FIXARRAY_MIN}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max FIXARRAY. - value = decltype(value)((1 << 4) - 1, 'x'); - wrapper = decltype(wrapper)(value.data(), value.capacity(), value.size()); - Serialize(wrapper, &result); - expected = {ENCODING_TYPE_FIXARRAY_MAX}; - expected.Append((1 << 4) - 1, 'x'); - EXPECT_EQ(expected, result); - result.Clear(); - - // Min ARRAY16. - value = decltype(value)((1 << 4), 'x'); - wrapper = decltype(wrapper)(value.data(), value.capacity(), value.size()); - Serialize(wrapper, &result); - expected = {ENCODING_TYPE_ARRAY16, 0x10, 0x00}; - expected.Append((1 << 4), 'x'); - EXPECT_EQ(expected, result); - result.Clear(); - - // Max ARRAY16. - value = decltype(value)((1 << 16) - 1, 'x'); - wrapper = decltype(wrapper)(value.data(), value.capacity(), value.size()); - Serialize(wrapper, &result); - expected = {ENCODING_TYPE_ARRAY16, 0xff, 0xff}; - expected.Append((1 << 16) - 1, 'x'); - EXPECT_EQ(expected, result); - result.Clear(); - - // Min ARRAY32. - value = decltype(value)((1 << 16), 'x'); - wrapper = decltype(wrapper)(value.data(), value.capacity(), value.size()); - Serialize(wrapper, &result); - expected = {ENCODING_TYPE_ARRAY32, 0x00, 0x00, 0x01, 0x00}; - expected.Append((1 << 16), 'x'); - EXPECT_EQ(expected, result); - result.Clear(); -} - -TEST(SerializationTest, pair) { - Payload result; - Payload expected; - - auto p1 = std::make_pair(1, 2); - Serialize(p1, &result); - expected = {ENCODING_TYPE_FIXARRAY_MIN + 2, 1, 2}; - EXPECT_EQ(expected, result); - result.Clear(); - - auto p2 = std::make_pair('x', std::string("12345")); - Serialize(p2, &result); - expected = decltype(expected)({ENCODING_TYPE_FIXARRAY_MIN + 2, 'x', - ENCODING_TYPE_FIXSTR_MIN + 5, '1', '2', '3', - '4', '5'}); - EXPECT_EQ(expected, result); - result.Clear(); -} - -TEST(SerializationTest, tuple) { - Payload result; - Payload expected; - - // Min FIXARRAY. - auto t1 = std::make_tuple(); - Serialize(t1, &result); - expected = {ENCODING_TYPE_FIXARRAY_MIN}; - EXPECT_EQ(expected, result); - result.Clear(); - - // Max FIXARRAY. - auto t2 = GetNTuple<15>('x'); - Serialize(t2, &result); - expected = {ENCODING_TYPE_FIXARRAY_MAX}; - expected.Append((1 << 4) - 1, 'x'); - EXPECT_EQ(expected, result); - result.Clear(); - - // Min ARRAY16. - auto t3 = GetNTuple<(1 << 4)>('x'); - Serialize(t3, &result); - expected = {ENCODING_TYPE_ARRAY16, 0x10, 0x00}; - expected.Append((1 << 4), 'x'); - EXPECT_EQ(expected, result); - result.Clear(); - -// Template instantiation depth is an issue for these tests. They are commented -// out to document the expected behavior, even though tuples of this order are -// not expected in practice. -#if 0 - // Max ARRAY16. - auto t4 = GetNTuple<(1 << 16)-1>('x'); - Serialize(t4, &result); - expected = {ENCODING_TYPE_ARRAY16, 0xff, 0xff}; - expected.Append((1 << 16)-1, 'x'); - EXPECT_EQ(expected, result); - result.Clear(); - - // Min ARRAY32. - auto t5 = GetNTuple<(1 << 16)>('x'); - Serialize(t5, &result); - expected = {ENCODING_TYPE_ARRAY32, 0x00, 0x00, 0x01, 0x00}; - expected.Append((1 << 16), 'x'); - EXPECT_EQ(expected, result); - result.Clear(); -#endif -} - -// TODO(eieio): More exhaustive testing of type nesting. -TEST(SerializationTest, NestedTuple) { - Payload result; - Payload expected; - - auto t1 = std::make_tuple('x', std::make_tuple<int, int>(1, 2)); - Serialize(t1, &result); - expected = decltype(expected)({ENCODING_TYPE_FIXARRAY_MIN + 2, 'x', - ENCODING_TYPE_FIXARRAY_MIN + 2, 1, 2}); - EXPECT_EQ(expected, result); - result.Clear(); - - auto t2 = std::make_tuple('x', std::make_tuple<int, int>(1, 2), - std::string("0123456789")); - Serialize(t2, &result); - expected = decltype(expected)({ENCODING_TYPE_FIXARRAY_MIN + 3, 'x', - ENCODING_TYPE_FIXARRAY_MIN + 2, 1, 2, - ENCODING_TYPE_FIXSTR | 10, '0', '1', '2', '3', - '4', '5', '6', '7', '8', '9'}); - EXPECT_EQ(expected, result); - result.Clear(); - - auto t3 = std::make_tuple(0.0f, std::uint64_t(10ULL), - std::vector<char>{'a', 'b', 'c'}); - Serialize(t3, &result); - expected = decltype(expected)( - {ENCODING_TYPE_FIXARRAY_MIN + 3, ENCODING_TYPE_FLOAT32, - kZeroFloatBytes[0], kZeroFloatBytes[1], kZeroFloatBytes[2], - kZeroFloatBytes[3], ENCODING_TYPE_POSITIVE_FIXINT_MIN + 10, - ENCODING_TYPE_FIXARRAY_MIN + 3, 'a', 'b', 'c'}); - EXPECT_EQ(expected, result); - result.Clear(); -} - -TEST(SerializationTest, NestedMap) { - Payload result; - Payload expected; - - std::map<int, std::pair<std::string, int>> m1 = {{0, {"a", 2}}, - {1, {"b", 10}}}; - Serialize(m1, &result); - expected = decltype(expected)( - {ENCODING_TYPE_FIXMAP_MIN + 2, 0, ENCODING_TYPE_FIXARRAY_MIN + 2, - ENCODING_TYPE_FIXSTR_MIN + 1, 'a', 2, 1, ENCODING_TYPE_FIXARRAY_MIN + 2, - ENCODING_TYPE_FIXSTR_MIN + 1, 'b', 10}); - EXPECT_EQ(expected, result); - result.Clear(); -} - -TEST(SerializationTest, Serializable) { - Payload result; - Payload expected; - - TestType t1{10, 0.0, "12345", TestType::Foo::kBaz}; - Serialize(t1, &result); - expected = decltype(expected)( - {ENCODING_TYPE_FIXARRAY_MIN + 4, 10, ENCODING_TYPE_FLOAT32, - kZeroFloatBytes[0], kZeroFloatBytes[1], kZeroFloatBytes[2], - kZeroFloatBytes[3], ENCODING_TYPE_FIXSTR_MIN + 5, '1', '2', '3', '4', - '5', ENCODING_TYPE_POSITIVE_FIXINT_MIN + 2}); - EXPECT_EQ(expected, result); - result.Clear(); - - TestTemplateType<LocalHandle> tt{LocalHandle(-1)}; - Serialize(tt, &result); - expected = - decltype(expected)({ENCODING_TYPE_FIXARRAY_MIN + 1, ENCODING_TYPE_FIXEXT2, - ENCODING_EXT_TYPE_FILE_DESCRIPTOR, 0xff, 0xff}); - EXPECT_EQ(expected, result); -} - -TEST(SerializationTest, Variant) { - Payload result; - Payload expected; - - Variant<int, bool, float> v; - - // Empty variant. - Serialize(v, &result); - expected = {ENCODING_TYPE_FIXMAP_MIN + 1, ENCODING_TYPE_NEGATIVE_FIXINT_MAX, - ENCODING_TYPE_NIL}; - EXPECT_EQ(expected, result); - result.Clear(); - - v = 10; - Serialize(v, &result); - expected = {ENCODING_TYPE_FIXMAP_MIN + 1, - ENCODING_TYPE_POSITIVE_FIXINT_MIN + 0, - ENCODING_TYPE_POSITIVE_FIXINT_MIN + 10}; - EXPECT_EQ(expected, result); - result.Clear(); - - v = true; - Serialize(v, &result); - expected = {ENCODING_TYPE_FIXMAP_MIN + 1, - ENCODING_TYPE_POSITIVE_FIXINT_MIN + 1, ENCODING_TYPE_TRUE}; - EXPECT_EQ(expected, result); - result.Clear(); - - v = false; - Serialize(v, &result); - expected = {ENCODING_TYPE_FIXMAP_MIN + 1, - ENCODING_TYPE_POSITIVE_FIXINT_MIN + 1, ENCODING_TYPE_FALSE}; - EXPECT_EQ(expected, result); - result.Clear(); - - v = 1.0f; - Serialize(v, &result); - expected = {ENCODING_TYPE_FIXMAP_MIN + 1, - ENCODING_TYPE_POSITIVE_FIXINT_MIN + 2, - ENCODING_TYPE_FLOAT32, - kOneFloatBytes[0], - kOneFloatBytes[1], - kOneFloatBytes[2], - kOneFloatBytes[3]}; - EXPECT_EQ(expected, result); - result.Clear(); - - // TODO(eieio): Add more serialization tests for Variant. -} - -TEST(DeserializationTest, bool) { - Payload buffer; - bool result = false; - ErrorType error; - - // True. - buffer = {ENCODING_TYPE_TRUE}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(1, result); // Gtest generates warning from bool literals. - - // False. - buffer = {ENCODING_TYPE_FALSE}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(0, result); // Gtest generates warning from bool literals. -} - -TEST(DeserializationTest, uint8_t) { - Payload buffer; - std::uint8_t result = 0; - ErrorType error; - - // Min FIXINT. - buffer = {ENCODING_TYPE_POSITIVE_FIXINT_MIN}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(0U, result); - - // Max FIXINT. - buffer = {ENCODING_TYPE_POSITIVE_FIXINT_MAX}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(127U, result); - - // Min UINT8. - buffer = {ENCODING_TYPE_UINT8, 0x00}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(0U, result); - - // Max UINT8. - buffer = {ENCODING_TYPE_UINT8, 0xff}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(0xffU, result); - - // UINT16 out of range. - buffer = {ENCODING_TYPE_UINT16}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::UNEXPECTED_ENCODING, error); - EXPECT_EQ(ENCODING_CLASS_UINT, error.encoding_class()); - EXPECT_EQ(ENCODING_TYPE_UINT16, error.encoding_type()); - - // UINT32 out of range. - buffer = {ENCODING_TYPE_UINT32}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::UNEXPECTED_ENCODING, error); - EXPECT_EQ(ENCODING_CLASS_UINT, error.encoding_class()); - EXPECT_EQ(ENCODING_TYPE_UINT32, error.encoding_type()); - - // UINT64 out of range. - buffer = {ENCODING_TYPE_UINT64}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::UNEXPECTED_ENCODING, error); - EXPECT_EQ(ENCODING_CLASS_UINT, error.encoding_class()); - EXPECT_EQ(ENCODING_TYPE_UINT64, error.encoding_type()); -} - -TEST(DeserializationTest, uint16_t) { - Payload buffer; - std::uint16_t result = 0; - ErrorType error; - - // Min FIXINT. - buffer = {ENCODING_TYPE_POSITIVE_FIXINT_MIN}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(0U, result); - - // Max FIXINT. - buffer = {ENCODING_TYPE_POSITIVE_FIXINT_MAX}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(127U, result); - - // Min UINT8. - buffer = {ENCODING_TYPE_UINT8, 0x00}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(0U, result); - - // Max UINT8. - buffer = {ENCODING_TYPE_UINT8, 0xff}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(0xffU, result); - - // Min UINT16. - buffer = {ENCODING_TYPE_UINT16, 0x00, 0x00}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(0U, result); - - // Max UINT16. - buffer = {ENCODING_TYPE_UINT16, 0xff, 0xff}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(0xffffU, result); - - // UINT32 out of range. - buffer = {ENCODING_TYPE_UINT32}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::UNEXPECTED_ENCODING, error); - EXPECT_EQ(ENCODING_CLASS_UINT, error.encoding_class()); - EXPECT_EQ(ENCODING_TYPE_UINT32, error.encoding_type()); - - // UINT64 out of range. - buffer = {ENCODING_TYPE_UINT64}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::UNEXPECTED_ENCODING, error); - EXPECT_EQ(ENCODING_CLASS_UINT, error.encoding_class()); - EXPECT_EQ(ENCODING_TYPE_UINT64, error.encoding_type()); -} - -TEST(DeserializationTest, uint32_t) { - Payload buffer; - std::uint32_t result = 0; - ErrorType error; - - // Min FIXINT. - buffer = {ENCODING_TYPE_POSITIVE_FIXINT_MIN}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(0U, result); - - // Max FIXINT. - buffer = {ENCODING_TYPE_POSITIVE_FIXINT_MAX}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(127U, result); - - // Min UINT8. - buffer = {ENCODING_TYPE_UINT8, 0x00}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(0U, result); - - // Max UINT8. - buffer = {ENCODING_TYPE_UINT8, 0xff}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(0xffU, result); - - // Min UINT16. - buffer = {ENCODING_TYPE_UINT16, 0x00, 0x00}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(0U, result); - - // Max UINT16. - buffer = {ENCODING_TYPE_UINT16, 0xff, 0xff}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(0xffffU, result); - - // Min UINT32. - buffer = {ENCODING_TYPE_UINT32, 0x00, 0x00, 0x00, 0x00}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(0U, result); - - // Max UINT32. - buffer = {ENCODING_TYPE_UINT32, 0xff, 0xff, 0xff, 0xff}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(0xffffffffU, result); - - // UINT64 out of range. - buffer = {ENCODING_TYPE_UINT64}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::UNEXPECTED_ENCODING, error); - EXPECT_EQ(ENCODING_CLASS_UINT, error.encoding_class()); - EXPECT_EQ(ENCODING_TYPE_UINT64, error.encoding_type()); -} - -TEST(DeserializationTest, uint64_t) { - Payload buffer; - std::uint64_t result = 0; - ErrorType error; - - // Min FIXINT. - buffer = {ENCODING_TYPE_POSITIVE_FIXINT_MIN}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(0U, result); - - // Max FIXINT. - buffer = {ENCODING_TYPE_POSITIVE_FIXINT_MAX}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(127U, result); - - // Min UINT8. - buffer = {ENCODING_TYPE_UINT8, 0x00}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(0U, result); - - // Max UINT8. - buffer = {ENCODING_TYPE_UINT8, 0xff}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(0xffU, result); - - // Min UINT16. - buffer = {ENCODING_TYPE_UINT16, 0x00, 0x00}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(0U, result); - - // Max UINT16. - buffer = {ENCODING_TYPE_UINT16, 0xff, 0xff}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(0xffffU, result); - - // Min UINT32. - buffer = {ENCODING_TYPE_UINT32, 0x00, 0x00, 0x00, 0x00}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(0U, result); - - // Max UINT32. - buffer = {ENCODING_TYPE_UINT32, 0xff, 0xff, 0xff, 0xff}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(0xffffffffU, result); - - // Min UINT64. - buffer = { - ENCODING_TYPE_UINT64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(0U, result); - - // Max UINT64. - buffer = { - ENCODING_TYPE_UINT64, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(0xffffffffffffffffUL, result); -} - -TEST(DeserializationTest, int8_t) { - Payload buffer; - std::int8_t result = 0; - ErrorType error; - - // Min NEGATIVE FIXINT. - buffer = {ENCODING_TYPE_NEGATIVE_FIXINT_MIN}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(-32, result); - - // Max NEGATIVE FIXINT. - buffer = {ENCODING_TYPE_NEGATIVE_FIXINT_MAX}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(-1, result); - - // Min FIXINT. - buffer = {ENCODING_TYPE_POSITIVE_FIXINT_MIN}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(0, result); - - // Max FIXINT. - buffer = {ENCODING_TYPE_POSITIVE_FIXINT_MAX}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(127, result); - - // Min INT8. - buffer = {ENCODING_TYPE_INT8, 0x80}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(-128, result); - - // Max INT8. - buffer = {ENCODING_TYPE_INT8, 0x7f}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(127, result); - - // INT16 out of range. - buffer = {ENCODING_TYPE_INT16}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::UNEXPECTED_ENCODING, error); - EXPECT_EQ(ENCODING_CLASS_INT, error.encoding_class()); - EXPECT_EQ(ENCODING_TYPE_INT16, error.encoding_type()); - - // INT32 out of range. - buffer = {ENCODING_TYPE_INT32}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::UNEXPECTED_ENCODING, error); - EXPECT_EQ(ENCODING_CLASS_INT, error.encoding_class()); - EXPECT_EQ(ENCODING_TYPE_INT32, error.encoding_type()); - - // INT64 out of range. - buffer = {ENCODING_TYPE_INT64}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::UNEXPECTED_ENCODING, error); - EXPECT_EQ(ENCODING_CLASS_INT, error.encoding_class()); - EXPECT_EQ(ENCODING_TYPE_INT64, error.encoding_type()); -} - -TEST(DeserializationTest, int16_t) { - Payload buffer; - std::int16_t result = 0; - ErrorType error; - - // Min NEGATIVE FIXINT. - buffer = {ENCODING_TYPE_NEGATIVE_FIXINT_MIN}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(-32, result); - - // Max NEGATIVE FIXINT. - buffer = {ENCODING_TYPE_NEGATIVE_FIXINT_MAX}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(-1, result); - - // Min FIXINT. - buffer = {ENCODING_TYPE_POSITIVE_FIXINT_MIN}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(0, result); - - // Max FIXINT. - buffer = {ENCODING_TYPE_POSITIVE_FIXINT_MAX}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(127, result); - - // Min INT8. - buffer = {ENCODING_TYPE_INT8, 0x80}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(-128, result); - - // Max INT8. - buffer = {ENCODING_TYPE_INT8, 0x7f}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(127, result); - - // Min INT16. - buffer = {ENCODING_TYPE_INT16, 0x00, 0x80}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(-32768, result); - - // Max INT16. - buffer = {ENCODING_TYPE_INT16, 0xff, 0x7f}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(32767, result); - - // INT32 out of range. - buffer = {ENCODING_TYPE_INT32}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::UNEXPECTED_ENCODING, error); - EXPECT_EQ(ENCODING_CLASS_INT, error.encoding_class()); - EXPECT_EQ(ENCODING_TYPE_INT32, error.encoding_type()); - - // INT64 out of range. - buffer = {ENCODING_TYPE_INT64}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::UNEXPECTED_ENCODING, error); - EXPECT_EQ(ENCODING_CLASS_INT, error.encoding_class()); - EXPECT_EQ(ENCODING_TYPE_INT64, error.encoding_type()); -} - -TEST(DeserializationTest, int32_t) { - Payload buffer; - std::int32_t result = 0; - ErrorType error; - - // Min NEGATIVE FIXINT. - buffer = {ENCODING_TYPE_NEGATIVE_FIXINT_MIN}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(-32, result); - - // Max NEGATIVE FIXINT. - buffer = {ENCODING_TYPE_NEGATIVE_FIXINT_MAX}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(-1, result); - - // Min FIXINT. - buffer = {ENCODING_TYPE_POSITIVE_FIXINT_MIN}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(0, result); - - // Max FIXINT. - buffer = {ENCODING_TYPE_POSITIVE_FIXINT_MAX}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(127, result); - - // Min INT8. - buffer = {ENCODING_TYPE_INT8, 0x80}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(-128, result); - - // Max INT8. - buffer = {ENCODING_TYPE_INT8, 0x7f}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(127, result); - - // Min INT16. - buffer = {ENCODING_TYPE_INT16, 0x00, 0x80}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(-32768, result); - - // Max INT16. - buffer = {ENCODING_TYPE_INT16, 0xff, 0x7f}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(32767, result); - - // Min INT32. - buffer = {ENCODING_TYPE_INT32, 0x00, 0x00, 0x00, 0x80}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(-2147483648, result); - - // Max INT32. - buffer = {ENCODING_TYPE_INT32, 0xff, 0xff, 0xff, 0x7f}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(2147483647, result); - - // INT64 out of range. - buffer = {ENCODING_TYPE_INT64}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::UNEXPECTED_ENCODING, error); - EXPECT_EQ(ENCODING_CLASS_INT, error.encoding_class()); - EXPECT_EQ(ENCODING_TYPE_INT64, error.encoding_type()); -} - -TEST(DeserializationTest, int64_t) { - Payload buffer; - std::int64_t result = 0; - ErrorType error; - - // Min NEGATIVE FIXINT. - buffer = {ENCODING_TYPE_NEGATIVE_FIXINT_MIN}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(-32, result); - - // Max NEGATIVE FIXINT. - buffer = {ENCODING_TYPE_NEGATIVE_FIXINT_MAX}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(-1, result); - - // Min FIXINT. - buffer = {ENCODING_TYPE_POSITIVE_FIXINT_MIN}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(0, result); - - // Max FIXINT. - buffer = {ENCODING_TYPE_POSITIVE_FIXINT_MAX}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(127, result); - - // Min INT8. - buffer = {ENCODING_TYPE_INT8, 0x80}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(-128, result); - - // Max INT8. - buffer = {ENCODING_TYPE_INT8, 0x7f}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(127, result); - - // Min INT16. - buffer = {ENCODING_TYPE_INT16, 0x00, 0x80}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(-32768, result); - - // Max INT16. - buffer = {ENCODING_TYPE_INT16, 0xff, 0x7f}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(32767, result); - - // Min INT32. - buffer = {ENCODING_TYPE_INT32, 0x00, 0x00, 0x00, 0x80}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(-2147483648, result); - - // Max INT32. - buffer = {ENCODING_TYPE_INT32, 0xff, 0xff, 0xff, 0x7f}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(2147483647, result); - - // Min INT64. - buffer = { - ENCODING_TYPE_INT64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - // Believe it or not, this is actually the correct way to specify the most - // negative signed long long. - EXPECT_EQ(-9223372036854775807LL - 1, result); - - // Max INT64. - buffer = { - ENCODING_TYPE_INT64, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(9223372036854775807LL, result); -} - -TEST(DeserializationTest, float) { - Payload buffer; - float result; - ErrorType error; - - // FLOAT32. - buffer = {ENCODING_TYPE_FLOAT32, kZeroFloatBytes[0], kZeroFloatBytes[1], - kZeroFloatBytes[2], kZeroFloatBytes[3]}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(kZeroFloat, result); - - // FLOAT32. - buffer = {ENCODING_TYPE_FLOAT32, kOneFloatBytes[0], kOneFloatBytes[1], - kOneFloatBytes[2], kOneFloatBytes[3]}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(kOneFloat, result); -} - -TEST(DeserializationTest, double) { - Payload buffer; - double result; - ErrorType error; - - // FLOAT32. - buffer = {ENCODING_TYPE_FLOAT32, kZeroFloatBytes[0], kZeroFloatBytes[1], - kZeroFloatBytes[2], kZeroFloatBytes[3]}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(kZeroDouble, result); - - // FLOAT64. - buffer = {ENCODING_TYPE_FLOAT64, kZeroDoubleBytes[0], kZeroDoubleBytes[1], - kZeroDoubleBytes[2], kZeroDoubleBytes[3], kZeroDoubleBytes[4], - kZeroDoubleBytes[5], kZeroDoubleBytes[6], kZeroDoubleBytes[7]}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(kZeroDouble, result); - - // FLOAT32. - buffer = {ENCODING_TYPE_FLOAT32, kOneFloatBytes[0], kOneFloatBytes[1], - kOneFloatBytes[2], kOneFloatBytes[3]}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(kOneDouble, result); - - // FLOAT64. - buffer = {ENCODING_TYPE_FLOAT64, kOneDoubleBytes[0], kOneDoubleBytes[1], - kOneDoubleBytes[2], kOneDoubleBytes[3], kOneDoubleBytes[4], - kOneDoubleBytes[5], kOneDoubleBytes[6], kOneDoubleBytes[7]}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(kOneDouble, result); -} - -TEST(DeserializationTest, Enum) { - Payload buffer; - enum Foo { kFoo, kBar, kBaz } result; - ErrorType error; - - buffer = {ENCODING_TYPE_POSITIVE_FIXINT_MIN + 1}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(kBar, result); -} - -TEST(DeserializationTest, EnumClass) { - Payload buffer; - enum Foo { kFoo, kBar, kBaz } result; - ErrorType error; - - buffer = {ENCODING_TYPE_POSITIVE_FIXINT_MIN + 2}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(Foo::kBaz, result); -} - -TEST(DeserializationTest, LocalHandle) { - Payload buffer; - LocalHandle result1; - LocalHandle result2; - ErrorType error; - - buffer = {ENCODING_TYPE_FIXEXT2, ENCODING_EXT_TYPE_FILE_DESCRIPTOR, 0, 0}; - error = Deserialize(&result1, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(0, result1.Get()); - result1.Release(); // Don't close fd 0. - - std::tuple<LocalHandle&, LocalHandle&> t1(result1, result2); - buffer = decltype(buffer)( - {ENCODING_TYPE_FIXARRAY_MIN + 2, ENCODING_TYPE_FIXEXT2, - ENCODING_EXT_TYPE_FILE_DESCRIPTOR, 0, 0, ENCODING_TYPE_FIXEXT2, - ENCODING_EXT_TYPE_FILE_DESCRIPTOR, 1, 0}); - error = Deserialize(&t1, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(0, result1.Get()); - EXPECT_EQ(1, result2.Get()); - result1.Release(); // Don't close fd 0. - result2.Release(); // Don't close fd 1. - - buffer = {ENCODING_TYPE_FIXEXT2, ENCODING_EXT_TYPE_FILE_DESCRIPTOR, 0xfe, - 0xff}; - error = Deserialize(&result1, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(-2, result1.Get()); -} - -TEST(DeserializationTest, string) { - Payload buffer; - std::string result = ""; - ErrorType error; - - // Min FIXSTR. - buffer = {ENCODING_TYPE_FIXSTR_MIN}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ("", result); - - // Max FIXSTR. - buffer = {ENCODING_TYPE_FIXSTR_MAX}; - buffer.Append((1 << 5) - 1, 'x'); - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(std::string((1 << 5) - 1, 'x'), result); - - // Min STR8. - buffer = {ENCODING_TYPE_STR8, 0x00}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ("", result); - - // Max STR8. - buffer = {ENCODING_TYPE_STR8, 0xff}; - buffer.Append(0xff, 'x'); - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(std::string(0xff, 'x'), result); - - // Min STR16. - buffer = {ENCODING_TYPE_STR16, 0x00, 0x00}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ("", result); - - // Max STR16. - buffer = {ENCODING_TYPE_STR16, 0xff, 0xff}; - buffer.Append(0xffff, 'x'); - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(std::string(0xffff, 'x'), result); - - // Min STR32. - buffer = {ENCODING_TYPE_STR32, 0x00, 0x00, 0x00, 0x00}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ("", result); - - // Test STR32 with max STR16 + 1 bytes. It's not practical to test max - // STR32. - buffer = {ENCODING_TYPE_STR32, 0x00, 0x00, 0x01, 0x00}; - buffer.Append(0x10000, 'x'); - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(std::string(0x10000, 'x'), result); -} - -TEST(DeserializationTest, vector) { - Payload buffer; - std::vector<std::uint8_t, DefaultInitializationAllocator<std::uint8_t>> - result; - Payload expected; - ErrorType error; - - // Min FIXARRAY. - buffer = {ENCODING_TYPE_FIXARRAY_MIN}; - error = Deserialize(&result, &buffer); - expected = {}; - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(expected, result); - - // Max FIXARRAY. - buffer = {ENCODING_TYPE_FIXARRAY_MAX}; - buffer.Append((1 << 4) - 1, 1); - error = Deserialize(&result, &buffer); - expected = decltype(expected)((1 << 4) - 1, 1); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(expected, result); - - // Min ARRAY16. - buffer = {ENCODING_TYPE_ARRAY16, 0x00, 0x00}; - error = Deserialize(&result, &buffer); - expected = {}; - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(expected, result); - - // Max ARRAY16. - buffer = {ENCODING_TYPE_ARRAY16, 0xff, 0xff}; - buffer.Append(0xffff, 1); - error = Deserialize(&result, &buffer); - expected = decltype(expected)(0xffff, 1); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(expected, result); - - // Min ARRAY32. - buffer = {ENCODING_TYPE_ARRAY32, 0x00, 0x00, 0x00, 0x00}; - error = Deserialize(&result, &buffer); - expected = {}; - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(expected, result); - - // ARRAY32 with max ARRAY16 + 1. It's not practical to test max ARRAY32. - buffer = {ENCODING_TYPE_ARRAY32, 0x00, 0x00, 0x01, 0x00}; - buffer.Append(0x10000, 1); - error = Deserialize(&result, &buffer); - expected = decltype(expected)(0x10000, 1); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(expected, result); -} - -TEST(DeserializationTest, map) { - Payload buffer; - std::map<std::uint32_t, std::uint32_t> result; - std::map<std::uint32_t, std::uint32_t> expected; - ErrorType error; - - // Min FIXMAP. - buffer = {ENCODING_TYPE_FIXMAP_MIN}; - error = Deserialize(&result, &buffer); - expected = {}; - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(expected, result); - - // Size mismatch. - buffer = {ENCODING_TYPE_FIXMAP_MIN + 1}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::INSUFFICIENT_BUFFER, error); - - // Max FIXMAP. - buffer = {ENCODING_TYPE_FIXMAP_MAX}; - InsertKeyValue<decltype(result)>(&buffer, (1 << 4) - 1); - error = Deserialize(&result, &buffer); - expected = MakeMap<decltype(expected)>((1 << 4) - 1); - EXPECT_EQ(ErrorCode::NO_ERROR, error) << std::string(error); - EXPECT_EQ(expected, result); - - // Min MAP16. - buffer = {ENCODING_TYPE_MAP16, 0x00, 0x00}; - error = Deserialize(&result, &buffer); - expected = {}; - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(expected, result); - - // Max MAP16. - buffer = {ENCODING_TYPE_MAP16, 0xff, 0xff}; - InsertKeyValue<decltype(result)>(&buffer, (1 << 16) - 1); - error = Deserialize(&result, &buffer); - expected = MakeMap<decltype(expected)>((1 << 16) - 1); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(expected, result); - - // Min MAP32. - buffer = {ENCODING_TYPE_MAP32, 0x00, 0x00, 0x00, 0x00}; - error = Deserialize(&result, &buffer); - expected = {}; - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(expected, result); - - // MAP32 with max MAP16 + 1. It's not practical to test max MAP32. - buffer = {ENCODING_TYPE_MAP32, 0x00, 0x00, 0x01, 0x00}; - InsertKeyValue<decltype(result)>(&buffer, (1 << 16)); - error = Deserialize(&result, &buffer); - expected = MakeMap<decltype(expected)>((1 << 16)); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(expected, result); -} - -TEST(DeserializationTest, unordered_map) { - Payload buffer; - std::unordered_map<std::uint32_t, std::uint32_t> result; - std::unordered_map<std::uint32_t, std::uint32_t> expected; - ErrorType error; - - // Min FIXMAP. - buffer = {ENCODING_TYPE_FIXMAP_MIN}; - error = Deserialize(&result, &buffer); - expected = {}; - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(expected, result); - - // Size mismatch. - buffer = {ENCODING_TYPE_FIXMAP_MIN + 1}; - error = Deserialize(&result, &buffer); - EXPECT_EQ(ErrorCode::INSUFFICIENT_BUFFER, error); - - // Max FIXMAP. - buffer = {ENCODING_TYPE_FIXMAP_MAX}; - InsertKeyValue<decltype(result)>(&buffer, (1 << 4) - 1); - error = Deserialize(&result, &buffer); - expected = MakeMap<decltype(expected)>((1 << 4) - 1); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(expected, result); - - // Min MAP16. - buffer = {ENCODING_TYPE_MAP16, 0x00, 0x00}; - error = Deserialize(&result, &buffer); - expected = {}; - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(expected, result); - - // Max MAP16. - buffer = {ENCODING_TYPE_MAP16, 0xff, 0xff}; - InsertKeyValue<decltype(result)>(&buffer, (1 << 16) - 1); - error = Deserialize(&result, &buffer); - expected = MakeMap<decltype(expected)>((1 << 16) - 1); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(expected, result); - - // Min MAP32. - buffer = {ENCODING_TYPE_MAP32, 0x00, 0x00, 0x00, 0x00}; - error = Deserialize(&result, &buffer); - expected = {}; - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(expected, result); - - // MAP32 with max MAP16 + 1. It's not practical to test max MAP32. - buffer = {ENCODING_TYPE_MAP32, 0x00, 0x00, 0x01, 0x00}; - InsertKeyValue<decltype(result)>(&buffer, (1 << 16)); - error = Deserialize(&result, &buffer); - expected = MakeMap<decltype(expected)>((1 << 16)); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(expected, result); -} - -TEST(DeserializationTest, array) { - Payload buffer; - ErrorType error; - - // Min FIXARRAY. - buffer = {ENCODING_TYPE_FIXARRAY_MIN}; - std::array<std::uint8_t, 0> a0; - error = Deserialize(&a0, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - - // Size mismatch. - buffer = {ENCODING_TYPE_FIXARRAY_MIN + 1}; - error = Deserialize(&a0, &buffer); - EXPECT_EQ(ErrorCode::INSUFFICIENT_DESTINATION_SIZE, error); - - // Max FIXARRAY. - buffer = {ENCODING_TYPE_FIXARRAY_MAX}; - buffer.Append((1 << 4) - 1, 'x'); - std::array<std::uint8_t, (1 << 4) - 1> a1, expected1; - for (auto& element : expected1) - element = 'x'; - error = Deserialize(&a1, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(expected1, a1); - - // Min ARRAY16. - buffer = {ENCODING_TYPE_ARRAY16, 0x00, 0x00}; - error = Deserialize(&a0, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - - // Max ARRAY16. - buffer = {ENCODING_TYPE_ARRAY16, 0xff, 0xff}; - buffer.Append((1 << 16) - 1, 'x'); - std::array<std::uint8_t, (1 << 16) - 1> a3, expected3; - for (auto& element : expected3) - element = 'x'; - error = Deserialize(&a3, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(expected3, a3); - - // Min ARRAY32. - buffer = {ENCODING_TYPE_ARRAY32, 0x00, 0x00, 0x00, 0x00}; - error = Deserialize(&a0, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - - // ARRAY32 with max ARRAY16 + 1. It's not practical to test max ARRAY32. - buffer = {ENCODING_TYPE_ARRAY32, 0x00, 0x00, 0x01, 0x00}; - buffer.Append((1 << 16), 'x'); - std::array<std::uint8_t, (1 << 16)> a4, expected4; - for (auto& element : expected4) - element = 'x'; - error = Deserialize(&a4, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(expected4, a4); -} - -TEST(DeserializationTest, ArrayWrapper) { - Payload buffer; - std::vector<std::uint8_t, DefaultInitializationAllocator<std::uint8_t>> - result; - std::vector<std::uint8_t, DefaultInitializationAllocator<std::uint8_t>> - expected; - ErrorType error; - - result.reserve(0x10000); - ArrayWrapper<std::uint8_t> wrapper(result.data(), result.capacity()); - - // Min FIXARRAY. - buffer = {ENCODING_TYPE_FIXARRAY_MIN}; - error = Deserialize(&wrapper, &buffer); - expected = {}; - result.resize(wrapper.size()); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(expected, result); - - // Max FIXARRAY. - buffer = {ENCODING_TYPE_FIXARRAY_MAX}; - buffer.Append((1 << 4) - 1, 1); - error = Deserialize(&wrapper, &buffer); - expected = decltype(expected)((1 << 4) - 1, 1); - result.resize(wrapper.size()); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(expected, result); - - // Min ARRAY16. - buffer = {ENCODING_TYPE_ARRAY16, 0x00, 0x00}; - error = Deserialize(&wrapper, &buffer); - expected = {}; - result.resize(wrapper.size()); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(expected, result); - - // Max ARRAY16. - buffer = {ENCODING_TYPE_ARRAY16, 0xff, 0xff}; - buffer.Append(0xffff, 1); - error = Deserialize(&wrapper, &buffer); - expected = decltype(expected)(0xffff, 1); - result.resize(wrapper.size()); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(expected, result); - - // Min ARRAY32. - buffer = {ENCODING_TYPE_ARRAY32, 0x00, 0x00, 0x00, 0x00}; - error = Deserialize(&wrapper, &buffer); - expected = {}; - result.resize(wrapper.size()); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(expected, result); - - // ARRAY32 with max ARRAY16 + 1. It's not practical to test max ARRAY32. - buffer = {ENCODING_TYPE_ARRAY32, 0x00, 0x00, 0x01, 0x00}; - buffer.Append(0x10000, 1); - error = Deserialize(&wrapper, &buffer); - expected = decltype(expected)(0x10000, 1); - result.resize(wrapper.size()); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(expected, result); -} - -TEST(DeserializationTest, pair) { - Payload buffer; - ErrorType error; - - std::pair<int, int> p1; - buffer = {ENCODING_TYPE_FIXARRAY_MIN + 2, 1, 2}; - error = Deserialize(&p1, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(std::make_pair(1, 2), p1); -} - -TEST(DeserializationTest, tuple) { - Payload buffer; - ErrorType error; - - // Min FIXARRAY. - std::tuple<> t1; - buffer = {ENCODING_TYPE_FIXARRAY_MIN}; - error = Deserialize(&t1, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(std::make_tuple(), t1); // Superfluous. - - // Max FIXARRAY. - auto t2 = GetNTuple<15, int>(0); - buffer = {ENCODING_TYPE_FIXARRAY_MAX}; - buffer.Append((1 << 4) - 1, 1); - error = Deserialize(&t2, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ((GetNTuple<15, int>(1)), t2); - - // Min ARRAY16. - // Using t1 above. - buffer = {ENCODING_TYPE_ARRAY16, 0x00, 0x00}; - error = Deserialize(&t1, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(std::make_tuple(), t1); - - // ARRAY16 at Max FIXARRAY + 1 - auto t3 = GetNTuple<(1 << 4), int>(0); - buffer = {ENCODING_TYPE_ARRAY16, 0x10, 0x00}; - buffer.Append((1 << 4), 1); - error = Deserialize(&t3, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ((GetNTuple<(1 << 4), int>(1)), t3); - - // Min ARRAY32. - // Using t1 from above. - buffer = {ENCODING_TYPE_ARRAY32, 0x00, 0x00, 0x00, 0x00}; - error = Deserialize(&t1, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(std::make_tuple(), t1); - - // ARRAY32 at Max FIXARRAY + 1 - auto t4 = GetNTuple<(1 << 4), int>(0); - buffer = {ENCODING_TYPE_ARRAY32, 0x10, 0x00, 0x00, 0x00}; - buffer.Append((1 << 4), 1); - error = Deserialize(&t4, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ((GetNTuple<(1 << 4), int>(1)), t4); - - // Template instantiation depth is an issue for tuples with large numbers of - // elements. As these are not expected in practice, the limits of ARRAY16 - // and ARRAY32 are not tested. -} - -TEST(DeserializationTest, Serializable) { - Payload buffer; - ErrorType error; - - buffer = decltype(buffer)( - {ENCODING_TYPE_FIXARRAY_MIN + 4, 10, ENCODING_TYPE_FLOAT32, - kZeroFloatBytes[0], kZeroFloatBytes[1], kZeroFloatBytes[2], - kZeroFloatBytes[3], ENCODING_TYPE_FIXSTR_MIN + 5, '1', '2', '3', '4', - '5', ENCODING_TYPE_POSITIVE_FIXINT_MIN + 1}); - TestType t1; - error = Deserialize(&t1, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(TestType(10, 0.f, "12345", TestType::Foo::kBar), t1); - - buffer = - decltype(buffer)({ENCODING_TYPE_FIXARRAY_MIN + 1, ENCODING_TYPE_FIXEXT2, - ENCODING_EXT_TYPE_FILE_DESCRIPTOR, 0xff, 0xff}); - TestTemplateType<LocalHandle> tt; - error = Deserialize(&tt, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_EQ(TestTemplateType<LocalHandle>(LocalHandle(-1)), tt); -} - -TEST(DeserializationTest, Variant) { - Payload buffer; - ErrorType error; - - Variant<int, bool, float> v; - - buffer = {ENCODING_TYPE_FIXMAP_MIN + 1, ENCODING_TYPE_NEGATIVE_FIXINT_MAX, - ENCODING_TYPE_NIL}; - error = Deserialize(&v, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - EXPECT_TRUE(v.empty()); - - buffer = {ENCODING_TYPE_FIXMAP_MIN + 1, ENCODING_TYPE_POSITIVE_FIXINT_MIN + 0, - ENCODING_TYPE_POSITIVE_FIXINT_MIN + 10}; - error = Deserialize(&v, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - ASSERT_TRUE(v.is<int>()); - EXPECT_EQ(10, std::get<int>(v)); - - buffer = {ENCODING_TYPE_FIXMAP_MIN + 1, ENCODING_TYPE_POSITIVE_FIXINT_MIN + 1, - ENCODING_TYPE_TRUE}; - error = Deserialize(&v, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - ASSERT_TRUE(v.is<bool>()); - EXPECT_EQ(true, std::get<bool>(v)); - - buffer = {ENCODING_TYPE_FIXMAP_MIN + 1, ENCODING_TYPE_POSITIVE_FIXINT_MIN + 1, - ENCODING_TYPE_FALSE}; - error = Deserialize(&v, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - ASSERT_TRUE(v.is<bool>()); - EXPECT_EQ(false, std::get<bool>(v)); - - buffer = {ENCODING_TYPE_FIXMAP_MIN + 1, - ENCODING_TYPE_POSITIVE_FIXINT_MIN + 2, - ENCODING_TYPE_FLOAT32, - kOneFloatBytes[0], - kOneFloatBytes[1], - kOneFloatBytes[2], - kOneFloatBytes[3]}; - error = Deserialize(&v, &buffer); - EXPECT_EQ(ErrorCode::NO_ERROR, error); - ASSERT_TRUE(v.is<float>()); - EXPECT_FLOAT_EQ(1.0, std::get<float>(v)); - - // TODO(eieio): Add more deserialization tests for Variant. -} - -TEST(DeserializationTest, ErrorType) { - Payload buffer; - ErrorType error; - - std::uint8_t u8; - buffer = {ENCODING_TYPE_STR8}; - error = Deserialize(&u8, &buffer); - EXPECT_EQ(ErrorCode::UNEXPECTED_ENCODING, error); - EXPECT_EQ(ENCODING_CLASS_UINT, error.encoding_class()); - EXPECT_EQ(ENCODING_TYPE_STR8, error.encoding_type()); - - std::uint16_t u16; - buffer = {ENCODING_TYPE_STR8}; - error = Deserialize(&u16, &buffer); - EXPECT_EQ(ErrorCode::UNEXPECTED_ENCODING, error); - EXPECT_EQ(ENCODING_CLASS_UINT, error.encoding_class()); - EXPECT_EQ(ENCODING_TYPE_STR8, error.encoding_type()); - - std::uint32_t u32; - buffer = {ENCODING_TYPE_STR8}; - error = Deserialize(&u32, &buffer); - EXPECT_EQ(ErrorCode::UNEXPECTED_ENCODING, error); - EXPECT_EQ(ENCODING_CLASS_UINT, error.encoding_class()); - EXPECT_EQ(ENCODING_TYPE_STR8, error.encoding_type()); - - std::uint64_t u64; - buffer = {ENCODING_TYPE_STR8}; - error = Deserialize(&u64, &buffer); - EXPECT_EQ(ErrorCode::UNEXPECTED_ENCODING, error); - EXPECT_EQ(ENCODING_CLASS_UINT, error.encoding_class()); - EXPECT_EQ(ENCODING_TYPE_STR8, error.encoding_type()); - - std::int8_t i8; - buffer = {ENCODING_TYPE_STR8}; - error = Deserialize(&i8, &buffer); - EXPECT_EQ(ErrorCode::UNEXPECTED_ENCODING, error); - EXPECT_EQ(ENCODING_CLASS_INT, error.encoding_class()); - EXPECT_EQ(ENCODING_TYPE_STR8, error.encoding_type()); - - std::int16_t i16; - buffer = {ENCODING_TYPE_STR8}; - error = Deserialize(&i16, &buffer); - EXPECT_EQ(ErrorCode::UNEXPECTED_ENCODING, error); - EXPECT_EQ(ENCODING_CLASS_INT, error.encoding_class()); - EXPECT_EQ(ENCODING_TYPE_STR8, error.encoding_type()); - - std::int32_t i32; - buffer = {ENCODING_TYPE_STR8}; - error = Deserialize(&i32, &buffer); - EXPECT_EQ(ErrorCode::UNEXPECTED_ENCODING, error); - EXPECT_EQ(ENCODING_CLASS_INT, error.encoding_class()); - EXPECT_EQ(ENCODING_TYPE_STR8, error.encoding_type()); - - std::int64_t i64; - buffer = {ENCODING_TYPE_STR8}; - error = Deserialize(&i64, &buffer); - EXPECT_EQ(ErrorCode::UNEXPECTED_ENCODING, error); - EXPECT_EQ(ENCODING_CLASS_INT, error.encoding_class()); - EXPECT_EQ(ENCODING_TYPE_STR8, error.encoding_type()); - - std::string s; - buffer = {ENCODING_TYPE_POSITIVE_FIXINT}; - error = Deserialize(&s, &buffer); - EXPECT_EQ(ErrorCode::UNEXPECTED_ENCODING, error); - EXPECT_EQ(ENCODING_CLASS_STRING, error.encoding_class()); - EXPECT_EQ(ENCODING_TYPE_POSITIVE_FIXINT, error.encoding_type()); - - std::vector<std::uint8_t> v; - buffer = {ENCODING_TYPE_POSITIVE_FIXINT}; - error = Deserialize(&v, &buffer); - EXPECT_EQ(ErrorCode::UNEXPECTED_ENCODING, error); - EXPECT_EQ(ENCODING_CLASS_ARRAY, error.encoding_class()); - EXPECT_EQ(ENCODING_TYPE_POSITIVE_FIXINT, error.encoding_type()); - - buffer = {ENCODING_TYPE_FIXARRAY_MIN + 1, ENCODING_TYPE_STR8}; - error = Deserialize(&v, &buffer); - EXPECT_EQ(ErrorCode::UNEXPECTED_ENCODING, error); - EXPECT_EQ(ENCODING_CLASS_UINT, error.encoding_class()); - EXPECT_EQ(ENCODING_TYPE_STR8, error.encoding_type()); - - buffer = {ENCODING_TYPE_FIXARRAY_MIN + 2, 0, 1}; - std::tuple<int> t; - error = Deserialize(&t, &buffer); - EXPECT_EQ(ErrorCode::UNEXPECTED_TYPE_SIZE, error); - - buffer = {ENCODING_TYPE_FIXARRAY_MIN + 3, 0, 1, 2}; - std::pair<int, int> p; - error = Deserialize(&p, &buffer); - EXPECT_EQ(ErrorCode::UNEXPECTED_TYPE_SIZE, error); -} diff --git a/libs/vr/libpdx/service.cpp b/libs/vr/libpdx/service.cpp deleted file mode 100644 index 3769162344..0000000000 --- a/libs/vr/libpdx/service.cpp +++ /dev/null @@ -1,675 +0,0 @@ -#include "pdx/service.h" - -#include <fcntl.h> -#include <log/log.h> -#include <utils/misc.h> - -#include <algorithm> -#include <cstdint> - -#include <pdx/trace.h> - -namespace android { -namespace pdx { - -std::shared_ptr<Channel> Channel::GetFromMessageInfo(const MessageInfo& info) { - return info.channel ? info.channel->shared_from_this() - : std::shared_ptr<Channel>(); -} - -Message::Message() : replied_(true) {} - -Message::Message(const MessageInfo& info) - : service_{Service::GetFromMessageInfo(info)}, - channel_{Channel::GetFromMessageInfo(info)}, - info_{info}, - replied_{IsImpulse()} { - auto svc = service_.lock(); - if (svc) - state_ = svc->endpoint()->AllocateMessageState(); -} - -// C++11 specifies the move semantics for shared_ptr but not weak_ptr. This -// means we have to manually implement the desired move semantics for Message. -Message::Message(Message&& other) noexcept { *this = std::move(other); } - -Message& Message::operator=(Message&& other) noexcept { - Destroy(); - auto base = reinterpret_cast<std::uint8_t*>(&info_); - std::fill(&base[0], &base[sizeof(info_)], 0); - replied_ = true; - std::swap(service_, other.service_); - std::swap(channel_, other.channel_); - std::swap(info_, other.info_); - std::swap(state_, other.state_); - std::swap(replied_, other.replied_); - return *this; -} - -Message::~Message() { Destroy(); } - -void Message::Destroy() { - auto svc = service_.lock(); - if (svc) { - if (!replied_) { - ALOGE( - "ERROR: Service \"%s\" failed to reply to message: op=%d pid=%d " - "cid=%d\n", - svc->name_.c_str(), info_.op, info_.pid, info_.cid); - svc->DefaultHandleMessage(*this); - } - svc->endpoint()->FreeMessageState(state_); - } - state_ = nullptr; - service_.reset(); - channel_.reset(); -} - -const std::uint8_t* Message::ImpulseBegin() const { - return reinterpret_cast<const std::uint8_t*>(info_.impulse); -} - -const std::uint8_t* Message::ImpulseEnd() const { - return ImpulseBegin() + (IsImpulse() ? GetSendLength() : 0); -} - -Status<size_t> Message::ReadVector(const struct iovec* vector, - size_t vector_length) { - PDX_TRACE_NAME("Message::ReadVector"); - if (auto svc = service_.lock()) { - return svc->endpoint()->ReadMessageData(this, vector, vector_length); - } else { - return ErrorStatus{ESHUTDOWN}; - } -} - -Status<void> Message::ReadVectorAll(const struct iovec* vector, - size_t vector_length) { - PDX_TRACE_NAME("Message::ReadVectorAll"); - if (auto svc = service_.lock()) { - const auto status = - svc->endpoint()->ReadMessageData(this, vector, vector_length); - if (!status) - return status.error_status(); - size_t size_to_read = 0; - for (size_t i = 0; i < vector_length; i++) - size_to_read += vector[i].iov_len; - if (status.get() < size_to_read) - return ErrorStatus{EIO}; - return {}; - } else { - return ErrorStatus{ESHUTDOWN}; - } -} - -Status<size_t> Message::Read(void* buffer, size_t length) { - PDX_TRACE_NAME("Message::Read"); - if (auto svc = service_.lock()) { - const struct iovec vector = {buffer, length}; - return svc->endpoint()->ReadMessageData(this, &vector, 1); - } else { - return ErrorStatus{ESHUTDOWN}; - } -} - -Status<size_t> Message::WriteVector(const struct iovec* vector, - size_t vector_length) { - PDX_TRACE_NAME("Message::WriteVector"); - if (auto svc = service_.lock()) { - return svc->endpoint()->WriteMessageData(this, vector, vector_length); - } else { - return ErrorStatus{ESHUTDOWN}; - } -} - -Status<void> Message::WriteVectorAll(const struct iovec* vector, - size_t vector_length) { - PDX_TRACE_NAME("Message::WriteVector"); - if (auto svc = service_.lock()) { - const auto status = - svc->endpoint()->WriteMessageData(this, vector, vector_length); - if (!status) - return status.error_status(); - size_t size_to_write = 0; - for (size_t i = 0; i < vector_length; i++) - size_to_write += vector[i].iov_len; - if (status.get() < size_to_write) - return ErrorStatus{EIO}; - return {}; - } else { - return ErrorStatus{ESHUTDOWN}; - } -} - -Status<size_t> Message::Write(const void* buffer, size_t length) { - PDX_TRACE_NAME("Message::Write"); - if (auto svc = service_.lock()) { - const struct iovec vector = {const_cast<void*>(buffer), length}; - return svc->endpoint()->WriteMessageData(this, &vector, 1); - } else { - return ErrorStatus{ESHUTDOWN}; - } -} - -Status<FileReference> Message::PushFileHandle(const LocalHandle& handle) { - PDX_TRACE_NAME("Message::PushFileHandle"); - if (auto svc = service_.lock()) { - return svc->endpoint()->PushFileHandle(this, handle); - } else { - return ErrorStatus{ESHUTDOWN}; - } -} - -Status<FileReference> Message::PushFileHandle(const BorrowedHandle& handle) { - PDX_TRACE_NAME("Message::PushFileHandle"); - if (auto svc = service_.lock()) { - return svc->endpoint()->PushFileHandle(this, handle); - } else { - return ErrorStatus{ESHUTDOWN}; - } -} - -Status<FileReference> Message::PushFileHandle(const RemoteHandle& handle) { - PDX_TRACE_NAME("Message::PushFileHandle"); - if (auto svc = service_.lock()) { - return svc->endpoint()->PushFileHandle(this, handle); - } else { - return ErrorStatus{ESHUTDOWN}; - } -} - -Status<ChannelReference> Message::PushChannelHandle( - const LocalChannelHandle& handle) { - PDX_TRACE_NAME("Message::PushChannelHandle"); - if (auto svc = service_.lock()) { - return svc->endpoint()->PushChannelHandle(this, handle); - } else { - return ErrorStatus{ESHUTDOWN}; - } -} - -Status<ChannelReference> Message::PushChannelHandle( - const BorrowedChannelHandle& handle) { - PDX_TRACE_NAME("Message::PushChannelHandle"); - if (auto svc = service_.lock()) { - return svc->endpoint()->PushChannelHandle(this, handle); - } else { - return ErrorStatus{ESHUTDOWN}; - } -} - -Status<ChannelReference> Message::PushChannelHandle( - const RemoteChannelHandle& handle) { - PDX_TRACE_NAME("Message::PushChannelHandle"); - if (auto svc = service_.lock()) { - return svc->endpoint()->PushChannelHandle(this, handle); - } else { - return ErrorStatus{ESHUTDOWN}; - } -} - -bool Message::GetFileHandle(FileReference ref, LocalHandle* handle) { - PDX_TRACE_NAME("Message::GetFileHandle"); - auto svc = service_.lock(); - if (!svc) - return false; - - if (ref >= 0) { - *handle = svc->endpoint()->GetFileHandle(this, ref); - if (!handle->IsValid()) - return false; - } else { - *handle = LocalHandle{ref}; - } - return true; -} - -bool Message::GetChannelHandle(ChannelReference ref, - LocalChannelHandle* handle) { - PDX_TRACE_NAME("Message::GetChannelHandle"); - auto svc = service_.lock(); - if (!svc) - return false; - - if (ref >= 0) { - *handle = svc->endpoint()->GetChannelHandle(this, ref); - if (!handle->valid()) - return false; - } else { - *handle = LocalChannelHandle{nullptr, ref}; - } - return true; -} - -Status<void> Message::Reply(int return_code) { - PDX_TRACE_NAME("Message::Reply"); - auto svc = service_.lock(); - if (!replied_ && svc) { - const auto ret = svc->endpoint()->MessageReply(this, return_code); - replied_ = ret.ok(); - return ret; - } else { - return ErrorStatus{EINVAL}; - } -} - -Status<void> Message::ReplyFileDescriptor(unsigned int fd) { - PDX_TRACE_NAME("Message::ReplyFileDescriptor"); - auto svc = service_.lock(); - if (!replied_ && svc) { - const auto ret = svc->endpoint()->MessageReplyFd(this, fd); - replied_ = ret.ok(); - return ret; - } else { - return ErrorStatus{EINVAL}; - } -} - -Status<void> Message::ReplyError(unsigned int error) { - PDX_TRACE_NAME("Message::ReplyError"); - auto svc = service_.lock(); - if (!replied_ && svc) { - const auto ret = - svc->endpoint()->MessageReply(this, -static_cast<int>(error)); - replied_ = ret.ok(); - return ret; - } else { - return ErrorStatus{EINVAL}; - } -} - -Status<void> Message::Reply(const LocalHandle& handle) { - PDX_TRACE_NAME("Message::ReplyFileHandle"); - auto svc = service_.lock(); - if (!replied_ && svc) { - Status<void> ret; - - if (handle) - ret = svc->endpoint()->MessageReplyFd(this, handle.Get()); - else - ret = svc->endpoint()->MessageReply(this, handle.Get()); - - replied_ = ret.ok(); - return ret; - } else { - return ErrorStatus{EINVAL}; - } -} - -Status<void> Message::Reply(const BorrowedHandle& handle) { - PDX_TRACE_NAME("Message::ReplyFileHandle"); - auto svc = service_.lock(); - if (!replied_ && svc) { - Status<void> ret; - - if (handle) - ret = svc->endpoint()->MessageReplyFd(this, handle.Get()); - else - ret = svc->endpoint()->MessageReply(this, handle.Get()); - - replied_ = ret.ok(); - return ret; - } else { - return ErrorStatus{EINVAL}; - } -} - -Status<void> Message::Reply(const RemoteHandle& handle) { - PDX_TRACE_NAME("Message::ReplyFileHandle"); - auto svc = service_.lock(); - if (!replied_ && svc) { - Status<void> ret = svc->endpoint()->MessageReply(this, handle.Get()); - replied_ = ret.ok(); - return ret; - } else { - return ErrorStatus{EINVAL}; - } -} - -Status<void> Message::Reply(const LocalChannelHandle& handle) { - auto svc = service_.lock(); - if (!replied_ && svc) { - const auto ret = svc->endpoint()->MessageReplyChannelHandle(this, handle); - replied_ = ret.ok(); - return ret; - } else { - return ErrorStatus{EINVAL}; - } -} - -Status<void> Message::Reply(const BorrowedChannelHandle& handle) { - auto svc = service_.lock(); - if (!replied_ && svc) { - const auto ret = svc->endpoint()->MessageReplyChannelHandle(this, handle); - replied_ = ret.ok(); - return ret; - } else { - return ErrorStatus{EINVAL}; - } -} - -Status<void> Message::Reply(const RemoteChannelHandle& handle) { - auto svc = service_.lock(); - if (!replied_ && svc) { - const auto ret = svc->endpoint()->MessageReplyChannelHandle(this, handle); - replied_ = ret.ok(); - return ret; - } else { - return ErrorStatus{EINVAL}; - } -} - -Status<void> Message::ModifyChannelEvents(int clear_mask, int set_mask) { - PDX_TRACE_NAME("Message::ModifyChannelEvents"); - if (auto svc = service_.lock()) { - return svc->endpoint()->ModifyChannelEvents(info_.cid, clear_mask, - set_mask); - } else { - return ErrorStatus{ESHUTDOWN}; - } -} - -Status<RemoteChannelHandle> Message::PushChannel( - int flags, const std::shared_ptr<Channel>& channel, int* channel_id) { - PDX_TRACE_NAME("Message::PushChannel"); - if (auto svc = service_.lock()) { - return svc->PushChannel(this, flags, channel, channel_id); - } else { - return ErrorStatus(ESHUTDOWN); - } -} - -Status<RemoteChannelHandle> Message::PushChannel( - Service* service, int flags, const std::shared_ptr<Channel>& channel, - int* channel_id) { - PDX_TRACE_NAME("Message::PushChannel"); - return service->PushChannel(this, flags, channel, channel_id); -} - -Status<int> Message::CheckChannel(ChannelReference ref, - std::shared_ptr<Channel>* channel) const { - PDX_TRACE_NAME("Message::CheckChannel"); - if (auto svc = service_.lock()) { - return svc->CheckChannel(this, ref, channel); - } else { - return ErrorStatus(ESHUTDOWN); - } -} - -Status<int> Message::CheckChannel(const Service* service, ChannelReference ref, - std::shared_ptr<Channel>* channel) const { - PDX_TRACE_NAME("Message::CheckChannel"); - return service->CheckChannel(this, ref, channel); -} - -pid_t Message::GetProcessId() const { return info_.pid; } - -pid_t Message::GetThreadId() const { return info_.tid; } - -uid_t Message::GetEffectiveUserId() const { return info_.euid; } - -gid_t Message::GetEffectiveGroupId() const { return info_.egid; } - -int Message::GetChannelId() const { return info_.cid; } - -int Message::GetMessageId() const { return info_.mid; } - -int Message::GetOp() const { return info_.op; } - -int Message::GetFlags() const { return info_.flags; } - -size_t Message::GetSendLength() const { return info_.send_len; } - -size_t Message::GetReceiveLength() const { return info_.recv_len; } - -size_t Message::GetFileDescriptorCount() const { return info_.fd_count; } - -std::shared_ptr<Channel> Message::GetChannel() const { return channel_.lock(); } - -Status<void> Message::SetChannel(const std::shared_ptr<Channel>& chan) { - channel_ = chan; - Status<void> status; - if (auto svc = service_.lock()) - status = svc->SetChannel(info_.cid, chan); - return status; -} - -std::shared_ptr<Service> Message::GetService() const { return service_.lock(); } - -const MessageInfo& Message::GetInfo() const { return info_; } - -Service::Service(const std::string& name, std::unique_ptr<Endpoint> endpoint) - : name_(name), endpoint_{std::move(endpoint)} { - if (!endpoint_) - return; - - const auto status = endpoint_->SetService(this); - ALOGE_IF(!status, "Failed to set service context because: %s", - status.GetErrorMessage().c_str()); -} - -Service::~Service() { - if (endpoint_) { - const auto status = endpoint_->SetService(nullptr); - ALOGE_IF(!status, "Failed to clear service context because: %s", - status.GetErrorMessage().c_str()); - } -} - -std::shared_ptr<Service> Service::GetFromMessageInfo(const MessageInfo& info) { - return info.service ? info.service->shared_from_this() - : std::shared_ptr<Service>(); -} - -bool Service::IsInitialized() const { return endpoint_.get() != nullptr; } - -std::shared_ptr<Channel> Service::OnChannelOpen(Message& /*message*/) { - return nullptr; -} - -void Service::OnChannelClose(Message& /*message*/, - const std::shared_ptr<Channel>& /*channel*/) {} - -Status<void> Service::SetChannel(int channel_id, - const std::shared_ptr<Channel>& channel) { - PDX_TRACE_NAME("Service::SetChannel"); - std::lock_guard<std::mutex> autolock(channels_mutex_); - - const auto status = endpoint_->SetChannel(channel_id, channel.get()); - if (!status) { - ALOGE("%s::SetChannel: Failed to set channel context: %s\n", name_.c_str(), - status.GetErrorMessage().c_str()); - - // It's possible someone mucked with things behind our back by calling the C - // API directly. Since we know the channel id isn't valid, make sure we - // don't have it in the channels map. - if (status.error() == ENOENT) - channels_.erase(channel_id); - } else { - if (channel != nullptr) - channels_[channel_id] = channel; - else - channels_.erase(channel_id); - } - return status; -} - -std::shared_ptr<Channel> Service::GetChannel(int channel_id) const { - PDX_TRACE_NAME("Service::GetChannel"); - std::lock_guard<std::mutex> autolock(channels_mutex_); - - auto search = channels_.find(channel_id); - if (search != channels_.end()) - return search->second; - else - return nullptr; -} - -Status<void> Service::CloseChannel(int channel_id) { - PDX_TRACE_NAME("Service::CloseChannel"); - std::lock_guard<std::mutex> autolock(channels_mutex_); - - const auto status = endpoint_->CloseChannel(channel_id); - - // Always erase the map entry, in case someone mucked with things behind our - // back using the C API directly. - channels_.erase(channel_id); - - return status; -} - -Status<void> Service::ModifyChannelEvents(int channel_id, int clear_mask, - int set_mask) { - PDX_TRACE_NAME("Service::ModifyChannelEvents"); - return endpoint_->ModifyChannelEvents(channel_id, clear_mask, set_mask); -} - -Status<RemoteChannelHandle> Service::PushChannel( - Message* message, int flags, const std::shared_ptr<Channel>& channel, - int* channel_id) { - PDX_TRACE_NAME("Service::PushChannel"); - - std::lock_guard<std::mutex> autolock(channels_mutex_); - - int channel_id_temp = -1; - Status<RemoteChannelHandle> ret = - endpoint_->PushChannel(message, flags, channel.get(), &channel_id_temp); - ALOGE_IF(!ret.ok(), "%s::PushChannel: Failed to push channel: %s", - name_.c_str(), strerror(ret.error())); - - if (channel && channel_id_temp != -1) - channels_[channel_id_temp] = channel; - if (channel_id) - *channel_id = channel_id_temp; - - return ret; -} - -Status<int> Service::CheckChannel(const Message* message, ChannelReference ref, - std::shared_ptr<Channel>* channel) const { - PDX_TRACE_NAME("Service::CheckChannel"); - - // Synchronization to maintain consistency between the kernel's channel - // context pointer and the userspace channels_ map. Other threads may attempt - // to modify the map at the same time, which could cause the channel context - // pointer returned by the kernel to be invalid. - std::lock_guard<std::mutex> autolock(channels_mutex_); - - Channel* channel_context = nullptr; - Status<int> ret = endpoint_->CheckChannel( - message, ref, channel ? &channel_context : nullptr); - if (ret && channel) { - if (channel_context) - *channel = channel_context->shared_from_this(); - else - *channel = nullptr; - } - - return ret; -} - -std::string Service::DumpState(size_t /*max_length*/) { return ""; } - -Status<void> Service::HandleMessage(Message& message) { - return DefaultHandleMessage(message); -} - -void Service::HandleImpulse(Message& /*impulse*/) {} - -Status<void> Service::HandleSystemMessage(Message& message) { - const MessageInfo& info = message.GetInfo(); - - switch (info.op) { - case opcodes::CHANNEL_OPEN: { - ALOGD("%s::OnChannelOpen: pid=%d cid=%d\n", name_.c_str(), info.pid, - info.cid); - message.SetChannel(OnChannelOpen(message)); - return message.Reply(0); - } - - case opcodes::CHANNEL_CLOSE: { - ALOGD("%s::OnChannelClose: pid=%d cid=%d\n", name_.c_str(), info.pid, - info.cid); - OnChannelClose(message, Channel::GetFromMessageInfo(info)); - message.SetChannel(nullptr); - return message.Reply(0); - } - - case opcodes::REPORT_SYSPROP_CHANGE: - ALOGD("%s:REPORT_SYSPROP_CHANGE: pid=%d cid=%d\n", name_.c_str(), - info.pid, info.cid); - OnSysPropChange(); - android::report_sysprop_change(); - return message.Reply(0); - - case opcodes::DUMP_STATE: { - ALOGD("%s:DUMP_STATE: pid=%d cid=%d\n", name_.c_str(), info.pid, - info.cid); - auto response = DumpState(message.GetReceiveLength()); - const size_t response_size = response.size() < message.GetReceiveLength() - ? response.size() - : message.GetReceiveLength(); - const Status<size_t> status = - message.Write(response.data(), response_size); - if (status && status.get() < response_size) - return message.ReplyError(EIO); - else - return message.Reply(status); - } - - default: - return ErrorStatus{EOPNOTSUPP}; - } -} - -Status<void> Service::DefaultHandleMessage(Message& message) { - const MessageInfo& info = message.GetInfo(); - - ALOGD_IF(TRACE, "Service::DefaultHandleMessage: pid=%d cid=%d op=%d\n", - info.pid, info.cid, info.op); - - switch (info.op) { - case opcodes::CHANNEL_OPEN: - case opcodes::CHANNEL_CLOSE: - case opcodes::REPORT_SYSPROP_CHANGE: - case opcodes::DUMP_STATE: - return HandleSystemMessage(message); - - default: - return message.ReplyError(EOPNOTSUPP); - } -} - -void Service::OnSysPropChange() {} - -Status<void> Service::ReceiveAndDispatch() { - Message message; - const auto status = endpoint_->MessageReceive(&message); - if (!status) { - ALOGE("Failed to receive message: %s\n", status.GetErrorMessage().c_str()); - return status; - } - - std::shared_ptr<Service> service = message.GetService(); - - if (!service) { - ALOGE("Service::ReceiveAndDispatch: service context is NULL!!!\n"); - // Don't block the sender indefinitely in this error case. - endpoint_->MessageReply(&message, -EINVAL); - return ErrorStatus{EINVAL}; - } - - if (message.IsImpulse()) { - service->HandleImpulse(message); - return {}; - } else if (service->HandleSystemMessage(message)) { - return {}; - } else { - return service->HandleMessage(message); - } -} - -Status<void> Service::Cancel() { return endpoint_->Cancel(); } - -} // namespace pdx -} // namespace android diff --git a/libs/vr/libpdx/service_dispatcher.cpp b/libs/vr/libpdx/service_dispatcher.cpp deleted file mode 100644 index ba0d69c178..0000000000 --- a/libs/vr/libpdx/service_dispatcher.cpp +++ /dev/null @@ -1,192 +0,0 @@ -#include <pdx/service_dispatcher.h> - -#include <errno.h> -#include <log/log.h> -#include <sys/epoll.h> -#include <sys/eventfd.h> - -#include <pdx/service.h> -#include <pdx/service_endpoint.h> - -static const int kMaxEventsPerLoop = 128; - -namespace android { -namespace pdx { - -std::unique_ptr<ServiceDispatcher> ServiceDispatcher::Create() { - std::unique_ptr<ServiceDispatcher> dispatcher{new ServiceDispatcher()}; - if (!dispatcher->epoll_fd_ || !dispatcher->event_fd_) { - dispatcher.reset(); - } - - return dispatcher; -} - -ServiceDispatcher::ServiceDispatcher() { - event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK)); - if (!event_fd_) { - ALOGE("Failed to create event fd because: %s\n", strerror(errno)); - return; - } - - epoll_fd_.Reset(epoll_create1(EPOLL_CLOEXEC)); - if (!epoll_fd_) { - ALOGE("Failed to create epoll fd because: %s\n", strerror(errno)); - return; - } - - // Use "this" as a unique pointer to distinguish the event fd from all - // the other entries that point to instances of Service. - epoll_event event; - event.events = EPOLLIN; - event.data.ptr = this; - - if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, event_fd_.Get(), &event) < 0) { - ALOGE("Failed to add event fd to epoll fd because: %s\n", strerror(errno)); - - // Close the fds here and signal failure to the factory method. - event_fd_.Close(); - epoll_fd_.Close(); - } -} - -ServiceDispatcher::~ServiceDispatcher() { SetCanceled(true); } - -int ServiceDispatcher::ThreadEnter() { - std::lock_guard<std::mutex> autolock(mutex_); - - if (canceled_) - return -EBUSY; - - thread_count_++; - return 0; -} - -void ServiceDispatcher::ThreadExit() { - std::lock_guard<std::mutex> autolock(mutex_); - thread_count_--; - condition_.notify_one(); -} - -int ServiceDispatcher::AddService(const std::shared_ptr<Service>& service) { - std::lock_guard<std::mutex> autolock(mutex_); - - epoll_event event; - event.events = EPOLLIN; - event.data.ptr = service.get(); - - if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, service->endpoint()->epoll_fd(), - &event) < 0) { - ALOGE("Failed to add service to dispatcher because: %s\n", strerror(errno)); - return -errno; - } - - services_.push_back(service); - return 0; -} - -int ServiceDispatcher::RemoveService(const std::shared_ptr<Service>& service) { - std::lock_guard<std::mutex> autolock(mutex_); - - // It's dangerous to remove a service while other threads may be using it. - if (thread_count_ > 0) - return -EBUSY; - - epoll_event ee; // See BUGS in man 2 epoll_ctl. - if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_DEL, service->endpoint()->epoll_fd(), - &ee) < 0) { - ALOGE("Failed to remove service from dispatcher because: %s\n", - strerror(errno)); - return -errno; - } - - services_.erase(std::remove(services_.begin(), services_.end(), service), - services_.end()); - return 0; -} - -int ServiceDispatcher::ReceiveAndDispatch() { return ReceiveAndDispatch(-1); } - -int ServiceDispatcher::ReceiveAndDispatch(int timeout) { - int ret = ThreadEnter(); - if (ret < 0) - return ret; - - epoll_event events[kMaxEventsPerLoop]; - - int count = epoll_wait(epoll_fd_.Get(), events, kMaxEventsPerLoop, timeout); - if (count <= 0) { - ALOGE_IF(count < 0, "Failed to wait for epoll events because: %s\n", - strerror(errno)); - ThreadExit(); - return count < 0 ? -errno : -ETIMEDOUT; - } - - for (int i = 0; i < count; i++) { - if (events[i].data.ptr == this) { - ThreadExit(); - return -EBUSY; - } else { - Service* service = static_cast<Service*>(events[i].data.ptr); - - ALOGI_IF(TRACE, "Dispatching message: fd=%d\n", - service->endpoint()->epoll_fd()); - service->ReceiveAndDispatch(); - } - } - - ThreadExit(); - return 0; -} - -int ServiceDispatcher::EnterDispatchLoop() { - int ret = ThreadEnter(); - if (ret < 0) - return ret; - - epoll_event events[kMaxEventsPerLoop]; - - while (!IsCanceled()) { - int count = epoll_wait(epoll_fd_.Get(), events, kMaxEventsPerLoop, -1); - if (count < 0 && errno != EINTR) { - ALOGE("Failed to wait for epoll events because: %s\n", strerror(errno)); - ThreadExit(); - return -errno; - } - - for (int i = 0; i < count; i++) { - if (events[i].data.ptr == this) { - ThreadExit(); - return -EBUSY; - } else { - Service* service = static_cast<Service*>(events[i].data.ptr); - - ALOGI_IF(TRACE, "Dispatching message: fd=%d\n", - service->endpoint()->epoll_fd()); - service->ReceiveAndDispatch(); - } - } - } - - ThreadExit(); - return 0; -} - -void ServiceDispatcher::SetCanceled(bool cancel) { - std::unique_lock<std::mutex> lock(mutex_); - canceled_ = cancel; - - if (canceled_ && thread_count_ > 0) { - eventfd_write(event_fd_.Get(), 1); // Signal threads to quit. - - condition_.wait(lock, [this] { return !(canceled_ && thread_count_ > 0); }); - - eventfd_t value; - eventfd_read(event_fd_.Get(), &value); // Unsignal. - } -} - -bool ServiceDispatcher::IsCanceled() const { return canceled_; } - -} // namespace pdx -} // namespace android diff --git a/libs/vr/libpdx/service_tests.cpp b/libs/vr/libpdx/service_tests.cpp deleted file mode 100644 index 938d73774e..0000000000 --- a/libs/vr/libpdx/service_tests.cpp +++ /dev/null @@ -1,809 +0,0 @@ -#include <pdx/service.h> - -#include <memory> -#include <string> - -#include <gmock/gmock.h> -#include <pdx/mock_service_endpoint.h> - -using android::pdx::BorrowedChannelHandle; -using android::pdx::BorrowedHandle; -using android::pdx::Channel; -using android::pdx::ChannelReference; -using android::pdx::ErrorStatus; -using android::pdx::FileReference; -using android::pdx::LocalChannelHandle; -using android::pdx::LocalHandle; -using android::pdx::Message; -using android::pdx::MessageInfo; -using android::pdx::MockEndpoint; -using android::pdx::RemoteChannelHandle; -using android::pdx::RemoteHandle; -using android::pdx::Service; -using android::pdx::Status; - -using testing::A; -using testing::ByMove; -using testing::DoAll; -using testing::Invoke; -using testing::Matcher; -using testing::Ref; -using testing::Return; -using testing::SetArgPointee; -using testing::WithArg; -using testing::WithoutArgs; -using testing::_; - -namespace { - -// Helper functions to construct fake void pointers for tests. -inline void* IntToPtr(intptr_t addr) { return reinterpret_cast<void*>(addr); } - -// Helper matchers for working with iovec structures in tests. -// Simple matcher for one element iovec array: -// EXPECT_CALL(mock, method(IoVecMatcher(ptr, size))); -MATCHER_P2(IoVecMatcher, ptr, size, "") { - return arg->iov_base == ptr && arg->iov_len == size; -} - -// Matcher for an array of iovecs: -// EXPECT_CALL(mock, -// method(IoVecMatcher(IoVecArray{{ptr1, size1}, {ptr2, size2}}))); -using IoVecArray = std::vector<iovec>; -MATCHER_P(IoVecMatcher, iovec_array, "") { - auto local_arg = arg; - for (const iovec& item : iovec_array) { - if (local_arg->iov_base != item.iov_base || local_arg->iov_len != item.iov_len) - return false; - local_arg++; - } - return true; -} - -using IoVecData = std::vector<std::string>; -MATCHER_P(IoVecDataMatcher, iovec_data, "") { - auto local_arg = arg; - for (const std::string& item : iovec_data) { - std::string data{reinterpret_cast<const char*>(local_arg->iov_base), - local_arg->iov_len}; - if (data != item) - return false; - local_arg++; - } - return true; -} - -MATCHER_P(FileHandleMatcher, value, "") { return arg.Get() == value; } -MATCHER_P(ChannelHandleMatcher, value, "") { return arg.value() == value; } - -enum : int { - kTestPid = 1, - kTestTid, - kTestCid, - kTestMid, - kTestEuid, - kTestEgid, - kTestOp, -}; - -class MockService : public Service { - public: - using Service::Service; - MOCK_METHOD1(OnChannelOpen, std::shared_ptr<Channel>(Message& message)); - MOCK_METHOD2(OnChannelClose, - void(Message& message, const std::shared_ptr<Channel>& channel)); - MOCK_METHOD1(HandleMessage, Status<void>(Message& message)); - MOCK_METHOD1(HandleImpulse, void(Message& impulse)); - MOCK_METHOD0(OnSysPropChange, void()); - MOCK_METHOD1(DumpState, std::string(size_t max_length)); -}; - -class ServiceTest : public testing::Test { - public: - ServiceTest() { - auto endpoint = std::make_unique<testing::StrictMock<MockEndpoint>>(); - EXPECT_CALL(*endpoint, SetService(_)) - .Times(2) - .WillRepeatedly(Return(Status<void>{})); - service_ = std::make_shared<MockService>("MockSvc", std::move(endpoint)); - } - - MockEndpoint* endpoint() { - return static_cast<MockEndpoint*>(service_->endpoint()); - } - - void SetupMessageInfo(MessageInfo* info, int32_t op, bool impulse = false) { - info->pid = kTestPid; - info->tid = kTestTid; - info->cid = kTestCid; - info->mid = impulse ? Message::IMPULSE_MESSAGE_ID : kTestMid; - info->euid = kTestEuid; - info->egid = kTestEgid; - info->op = op; - info->flags = 0; - info->service = service_.get(); - info->channel = nullptr; - info->send_len = 0; - info->recv_len = 0; - info->fd_count = 0; - memset(info->impulse, 0, sizeof(info->impulse)); - } - - void SetupMessageInfoAndDefaultExpectations(MessageInfo* info, int32_t op, - bool impulse = false) { - SetupMessageInfo(info, op, impulse); - EXPECT_CALL(*endpoint(), AllocateMessageState()).WillOnce(Return(kState)); - EXPECT_CALL(*endpoint(), FreeMessageState(kState)); - } - - void ExpectDefaultHandleMessage() { - EXPECT_CALL(*endpoint(), MessageReply(_, -EOPNOTSUPP)) - .WillOnce(Return(Status<void>{})); - } - - std::shared_ptr<MockService> service_; - void* kState = IntToPtr(123456); -}; - -class ServiceMessageTest : public ServiceTest { - public: - ServiceMessageTest() { - MessageInfo info; - SetupMessageInfoAndDefaultExpectations(&info, kTestOp); - message_ = std::make_unique<Message>(info); - } - - std::unique_ptr<Message> message_; -}; - -} // anonymous namespace - -/////////////////////////////////////////////////////////////////////////////// -// Service class tests -/////////////////////////////////////////////////////////////////////////////// - -TEST_F(ServiceTest, IsInitialized) { - EXPECT_TRUE(service_->IsInitialized()); - service_ = std::make_shared<MockService>("MockSvc2", nullptr); - EXPECT_FALSE(service_->IsInitialized()); -} - -TEST_F(ServiceTest, ConstructMessage) { - MessageInfo info; - SetupMessageInfo(&info, kTestOp); - auto test_channel = std::make_shared<Channel>(); - info.channel = test_channel.get(); - EXPECT_CALL(*endpoint(), AllocateMessageState()).WillOnce(Return(kState)); - - Message message{info}; - - EXPECT_FALSE(message.IsImpulse()); - EXPECT_EQ(kTestPid, message.GetProcessId()); - EXPECT_EQ(kTestTid, message.GetThreadId()); - EXPECT_EQ(kTestCid, message.GetChannelId()); - EXPECT_EQ(kTestMid, message.GetMessageId()); - EXPECT_EQ((unsigned) kTestEuid, message.GetEffectiveUserId()); - EXPECT_EQ((unsigned) kTestEgid, message.GetEffectiveGroupId()); - EXPECT_EQ(kTestOp, message.GetOp()); - EXPECT_EQ(service_, message.GetService()); - EXPECT_EQ(test_channel, message.GetChannel()); - EXPECT_FALSE(message.replied()); - EXPECT_FALSE(message.IsChannelExpired()); - EXPECT_FALSE(message.IsServiceExpired()); - EXPECT_EQ(kState, message.GetState()); - - ExpectDefaultHandleMessage(); - EXPECT_CALL(*endpoint(), FreeMessageState(kState)); -} - -TEST_F(ServiceTest, ConstructImpulseMessage) { - MessageInfo info; - SetupMessageInfo(&info, kTestOp, true); - auto test_channel = std::make_shared<Channel>(); - info.channel = test_channel.get(); - EXPECT_CALL(*endpoint(), AllocateMessageState()).WillOnce(Return(nullptr)); - - Message message{info}; - - EXPECT_TRUE(message.IsImpulse()); - EXPECT_EQ(kTestOp, message.GetOp()); - EXPECT_EQ(service_, message.GetService()); - EXPECT_EQ(test_channel, message.GetChannel()); - EXPECT_TRUE(message.replied()); - EXPECT_FALSE(message.IsChannelExpired()); - EXPECT_FALSE(message.IsServiceExpired()); - - // DefaultHandleMessage should not be called here. - EXPECT_CALL(*endpoint(), FreeMessageState(nullptr)); -} - -TEST_F(ServiceTest, HandleMessageChannelOpen) { - MessageInfo info; - SetupMessageInfoAndDefaultExpectations(&info, - android::pdx::opcodes::CHANNEL_OPEN); - Message message{info}; - - auto channel = std::make_shared<Channel>(); - EXPECT_CALL(*service_, OnChannelOpen(Ref(message))).WillOnce(Return(channel)); - EXPECT_CALL(*endpoint(), SetChannel(kTestCid, channel.get())) - .WillOnce(Return(Status<void>{})); - EXPECT_CALL(*endpoint(), MessageReply(&message, 0)) - .WillOnce(Return(Status<void>{})); - - EXPECT_TRUE(service_->Service::HandleMessage(message)); -} - -TEST_F(ServiceTest, HandleMessageChannelClose) { - MessageInfo info; - SetupMessageInfoAndDefaultExpectations(&info, - android::pdx::opcodes::CHANNEL_CLOSE); - auto channel = std::make_shared<Channel>(); - info.channel = channel.get(); - Message message{info}; - - EXPECT_CALL(*service_, OnChannelClose(Ref(message), channel)); - EXPECT_CALL(*endpoint(), SetChannel(kTestCid, nullptr)) - .WillOnce(Return(Status<void>{})); - EXPECT_CALL(*endpoint(), MessageReply(&message, 0)) - .WillOnce(Return(Status<void>{})); - - EXPECT_TRUE(service_->Service::HandleMessage(message)); -} - -TEST_F(ServiceTest, HandleMessageOnSysPropChange) { - MessageInfo info; - SetupMessageInfoAndDefaultExpectations( - &info, android::pdx::opcodes::REPORT_SYSPROP_CHANGE); - Message message{info}; - - EXPECT_CALL(*service_, OnSysPropChange()); - EXPECT_CALL(*endpoint(), MessageReply(&message, 0)) - .WillOnce(Return(Status<void>{})); - - EXPECT_TRUE(service_->Service::HandleMessage(message)); -} - -TEST_F(ServiceTest, HandleMessageOnDumpState) { - const size_t kRecvBufSize = 1000; - MessageInfo info; - SetupMessageInfoAndDefaultExpectations(&info, - android::pdx::opcodes::DUMP_STATE); - info.recv_len = kRecvBufSize; - Message message{info}; - - const std::string kReply = "foo"; - EXPECT_CALL(*service_, DumpState(kRecvBufSize)).WillOnce(Return(kReply)); - EXPECT_CALL( - *endpoint(), - WriteMessageData(&message, IoVecDataMatcher(IoVecData{kReply}), 1)) - .WillOnce(Return(kReply.size())); - EXPECT_CALL(*endpoint(), MessageReply(&message, kReply.size())) - .WillOnce(Return(Status<void>{})); - - EXPECT_TRUE(service_->Service::HandleMessage(message)); -} - -TEST_F(ServiceTest, HandleMessageOnDumpStateTooLarge) { - const size_t kRecvBufSize = 3; - MessageInfo info; - SetupMessageInfoAndDefaultExpectations(&info, - android::pdx::opcodes::DUMP_STATE); - info.recv_len = kRecvBufSize; - Message message{info}; - - const std::string kReply = "0123456789"; - const std::string kActualReply = kReply.substr(0, kRecvBufSize); - EXPECT_CALL(*service_, DumpState(kRecvBufSize)).WillOnce(Return(kReply)); - EXPECT_CALL( - *endpoint(), - WriteMessageData(&message, IoVecDataMatcher(IoVecData{kActualReply}), 1)) - .WillOnce(Return(kActualReply.size())); - EXPECT_CALL(*endpoint(), MessageReply(&message, kActualReply.size())) - .WillOnce(Return(Status<void>{})); - - EXPECT_TRUE(service_->Service::HandleMessage(message)); -} - -TEST_F(ServiceTest, HandleMessageOnDumpStateFail) { - const size_t kRecvBufSize = 1000; - MessageInfo info; - SetupMessageInfoAndDefaultExpectations(&info, - android::pdx::opcodes::DUMP_STATE); - info.recv_len = kRecvBufSize; - Message message{info}; - - const std::string kReply = "foo"; - EXPECT_CALL(*service_, DumpState(kRecvBufSize)).WillOnce(Return(kReply)); - EXPECT_CALL( - *endpoint(), - WriteMessageData(&message, IoVecDataMatcher(IoVecData{kReply}), 1)) - .WillOnce(Return(1)); - EXPECT_CALL(*endpoint(), MessageReply(&message, -EIO)) - .WillOnce(Return(Status<void>{})); - - EXPECT_TRUE(service_->Service::HandleMessage(message)); -} - -TEST_F(ServiceTest, HandleMessageCustom) { - MessageInfo info; - SetupMessageInfoAndDefaultExpectations(&info, kTestOp); - Message message{info}; - - EXPECT_CALL(*endpoint(), MessageReply(&message, -EOPNOTSUPP)) - .WillOnce(Return(Status<void>{})); - - EXPECT_TRUE(service_->Service::HandleMessage(message)); -} - -TEST_F(ServiceTest, ReplyMessageWithoutService) { - MessageInfo info; - SetupMessageInfo(&info, kTestOp); - EXPECT_CALL(*endpoint(), AllocateMessageState()).WillOnce(Return(nullptr)); - - Message message{info}; - - EXPECT_FALSE(message.IsServiceExpired()); - service_.reset(); - EXPECT_TRUE(message.IsServiceExpired()); - - EXPECT_EQ(EINVAL, message.Reply(12).error()); -} - -TEST_F(ServiceTest, ReceiveAndDispatchMessage) { - MessageInfo info; - SetupMessageInfoAndDefaultExpectations(&info, kTestOp); - ExpectDefaultHandleMessage(); - - auto on_receive = [&info](Message* message) -> Status<void> { - *message = Message{info}; - return {}; - }; - EXPECT_CALL(*endpoint(), MessageReceive(_)).WillOnce(Invoke(on_receive)); - EXPECT_CALL(*service_, HandleMessage(_)).WillOnce(Return(Status<void>{})); - - EXPECT_TRUE(service_->ReceiveAndDispatch()); -} - -TEST_F(ServiceTest, ReceiveAndDispatchImpulse) { - MessageInfo info; - SetupMessageInfoAndDefaultExpectations(&info, kTestOp, true); - - auto on_receive = [&info](Message* message) -> Status<void> { - *message = Message{info}; - return {}; - }; - EXPECT_CALL(*endpoint(), MessageReceive(_)).WillOnce(Invoke(on_receive)); - EXPECT_CALL(*service_, HandleImpulse(_)); - - EXPECT_TRUE(service_->ReceiveAndDispatch()); -} - -TEST_F(ServiceTest, Cancel) { - EXPECT_CALL(*endpoint(), Cancel()).WillOnce(Return(Status<void>{})); - EXPECT_TRUE(service_->Cancel()); -} - -/////////////////////////////////////////////////////////////////////////////// -// Message class tests -/////////////////////////////////////////////////////////////////////////////// - -TEST_F(ServiceMessageTest, Reply) { - EXPECT_CALL(*endpoint(), MessageReply(message_.get(), 12)) - .WillOnce(Return(Status<void>{})); - EXPECT_FALSE(message_->replied()); - EXPECT_TRUE(message_->Reply(12)); - EXPECT_TRUE(message_->replied()); - - EXPECT_EQ(EINVAL, message_->Reply(12).error()); // Already replied. -} - -TEST_F(ServiceMessageTest, ReplyFail) { - EXPECT_CALL(*endpoint(), MessageReply(message_.get(), 12)) - .WillOnce(Return(ErrorStatus{EIO})); - EXPECT_EQ(EIO, message_->Reply(12).error()); - - ExpectDefaultHandleMessage(); -} - -TEST_F(ServiceMessageTest, ReplyError) { - EXPECT_CALL(*endpoint(), MessageReply(message_.get(), -12)) - .WillOnce(Return(Status<void>{})); - EXPECT_TRUE(message_->ReplyError(12)); -} - -TEST_F(ServiceMessageTest, ReplyFileDescriptor) { - EXPECT_CALL(*endpoint(), MessageReplyFd(message_.get(), 5)) - .WillOnce(Return(Status<void>{})); - EXPECT_TRUE(message_->ReplyFileDescriptor(5)); -} - -TEST_F(ServiceMessageTest, ReplyLocalFileHandle) { - const int kFakeFd = 12345; - LocalHandle handle{kFakeFd}; - EXPECT_CALL(*endpoint(), MessageReplyFd(message_.get(), kFakeFd)) - .WillOnce(Return(Status<void>{})); - EXPECT_TRUE(message_->Reply(handle)); - handle.Release(); // Make sure we do not close the fake file descriptor. -} - -TEST_F(ServiceMessageTest, ReplyLocalFileHandleError) { - LocalHandle handle{-EINVAL}; - EXPECT_CALL(*endpoint(), MessageReply(message_.get(), -EINVAL)) - .WillOnce(Return(Status<void>{})); - EXPECT_TRUE(message_->Reply(handle)); -} - -TEST_F(ServiceMessageTest, ReplyBorrowedFileHandle) { - const int kFakeFd = 12345; - BorrowedHandle handle{kFakeFd}; - EXPECT_CALL(*endpoint(), MessageReplyFd(message_.get(), kFakeFd)) - .WillOnce(Return(Status<void>{})); - EXPECT_TRUE(message_->Reply(handle)); -} - -TEST_F(ServiceMessageTest, ReplyBorrowedFileHandleError) { - BorrowedHandle handle{-EACCES}; - EXPECT_CALL(*endpoint(), MessageReply(message_.get(), -EACCES)) - .WillOnce(Return(Status<void>{})); - EXPECT_TRUE(message_->Reply(handle)); -} - -TEST_F(ServiceMessageTest, ReplyRemoteFileHandle) { - RemoteHandle handle{123}; - EXPECT_CALL(*endpoint(), MessageReply(message_.get(), handle.Get())) - .WillOnce(Return(Status<void>{})); - EXPECT_TRUE(message_->Reply(handle)); -} - -TEST_F(ServiceMessageTest, ReplyRemoteFileHandleError) { - RemoteHandle handle{-EIO}; - EXPECT_CALL(*endpoint(), MessageReply(message_.get(), -EIO)) - .WillOnce(Return(Status<void>{})); - EXPECT_TRUE(message_->Reply(handle)); -} - -TEST_F(ServiceMessageTest, ReplyLocalChannelHandle) { - LocalChannelHandle handle{nullptr, 12345}; - EXPECT_CALL(*endpoint(), MessageReplyChannelHandle( - message_.get(), A<const LocalChannelHandle&>())) - .WillOnce(Return(Status<void>{})); - EXPECT_TRUE(message_->Reply(handle)); -} - -TEST_F(ServiceMessageTest, ReplyBorrowedChannelHandle) { - BorrowedChannelHandle handle{12345}; - EXPECT_CALL(*endpoint(), - MessageReplyChannelHandle(message_.get(), - A<const BorrowedChannelHandle&>())) - .WillOnce(Return(Status<void>{})); - EXPECT_TRUE(message_->Reply(handle)); -} - -TEST_F(ServiceMessageTest, ReplyRemoteChannelHandle) { - RemoteChannelHandle handle{12345}; - EXPECT_CALL(*endpoint(), MessageReplyChannelHandle( - message_.get(), A<const RemoteChannelHandle&>())) - .WillOnce(Return(Status<void>{})); - EXPECT_TRUE(message_->Reply(handle)); -} - -TEST_F(ServiceMessageTest, ReplyStatusInt) { - Status<int> status{123}; - EXPECT_CALL(*endpoint(), MessageReply(message_.get(), status.get())) - .WillOnce(Return(Status<void>{})); - EXPECT_TRUE(message_->Reply(status)); -} - -TEST_F(ServiceMessageTest, ReplyStatusError) { - Status<int> status{ErrorStatus{EIO}}; - EXPECT_CALL(*endpoint(), MessageReply(message_.get(), -status.error())) - .WillOnce(Return(Status<void>{})); - EXPECT_TRUE(message_->Reply(status)); -} - -TEST_F(ServiceMessageTest, Read) { - ExpectDefaultHandleMessage(); - void* const kDataBuffer = IntToPtr(12345); - const size_t kDataSize = 100; - EXPECT_CALL( - *endpoint(), - ReadMessageData(message_.get(), IoVecMatcher(kDataBuffer, kDataSize), 1)) - .WillOnce(Return(50)) - .WillOnce(Return(ErrorStatus{EACCES})); - EXPECT_EQ(50u, message_->Read(kDataBuffer, kDataSize).get()); - EXPECT_EQ(EACCES, message_->Read(kDataBuffer, kDataSize).error()); -} - -TEST_F(ServiceMessageTest, ReadVector) { - ExpectDefaultHandleMessage(); - char buffer1[10]; - char buffer2[20]; - iovec vec[] = {{buffer1, sizeof(buffer1)}, {buffer2, sizeof(buffer2)}}; - EXPECT_CALL(*endpoint(), - ReadMessageData( - message_.get(), - IoVecMatcher(IoVecArray{std::begin(vec), std::end(vec)}), 2)) - .WillOnce(Return(30)) - .WillOnce(Return(15)) - .WillOnce(Return(ErrorStatus{EBADF})); - EXPECT_EQ(30u, message_->ReadVector(vec, 2).get()); - EXPECT_EQ(15u, message_->ReadVector(vec).get()); - EXPECT_EQ(EBADF, message_->ReadVector(vec).error()); -} - -TEST_F(ServiceMessageTest, Write) { - ExpectDefaultHandleMessage(); - void* const kDataBuffer = IntToPtr(12345); - const size_t kDataSize = 100; - EXPECT_CALL( - *endpoint(), - WriteMessageData(message_.get(), IoVecMatcher(kDataBuffer, kDataSize), 1)) - .WillOnce(Return(50)) - .WillOnce(Return(ErrorStatus{EBADMSG})); - EXPECT_EQ(50u, message_->Write(kDataBuffer, kDataSize).get()); - EXPECT_EQ(EBADMSG, message_->Write(kDataBuffer, kDataSize).error()); -} - -TEST_F(ServiceMessageTest, WriteVector) { - ExpectDefaultHandleMessage(); - char buffer1[10]; - char buffer2[20]; - iovec vec[] = {{buffer1, sizeof(buffer1)}, {buffer2, sizeof(buffer2)}}; - EXPECT_CALL(*endpoint(), - WriteMessageData( - message_.get(), - IoVecMatcher(IoVecArray{std::begin(vec), std::end(vec)}), 2)) - .WillOnce(Return(30)) - .WillOnce(Return(15)) - .WillOnce(Return(ErrorStatus{EIO})); - EXPECT_EQ(30u, message_->WriteVector(vec, 2).get()); - EXPECT_EQ(15u, message_->WriteVector(vec).get()); - EXPECT_EQ(EIO, message_->WriteVector(vec, 2).error()); -} - -TEST_F(ServiceMessageTest, PushLocalFileHandle) { - ExpectDefaultHandleMessage(); - const int kFakeFd = 12345; - LocalHandle handle{kFakeFd}; - EXPECT_CALL(*endpoint(), - PushFileHandle(message_.get(), Matcher<const LocalHandle&>( - FileHandleMatcher(kFakeFd)))) - .WillOnce(Return(12)) - .WillOnce(Return(ErrorStatus{EIO})); - EXPECT_EQ(12, message_->PushFileHandle(handle).get()); - EXPECT_EQ(EIO, message_->PushFileHandle(handle).error()); - handle.Release(); // Make sure we do not close the fake file descriptor. -} - -TEST_F(ServiceMessageTest, PushBorrowedFileHandle) { - ExpectDefaultHandleMessage(); - const int kFakeFd = 12345; - BorrowedHandle handle{kFakeFd}; - EXPECT_CALL(*endpoint(), - PushFileHandle(message_.get(), Matcher<const BorrowedHandle&>( - FileHandleMatcher(kFakeFd)))) - .WillOnce(Return(13)) - .WillOnce(Return(ErrorStatus{EACCES})); - EXPECT_EQ(13, message_->PushFileHandle(handle).get()); - EXPECT_EQ(EACCES, message_->PushFileHandle(handle).error()); -} - -TEST_F(ServiceMessageTest, PushRemoteFileHandle) { - ExpectDefaultHandleMessage(); - const int kFakeFd = 12345; - RemoteHandle handle{kFakeFd}; - EXPECT_CALL(*endpoint(), - PushFileHandle(message_.get(), Matcher<const RemoteHandle&>( - FileHandleMatcher(kFakeFd)))) - .WillOnce(Return(kFakeFd)) - .WillOnce(Return(ErrorStatus{EIO})); - EXPECT_EQ(kFakeFd, message_->PushFileHandle(handle).get()); - EXPECT_EQ(EIO, message_->PushFileHandle(handle).error()); -} - -TEST_F(ServiceMessageTest, PushLocalChannelHandle) { - ExpectDefaultHandleMessage(); - int32_t kValue = 12345; - LocalChannelHandle handle{nullptr, kValue}; - EXPECT_CALL(*endpoint(), PushChannelHandle(message_.get(), - Matcher<const LocalChannelHandle&>( - ChannelHandleMatcher(kValue)))) - .WillOnce(Return(7)) - .WillOnce(Return(ErrorStatus{EIO})); - EXPECT_EQ(7, message_->PushChannelHandle(handle).get()); - EXPECT_EQ(EIO, message_->PushChannelHandle(handle).error()); -} - -TEST_F(ServiceMessageTest, PushBorrowedChannelHandle) { - ExpectDefaultHandleMessage(); - int32_t kValue = 12345; - BorrowedChannelHandle handle{kValue}; - EXPECT_CALL( - *endpoint(), - PushChannelHandle(message_.get(), Matcher<const BorrowedChannelHandle&>( - ChannelHandleMatcher(kValue)))) - .WillOnce(Return(8)) - .WillOnce(Return(ErrorStatus{EIO})); - EXPECT_EQ(8, message_->PushChannelHandle(handle).get()); - EXPECT_EQ(EIO, message_->PushChannelHandle(handle).error()); -} - -TEST_F(ServiceMessageTest, PushRemoteChannelHandle) { - ExpectDefaultHandleMessage(); - int32_t kValue = 12345; - RemoteChannelHandle handle{kValue}; - EXPECT_CALL( - *endpoint(), - PushChannelHandle(message_.get(), Matcher<const RemoteChannelHandle&>( - ChannelHandleMatcher(kValue)))) - .WillOnce(Return(kValue)) - .WillOnce(Return(ErrorStatus{EIO})); - EXPECT_EQ(kValue, message_->PushChannelHandle(handle).get()); - EXPECT_EQ(EIO, message_->PushChannelHandle(handle).error()); -} - -TEST_F(ServiceMessageTest, GetFileHandle) { - ExpectDefaultHandleMessage(); - auto make_file_handle = [](FileReference ref) { return LocalHandle{ref}; }; - EXPECT_CALL(*endpoint(), GetFileHandle(message_.get(), _)) - .WillOnce(WithArg<1>(Invoke(make_file_handle))); - LocalHandle handle; - FileReference kRef = 12345; - EXPECT_TRUE(message_->GetFileHandle(kRef, &handle)); - EXPECT_EQ(kRef, handle.Get()); - handle.Release(); // Make sure we do not close the fake file descriptor. -} - -TEST_F(ServiceMessageTest, GetFileHandleInvalid) { - ExpectDefaultHandleMessage(); - LocalHandle handle; - FileReference kRef = -12; - EXPECT_TRUE(message_->GetFileHandle(kRef, &handle)); - EXPECT_EQ(kRef, handle.Get()); -} - -TEST_F(ServiceMessageTest, GetFileHandleError) { - ExpectDefaultHandleMessage(); - EXPECT_CALL(*endpoint(), GetFileHandle(message_.get(), _)) - .WillOnce(WithoutArgs(Invoke([] { return LocalHandle{-EIO}; }))); - LocalHandle handle; - FileReference kRef = 12345; - EXPECT_FALSE(message_->GetFileHandle(kRef, &handle)); - EXPECT_EQ(-EIO, handle.Get()); -} - -TEST_F(ServiceMessageTest, GetChannelHandle) { - ExpectDefaultHandleMessage(); - auto make_channel_handle = [](ChannelReference ref) { - return LocalChannelHandle{nullptr, ref}; - }; - EXPECT_CALL(*endpoint(), GetChannelHandle(message_.get(), _)) - .WillOnce(WithArg<1>(Invoke(make_channel_handle))); - LocalChannelHandle handle; - ChannelReference kRef = 12345; - EXPECT_TRUE(message_->GetChannelHandle(kRef, &handle)); - EXPECT_EQ(kRef, handle.value()); -} - -TEST_F(ServiceMessageTest, GetChannelHandleInvalid) { - ExpectDefaultHandleMessage(); - LocalChannelHandle handle; - ChannelReference kRef = -12; - EXPECT_TRUE(message_->GetChannelHandle(kRef, &handle)); - EXPECT_EQ(-12, handle.value()); -} - -TEST_F(ServiceMessageTest, GetChannelHandleError) { - ExpectDefaultHandleMessage(); - EXPECT_CALL(*endpoint(), GetChannelHandle(message_.get(), _)) - .WillOnce(WithoutArgs(Invoke([] { - return LocalChannelHandle{nullptr, -EIO}; - }))); - LocalChannelHandle handle; - ChannelReference kRef = 12345; - EXPECT_FALSE(message_->GetChannelHandle(kRef, &handle)); - EXPECT_EQ(-EIO, handle.value()); -} - -TEST_F(ServiceMessageTest, ModifyChannelEvents) { - ExpectDefaultHandleMessage(); - int kClearMask = 1; - int kSetMask = 2; - EXPECT_CALL(*endpoint(), ModifyChannelEvents(kTestCid, kClearMask, kSetMask)) - .WillOnce(Return(Status<void>{})); - EXPECT_TRUE(message_->ModifyChannelEvents(kClearMask, kSetMask)); -} - -TEST_F(ServiceMessageTest, PushChannelSameService) { - ExpectDefaultHandleMessage(); - int kFlags = 123; - int32_t kValue = 12; - EXPECT_CALL(*endpoint(), PushChannel(message_.get(), kFlags, nullptr, _)) - .WillOnce(DoAll(SetArgPointee<3>(kTestCid), - Return(ByMove(RemoteChannelHandle{kValue})))); - int channel_id = -1; - auto status = message_->PushChannel(kFlags, nullptr, &channel_id); - ASSERT_TRUE(status); - EXPECT_EQ(kValue, status.get().value()); - EXPECT_EQ(kTestCid, channel_id); -} - -TEST_F(ServiceMessageTest, PushChannelFailure) { - ExpectDefaultHandleMessage(); - int kFlags = 123; - EXPECT_CALL(*endpoint(), PushChannel(message_.get(), kFlags, nullptr, _)) - .WillOnce(Return(ByMove(ErrorStatus{EIO}))); - int channel_id = -1; - auto status = message_->PushChannel(kFlags, nullptr, &channel_id); - ASSERT_FALSE(status); - EXPECT_EQ(EIO, status.error()); -} - -TEST_F(ServiceMessageTest, PushChannelDifferentService) { - ExpectDefaultHandleMessage(); - auto endpoint2 = std::make_unique<testing::StrictMock<MockEndpoint>>(); - EXPECT_CALL(*endpoint2, SetService(_)) - .Times(2) - .WillRepeatedly(Return(Status<void>{})); - auto service2 = - std::make_shared<MockService>("MockSvc2", std::move(endpoint2)); - - int kFlags = 123; - int32_t kValue = 12; - EXPECT_CALL(*static_cast<MockEndpoint*>(service2->endpoint()), - PushChannel(message_.get(), kFlags, nullptr, _)) - .WillOnce(DoAll(SetArgPointee<3>(kTestCid), - Return(ByMove(RemoteChannelHandle{kValue})))); - int channel_id = -1; - auto status = - message_->PushChannel(service2.get(), kFlags, nullptr, &channel_id); - ASSERT_TRUE(status); - EXPECT_EQ(kValue, status.get().value()); - EXPECT_EQ(kTestCid, channel_id); -} - -TEST_F(ServiceMessageTest, CheckChannelSameService) { - ExpectDefaultHandleMessage(); - - auto test_channel = std::make_shared<Channel>(); - ChannelReference kRef = 123; - EXPECT_CALL(*endpoint(), CheckChannel(message_.get(), kRef, _)) - .WillOnce(DoAll(SetArgPointee<2>(test_channel.get()), Return(kTestCid))); - std::shared_ptr<Channel> channel; - auto status = message_->CheckChannel(kRef, &channel); - ASSERT_TRUE(status); - EXPECT_EQ(kTestCid, status.get()); - EXPECT_EQ(test_channel, channel); -} - -TEST_F(ServiceMessageTest, CheckChannelFailure) { - ExpectDefaultHandleMessage(); - ChannelReference kRef = 123; - EXPECT_CALL(*endpoint(), CheckChannel(message_.get(), kRef, _)) - .WillOnce(Return(ByMove(ErrorStatus{EOPNOTSUPP}))); - std::shared_ptr<Channel> channel; - auto status = message_->CheckChannel(kRef, &channel); - ASSERT_FALSE(status); - EXPECT_EQ(EOPNOTSUPP, status.error()); -} - -TEST_F(ServiceMessageTest, CheckChannelDifferentService) { - ExpectDefaultHandleMessage(); - auto endpoint2 = std::make_unique<testing::StrictMock<MockEndpoint>>(); - EXPECT_CALL(*endpoint2, SetService(_)) - .Times(2) - .WillRepeatedly(Return(Status<void>{})); - auto service2 = - std::make_shared<MockService>("MockSvc2", std::move(endpoint2)); - - auto test_channel = std::make_shared<Channel>(); - ChannelReference kRef = 123; - EXPECT_CALL(*static_cast<MockEndpoint*>(service2->endpoint()), - CheckChannel(message_.get(), kRef, _)) - .WillOnce(DoAll(SetArgPointee<2>(test_channel.get()), Return(kTestCid))); - std::shared_ptr<Channel> channel; - auto status = message_->CheckChannel(service2.get(), kRef, &channel); - ASSERT_TRUE(status); - EXPECT_EQ(kTestCid, status.get()); - EXPECT_EQ(test_channel, channel); -} diff --git a/libs/vr/libpdx/status.cpp b/libs/vr/libpdx/status.cpp deleted file mode 100644 index c275dafc5f..0000000000 --- a/libs/vr/libpdx/status.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "pdx/status.h" - -#include <pdx/rpc/serialization.h> -#include <string.h> - -namespace android { -namespace pdx { - -std::string ErrorStatus::ErrorToString(int error_code) { - char message[1024] = {}; - return strerror_r(error_code, message, sizeof(message)); -} - -} // namespace pdx -} // namespace android diff --git a/libs/vr/libpdx/status_tests.cpp b/libs/vr/libpdx/status_tests.cpp deleted file mode 100644 index 772c529947..0000000000 --- a/libs/vr/libpdx/status_tests.cpp +++ /dev/null @@ -1,127 +0,0 @@ -#include <pdx/status.h> - -#include <gtest/gtest.h> - -#include <memory> - -using android::pdx::ErrorStatus; -using android::pdx::Status; - -TEST(Status, DefaultInit) { - Status<int> status; - EXPECT_FALSE(status.ok()); - EXPECT_TRUE(status.empty()); - EXPECT_EQ(0, status.get()); - EXPECT_EQ(0, status.error()); -} - -TEST(Status, InitalizeSuccess) { - Status<int> status_int{0}; - EXPECT_FALSE(status_int.empty()); - EXPECT_TRUE(status_int.ok()); - EXPECT_EQ(0, status_int.get()); - status_int = Status<int>(3); - EXPECT_FALSE(status_int.empty()); - EXPECT_TRUE(status_int.ok()); - EXPECT_EQ(3, status_int.get()); - status_int = Status<int>(-3); - EXPECT_FALSE(status_int.empty()); - EXPECT_TRUE(status_int.ok()); - EXPECT_EQ(-3, status_int.get()); - - Status<std::string> status_str{"foo"}; - EXPECT_FALSE(status_str.empty()); - EXPECT_TRUE(status_str.ok()); - EXPECT_EQ("foo", status_str.get()); -} - -TEST(Status, InitalizeError) { - Status<int> status_int = ErrorStatus(12); - EXPECT_FALSE(status_int.empty()); - EXPECT_FALSE(status_int.ok()); - EXPECT_EQ(0, status_int.get()); - EXPECT_EQ(12, status_int.error()); - - Status<std::string> status_str = ErrorStatus(EIO); - EXPECT_FALSE(status_str.empty()); - EXPECT_FALSE(status_str.ok()); - EXPECT_EQ(EIO, status_str.error()); -} - -TEST(Status, ErrorMessage) { - Status<int> status = ErrorStatus(EIO); - EXPECT_EQ(status.GetErrorMessage(), strerror(EIO)); - - status = ErrorStatus(EINVAL); - EXPECT_EQ(status.GetErrorMessage(), strerror(EINVAL)); -} - -TEST(Status, Copy) { - Status<int> status1; - Status<int> status2; - - status1 = Status<int>{12}; - status2 = ErrorStatus(13); - EXPECT_FALSE(status1.empty()); - EXPECT_FALSE(status2.empty()); - EXPECT_TRUE(status1.ok()); - EXPECT_FALSE(status2.ok()); - EXPECT_EQ(12, status1.get()); - EXPECT_EQ(0, status1.error()); - EXPECT_EQ(0, status2.get()); - EXPECT_EQ(13, status2.error()); - - status1 = status2; - EXPECT_FALSE(status1.empty()); - EXPECT_FALSE(status2.empty()); - EXPECT_FALSE(status1.ok()); - EXPECT_FALSE(status2.ok()); - EXPECT_EQ(0, status1.get()); - EXPECT_EQ(13, status1.error()); - EXPECT_EQ(0, status2.get()); - EXPECT_EQ(13, status2.error()); -} - -TEST(Status, Move) { - Status<std::unique_ptr<int>> status1; - Status<std::unique_ptr<int>> status2; - - status1 = Status<std::unique_ptr<int>>{std::make_unique<int>(int{11})}; - status2 = Status<std::unique_ptr<int>>{std::make_unique<int>(int{12})}; - EXPECT_FALSE(status1.empty()); - EXPECT_FALSE(status2.empty()); - EXPECT_TRUE(status1.ok()); - EXPECT_TRUE(status2.ok()); - EXPECT_EQ(11, *status1.get()); - EXPECT_EQ(12, *status2.get()); - - Status<std::unique_ptr<int>> status3 = std::move(status2); - EXPECT_FALSE(status1.empty()); - EXPECT_TRUE(status2.empty()); - EXPECT_FALSE(status3.empty()); - EXPECT_TRUE(status1.ok()); - EXPECT_FALSE(status2.ok()); - EXPECT_TRUE(status3.ok()); - EXPECT_EQ(11, *status1.get()); - EXPECT_EQ(nullptr, status2.get()); - EXPECT_EQ(12, *status3.get()); - - std::swap(status1, status3); - EXPECT_EQ(12, *status1.get()); - EXPECT_EQ(11, *status3.get()); - - status3 = std::move(status1); - EXPECT_TRUE(status1.empty()); - EXPECT_EQ(12, *status3.get()); -} - -TEST(Status, Take) { - Status<std::unique_ptr<int>> status{std::make_unique<int>(int{123})}; - EXPECT_FALSE(status.empty()); - EXPECT_NE(nullptr, status.get()); - - auto data = status.take(); - EXPECT_TRUE(status.empty()); - EXPECT_EQ(nullptr, status.get()); - EXPECT_EQ(123, *data); -} diff --git a/libs/vr/libpdx/thread_local_buffer_tests.cpp b/libs/vr/libpdx/thread_local_buffer_tests.cpp deleted file mode 100644 index 6cdaf1071a..0000000000 --- a/libs/vr/libpdx/thread_local_buffer_tests.cpp +++ /dev/null @@ -1,117 +0,0 @@ -#include <memory> -#include <string> -#include <thread> -#include <utility> - -#include <gtest/gtest.h> -#include <pdx/rpc/message_buffer.h> - -namespace android { -namespace pdx { -namespace rpc { - -class ThreadLocalBufferTest { - public: - // Returns the unique address of the thread-local buffer. Used to test the - // correct behavior of the type-based thread local storage slot mapping - // mechanism. - template <typename Slot> - static std::uintptr_t GetSlotAddress() { - return reinterpret_cast<std::uintptr_t>(&MessageBuffer<Slot>::buffer_); - } - - // Returns the raw value of the thread local buffer. Used to test the behavior - // of backing buffer initialization. - template <typename Slot> - static std::uintptr_t GetSlotValue() { - return reinterpret_cast<std::uintptr_t>(MessageBuffer<Slot>::buffer_); - } -}; - -} // namespace rpc -} // namespace pdx -} // namespace android - -using namespace android::pdx::rpc; - -namespace { - -struct TypeTagA; -struct TypeTagB; - -constexpr std::size_t kSendBufferIndex = 0; -constexpr std::size_t kReceiveBufferIndex = 1; - -using SendSlotA = ThreadLocalSlot<TypeTagA, kSendBufferIndex>; -using SendSlotB = ThreadLocalSlot<TypeTagB, kSendBufferIndex>; -using ReceiveSlotA = ThreadLocalSlot<TypeTagA, kReceiveBufferIndex>; -using ReceiveSlotB = ThreadLocalSlot<TypeTagB, kReceiveBufferIndex>; - -} // anonymous namespace - -// Tests that index and type-based thread-local slot addressing works by -// checking that the slot address is the same when the same index/type -// combination is used and different when different combinations are used. -TEST(ThreadLocalBufferTest, TypeSlots) { - auto id1 = ThreadLocalBufferTest::GetSlotAddress<SendSlotA>(); - auto id2 = ThreadLocalBufferTest::GetSlotAddress<ReceiveSlotA>(); - auto id3 = ThreadLocalBufferTest::GetSlotAddress<SendSlotB>(); - auto id4 = ThreadLocalBufferTest::GetSlotAddress<ReceiveSlotB>(); - - EXPECT_NE(id1, id2); - EXPECT_NE(id3, id4); - EXPECT_NE(id1, id3); - EXPECT_NE(id2, id4); - - auto id1_alias = ThreadLocalBufferTest::GetSlotAddress<SendSlotA>(); - auto id2_alias = ThreadLocalBufferTest::GetSlotAddress<ReceiveSlotA>(); - auto id3_alias = ThreadLocalBufferTest::GetSlotAddress<SendSlotB>(); - auto id4_alias = ThreadLocalBufferTest::GetSlotAddress<ReceiveSlotB>(); - - EXPECT_EQ(id1, id1_alias); - EXPECT_EQ(id2, id2_alias); - EXPECT_EQ(id3, id3_alias); - EXPECT_EQ(id4, id4_alias); -} - -// Tests that different threads get different buffers for the same slot address. -TEST(ThreadLocalBufferTest, ThreadSlots) { - auto id1 = ThreadLocalBufferTest::GetSlotAddress<SendBuffer>(); - std::uintptr_t id2 = 0U; - - std::thread thread([&id2]() mutable { - id2 = ThreadLocalBufferTest::GetSlotAddress<SendBuffer>(); - }); - thread.join(); - - EXPECT_NE(0U, id1); - EXPECT_NE(0U, id2); - EXPECT_NE(id1, id2); -} - -// Tests that thread-local buffers are allocated at the first buffer request. -TEST(ThreadLocalBufferTest, InitialValue) { - struct TypeTagX; - using SendSlotX = ThreadLocalSlot<TypeTagX, kSendBufferIndex>; - - auto value1 = ThreadLocalBufferTest::GetSlotValue<SendSlotX>(); - MessageBuffer<SendSlotX>::GetBuffer(); - auto value2 = ThreadLocalBufferTest::GetSlotValue<SendSlotX>(); - - EXPECT_EQ(0U, value1); - EXPECT_NE(0U, value2); -} - -// Tests that the underlying buffers are the same for a given index/type pair -// and different across index/type combinations. -TEST(ThreadLocalBufferTest, BackingBuffer) { - auto& buffer1 = MessageBuffer<SendSlotA>::GetBuffer(); - auto& buffer2 = MessageBuffer<SendSlotA>::GetBuffer(); - auto& buffer3 = MessageBuffer<SendSlotB>::GetBuffer(); - auto& buffer4 = MessageBuffer<SendSlotB>::GetBuffer(); - - EXPECT_EQ(buffer1.data(), buffer2.data()); - EXPECT_EQ(buffer3.data(), buffer4.data()); - EXPECT_NE(buffer1.data(), buffer3.data()); - EXPECT_NE(buffer2.data(), buffer4.data()); -} diff --git a/libs/vr/libpdx/variant_tests.cpp b/libs/vr/libpdx/variant_tests.cpp deleted file mode 100644 index a977fd31cf..0000000000 --- a/libs/vr/libpdx/variant_tests.cpp +++ /dev/null @@ -1,1153 +0,0 @@ -#include <array> -#include <cstdint> -#include <functional> -#include <memory> -#include <string> -#include <type_traits> - -#include <gtest/gtest.h> -#include <pdx/rpc/variant.h> - -using namespace android::pdx; -using namespace android::pdx::rpc; - -namespace { - -struct BaseType { - // NOLINTNEXTLINE(google-explicit-constructor) - BaseType(int value) : value(value) {} - int value; -}; - -struct DerivedType : BaseType { - // NOLINTNEXTLINE(google-explicit-constructor) - DerivedType(int value) : BaseType{value} {}; -}; - -template <typename T> -class TestType { - public: - // NOLINTNEXTLINE(google-explicit-constructor) - TestType(const T& value) : value_(value) {} - // NOLINTNEXTLINE(google-explicit-constructor) - TestType(T&& value) : value_(std::move(value)) {} - TestType(const TestType&) = default; - TestType(TestType&&) = default; - - TestType& operator=(const TestType&) = default; - TestType& operator=(TestType&&) = default; - - const T& get() const { return value_; } - T&& take() { return std::move(value_); } - - private: - T value_; -}; - -template <typename T> -class InstrumentType { - public: - // NOLINTNEXTLINE(google-explicit-constructor) - InstrumentType(const T& value) : value_(value) { constructor_count_++; } - // NOLINTNEXTLINE(google-explicit-constructor) - InstrumentType(T&& value) : value_(std::move(value)) { constructor_count_++; } - InstrumentType(const InstrumentType& other) : value_(other.value_) { - constructor_count_++; - } - InstrumentType(InstrumentType&& other) : value_(std::move(other.value_)) { - constructor_count_++; - } - // NOLINTNEXTLINE(google-explicit-constructor) - InstrumentType(const TestType<T>& other) : value_(other.get()) { - constructor_count_++; - } - // NOLINTNEXTLINE(google-explicit-constructor) - InstrumentType(TestType<T>&& other) : value_(other.take()) { - constructor_count_++; - } - ~InstrumentType() { destructor_count_++; } - - InstrumentType& operator=(const InstrumentType& other) { - copy_assignment_count_++; - value_ = other.value_; - return *this; - } - InstrumentType& operator=(InstrumentType&& other) { - move_assignment_count_++; - value_ = std::move(other.value_); - return *this; - } - - InstrumentType& operator=(const TestType<T>& other) { - copy_assignment_count_++; - value_ = other.get(); - return *this; - } - InstrumentType& operator=(TestType<T>&& other) { - move_assignment_count_++; - value_ = other.take(); - return *this; - } - - static std::size_t constructor_count() { return constructor_count_; } - static std::size_t destructor_count() { return destructor_count_; } - static std::size_t move_assignment_count() { return move_assignment_count_; } - static std::size_t copy_assignment_count() { return copy_assignment_count_; } - - const T& get() const { return value_; } - T&& take() { return std::move(value_); } - - static void clear() { - constructor_count_ = 0; - destructor_count_ = 0; - move_assignment_count_ = 0; - copy_assignment_count_ = 0; - } - - private: - T value_; - - static std::size_t constructor_count_; - static std::size_t destructor_count_; - static std::size_t move_assignment_count_; - static std::size_t copy_assignment_count_; -}; - -template <typename T> -std::size_t InstrumentType<T>::constructor_count_ = 0; -template <typename T> -std::size_t InstrumentType<T>::destructor_count_ = 0; -template <typename T> -std::size_t InstrumentType<T>::move_assignment_count_ = 0; -template <typename T> -std::size_t InstrumentType<T>::copy_assignment_count_ = 0; - -} // anonymous namespace - -TEST(Variant, Assignment) { - // Assert basic type properties. - { - Variant<int, bool, float> v; - ASSERT_EQ(-1, v.index()); - ASSERT_FALSE(v.is<int>()); - ASSERT_FALSE(v.is<bool>()); - ASSERT_FALSE(v.is<float>()); - } - - { - Variant<int, bool, float> v; - v = 10; - ASSERT_EQ(0, v.index()); - ASSERT_TRUE(v.is<int>()); - ASSERT_FALSE(v.is<bool>()); - ASSERT_FALSE(v.is<float>()); - EXPECT_EQ(10, std::get<int>(v)); - } - - { - Variant<int, bool, float> v; - v = false; - ASSERT_EQ(1, v.index()); - ASSERT_FALSE(v.is<int>()); - ASSERT_TRUE(v.is<bool>()); - ASSERT_FALSE(v.is<float>()); - EXPECT_EQ(false, std::get<bool>(v)); - } - - { - Variant<int, bool, float> v; - v = 1.0f; - ASSERT_EQ(2, v.index()); - ASSERT_FALSE(v.is<int>()); - ASSERT_FALSE(v.is<bool>()); - ASSERT_TRUE(v.is<float>()); - EXPECT_FLOAT_EQ(1.0f, std::get<float>(v)); - } - - { - Variant<int, bool, float> v; - // ERROR: More than one type is implicitly convertible from double. - // v = 1.0; - v = static_cast<float>(1.0); - } - - { - Variant<int, bool, float> v; - - double x = 1.1; - v = static_cast<float>(x); - ASSERT_EQ(2, v.index()); - ASSERT_FALSE(v.is<int>()); - ASSERT_FALSE(v.is<bool>()); - ASSERT_TRUE(v.is<float>()); - EXPECT_FLOAT_EQ(1.1, std::get<float>(v)); - } - - { - Variant<int, std::string> v; - ASSERT_EQ(-1, v.index()); - ASSERT_FALSE(v.is<int>()); - ASSERT_FALSE(v.is<std::string>()); - } - - { - Variant<int, std::string> v; - v = 20; - ASSERT_EQ(0, v.index()); - ASSERT_TRUE(v.is<int>()); - ASSERT_FALSE(v.is<std::string>()); - EXPECT_EQ(20, std::get<int>(v)); - } - - { - Variant<int, std::string> v; - v = std::string("test"); - ASSERT_EQ(1, v.index()); - ASSERT_FALSE(v.is<int>()); - ASSERT_TRUE(v.is<std::string>()); - EXPECT_EQ("test", std::get<std::string>(v)); - } - - { - Variant<int, std::string> v; - v = "test"; - ASSERT_EQ(1, v.index()); - ASSERT_FALSE(v.is<int>()); - ASSERT_TRUE(v.is<std::string>()); - EXPECT_EQ("test", std::get<std::string>(v)); - } - - { - Variant<const char*> v1; - Variant<std::string> v2; - - v1 = "test"; - ASSERT_TRUE(v1.is<const char*>()); - v2 = v1; - ASSERT_TRUE(v2.is<std::string>()); - EXPECT_EQ("test", std::get<std::string>(v2)); - } - - { - Variant<int> a(1); - Variant<int> b; - ASSERT_TRUE(!a.empty()); - ASSERT_TRUE(b.empty()); - - a = b; - ASSERT_TRUE(a.empty()); - ASSERT_TRUE(b.empty()); - } - - { - Variant<int*, char*> v; - - // ERROR: More than one type is implicitly convertible from nullptr. - // v = nullptr; - - v = static_cast<int*>(nullptr); - EXPECT_TRUE(v.is<int*>()); - - v = static_cast<char*>(nullptr); - EXPECT_TRUE(v.is<char*>()); - } - - { - Variant<int*, char*> v; - int a = 10; - char b = 20; - - v = &b; - ASSERT_TRUE(v.is<char*>()); - EXPECT_EQ(&b, std::get<char*>(v)); - EXPECT_EQ(b, *std::get<char*>(v)); - - v = &a; - ASSERT_TRUE(v.is<int*>()); - EXPECT_EQ(&a, std::get<int*>(v)); - EXPECT_EQ(a, *std::get<int*>(v)); - } - - { - using IntRef = std::reference_wrapper<int>; - Variant<IntRef> v; - int a = 10; - - v = a; - ASSERT_TRUE(v.is<IntRef>()); - EXPECT_EQ(a, std::get<IntRef>(v)); - - a = 20; - EXPECT_EQ(a, std::get<IntRef>(v)); - } -} - -TEST(Variant, MoveAssignment) { - { - Variant<std::string> v; - std::string s = "test"; - v = std::move(s); - - EXPECT_TRUE(s.empty()); - ASSERT_TRUE(v.is<std::string>()); - EXPECT_EQ("test", std::get<std::string>(v)); - } - - { - Variant<std::string> v("test"); - std::string s = "fizz"; - s = std::move(std::get<std::string>(v)); - - ASSERT_TRUE(v.is<std::string>()); - EXPECT_TRUE(std::get<std::string>(v).empty()); - EXPECT_EQ("test", s); - } - - { - Variant<std::string> a("test"); - Variant<std::string> b; - - b = std::move(a); - ASSERT_TRUE(a.is<std::string>()); - ASSERT_TRUE(b.is<std::string>()); - EXPECT_TRUE(std::get<std::string>(a).empty()); - EXPECT_EQ("test", std::get<std::string>(b)); - } - - { - Variant<std::string> a("test"); - Variant<std::string> b("fizz"); - - b = std::move(a); - ASSERT_TRUE(a.is<std::string>()); - ASSERT_TRUE(b.is<std::string>()); - EXPECT_TRUE(std::get<std::string>(a).empty()); - EXPECT_EQ("test", std::get<std::string>(b)); - } - - { - Variant<int, std::string> a("test"); - Variant<int, std::string> b(10); - - b = std::move(a); - ASSERT_TRUE(a.is<std::string>()); - ASSERT_TRUE(b.is<std::string>()); - EXPECT_TRUE(std::get<std::string>(a).empty()); - EXPECT_EQ("test", std::get<std::string>(b)); - } - - { - Variant<int, std::string> a(10); - Variant<int, std::string> b("test"); - - b = std::move(a); - ASSERT_TRUE(a.is<int>()); - ASSERT_TRUE(b.is<int>()); - EXPECT_EQ(10, std::get<int>(a)); - EXPECT_EQ(10, std::get<int>(b)); - } -} - -TEST(Variant, Constructor) { - { - Variant<int, bool, float> v(true); - EXPECT_TRUE(v.is<bool>()); - } - - { - Variant<int, bool, float> v(10); - EXPECT_TRUE(v.is<int>()); - } - - { - Variant<int, bool, float> v(10.1f); - EXPECT_TRUE(v.is<float>()); - } - - { - Variant<float, std::string> v(10.); - EXPECT_TRUE(v.is<float>()); - } - - { - TestType<int> i(1); - Variant<int, bool, float> v(i.take()); - ASSERT_TRUE(v.is<int>()); - EXPECT_EQ(1, std::get<int>(v)); - } - - { - TestType<int> i(1); - Variant<int, bool, float> v(i.get()); - ASSERT_TRUE(v.is<int>()); - EXPECT_EQ(1, std::get<int>(v)); - } - - { - TestType<bool> b(true); - Variant<int, bool, float> v(b.take()); - ASSERT_TRUE(v.is<bool>()); - EXPECT_EQ(true, std::get<bool>(v)); - } - - { - TestType<bool> b(true); - Variant<int, bool, float> v(b.get()); - ASSERT_TRUE(v.is<bool>()); - EXPECT_EQ(true, std::get<bool>(v)); - } - - { - Variant<const char*> c("test"); - Variant<std::string> s(c); - ASSERT_TRUE(s.is<std::string>()); - EXPECT_EQ("test", std::get<std::string>(s)); - } - - { - Variant<int, bool, float> a(true); - Variant<int, bool, float> b(a); - - ASSERT_TRUE(b.is<bool>()); - } - - { - using IntRef = std::reference_wrapper<int>; - int a = 10; - Variant<IntRef> v(a); - TestType<IntRef> t(a); - - ASSERT_TRUE(v.is<IntRef>()); - EXPECT_EQ(a, std::get<IntRef>(v)); - EXPECT_EQ(a, t.get()); - - a = 20; - EXPECT_EQ(a, std::get<IntRef>(v)); - EXPECT_EQ(a, t.get()); - } -} - -// Verify correct ctor/dtor and assignment behavior used an instrumented type. -TEST(Variant, CopyMoveConstructAssign) { - { - InstrumentType<int>::clear(); - - // Default construct to empty, no InstrumentType activity. - Variant<int, InstrumentType<int>> v; - ASSERT_EQ(0u, InstrumentType<int>::constructor_count()); - ASSERT_EQ(0u, InstrumentType<int>::destructor_count()); - ASSERT_EQ(0u, InstrumentType<int>::move_assignment_count()); - ASSERT_EQ(0u, InstrumentType<int>::copy_assignment_count()); - } - - { - InstrumentType<int>::clear(); - - // Construct from int type, no InstrumentType activity. - Variant<int, InstrumentType<int>> v; - v = 10; - EXPECT_EQ(0u, InstrumentType<int>::constructor_count()); - EXPECT_EQ(0u, InstrumentType<int>::destructor_count()); - EXPECT_EQ(0u, InstrumentType<int>::move_assignment_count()); - EXPECT_EQ(0u, InstrumentType<int>::copy_assignment_count()); - } - - { - InstrumentType<int>::clear(); - - // Construct from int type, no InstrumentType activity. - Variant<int, InstrumentType<int>> v(10); - EXPECT_EQ(0u, InstrumentType<int>::constructor_count()); - EXPECT_EQ(0u, InstrumentType<int>::destructor_count()); - EXPECT_EQ(0u, InstrumentType<int>::move_assignment_count()); - EXPECT_EQ(0u, InstrumentType<int>::copy_assignment_count()); - } - - { - InstrumentType<int>::clear(); - - // Construct from temporary, temporary ctor/dtor. - Variant<int, InstrumentType<int>> v; - v = InstrumentType<int>(25); - EXPECT_EQ(2u, InstrumentType<int>::constructor_count()); - EXPECT_EQ(1u, InstrumentType<int>::destructor_count()); - EXPECT_EQ(0u, InstrumentType<int>::move_assignment_count()); - EXPECT_EQ(0u, InstrumentType<int>::copy_assignment_count()); - } - - { - InstrumentType<int>::clear(); - - // Construct from temporary, temporary ctor/dtor. - Variant<int, InstrumentType<int>> v(InstrumentType<int>(25)); - EXPECT_EQ(2u, InstrumentType<int>::constructor_count()); - EXPECT_EQ(1u, InstrumentType<int>::destructor_count()); - EXPECT_EQ(0u, InstrumentType<int>::move_assignment_count()); - EXPECT_EQ(0u, InstrumentType<int>::copy_assignment_count()); - } - - { - InstrumentType<int>::clear(); - - // Construct from temporary, temporary ctor/dtor. - Variant<int, InstrumentType<int>> v(InstrumentType<int>(25)); - - // Assign from temporary, temporary ctor/dtor. - v = InstrumentType<int>(35); - EXPECT_EQ(3u, InstrumentType<int>::constructor_count()); - EXPECT_EQ(2u, InstrumentType<int>::destructor_count()); - EXPECT_EQ(1u, InstrumentType<int>::move_assignment_count()); - EXPECT_EQ(0u, InstrumentType<int>::copy_assignment_count()); - } - - { - InstrumentType<int>::clear(); - - // Construct from temporary, temporary ctor/dtor. - Variant<int, InstrumentType<int>> v(InstrumentType<int>(25)); - - // dtor. - v = 10; - EXPECT_EQ(2u, InstrumentType<int>::constructor_count()); - EXPECT_EQ(2u, InstrumentType<int>::destructor_count()); - EXPECT_EQ(0u, InstrumentType<int>::move_assignment_count()); - EXPECT_EQ(0u, InstrumentType<int>::copy_assignment_count()); - } - - { - InstrumentType<int>::clear(); - - // Construct from temporary, temporary ctor/dtor. - Variant<int, InstrumentType<int>> v(InstrumentType<int>(25)); - - EXPECT_EQ(2u, InstrumentType<int>::constructor_count()); - EXPECT_EQ(1u, InstrumentType<int>::destructor_count()); - EXPECT_EQ(0u, InstrumentType<int>::move_assignment_count()); - EXPECT_EQ(0u, InstrumentType<int>::copy_assignment_count()); - } - EXPECT_EQ(2u, InstrumentType<int>::constructor_count()); - EXPECT_EQ(2u, InstrumentType<int>::destructor_count()); - EXPECT_EQ(0u, InstrumentType<int>::move_assignment_count()); - EXPECT_EQ(0u, InstrumentType<int>::copy_assignment_count()); - - { - InstrumentType<int>::clear(); - - // Construct from other temporary. - Variant<int, InstrumentType<int>> v(TestType<int>(10)); - EXPECT_EQ(1u, InstrumentType<int>::constructor_count()); - EXPECT_EQ(0u, InstrumentType<int>::destructor_count()); - EXPECT_EQ(0u, InstrumentType<int>::move_assignment_count()); - EXPECT_EQ(0u, InstrumentType<int>::copy_assignment_count()); - } - - { - InstrumentType<int>::clear(); - - // Construct from other temporary. - Variant<int, InstrumentType<int>> v(TestType<int>(10)); - // Assign from other temporary. - v = TestType<int>(11); - EXPECT_EQ(1u, InstrumentType<int>::constructor_count()); - EXPECT_EQ(0u, InstrumentType<int>::destructor_count()); - EXPECT_EQ(1u, InstrumentType<int>::move_assignment_count()); - EXPECT_EQ(0u, InstrumentType<int>::copy_assignment_count()); - } - - { - InstrumentType<int>::clear(); - - // Construct from other temporary. - Variant<int, InstrumentType<int>> v(TestType<int>(10)); - // Assign from empty Variant. - v = Variant<int, InstrumentType<int>>(); - EXPECT_EQ(1u, InstrumentType<int>::constructor_count()); - EXPECT_EQ(1u, InstrumentType<int>::destructor_count()); - EXPECT_EQ(0u, InstrumentType<int>::move_assignment_count()); - EXPECT_EQ(0u, InstrumentType<int>::copy_assignment_count()); - } - - { - InstrumentType<int>::clear(); - - TestType<int> other(10); - // Construct from other. - Variant<int, InstrumentType<int>> v(other); - - EXPECT_EQ(1u, InstrumentType<int>::constructor_count()); - EXPECT_EQ(0u, InstrumentType<int>::destructor_count()); - EXPECT_EQ(0u, InstrumentType<int>::move_assignment_count()); - EXPECT_EQ(0u, InstrumentType<int>::copy_assignment_count()); - } - - { - InstrumentType<int>::clear(); - - // Construct from other temporary. - Variant<int, InstrumentType<int>> v(TestType<int>(0)); - TestType<int> other(10); - // Assign from other. - v = other; - EXPECT_EQ(1u, InstrumentType<int>::constructor_count()); - EXPECT_EQ(0u, InstrumentType<int>::destructor_count()); - EXPECT_EQ(0u, InstrumentType<int>::move_assignment_count()); - EXPECT_EQ(1u, InstrumentType<int>::copy_assignment_count()); - } - - { - InstrumentType<int>::clear(); - - // Construct from temporary, temporary ctor/dtor. - Variant<int, InstrumentType<int>> v(InstrumentType<int>(25)); - - // Assign EmptyVariant. - v = EmptyVariant{}; - - EXPECT_EQ(2u, InstrumentType<int>::constructor_count()); - EXPECT_EQ(2u, InstrumentType<int>::destructor_count()); - EXPECT_EQ(0u, InstrumentType<int>::move_assignment_count()); - EXPECT_EQ(0u, InstrumentType<int>::copy_assignment_count()); - } - EXPECT_EQ(2u, InstrumentType<int>::constructor_count()); - EXPECT_EQ(2u, InstrumentType<int>::destructor_count()); - EXPECT_EQ(0u, InstrumentType<int>::move_assignment_count()); - EXPECT_EQ(0u, InstrumentType<int>::copy_assignment_count()); -} - -TEST(Variant, MoveConstructor) { - { - std::unique_ptr<int> pointer = std::make_unique<int>(10); - Variant<std::unique_ptr<int>> v(std::move(pointer)); - ASSERT_TRUE(v.is<std::unique_ptr<int>>()); - EXPECT_TRUE(std::get<std::unique_ptr<int>>(v) != nullptr); - EXPECT_TRUE(pointer == nullptr); - } - - { - Variant<std::unique_ptr<int>> a(std::make_unique<int>(10)); - Variant<std::unique_ptr<int>> b(std::move(a)); - - ASSERT_TRUE(a.is<std::unique_ptr<int>>()); - ASSERT_TRUE(b.is<std::unique_ptr<int>>()); - EXPECT_TRUE(std::get<std::unique_ptr<int>>(a) == nullptr); - EXPECT_TRUE(std::get<std::unique_ptr<int>>(b) != nullptr); - } -} - -TEST(Variant, IndexOf) { - Variant<int, bool, float> v1; - - EXPECT_EQ(0, v1.index_of<int>()); - EXPECT_EQ(1, v1.index_of<bool>()); - EXPECT_EQ(2, v1.index_of<float>()); - - Variant<int, bool, float, int> v2; - - EXPECT_EQ(0, v2.index_of<int>()); - EXPECT_EQ(1, v2.index_of<bool>()); - EXPECT_EQ(2, v2.index_of<float>()); -} - -struct Visitor { - int int_value = 0; - bool bool_value = false; - float float_value = 0.0; - bool empty_value = false; - - void Visit(int value) { int_value = value; } - void Visit(bool value) { bool_value = value; } - void Visit(float value) { float_value = value; } - void Visit(EmptyVariant) { empty_value = true; } -}; - -TEST(Variant, Visit) { - { - Variant<int, bool, float> v(10); - EXPECT_TRUE(v.is<int>()); - - Visitor visitor; - v.Visit([&visitor](const auto& value) { visitor.Visit(value); }); - EXPECT_EQ(10, visitor.int_value); - - visitor = {}; - v = true; - v.Visit([&visitor](const auto& value) { visitor.Visit(value); }); - EXPECT_EQ(true, visitor.bool_value); - } - - { - Variant<int, bool, float> v; - EXPECT_EQ(-1, v.index()); - - Visitor visitor; - v.Visit([&visitor](const auto& value) { visitor.Visit(value); }); - EXPECT_TRUE(visitor.empty_value); - } - - { - Variant<std::string> v("test"); - ASSERT_TRUE(v.is<std::string>()); - EXPECT_FALSE(std::get<std::string>(v).empty()); - - v.Visit([](auto&& value) { - std::remove_reference_t<decltype(value)> empty; - std::swap(empty, value); - }); - ASSERT_TRUE(v.is<std::string>()); - EXPECT_TRUE(std::get<std::string>(v).empty()); - } -} - -TEST(Variant, Become) { - { - Variant<int, bool, float> v; - - v.Become(0); - EXPECT_TRUE(v.is<int>()); - - v.Become(1); - EXPECT_TRUE(v.is<bool>()); - - v.Become(2); - EXPECT_TRUE(v.is<float>()); - - v.Become(3); - EXPECT_TRUE(v.empty()); - - v.Become(-1); - EXPECT_TRUE(v.empty()); - - v.Become(-2); - EXPECT_TRUE(v.empty()); - } - - { - Variant<int, bool, float> v; - - v.Become(0, 10); - ASSERT_TRUE(v.is<int>()); - EXPECT_EQ(10, std::get<int>(v)); - - v.Become(1, true); - ASSERT_TRUE(v.is<bool>()); - EXPECT_EQ(true, std::get<bool>(v)); - - v.Become(2, 2.0f); - ASSERT_TRUE(v.is<float>()); - EXPECT_FLOAT_EQ(2.0f, std::get<float>(v)); - - v.Become(3, 10); - EXPECT_TRUE(v.empty()); - - v.Become(-1, 10); - EXPECT_TRUE(v.empty()); - - v.Become(-2, 20); - EXPECT_TRUE(v.empty()); - } - - { - Variant<std::string> v; - - v.Become(0); - ASSERT_TRUE(v.is<std::string>()); - EXPECT_TRUE(std::get<std::string>(v).empty()); - } - - { - Variant<std::string> v; - - v.Become(0, "test"); - ASSERT_TRUE(v.is<std::string>()); - EXPECT_EQ("test", std::get<std::string>(v)); - } - - { - Variant<std::string> v("foo"); - - v.Become(0, "bar"); - ASSERT_TRUE(v.is<std::string>()); - EXPECT_EQ("foo", std::get<std::string>(v)); - } -} - -TEST(Variant, Swap) { - { - Variant<std::string> a; - Variant<std::string> b; - - std::swap(a, b); - EXPECT_TRUE(a.empty()); - EXPECT_TRUE(b.empty()); - } - - { - Variant<std::string> a("1"); - Variant<std::string> b; - - std::swap(a, b); - EXPECT_TRUE(a.empty()); - EXPECT_TRUE(!b.empty()); - ASSERT_TRUE(b.is<std::string>()); - EXPECT_EQ("1", std::get<std::string>(b)); - } - - { - Variant<std::string> a; - Variant<std::string> b("1"); - - std::swap(a, b); - EXPECT_TRUE(!a.empty()); - EXPECT_TRUE(b.empty()); - ASSERT_TRUE(a.is<std::string>()); - EXPECT_EQ("1", std::get<std::string>(a)); - } - - { - Variant<std::string> a("1"); - Variant<std::string> b("2"); - - std::swap(a, b); - ASSERT_TRUE(a.is<std::string>()); - ASSERT_TRUE(b.is<std::string>()); - EXPECT_EQ("2", std::get<std::string>(a)); - EXPECT_EQ("1", std::get<std::string>(b)); - } - - { - Variant<int, std::string> a(10); - Variant<int, std::string> b("1"); - - std::swap(a, b); - ASSERT_TRUE(a.is<std::string>()); - ASSERT_TRUE(b.is<int>()); - EXPECT_EQ("1", std::get<std::string>(a)); - EXPECT_EQ(10, std::get<int>(b)); - } - - { - Variant<int, std::string> a("1"); - Variant<int, std::string> b(10); - - std::swap(a, b); - ASSERT_TRUE(a.is<int>()); - ASSERT_TRUE(b.is<std::string>()); - EXPECT_EQ(10, std::get<int>(a)); - EXPECT_EQ("1", std::get<std::string>(b)); - } -} - -TEST(Variant, Get) { - { - Variant<int, bool, float, int> v; - - EXPECT_EQ(nullptr, &std::get<int>(v)); - EXPECT_EQ(nullptr, &std::get<bool>(v)); - EXPECT_EQ(nullptr, &std::get<float>(v)); - EXPECT_EQ(nullptr, &std::get<0>(v)); - EXPECT_EQ(nullptr, &std::get<1>(v)); - EXPECT_EQ(nullptr, &std::get<2>(v)); - EXPECT_EQ(nullptr, &std::get<3>(v)); - } - - { - Variant<int, bool, float, int> v; - v = 9; - ASSERT_TRUE(v.is<int>()) - << "Expected type " << v.index_of<int>() << " got type " << v.index(); - EXPECT_EQ(9, std::get<int>(v)); - EXPECT_EQ(9, std::get<0>(v)); - - std::get<int>(v) = 10; - EXPECT_EQ(10, std::get<int>(v)); - EXPECT_EQ(10, std::get<0>(v)); - - std::get<0>(v) = 11; - EXPECT_EQ(11, std::get<int>(v)); - EXPECT_EQ(11, std::get<0>(v)); - - std::get<3>(v) = 12; - EXPECT_EQ(12, std::get<int>(v)); - EXPECT_EQ(12, std::get<3>(v)); - } - - { - Variant<int, bool, float, int> v; - v = false; - ASSERT_TRUE(v.is<bool>()) - << "Expected type " << v.index_of<bool>() << " got type " << v.index(); - EXPECT_EQ(false, std::get<bool>(v)); - EXPECT_EQ(false, std::get<1>(v)); - - std::get<bool>(v) = true; - EXPECT_EQ(true, std::get<bool>(v)); - EXPECT_EQ(true, std::get<1>(v)); - - std::get<bool>(v) = false; - EXPECT_EQ(false, std::get<bool>(v)); - EXPECT_EQ(false, std::get<1>(v)); - - std::get<1>(v) = true; - EXPECT_EQ(true, std::get<bool>(v)); - EXPECT_EQ(true, std::get<1>(v)); - - std::get<1>(v) = false; - EXPECT_EQ(false, std::get<bool>(v)); - EXPECT_EQ(false, std::get<1>(v)); - } - - { - Variant<int, bool, float, int> v; - v = 1.0f; - ASSERT_TRUE(v.is<float>()) - << "Expected type " << v.index_of<float>() << " got type " << v.index(); - EXPECT_EQ(2, v.index()); - EXPECT_FLOAT_EQ(1.0, std::get<float>(v)); - EXPECT_FLOAT_EQ(1.0, std::get<2>(v)); - - std::get<float>(v) = 1.1; - EXPECT_FLOAT_EQ(1.1, std::get<float>(v)); - EXPECT_FLOAT_EQ(1.1, std::get<2>(v)); - - std::get<float>(v) = -3.0; - EXPECT_FLOAT_EQ(-3.0, std::get<float>(v)); - EXPECT_FLOAT_EQ(-3.0, std::get<2>(v)); - - std::get<2>(v) = 1.1; - EXPECT_FLOAT_EQ(1.1, std::get<float>(v)); - EXPECT_FLOAT_EQ(1.1, std::get<2>(v)); - - std::get<2>(v) = -3.0; - EXPECT_FLOAT_EQ(-3.0, std::get<float>(v)); - EXPECT_FLOAT_EQ(-3.0, std::get<2>(v)); - } - - { - Variant<std::unique_ptr<int>> v(std::make_unique<int>(10)); - std::unique_ptr<int> pointer = std::move(std::get<std::unique_ptr<int>>(v)); - ASSERT_FALSE(v.empty()); - EXPECT_TRUE(pointer != nullptr); - EXPECT_TRUE(std::get<std::unique_ptr<int>>(v) == nullptr); - } - - { - Variant<std::string> v("test"); - std::string s = std::get<std::string>(std::move(v)); - EXPECT_EQ("test", s); - } -} - -TEST(Variant, IfAnyOf) { - { - Variant<int, float> v(10); - ASSERT_TRUE(v.is<int>()); - - bool b = false; - EXPECT_TRUE(IfAnyOf<int>::Get(&v, &b)); - EXPECT_TRUE(b); - - float f = 0.0f; - EXPECT_TRUE((IfAnyOf<int, float>::Get(&v, &f))); - EXPECT_FLOAT_EQ(10.f, f); - } - - { - const Variant<int, float> v(10); - ASSERT_TRUE(v.is<int>()); - - bool b = false; - EXPECT_TRUE(IfAnyOf<int>::Get(&v, &b)); - EXPECT_TRUE(b); - - float f = 0.0f; - EXPECT_TRUE((IfAnyOf<int, float>::Get(&v, &f))); - EXPECT_FLOAT_EQ(10.f, f); - } - - { - Variant<int, float> v(10); - ASSERT_TRUE(v.is<int>()); - - bool b = false; - EXPECT_TRUE(IfAnyOf<int>::Call(&v, [&b](const auto& value) { b = value; })); - EXPECT_TRUE(b); - - float f = 0.0f; - EXPECT_TRUE(( - IfAnyOf<int, float>::Call(&v, [&f](const auto& value) { f = value; }))); - EXPECT_FLOAT_EQ(10.f, f); - } - - { - Variant<std::unique_ptr<int>, int> v(std::make_unique<int>(10)); - ASSERT_TRUE(v.is<std::unique_ptr<int>>()); - const int* original_v = std::get<std::unique_ptr<int>>(v).get(); - - std::unique_ptr<int> u(std::make_unique<int>(20)); - - EXPECT_TRUE(IfAnyOf<std::unique_ptr<int>>::Take(&v, &u)); - ASSERT_TRUE(v.is<std::unique_ptr<int>>()); - EXPECT_TRUE(std::get<std::unique_ptr<int>>(v) == nullptr); - EXPECT_EQ(u.get(), original_v); - } - - { - Variant<std::unique_ptr<DerivedType>, int> v( - std::make_unique<DerivedType>(10)); - ASSERT_TRUE(v.is<std::unique_ptr<DerivedType>>()); - const DerivedType* original_v = - std::get<std::unique_ptr<DerivedType>>(v).get(); - - std::unique_ptr<BaseType> u(std::make_unique<BaseType>(20)); - - EXPECT_TRUE(IfAnyOf<std::unique_ptr<DerivedType>>::Take(&v, &u)); - ASSERT_TRUE(v.is<std::unique_ptr<DerivedType>>()); - EXPECT_TRUE(std::get<std::unique_ptr<DerivedType>>(v) == nullptr); - EXPECT_EQ(u.get(), original_v); - } - - { - Variant<std::unique_ptr<int>, int> v(std::make_unique<int>(10)); - ASSERT_TRUE(v.is<std::unique_ptr<int>>()); - const int* original_v = std::get<std::unique_ptr<int>>(v).get(); - - std::unique_ptr<int> u(std::make_unique<int>(20)); - - EXPECT_TRUE(IfAnyOf<std::unique_ptr<int>>::Call( - &v, [&u](auto&& value) { u = std::move(value); })); - ASSERT_TRUE(v.is<std::unique_ptr<int>>()); - EXPECT_TRUE(std::get<std::unique_ptr<int>>(v) == nullptr); - EXPECT_EQ(u.get(), original_v); - } - - { - Variant<int, bool, float> v(true); - ASSERT_TRUE(v.is<bool>()); - - float f = 0.f; - EXPECT_FALSE((IfAnyOf<int, float>::Get(&v, &f))); - EXPECT_FLOAT_EQ(0.f, f); - } - - { - Variant<std::string, int> v("foo"); - ASSERT_TRUE(v.is<std::string>()); - - std::string s = "bar"; - EXPECT_TRUE(IfAnyOf<std::string>::Swap(&v, &s)); - ASSERT_TRUE(v.is<std::string>()); - EXPECT_EQ("bar", std::get<std::string>(v)); - EXPECT_EQ("foo", s); - } - - { - Variant<std::string, const char*> v(static_cast<const char*>("foo")); - ASSERT_TRUE(v.is<const char*>()); - - std::string s = "bar"; - EXPECT_TRUE((IfAnyOf<std::string, const char*>::Take(&v, &s))); - ASSERT_TRUE(v.is<const char*>()); - EXPECT_EQ("foo", std::get<const char*>(v)); - EXPECT_EQ("foo", s); - - v = std::string("bar"); - ASSERT_TRUE(v.is<std::string>()); - - EXPECT_TRUE((IfAnyOf<std::string, const char*>::Take(&v, &s))); - ASSERT_TRUE(v.is<std::string>()); - EXPECT_EQ("bar", s); - } - - { - Variant<std::string, const char*> v; - ASSERT_TRUE(v.empty()); - - std::string s = "bar"; - EXPECT_FALSE((IfAnyOf<std::string, const char*>::Take(&v, &s))); - EXPECT_EQ("bar", s); - } - - { - Variant<std::string, const char*> v(static_cast<const char*>("test")); - ASSERT_TRUE(v.is<const char*>()); - - std::string s; - EXPECT_FALSE(IfAnyOf<>::Take(&v, &s)); - EXPECT_TRUE(s.empty()); - } -} - -TEST(Variant, ConstVolatile) { - { - Variant<const int> v(10); - ASSERT_TRUE(v.is<const int>()); - EXPECT_EQ(10, std::get<const int>(v)); - } - - { - Variant<const std::string> v("test"); - ASSERT_TRUE(v.is<const std::string>()); - EXPECT_EQ("test", std::get<const std::string>(v)); - } - - { - Variant<volatile int, std::string> v(10); - ASSERT_TRUE(v.is<volatile int>()); - EXPECT_EQ(10, std::get<volatile int>(v)); - } -} - -TEST(Variant, HasType) { - EXPECT_TRUE((detail::HasType<int, int, float, bool>::value)); - EXPECT_FALSE((detail::HasType<char, int, float, bool>::value)); - EXPECT_FALSE(detail::HasType<>::value); - - EXPECT_TRUE((detail::HasType<int&, int, float, bool>::value)); - EXPECT_FALSE((detail::HasType<char&, int, float, bool>::value)); -} - -TEST(Variant, IsConstructible) { - using ArrayType = const float[3]; - struct ImplicitBool { - // NOLINTNEXTLINE(google-explicit-constructor) - operator bool() const { return true; } - }; - struct ExplicitBool { - explicit operator bool() const { return true; } - }; - struct NonBool {}; - struct TwoArgs { - TwoArgs(int, bool) {} - }; - - EXPECT_FALSE((detail::IsConstructible<bool, ArrayType>::value)); - EXPECT_TRUE((detail::IsConstructible<bool, int>::value)); - EXPECT_TRUE((detail::IsConstructible<bool, ImplicitBool>::value)); - EXPECT_TRUE((detail::IsConstructible<bool, ExplicitBool>::value)); - EXPECT_FALSE((detail::IsConstructible<bool, NonBool>::value)); - EXPECT_TRUE((detail::IsConstructible<TwoArgs, int, bool>::value)); - EXPECT_FALSE((detail::IsConstructible<TwoArgs, int, std::string>::value)); - EXPECT_FALSE((detail::IsConstructible<TwoArgs, int>::value)); -} - -TEST(Variant, Set) { - EXPECT_TRUE((detail::Set<int, bool, float>::template IsSubset<int, bool, - float>::value)); - EXPECT_TRUE( - (detail::Set<int, bool, float>::template IsSubset<bool, float>::value)); - EXPECT_TRUE((detail::Set<int, bool, float>::template IsSubset<float>::value)); - EXPECT_TRUE((detail::Set<int, bool, float>::template IsSubset<>::value)); - - EXPECT_FALSE( - (detail::Set<int, bool, float>::template IsSubset<int, bool, float, - char>::value)); - EXPECT_FALSE((detail::Set<int, bool, float>::template IsSubset<bool, float, - char>::value)); - EXPECT_FALSE( - (detail::Set<int, bool, float>::template IsSubset<float, char>::value)); - EXPECT_FALSE((detail::Set<int, bool, float>::template IsSubset<char>::value)); - - EXPECT_TRUE(detail::Set<>::template IsSubset<>::value); - EXPECT_FALSE(detail::Set<>::template IsSubset<int>::value); - EXPECT_FALSE((detail::Set<>::template IsSubset<int, float>::value)); -} diff --git a/libs/vr/libpdx_default_transport/Android.bp b/libs/vr/libpdx_default_transport/Android.bp deleted file mode 100644 index a5758b589f..0000000000 --- a/libs/vr/libpdx_default_transport/Android.bp +++ /dev/null @@ -1,88 +0,0 @@ -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "frameworks_native_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["frameworks_native_license"], -} - -cc_defaults { - name: "pdx_default_transport_compiler_defaults", - cflags: [ - "-Wall", - "-Wextra", - "-Werror", - ], -} - -cc_defaults { - name: "pdx_default_transport_lib_defaults", - export_include_dirs: ["private"], - whole_static_libs: ["libpdx"], -} - -cc_defaults { - name: "pdx_use_transport_servicefs", - export_include_dirs: ["private/servicefs"], - whole_static_libs: [ - "libpdx_servicefs", - "libservicefs", - ], -} - -cc_defaults { - name: "pdx_use_transport_uds", - export_include_dirs: ["private/uds"], - whole_static_libs: ["libpdx_uds"], -} - -cc_library_shared { - name: "libpdx_default_transport", - defaults: [ - "pdx_default_transport_compiler_defaults", - "pdx_default_transport_lib_defaults", - "pdx_use_transport_uds", - ], - shared_libs: [ - "libbase", - "libbinder", - "libcutils", - "liblog", - "libutils", - "libselinux", - ], -} - -cc_binary { - name: "pdx_tool", - system_ext_specific: true, - defaults: ["pdx_default_transport_compiler_defaults"], - srcs: [ - "pdx_tool.cpp", - ], - shared_libs: [ - "libbinder", - "libcutils", - "liblog", - "libpdx_default_transport", - ], -} - -// Benchmarks. -cc_binary { - name: "pdx_benchmarks", - defaults: ["pdx_default_transport_compiler_defaults"], - srcs: [ - "pdx_benchmarks.cpp", - ], - shared_libs: [ - "libbase", - "libbinder", - "libchrome", - "libcutils", - "liblog", - "libutils", - "libpdx_default_transport", - ], -} diff --git a/libs/vr/libpdx_default_transport/pdx_benchmarks.cpp b/libs/vr/libpdx_default_transport/pdx_benchmarks.cpp deleted file mode 100644 index 5c9e74c74a..0000000000 --- a/libs/vr/libpdx_default_transport/pdx_benchmarks.cpp +++ /dev/null @@ -1,1090 +0,0 @@ -// Use ALWAYS at the tag level. Control is performed manually during command -// line processing. -#define ATRACE_TAG ATRACE_TAG_ALWAYS -#include <utils/Trace.h> - -#include <base/files/file_util.h> -#include <base/logging.h> -#include <base/strings/string_split.h> -#include <errno.h> -#include <getopt.h> -#include <pdx/client.h> -#include <pdx/default_transport/client_channel_factory.h> -#include <pdx/default_transport/service_endpoint.h> -#include <pdx/rpc/buffer_wrapper.h> -#include <pdx/rpc/default_initialization_allocator.h> -#include <pdx/rpc/message_buffer.h> -#include <pdx/rpc/remote_method.h> -#include <pdx/rpc/serializable.h> -#include <pdx/service.h> -#include <sys/prctl.h> -#include <time.h> -#include <unistd.h> - -#include <atomic> -#include <cstdlib> -#include <functional> -#include <future> -#include <iomanip> -#include <ios> -#include <iostream> -#include <memory> -#include <numeric> -#include <sstream> -#include <string> -#include <thread> -#include <vector> - -using android::pdx::Channel; -using android::pdx::ClientBase; -using android::pdx::Endpoint; -using android::pdx::ErrorStatus; -using android::pdx::Message; -using android::pdx::Service; -using android::pdx::ServiceBase; -using android::pdx::default_transport::ClientChannelFactory; -using android::pdx::Status; -using android::pdx::Transaction; -using android::pdx::rpc::BufferWrapper; -using android::pdx::rpc::DefaultInitializationAllocator; -using android::pdx::rpc::MessageBuffer; -using android::pdx::rpc::DispatchRemoteMethod; -using android::pdx::rpc::RemoteMethodReturn; -using android::pdx::rpc::ReplyBuffer; -using android::pdx::rpc::Void; -using android::pdx::rpc::WrapBuffer; - -namespace { - -constexpr size_t kMaxMessageSize = 4096 * 1024; - -std::string GetServicePath(const std::string& path, int instance_id) { - return path + std::to_string(instance_id); -} - -void SetThreadName(const std::string& name) { - prctl(PR_SET_NAME, reinterpret_cast<unsigned long>(name.c_str()), 0, 0, 0); -} - -constexpr uint64_t kNanosPerSecond = 1000000000LLU; - -uint64_t GetClockNs() { - timespec t; - clock_gettime(CLOCK_MONOTONIC, &t); - return kNanosPerSecond * t.tv_sec + t.tv_nsec; -} - -template <typename T> -ssize_t ssizeof(const T&) { - return static_cast<ssize_t>(sizeof(T)); -} - -class SchedStats { - public: - SchedStats() : SchedStats(gettid()) {} - explicit SchedStats(pid_t task_id) : task_id_(task_id) {} - SchedStats(const SchedStats&) = default; - SchedStats& operator=(const SchedStats&) = default; - - void Update() { - const std::string stats_path = - "/proc/" + std::to_string(task_id_) + "/schedstat"; - - std::string line; - base::ReadFileToString(base::FilePath{stats_path}, &line); - std::vector<std::string> stats = base::SplitString( - line, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); - - CHECK_EQ(3u, stats.size()); - - // Calculate the deltas since the last update. Each value is absolute since - // the task started. - uint64_t current_cpu_time_ns = std::stoull(stats[0]); - uint64_t current_wait_ns = std::stoull(stats[1]); - uint64_t current_timeslices = std::stoull(stats[2]); - cpu_time_ns_ = current_cpu_time_ns - last_cpu_time_ns_; - wait_ns_ = current_wait_ns - last_wait_ns_; - timeslices_ = current_timeslices - last_timeslices_; - last_cpu_time_ns_ = current_cpu_time_ns; - last_wait_ns_ = current_wait_ns; - last_timeslices_ = current_timeslices; - } - - pid_t task_id() const { return task_id_; } - uint64_t cpu_time_ns() const { return cpu_time_ns_; } - uint64_t wait_ns() const { return wait_ns_; } - uint64_t timeslices() const { return timeslices_; } - - double cpu_time_s() const { - return static_cast<double>(cpu_time_ns_) / kNanosPerSecond; - } - double wait_s() const { - return static_cast<double>(wait_ns_) / kNanosPerSecond; - } - - private: - int32_t task_id_; - uint64_t cpu_time_ns_ = 0; - uint64_t last_cpu_time_ns_ = 0; - uint64_t wait_ns_ = 0; - uint64_t last_wait_ns_ = 0; - uint64_t timeslices_ = 0; - uint64_t last_timeslices_ = 0; - - PDX_SERIALIZABLE_MEMBERS(SchedStats, task_id_, cpu_time_ns_, wait_ns_, - timeslices_); -}; - -// Opcodes for client/service protocol. -struct BenchmarkOps { - enum : int { - Nop, - Read, - Write, - Echo, - Stats, - WriteVector, - EchoVector, - Quit, - }; -}; - -struct BenchmarkRPC { - PDX_REMOTE_METHOD(Stats, BenchmarkOps::Stats, - std::tuple<uint64_t, uint64_t, SchedStats>(Void)); - PDX_REMOTE_METHOD(WriteVector, BenchmarkOps::WriteVector, - int(const BufferWrapper<std::vector<uint8_t>> data)); - PDX_REMOTE_METHOD(EchoVector, BenchmarkOps::EchoVector, - BufferWrapper<std::vector<uint8_t>>( - const BufferWrapper<std::vector<uint8_t>> data)); -}; - -struct BenchmarkResult { - int thread_id = 0; - int service_id = 0; - double time_delta_s = 0.0; - uint64_t bytes_sent = 0; - SchedStats sched_stats = {}; -}; - -// Global command line option values. -struct Options { - bool verbose = false; - int threads = 1; - int opcode = BenchmarkOps::Read; - int blocksize = 1; - int count = 1; - int instances = 1; - int timeout = 1; - int warmup = 0; -} ProgramOptions; - -// Command line option names. -const char kOptionService[] = "service"; -const char kOptionClient[] = "client"; -const char kOptionVerbose[] = "verbose"; -const char kOptionOpcode[] = "op"; -const char kOptionBlocksize[] = "bs"; -const char kOptionCount[] = "count"; -const char kOptionThreads[] = "threads"; -const char kOptionInstances[] = "instances"; -const char kOptionTimeout[] = "timeout"; -const char kOptionTrace[] = "trace"; -const char kOptionWarmup[] = "warmup"; - -// getopt() long options. -static option long_options[] = { - {kOptionService, required_argument, 0, 0}, - {kOptionClient, required_argument, 0, 0}, - {kOptionVerbose, no_argument, 0, 0}, - {kOptionOpcode, required_argument, 0, 0}, - {kOptionBlocksize, required_argument, 0, 0}, - {kOptionCount, required_argument, 0, 0}, - {kOptionThreads, required_argument, 0, 0}, - {kOptionInstances, required_argument, 0, 0}, - {kOptionTimeout, required_argument, 0, 0}, - {kOptionTrace, no_argument, 0, 0}, - {kOptionWarmup, required_argument, 0, 0}, - {0, 0, 0, 0}, -}; - -// Parses the argument for kOptionOpcode and sets the value of -// ProgramOptions.opcode. -void ParseOpcodeOption(const std::string& argument) { - if (argument == "read") { - ProgramOptions.opcode = BenchmarkOps::Read; - } else if (argument == "write") { - ProgramOptions.opcode = BenchmarkOps::Write; - } else if (argument == "echo") { - ProgramOptions.opcode = BenchmarkOps::Echo; - } else if (argument == "writevec") { - ProgramOptions.opcode = BenchmarkOps::WriteVector; - } else if (argument == "echovec") { - ProgramOptions.opcode = BenchmarkOps::EchoVector; - } else if (argument == "quit") { - ProgramOptions.opcode = BenchmarkOps::Quit; - } else if (argument == "nop") { - ProgramOptions.opcode = BenchmarkOps::Nop; - } else if (argument == "stats") { - ProgramOptions.opcode = BenchmarkOps::Stats; - } else { - ProgramOptions.opcode = std::stoi(argument); - } -} - -// Implements the service side of the benchmark. -class BenchmarkService : public ServiceBase<BenchmarkService> { - public: - std::shared_ptr<Channel> OnChannelOpen(Message& message) override { - VLOG(1) << "BenchmarkService::OnChannelCreate: cid=" - << message.GetChannelId(); - return nullptr; - } - - void OnChannelClose(Message& message, - const std::shared_ptr<Channel>& /*channel*/) override { - VLOG(1) << "BenchmarkService::OnChannelClose: cid=" - << message.GetChannelId(); - } - - Status<void> HandleMessage(Message& message) override { - ATRACE_NAME("BenchmarkService::HandleMessage"); - - switch (message.GetOp()) { - case BenchmarkOps::Nop: - VLOG(1) << "BenchmarkService::HandleMessage: op=nop"; - { - ATRACE_NAME("Reply"); - CHECK(message.Reply(0)); - } - return {}; - - case BenchmarkOps::Write: { - VLOG(1) << "BenchmarkService::HandleMessage: op=write send_length=" - << message.GetSendLength() - << " receive_length=" << message.GetReceiveLength(); - - Status<void> status; - if (message.GetSendLength()) - status = message.ReadAll(send_buffer.data(), message.GetSendLength()); - - { - ATRACE_NAME("Reply"); - if (!status) - CHECK(message.ReplyError(status.error())); - else - CHECK(message.Reply(message.GetSendLength())); - } - return {}; - } - - case BenchmarkOps::Read: { - VLOG(1) << "BenchmarkService::HandleMessage: op=read send_length=" - << message.GetSendLength() - << " receive_length=" << message.GetReceiveLength(); - - Status<void> status; - if (message.GetReceiveLength()) { - status = message.WriteAll(receive_buffer.data(), - message.GetReceiveLength()); - } - - { - ATRACE_NAME("Reply"); - if (!status) - CHECK(message.ReplyError(status.error())); - else - CHECK(message.Reply(message.GetReceiveLength())); - } - return {}; - } - - case BenchmarkOps::Echo: { - VLOG(1) << "BenchmarkService::HandleMessage: op=echo send_length=" - << message.GetSendLength() - << " receive_length=" << message.GetReceiveLength(); - - Status<void> status; - if (message.GetSendLength()) - status = message.ReadAll(send_buffer.data(), message.GetSendLength()); - - if (!status) { - CHECK(message.ReplyError(status.error())); - return {}; - } - - if (message.GetSendLength()) { - status = - message.WriteAll(send_buffer.data(), message.GetSendLength()); - } - - { - ATRACE_NAME("Reply"); - if (!status) - CHECK(message.ReplyError(status.error())); - else - CHECK(message.Reply(message.GetSendLength())); - } - return {}; - } - - case BenchmarkOps::Stats: { - VLOG(1) << "BenchmarkService::HandleMessage: op=echo send_length=" - << message.GetSendLength() - << " receive_length=" << message.GetReceiveLength(); - - // Snapshot the stats when the message is received. - const uint64_t receive_time_ns = GetClockNs(); - sched_stats_.Update(); - - // Use the RPC system to return the results. - RemoteMethodReturn<BenchmarkRPC::Stats>( - message, BenchmarkRPC::Stats::Return{receive_time_ns, GetClockNs(), - sched_stats_}); - return {}; - } - - case BenchmarkOps::WriteVector: - VLOG(1) << "BenchmarkService::HandleMessage: op=writevec send_length=" - << message.GetSendLength() - << " receive_length=" << message.GetReceiveLength(); - - DispatchRemoteMethod<BenchmarkRPC::WriteVector>( - *this, &BenchmarkService::OnWriteVector, message, kMaxMessageSize); - return {}; - - case BenchmarkOps::EchoVector: - VLOG(1) << "BenchmarkService::HandleMessage: op=echovec send_length=" - << message.GetSendLength() - << " receive_length=" << message.GetReceiveLength(); - - DispatchRemoteMethod<BenchmarkRPC::EchoVector>( - *this, &BenchmarkService::OnEchoVector, message, kMaxMessageSize); - return {}; - - case BenchmarkOps::Quit: - Cancel(); - return ErrorStatus{ESHUTDOWN}; - - default: - VLOG(1) << "BenchmarkService::HandleMessage: default case; op=" - << message.GetOp(); - return Service::DefaultHandleMessage(message); - } - } - - // Updates the scheduler stats from procfs for this thread. - void UpdateSchedStats() { sched_stats_.Update(); } - - private: - friend BASE; - - explicit BenchmarkService(std::unique_ptr<Endpoint> endpoint) - : BASE("BenchmarkService", std::move(endpoint)), - send_buffer(kMaxMessageSize), - receive_buffer(kMaxMessageSize) {} - - std::vector<uint8_t> send_buffer; - std::vector<uint8_t> receive_buffer; - - // Each service thread has its own scheduler stats object. - static thread_local SchedStats sched_stats_; - - using BufferType = BufferWrapper< - std::vector<uint8_t, DefaultInitializationAllocator<uint8_t>>>; - - int OnWriteVector(Message&, const BufferType& data) { return data.size(); } - BufferType OnEchoVector(Message&, BufferType&& data) { - return std::move(data); - } - - BenchmarkService(const BenchmarkService&) = delete; - void operator=(const BenchmarkService&) = delete; -}; - -thread_local SchedStats BenchmarkService::sched_stats_; - -// Implements the client side of the benchmark. -class BenchmarkClient : public ClientBase<BenchmarkClient> { - public: - int Nop() { - ATRACE_NAME("BenchmarkClient::Nop"); - VLOG(1) << "BenchmarkClient::Nop"; - Transaction transaction{*this}; - return ReturnStatusOrError(transaction.Send<int>(BenchmarkOps::Nop)); - } - - int Write(const void* buffer, size_t length) { - ATRACE_NAME("BenchmarkClient::Write"); - VLOG(1) << "BenchmarkClient::Write: buffer=" << buffer - << " length=" << length; - Transaction transaction{*this}; - return ReturnStatusOrError( - transaction.Send<int>(BenchmarkOps::Write, buffer, length, nullptr, 0)); - // return write(endpoint_fd(), buffer, length); - } - - int Read(void* buffer, size_t length) { - ATRACE_NAME("BenchmarkClient::Read"); - VLOG(1) << "BenchmarkClient::Read: buffer=" << buffer - << " length=" << length; - Transaction transaction{*this}; - return ReturnStatusOrError( - transaction.Send<int>(BenchmarkOps::Read, nullptr, 0, buffer, length)); - // return read(endpoint_fd(), buffer, length); - } - - int Echo(const void* send_buffer, size_t send_length, void* receive_buffer, - size_t receive_length) { - ATRACE_NAME("BenchmarkClient::Echo"); - VLOG(1) << "BenchmarkClient::Echo: send_buffer=" << send_buffer - << " send_length=" << send_length - << " receive_buffer=" << receive_buffer - << " receive_length=" << receive_length; - Transaction transaction{*this}; - return ReturnStatusOrError( - transaction.Send<int>(BenchmarkOps::Echo, send_buffer, send_length, - receive_buffer, receive_length)); - } - - int Stats(std::tuple<uint64_t, uint64_t, SchedStats>* stats_out) { - ATRACE_NAME("BenchmarkClient::Stats"); - VLOG(1) << "BenchmarkClient::Stats"; - - auto status = InvokeRemoteMethodInPlace<BenchmarkRPC::Stats>(stats_out); - return status ? 0 : -status.error(); - } - - int WriteVector(const BufferWrapper<std::vector<uint8_t>>& data) { - ATRACE_NAME("BenchmarkClient::Stats"); - VLOG(1) << "BenchmarkClient::Stats"; - - auto status = InvokeRemoteMethod<BenchmarkRPC::WriteVector>(data); - return ReturnStatusOrError(status); - } - - template <typename T> - int WriteVector(const BufferWrapper<T>& data) { - ATRACE_NAME("BenchmarkClient::WriteVector"); - VLOG(1) << "BenchmarkClient::WriteVector"; - - auto status = InvokeRemoteMethod<BenchmarkRPC::WriteVector>(data); - return ReturnStatusOrError(status); - } - - template <typename T, typename U> - int EchoVector(const BufferWrapper<T>& data, BufferWrapper<U>* data_out) { - ATRACE_NAME("BenchmarkClient::EchoVector"); - VLOG(1) << "BenchmarkClient::EchoVector"; - - MessageBuffer<ReplyBuffer>::Reserve(kMaxMessageSize - 1); - auto status = - InvokeRemoteMethodInPlace<BenchmarkRPC::EchoVector>(data_out, data); - return status ? 0 : -status.error(); - } - - int Quit() { - VLOG(1) << "BenchmarkClient::Quit"; - Transaction transaction{*this}; - return ReturnStatusOrError(transaction.Send<int>(BenchmarkOps::Echo)); - } - - private: - friend BASE; - - explicit BenchmarkClient(const std::string& service_path) - : BASE(ClientChannelFactory::Create(service_path), - ProgramOptions.timeout) {} - - BenchmarkClient(const BenchmarkClient&) = delete; - void operator=(const BenchmarkClient&) = delete; -}; - -// Creates a benchmark service at |path| and dispatches messages. -int ServiceCommand(const std::string& path) { - if (path.empty()) - return -EINVAL; - - // Start the requested number of dispatch threads. - std::vector<std::thread> dispatch_threads; - int service_count = ProgramOptions.instances; - int service_id_counter = 0; - int thread_id_counter = 0; - std::atomic<bool> done(false); - - while (service_count--) { - std::cerr << "Starting service instance " << service_id_counter - << std::endl; - auto service = BenchmarkService::Create( - android::pdx::default_transport::Endpoint::CreateAndBindSocket( - GetServicePath(path, service_id_counter), - android::pdx::default_transport::Endpoint::kBlocking)); - if (!service) { - std::cerr << "Failed to create service instance!!" << std::endl; - done = true; - break; - } - - int thread_count = ProgramOptions.threads; - while (thread_count--) { - std::cerr << "Starting dispatch thread " << thread_id_counter - << " service " << service_id_counter << std::endl; - - dispatch_threads.emplace_back( - [&](const int thread_id, const int service_id, - const std::shared_ptr<BenchmarkService>& local_service) { - SetThreadName("service" + std::to_string(service_id)); - - // Read the initial schedstats for this thread from procfs. - local_service->UpdateSchedStats(); - - ATRACE_NAME("BenchmarkService::Dispatch"); - while (!done) { - auto ret = local_service->ReceiveAndDispatch(); - if (!ret) { - if (ret.error() != ESHUTDOWN) { - std::cerr << "Error while dispatching message on thread " - << thread_id << " service " << service_id << ": " - << ret.GetErrorMessage() << std::endl; - } else { - std::cerr << "Quitting thread " << thread_id << " service " - << service_id << std::endl; - } - done = true; - return; - } - } - }, - thread_id_counter++, service_id_counter, service); - } - - service_id_counter++; - } - - // Wait for the dispatch threads to exit. - for (auto& thread : dispatch_threads) { - thread.join(); - } - - return 0; -} - -int ClientCommand(const std::string& path) { - // Start the requested number of client threads. - std::vector<std::thread> client_threads; - std::vector<std::future<BenchmarkResult>> client_results; - int service_count = ProgramOptions.instances; - int thread_id_counter = 0; - int service_id_counter = 0; - - // Aggregate statistics, updated when worker threads exit. - std::atomic<uint64_t> total_bytes(0); - std::atomic<uint64_t> total_time_ns(0); - - // Samples for variance calculation. - std::vector<uint64_t> latency_samples_ns( - ProgramOptions.instances * ProgramOptions.threads * ProgramOptions.count); - const size_t samples_per_thread = ProgramOptions.count; - - std::vector<uint8_t> send_buffer(ProgramOptions.blocksize); - std::vector<uint8_t> receive_buffer(kMaxMessageSize); - - // Barriers for synchronizing thread start. - std::vector<std::future<void>> ready_barrier_futures; - std::promise<void> go_barrier_promise; - std::future<void> go_barrier_future = go_barrier_promise.get_future(); - - // Barrier for synchronizing thread tear down. - std::promise<void> done_barrier_promise; - std::future<void> done_barrier_future = done_barrier_promise.get_future(); - - while (service_count--) { - int thread_count = ProgramOptions.threads; - while (thread_count--) { - std::cerr << "Starting client thread " << thread_id_counter << " service " - << service_id_counter << std::endl; - - std::promise<BenchmarkResult> result_promise; - client_results.push_back(result_promise.get_future()); - - std::promise<void> ready_barrier_promise; - ready_barrier_futures.push_back(ready_barrier_promise.get_future()); - - client_threads.emplace_back( - [&](const int thread_id, const int service_id, - std::promise<BenchmarkResult> result, std::promise<void> ready) { - SetThreadName("client" + std::to_string(thread_id) + "/" + - std::to_string(service_id)); - - ATRACE_NAME("BenchmarkClient::Dispatch"); - - auto client = - BenchmarkClient::Create(GetServicePath(path, service_id)); - if (!client) { - std::cerr << "Failed to create client for service " << service_id - << std::endl; - return -ENOMEM; - } - - uint64_t* thread_samples = - &latency_samples_ns[samples_per_thread * thread_id]; - - // Per-thread statistics. - uint64_t bytes_sent = 0; - uint64_t time_start_ns; - uint64_t time_end_ns; - SchedStats sched_stats; - - // Signal ready and wait for go. - ready.set_value(); - go_barrier_future.wait(); - - // Warmup the scheduler. - int warmup = ProgramOptions.warmup; - while (warmup--) { - for (int i = 0; i < 1000000; i++) - ; - } - - sched_stats.Update(); - time_start_ns = GetClockNs(); - - int count = ProgramOptions.count; - while (count--) { - uint64_t iteration_start_ns = GetClockNs(); - - switch (ProgramOptions.opcode) { - case BenchmarkOps::Nop: { - const int ret = client->Nop(); - if (ret < 0) { - std::cerr << "Failed to send nop: " << strerror(-ret) - << std::endl; - return ret; - } else { - VLOG(1) << "Success"; - } - break; - } - - case BenchmarkOps::Read: { - const int ret = client->Read(receive_buffer.data(), - ProgramOptions.blocksize); - if (ret < 0) { - std::cerr << "Failed to read: " << strerror(-ret) - << std::endl; - return ret; - } else if (ret != ProgramOptions.blocksize) { - std::cerr << "Expected ret=" << ProgramOptions.blocksize - << "; actual ret=" << ret << std::endl; - return -EINVAL; - } else { - VLOG(1) << "Success"; - bytes_sent += ret; - } - break; - } - - case BenchmarkOps::Write: { - const int ret = - client->Write(send_buffer.data(), send_buffer.size()); - if (ret < 0) { - std::cerr << "Failed to write: " << strerror(-ret) - << std::endl; - return ret; - } else if (ret != ProgramOptions.blocksize) { - std::cerr << "Expected ret=" << ProgramOptions.blocksize - << "; actual ret=" << ret << std::endl; - return -EINVAL; - } else { - VLOG(1) << "Success"; - bytes_sent += ret; - } - break; - } - - case BenchmarkOps::Echo: { - const int ret = client->Echo( - send_buffer.data(), send_buffer.size(), - receive_buffer.data(), receive_buffer.size()); - if (ret < 0) { - std::cerr << "Failed to echo: " << strerror(-ret) - << std::endl; - return ret; - } else if (ret != ProgramOptions.blocksize) { - std::cerr << "Expected ret=" << ProgramOptions.blocksize - << "; actual ret=" << ret << std::endl; - return -EINVAL; - } else { - VLOG(1) << "Success"; - bytes_sent += ret * 2; - } - break; - } - - case BenchmarkOps::Stats: { - std::tuple<uint64_t, uint64_t, SchedStats> stats; - const int ret = client->Stats(&stats); - if (ret < 0) { - std::cerr << "Failed to get stats: " << strerror(-ret) - << std::endl; - return ret; - } else { - VLOG(1) << "Success"; - std::cerr - << "Round trip: receive_time_ns=" << std::get<0>(stats) - << " reply_time_ns=" << std::get<1>(stats) - << " cpu_time_s=" << std::get<2>(stats).cpu_time_s() - << " wait_s=" << std::get<2>(stats).wait_s() - << std::endl; - } - break; - } - - case BenchmarkOps::WriteVector: { - const int ret = client->WriteVector( - WrapBuffer(send_buffer.data(), ProgramOptions.blocksize)); - if (ret < 0) { - std::cerr << "Failed to write vector: " << strerror(-ret) - << std::endl; - return ret; - } else { - VLOG(1) << "Success"; - bytes_sent += ret; - } - break; - } - - case BenchmarkOps::EchoVector: { - thread_local BufferWrapper<std::vector< - uint8_t, DefaultInitializationAllocator<uint8_t>>> - response_buffer; - const int ret = client->EchoVector( - WrapBuffer(send_buffer.data(), ProgramOptions.blocksize), - &response_buffer); - if (ret < 0) { - std::cerr << "Failed to echo vector: " << strerror(-ret) - << std::endl; - return ret; - } else { - VLOG(1) << "Success"; - bytes_sent += send_buffer.size() + response_buffer.size(); - } - break; - } - - case BenchmarkOps::Quit: { - const int ret = client->Quit(); - if (ret < 0 && ret != -ESHUTDOWN) { - std::cerr << "Failed to send quit: " << strerror(-ret); - return ret; - } else { - VLOG(1) << "Success"; - } - break; - } - - default: - std::cerr - << "Invalid client operation: " << ProgramOptions.opcode - << std::endl; - return -EINVAL; - } - - uint64_t iteration_end_ns = GetClockNs(); - uint64_t iteration_delta_ns = - iteration_end_ns - iteration_start_ns; - thread_samples[count] = iteration_delta_ns; - - if (iteration_delta_ns > (kNanosPerSecond / 100)) { - SchedStats stats = sched_stats; - stats.Update(); - std::cerr << "Thread " << thread_id << " iteration_delta_s=" - << (static_cast<double>(iteration_delta_ns) / - kNanosPerSecond) - << " " << stats.cpu_time_s() << " " << stats.wait_s() - << std::endl; - } - } - - time_end_ns = GetClockNs(); - sched_stats.Update(); - - const double time_delta_s = - static_cast<double>(time_end_ns - time_start_ns) / - kNanosPerSecond; - - total_bytes += bytes_sent; - total_time_ns += time_end_ns - time_start_ns; - - result.set_value( - {thread_id, service_id, time_delta_s, bytes_sent, sched_stats}); - done_barrier_future.wait(); - - return 0; - }, - thread_id_counter++, service_id_counter, std::move(result_promise), - std::move(ready_barrier_promise)); - } - - service_id_counter++; - } - - // Wait for workers to be ready. - std::cerr << "Waiting for workers to be ready..." << std::endl; - for (auto& ready : ready_barrier_futures) - ready.wait(); - - // Signal workers to go. - std::cerr << "Kicking off benchmark." << std::endl; - go_barrier_promise.set_value(); - - // Wait for all the worker threas to finish. - for (auto& result : client_results) - result.wait(); - - // Report worker thread results. - for (auto& result : client_results) { - BenchmarkResult benchmark_result = result.get(); - std::cerr << std::fixed << "Thread " << benchmark_result.thread_id - << " service " << benchmark_result.service_id << ":" << std::endl; - std::cerr << "\t " << benchmark_result.bytes_sent << " bytes in " - << benchmark_result.time_delta_s << " seconds (" - << std::setprecision(0) << (benchmark_result.bytes_sent / 1024.0 / - benchmark_result.time_delta_s) - << " K/s; " << std::setprecision(3) - << (ProgramOptions.count / benchmark_result.time_delta_s) - << " txn/s; " << std::setprecision(9) - << (benchmark_result.time_delta_s / ProgramOptions.count) - << " s/txn)" << std::endl; - std::cerr << "\tStats: " << benchmark_result.sched_stats.cpu_time_s() << " " - << (benchmark_result.sched_stats.cpu_time_s() / - ProgramOptions.count) - << " " << benchmark_result.sched_stats.wait_s() << " " - << (benchmark_result.sched_stats.wait_s() / ProgramOptions.count) - << " " << benchmark_result.sched_stats.timeslices() << std::endl; - } - - // Signal worker threads to exit. - done_barrier_promise.set_value(); - - // Wait for the worker threads to exit. - for (auto& thread : client_threads) { - thread.join(); - } - - // Report aggregate results. - const int total_threads = ProgramOptions.threads * ProgramOptions.instances; - const int iterations = ProgramOptions.count; - const double total_time_s = - static_cast<double>(total_time_ns) / kNanosPerSecond; - // This is about how much wall time it took to completely transfer all the - // paylaods. - const double average_time_s = total_time_s / total_threads; - - const uint64_t min_sample_time_ns = - *std::min_element(latency_samples_ns.begin(), latency_samples_ns.end()); - const double min_sample_time_s = - static_cast<double>(min_sample_time_ns) / kNanosPerSecond; - - const uint64_t max_sample_time_ns = - *std::max_element(latency_samples_ns.begin(), latency_samples_ns.end()); - const double max_sample_time_s = - static_cast<double>(max_sample_time_ns) / kNanosPerSecond; - - const double total_sample_time_s = - std::accumulate(latency_samples_ns.begin(), latency_samples_ns.end(), 0.0, - [](double s, uint64_t ns) { - return s + static_cast<double>(ns) / kNanosPerSecond; - }); - const double average_sample_time_s = - total_sample_time_s / latency_samples_ns.size(); - - const double sum_of_squared_deviations = std::accumulate( - latency_samples_ns.begin(), latency_samples_ns.end(), 0.0, - [&](double s, uint64_t ns) { - const double delta = - static_cast<double>(ns) / kNanosPerSecond - average_sample_time_s; - return s + delta * delta; - }); - const double variance = sum_of_squared_deviations / latency_samples_ns.size(); - const double standard_deviation = std::sqrt(variance); - - const int num_buckets = 200; - const uint64_t sample_range_ns = max_sample_time_ns - min_sample_time_ns; - const uint64_t ns_per_bucket = sample_range_ns / num_buckets; - std::array<uint64_t, num_buckets> sample_buckets = {{0}}; - - // Count samples in each bucket range. - for (uint64_t sample_ns : latency_samples_ns) { - sample_buckets[(sample_ns - min_sample_time_ns) / (ns_per_bucket + 1)] += 1; - } - - // Calculate population percentiles. - const uint64_t percent_50 = - static_cast<uint64_t>(latency_samples_ns.size() * 0.5); - const uint64_t percent_90 = - static_cast<uint64_t>(latency_samples_ns.size() * 0.9); - const uint64_t percent_95 = - static_cast<uint64_t>(latency_samples_ns.size() * 0.95); - const uint64_t percent_99 = - static_cast<uint64_t>(latency_samples_ns.size() * 0.99); - - uint64_t sample_count = 0; - double latency_50th_percentile_s, latency_90th_percentile_s, - latency_95th_percentile_s, latency_99th_percentile_s; - for (int i = 0; i < num_buckets; i++) { - // Report the midpoint of the bucket range as the value of the - // corresponding - // percentile. - const double bucket_midpoint_time_s = - (ns_per_bucket * i + 0.5 * ns_per_bucket + min_sample_time_ns) / - kNanosPerSecond; - if (sample_count < percent_50 && - (sample_count + sample_buckets[i]) >= percent_50) { - latency_50th_percentile_s = bucket_midpoint_time_s; - } - if (sample_count < percent_90 && - (sample_count + sample_buckets[i]) >= percent_90) { - latency_90th_percentile_s = bucket_midpoint_time_s; - } - if (sample_count < percent_95 && - (sample_count + sample_buckets[i]) >= percent_95) { - latency_95th_percentile_s = bucket_midpoint_time_s; - } - if (sample_count < percent_99 && - (sample_count + sample_buckets[i]) >= percent_99) { - latency_99th_percentile_s = bucket_midpoint_time_s; - } - sample_count += sample_buckets[i]; - } - - std::cerr << std::fixed << "Total throughput over " << total_threads - << " threads:\n\t " << total_bytes << " bytes in " << average_time_s - << " seconds (" << std::setprecision(0) - << (total_bytes / 1024.0 / average_time_s) << " K/s; " - << std::setprecision(3) - << (iterations * total_threads / average_time_s) - << std::setprecision(9) << " txn/s; " - << (average_time_s / (iterations * total_threads)) << " s/txn)" - << std::endl; - std::cerr << "Sample statistics: " << std::endl; - std::cerr << total_sample_time_s << " s total sample time" << std::endl; - std::cerr << average_sample_time_s << " s avg" << std::endl; - std::cerr << standard_deviation << " s std dev" << std::endl; - std::cerr << min_sample_time_s << " s min" << std::endl; - std::cerr << max_sample_time_s << " s max" << std::endl; - std::cerr << "Latency percentiles:" << std::endl; - std::cerr << "50th: " << latency_50th_percentile_s << " s" << std::endl; - std::cerr << "90th: " << latency_90th_percentile_s << " s" << std::endl; - std::cerr << "95th: " << latency_95th_percentile_s << " s" << std::endl; - std::cerr << "99th: " << latency_99th_percentile_s << " s" << std::endl; - - std::cout << total_time_ns << " " << std::fixed << std::setprecision(9) - << average_sample_time_s << " " << std::fixed - << std::setprecision(9) << standard_deviation << std::endl; - return 0; -} - -int Usage(const std::string& command_name) { - // clang-format off - std::cout << "Usage: " << command_name << " [options]" << std::endl; - std::cout << "\t--verbose : Use verbose messages." << std::endl; - std::cout << "\t--service <endpoint path> : Start service at the given path." << std::endl; - std::cout << "\t--client <endpoint path> : Start client to the given path." << std::endl; - std::cout << "\t--op <read | write | echo> : Sepcify client operation mode." << std::endl; - std::cout << "\t--bs <block size bytes> : Sepcify block size to use." << std::endl; - std::cout << "\t--count <count> : Sepcify number of transactions to make." << std::endl; - std::cout << "\t--instances <count> : Specify number of service instances." << std::endl; - std::cout << "\t--threads <count> : Sepcify number of threads per instance." << std::endl; - std::cout << "\t--timeout <timeout ms | -1> : Timeout to wait for services." << std::endl; - std::cout << "\t--trace : Enable systrace logging." << std::endl; - std::cout << "\t--warmup <iterations> : Busy loops before running benchmarks." << std::endl; - // clang-format on - return -1; -} - -} // anonymous namespace - -int main(int argc, char** argv) { - logging::LoggingSettings logging_settings; - logging_settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG; - logging::InitLogging(logging_settings); - - int getopt_code; - int option_index; - std::string option = ""; - std::string command = ""; - std::string command_argument = ""; - bool tracing_enabled = false; - - // Process command line options. - while ((getopt_code = - getopt_long(argc, argv, "", long_options, &option_index)) != -1) { - option = long_options[option_index].name; - VLOG(1) << "option=" << option; - switch (getopt_code) { - case 0: - if (option == kOptionVerbose) { - ProgramOptions.verbose = true; - logging::SetMinLogLevel(-1); - } else if (option == kOptionOpcode) { - ParseOpcodeOption(optarg); - } else if (option == kOptionBlocksize) { - ProgramOptions.blocksize = std::stoi(optarg); - if (ProgramOptions.blocksize < 0) { - std::cerr << "Invalid blocksize argument: " - << ProgramOptions.blocksize << std::endl; - return -EINVAL; - } - } else if (option == kOptionCount) { - ProgramOptions.count = std::stoi(optarg); - if (ProgramOptions.count < 1) { - std::cerr << "Invalid count argument: " << ProgramOptions.count - << std::endl; - return -EINVAL; - } - } else if (option == kOptionThreads) { - ProgramOptions.threads = std::stoi(optarg); - if (ProgramOptions.threads < 1) { - std::cerr << "Invalid threads argument: " << ProgramOptions.threads - << std::endl; - return -EINVAL; - } - } else if (option == kOptionInstances) { - ProgramOptions.instances = std::stoi(optarg); - if (ProgramOptions.instances < 1) { - std::cerr << "Invalid instances argument: " - << ProgramOptions.instances << std::endl; - return -EINVAL; - } - } else if (option == kOptionTimeout) { - ProgramOptions.timeout = std::stoi(optarg); - } else if (option == kOptionTrace) { - tracing_enabled = true; - } else if (option == kOptionWarmup) { - ProgramOptions.warmup = std::stoi(optarg); - } else { - command = option; - if (optarg) - command_argument = optarg; - } - break; - } - } - - // Setup ATRACE/systrace based on command line. - atrace_setup(); - atrace_set_tracing_enabled(tracing_enabled); - - VLOG(1) << "command=" << command << " command_argument=" << command_argument; - - if (command == "") { - return Usage(argv[0]); - } else if (command == kOptionService) { - return ServiceCommand(command_argument); - } else if (command == kOptionClient) { - return ClientCommand(command_argument); - } else { - return Usage(argv[0]); - } -} diff --git a/libs/vr/libpdx_default_transport/pdx_tool.cpp b/libs/vr/libpdx_default_transport/pdx_tool.cpp deleted file mode 100644 index 60eedb3847..0000000000 --- a/libs/vr/libpdx_default_transport/pdx_tool.cpp +++ /dev/null @@ -1,244 +0,0 @@ -#include <errno.h> -#include <ftw.h> -#include <getopt.h> -#include <pdx/client.h> -#include <pdx/service.h> -#include <sys/stat.h> - -#include <algorithm> -#include <vector> - -#include <pdx/default_transport/client_channel_factory.h> - -using android::pdx::default_transport::ClientChannelFactory; - -namespace { - -constexpr long kClientTimeoutMs = 0; // Don't wait for non-existent services. -constexpr int kDumpBufferSize = 2 * 4096; // Two pages. - -class ControlClient : public android::pdx::ClientBase<ControlClient> { - public: - explicit ControlClient(const std::string& service_path, long timeout_ms); - - void Reload(); - std::string Dump(); - - private: - friend BASE; - - ControlClient(const ControlClient&) = delete; - void operator=(const ControlClient&) = delete; -}; - -bool option_verbose = false; - -static struct option long_options[] = { - {"reload", required_argument, 0, 0}, - {"dump", required_argument, 0, 0}, - {"verbose", no_argument, 0, 0}, - {0, 0, 0, 0}, -}; - -#define printf_verbose(fmt, ... /*args*/) \ - do { \ - if (option_verbose) \ - printf(fmt, ##__VA_ARGS__); \ - } while (0) - -void HexDump(const void* pointer, size_t length); - -ControlClient::ControlClient(const std::string& service_path, long timeout_ms) - : BASE{ClientChannelFactory::Create(service_path), timeout_ms} {} - -void ControlClient::Reload() { - android::pdx::Transaction trans{*this}; - auto status = trans.Send<void>(android::pdx::opcodes::REPORT_SYSPROP_CHANGE, - nullptr, 0, nullptr, 0); - if (!status) { - fprintf(stderr, "Failed to send reload: %s\n", - status.GetErrorMessage().c_str()); - } -} - -std::string ControlClient::Dump() { - android::pdx::Transaction trans{*this}; - std::vector<char> buffer(kDumpBufferSize); - auto status = trans.Send<int>(android::pdx::opcodes::DUMP_STATE, nullptr, 0, - buffer.data(), buffer.size()); - - printf_verbose("ControlClient::Dump: ret=%d\n", ReturnStatusOrError(status)); - - if (!status) { - fprintf(stderr, "Failed to send dump request: %s\n", - status.GetErrorMessage().c_str()); - return ""; - } else if (status.get() > static_cast<ssize_t>(buffer.capacity())) { - fprintf(stderr, "Service returned a larger size than requested: %d\n", - status.get()); - return ""; - } - - if (option_verbose) - HexDump(buffer.data(), status.get()); - - return std::string(buffer.data(), status.get()); -} - -int Usage(const std::string& command_name) { - printf("Usage: %s [options]\n", command_name.c_str()); - printf("\t--verbose : Use verbose messages.\n"); - printf( - "\t--reload <all | service path> : Ask service(s) to reload system " - "properties.\n"); - printf("\t--dump <all | service path> : Dump service(s) state.\n"); - return -1; -} - -typedef int (*CallbackType)(const char* path, const struct stat* sb, - int type_flag, FTW* ftw_buffer); - -int ReloadCommandCallback(const char* path, const struct stat* sb, - int type_flag, FTW* ftw_buffer); -int DumpCommandCallback(const char* path, const struct stat* sb, int type_flag, - FTW* ftw_buffer); - -void CallOnAllFiles(CallbackType callback, const std::string& base_path) { - const int kMaxDepth = 32; - nftw(base_path.c_str(), callback, kMaxDepth, FTW_PHYS); -} - -int ReloadCommand(const std::string& service_path) { - printf_verbose("ReloadCommand: service_path=%s\n", service_path.c_str()); - - if (service_path == "" || service_path == "all") { - CallOnAllFiles(ReloadCommandCallback, - ClientChannelFactory::GetRootEndpointPath()); - return 0; - } else { - auto client = ControlClient::Create(service_path, kClientTimeoutMs); - if (!client) { - fprintf(stderr, "Failed to open service at \"%s\".\n", - service_path.c_str()); - return -1; - } - - client->Reload(); - return 0; - } -} - -int DumpCommand(const std::string& service_path) { - printf_verbose("DumpCommand: service_path=%s\n", service_path.c_str()); - - if (service_path == "" || service_path == "all") { - CallOnAllFiles(DumpCommandCallback, - ClientChannelFactory::GetRootEndpointPath()); - return 0; - } else { - auto client = ControlClient::Create(service_path, kClientTimeoutMs); - if (!client) { - fprintf(stderr, "Failed to open service at \"%s\".\n", - service_path.c_str()); - return -1; - } - - std::string response = client->Dump(); - if (!response.empty()) { - printf( - "--------------------------------------------------------------------" - "---\n"); - printf("%s:\n", service_path.c_str()); - printf("%s\n", response.c_str()); - } - return 0; - } -} - -int ReloadCommandCallback(const char* path, const struct stat*, int type_flag, - FTW*) { - if (type_flag == FTW_F) - ReloadCommand(path); - return 0; -} - -int DumpCommandCallback(const char* path, const struct stat*, int type_flag, - FTW*) { - if (type_flag == FTW_F) - DumpCommand(path); - return 0; -} - -void HexDump(const void* pointer, size_t length) { - uintptr_t address = reinterpret_cast<uintptr_t>(pointer); - - for (size_t count = 0; count < length; count += 16, address += 16) { - printf("0x%08lx: ", static_cast<unsigned long>(address)); - - for (size_t i = 0; i < 16u; i++) { - if (i < std::min(length - count, static_cast<size_t>(16))) { - printf("%02x ", *reinterpret_cast<const uint8_t*>(address + i)); - } else { - printf(" "); - } - } - - printf("|"); - - for (size_t i = 0; i < 16u; i++) { - if (i < std::min(length - count, static_cast<size_t>(16))) { - char c = *reinterpret_cast<const char*>(address + i); - if (isalnum(c) || c == ' ') { - printf("%c", c); - } else { - printf("."); - } - } else { - printf(" "); - } - } - - printf("|\n"); - } -} - -} // anonymous namespace - -int main(int argc, char** argv) { - int getopt_code; - int option_index; - std::string option = ""; - std::string command = ""; - std::string command_argument = ""; - - // Process command line options. - while ((getopt_code = - getopt_long(argc, argv, "", long_options, &option_index)) != -1) { - option = long_options[option_index].name; - printf_verbose("option=%s\n", option.c_str()); - switch (getopt_code) { - case 0: - if (option == "verbose") { - option_verbose = true; - } else { - command = option; - if (optarg) - command_argument = optarg; - } - break; - } - } - - printf_verbose("command=%s command_argument=%s\n", command.c_str(), - command_argument.c_str()); - - if (command == "") { - return Usage(argv[0]); - } else if (command == "reload") { - return ReloadCommand(command_argument); - } else if (command == "dump") { - return DumpCommand(command_argument); - } else { - return Usage(argv[0]); - } -} diff --git a/libs/vr/libpdx_default_transport/private/pdx/default_transport/service_utility.h b/libs/vr/libpdx_default_transport/private/pdx/default_transport/service_utility.h deleted file mode 100644 index 3ebab86138..0000000000 --- a/libs/vr/libpdx_default_transport/private/pdx/default_transport/service_utility.h +++ /dev/null @@ -1,92 +0,0 @@ -#ifndef ANDROID_PDX_DEFAULT_TRANSPORT_SERVICE_UTILITY_H_ -#define ANDROID_PDX_DEFAULT_TRANSPORT_SERVICE_UTILITY_H_ - -#include <ftw.h> - -#include <pdx/client.h> -#include <pdx/default_transport/client_channel_factory.h> -#include <pdx/service.h> -#include <pdx/status.h> - -namespace android { -namespace pdx { -namespace default_transport { - -class ServiceUtility : public ClientBase<ServiceUtility> { - public: - Status<int> ReloadSystemProperties() { - Transaction transaction{*this}; - return ReturnStatusOrError( - transaction.Send<int>(opcodes::REPORT_SYSPROP_CHANGE)); - } - - static std::string GetRootEndpointPath() { - return ClientChannelFactory::GetRootEndpointPath(); - } - static std::string GetEndpointPath(const std::string& endpoint_path) { - return ClientChannelFactory::GetEndpointPath(endpoint_path); - } - - // Traverses the PDX service path space and sends a message to reload system - // properties to each service endpoint it finds along the way. - // NOTE: This method is used by atrace to poke PDX services. Please avoid - // unnecessary changes to this mechanism to minimize impact on atrace. - static bool PokeServices() { - const int kMaxDepth = 16; - const int result = - nftw(GetRootEndpointPath().c_str(), PokeService, kMaxDepth, FTW_PHYS); - return result == 0 ? true : false; - } - - private: - friend BASE; - - explicit ServiceUtility(const std::string& endpoint_path, - int* error = nullptr) - : BASE(ClientChannelFactory::Create(endpoint_path), 0) { - if (error) - *error = Client::error(); - } - - // Sends the sysprop_change message to the service at fpath, so it re-reads - // its system properties. Returns 0 on success or a negated errno code on - // failure. - // NOTE: This method is used by atrace to poke PDX services. Please avoid - // unnecessary changes to this mechanism to minimize impact on atrace. - static int PokeService(const char* fpath, const struct stat* /*sb*/, - int typeflag, struct FTW* /*ftwbuf*/) { - const bool kIgnoreErrors = true; - - if (typeflag == FTW_F) { - int error; - auto utility = ServiceUtility::Create(fpath, &error); - if (!utility) { - if (error != -ECONNREFUSED) { - ALOGE("ServiceUtility::PokeService: Failed to open %s: %s.", fpath, - strerror(-error)); - } - return kIgnoreErrors ? 0 : error; - } - - auto status = utility->ReloadSystemProperties(); - if (!status) { - ALOGE( - "ServiceUtility::PokeService: Failed to send sysprop change to %s: " - "%s", - fpath, status.GetErrorMessage().c_str()); - return kIgnoreErrors ? 0 : -status.error(); - } - } - - return 0; - } - - ServiceUtility(const ServiceUtility&) = delete; - void operator=(const ServiceUtility&) = delete; -}; - -} // namespace default_transport -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_DEFAULT_TRANSPORT_SERVICE_UTILITY_H_ diff --git a/libs/vr/libpdx_default_transport/private/servicefs/pdx/default_transport/channel_manager.h b/libs/vr/libpdx_default_transport/private/servicefs/pdx/default_transport/channel_manager.h deleted file mode 100644 index 11163b3c48..0000000000 --- a/libs/vr/libpdx_default_transport/private/servicefs/pdx/default_transport/channel_manager.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef ANDROID_PDX_DEFAULT_TRANSPORT_SERVICEFS_CHANNEL_MANAGER_H_ -#define ANDROID_PDX_DEFAULT_TRANSPORT_SERVICEFS_CHANNEL_MANAGER_H_ - -#include <servicefs/channel_manager.h> - -namespace android { -namespace pdx { -namespace default_transport { - -using ChannelManager = ::android::pdx::servicefs::ChannelManager; - -} // namespace default_transport -} // namespace pdx -} // namespace android - - -#endif // ANDROID_PDX_DEFAULT_TRANSPORT_SERVICEFS_CHANNEL_MANAGER_H_ diff --git a/libs/vr/libpdx_default_transport/private/servicefs/pdx/default_transport/channel_parcelable.h b/libs/vr/libpdx_default_transport/private/servicefs/pdx/default_transport/channel_parcelable.h deleted file mode 100644 index a8623b25f7..0000000000 --- a/libs/vr/libpdx_default_transport/private/servicefs/pdx/default_transport/channel_parcelable.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef ANDROID_PDX_DEFAULT_TRANSPORT_SERVICEFS_CHANNEL_PARCELABLE_H_ -#define ANDROID_PDX_DEFAULT_TRANSPORT_SERVICEFS_CHANNEL_PARCELABLE_H_ - -#include <servicefs/channel_parcelable.h> - -namespace android { -namespace pdx { -namespace default_transport { - -using ChannelParcelable = ::android::pdx::servicefs::ChannelParcelable; - -} // namespace default_transport -} // namespace pdx -} // namespace android - - -#endif // ANDROID_PDX_DEFAULT_TRANSPORT_SERVICEFS_CHANNEL_PARCELABLE_H_ diff --git a/libs/vr/libpdx_default_transport/private/servicefs/pdx/default_transport/client_channel.h b/libs/vr/libpdx_default_transport/private/servicefs/pdx/default_transport/client_channel.h deleted file mode 100644 index d1717801bc..0000000000 --- a/libs/vr/libpdx_default_transport/private/servicefs/pdx/default_transport/client_channel.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef ANDROID_PDX_DEFAULT_TRANSPORT_SERVICEFS_CLIENT_CHANNEL_H_ -#define ANDROID_PDX_DEFAULT_TRANSPORT_SERVICEFS_CLIENT_CHANNEL_H_ - -#include <servicefs/client_channel.h> - -namespace android { -namespace pdx { -namespace default_transport { - -using ClientChannel = ::android::pdx::servicefs::ClientChannel; - -} // namespace default_transport -} // namespace pdx -} // namespace android - - -#endif // ANDROID_PDX_DEFAULT_TRANSPORT_SERVICEFS_CLIENT_CHANNEL_H_ diff --git a/libs/vr/libpdx_default_transport/private/servicefs/pdx/default_transport/client_channel_factory.h b/libs/vr/libpdx_default_transport/private/servicefs/pdx/default_transport/client_channel_factory.h deleted file mode 100644 index 77b5cac2f5..0000000000 --- a/libs/vr/libpdx_default_transport/private/servicefs/pdx/default_transport/client_channel_factory.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef ANDROID_PDX_DEFAULT_TRANSPORT_SERVICEFS_CLIENT_CHANNEL_FACTORY_H_ -#define ANDROID_PDX_DEFAULT_TRANSPORT_SERVICEFS_CLIENT_CHANNEL_FACTORY_H_ - -#include <servicefs/client_channel_factory.h> - -namespace android { -namespace pdx { -namespace default_transport { - -using ClientChannelFactory = ::android::pdx::servicefs::ClientChannelFactory; - -} // namespace default_transport -} // namespace pdx -} // namespace android - - -#endif // ANDROID_PDX_DEFAULT_TRANSPORT_SERVICEFS_CLIENT_CHANNEL_FACTORY_H_ diff --git a/libs/vr/libpdx_default_transport/private/servicefs/pdx/default_transport/service_endpoint.h b/libs/vr/libpdx_default_transport/private/servicefs/pdx/default_transport/service_endpoint.h deleted file mode 100644 index 8f413c1fa1..0000000000 --- a/libs/vr/libpdx_default_transport/private/servicefs/pdx/default_transport/service_endpoint.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef ANDROID_PDX_DEFAULT_TRANSPORT_SERVICEFS_SERVICE_ENDPOINT_H_ -#define ANDROID_PDX_DEFAULT_TRANSPORT_SERVICEFS_SERVICE_ENDPOINT_H_ - -#include <servicefs/service_endpoint.h> - -namespace android { -namespace pdx { -namespace default_transport { - -using Endpoint = ::android::pdx::servicefs::Endpoint; - -} // namespace default_transport -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_DEFAULT_TRANSPORT_SERVICEFS_PDX_SERVICE_ENDPOINT_H_ diff --git a/libs/vr/libpdx_default_transport/private/uds/pdx/default_transport/channel_manager.h b/libs/vr/libpdx_default_transport/private/uds/pdx/default_transport/channel_manager.h deleted file mode 100644 index f34636f10a..0000000000 --- a/libs/vr/libpdx_default_transport/private/uds/pdx/default_transport/channel_manager.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef ANDROID_PDX_DEFAULT_TRANSPORT_UDS_CHANNEL_MANAGER_H_ -#define ANDROID_PDX_DEFAULT_TRANSPORT_UDS_CHANNEL_MANAGER_H_ - -#include <uds/channel_manager.h> - -namespace android { -namespace pdx { -namespace default_transport { - -using ChannelManager = ::android::pdx::uds::ChannelManager; - -} // namespace default_transport -} // namespace pdx -} // namespace android - - -#endif // ANDROID_PDX_DEFAULT_TRANSPORT_UDS_CHANNEL_MANAGER_H_ diff --git a/libs/vr/libpdx_default_transport/private/uds/pdx/default_transport/channel_parcelable.h b/libs/vr/libpdx_default_transport/private/uds/pdx/default_transport/channel_parcelable.h deleted file mode 100644 index bcd74e6f25..0000000000 --- a/libs/vr/libpdx_default_transport/private/uds/pdx/default_transport/channel_parcelable.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef ANDROID_PDX_DEFAULT_TRANSPORT_UDS_CHANNEL_PARCELABLE_H_ -#define ANDROID_PDX_DEFAULT_TRANSPORT_UDS_CHANNEL_PARCELABLE_H_ - -#include <uds/channel_parcelable.h> - -namespace android { -namespace pdx { -namespace default_transport { - -using ChannelParcelable = ::android::pdx::uds::ChannelParcelable; - -} // namespace default_transport -} // namespace pdx -} // namespace android - - -#endif // ANDROID_PDX_DEFAULT_TRANSPORT_UDS_CHANNEL_PARCELABLE_H_ diff --git a/libs/vr/libpdx_default_transport/private/uds/pdx/default_transport/client_channel.h b/libs/vr/libpdx_default_transport/private/uds/pdx/default_transport/client_channel.h deleted file mode 100644 index bf632d7512..0000000000 --- a/libs/vr/libpdx_default_transport/private/uds/pdx/default_transport/client_channel.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef ANDROID_PDX_DEFAULT_TRANSPORT_UDS_CLIENT_CHANNEL_H_ -#define ANDROID_PDX_DEFAULT_TRANSPORT_UDS_CLIENT_CHANNEL_H_ - -#include <uds/client_channel.h> - -namespace android { -namespace pdx { -namespace default_transport { - -using ClientChannel = ::android::pdx::uds::ClientChannel; - -} // namespace default_transport -} // namespace pdx -} // namespace android - - -#endif // ANDROID_PDX_DEFAULT_TRANSPORT_UDS_CLIENT_CHANNEL_H_ diff --git a/libs/vr/libpdx_default_transport/private/uds/pdx/default_transport/client_channel_factory.h b/libs/vr/libpdx_default_transport/private/uds/pdx/default_transport/client_channel_factory.h deleted file mode 100644 index e5c4e30368..0000000000 --- a/libs/vr/libpdx_default_transport/private/uds/pdx/default_transport/client_channel_factory.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef ANDROID_PDX_DEFAULT_TRANSPORT_UDS_CLIENT_CHANNEL_FACTORY_H_ -#define ANDROID_PDX_DEFAULT_TRANSPORT_UDS_CLIENT_CHANNEL_FACTORY_H_ - -#include <uds/client_channel_factory.h> - -namespace android { -namespace pdx { -namespace default_transport { - -using ClientChannelFactory = ::android::pdx::uds::ClientChannelFactory; - -} // namespace default_transport -} // namespace pdx -} // namespace android - - -#endif // ANDROID_PDX_DEFAULT_TRANSPORT_UDS_CLIENT_CHANNEL_FACTORY_H_ diff --git a/libs/vr/libpdx_default_transport/private/uds/pdx/default_transport/service_endpoint.h b/libs/vr/libpdx_default_transport/private/uds/pdx/default_transport/service_endpoint.h deleted file mode 100644 index 1fd61030f9..0000000000 --- a/libs/vr/libpdx_default_transport/private/uds/pdx/default_transport/service_endpoint.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef ANDROID_PDX_DEFAULT_TRANSPORT_UDS_SERVICE_ENDPOINT_H_ -#define ANDROID_PDX_DEFAULT_TRANSPORT_UDS_SERVICE_ENDPOINT_H_ - -#include <uds/service_endpoint.h> - -namespace android { -namespace pdx { -namespace default_transport { - -using Endpoint = ::android::pdx::uds::Endpoint; - -} // namespace default_transport -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_DEFAULT_TRANSPORT_UDS_PDX_SERVICE_ENDPOINT_H_ diff --git a/libs/vr/libpdx_uds/Android.bp b/libs/vr/libpdx_uds/Android.bp deleted file mode 100644 index 7f88dafc81..0000000000 --- a/libs/vr/libpdx_uds/Android.bp +++ /dev/null @@ -1,67 +0,0 @@ -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "frameworks_native_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["frameworks_native_license"], -} - -cc_library_static { - name: "libpdx_uds", - cflags: [ - "-Wall", - "-Wextra", - "-Werror", - "-DLOG_TAG=\"libpdx_uds\"", - "-DTRACE=0", - ], - export_include_dirs: ["private"], - local_include_dirs: ["private"], - srcs: [ - "channel_event_set.cpp", - "channel_manager.cpp", - "channel_parcelable.cpp", - "client_channel_factory.cpp", - "client_channel.cpp", - "ipc_helper.cpp", - "service_endpoint.cpp", - ], - static_libs: [ - "libcutils", - "libbase", - "libpdx", - ], - shared_libs: [ - "libbinder", - "libselinux", - ], -} - -cc_test { - name: "libpdx_uds_tests", - cflags: [ - "-Wall", - "-Wextra", - "-Werror", - ], - srcs: [ - "client_channel_tests.cpp", - "ipc_helper_tests.cpp", - "remote_method_tests.cpp", - "service_framework_tests.cpp", - ], - static_libs: [ - "libgmock", - "libpdx_uds", - "libpdx", - ], - shared_libs: [ - "libbase", - "libcutils", - "liblog", - "libutils", - "libbinder", - "libselinux", - ], -} diff --git a/libs/vr/libpdx_uds/channel_event_set.cpp b/libs/vr/libpdx_uds/channel_event_set.cpp deleted file mode 100644 index c68968e1f2..0000000000 --- a/libs/vr/libpdx_uds/channel_event_set.cpp +++ /dev/null @@ -1,150 +0,0 @@ -#include "private/uds/channel_event_set.h" - -#include <errno.h> -#include <log/log.h> -#include <poll.h> -#include <sys/epoll.h> -#include <sys/eventfd.h> - -#include <uds/ipc_helper.h> - -namespace android { -namespace pdx { -namespace uds { - -namespace { - -template <typename FileHandleType> -Status<void> SetupHandle(int fd, FileHandleType* handle, - const char* error_name) { - const int error = errno; - handle->Reset(fd); - if (!*handle) { - ALOGE("SetupHandle: Failed to setup %s handle: %s", error_name, - strerror(error)); - return ErrorStatus{error}; - } - return {}; -} - -} // anonymous namespace - -ChannelEventSet::ChannelEventSet() { - const int flags = EFD_CLOEXEC | EFD_NONBLOCK; - LocalHandle pollin_event_fd, pollhup_event_fd; - - if (!SetupHandle(eventfd(0, flags), &pollin_event_fd, "pollin_event") || - !SetupHandle(eventfd(0, flags), &pollhup_event_fd, "pollhup_event")) { - return; - } - - pollin_event_fd_ = std::move(pollin_event_fd); - pollhup_event_fd_ = std::move(pollhup_event_fd); -} - -int ChannelEventSet::ModifyEvents(int clear_mask, int set_mask) { - ALOGD_IF(TRACE, "ChannelEventSet::ModifyEvents: clear_mask=%x set_mask=%x", - clear_mask, set_mask); - const int old_bits = event_bits_; - const int new_bits = (event_bits_ & ~clear_mask) | set_mask; - event_bits_ = new_bits; - eventfd_t value; - - // Calculate which bits changed and how. Bits that haven't changed since last - // modification will not change the state of an eventfd. - const int set_bits = new_bits & ~old_bits; - const int clear_bits = ~new_bits & old_bits; - - if (set_bits & EPOLLIN) - eventfd_write(pollin_event_fd_.Get(), 1); - else if (clear_bits & EPOLLIN) - eventfd_read(pollin_event_fd_.Get(), &value); - - if (set_bits & EPOLLHUP) - eventfd_write(pollhup_event_fd_.Get(), 1); - else if (clear_bits & EPOLLHUP) - eventfd_read(pollhup_event_fd_.Get(), &value); - - return 0; -} - -ChannelEventReceiver::ChannelEventReceiver(LocalHandle data_fd, - LocalHandle pollin_event_fd, - LocalHandle pollhup_event_fd) { - LocalHandle epoll_fd; - if (!SetupHandle(epoll_create1(EPOLL_CLOEXEC), &epoll_fd, "epoll")) { - return; - } - - epoll_event event; - event.events = EPOLLHUP | EPOLLRDHUP; - event.data.u32 = 0; - if (epoll_ctl(epoll_fd.Get(), EPOLL_CTL_ADD, data_fd.Get(), &event) < 0) { - const int error = errno; - ALOGE("ChannelEventSet::ChannelEventSet: Failed to add data_fd: %s", - strerror(error)); - return; - } - - event.events = EPOLLIN; - event.data.u32 = 0; - if (epoll_ctl(epoll_fd.Get(), EPOLL_CTL_ADD, pollin_event_fd.Get(), &event) < - 0) { - const int error = errno; - ALOGE("ChannelEventSet::ChannelEventSet: Failed to add pollin_event_fd: %s", - strerror(error)); - return; - } - - event.events = EPOLLIN; - event.data.u32 = 0; - if (epoll_ctl(epoll_fd.Get(), EPOLL_CTL_ADD, pollhup_event_fd.Get(), &event) < - 0) { - const int error = errno; - ALOGE( - "ChannelEventSet::ChannelEventSet: Failed to add pollhup_event_fd: %s", - strerror(error)); - return; - } - - pollin_event_fd_ = std::move(pollin_event_fd); - pollhup_event_fd_ = std::move(pollhup_event_fd); - data_fd_ = std::move(data_fd); - epoll_fd_ = std::move(epoll_fd); -} - -Status<int> ChannelEventReceiver::PollPendingEvents(int timeout_ms) const { - std::array<pollfd, 3> pfds = {{{pollin_event_fd_.Get(), POLLIN, 0}, - {pollhup_event_fd_.Get(), POLLIN, 0}, - {data_fd_.Get(), POLLHUP | POLLRDHUP, 0}}}; - if (RETRY_EINTR(poll(pfds.data(), pfds.size(), timeout_ms)) < 0) { - const int error = errno; - ALOGE( - "ChannelEventReceiver::PollPendingEvents: Failed to poll for events: " - "%s", - strerror(error)); - return ErrorStatus{error}; - } - - const int event_mask = - ((pfds[0].revents & POLLIN) ? EPOLLIN : 0) | - ((pfds[1].revents & POLLIN) ? EPOLLHUP : 0) | - ((pfds[2].revents & (POLLHUP | POLLRDHUP)) ? EPOLLHUP : 0); - return {event_mask}; -} - -Status<int> ChannelEventReceiver::GetPendingEvents() const { - constexpr long kTimeoutMs = 0; - return PollPendingEvents(kTimeoutMs); -} - -std::vector<ClientChannel::EventSource> ChannelEventReceiver::GetEventSources() - const { - return {{data_fd_.Get(), EPOLLHUP | EPOLLRDHUP}, - {pollin_event_fd_.Get(), EPOLLIN}, - {pollhup_event_fd_.Get(), POLLIN}}; -} - -} // namespace uds -} // namespace pdx -} // namespace android diff --git a/libs/vr/libpdx_uds/channel_manager.cpp b/libs/vr/libpdx_uds/channel_manager.cpp deleted file mode 100644 index 43ebe05021..0000000000 --- a/libs/vr/libpdx_uds/channel_manager.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include <uds/channel_manager.h> - -#include <log/log.h> - -namespace android { -namespace pdx { -namespace uds { - -ChannelManager& ChannelManager::Get() { - static ChannelManager instance; - return instance; -} - -void ChannelManager::CloseHandle(int32_t handle) { - std::lock_guard<std::mutex> autolock(mutex_); - auto channel = channels_.find(handle); - if (channel == channels_.end()) { - ALOGE("Invalid channel handle: %d", handle); - } else { - channels_.erase(channel); - } -} - -LocalChannelHandle ChannelManager::CreateHandle(LocalHandle data_fd, - LocalHandle pollin_event_fd, - LocalHandle pollhup_event_fd) { - if (data_fd && pollin_event_fd && pollhup_event_fd) { - std::lock_guard<std::mutex> autolock(mutex_); - const int32_t handle = data_fd.Get(); - channels_.emplace( - handle, - ChannelEventReceiver{std::move(data_fd), std::move(pollin_event_fd), - std::move(pollhup_event_fd)}); - return LocalChannelHandle(this, handle); - } else { - ALOGE( - "ChannelManager::CreateHandle: Invalid arguments: data_fd=%d " - "pollin_event_fd=%d pollhup_event_fd=%d", - data_fd.Get(), pollin_event_fd.Get(), pollhup_event_fd.Get()); - return LocalChannelHandle(nullptr, -1); - } -} - -ChannelEventReceiver* ChannelManager::GetChannelData(int32_t handle) { - std::lock_guard<std::mutex> autolock(mutex_); - auto channel = channels_.find(handle); - return channel != channels_.end() ? &channel->second : nullptr; -} - -} // namespace uds -} // namespace pdx -} // namespace android diff --git a/libs/vr/libpdx_uds/channel_parcelable.cpp b/libs/vr/libpdx_uds/channel_parcelable.cpp deleted file mode 100644 index 515684696b..0000000000 --- a/libs/vr/libpdx_uds/channel_parcelable.cpp +++ /dev/null @@ -1,125 +0,0 @@ -#include "uds/channel_parcelable.h" - -#include <binder/Parcel.h> -#include <uds/channel_manager.h> - -namespace android { -namespace pdx { -namespace uds { - -namespace { - -static constexpr uint32_t kUdsMagicParcelHeader = 0x7564736d; // 'udsm'. - -} // namespace - -ChannelParcelable::ChannelParcelable(LocalHandle data_fd, - LocalHandle pollin_event_fd, - LocalHandle pollhup_event_fd) - : data_fd_{std::move(data_fd)}, - pollin_event_fd_{std::move(pollin_event_fd)}, - pollhup_event_fd_{std::move(pollhup_event_fd)} {} - -bool ChannelParcelable::IsValid() const { - return !!data_fd_ && !!pollin_event_fd_ && !!pollhup_event_fd_; -} - -LocalChannelHandle ChannelParcelable::TakeChannelHandle() { - if (!IsValid()) { - ALOGE("ChannelParcelable::TakeChannelHandle: Invalid channel parcel."); - return {}; // Returns an empty channel handle. - } - - return ChannelManager::Get().CreateHandle(std::move(data_fd_), - std::move(pollin_event_fd_), - std::move(pollhup_event_fd_)); -} - -status_t ChannelParcelable::writeToParcel(Parcel* parcel) const { - status_t res = OK; - - if (!IsValid()) { - ALOGE("ChannelParcelable::writeToParcel: Invalid channel parcel."); - return BAD_VALUE; - } - - res = parcel->writeUint32(kUdsMagicParcelHeader); - if (res != OK) { - ALOGE("ChannelParcelable::writeToParcel: Cannot write magic: res=%d.", res); - return res; - } - - res = parcel->writeFileDescriptor(data_fd_.Get()); - if (res != OK) { - ALOGE("ChannelParcelable::writeToParcel: Cannot write data fd: res=%d.", - res); - return res; - } - - res = parcel->writeFileDescriptor(pollin_event_fd_.Get()); - if (res != OK) { - ALOGE( - "ChannelParcelable::writeToParcel: Cannot write pollin event fd: " - "res=%d.", - res); - return res; - } - - res = parcel->writeFileDescriptor(pollhup_event_fd_.Get()); - if (res != OK) { - ALOGE( - "ChannelParcelable::writeToParcel: Cannot write pollhup event fd: " - "res=%d.", - res); - return res; - } - - return res; -} - -status_t ChannelParcelable::readFromParcel(const Parcel* parcel) { - uint32_t magic = 0; - status_t res = OK; - - if (IsValid()) { - ALOGE( - "ChannelParcelable::readFromParcel: This channel parcel is already " - "initailzied."); - return ALREADY_EXISTS; - } - - res = parcel->readUint32(&magic); - if (res != OK) { - ALOGE("ChannelParcelable::readFromParcel: Failed to read magic: res=%d.", - res); - return res; - } - - if (magic != kUdsMagicParcelHeader) { - ALOGE( - "ChannelParcelable::readFromParcel: Unknown magic: 0x%x, epxected: " - "0x%x", - magic, kUdsMagicParcelHeader); - return BAD_VALUE; - } - - // TODO(b/69010509): We have to dup() the FD from android::Parcel as it - // doesn't support taking out the FD's ownership. We can remove the dup() here - // once android::Parcel support such operation. - data_fd_.Reset(dup(parcel->readFileDescriptor())); - pollin_event_fd_.Reset(dup(parcel->readFileDescriptor())); - pollhup_event_fd_.Reset(dup(parcel->readFileDescriptor())); - if (!IsValid()) { - ALOGE( - "ChannelParcelable::readFromParcel: Cannot read fd from parcel: " - "data_fd=%d, pollin_event_fd=%d, pollhup_event_fd=%d.", - data_fd_.Get(), pollin_event_fd_.Get(), pollhup_event_fd_.Get()); - return DEAD_OBJECT; - } - - return res; -} - -} // namespace uds -} // namespace pdx -} // namespace android diff --git a/libs/vr/libpdx_uds/client_channel.cpp b/libs/vr/libpdx_uds/client_channel.cpp deleted file mode 100644 index 6073c3cd05..0000000000 --- a/libs/vr/libpdx_uds/client_channel.cpp +++ /dev/null @@ -1,321 +0,0 @@ -#include "uds/channel_parcelable.h" -#include "uds/client_channel.h" - -#include <errno.h> -#include <log/log.h> -#include <sys/epoll.h> -#include <sys/socket.h> - -#include <pdx/client.h> -#include <pdx/service_endpoint.h> -#include <uds/ipc_helper.h> - -namespace android { -namespace pdx { -namespace uds { - -namespace { - -struct TransactionState { - bool GetLocalFileHandle(int index, LocalHandle* handle) { - if (index < 0) { - handle->Reset(index); - } else if (static_cast<size_t>(index) < response.file_descriptors.size()) { - *handle = std::move(response.file_descriptors[index]); - } else { - return false; - } - return true; - } - - bool GetLocalChannelHandle(int index, LocalChannelHandle* handle) { - if (index < 0) { - *handle = LocalChannelHandle{nullptr, index}; - } else if (static_cast<size_t>(index) < response.channels.size()) { - auto& channel_info = response.channels[index]; - *handle = ChannelManager::Get().CreateHandle( - std::move(channel_info.data_fd), - std::move(channel_info.pollin_event_fd), - std::move(channel_info.pollhup_event_fd)); - } else { - return false; - } - return true; - } - - FileReference PushFileHandle(BorrowedHandle handle) { - if (!handle) - return handle.Get(); - request.file_descriptors.push_back(std::move(handle)); - return request.file_descriptors.size() - 1; - } - - ChannelReference PushChannelHandle(BorrowedChannelHandle handle) { - if (!handle) - return handle.value(); - - if (auto* channel_data = - ChannelManager::Get().GetChannelData(handle.value())) { - ChannelInfo<BorrowedHandle> channel_info{ - channel_data->data_fd(), channel_data->pollin_event_fd(), - channel_data->pollhup_event_fd()}; - request.channels.push_back(std::move(channel_info)); - return request.channels.size() - 1; - } else { - return -1; - } - } - - RequestHeader<BorrowedHandle> request; - ResponseHeader<LocalHandle> response; -}; - -Status<void> ReadAndDiscardData(const BorrowedHandle& socket_fd, size_t size) { - while (size > 0) { - // If there is more data to read in the message than the buffers provided - // by the caller, read and discard the extra data from the socket. - char buffer[1024]; - size_t size_to_read = std::min(sizeof(buffer), size); - auto status = ReceiveData(socket_fd, buffer, size_to_read); - if (!status) - return status; - size -= size_to_read; - } - // We still want to return EIO error to the caller in case we had unexpected - // data in the socket stream. - return ErrorStatus(EIO); -} - -Status<void> SendRequest(const BorrowedHandle& socket_fd, - TransactionState* transaction_state, int opcode, - const iovec* send_vector, size_t send_count, - size_t max_recv_len) { - size_t send_len = CountVectorSize(send_vector, send_count); - InitRequest(&transaction_state->request, opcode, send_len, max_recv_len, - false); - if (send_len == 0) { - send_vector = nullptr; - send_count = 0; - } - return SendData(socket_fd, transaction_state->request, send_vector, - send_count); -} - -Status<void> ReceiveResponse(const BorrowedHandle& socket_fd, - TransactionState* transaction_state, - const iovec* receive_vector, size_t receive_count, - size_t max_recv_len) { - auto status = ReceiveData(socket_fd, &transaction_state->response); - if (!status) - return status; - - if (transaction_state->response.recv_len > 0) { - std::vector<iovec> read_buffers; - size_t size_remaining = 0; - if (transaction_state->response.recv_len != max_recv_len) { - // If the receive buffer not exactly the size of data available, recreate - // the vector list to consume the data exactly since ReceiveDataVector() - // validates that the number of bytes received equals the number of bytes - // requested. - size_remaining = transaction_state->response.recv_len; - for (size_t i = 0; i < receive_count && size_remaining > 0; i++) { - read_buffers.push_back(receive_vector[i]); - iovec& last_vec = read_buffers.back(); - if (last_vec.iov_len > size_remaining) - last_vec.iov_len = size_remaining; - size_remaining -= last_vec.iov_len; - } - receive_vector = read_buffers.data(); - receive_count = read_buffers.size(); - } - status = ReceiveDataVector(socket_fd, receive_vector, receive_count); - if (status && size_remaining > 0) - status = ReadAndDiscardData(socket_fd, size_remaining); - } - return status; -} - -} // anonymous namespace - -ClientChannel::ClientChannel(LocalChannelHandle channel_handle) - : channel_handle_{std::move(channel_handle)} { - channel_data_ = ChannelManager::Get().GetChannelData(channel_handle_.value()); -} - -std::unique_ptr<pdx::ClientChannel> ClientChannel::Create( - LocalChannelHandle channel_handle) { - return std::unique_ptr<pdx::ClientChannel>{ - new ClientChannel{std::move(channel_handle)}}; -} - -ClientChannel::~ClientChannel() { - if (channel_handle_) - shutdown(channel_handle_.value(), SHUT_WR); -} - -void* ClientChannel::AllocateTransactionState() { return new TransactionState; } - -void ClientChannel::FreeTransactionState(void* state) { - delete static_cast<TransactionState*>(state); -} - -Status<void> ClientChannel::SendImpulse(int opcode, const void* buffer, - size_t length) { - std::unique_lock<std::mutex> lock(socket_mutex_); - Status<void> status; - android::pdx::uds::RequestHeader<BorrowedHandle> request; - if (length > request.impulse_payload.size() || - (buffer == nullptr && length != 0)) { - status.SetError(EINVAL); - return status; - } - - InitRequest(&request, opcode, length, 0, true); - memcpy(request.impulse_payload.data(), buffer, length); - return SendData(BorrowedHandle{channel_handle_.value()}, request); -} - -Status<int> ClientChannel::SendAndReceive(void* transaction_state, int opcode, - const iovec* send_vector, - size_t send_count, - const iovec* receive_vector, - size_t receive_count) { - std::unique_lock<std::mutex> lock(socket_mutex_); - Status<int> result; - if ((send_vector == nullptr && send_count != 0) || - (receive_vector == nullptr && receive_count != 0)) { - result.SetError(EINVAL); - return result; - } - - auto* state = static_cast<TransactionState*>(transaction_state); - size_t max_recv_len = CountVectorSize(receive_vector, receive_count); - - auto status = SendRequest(BorrowedHandle{channel_handle_.value()}, state, - opcode, send_vector, send_count, max_recv_len); - if (status) { - status = ReceiveResponse(BorrowedHandle{channel_handle_.value()}, state, - receive_vector, receive_count, max_recv_len); - } - if (!result.PropagateError(status)) { - const int return_code = state->response.ret_code; - if (return_code >= 0) - result.SetValue(return_code); - else - result.SetError(-return_code); - } - return result; -} - -Status<int> ClientChannel::SendWithInt(void* transaction_state, int opcode, - const iovec* send_vector, - size_t send_count, - const iovec* receive_vector, - size_t receive_count) { - return SendAndReceive(transaction_state, opcode, send_vector, send_count, - receive_vector, receive_count); -} - -Status<LocalHandle> ClientChannel::SendWithFileHandle( - void* transaction_state, int opcode, const iovec* send_vector, - size_t send_count, const iovec* receive_vector, size_t receive_count) { - Status<int> int_status = - SendAndReceive(transaction_state, opcode, send_vector, send_count, - receive_vector, receive_count); - Status<LocalHandle> status; - if (status.PropagateError(int_status)) - return status; - - auto* state = static_cast<TransactionState*>(transaction_state); - LocalHandle handle; - if (state->GetLocalFileHandle(int_status.get(), &handle)) { - status.SetValue(std::move(handle)); - } else { - status.SetError(EINVAL); - } - return status; -} - -Status<LocalChannelHandle> ClientChannel::SendWithChannelHandle( - void* transaction_state, int opcode, const iovec* send_vector, - size_t send_count, const iovec* receive_vector, size_t receive_count) { - Status<int> int_status = - SendAndReceive(transaction_state, opcode, send_vector, send_count, - receive_vector, receive_count); - Status<LocalChannelHandle> status; - if (status.PropagateError(int_status)) - return status; - - auto* state = static_cast<TransactionState*>(transaction_state); - LocalChannelHandle handle; - if (state->GetLocalChannelHandle(int_status.get(), &handle)) { - status.SetValue(std::move(handle)); - } else { - status.SetError(EINVAL); - } - return status; -} - -FileReference ClientChannel::PushFileHandle(void* transaction_state, - const LocalHandle& handle) { - auto* state = static_cast<TransactionState*>(transaction_state); - return state->PushFileHandle(handle.Borrow()); -} - -FileReference ClientChannel::PushFileHandle(void* transaction_state, - const BorrowedHandle& handle) { - auto* state = static_cast<TransactionState*>(transaction_state); - return state->PushFileHandle(handle.Duplicate()); -} - -ChannelReference ClientChannel::PushChannelHandle( - void* transaction_state, const LocalChannelHandle& handle) { - auto* state = static_cast<TransactionState*>(transaction_state); - return state->PushChannelHandle(handle.Borrow()); -} - -ChannelReference ClientChannel::PushChannelHandle( - void* transaction_state, const BorrowedChannelHandle& handle) { - auto* state = static_cast<TransactionState*>(transaction_state); - return state->PushChannelHandle(handle.Duplicate()); -} - -bool ClientChannel::GetFileHandle(void* transaction_state, FileReference ref, - LocalHandle* handle) const { - auto* state = static_cast<TransactionState*>(transaction_state); - return state->GetLocalFileHandle(ref, handle); -} - -bool ClientChannel::GetChannelHandle(void* transaction_state, - ChannelReference ref, - LocalChannelHandle* handle) const { - auto* state = static_cast<TransactionState*>(transaction_state); - return state->GetLocalChannelHandle(ref, handle); -} - -std::unique_ptr<pdx::ChannelParcelable> ClientChannel::TakeChannelParcelable() - { - if (!channel_handle_) - return nullptr; - - if (auto* channel_data = - ChannelManager::Get().GetChannelData(channel_handle_.value())) { - auto fds = channel_data->TakeFds(); - auto parcelable = std::make_unique<ChannelParcelable>( - std::move(std::get<0>(fds)), std::move(std::get<1>(fds)), - std::move(std::get<2>(fds))); - - // Here we need to explicitly close the channel handle so that the channel - // won't get shutdown in the destructor, while the FDs in ChannelParcelable - // can keep the channel alive so that new client can be created from it - // later. - channel_handle_.Close(); - return parcelable; - } else { - return nullptr; - } -} - -} // namespace uds -} // namespace pdx -} // namespace android diff --git a/libs/vr/libpdx_uds/client_channel_factory.cpp b/libs/vr/libpdx_uds/client_channel_factory.cpp deleted file mode 100644 index 09dc7beb76..0000000000 --- a/libs/vr/libpdx_uds/client_channel_factory.cpp +++ /dev/null @@ -1,173 +0,0 @@ -#include <uds/client_channel_factory.h> - -#include <errno.h> -#include <log/log.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <unistd.h> - -#include <chrono> -#include <thread> - -#include <uds/channel_manager.h> -#include <uds/client_channel.h> -#include <uds/ipc_helper.h> - -using std::chrono::duration_cast; -using std::chrono::steady_clock; - -namespace android { -namespace pdx { -namespace uds { - -std::string ClientChannelFactory::GetRootEndpointPath() { - return "/dev/socket/pdx"; -} - -std::string ClientChannelFactory::GetEndpointPath( - const std::string& endpoint_path) { - std::string path; - if (!endpoint_path.empty()) { - if (endpoint_path.front() == '/') - path = endpoint_path; - else - path = GetRootEndpointPath() + '/' + endpoint_path; - } - return path; -} - -ClientChannelFactory::ClientChannelFactory(const std::string& endpoint_path) - : endpoint_path_{GetEndpointPath(endpoint_path)} {} - -ClientChannelFactory::ClientChannelFactory(LocalHandle socket) - : socket_{std::move(socket)} {} - -std::unique_ptr<pdx::ClientChannelFactory> ClientChannelFactory::Create( - const std::string& endpoint_path) { - return std::unique_ptr<pdx::ClientChannelFactory>{ - new ClientChannelFactory{endpoint_path}}; -} - -std::unique_ptr<pdx::ClientChannelFactory> ClientChannelFactory::Create( - LocalHandle socket) { - return std::unique_ptr<pdx::ClientChannelFactory>{ - new ClientChannelFactory{std::move(socket)}}; -} - -Status<std::unique_ptr<pdx::ClientChannel>> ClientChannelFactory::Connect( - int64_t timeout_ms) const { - Status<void> status; - - bool connected = socket_.IsValid(); - if (!connected) { - socket_.Reset(socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)); - LOG_ALWAYS_FATAL_IF( - endpoint_path_.empty(), - "ClientChannelFactory::Connect: unspecified socket path"); - } - - if (!socket_) { - ALOGE("ClientChannelFactory::Connect: socket error: %s", strerror(errno)); - return ErrorStatus(errno); - } - - bool use_timeout = (timeout_ms >= 0); - auto now = steady_clock::now(); - auto time_end = now + std::chrono::milliseconds{timeout_ms}; - - int max_eaccess = 5; // Max number of times to retry when EACCES returned. - while (!connected) { - int64_t timeout = -1; - if (use_timeout) { - auto remaining = time_end - now; - timeout = duration_cast<std::chrono::milliseconds>(remaining).count(); - if (timeout < 0) - return ErrorStatus(ETIMEDOUT); - } - sockaddr_un remote; - remote.sun_family = AF_UNIX; - strncpy(remote.sun_path, endpoint_path_.c_str(), sizeof(remote.sun_path)); - remote.sun_path[sizeof(remote.sun_path) - 1] = '\0'; - ALOGD("ClientChannelFactory: Waiting for endpoint at %s", remote.sun_path); - status = WaitForEndpoint(endpoint_path_, timeout); - if (!status) - return ErrorStatus(status.error()); - - ALOGD("ClientChannelFactory: Connecting to %s", remote.sun_path); - int ret = RETRY_EINTR(connect( - socket_.Get(), reinterpret_cast<sockaddr*>(&remote), sizeof(remote))); - if (ret == -1) { - ALOGD("ClientChannelFactory: Connect error %d: %s", errno, - strerror(errno)); - // if |max_eaccess| below reaches zero when errno is EACCES, the control - // flows into the next "else if" statement and a permanent error is - // returned from this function. - if (errno == ECONNREFUSED || (errno == EACCES && max_eaccess-- > 0)) { - // Connection refused/Permission denied can be the result of connecting - // too early (the service socket is created but its access rights are - // not set or not being listened to yet). - ALOGD("ClientChannelFactory: %s, waiting...", strerror(errno)); - using namespace std::literals::chrono_literals; - std::this_thread::sleep_for(100ms); - } else if (errno != ENOENT && errno != ENOTDIR) { - // ENOENT/ENOTDIR might mean that the socket file/directory containing - // it has been just deleted. Try to wait for its creation and do not - // return an error immediately. - ALOGE( - "ClientChannelFactory::Connect: Failed to initialize connection " - "when connecting: %s", - strerror(errno)); - return ErrorStatus(errno); - } - } else { - connected = true; - ALOGD("ClientChannelFactory: Connected successfully to %s...", - remote.sun_path); - ChannelConnectionInfo<LocalHandle> connection_info; - status = ReceiveData(socket_.Borrow(), &connection_info); - if (!status) - return status.error_status(); - socket_ = std::move(connection_info.channel_fd); - if (!socket_) { - ALOGE("ClientChannelFactory::Connect: Failed to obtain channel socket"); - return ErrorStatus(EIO); - } - } - if (use_timeout) - now = steady_clock::now(); - } // while (!connected) - - RequestHeader<BorrowedHandle> request; - InitRequest(&request, opcodes::CHANNEL_OPEN, 0, 0, false); - - status = SendData(socket_.Borrow(), request); - if (!status) - return status.error_status(); - - ResponseHeader<LocalHandle> response; - status = ReceiveData(socket_.Borrow(), &response); - if (!status) - return status.error_status(); - else if (response.ret_code < 0 || response.channels.size() != 1) - return ErrorStatus(EIO); - - LocalHandle pollin_event_fd = std::move(response.channels[0].pollin_event_fd); - LocalHandle pollhup_event_fd = - std::move(response.channels[0].pollhup_event_fd); - - if (!pollin_event_fd || !pollhup_event_fd) { - ALOGE( - "ClientChannelFactory::Connect: Required fd was not returned from the " - "service: pollin_event_fd=%d pollhup_event_fd=%d", - pollin_event_fd.Get(), pollhup_event_fd.Get()); - return ErrorStatus(EIO); - } - - return ClientChannel::Create(ChannelManager::Get().CreateHandle( - std::move(socket_), std::move(pollin_event_fd), - std::move(pollhup_event_fd))); -} - -} // namespace uds -} // namespace pdx -} // namespace android diff --git a/libs/vr/libpdx_uds/client_channel_tests.cpp b/libs/vr/libpdx_uds/client_channel_tests.cpp deleted file mode 100644 index c9c5d15b54..0000000000 --- a/libs/vr/libpdx_uds/client_channel_tests.cpp +++ /dev/null @@ -1,163 +0,0 @@ -#include <uds/client_channel.h> - -#include <sys/socket.h> - -#include <algorithm> -#include <limits> -#include <random> -#include <thread> - -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -#include <pdx/client.h> -#include <pdx/rpc/remote_method.h> -#include <pdx/service.h> -#include <pdx/service_dispatcher.h> - -#include <uds/client_channel_factory.h> -#include <uds/service_endpoint.h> - -using testing::Return; -using testing::_; - -using android::pdx::ClientBase; -using android::pdx::LocalChannelHandle; -using android::pdx::LocalHandle; -using android::pdx::Message; -using android::pdx::ServiceBase; -using android::pdx::ServiceDispatcher; -using android::pdx::Status; -using android::pdx::rpc::DispatchRemoteMethod; -using android::pdx::uds::ClientChannel; -using android::pdx::uds::ClientChannelFactory; -using android::pdx::uds::Endpoint; - -namespace { - -struct TestProtocol { - using DataType = int8_t; - enum { - kOpSum = 0, - }; - PDX_REMOTE_METHOD(Sum, kOpSum, int64_t(const std::vector<DataType>&)); -}; - -class TestService : public ServiceBase<TestService> { - public: - explicit TestService(std::unique_ptr<Endpoint> endpoint) - : ServiceBase{"TestService", std::move(endpoint)} {} - - Status<void> HandleMessage(Message& message) override { - switch (message.GetOp()) { - case TestProtocol::kOpSum: - DispatchRemoteMethod<TestProtocol::Sum>(*this, &TestService::OnSum, - message); - return {}; - - default: - return Service::HandleMessage(message); - } - } - - int64_t OnSum(Message& /*message*/, - const std::vector<TestProtocol::DataType>& data) { - return std::accumulate(data.begin(), data.end(), int64_t{0}); - } -}; - -class TestClient : public ClientBase<TestClient> { - public: - using ClientBase::ClientBase; - - int64_t Sum(const std::vector<TestProtocol::DataType>& data) { - auto status = InvokeRemoteMethod<TestProtocol::Sum>(data); - return status ? status.get() : -1; - } -}; - -class TestServiceRunner { - public: - explicit TestServiceRunner(LocalHandle channel_socket) { - auto endpoint = Endpoint::CreateFromSocketFd(LocalHandle{}); - endpoint->RegisterNewChannelForTests(std::move(channel_socket)); - service_ = TestService::Create(std::move(endpoint)); - dispatcher_ = ServiceDispatcher::Create(); - dispatcher_->AddService(service_); - dispatch_thread_ = std::thread( - std::bind(&ServiceDispatcher::EnterDispatchLoop, dispatcher_.get())); - } - - ~TestServiceRunner() { - dispatcher_->SetCanceled(true); - dispatch_thread_.join(); - dispatcher_->RemoveService(service_); - } - - private: - std::shared_ptr<TestService> service_; - std::unique_ptr<ServiceDispatcher> dispatcher_; - std::thread dispatch_thread_; -}; - -class ClientChannelTest : public testing::Test { - public: - void SetUp() override { - int channel_sockets[2] = {}; - ASSERT_EQ( - 0, socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, channel_sockets)); - LocalHandle service_channel{channel_sockets[0]}; - LocalHandle client_channel{channel_sockets[1]}; - - service_runner_.reset(new TestServiceRunner{std::move(service_channel)}); - auto factory = ClientChannelFactory::Create(std::move(client_channel)); - auto status = factory->Connect(android::pdx::Client::kInfiniteTimeout); - ASSERT_TRUE(status); - client_ = TestClient::Create(status.take()); - } - - void TearDown() override { - service_runner_.reset(); - client_.reset(); - } - - protected: - std::unique_ptr<TestServiceRunner> service_runner_; - std::shared_ptr<TestClient> client_; -}; - -TEST_F(ClientChannelTest, MultithreadedClient) { - constexpr int kNumTestThreads = 8; - constexpr size_t kDataSize = 1000; // Try to keep RPC buffer size below 4K. - - std::random_device rd; - std::mt19937 gen{rd()}; - std::uniform_int_distribution<TestProtocol::DataType> dist{ - std::numeric_limits<TestProtocol::DataType>::min(), - std::numeric_limits<TestProtocol::DataType>::max()}; - - auto worker = [](std::shared_ptr<TestClient> client, - std::vector<TestProtocol::DataType> data) { - constexpr int kMaxIterations = 500; - int64_t expected = std::accumulate(data.begin(), data.end(), int64_t{0}); - for (int i = 0; i < kMaxIterations; i++) { - ASSERT_EQ(expected, client->Sum(data)); - } - }; - - // Start client threads. - std::vector<TestProtocol::DataType> data; - data.resize(kDataSize); - std::vector<std::thread> threads; - for (int i = 0; i < kNumTestThreads; i++) { - std::generate(data.begin(), data.end(), - [&dist, &gen]() { return dist(gen); }); - threads.emplace_back(worker, client_, data); - } - - // Wait for threads to finish. - for (auto& thread : threads) - thread.join(); -} - -} // namespace diff --git a/libs/vr/libpdx_uds/ipc_helper.cpp b/libs/vr/libpdx_uds/ipc_helper.cpp deleted file mode 100644 index f85b3bb666..0000000000 --- a/libs/vr/libpdx_uds/ipc_helper.cpp +++ /dev/null @@ -1,543 +0,0 @@ -#include "uds/ipc_helper.h" - -#include <alloca.h> -#include <errno.h> -#include <log/log.h> -#include <poll.h> -#include <string.h> -#include <sys/inotify.h> -#include <sys/param.h> -#include <sys/socket.h> - -#include <algorithm> - -#include <pdx/service.h> -#include <pdx/utility.h> - -namespace android { -namespace pdx { -namespace uds { - -namespace { - -constexpr size_t kMaxFdCount = - 256; // Total of 1KiB of data to transfer these FDs. - -// Default implementations of Send/Receive interfaces to use standard socket -// send/sendmsg/recv/recvmsg functions. -class SocketSender : public SendInterface { - public: - ssize_t Send(int socket_fd, const void* data, size_t size, - int flags) override { - return send(socket_fd, data, size, flags); - } - ssize_t SendMessage(int socket_fd, const msghdr* msg, int flags) override { - return sendmsg(socket_fd, msg, flags); - } -} g_socket_sender; - -class SocketReceiver : public RecvInterface { - public: - ssize_t Receive(int socket_fd, void* data, size_t size, int flags) override { - return recv(socket_fd, data, size, flags); - } - ssize_t ReceiveMessage(int socket_fd, msghdr* msg, int flags) override { - return recvmsg(socket_fd, msg, flags); - } -} g_socket_receiver; - -} // anonymous namespace - -// Helper wrappers around send()/sendmsg() which repeat send() calls on data -// that was not sent with the initial call to send/sendmsg. This is important to -// handle transmissions interrupted by signals. -Status<void> SendAll(SendInterface* sender, const BorrowedHandle& socket_fd, - const void* data, size_t size) { - Status<void> ret; - const uint8_t* ptr = static_cast<const uint8_t*>(data); - while (size > 0) { - ssize_t size_written = - RETRY_EINTR(sender->Send(socket_fd.Get(), ptr, size, MSG_NOSIGNAL)); - if (size_written < 0) { - ret.SetError(errno); - ALOGE("SendAll: Failed to send data over socket: %s", - ret.GetErrorMessage().c_str()); - break; - } - size -= size_written; - ptr += size_written; - } - return ret; -} - -Status<void> SendMsgAll(SendInterface* sender, const BorrowedHandle& socket_fd, - const msghdr* msg) { - Status<void> ret; - ssize_t sent_size = - RETRY_EINTR(sender->SendMessage(socket_fd.Get(), msg, MSG_NOSIGNAL)); - if (sent_size < 0) { - ret.SetError(errno); - ALOGE("SendMsgAll: Failed to send data over socket: %s", - ret.GetErrorMessage().c_str()); - return ret; - } - - ssize_t chunk_start_offset = 0; - for (size_t i = 0; i < msg->msg_iovlen; i++) { - ssize_t chunk_end_offset = chunk_start_offset + msg->msg_iov[i].iov_len; - if (sent_size < chunk_end_offset) { - size_t offset_within_chunk = sent_size - chunk_start_offset; - size_t data_size = msg->msg_iov[i].iov_len - offset_within_chunk; - const uint8_t* chunk_base = - static_cast<const uint8_t*>(msg->msg_iov[i].iov_base); - ret = SendAll(sender, socket_fd, chunk_base + offset_within_chunk, - data_size); - if (!ret) - break; - sent_size += data_size; - } - chunk_start_offset = chunk_end_offset; - } - return ret; -} - -// Helper wrappers around recv()/recvmsg() which repeat recv() calls on data -// that was not received with the initial call to recvmsg(). This is important -// to handle transmissions interrupted by signals as well as the case when -// initial data did not arrive in a single chunk over the socket (e.g. socket -// buffer was full at the time of transmission, and only portion of initial -// message was sent and the rest was blocked until the buffer was cleared by the -// receiving side). -Status<void> RecvMsgAll(RecvInterface* receiver, - const BorrowedHandle& socket_fd, msghdr* msg) { - Status<void> ret; - ssize_t size_read = RETRY_EINTR(receiver->ReceiveMessage( - socket_fd.Get(), msg, MSG_WAITALL | MSG_CMSG_CLOEXEC)); - if (size_read < 0) { - ret.SetError(errno); - ALOGE("RecvMsgAll: Failed to receive data from socket: %s", - ret.GetErrorMessage().c_str()); - return ret; - } else if (size_read == 0) { - ret.SetError(ESHUTDOWN); - ALOGW("RecvMsgAll: Socket has been shut down"); - return ret; - } - - ssize_t chunk_start_offset = 0; - for (size_t i = 0; i < msg->msg_iovlen; i++) { - ssize_t chunk_end_offset = chunk_start_offset + msg->msg_iov[i].iov_len; - if (size_read < chunk_end_offset) { - size_t offset_within_chunk = size_read - chunk_start_offset; - size_t data_size = msg->msg_iov[i].iov_len - offset_within_chunk; - uint8_t* chunk_base = static_cast<uint8_t*>(msg->msg_iov[i].iov_base); - ret = RecvAll(receiver, socket_fd, chunk_base + offset_within_chunk, - data_size); - if (!ret) - break; - size_read += data_size; - } - chunk_start_offset = chunk_end_offset; - } - return ret; -} - -Status<void> RecvAll(RecvInterface* receiver, const BorrowedHandle& socket_fd, - void* data, size_t size) { - Status<void> ret; - uint8_t* ptr = static_cast<uint8_t*>(data); - while (size > 0) { - ssize_t size_read = RETRY_EINTR(receiver->Receive( - socket_fd.Get(), ptr, size, MSG_WAITALL | MSG_CMSG_CLOEXEC)); - if (size_read < 0) { - ret.SetError(errno); - ALOGE("RecvAll: Failed to receive data from socket: %s", - ret.GetErrorMessage().c_str()); - break; - } else if (size_read == 0) { - ret.SetError(ESHUTDOWN); - ALOGW("RecvAll: Socket has been shut down"); - break; - } - size -= size_read; - ptr += size_read; - } - return ret; -} - -uint32_t kMagicPreamble = 0x7564736d; // 'udsm'. - -struct MessagePreamble { - uint32_t magic{0}; - uint32_t data_size{0}; - uint32_t fd_count{0}; -}; - -Status<void> SendPayload::Send(const BorrowedHandle& socket_fd) { - return Send(socket_fd, nullptr); -} - -Status<void> SendPayload::Send(const BorrowedHandle& socket_fd, - const ucred* cred, const iovec* data_vec, - size_t vec_count) { - if (file_handles_.size() > kMaxFdCount) { - ALOGE( - "SendPayload::Send: Trying to send too many file descriptors (%zu), " - "max allowed = %zu", - file_handles_.size(), kMaxFdCount); - return ErrorStatus{EINVAL}; - } - - SendInterface* sender = sender_ ? sender_ : &g_socket_sender; - MessagePreamble preamble; - preamble.magic = kMagicPreamble; - preamble.data_size = buffer_.size(); - preamble.fd_count = file_handles_.size(); - - msghdr msg = {}; - msg.msg_iovlen = 2 + vec_count; - msg.msg_iov = static_cast<iovec*>(alloca(sizeof(iovec) * msg.msg_iovlen)); - msg.msg_iov[0].iov_base = &preamble; - msg.msg_iov[0].iov_len = sizeof(preamble); - msg.msg_iov[1].iov_base = buffer_.data(); - msg.msg_iov[1].iov_len = buffer_.size(); - for (size_t i = 0; i < vec_count; i++) - msg.msg_iov[i + 2] = data_vec[i]; - - if (cred || !file_handles_.empty()) { - const size_t fd_bytes = file_handles_.size() * sizeof(int); - msg.msg_controllen = (cred ? CMSG_SPACE(sizeof(ucred)) : 0) + - (fd_bytes == 0 ? 0 : CMSG_SPACE(fd_bytes)); - msg.msg_control = alloca(msg.msg_controllen); - - cmsghdr* control = CMSG_FIRSTHDR(&msg); - if (cred) { - control->cmsg_level = SOL_SOCKET; - control->cmsg_type = SCM_CREDENTIALS; - control->cmsg_len = CMSG_LEN(sizeof(ucred)); - memcpy(CMSG_DATA(control), cred, sizeof(ucred)); - control = CMSG_NXTHDR(&msg, control); - } - - if (fd_bytes) { - control->cmsg_level = SOL_SOCKET; - control->cmsg_type = SCM_RIGHTS; - control->cmsg_len = CMSG_LEN(fd_bytes); - memcpy(CMSG_DATA(control), file_handles_.data(), fd_bytes); - } - } - - return SendMsgAll(sender, socket_fd, &msg); -} - -// MessageWriter -void* SendPayload::GetNextWriteBufferSection(size_t size) { - return buffer_.grow_by(size); -} - -OutputResourceMapper* SendPayload::GetOutputResourceMapper() { return this; } - -// OutputResourceMapper -Status<FileReference> SendPayload::PushFileHandle(const LocalHandle& handle) { - if (handle) { - const int ref = file_handles_.size(); - file_handles_.push_back(handle.Get()); - return ref; - } else { - return handle.Get(); - } -} - -Status<FileReference> SendPayload::PushFileHandle( - const BorrowedHandle& handle) { - if (handle) { - const int ref = file_handles_.size(); - file_handles_.push_back(handle.Get()); - return ref; - } else { - return handle.Get(); - } -} - -Status<FileReference> SendPayload::PushFileHandle(const RemoteHandle& handle) { - return handle.Get(); -} - -Status<ChannelReference> SendPayload::PushChannelHandle( - const LocalChannelHandle& /*handle*/) { - return ErrorStatus{EOPNOTSUPP}; -} -Status<ChannelReference> SendPayload::PushChannelHandle( - const BorrowedChannelHandle& /*handle*/) { - return ErrorStatus{EOPNOTSUPP}; -} -Status<ChannelReference> SendPayload::PushChannelHandle( - const RemoteChannelHandle& /*handle*/) { - return ErrorStatus{EOPNOTSUPP}; -} - -Status<void> ReceivePayload::Receive(const BorrowedHandle& socket_fd) { - return Receive(socket_fd, nullptr); -} - -Status<void> ReceivePayload::Receive(const BorrowedHandle& socket_fd, - ucred* cred) { - RecvInterface* receiver = receiver_ ? receiver_ : &g_socket_receiver; - MessagePreamble preamble; - msghdr msg = {}; - iovec recv_vect = {&preamble, sizeof(preamble)}; - msg.msg_iov = &recv_vect; - msg.msg_iovlen = 1; - const size_t receive_fd_bytes = kMaxFdCount * sizeof(int); - msg.msg_controllen = CMSG_SPACE(sizeof(ucred)) + CMSG_SPACE(receive_fd_bytes); - msg.msg_control = alloca(msg.msg_controllen); - - Status<void> ret = RecvMsgAll(receiver, socket_fd, &msg); - if (!ret) - return ret; - - if (preamble.magic != kMagicPreamble) { - ALOGE("ReceivePayload::Receive: Message header is invalid"); - ret.SetError(EIO); - return ret; - } - - buffer_.resize(preamble.data_size); - file_handles_.clear(); - read_pos_ = 0; - - bool cred_available = false; - file_handles_.reserve(preamble.fd_count); - cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); - while (cmsg) { - if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS && - cred && cmsg->cmsg_len == CMSG_LEN(sizeof(ucred))) { - cred_available = true; - memcpy(cred, CMSG_DATA(cmsg), sizeof(ucred)); - } else if (cmsg->cmsg_level == SOL_SOCKET && - cmsg->cmsg_type == SCM_RIGHTS) { - socklen_t payload_len = cmsg->cmsg_len - CMSG_LEN(0); - const int* fds = reinterpret_cast<const int*>(CMSG_DATA(cmsg)); - size_t fd_count = payload_len / sizeof(int); - std::transform(fds, fds + fd_count, std::back_inserter(file_handles_), - [](int fd) { return LocalHandle{fd}; }); - } - cmsg = CMSG_NXTHDR(&msg, cmsg); - } - - ret = RecvAll(receiver, socket_fd, buffer_.data(), buffer_.size()); - if (!ret) - return ret; - - if (cred && !cred_available) { - ALOGE("ReceivePayload::Receive: Failed to obtain message credentials"); - ret.SetError(EIO); - } - - return ret; -} - -// MessageReader -MessageReader::BufferSection ReceivePayload::GetNextReadBufferSection() { - return {buffer_.data() + read_pos_, &*buffer_.end()}; -} - -void ReceivePayload::ConsumeReadBufferSectionData(const void* new_start) { - read_pos_ = PointerDistance(new_start, buffer_.data()); -} - -InputResourceMapper* ReceivePayload::GetInputResourceMapper() { return this; } - -// InputResourceMapper -bool ReceivePayload::GetFileHandle(FileReference ref, LocalHandle* handle) { - if (ref < 0) { - *handle = LocalHandle{ref}; - return true; - } - if (static_cast<size_t>(ref) > file_handles_.size()) - return false; - *handle = std::move(file_handles_[ref]); - return true; -} - -bool ReceivePayload::GetChannelHandle(ChannelReference /*ref*/, - LocalChannelHandle* /*handle*/) { - return false; -} - -Status<void> SendData(const BorrowedHandle& socket_fd, const void* data, - size_t size) { - return SendAll(&g_socket_sender, socket_fd, data, size); -} - -Status<void> SendDataVector(const BorrowedHandle& socket_fd, const iovec* data, - size_t count) { - msghdr msg = {}; - msg.msg_iov = const_cast<iovec*>(data); - msg.msg_iovlen = count; - return SendMsgAll(&g_socket_sender, socket_fd, &msg); -} - -Status<void> ReceiveData(const BorrowedHandle& socket_fd, void* data, - size_t size) { - return RecvAll(&g_socket_receiver, socket_fd, data, size); -} - -Status<void> ReceiveDataVector(const BorrowedHandle& socket_fd, - const iovec* data, size_t count) { - msghdr msg = {}; - msg.msg_iov = const_cast<iovec*>(data); - msg.msg_iovlen = count; - return RecvMsgAll(&g_socket_receiver, socket_fd, &msg); -} - -size_t CountVectorSize(const iovec* vector, size_t count) { - return std::accumulate( - vector, vector + count, size_t{0}, - [](size_t size, const iovec& vec) { return size + vec.iov_len; }); -} - -void InitRequest(android::pdx::uds::RequestHeader<BorrowedHandle>* request, - int opcode, uint32_t send_len, uint32_t max_recv_len, - bool is_impulse) { - request->op = opcode; - request->cred.pid = getpid(); - request->cred.uid = geteuid(); - request->cred.gid = getegid(); - request->send_len = send_len; - request->max_recv_len = max_recv_len; - request->is_impulse = is_impulse; -} - -Status<void> WaitForEndpoint(const std::string& endpoint_path, - int64_t timeout_ms) { - // Endpoint path must be absolute. - if (endpoint_path.empty() || endpoint_path.front() != '/') - return ErrorStatus(EINVAL); - - // Create inotify fd. - LocalHandle fd{inotify_init()}; - if (!fd) - return ErrorStatus(errno); - - // Set the inotify fd to non-blocking. - int ret = fcntl(fd.Get(), F_GETFL); - fcntl(fd.Get(), F_SETFL, ret | O_NONBLOCK); - - // Setup the pollfd. - pollfd pfd = {fd.Get(), POLLIN, 0}; - - // Find locations of each path separator. - std::vector<size_t> separators{0}; // The path is absolute, so '/' is at #0. - size_t pos = endpoint_path.find('/', 1); - while (pos != std::string::npos) { - separators.push_back(pos); - pos = endpoint_path.find('/', pos + 1); - } - separators.push_back(endpoint_path.size()); - - // Walk down the path, checking for existence and waiting if needed. - pos = 1; - size_t links = 0; - std::string current; - while (pos < separators.size() && links <= MAXSYMLINKS) { - std::string previous = current; - current = endpoint_path.substr(0, separators[pos]); - - // Check for existence; proceed to setup a watch if not. - if (access(current.c_str(), F_OK) < 0) { - if (errno != ENOENT) - return ErrorStatus(errno); - - // Extract the name of the path component to wait for. - std::string next = current.substr( - separators[pos - 1] + 1, separators[pos] - separators[pos - 1] - 1); - - // Add a watch on the last existing directory we reach. - int wd = inotify_add_watch( - fd.Get(), previous.c_str(), - IN_CREATE | IN_DELETE_SELF | IN_MOVE_SELF | IN_MOVED_TO); - if (wd < 0) { - if (errno != ENOENT) - return ErrorStatus(errno); - // Restart at the beginning if previous was deleted. - links = 0; - current.clear(); - pos = 1; - continue; - } - - // Make sure current didn't get created before the watch was added. - ret = access(current.c_str(), F_OK); - if (ret < 0) { - if (errno != ENOENT) - return ErrorStatus(errno); - - bool exit_poll = false; - while (!exit_poll) { - // Wait for an event or timeout. - ret = poll(&pfd, 1, timeout_ms); - if (ret <= 0) - return ErrorStatus(ret == 0 ? ETIMEDOUT : errno); - - // Read events. - char buffer[sizeof(inotify_event) + NAME_MAX + 1]; - - ret = read(fd.Get(), buffer, sizeof(buffer)); - if (ret < 0) { - if (errno == EAGAIN || errno == EWOULDBLOCK) - continue; - else - return ErrorStatus(errno); - } else if (static_cast<size_t>(ret) < sizeof(struct inotify_event)) { - return ErrorStatus(EIO); - } - - auto* event = reinterpret_cast<const inotify_event*>(buffer); - auto* end = reinterpret_cast<const inotify_event*>(buffer + ret); - while (event < end) { - std::string event_for; - if (event->len > 0) - event_for = event->name; - - if (event->mask & (IN_CREATE | IN_MOVED_TO)) { - // See if this is the droid we're looking for. - if (next == event_for) { - exit_poll = true; - break; - } - } else if (event->mask & (IN_DELETE_SELF | IN_MOVE_SELF)) { - // Restart at the beginning if our watch dir is deleted. - links = 0; - current.clear(); - pos = 0; - exit_poll = true; - break; - } - - event = reinterpret_cast<const inotify_event*>(AdvancePointer( - event, sizeof(struct inotify_event) + event->len)); - } // while (event < end) - } // while (!exit_poll) - } // Current dir doesn't exist. - ret = inotify_rm_watch(fd.Get(), wd); - if (ret < 0 && errno != EINVAL) - return ErrorStatus(errno); - } // if (access(current.c_str(), F_OK) < 0) - - // Check for symbolic link and update link count. - struct stat stat_buf; - ret = lstat(current.c_str(), &stat_buf); - if (ret < 0 && errno != ENOENT) - return ErrorStatus(errno); - else if (ret == 0 && S_ISLNK(stat_buf.st_mode)) - links++; - pos++; - } // while (pos < separators.size() && links <= MAXSYMLINKS) - - return {}; -} - -} // namespace uds -} // namespace pdx -} // namespace android diff --git a/libs/vr/libpdx_uds/ipc_helper_tests.cpp b/libs/vr/libpdx_uds/ipc_helper_tests.cpp deleted file mode 100644 index bfa827e641..0000000000 --- a/libs/vr/libpdx_uds/ipc_helper_tests.cpp +++ /dev/null @@ -1,365 +0,0 @@ -#include "uds/ipc_helper.h" - -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -using testing::Return; -using testing::SetErrnoAndReturn; -using testing::_; - -using android::pdx::BorrowedHandle; -using android::pdx::uds::SendInterface; -using android::pdx::uds::RecvInterface; -using android::pdx::uds::SendAll; -using android::pdx::uds::SendMsgAll; -using android::pdx::uds::RecvAll; -using android::pdx::uds::RecvMsgAll; - -namespace { - -// Useful constants for tests. -static constexpr intptr_t kPtr = 1234; -static constexpr int kSocketFd = 5678; -static const BorrowedHandle kSocket{kSocketFd}; - -// Helper functions to construct test data pointer values. -void* IntToPtr(intptr_t value) { return reinterpret_cast<void*>(value); } -const void* IntToConstPtr(intptr_t value) { - return reinterpret_cast<const void*>(value); -} - -// Mock classes for SendInterface/RecvInterface. -class MockSender : public SendInterface { - public: - MOCK_METHOD4(Send, ssize_t(int socket_fd, const void* data, size_t size, - int flags)); - MOCK_METHOD3(SendMessage, - ssize_t(int socket_fd, const msghdr* msg, int flags)); -}; - -class MockReceiver : public RecvInterface { - public: - MOCK_METHOD4(Receive, - ssize_t(int socket_fd, void* data, size_t size, int flags)); - MOCK_METHOD3(ReceiveMessage, ssize_t(int socket_fd, msghdr* msg, int flags)); -}; - -// Test case classes. -class SendTest : public testing::Test { - public: - SendTest() { - ON_CALL(sender_, Send(_, _, _, _)) - .WillByDefault(SetErrnoAndReturn(EIO, -1)); - ON_CALL(sender_, SendMessage(_, _, _)) - .WillByDefault(SetErrnoAndReturn(EIO, -1)); - } - - protected: - MockSender sender_; -}; - -class RecvTest : public testing::Test { - public: - RecvTest() { - ON_CALL(receiver_, Receive(_, _, _, _)) - .WillByDefault(SetErrnoAndReturn(EIO, -1)); - ON_CALL(receiver_, ReceiveMessage(_, _, _)) - .WillByDefault(SetErrnoAndReturn(EIO, -1)); - } - - protected: - MockReceiver receiver_; -}; - -class MessageTestBase : public testing::Test { - public: - MessageTestBase() { - memset(&msg_, 0, sizeof(msg_)); - msg_.msg_iovlen = data_.size(); - msg_.msg_iov = data_.data(); - } - - protected: - static constexpr intptr_t kPtr1 = kPtr; - static constexpr intptr_t kPtr2 = kPtr + 200; - static constexpr intptr_t kPtr3 = kPtr + 1000; - - MockSender sender_; - msghdr msg_; - std::vector<iovec> data_{ - {IntToPtr(kPtr1), 100}, {IntToPtr(kPtr2), 200}, {IntToPtr(kPtr3), 300}}; -}; - -class SendMessageTest : public MessageTestBase { - public: - SendMessageTest() { - ON_CALL(sender_, Send(_, _, _, _)) - .WillByDefault(SetErrnoAndReturn(EIO, -1)); - ON_CALL(sender_, SendMessage(_, _, _)) - .WillByDefault(SetErrnoAndReturn(EIO, -1)); - } - - protected: - MockSender sender_; -}; - -class RecvMessageTest : public MessageTestBase { - public: - RecvMessageTest() { - ON_CALL(receiver_, Receive(_, _, _, _)) - .WillByDefault(SetErrnoAndReturn(EIO, -1)); - ON_CALL(receiver_, ReceiveMessage(_, _, _)) - .WillByDefault(SetErrnoAndReturn(EIO, -1)); - } - - protected: - MockReceiver receiver_; -}; - -// Actual tests. - -// SendAll -TEST_F(SendTest, Complete) { - EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr), 100, MSG_NOSIGNAL)) - .WillOnce(Return(100)); - - auto status = SendAll(&sender_, kSocket, IntToConstPtr(kPtr), 100); - EXPECT_TRUE(status); -} - -TEST_F(SendTest, Signal) { - EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr), 100, MSG_NOSIGNAL)) - .WillOnce(Return(20)); - EXPECT_CALL(sender_, - Send(kSocketFd, IntToConstPtr(kPtr + 20), 80, MSG_NOSIGNAL)) - .WillOnce(Return(40)); - EXPECT_CALL(sender_, - Send(kSocketFd, IntToConstPtr(kPtr + 60), 40, MSG_NOSIGNAL)) - .WillOnce(Return(40)); - - auto status = SendAll(&sender_, kSocket, IntToConstPtr(kPtr), 100); - EXPECT_TRUE(status); -} - -TEST_F(SendTest, Eintr) { - EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr), 100, MSG_NOSIGNAL)) - .WillOnce(SetErrnoAndReturn(EINTR, -1)) - .WillOnce(Return(100)); - - auto status = SendAll(&sender_, kSocket, IntToConstPtr(kPtr), 100); - EXPECT_TRUE(status); -} - -TEST_F(SendTest, Error) { - EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr), 100, MSG_NOSIGNAL)) - .WillOnce(SetErrnoAndReturn(EIO, -1)); - - auto status = SendAll(&sender_, kSocket, IntToConstPtr(kPtr), 100); - ASSERT_FALSE(status); - EXPECT_EQ(EIO, status.error()); -} - -TEST_F(SendTest, Error2) { - EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr), 100, MSG_NOSIGNAL)) - .WillOnce(Return(50)); - EXPECT_CALL(sender_, - Send(kSocketFd, IntToConstPtr(kPtr + 50), 50, MSG_NOSIGNAL)) - .WillOnce(SetErrnoAndReturn(EIO, -1)); - - auto status = SendAll(&sender_, kSocket, IntToConstPtr(kPtr), 100); - ASSERT_FALSE(status); - EXPECT_EQ(EIO, status.error()); -} - -// RecvAll -TEST_F(RecvTest, Complete) { - EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr), 100, - MSG_WAITALL | MSG_CMSG_CLOEXEC)) - .WillOnce(Return(100)); - - auto status = RecvAll(&receiver_, kSocket, IntToPtr(kPtr), 100); - EXPECT_TRUE(status); -} - -TEST_F(RecvTest, Signal) { - EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr), 100, _)) - .WillOnce(Return(20)); - EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr + 20), 80, _)) - .WillOnce(Return(40)); - EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr + 60), 40, _)) - .WillOnce(Return(40)); - - auto status = RecvAll(&receiver_, kSocket, IntToPtr(kPtr), 100); - EXPECT_TRUE(status); -} - -TEST_F(RecvTest, Eintr) { - EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr), 100, _)) - .WillOnce(SetErrnoAndReturn(EINTR, -1)) - .WillOnce(Return(100)); - - auto status = RecvAll(&receiver_, kSocket, IntToPtr(kPtr), 100); - EXPECT_TRUE(status); -} - -TEST_F(RecvTest, Error) { - EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr), 100, _)) - .WillOnce(SetErrnoAndReturn(EIO, -1)); - - auto status = RecvAll(&receiver_, kSocket, IntToPtr(kPtr), 100); - ASSERT_FALSE(status); - EXPECT_EQ(EIO, status.error()); -} - -TEST_F(RecvTest, Error2) { - EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr), 100, _)) - .WillOnce(Return(30)); - EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr + 30), 70, _)) - .WillOnce(SetErrnoAndReturn(EIO, -1)); - - auto status = RecvAll(&receiver_, kSocket, IntToPtr(kPtr), 100); - ASSERT_FALSE(status); - EXPECT_EQ(EIO, status.error()); -} - -// SendMsgAll -TEST_F(SendMessageTest, Complete) { - EXPECT_CALL(sender_, SendMessage(kSocketFd, &msg_, MSG_NOSIGNAL)) - .WillOnce(Return(600)); - - auto status = SendMsgAll(&sender_, kSocket, &msg_); - EXPECT_TRUE(status); -} - -TEST_F(SendMessageTest, Partial) { - EXPECT_CALL(sender_, SendMessage(kSocketFd, &msg_, _)).WillOnce(Return(70)); - EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr1 + 70), 30, _)) - .WillOnce(Return(30)); - EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr2), 200, _)) - .WillOnce(Return(190)); - EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr2 + 190), 10, _)) - .WillOnce(Return(10)); - EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr3), 300, _)) - .WillOnce(Return(300)); - - auto status = SendMsgAll(&sender_, kSocket, &msg_); - EXPECT_TRUE(status); -} - -TEST_F(SendMessageTest, Partial2) { - EXPECT_CALL(sender_, SendMessage(kSocketFd, &msg_, _)).WillOnce(Return(310)); - EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr3 + 10), 290, _)) - .WillOnce(Return(290)); - - auto status = SendMsgAll(&sender_, kSocket, &msg_); - EXPECT_TRUE(status); -} - -TEST_F(SendMessageTest, Eintr) { - EXPECT_CALL(sender_, SendMessage(kSocketFd, &msg_, _)) - .WillOnce(SetErrnoAndReturn(EINTR, -1)) - .WillOnce(Return(70)); - EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr1 + 70), 30, _)) - .WillOnce(SetErrnoAndReturn(EINTR, -1)) - .WillOnce(Return(30)); - EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr2), 200, _)) - .WillOnce(Return(200)); - EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr3), 300, _)) - .WillOnce(Return(300)); - - auto status = SendMsgAll(&sender_, kSocket, &msg_); - EXPECT_TRUE(status); -} - -TEST_F(SendMessageTest, Error) { - EXPECT_CALL(sender_, SendMessage(kSocketFd, &msg_, _)) - .WillOnce(SetErrnoAndReturn(EBADF, -1)); - - auto status = SendMsgAll(&sender_, kSocket, &msg_); - ASSERT_FALSE(status); - EXPECT_EQ(EBADF, status.error()); -} - -TEST_F(SendMessageTest, Error2) { - EXPECT_CALL(sender_, SendMessage(kSocketFd, &msg_, _)).WillOnce(Return(20)); - EXPECT_CALL(sender_, Send(kSocketFd, IntToConstPtr(kPtr1 + 20), 80, _)) - .WillOnce(SetErrnoAndReturn(EBADF, -1)); - - auto status = SendMsgAll(&sender_, kSocket, &msg_); - ASSERT_FALSE(status); - EXPECT_EQ(EBADF, status.error()); -} - -// RecvMsgAll -TEST_F(RecvMessageTest, Complete) { - EXPECT_CALL(receiver_, - ReceiveMessage(kSocketFd, &msg_, MSG_WAITALL | MSG_CMSG_CLOEXEC)) - .WillOnce(Return(600)); - - auto status = RecvMsgAll(&receiver_, kSocket, &msg_); - EXPECT_TRUE(status); -} - -TEST_F(RecvMessageTest, Partial) { - EXPECT_CALL(receiver_, ReceiveMessage(kSocketFd, &msg_, _)) - .WillOnce(Return(70)); - EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr1 + 70), 30, _)) - .WillOnce(Return(30)); - EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr2), 200, _)) - .WillOnce(Return(190)); - EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr2 + 190), 10, _)) - .WillOnce(Return(10)); - EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr3), 300, _)) - .WillOnce(Return(300)); - - auto status = RecvMsgAll(&receiver_, kSocket, &msg_); - EXPECT_TRUE(status); -} - -TEST_F(RecvMessageTest, Partial2) { - EXPECT_CALL(receiver_, ReceiveMessage(kSocketFd, &msg_, _)) - .WillOnce(Return(310)); - EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr3 + 10), 290, _)) - .WillOnce(Return(290)); - - auto status = RecvMsgAll(&receiver_, kSocket, &msg_); - EXPECT_TRUE(status); -} - -TEST_F(RecvMessageTest, Eintr) { - EXPECT_CALL(receiver_, ReceiveMessage(kSocketFd, &msg_, _)) - .WillOnce(SetErrnoAndReturn(EINTR, -1)) - .WillOnce(Return(70)); - EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr1 + 70), 30, _)) - .WillOnce(SetErrnoAndReturn(EINTR, -1)) - .WillOnce(Return(30)); - EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr2), 200, _)) - .WillOnce(Return(200)); - EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr3), 300, _)) - .WillOnce(Return(300)); - - auto status = RecvMsgAll(&receiver_, kSocket, &msg_); - EXPECT_TRUE(status); -} - -TEST_F(RecvMessageTest, Error) { - EXPECT_CALL(receiver_, ReceiveMessage(kSocketFd, &msg_, _)) - .WillOnce(SetErrnoAndReturn(EBADF, -1)); - - auto status = RecvMsgAll(&receiver_, kSocket, &msg_); - ASSERT_FALSE(status); - EXPECT_EQ(EBADF, status.error()); -} - -TEST_F(RecvMessageTest, Error2) { - EXPECT_CALL(receiver_, ReceiveMessage(kSocketFd, &msg_, _)) - .WillOnce(Return(20)); - EXPECT_CALL(receiver_, Receive(kSocketFd, IntToPtr(kPtr1 + 20), 80, _)) - .WillOnce(SetErrnoAndReturn(EBADF, -1)); - - auto status = RecvMsgAll(&receiver_, kSocket, &msg_); - ASSERT_FALSE(status); - EXPECT_EQ(EBADF, status.error()); -} - -} // namespace diff --git a/libs/vr/libpdx_uds/private/uds/channel_event_set.h b/libs/vr/libpdx_uds/private/uds/channel_event_set.h deleted file mode 100644 index e960740787..0000000000 --- a/libs/vr/libpdx_uds/private/uds/channel_event_set.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef ANDROID_PDX_UDS_CHANNEL_EVENT_SET_H_ -#define ANDROID_PDX_UDS_CHANNEL_EVENT_SET_H_ - -#include <vector> - -#include <pdx/client_channel.h> -#include <pdx/file_handle.h> -#include <pdx/status.h> - -namespace android { -namespace pdx { -namespace uds { - -class ChannelEventSet { - public: - ChannelEventSet(); - ChannelEventSet(ChannelEventSet&&) = default; - ChannelEventSet& operator=(ChannelEventSet&&) = default; - - BorrowedHandle pollin_event_fd() const { return pollin_event_fd_.Borrow(); } - BorrowedHandle pollhup_event_fd() const { return pollhup_event_fd_.Borrow(); } - - explicit operator bool() const { - return !!pollin_event_fd_ && !!pollhup_event_fd_; - } - - int ModifyEvents(int clear_mask, int set_mask); - - private: - LocalHandle pollin_event_fd_; - LocalHandle pollhup_event_fd_; - uint32_t event_bits_ = 0; - - ChannelEventSet(const ChannelEventSet&) = delete; - void operator=(const ChannelEventSet&) = delete; -}; - -class ChannelEventReceiver { - public: - ChannelEventReceiver() = default; - ChannelEventReceiver(LocalHandle data_fd, LocalHandle pollin_event_fd, - LocalHandle pollhup_event_fd); - ChannelEventReceiver(ChannelEventReceiver&&) = default; - ChannelEventReceiver& operator=(ChannelEventReceiver&&) = default; - - explicit operator bool() const { - return !!pollin_event_fd_ && !!pollhup_event_fd_ && !!data_fd_ && - !!epoll_fd_; - } - - BorrowedHandle event_fd() const { return epoll_fd_.Borrow(); } - - BorrowedHandle pollin_event_fd() const { return pollin_event_fd_.Borrow(); } - BorrowedHandle pollhup_event_fd() const { return pollhup_event_fd_.Borrow(); } - BorrowedHandle data_fd() const { return data_fd_.Borrow(); } - - // Moves file descriptors out of ChannelEventReceiver. Note these operations - // immediately invalidates the receiver. - std::tuple<LocalHandle, LocalHandle, LocalHandle> TakeFds() { - epoll_fd_.Close(); - return {std::move(data_fd_), std::move(pollin_event_fd_), - std::move(pollhup_event_fd_)}; - } - - Status<int> GetPendingEvents() const; - Status<int> PollPendingEvents(int timeout_ms) const; - - std::vector<ClientChannel::EventSource> GetEventSources() const; - - private: - LocalHandle data_fd_; - LocalHandle pollin_event_fd_; - LocalHandle pollhup_event_fd_; - LocalHandle epoll_fd_; - - ChannelEventReceiver(const ChannelEventReceiver&) = delete; - void operator=(const ChannelEventReceiver&) = delete; -}; - -} // namespace uds -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_UDS_CHANNEL_EVENT_SET_H_ diff --git a/libs/vr/libpdx_uds/private/uds/channel_manager.h b/libs/vr/libpdx_uds/private/uds/channel_manager.h deleted file mode 100644 index 5f6a514340..0000000000 --- a/libs/vr/libpdx_uds/private/uds/channel_manager.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef ANDROID_PDX_UDS_CHANNEL_MANAGER_H_ -#define ANDROID_PDX_UDS_CHANNEL_MANAGER_H_ - -#include <mutex> -#include <unordered_map> - -#include <pdx/channel_handle.h> -#include <pdx/file_handle.h> -#include <uds/channel_event_set.h> - -namespace android { -namespace pdx { -namespace uds { - -class ChannelManager : public ChannelManagerInterface { - public: - static ChannelManager& Get(); - - LocalChannelHandle CreateHandle(LocalHandle data_fd, - LocalHandle pollin_event_fd, - LocalHandle pollhup_event_fd); - - ChannelEventReceiver* GetChannelData(int32_t handle); - - private: - ChannelManager() = default; - - void CloseHandle(int32_t handle) override; - - std::mutex mutex_; - std::unordered_map<int32_t, ChannelEventReceiver> channels_; -}; - -} // namespace uds -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_UDS_CHANNEL_MANAGER_H_ diff --git a/libs/vr/libpdx_uds/private/uds/channel_parcelable.h b/libs/vr/libpdx_uds/private/uds/channel_parcelable.h deleted file mode 100644 index 1c3fae91d8..0000000000 --- a/libs/vr/libpdx_uds/private/uds/channel_parcelable.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef ANDROID_PDX_UDS_CHANNEL_PARCELABLE_H_ -#define ANDROID_PDX_UDS_CHANNEL_PARCELABLE_H_ - -#include <pdx/channel_parcelable.h> -#include <pdx/file_handle.h> - -namespace android { -namespace pdx { -namespace uds { - -class ChannelParcelable : public pdx::ChannelParcelable { - public: - ChannelParcelable() = default; - ChannelParcelable(LocalHandle data_fd, LocalHandle pollin_event_fd, - LocalHandle pollhup_event_fd); - - // Implements pdx::ChannelParcelable interface. - bool IsValid() const override; - LocalChannelHandle TakeChannelHandle() override; - - // Implements android::Parcelable interface. - status_t writeToParcel(Parcel* parcel) const override; - status_t readFromParcel(const Parcel* parcel) override; - - private: - LocalHandle data_fd_; - LocalHandle pollin_event_fd_; - LocalHandle pollhup_event_fd_; -}; - -} // namespace uds -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_UDS_CHANNEL_PARCELABLE_H_ diff --git a/libs/vr/libpdx_uds/private/uds/client_channel.h b/libs/vr/libpdx_uds/private/uds/client_channel.h deleted file mode 100644 index 3561c6f191..0000000000 --- a/libs/vr/libpdx_uds/private/uds/client_channel.h +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef ANDROID_PDX_UDS_CLIENT_CHANNEL_H_ -#define ANDROID_PDX_UDS_CLIENT_CHANNEL_H_ - -#include <pdx/client_channel.h> - -#include <mutex> - -#include <uds/channel_event_set.h> -#include <uds/channel_manager.h> -#include <uds/service_endpoint.h> - -namespace android { -namespace pdx { -namespace uds { - -class ClientChannel : public pdx::ClientChannel { - public: - ~ClientChannel() override; - - static std::unique_ptr<pdx::ClientChannel> Create( - LocalChannelHandle channel_handle); - - uint32_t GetIpcTag() const override { return Endpoint::kIpcTag; } - - int event_fd() const override { - return channel_data_ ? channel_data_->event_fd().Get() : -1; - } - - std::vector<EventSource> GetEventSources() const override { - if (channel_data_) - return channel_data_->GetEventSources(); - else - return {}; - } - - Status<int> GetEventMask(int /*events*/) override { - if (channel_data_) - return channel_data_->GetPendingEvents(); - else - return ErrorStatus(EINVAL); - } - - LocalChannelHandle& GetChannelHandle() override { return channel_handle_; } - const LocalChannelHandle& GetChannelHandle() const override { - return channel_handle_; - } - void* AllocateTransactionState() override; - void FreeTransactionState(void* state) override; - - Status<void> SendImpulse(int opcode, const void* buffer, - size_t length) override; - - Status<int> SendWithInt(void* transaction_state, int opcode, - const iovec* send_vector, size_t send_count, - const iovec* receive_vector, - size_t receive_count) override; - Status<LocalHandle> SendWithFileHandle(void* transaction_state, int opcode, - const iovec* send_vector, - size_t send_count, - const iovec* receive_vector, - size_t receive_count) override; - Status<LocalChannelHandle> SendWithChannelHandle( - void* transaction_state, int opcode, const iovec* send_vector, - size_t send_count, const iovec* receive_vector, - size_t receive_count) override; - - FileReference PushFileHandle(void* transaction_state, - const LocalHandle& handle) override; - FileReference PushFileHandle(void* transaction_state, - const BorrowedHandle& handle) override; - ChannelReference PushChannelHandle(void* transaction_state, - const LocalChannelHandle& handle) override; - ChannelReference PushChannelHandle( - void* transaction_state, const BorrowedChannelHandle& handle) override; - bool GetFileHandle(void* transaction_state, FileReference ref, - LocalHandle* handle) const override; - bool GetChannelHandle(void* transaction_state, ChannelReference ref, - LocalChannelHandle* handle) const override; - - std::unique_ptr<pdx::ChannelParcelable> TakeChannelParcelable() override; - - private: - explicit ClientChannel(LocalChannelHandle channel_handle); - - Status<int> SendAndReceive(void* transaction_state, int opcode, - const iovec* send_vector, size_t send_count, - const iovec* receive_vector, size_t receive_count); - - LocalChannelHandle channel_handle_; - ChannelEventReceiver* channel_data_; - std::mutex socket_mutex_; -}; - -} // namespace uds -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_UDS_CLIENT_CHANNEL_H_ diff --git a/libs/vr/libpdx_uds/private/uds/client_channel_factory.h b/libs/vr/libpdx_uds/private/uds/client_channel_factory.h deleted file mode 100644 index c43c5c7c49..0000000000 --- a/libs/vr/libpdx_uds/private/uds/client_channel_factory.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef ANDROID_PDX_UDS_CLIENT_CHANNEL_FACTORY_H_ -#define ANDROID_PDX_UDS_CLIENT_CHANNEL_FACTORY_H_ - -#include <string> - -#include <pdx/client_channel_factory.h> - -namespace android { -namespace pdx { -namespace uds { - -class ClientChannelFactory : public pdx::ClientChannelFactory { - public: - static std::unique_ptr<pdx::ClientChannelFactory> Create( - const std::string& endpoint_path); - static std::unique_ptr<pdx::ClientChannelFactory> Create(LocalHandle socket); - - Status<std::unique_ptr<pdx::ClientChannel>> Connect( - int64_t timeout_ms) const override; - - static std::string GetRootEndpointPath(); - static std::string GetEndpointPath(const std::string& endpoint_path); - - private: - explicit ClientChannelFactory(const std::string& endpoint_path); - explicit ClientChannelFactory(LocalHandle socket); - - mutable LocalHandle socket_; - std::string endpoint_path_; -}; - -} // namespace uds -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_UDS_CLIENT_CHANNEL_FACTORY_H_ diff --git a/libs/vr/libpdx_uds/private/uds/ipc_helper.h b/libs/vr/libpdx_uds/private/uds/ipc_helper.h deleted file mode 100644 index 704a569d0c..0000000000 --- a/libs/vr/libpdx_uds/private/uds/ipc_helper.h +++ /dev/null @@ -1,222 +0,0 @@ -#ifndef ANDROID_PDX_UDS_IPC_HELPER_H_ -#define ANDROID_PDX_UDS_IPC_HELPER_H_ - -#include <sys/socket.h> -#include <utility> -#include <vector> - -#include <pdx/rpc/serializable.h> -#include <pdx/rpc/serialization.h> -#include <pdx/status.h> -#include <pdx/utility.h> - -namespace android { -namespace pdx { -namespace uds { - -// Test interfaces used for unit-testing payload sending/receiving over sockets. -class SendInterface { - public: - virtual ssize_t Send(int socket_fd, const void* data, size_t size, - int flags) = 0; - virtual ssize_t SendMessage(int socket_fd, const msghdr* msg, int flags) = 0; - - protected: - virtual ~SendInterface() = default; -}; - -class RecvInterface { - public: - virtual ssize_t Receive(int socket_fd, void* data, size_t size, - int flags) = 0; - virtual ssize_t ReceiveMessage(int socket_fd, msghdr* msg, int flags) = 0; - - protected: - virtual ~RecvInterface() = default; -}; - -// Helper methods that allow to send/receive data through abstract interfaces. -// Useful for mocking out the underlying socket I/O. -Status<void> SendAll(SendInterface* sender, const BorrowedHandle& socket_fd, - const void* data, size_t size); -Status<void> SendMsgAll(SendInterface* sender, const BorrowedHandle& socket_fd, - const msghdr* msg); -Status<void> RecvAll(RecvInterface* receiver, const BorrowedHandle& socket_fd, - void* data, size_t size); -Status<void> RecvMsgAll(RecvInterface* receiver, - const BorrowedHandle& socket_fd, msghdr* msg); - -#define RETRY_EINTR(fnc_call) \ - ([&]() -> decltype(fnc_call) { \ - decltype(fnc_call) result; \ - do { \ - result = (fnc_call); \ - } while (result == -1 && errno == EINTR); \ - return result; \ - })() - -class SendPayload : public MessageWriter, public OutputResourceMapper { - public: - explicit SendPayload(SendInterface* sender = nullptr) : sender_{sender} {} - Status<void> Send(const BorrowedHandle& socket_fd); - Status<void> Send(const BorrowedHandle& socket_fd, const ucred* cred, - const iovec* data_vec = nullptr, size_t vec_count = 0); - - // MessageWriter - void* GetNextWriteBufferSection(size_t size) override; - OutputResourceMapper* GetOutputResourceMapper() override; - - // OutputResourceMapper - Status<FileReference> PushFileHandle(const LocalHandle& handle) override; - Status<FileReference> PushFileHandle(const BorrowedHandle& handle) override; - Status<FileReference> PushFileHandle(const RemoteHandle& handle) override; - Status<ChannelReference> PushChannelHandle( - const LocalChannelHandle& handle) override; - Status<ChannelReference> PushChannelHandle( - const BorrowedChannelHandle& handle) override; - Status<ChannelReference> PushChannelHandle( - const RemoteChannelHandle& handle) override; - - private: - SendInterface* sender_; - ByteBuffer buffer_; - std::vector<int> file_handles_; -}; - -class ReceivePayload : public MessageReader, public InputResourceMapper { - public: - explicit ReceivePayload(RecvInterface* receiver = nullptr) - : receiver_{receiver} {} - Status<void> Receive(const BorrowedHandle& socket_fd); - Status<void> Receive(const BorrowedHandle& socket_fd, ucred* cred); - - // MessageReader - BufferSection GetNextReadBufferSection() override; - void ConsumeReadBufferSectionData(const void* new_start) override; - InputResourceMapper* GetInputResourceMapper() override; - - // InputResourceMapper - bool GetFileHandle(FileReference ref, LocalHandle* handle) override; - bool GetChannelHandle(ChannelReference ref, - LocalChannelHandle* handle) override; - - private: - RecvInterface* receiver_; - ByteBuffer buffer_; - std::vector<LocalHandle> file_handles_; - size_t read_pos_{0}; -}; - -template <typename FileHandleType> -class ChannelInfo { - public: - FileHandleType data_fd; - FileHandleType pollin_event_fd; - FileHandleType pollhup_event_fd; - - private: - PDX_SERIALIZABLE_MEMBERS(ChannelInfo, data_fd, pollin_event_fd, - pollhup_event_fd); -}; - -template <typename FileHandleType> -class ChannelConnectionInfo { - public: - FileHandleType channel_fd; - - private: - PDX_SERIALIZABLE_MEMBERS(ChannelConnectionInfo, channel_fd); -}; - -template <typename FileHandleType> -class RequestHeader { - public: - int32_t op{0}; - ucred cred; - uint32_t send_len{0}; - uint32_t max_recv_len{0}; - std::vector<FileHandleType> file_descriptors; - std::vector<ChannelInfo<FileHandleType>> channels; - std::array<uint8_t, 32> impulse_payload; - bool is_impulse{false}; - - private: - PDX_SERIALIZABLE_MEMBERS(RequestHeader, op, send_len, max_recv_len, - file_descriptors, channels, impulse_payload, - is_impulse); -}; - -template <typename FileHandleType> -class ResponseHeader { - public: - int32_t ret_code{0}; - uint32_t recv_len{0}; - std::vector<FileHandleType> file_descriptors; - std::vector<ChannelInfo<FileHandleType>> channels; - - private: - PDX_SERIALIZABLE_MEMBERS(ResponseHeader, ret_code, recv_len, file_descriptors, - channels); -}; - -template <typename T> -inline Status<void> SendData(const BorrowedHandle& socket_fd, const T& data, - const iovec* data_vec = nullptr, - size_t vec_count = 0) { - SendPayload payload; - rpc::Serialize(data, &payload); - return payload.Send(socket_fd, nullptr, data_vec, vec_count); -} - -template <typename FileHandleType> -inline Status<void> SendData(const BorrowedHandle& socket_fd, - const RequestHeader<FileHandleType>& request, - const iovec* data_vec = nullptr, - size_t vec_count = 0) { - SendPayload payload; - rpc::Serialize(request, &payload); - return payload.Send(socket_fd, &request.cred, data_vec, vec_count); -} - -Status<void> SendData(const BorrowedHandle& socket_fd, const void* data, - size_t size); -Status<void> SendDataVector(const BorrowedHandle& socket_fd, const iovec* data, - size_t count); - -template <typename T> -inline Status<void> ReceiveData(const BorrowedHandle& socket_fd, T* data) { - ReceivePayload payload; - Status<void> status = payload.Receive(socket_fd); - if (status && rpc::Deserialize(data, &payload) != rpc::ErrorCode::NO_ERROR) - status.SetError(EIO); - return status; -} - -template <typename FileHandleType> -inline Status<void> ReceiveData(const BorrowedHandle& socket_fd, - RequestHeader<FileHandleType>* request) { - ReceivePayload payload; - Status<void> status = payload.Receive(socket_fd, &request->cred); - if (status && rpc::Deserialize(request, &payload) != rpc::ErrorCode::NO_ERROR) - status.SetError(EIO); - return status; -} - -Status<void> ReceiveData(const BorrowedHandle& socket_fd, void* data, - size_t size); -Status<void> ReceiveDataVector(const BorrowedHandle& socket_fd, - const iovec* data, size_t count); - -size_t CountVectorSize(const iovec* data, size_t count); -void InitRequest(android::pdx::uds::RequestHeader<BorrowedHandle>* request, - int opcode, uint32_t send_len, uint32_t max_recv_len, - bool is_impulse); - -Status<void> WaitForEndpoint(const std::string& endpoint_path, - int64_t timeout_ms); - -} // namespace uds -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_UDS_IPC_HELPER_H_ diff --git a/libs/vr/libpdx_uds/private/uds/service_endpoint.h b/libs/vr/libpdx_uds/private/uds/service_endpoint.h deleted file mode 100644 index 50fc484862..0000000000 --- a/libs/vr/libpdx_uds/private/uds/service_endpoint.h +++ /dev/null @@ -1,168 +0,0 @@ -#ifndef ANDROID_PDX_UDS_SERVICE_ENDPOINT_H_ -#define ANDROID_PDX_UDS_SERVICE_ENDPOINT_H_ - -#include <sys/stat.h> -#include <map> -#include <memory> -#include <mutex> -#include <string> -#include <unordered_map> -#include <utility> -#include <vector> - -#include <pdx/service.h> -#include <pdx/service_endpoint.h> -#include <uds/channel_event_set.h> - -namespace android { -namespace pdx { -namespace uds { - -class Endpoint : public pdx::Endpoint { - public: - enum { - kIpcTag = 0x00736674, // 'uds' - }; - - // Blocking modes for service endpoint. Controls whether the epoll set is in - // blocking mode or not for message receive. - enum { - kBlocking = true, - kNonBlocking = false, - kDefaultBlocking = kNonBlocking, - }; - - enum : mode_t { - kDefaultMode = 0, - }; - - ~Endpoint() override = default; - - uint32_t GetIpcTag() const override { return kIpcTag; } - Status<void> SetService(Service* service) override; - Status<void> SetChannel(int channel_id, Channel* channel) override; - Status<void> CloseChannel(int channel_id) override; - Status<void> ModifyChannelEvents(int channel_id, int clear_mask, - int set_mask) override; - Status<RemoteChannelHandle> PushChannel(Message* message, int flags, - Channel* channel, - int* channel_id) override; - Status<int> CheckChannel(const Message* message, ChannelReference ref, - Channel** channel) override; - Status<void> MessageReceive(Message* message) override; - Status<void> MessageReply(Message* message, int return_code) override; - Status<void> MessageReplyFd(Message* message, unsigned int push_fd) override; - Status<void> MessageReplyChannelHandle( - Message* message, const LocalChannelHandle& handle) override; - Status<void> MessageReplyChannelHandle( - Message* message, const BorrowedChannelHandle& handle) override; - Status<void> MessageReplyChannelHandle( - Message* message, const RemoteChannelHandle& handle) override; - Status<size_t> ReadMessageData(Message* message, const iovec* vector, - size_t vector_length) override; - Status<size_t> WriteMessageData(Message* message, const iovec* vector, - size_t vector_length) override; - Status<FileReference> PushFileHandle(Message* message, - const LocalHandle& handle) override; - Status<FileReference> PushFileHandle(Message* message, - const BorrowedHandle& handle) override; - Status<FileReference> PushFileHandle(Message* message, - const RemoteHandle& handle) override; - Status<ChannelReference> PushChannelHandle( - Message* message, const LocalChannelHandle& handle) override; - Status<ChannelReference> PushChannelHandle( - Message* message, const BorrowedChannelHandle& handle) override; - Status<ChannelReference> PushChannelHandle( - Message* message, const RemoteChannelHandle& handle) override; - LocalHandle GetFileHandle(Message* message, FileReference ref) const override; - LocalChannelHandle GetChannelHandle(Message* message, - ChannelReference ref) const override; - - void* AllocateMessageState() override; - void FreeMessageState(void* state) override; - - Status<void> Cancel() override; - - // Open an endpoint at the given path. - // Second parameter is unused for UDS, but we have it here for compatibility - // in signature with servicefs::Endpoint::Create(). - // This method uses |endpoint_path| as a relative path to endpoint socket - // created by init process. - static std::unique_ptr<Endpoint> Create(const std::string& endpoint_path, - mode_t /*unused_mode*/ = kDefaultMode, - bool blocking = kDefaultBlocking); - - // Helper method to create an endpoint at the given UDS socket path. This - // method physically creates and binds a socket at that path. - static std::unique_ptr<Endpoint> CreateAndBindSocket( - const std::string& endpoint_path, bool blocking = kDefaultBlocking); - - // Helper method to create an endpoint from an existing socket FD. - // Mostly helpful for tests. - static std::unique_ptr<Endpoint> CreateFromSocketFd(LocalHandle socket_fd); - - // Test helper method to register a new channel identified by |channel_fd| - // socket file descriptor. - Status<void> RegisterNewChannelForTests(LocalHandle channel_fd); - - int epoll_fd() const override { return epoll_fd_.Get(); } - - private: - struct ChannelData { - LocalHandle data_fd; - ChannelEventSet event_set; - Channel* channel_state{nullptr}; - }; - - // This class must be instantiated using Create() static methods above. - Endpoint(const std::string& endpoint_path, bool blocking, - bool use_init_socket_fd = true); - explicit Endpoint(LocalHandle socket_fd); - - void Init(LocalHandle socket_fd); - - Endpoint(const Endpoint&) = delete; - void operator=(const Endpoint&) = delete; - - uint32_t GetNextAvailableMessageId() { - return next_message_id_.fetch_add(1, std::memory_order_relaxed); - } - - void BuildCloseMessage(int32_t channel_id, Message* message); - - Status<void> AcceptConnection(Message* message); - Status<void> ReceiveMessageForChannel(const BorrowedHandle& channel_fd, - Message* message); - Status<void> OnNewChannel(LocalHandle channel_fd); - Status<std::pair<int32_t, ChannelData*>> OnNewChannelLocked( - LocalHandle channel_fd, Channel* channel_state); - Status<void> CloseChannelLocked(int32_t channel_id); - Status<void> ReenableEpollEvent(const BorrowedHandle& channel_fd); - Channel* GetChannelState(int32_t channel_id); - BorrowedHandle GetChannelSocketFd(int32_t channel_id); - Status<std::pair<BorrowedHandle, BorrowedHandle>> GetChannelEventFd( - int32_t channel_id); - int32_t GetChannelId(const BorrowedHandle& channel_fd); - Status<void> CreateChannelSocketPair(LocalHandle* local_socket, - LocalHandle* remote_socket); - - std::string endpoint_path_; - bool is_blocking_; - LocalHandle socket_fd_; - LocalHandle cancel_event_fd_; - LocalHandle epoll_fd_; - - mutable std::mutex channel_mutex_; - std::map<int32_t, ChannelData> channels_; - std::map<int, int32_t> channel_fd_to_id_; - int32_t last_channel_id_{0}; - - Service* service_{nullptr}; - std::atomic<uint32_t> next_message_id_; -}; - -} // namespace uds -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_UDS_PDX_SERVICE_ENDPOINT_H_ diff --git a/libs/vr/libpdx_uds/remote_method_tests.cpp b/libs/vr/libpdx_uds/remote_method_tests.cpp deleted file mode 100644 index 4f0670ec09..0000000000 --- a/libs/vr/libpdx_uds/remote_method_tests.cpp +++ /dev/null @@ -1,951 +0,0 @@ -#include <errno.h> -#include <fcntl.h> -#include <unistd.h> - -#include <array> -#include <cstdint> -#include <memory> -#include <numeric> -#include <string> -#include <thread> - -#include <gtest/gtest.h> -#include <pdx/channel_handle.h> -#include <pdx/client.h> -#include <pdx/rpc/remote_method.h> -#include <pdx/rpc/serializable.h> -#include <pdx/service.h> -#include <pdx/service_dispatcher.h> -#include <uds/client_channel.h> -#include <uds/client_channel_factory.h> -#include <uds/service_endpoint.h> - -using android::pdx::BorrowedHandle; -using android::pdx::Channel; -using android::pdx::ClientBase; -using android::pdx::ErrorStatus; -using android::pdx::LocalChannelHandle; -using android::pdx::LocalHandle; -using android::pdx::Message; -using android::pdx::RemoteChannelHandle; -using android::pdx::RemoteHandle; -using android::pdx::ServiceBase; -using android::pdx::ServiceDispatcher; -using android::pdx::Status; -using android::pdx::uds::Endpoint; -using namespace android::pdx::rpc; - -namespace { - -std::string Rot13(const std::string& s) { - std::string text = s; - std::transform(std::begin(text), std::end(text), std::begin(text), - [](char c) -> char { - if (!std::isalpha(c)) { - return c; - } else { - const char pivot = std::isupper(c) ? 'A' : 'a'; - return (c - pivot + 13) % 26 + pivot; - } - }); - return text; -} - -// Defines a serializable user type that may be transferred between client and -// service. -struct TestType { - int a; - float b; - std::string c; - - TestType() {} - TestType(int a, float b, const std::string& c) : a(a), b(b), c(c) {} - - // Make gtest expressions simpler by defining equality operator. This is not - // needed for serialization. - bool operator==(const TestType& other) const { - return a == other.a && b == other.b && c == other.c; - } - - private: - PDX_SERIALIZABLE_MEMBERS(TestType, a, b, c); -}; - -struct DerivedTestType : public TestType { - DerivedTestType() : TestType() {} - DerivedTestType(int a, float b) : TestType(a, b, "constant") {} -}; - -// Defines a serializable user type with a LocalHandle member. -struct TestFdType { - int a; - LocalHandle fd; - - TestFdType() {} - TestFdType(int a, LocalHandle fd) : a(a), fd(std::move(fd)) {} - - private: - PDX_SERIALIZABLE_MEMBERS(TestFdType, a, fd); -}; - -// Defines a serializable user template type with a FileHandle member. -template <typename FileHandleType> -struct TestTemplateType { - FileHandleType fd; - - TestTemplateType() {} - explicit TestTemplateType(FileHandleType fd) : fd(std::move(fd)) {} - - private: - PDX_SERIALIZABLE_MEMBERS(TestTemplateType<FileHandleType>, fd); -}; - -struct BasicStruct { - int a; - int b; - std::string c; - - private: - PDX_SERIALIZABLE_MEMBERS(BasicStruct, a, b, c); -}; - -using BasicStructTraits = SerializableTraits<BasicStruct>; - -struct NonSerializableType { - int a; - int b; - std::string c; -}; - -struct IncorrectlyDefinedSerializableType { - int a; - int b; - - private: - using SerializableMembers = std::tuple<int, int>; -}; - -// Defines the contract between the client and service, including ServiceFS -// endpoint path, method opcodes, and remote method signatures. -struct TestInterface final { - // Service path. - static constexpr char kClientPath[] = "socket_test"; - - // Op codes. - enum { - kOpAdd = 0, - kOpFoo, - kOpConcatenate, - kOpWriteBuffer, - kOpStringLength, - kOpSendTestType, - kOpSendBasicStruct, - kOpSendVector, - kOpRot13, - kOpNoArgs, - kOpSendFile, - kOpGetFile, - kOpGetTestFdType, - kOpOpenFiles, - kOpReadFile, - kOpPushChannel, - kOpPositive, - }; - - // Methods. - PDX_REMOTE_METHOD(Add, kOpAdd, int(int, int)); - PDX_REMOTE_METHOD(Foo, kOpFoo, int(int, const std::string&)); - PDX_REMOTE_METHOD(Concatenate, kOpConcatenate, - std::string(const std::string&, const std::string&)); - PDX_REMOTE_METHOD(SumVector, kOpWriteBuffer, int(const std::vector<int>&)); - PDX_REMOTE_METHOD(StringLength, kOpStringLength, int(const std::string&)); - PDX_REMOTE_METHOD(SendTestType, kOpSendTestType, TestType(const TestType&)); - PDX_REMOTE_METHOD(SendBasicStruct, kOpSendBasicStruct, - BasicStruct(const BasicStruct&)); - PDX_REMOTE_METHOD(SendVector, kOpSendVector, - std::string(const std::vector<TestType>&)); - PDX_REMOTE_METHOD(Rot13, kOpRot13, std::string(const std::string&)); - PDX_REMOTE_METHOD(NoArgs, kOpNoArgs, int(Void)); - PDX_REMOTE_METHOD(SendFile, kOpSendFile, int(const LocalHandle& fd)); - PDX_REMOTE_METHOD(GetFile, kOpGetFile, LocalHandle(const std::string&, int)); - PDX_REMOTE_METHOD(GetTestFdType, kOpGetTestFdType, - TestFdType(int, const std::string&, int)); - PDX_REMOTE_METHOD(OpenFiles, kOpOpenFiles, - std::vector<LocalHandle>( - const std::vector<std::pair<std::string, int>>&)); - PDX_REMOTE_METHOD(ReadFile, kOpReadFile, - std::pair<int, BufferWrapper<std::uint8_t*>>( - const std::string&, int, std::size_t)); - PDX_REMOTE_METHOD(PushChannel, kOpPushChannel, LocalChannelHandle(Void)); - PDX_REMOTE_METHOD(Positive, kOpPositive, void(int)); - - PDX_REMOTE_API(API, Add, Foo, Concatenate, SumVector, StringLength, - SendTestType, SendVector, Rot13, NoArgs, SendFile, GetFile, - GetTestFdType, OpenFiles, PushChannel, Positive); -}; - -constexpr char TestInterface::kClientPath[]; - -// Test client to send messages to the test service. -class TestClient : public ClientBase<TestClient> { - public: - int Add(int a, int b) { - return ReturnStatusOrError(InvokeRemoteMethod<TestInterface::Add>(a, b)); - } - - int Foo(int a, const std::string& b) { - return ReturnStatusOrError(InvokeRemoteMethod<TestInterface::Foo>(a, b)); - } - - std::string Concatenate(const std::string& a, const std::string& b) { - std::string return_value; - - Status<std::string> status = - InvokeRemoteMethod<TestInterface::Concatenate>(a, b); - if (!status) - return std::string("[Error]"); - else - return status.take(); - } - - int SumVector(const int* buffer, std::size_t size) { - return ReturnStatusOrError( - InvokeRemoteMethod<TestInterface::SumVector>(WrapArray(buffer, size))); - } - - int SumVector(const std::vector<int>& buffer) { - return ReturnStatusOrError( - InvokeRemoteMethod<TestInterface::SumVector>(buffer)); - } - - int StringLength(const char* string, std::size_t size) { - return ReturnStatusOrError(InvokeRemoteMethod<TestInterface::StringLength>( - WrapString(string, size))); - } - - int StringLength(const std::string& string) { - return ReturnStatusOrError( - InvokeRemoteMethod<TestInterface::StringLength>(string)); - } - - TestType SendTestType(const TestType& tt) { - Status<TestType> status = - InvokeRemoteMethod<TestInterface::SendTestType>(tt); - if (!status) - return TestType(0, 0.0, "[Error]"); - else - return status.take(); - } - - BasicStruct SendBasicStruct(const BasicStruct& bs) { - Status<BasicStruct> status = - InvokeRemoteMethod<TestInterface::SendBasicStruct>(bs); - if (!status) - return BasicStruct{0, 0, "[Error]"}; - else - return status.take(); - } - - std::string SendVector(const std::vector<TestType>& v) { - Status<std::string> status = - InvokeRemoteMethod<TestInterface::SendVector>(v); - if (!status) - return "[Error]"; - else - return status.take(); - } - - std::string Rot13(const std::string& string) { - Status<std::string> status = - InvokeRemoteMethod<TestInterface::Rot13>(string); - return status ? status.get() : string; - } - - int NoArgs() { - return ReturnStatusOrError(InvokeRemoteMethod<TestInterface::NoArgs>()); - } - - int SendFile(const LocalHandle& fd) { - return ReturnStatusOrError(InvokeRemoteMethod<TestInterface::SendFile>(fd)); - } - - LocalHandle GetFile(const std::string& path, int mode) { - Status<LocalHandle> status = - InvokeRemoteMethod<TestInterface::GetFile>(path, mode); - if (!status) - return LocalHandle(-status.error()); - else - return status.take(); - } - - int GetFile(const std::string& path, int mode, LocalHandle* fd_out) { - Status<void> status = - InvokeRemoteMethodInPlace<TestInterface::GetFile>(fd_out, path, mode); - return status ? 0 : -status.error(); - } - - TestFdType GetTestFdType(int a, const std::string& path, int mode) { - Status<TestFdType> status = - InvokeRemoteMethod<TestInterface::GetTestFdType>(a, path, mode); - if (!status) - return {}; - else - return status.take(); - } - - std::vector<LocalHandle> OpenFiles( - const std::vector<std::pair<std::string, int>>& file_specs) { - Status<std::vector<LocalHandle>> status = - InvokeRemoteMethod<TestInterface::OpenFiles>(file_specs); - if (!status) - return {}; - else - return status.take(); - } - - int ReadFile(void* buffer, std::size_t size, const std::string& path, - int mode) { - auto buffer_wrapper = WrapBuffer(buffer, size); - auto return_value = std::make_pair(-1, buffer_wrapper); - - Status<void> status = InvokeRemoteMethodInPlace<TestInterface::ReadFile>( - &return_value, path, mode, size); - return status ? return_value.first : -status.error(); - } - - int PushChannel(LocalChannelHandle* fd_out) { - auto status = InvokeRemoteMethodInPlace<TestInterface::PushChannel>(fd_out); - return status ? 0 : -status.error(); - } - - bool Positive(int test_value) { - auto status = InvokeRemoteMethod<TestInterface::Positive>(test_value); - return status.ok(); - } - - int GetFd() const { return event_fd(); } - - private: - friend BASE; - - explicit TestClient(LocalChannelHandle channel_handle) - : BASE{android::pdx::uds::ClientChannel::Create( - std::move(channel_handle))} {} - TestClient() - : BASE{android::pdx::uds::ClientChannelFactory::Create( - TestInterface::kClientPath)} {} - - TestClient(const TestClient&) = delete; - void operator=(const TestClient&) = delete; -}; - -// Test service that encodes/decodes messages from clients. -class TestService : public ServiceBase<TestService> { - public: - Status<void> HandleMessage(Message& message) override { - switch (message.GetOp()) { - case TestInterface::Add::Opcode: - DispatchRemoteMethod<TestInterface::Add>(*this, &TestService::OnAdd, - message); - return {}; - - case TestInterface::Foo::Opcode: - DispatchRemoteMethod<TestInterface::Foo>(*this, &TestService::OnFoo, - message); - return {}; - - case TestInterface::Concatenate::Opcode: - DispatchRemoteMethod<TestInterface::Concatenate>( - *this, &TestService::OnConcatenate, message); - return {}; - - case TestInterface::SumVector::Opcode: - DispatchRemoteMethod<TestInterface::SumVector>( - *this, &TestService::OnSumVector, message); - return {}; - - case TestInterface::StringLength::Opcode: - DispatchRemoteMethod<TestInterface::StringLength>( - *this, &TestService::OnStringLength, message); - return {}; - - case TestInterface::SendTestType::Opcode: - DispatchRemoteMethod<TestInterface::SendTestType>( - *this, &TestService::OnSendTestType, message); - return {}; - - case TestInterface::SendVector::Opcode: - DispatchRemoteMethod<TestInterface::SendVector>( - *this, &TestService::OnSendVector, message); - return {}; - - case TestInterface::Rot13::Opcode: - DispatchRemoteMethod<TestInterface::Rot13>(*this, &TestService::OnRot13, - message); - return {}; - - case TestInterface::NoArgs::Opcode: - DispatchRemoteMethod<TestInterface::NoArgs>( - *this, &TestService::OnNoArgs, message); - return {}; - - case TestInterface::SendFile::Opcode: - DispatchRemoteMethod<TestInterface::SendFile>( - *this, &TestService::OnSendFile, message); - return {}; - - case TestInterface::GetFile::Opcode: - DispatchRemoteMethod<TestInterface::GetFile>( - *this, &TestService::OnGetFile, message); - return {}; - - case TestInterface::GetTestFdType::Opcode: - DispatchRemoteMethod<TestInterface::GetTestFdType>( - *this, &TestService::OnGetTestFdType, message); - return {}; - - case TestInterface::OpenFiles::Opcode: - DispatchRemoteMethod<TestInterface::OpenFiles>( - *this, &TestService::OnOpenFiles, message); - return {}; - - case TestInterface::ReadFile::Opcode: - DispatchRemoteMethod<TestInterface::ReadFile>( - *this, &TestService::OnReadFile, message); - return {}; - - case TestInterface::PushChannel::Opcode: - DispatchRemoteMethod<TestInterface::PushChannel>( - *this, &TestService::OnPushChannel, message); - return {}; - - case TestInterface::Positive::Opcode: - DispatchRemoteMethod<TestInterface::Positive>( - *this, &TestService::OnPositive, message); - return {}; - - default: - return Service::DefaultHandleMessage(message); - } - } - - private: - friend BASE; - - TestService() - : BASE("TestService", - Endpoint::CreateAndBindSocket(TestInterface::kClientPath)) {} - - int OnAdd(Message&, int a, int b) { return a + b; } - - int OnFoo(Message&, int a, const std::string& b) { return a + b.length(); } - - std::string OnConcatenate(Message&, const std::string& a, - const std::string& b) { - return a + b; - } - - int OnSumVector(Message&, const std::vector<int>& vector) { - return std::accumulate(vector.begin(), vector.end(), 0); - } - - int OnStringLength(Message&, const std::string& string) { - return string.length(); - } - - TestType OnSendTestType(Message&, const TestType& tt) { - return TestType(tt.a + 20, tt.b - 2.0, tt.c + "foo"); - } - - std::string OnSendVector(Message&, const std::vector<TestType>& v) { - std::string return_value = ""; - - for (const auto& tt : v) - return_value += tt.c; - - return return_value; - } - - Status<std::string> OnRot13(Message&, const std::string& s) { - return {Rot13(s)}; - } - - int OnNoArgs(Message&) { return 1; } - - int OnSendFile(Message&, const LocalHandle& fd) { return fd.Get(); } - - LocalHandle OnGetFile(Message& message, const std::string& path, int mode) { - LocalHandle fd(path.c_str(), mode); - if (!fd) - message.ReplyError(errno); - return fd; - } - - TestFdType OnGetTestFdType(Message& message, int a, const std::string& path, - int mode) { - TestFdType return_value(a, LocalHandle(path, mode)); - if (!return_value.fd) - message.ReplyError(errno); - return return_value; - } - - std::vector<LocalHandle> OnOpenFiles( - Message&, const std::vector<std::pair<std::string, int>>& file_specs) { - std::vector<LocalHandle> return_value; - for (auto& spec : file_specs) { - LocalHandle fd(spec.first, spec.second); - if (fd) - return_value.emplace_back(std::move(fd)); - else - return_value.emplace_back(-errno); - } - return return_value; - } - - std::pair<int, BufferWrapper<std::vector<std::uint8_t>>> OnReadFile( - Message& message, const std::string& path, int mode, std::size_t length) { - std::pair<int, BufferWrapper<std::vector<std::uint8_t>>> return_value; - LocalHandle fd(path, mode); - if (!fd) { - message.ReplyError(errno); - return return_value; - } - - return_value.second.reserve(length); - const int ret = read(fd.Get(), return_value.second.data(), length); - if (ret < 0) { - message.ReplyError(errno); - return return_value; - } - - return_value.second.resize(ret); - return_value.first = ret; - return return_value; - } - - RemoteChannelHandle OnPushChannel(Message& message) { - auto status = message.PushChannel(0, nullptr, nullptr); - if (!status) { - message.ReplyError(status.error()); - return {}; - } - return status.take(); - } - - Status<void> OnPositive(Message& /*message*/, int test_value) { - if (test_value >= 0) - return {}; - else - return ErrorStatus(EINVAL); - } - - TestService(const TestService&) = delete; - void operator=(const TestService&) = delete; -}; - -} // anonymous namespace - -// Use a test fixture to ensure proper order of cleanup between clients, -// services, and the dispatcher. As these objects are cleaned up in the same -// thread, either the service or client must be destroyed before stopping the -// dispatcher. The reason for this is that clients send blocking "close" -// messages to their respective services on destruction. If this happens after -// stopping the dispatcher the client destructor will get blocked waiting for a -// reply that will never come. In normal use of the service framework this is -// never an issue because clients and the dispatcher for the same service are -// never destructed in the same thread (they live in different processes). -class RemoteMethodTest : public ::testing::Test { - protected: - std::unique_ptr<ServiceDispatcher> dispatcher_; - std::thread dispatch_thread_; - - void SetUp() override { - // Create a dispatcher to handle messages to services. - dispatcher_ = android::pdx::ServiceDispatcher::Create(); - ASSERT_NE(nullptr, dispatcher_); - - // Start the message dispatch loop in a separate thread. - dispatch_thread_ = std::thread( - std::bind(&ServiceDispatcher::EnterDispatchLoop, dispatcher_.get())); - } - - void TearDown() override { - if (dispatcher_) { - // Cancel the dispatcher and wait for the thread to terminate. - // Explicitly - // join the thread so that destruction doesn't deallocate the - // dispatcher - // before the thread finishes. - dispatcher_->SetCanceled(true); - dispatch_thread_.join(); - } - } -}; - -// Test basic operation of TestService/TestClient classes. -TEST_F(RemoteMethodTest, BasicClientService) { - // Create a test service and add it to the dispatcher. - - auto service = TestService::Create(); - ASSERT_NE(nullptr, service); - ASSERT_EQ(0, dispatcher_->AddService(service)); - - // Create a client to service. - auto client = TestClient::Create(); - ASSERT_NE(nullptr, client); - - const int sum = client->Add(10, 25); - EXPECT_GE(35, sum); - - const auto cat = client->Concatenate("This is a string", ", that it is."); - EXPECT_EQ("This is a string, that it is.", cat); - - std::string alphabet = "abcdefghijklmnopqrstuvwxyz"; - const auto rot13_alphabet = client->Rot13(alphabet); - EXPECT_EQ(Rot13(alphabet), rot13_alphabet); - - const auto length = client->Foo(10, "123"); - EXPECT_EQ(13, length); - - const std::vector<int> vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - const int vector_sum = client->SumVector(vector.data(), vector.size()); - const int vector_sum2 = client->SumVector(vector); - EXPECT_EQ(std::accumulate(vector.begin(), vector.end(), 0), vector_sum); - EXPECT_EQ(std::accumulate(vector.begin(), vector.end(), 0), vector_sum2); - - const auto string_length1 = client->StringLength("This is a string"); - EXPECT_EQ(16, string_length1); - - const auto string_length2 = client->StringLength("1234567890"); - EXPECT_EQ(10, string_length2); - - std::string string = "1234567890"; - const auto string_length3 = - client->StringLength(string.c_str(), string.length()); - EXPECT_EQ(10, string_length3); - - TestType tt{10, 0.0, "string"}; - const auto tt_result = client->SendTestType(tt); - EXPECT_EQ(TestType(30, -2.0, "stringfoo"), tt_result); - - std::vector<TestType> ttv = {TestType(0, 0.0, "abc"), - TestType(0, 0.0, "123")}; - const std::string string_result = client->SendVector(ttv); - EXPECT_EQ("abc123", string_result); - - const int int_result = client->NoArgs(); - EXPECT_EQ(1, int_result); -} - -TEST_F(RemoteMethodTest, LocalHandle) { - // Create a test service and add it to the dispatcher. - auto service = TestService::Create(); - ASSERT_NE(nullptr, service); - ASSERT_EQ(0, dispatcher_->AddService(service)); - - // Create a client to service. - auto client = TestClient::Create(); - ASSERT_NE(nullptr, client); - - LocalHandle fd("/dev/zero", O_RDONLY); - ASSERT_TRUE(fd.IsValid()); - - int fd_result = client->SendFile(fd); - EXPECT_LE(0, fd_result); - EXPECT_NE(fd.Get(), fd_result); - fd = LocalHandle(-3); - fd_result = client->SendFile(fd); - EXPECT_EQ(fd.Get(), fd_result); - - fd = client->GetFile("/dev/zero", O_RDONLY); - ASSERT_TRUE(fd.IsValid()) << "Error code: " << fd.Get(); - - std::array<uint8_t, 10> buffer; - buffer.fill(1); - EXPECT_EQ(10, read(fd.Get(), buffer.data(), buffer.size())); - EXPECT_EQ(buffer, decltype(buffer){{0}}); - fd.Close(); - - const int error = client->GetFile("/dev/zero", O_RDONLY, &fd); - EXPECT_EQ(0, error); - EXPECT_TRUE(fd.IsValid()); - - buffer.fill(1); - EXPECT_EQ(10, read(fd.Get(), buffer.data(), buffer.size())); - EXPECT_EQ(buffer, decltype(buffer){{0}}); - - /* - Seg fault. - fd = client->GetFile("/dev/foobar", O_RDONLY); - EXPECT_FALSE(fd.IsValid()); - */ -} - -TEST_F(RemoteMethodTest, PushChannel) { - // Create a test service and add it to the dispatcher. - auto service = TestService::Create(); - ASSERT_NE(nullptr, service); - ASSERT_EQ(0, dispatcher_->AddService(service)); - - // Create a client to service. - auto client = TestClient::Create(); - ASSERT_NE(nullptr, client); - - // Get a new channel as an fd. - LocalChannelHandle channel; - const int ret = client->PushChannel(&channel); - EXPECT_EQ(0, ret); - EXPECT_TRUE(channel.valid()); - - // Create a new client from the channel. - auto client2 = TestClient::Create(std::move(channel)); - ASSERT_NE(nullptr, client2); - - // Test that the new channel works. - const int sum = client2->Add(10, 25); - EXPECT_GE(35, sum); -} - -TEST_F(RemoteMethodTest, Positive) { - // Create a test service and add it to the dispatcher. - auto service = TestService::Create(); - ASSERT_NE(nullptr, service); - ASSERT_EQ(0, dispatcher_->AddService(service)); - - // Create a client to service. - auto client = TestClient::Create(); - ASSERT_NE(nullptr, client); - - ASSERT_TRUE(client->Positive(0)); - ASSERT_TRUE(client->Positive(1)); - ASSERT_FALSE(client->Positive(-1)); -} - -TEST_F(RemoteMethodTest, AggregateLocalHandle) { - // Create a test service and add it to the dispatcher. - auto service = TestService::Create(); - ASSERT_NE(nullptr, service); - ASSERT_EQ(0, dispatcher_->AddService(service)); - - // Create a client to service. - auto client = TestClient::Create(); - ASSERT_NE(nullptr, client); - - TestFdType result = client->GetTestFdType(10, "/dev/zero", O_RDONLY); - EXPECT_TRUE(result.fd.IsValid()); - EXPECT_EQ(10, result.a); - - std::vector<LocalHandle> files = - client->OpenFiles({{{"/dev/zero", O_RDONLY}, - {"/dev/null", O_WRONLY}, - {"/dev/zero", O_RDONLY}}}); - ASSERT_EQ(3u, files.size()); - EXPECT_TRUE(files[0].IsValid()); - EXPECT_TRUE(files[1].IsValid()); - EXPECT_TRUE(files[2].IsValid()); -} - -TEST_F(RemoteMethodTest, BufferWrapper) { - // Create a test service and add it to the dispatcher. - auto service = TestService::Create(); - ASSERT_NE(nullptr, service); - ASSERT_EQ(0, dispatcher_->AddService(service)); - - // Create a client to service. - auto client = TestClient::Create(); - ASSERT_NE(nullptr, client); - - const int buffer_size = 20; - std::vector<std::uint8_t> buffer(buffer_size, 'x'); - std::vector<std::uint8_t> expected(buffer_size, 0); - int ret = - client->ReadFile(buffer.data(), buffer.size(), "/dev/zero", O_RDONLY); - EXPECT_EQ(buffer_size, ret); - EXPECT_EQ(expected, buffer); -} - -// -// RemoteMethodFramework: Tests the type-based framework that remote method -// support is built upon. -// - -// Test logical And template. -TEST(RemoteMethodFramework, And) { - EXPECT_TRUE((And<std::true_type, std::true_type>::value)); - EXPECT_FALSE((And<std::true_type, std::false_type>::value)); - EXPECT_FALSE((And<std::false_type, std::true_type>::value)); - EXPECT_FALSE((And<std::false_type, std::false_type>::value)); - - EXPECT_TRUE((And<std::true_type, std::true_type, std::true_type>::value)); - EXPECT_FALSE((And<std::true_type, std::true_type, std::false_type>::value)); - EXPECT_FALSE((And<std::true_type, std::false_type, std::true_type>::value)); - EXPECT_FALSE((And<std::true_type, std::false_type, std::false_type>::value)); - EXPECT_FALSE((And<std::false_type, std::true_type, std::true_type>::value)); - EXPECT_FALSE((And<std::false_type, std::true_type, std::false_type>::value)); - EXPECT_FALSE((And<std::false_type, std::false_type, std::true_type>::value)); - EXPECT_FALSE((And<std::false_type, std::false_type, std::false_type>::value)); -} - -// Test convertible type constraints. -TEST(RemoteMethodFramework, IsConvertible) { - // std::pair. - EXPECT_TRUE( - (IsConvertible<std::pair<int, float>, std::pair<int, float>>::value)); - EXPECT_FALSE( - (IsConvertible<std::pair<int, float>, std::pair<float, float>>::value)); - EXPECT_FALSE( - (IsConvertible<std::pair<int, float>, std::pair<float, int>>::value)); - - // Nested std::pair. - EXPECT_TRUE((IsConvertible<std::pair<std::pair<int, float>, float>, - std::pair<std::pair<int, float>, float>>::value)); - EXPECT_FALSE((IsConvertible<std::pair<std::pair<int, float>, float>, - std::pair<std::pair<float, int>, float>>::value)); - - // std::tuple and std::pair. - EXPECT_TRUE( - (IsConvertible<std::pair<int, float>, std::tuple<int, float>>::value)); - EXPECT_TRUE( - (IsConvertible<std::tuple<int, float>, std::pair<int, float>>::value)); - EXPECT_FALSE( - (IsConvertible<std::pair<float, float>, std::tuple<int, float>>::value)); - EXPECT_FALSE( - (IsConvertible<std::tuple<float, float>, std::pair<int, float>>::value)); - EXPECT_FALSE( - (IsConvertible<std::pair<int, int>, std::tuple<int, float>>::value)); - EXPECT_FALSE( - (IsConvertible<std::tuple<int, int>, std::pair<int, float>>::value)); - EXPECT_FALSE( - (IsConvertible<std::pair<int, int>, std::tuple<int, int, int>>::value)); - EXPECT_FALSE( - (IsConvertible<std::tuple<int, int, int>, std::pair<int, int>>::value)); - - // std::vector. - EXPECT_TRUE((IsConvertible<std::vector<int>, std::vector<int>>::value)); - EXPECT_FALSE((IsConvertible<std::vector<int>, std::vector<float>>::value)); - - // Nested std::vector. - EXPECT_TRUE((IsConvertible<std::vector<std::pair<int, int>>, - std::vector<std::pair<int, int>>>::value)); - EXPECT_FALSE((IsConvertible<std::vector<std::pair<int, int>>, - std::vector<std::pair<int, float>>>::value)); - EXPECT_FALSE((IsConvertible<std::vector<std::pair<int, int>>, - std::vector<std::pair<float, int>>>::value)); - EXPECT_FALSE((IsConvertible<std::vector<std::pair<int, int>>, - std::vector<std::pair<float, float>>>::value)); - - // std::vector with nested convertible types. - EXPECT_TRUE((IsConvertible<std::vector<StringWrapper<char>>, - std::vector<std::string>>::value)); - - // std::map and std::unordered_map. - EXPECT_TRUE((IsConvertible<std::map<int, float>, - std::unordered_map<int, float>>::value)); - EXPECT_FALSE((IsConvertible<std::map<float, float>, - std::unordered_map<int, float>>::value)); - EXPECT_FALSE((IsConvertible<std::map<float, float>, - std::unordered_map<float, int>>::value)); - EXPECT_FALSE((IsConvertible<std::map<float, float>, - std::unordered_map<int, int>>::value)); - EXPECT_TRUE((IsConvertible<std::unordered_map<int, float>, - std::map<int, float>>::value)); - EXPECT_FALSE((IsConvertible<std::unordered_map<float, float>, - std::map<int, float>>::value)); - EXPECT_FALSE((IsConvertible<std::unordered_map<float, float>, - std::map<float, int>>::value)); - EXPECT_FALSE((IsConvertible<std::unordered_map<float, float>, - std::map<int, int>>::value)); - - // std::map with nested convertible types. - EXPECT_TRUE((IsConvertible<std::map<int, std::string>, - std::map<int, StringWrapper<char>>>::value)); - EXPECT_TRUE( - (IsConvertible<std::map<std::tuple<int, int>, std::string>, - std::map<std::pair<int, int>, std::string>>::value)); - - // std::unordered_map with nested convertible types. - EXPECT_TRUE( - (IsConvertible<std::unordered_map<int, std::string>, - std::unordered_map<int, StringWrapper<char>>>::value)); - EXPECT_TRUE((IsConvertible< - std::unordered_map<std::tuple<int, int>, std::string>, - std::unordered_map<std::pair<int, int>, std::string>>::value)); - - // std::string. - EXPECT_TRUE((IsConvertible<std::string, std::string>::value)); - EXPECT_FALSE((IsConvertible<std::string, int>::value)); - EXPECT_FALSE((IsConvertible<int, std::string>::value)); - - // Nested std::string. - EXPECT_TRUE((IsConvertible<std::pair<std::string, std::string>, - std::pair<std::string, std::string>>::value)); - EXPECT_FALSE((IsConvertible<std::pair<std::string, std::string>, - std::pair<std::string, int>>::value)); - EXPECT_FALSE((IsConvertible<std::pair<std::string, std::string>, - std::pair<int, std::string>>::value)); - EXPECT_FALSE((IsConvertible<std::pair<std::string, std::string>, - std::pair<int, int>>::value)); - - // StringWrapper. - EXPECT_TRUE((IsConvertible<StringWrapper<char>, StringWrapper<char>>::value)); - EXPECT_TRUE((IsConvertible<StringWrapper<char>, std::string>::value)); - EXPECT_TRUE((IsConvertible<std::string, StringWrapper<char>>::value)); - EXPECT_FALSE((IsConvertible<StringWrapper<char>, int>::value)); - EXPECT_FALSE( - (IsConvertible<StringWrapper<char>, BufferWrapper<char*>>::value)); - - // BufferWrapper. - EXPECT_TRUE( - (IsConvertible<BufferWrapper<char*>, BufferWrapper<char*>>::value)); - EXPECT_TRUE( - (IsConvertible<BufferWrapper<char*>, BufferWrapper<const char*>>::value)); - EXPECT_FALSE( - (IsConvertible<BufferWrapper<char*>, BufferWrapper<int*>>::value)); - EXPECT_TRUE((IsConvertible<BufferWrapper<char*>, - BufferWrapper<std::vector<char>>>::value)); - - // RemoteHandle and BorrowedHandle. - EXPECT_TRUE((IsConvertible<LocalHandle, RemoteHandle>::value)); - EXPECT_TRUE((IsConvertible<LocalHandle, BorrowedHandle>::value)); - - // Test rewriting user defined types. - EXPECT_TRUE((IsConvertible<TestTemplateType<LocalHandle>, - TestTemplateType<RemoteHandle>>::value)); - EXPECT_TRUE((IsConvertible<TestTemplateType<LocalHandle>, - TestTemplateType<BorrowedHandle>>::value)); - EXPECT_FALSE((IsConvertible<TestTemplateType<RemoteHandle>, - TestTemplateType<LocalHandle>>::value)); - EXPECT_FALSE((IsConvertible<TestTemplateType<BorrowedHandle>, - TestTemplateType<LocalHandle>>::value)); - - // TODO(eieio): More thorough testing of convertible types. -} - -TEST(RemoteMethodFramework, SerializableMembers) { - EXPECT_TRUE(HasSerializableMembers<TestTemplateType<LocalHandle>>::value); - EXPECT_TRUE(HasSerializableMembers<TestTemplateType<RemoteHandle>>::value); - EXPECT_TRUE(HasSerializableMembers<TestTemplateType<BorrowedHandle>>::value); - - EXPECT_TRUE(std::is_void<EnableIfHasSerializableMembers< - TestTemplateType<LocalHandle>>>::value); - EXPECT_TRUE(std::is_void<EnableIfHasSerializableMembers< - TestTemplateType<RemoteHandle>>>::value); - EXPECT_TRUE(std::is_void<EnableIfHasSerializableMembers< - TestTemplateType<BorrowedHandle>>>::value); - - EXPECT_TRUE(HasSerializableMembers<DerivedTestType>::value); - - EXPECT_TRUE(HasSerializableMembers<BasicStruct>::value); - EXPECT_TRUE(HasSerializableMembers<TestType>::value); - EXPECT_TRUE(HasSerializableMembers<TestTemplateType<LocalHandle>>::value); - EXPECT_TRUE(HasSerializableMembers<TestTemplateType<RemoteHandle>>::value); - EXPECT_TRUE(HasSerializableMembers<TestTemplateType<BorrowedHandle>>::value); - EXPECT_TRUE(HasSerializableMembers<DerivedTestType>::value); - EXPECT_FALSE(HasSerializableMembers<NonSerializableType>::value); - EXPECT_FALSE( - HasSerializableMembers<IncorrectlyDefinedSerializableType>::value); -} - -TEST(RemoteMethodFramework, RemoteAPITypes) { - EXPECT_EQ(0u, TestInterface::API::MethodIndex<TestInterface::Add>()); -} diff --git a/libs/vr/libpdx_uds/service_endpoint.cpp b/libs/vr/libpdx_uds/service_endpoint.cpp deleted file mode 100644 index 810eb196ca..0000000000 --- a/libs/vr/libpdx_uds/service_endpoint.cpp +++ /dev/null @@ -1,789 +0,0 @@ -#include "uds/service_endpoint.h" - -#include <poll.h> -#include <sys/epoll.h> -#include <sys/eventfd.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <algorithm> // std::min - -#include <android-base/logging.h> -#include <android-base/strings.h> -#include <cutils/sockets.h> -#include <pdx/service.h> -#include <selinux/selinux.h> -#include <uds/channel_manager.h> -#include <uds/client_channel_factory.h> -#include <uds/ipc_helper.h> - -namespace { - -constexpr int kMaxBackLogForSocketListen = 1; - -using android::pdx::BorrowedChannelHandle; -using android::pdx::BorrowedHandle; -using android::pdx::ChannelReference; -using android::pdx::ErrorStatus; -using android::pdx::FileReference; -using android::pdx::LocalChannelHandle; -using android::pdx::LocalHandle; -using android::pdx::Status; -using android::pdx::uds::ChannelInfo; -using android::pdx::uds::ChannelManager; - -struct MessageState { - bool GetLocalFileHandle(int index, LocalHandle* handle) { - if (index < 0) { - handle->Reset(index); - } else if (static_cast<size_t>(index) < request.file_descriptors.size()) { - *handle = std::move(request.file_descriptors[index]); - } else { - return false; - } - return true; - } - - bool GetLocalChannelHandle(int index, LocalChannelHandle* handle) { - if (index < 0) { - *handle = LocalChannelHandle{nullptr, index}; - } else if (static_cast<size_t>(index) < request.channels.size()) { - auto& channel_info = request.channels[index]; - *handle = ChannelManager::Get().CreateHandle( - std::move(channel_info.data_fd), - std::move(channel_info.pollin_event_fd), - std::move(channel_info.pollhup_event_fd)); - } else { - return false; - } - return true; - } - - Status<FileReference> PushFileHandle(BorrowedHandle handle) { - if (!handle) - return handle.Get(); - response.file_descriptors.push_back(std::move(handle)); - return response.file_descriptors.size() - 1; - } - - Status<ChannelReference> PushChannelHandle(BorrowedChannelHandle handle) { - if (!handle) - return handle.value(); - - if (auto* channel_data = - ChannelManager::Get().GetChannelData(handle.value())) { - ChannelInfo<BorrowedHandle> channel_info{ - channel_data->data_fd(), channel_data->pollin_event_fd(), - channel_data->pollhup_event_fd()}; - response.channels.push_back(std::move(channel_info)); - return response.channels.size() - 1; - } else { - return ErrorStatus{EINVAL}; - } - } - - Status<ChannelReference> PushChannelHandle(BorrowedHandle data_fd, - BorrowedHandle pollin_event_fd, - BorrowedHandle pollhup_event_fd) { - if (!data_fd || !pollin_event_fd || !pollhup_event_fd) - return ErrorStatus{EINVAL}; - ChannelInfo<BorrowedHandle> channel_info{std::move(data_fd), - std::move(pollin_event_fd), - std::move(pollhup_event_fd)}; - response.channels.push_back(std::move(channel_info)); - return response.channels.size() - 1; - } - - Status<size_t> WriteData(const iovec* vector, size_t vector_length) { - size_t size = 0; - for (size_t i = 0; i < vector_length; i++) { - const auto* data = reinterpret_cast<const uint8_t*>(vector[i].iov_base); - response_data.insert(response_data.end(), data, data + vector[i].iov_len); - size += vector[i].iov_len; - } - return size; - } - - Status<size_t> ReadData(const iovec* vector, size_t vector_length) { - size_t size_remaining = request_data.size() - request_data_read_pos; - size_t size = 0; - for (size_t i = 0; i < vector_length && size_remaining > 0; i++) { - size_t size_to_copy = std::min(size_remaining, vector[i].iov_len); - memcpy(vector[i].iov_base, request_data.data() + request_data_read_pos, - size_to_copy); - size += size_to_copy; - request_data_read_pos += size_to_copy; - size_remaining -= size_to_copy; - } - return size; - } - - android::pdx::uds::RequestHeader<LocalHandle> request; - android::pdx::uds::ResponseHeader<BorrowedHandle> response; - std::vector<LocalHandle> sockets_to_close; - std::vector<uint8_t> request_data; - size_t request_data_read_pos{0}; - std::vector<uint8_t> response_data; -}; - -} // anonymous namespace - -namespace android { -namespace pdx { -namespace uds { - -Endpoint::Endpoint(const std::string& endpoint_path, bool blocking, - bool use_init_socket_fd) - : endpoint_path_{ClientChannelFactory::GetEndpointPath(endpoint_path)}, - is_blocking_{blocking} { - LocalHandle fd; - if (use_init_socket_fd) { - // Cut off the /dev/socket/ prefix from the full socket path and use the - // resulting "name" to retrieve the file descriptor for the socket created - // by the init process. - constexpr char prefix[] = "/dev/socket/"; - CHECK(android::base::StartsWith(endpoint_path_, prefix)) - << "Endpoint::Endpoint: Socket name '" << endpoint_path_ - << "' must begin with '" << prefix << "'"; - std::string socket_name = endpoint_path_.substr(sizeof(prefix) - 1); - fd.Reset(android_get_control_socket(socket_name.c_str())); - CHECK(fd.IsValid()) - << "Endpoint::Endpoint: Unable to obtain the control socket fd for '" - << socket_name << "'"; - fcntl(fd.Get(), F_SETFD, FD_CLOEXEC); - } else { - fd.Reset(socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)); - CHECK(fd.IsValid()) << "Endpoint::Endpoint: Failed to create socket: " - << strerror(errno); - - sockaddr_un local; - local.sun_family = AF_UNIX; - strncpy(local.sun_path, endpoint_path_.c_str(), sizeof(local.sun_path)); - local.sun_path[sizeof(local.sun_path) - 1] = '\0'; - - unlink(local.sun_path); - int ret = - bind(fd.Get(), reinterpret_cast<sockaddr*>(&local), sizeof(local)); - CHECK_EQ(ret, 0) << "Endpoint::Endpoint: bind error: " << strerror(errno); - } - Init(std::move(fd)); -} - -Endpoint::Endpoint(LocalHandle socket_fd) { Init(std::move(socket_fd)); } - -void Endpoint::Init(LocalHandle socket_fd) { - if (socket_fd) { - CHECK_EQ(listen(socket_fd.Get(), kMaxBackLogForSocketListen), 0) - << "Endpoint::Endpoint: listen error: " << strerror(errno); - } - cancel_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK)); - CHECK(cancel_event_fd_.IsValid()) - << "Endpoint::Endpoint: Failed to create event fd: " << strerror(errno); - - epoll_fd_.Reset(epoll_create1(EPOLL_CLOEXEC)); - CHECK(epoll_fd_.IsValid()) - << "Endpoint::Endpoint: Failed to create epoll fd: " << strerror(errno); - - if (socket_fd) { - epoll_event socket_event; - socket_event.events = EPOLLIN | EPOLLRDHUP | EPOLLONESHOT; - socket_event.data.fd = socket_fd.Get(); - int ret = epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, socket_fd.Get(), - &socket_event); - CHECK_EQ(ret, 0) - << "Endpoint::Endpoint: Failed to add socket fd to epoll fd: " - << strerror(errno); - } - - epoll_event cancel_event; - cancel_event.events = EPOLLIN; - cancel_event.data.fd = cancel_event_fd_.Get(); - - int ret = epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, cancel_event_fd_.Get(), - &cancel_event); - CHECK_EQ(ret, 0) - << "Endpoint::Endpoint: Failed to add cancel event fd to epoll fd: " - << strerror(errno); - socket_fd_ = std::move(socket_fd); -} - -void* Endpoint::AllocateMessageState() { return new MessageState; } - -void Endpoint::FreeMessageState(void* state) { - delete static_cast<MessageState*>(state); -} - -Status<void> Endpoint::AcceptConnection(Message* message) { - if (!socket_fd_) - return ErrorStatus(EBADF); - - sockaddr_un remote; - socklen_t addrlen = sizeof(remote); - LocalHandle connection_fd{accept4(socket_fd_.Get(), - reinterpret_cast<sockaddr*>(&remote), - &addrlen, SOCK_CLOEXEC)}; - if (!connection_fd) { - ALOGE("Endpoint::AcceptConnection: failed to accept connection: %s", - strerror(errno)); - return ErrorStatus(errno); - } - - LocalHandle local_socket; - LocalHandle remote_socket; - auto status = CreateChannelSocketPair(&local_socket, &remote_socket); - if (!status) - return status; - - // Borrow the local channel handle before we move it into OnNewChannel(). - BorrowedHandle channel_handle = local_socket.Borrow(); - status = OnNewChannel(std::move(local_socket)); - if (!status) - return status; - - // Send the channel socket fd to the client. - ChannelConnectionInfo<LocalHandle> connection_info; - connection_info.channel_fd = std::move(remote_socket); - status = SendData(connection_fd.Borrow(), connection_info); - - if (status) { - // Get the CHANNEL_OPEN message from client over the channel socket. - status = ReceiveMessageForChannel(channel_handle, message); - } else { - CloseChannel(GetChannelId(channel_handle)); - } - - // Don't need the connection socket anymore. Further communication should - // happen over the channel socket. - shutdown(connection_fd.Get(), SHUT_WR); - return status; -} - -Status<void> Endpoint::SetService(Service* service) { - service_ = service; - return {}; -} - -Status<void> Endpoint::SetChannel(int channel_id, Channel* channel) { - std::lock_guard<std::mutex> autolock(channel_mutex_); - auto channel_data = channels_.find(channel_id); - if (channel_data == channels_.end()) - return ErrorStatus{EINVAL}; - channel_data->second.channel_state = channel; - return {}; -} - -Status<void> Endpoint::OnNewChannel(LocalHandle channel_fd) { - std::lock_guard<std::mutex> autolock(channel_mutex_); - Status<void> status; - status.PropagateError(OnNewChannelLocked(std::move(channel_fd), nullptr)); - return status; -} - -Status<std::pair<int32_t, Endpoint::ChannelData*>> Endpoint::OnNewChannelLocked( - LocalHandle channel_fd, Channel* channel_state) { - epoll_event event; - event.events = EPOLLIN | EPOLLRDHUP | EPOLLONESHOT; - event.data.fd = channel_fd.Get(); - if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, channel_fd.Get(), &event) < 0) { - ALOGE( - "Endpoint::OnNewChannelLocked: Failed to add channel to endpoint: %s\n", - strerror(errno)); - return ErrorStatus(errno); - } - ChannelData channel_data; - channel_data.data_fd = std::move(channel_fd); - channel_data.channel_state = channel_state; - for (;;) { - // Try new channel IDs until we find one which is not already in the map. - if (last_channel_id_++ == std::numeric_limits<int32_t>::max()) - last_channel_id_ = 1; - auto iter = channels_.lower_bound(last_channel_id_); - if (iter == channels_.end() || iter->first != last_channel_id_) { - channel_fd_to_id_.emplace(channel_data.data_fd.Get(), last_channel_id_); - iter = channels_.emplace_hint(iter, last_channel_id_, - std::move(channel_data)); - return std::make_pair(last_channel_id_, &iter->second); - } - } -} - -Status<void> Endpoint::ReenableEpollEvent(const BorrowedHandle& fd) { - epoll_event event; - event.events = EPOLLIN | EPOLLRDHUP | EPOLLONESHOT; - event.data.fd = fd.Get(); - if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_MOD, fd.Get(), &event) < 0) { - ALOGE( - "Endpoint::ReenableEpollEvent: Failed to re-enable channel to " - "endpoint: %s\n", - strerror(errno)); - return ErrorStatus(errno); - } - return {}; -} - -Status<void> Endpoint::CloseChannel(int channel_id) { - std::lock_guard<std::mutex> autolock(channel_mutex_); - return CloseChannelLocked(channel_id); -} - -Status<void> Endpoint::CloseChannelLocked(int32_t channel_id) { - ALOGD_IF(TRACE, "Endpoint::CloseChannelLocked: channel_id=%d", channel_id); - - auto iter = channels_.find(channel_id); - if (iter == channels_.end()) - return ErrorStatus{EINVAL}; - - int channel_fd = iter->second.data_fd.Get(); - Status<void> status; - epoll_event ee; // See BUGS in man 2 epoll_ctl. - if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_DEL, channel_fd, &ee) < 0) { - status.SetError(errno); - ALOGE( - "Endpoint::CloseChannelLocked: Failed to remove channel from endpoint: " - "%s\n", - strerror(errno)); - } else { - status.SetValue(); - } - - channel_fd_to_id_.erase(channel_fd); - channels_.erase(iter); - return status; -} - -Status<void> Endpoint::ModifyChannelEvents(int channel_id, int clear_mask, - int set_mask) { - std::lock_guard<std::mutex> autolock(channel_mutex_); - - auto search = channels_.find(channel_id); - if (search != channels_.end()) { - auto& channel_data = search->second; - channel_data.event_set.ModifyEvents(clear_mask, set_mask); - return {}; - } - - return ErrorStatus{EINVAL}; -} - -Status<void> Endpoint::CreateChannelSocketPair(LocalHandle* local_socket, - LocalHandle* remote_socket) { - Status<void> status; - char* endpoint_context = nullptr; - // Make sure the channel socket has the correct SELinux label applied. - // Here we get the label from the endpoint file descriptor, which should be - // something like "u:object_r:pdx_service_endpoint_socket:s0" and replace - // "endpoint" with "channel" to produce the channel label such as this: - // "u:object_r:pdx_service_channel_socket:s0". - if (fgetfilecon_raw(socket_fd_.Get(), &endpoint_context) > 0) { - std::string channel_context = endpoint_context; - freecon(endpoint_context); - const std::string suffix = "_endpoint_socket"; - auto pos = channel_context.find(suffix); - if (pos != std::string::npos) { - channel_context.replace(pos, suffix.size(), "_channel_socket"); - } else { - ALOGW( - "Endpoint::CreateChannelSocketPair: Endpoint security context '%s' " - "does not contain expected substring '%s'", - channel_context.c_str(), suffix.c_str()); - } - ALOGE_IF(setsockcreatecon_raw(channel_context.c_str()) == -1, - "Endpoint::CreateChannelSocketPair: Failed to set channel socket " - "security context: %s", - strerror(errno)); - } else { - ALOGE( - "Endpoint::CreateChannelSocketPair: Failed to obtain the endpoint " - "socket's security context: %s", - strerror(errno)); - } - - int channel_pair[2] = {}; - if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, channel_pair) == -1) { - ALOGE("Endpoint::CreateChannelSocketPair: Failed to create socket pair: %s", - strerror(errno)); - status.SetError(errno); - return status; - } - - setsockcreatecon_raw(nullptr); - - local_socket->Reset(channel_pair[0]); - remote_socket->Reset(channel_pair[1]); - - int optval = 1; - if (setsockopt(local_socket->Get(), SOL_SOCKET, SO_PASSCRED, &optval, - sizeof(optval)) == -1) { - ALOGE( - "Endpoint::CreateChannelSocketPair: Failed to enable the receiving of " - "the credentials for channel %d: %s", - local_socket->Get(), strerror(errno)); - status.SetError(errno); - } - return status; -} - -Status<RemoteChannelHandle> Endpoint::PushChannel(Message* message, - int /*flags*/, - Channel* channel, - int* channel_id) { - LocalHandle local_socket; - LocalHandle remote_socket; - auto status = CreateChannelSocketPair(&local_socket, &remote_socket); - if (!status) - return status.error_status(); - - std::lock_guard<std::mutex> autolock(channel_mutex_); - auto channel_data_status = - OnNewChannelLocked(std::move(local_socket), channel); - if (!channel_data_status) - return channel_data_status.error_status(); - - ChannelData* channel_data; - std::tie(*channel_id, channel_data) = channel_data_status.take(); - - // Flags are ignored for now. - // TODO(xiaohuit): Implement those. - - auto* state = static_cast<MessageState*>(message->GetState()); - Status<ChannelReference> ref = state->PushChannelHandle( - remote_socket.Borrow(), channel_data->event_set.pollin_event_fd(), - channel_data->event_set.pollhup_event_fd()); - if (!ref) - return ref.error_status(); - state->sockets_to_close.push_back(std::move(remote_socket)); - return RemoteChannelHandle{ref.get()}; -} - -Status<int> Endpoint::CheckChannel(const Message* /*message*/, - ChannelReference /*ref*/, - Channel** /*channel*/) { - // TODO(xiaohuit): Implement this. - return ErrorStatus(EFAULT); -} - -Channel* Endpoint::GetChannelState(int32_t channel_id) { - std::lock_guard<std::mutex> autolock(channel_mutex_); - auto channel_data = channels_.find(channel_id); - return (channel_data != channels_.end()) ? channel_data->second.channel_state - : nullptr; -} - -BorrowedHandle Endpoint::GetChannelSocketFd(int32_t channel_id) { - std::lock_guard<std::mutex> autolock(channel_mutex_); - BorrowedHandle handle; - auto channel_data = channels_.find(channel_id); - if (channel_data != channels_.end()) - handle = channel_data->second.data_fd.Borrow(); - return handle; -} - -Status<std::pair<BorrowedHandle, BorrowedHandle>> Endpoint::GetChannelEventFd( - int32_t channel_id) { - std::lock_guard<std::mutex> autolock(channel_mutex_); - auto channel_data = channels_.find(channel_id); - if (channel_data != channels_.end()) { - return {{channel_data->second.event_set.pollin_event_fd(), - channel_data->second.event_set.pollhup_event_fd()}}; - } - return ErrorStatus(ENOENT); -} - -int32_t Endpoint::GetChannelId(const BorrowedHandle& channel_fd) { - std::lock_guard<std::mutex> autolock(channel_mutex_); - auto iter = channel_fd_to_id_.find(channel_fd.Get()); - return (iter != channel_fd_to_id_.end()) ? iter->second : -1; -} - -Status<void> Endpoint::ReceiveMessageForChannel( - const BorrowedHandle& channel_fd, Message* message) { - RequestHeader<LocalHandle> request; - int32_t channel_id = GetChannelId(channel_fd); - auto status = ReceiveData(channel_fd.Borrow(), &request); - if (!status) { - if (status.error() == ESHUTDOWN) { - BuildCloseMessage(channel_id, message); - return {}; - } else { - CloseChannel(channel_id); - return status; - } - } - - MessageInfo info; - info.pid = request.cred.pid; - info.tid = -1; - info.cid = channel_id; - info.mid = request.is_impulse ? Message::IMPULSE_MESSAGE_ID - : GetNextAvailableMessageId(); - info.euid = request.cred.uid; - info.egid = request.cred.gid; - info.op = request.op; - info.flags = 0; - info.service = service_; - info.channel = GetChannelState(channel_id); - if (info.channel != nullptr) { - info.channel->SetActiveProcessId(request.cred.pid); - } - info.send_len = request.send_len; - info.recv_len = request.max_recv_len; - info.fd_count = request.file_descriptors.size(); - static_assert(sizeof(info.impulse) == request.impulse_payload.size(), - "Impulse payload sizes must be the same in RequestHeader and " - "MessageInfo"); - memcpy(info.impulse, request.impulse_payload.data(), - request.impulse_payload.size()); - *message = Message{info}; - auto* state = static_cast<MessageState*>(message->GetState()); - state->request = std::move(request); - if (state->request.send_len > 0 && !state->request.is_impulse) { - state->request_data.resize(state->request.send_len); - status = ReceiveData(channel_fd, state->request_data.data(), - state->request_data.size()); - } - - if (status && state->request.is_impulse) - status = ReenableEpollEvent(channel_fd); - - if (!status) { - if (status.error() == ESHUTDOWN) { - BuildCloseMessage(channel_id, message); - return {}; - } else { - CloseChannel(channel_id); - return status; - } - } - - return status; -} - -void Endpoint::BuildCloseMessage(int32_t channel_id, Message* message) { - ALOGD_IF(TRACE, "Endpoint::BuildCloseMessage: channel_id=%d", channel_id); - MessageInfo info; - info.pid = -1; - info.tid = -1; - info.cid = channel_id; - info.mid = GetNextAvailableMessageId(); - info.euid = -1; - info.egid = -1; - info.op = opcodes::CHANNEL_CLOSE; - info.flags = 0; - info.service = service_; - info.channel = GetChannelState(channel_id); - info.send_len = 0; - info.recv_len = 0; - info.fd_count = 0; - *message = Message{info}; -} - -Status<void> Endpoint::MessageReceive(Message* message) { - // Receive at most one event from the epoll set. This should prevent multiple - // dispatch threads from attempting to handle messages on the same socket at - // the same time. - epoll_event event; - int count = RETRY_EINTR( - epoll_wait(epoll_fd_.Get(), &event, 1, is_blocking_ ? -1 : 0)); - if (count < 0) { - ALOGE("Endpoint::MessageReceive: Failed to wait for epoll events: %s\n", - strerror(errno)); - return ErrorStatus{errno}; - } else if (count == 0) { - return ErrorStatus{ETIMEDOUT}; - } - - if (event.data.fd == cancel_event_fd_.Get()) { - return ErrorStatus{ESHUTDOWN}; - } - - if (socket_fd_ && event.data.fd == socket_fd_.Get()) { - auto status = AcceptConnection(message); - auto reenable_status = ReenableEpollEvent(socket_fd_.Borrow()); - if (!reenable_status) - return reenable_status; - return status; - } - - BorrowedHandle channel_fd{event.data.fd}; - return ReceiveMessageForChannel(channel_fd, message); -} - -Status<void> Endpoint::MessageReply(Message* message, int return_code) { - const int32_t channel_id = message->GetChannelId(); - auto channel_socket = GetChannelSocketFd(channel_id); - if (!channel_socket) - return ErrorStatus{EBADF}; - - auto* state = static_cast<MessageState*>(message->GetState()); - switch (message->GetOp()) { - case opcodes::CHANNEL_CLOSE: - return CloseChannel(channel_id); - - case opcodes::CHANNEL_OPEN: - if (return_code < 0) { - return CloseChannel(channel_id); - } else { - // Open messages do not have a payload and may not transfer any channels - // or file descriptors on behalf of the service. - state->response_data.clear(); - state->response.file_descriptors.clear(); - state->response.channels.clear(); - - // Return the channel event-related fds in a single ChannelInfo entry - // with an empty data_fd member. - auto status = GetChannelEventFd(channel_id); - if (!status) - return status.error_status(); - - auto handles = status.take(); - state->response.channels.push_back({BorrowedHandle(), - std::move(handles.first), - std::move(handles.second)}); - return_code = 0; - } - break; - } - - state->response.ret_code = return_code; - state->response.recv_len = state->response_data.size(); - auto status = SendData(channel_socket, state->response); - if (status && !state->response_data.empty()) { - status = SendData(channel_socket, state->response_data.data(), - state->response_data.size()); - } - - if (status) - status = ReenableEpollEvent(channel_socket); - - return status; -} - -Status<void> Endpoint::MessageReplyFd(Message* message, unsigned int push_fd) { - auto* state = static_cast<MessageState*>(message->GetState()); - auto ref = state->PushFileHandle(BorrowedHandle{static_cast<int>(push_fd)}); - if (!ref) - return ref.error_status(); - return MessageReply(message, ref.get()); -} - -Status<void> Endpoint::MessageReplyChannelHandle( - Message* message, const LocalChannelHandle& handle) { - auto* state = static_cast<MessageState*>(message->GetState()); - auto ref = state->PushChannelHandle(handle.Borrow()); - if (!ref) - return ref.error_status(); - return MessageReply(message, ref.get()); -} - -Status<void> Endpoint::MessageReplyChannelHandle( - Message* message, const BorrowedChannelHandle& handle) { - auto* state = static_cast<MessageState*>(message->GetState()); - auto ref = state->PushChannelHandle(handle.Duplicate()); - if (!ref) - return ref.error_status(); - return MessageReply(message, ref.get()); -} - -Status<void> Endpoint::MessageReplyChannelHandle( - Message* message, const RemoteChannelHandle& handle) { - return MessageReply(message, handle.value()); -} - -Status<size_t> Endpoint::ReadMessageData(Message* message, const iovec* vector, - size_t vector_length) { - auto* state = static_cast<MessageState*>(message->GetState()); - return state->ReadData(vector, vector_length); -} - -Status<size_t> Endpoint::WriteMessageData(Message* message, const iovec* vector, - size_t vector_length) { - auto* state = static_cast<MessageState*>(message->GetState()); - return state->WriteData(vector, vector_length); -} - -Status<FileReference> Endpoint::PushFileHandle(Message* message, - const LocalHandle& handle) { - auto* state = static_cast<MessageState*>(message->GetState()); - return state->PushFileHandle(handle.Borrow()); -} - -Status<FileReference> Endpoint::PushFileHandle(Message* message, - const BorrowedHandle& handle) { - auto* state = static_cast<MessageState*>(message->GetState()); - return state->PushFileHandle(handle.Duplicate()); -} - -Status<FileReference> Endpoint::PushFileHandle(Message* /*message*/, - const RemoteHandle& handle) { - return handle.Get(); -} - -Status<ChannelReference> Endpoint::PushChannelHandle( - Message* message, const LocalChannelHandle& handle) { - auto* state = static_cast<MessageState*>(message->GetState()); - return state->PushChannelHandle(handle.Borrow()); -} - -Status<ChannelReference> Endpoint::PushChannelHandle( - Message* message, const BorrowedChannelHandle& handle) { - auto* state = static_cast<MessageState*>(message->GetState()); - return state->PushChannelHandle(handle.Duplicate()); -} - -Status<ChannelReference> Endpoint::PushChannelHandle( - Message* /*message*/, const RemoteChannelHandle& handle) { - return handle.value(); -} - -LocalHandle Endpoint::GetFileHandle(Message* message, FileReference ref) const { - LocalHandle handle; - auto* state = static_cast<MessageState*>(message->GetState()); - state->GetLocalFileHandle(ref, &handle); - return handle; -} - -LocalChannelHandle Endpoint::GetChannelHandle(Message* message, - ChannelReference ref) const { - LocalChannelHandle handle; - auto* state = static_cast<MessageState*>(message->GetState()); - state->GetLocalChannelHandle(ref, &handle); - return handle; -} - -Status<void> Endpoint::Cancel() { - if (eventfd_write(cancel_event_fd_.Get(), 1) < 0) - return ErrorStatus{errno}; - return {}; -} - -std::unique_ptr<Endpoint> Endpoint::Create(const std::string& endpoint_path, - mode_t /*unused_mode*/, - bool blocking) { - return std::unique_ptr<Endpoint>(new Endpoint(endpoint_path, blocking)); -} - -std::unique_ptr<Endpoint> Endpoint::CreateAndBindSocket( - const std::string& endpoint_path, bool blocking) { - return std::unique_ptr<Endpoint>( - new Endpoint(endpoint_path, blocking, false)); -} - -std::unique_ptr<Endpoint> Endpoint::CreateFromSocketFd(LocalHandle socket_fd) { - return std::unique_ptr<Endpoint>(new Endpoint(std::move(socket_fd))); -} - -Status<void> Endpoint::RegisterNewChannelForTests(LocalHandle channel_fd) { - int optval = 1; - if (setsockopt(channel_fd.Get(), SOL_SOCKET, SO_PASSCRED, &optval, - sizeof(optval)) == -1) { - ALOGE( - "Endpoint::RegisterNewChannelForTests: Failed to enable the receiving" - "of the credentials for channel %d: %s", - channel_fd.Get(), strerror(errno)); - return ErrorStatus(errno); - } - return OnNewChannel(std::move(channel_fd)); -} - -} // namespace uds -} // namespace pdx -} // namespace android diff --git a/libs/vr/libpdx_uds/service_framework_tests.cpp b/libs/vr/libpdx_uds/service_framework_tests.cpp deleted file mode 100644 index 27427162f5..0000000000 --- a/libs/vr/libpdx_uds/service_framework_tests.cpp +++ /dev/null @@ -1,718 +0,0 @@ -#include <errno.h> -#include <fcntl.h> -#include <poll.h> -#include <sys/epoll.h> -#include <sys/eventfd.h> -#include <unistd.h> - -#include <array> -#include <atomic> -#include <memory> -#include <numeric> -#include <string> -#include <thread> - -#include <gtest/gtest.h> -#include <pdx/channel_handle.h> -#include <pdx/client.h> -#include <pdx/file_handle.h> -#include <pdx/service.h> -#include <pdx/service_dispatcher.h> -#include <private/android_filesystem_config.h> -#include <uds/client_channel.h> -#include <uds/client_channel_factory.h> -#include <uds/service_endpoint.h> - -using android::pdx::BorrowedChannelHandle; -using android::pdx::Channel; -using android::pdx::ChannelReference; -using android::pdx::ClientBase; -using android::pdx::ErrorStatus; -using android::pdx::LocalChannelHandle; -using android::pdx::LocalHandle; -using android::pdx::Message; -using android::pdx::MessageInfo; -using android::pdx::RemoteChannelHandle; -using android::pdx::ServiceBase; -using android::pdx::ServiceDispatcher; -using android::pdx::Status; -using android::pdx::Transaction; -using android::pdx::uds::Endpoint; - -namespace { - -const size_t kLargeDataSize = 100000; - -const char kTestServicePath[] = "socket_test"; -const char kTestService1[] = "1"; -const char kTestService2[] = "2"; - -enum test_op_codes { - TEST_OP_GET_SERVICE_ID, - TEST_OP_SET_TEST_CHANNEL, - TEST_OP_GET_THIS_CHANNEL_ID, - TEST_OP_GET_TEST_CHANNEL_ID, - TEST_OP_CHECK_CHANNEL_ID, - TEST_OP_CHECK_CHANNEL_OBJECT, - TEST_OP_CHECK_CHANNEL_FROM_OTHER_SERVICE, - TEST_OP_GET_NEW_CHANNEL, - TEST_OP_GET_NEW_CHANNEL_FROM_OTHER_SERVICE, - TEST_OP_GET_THIS_PROCESS_ID, - TEST_OP_GET_THIS_THREAD_ID, - TEST_OP_GET_THIS_EUID, - TEST_OP_GET_THIS_EGID, - TEST_OP_IMPULSE, - TEST_OP_POLLHUP_FROM_SERVICE, - TEST_OP_POLLIN_FROM_SERVICE, - TEST_OP_SEND_LARGE_DATA_RETURN_SUM, -}; - -using ImpulsePayload = std::array<std::uint8_t, sizeof(MessageInfo::impulse)>; - -// The test service creates a TestChannel for every client (channel) that -// connects. This represents the service-side context for each client. -class TestChannel : public Channel { - public: - explicit TestChannel(int channel_id) : channel_id_(channel_id) {} - - int channel_id() const { return channel_id_; } - - private: - friend class TestService; - - int channel_id_; - - TestChannel(const TestChannel&) = delete; - void operator=(const TestChannel&) = delete; -}; - -// Test service that creates a TestChannel for each channel and responds to test -// messages. -class TestService : public ServiceBase<TestService> { - public: - std::shared_ptr<Channel> OnChannelOpen(Message& message) override { - return std::make_shared<TestChannel>(message.GetChannelId()); - } - - void OnChannelClose(Message& /*message*/, - const std::shared_ptr<Channel>& channel) override { - if (test_channel_ == channel) - test_channel_ = nullptr; - } - - void HandleImpulse(Message& message) override { - switch (message.GetOp()) { - case TEST_OP_SET_TEST_CHANNEL: - test_channel_ = message.GetChannel<TestChannel>(); - break; - - case TEST_OP_IMPULSE: { - impulse_payload_.fill(0); - std::copy(message.ImpulseBegin(), message.ImpulseEnd(), - impulse_payload_.begin()); - break; - } - - case TEST_OP_POLLHUP_FROM_SERVICE: { - message.ModifyChannelEvents(0, EPOLLHUP); - break; - } - } - } - - Status<void> HandleMessage(Message& message) override { - switch (message.GetOp()) { - case TEST_OP_GET_SERVICE_ID: - REPLY_MESSAGE_RETURN(message, service_id_, {}); - - // Set the test channel to the TestChannel for the current channel. Other - // messages can use this to perform tests. - case TEST_OP_SET_TEST_CHANNEL: - test_channel_ = message.GetChannel<TestChannel>(); - REPLY_MESSAGE_RETURN(message, 0, {}); - - // Return the channel id for the current channel. - case TEST_OP_GET_THIS_CHANNEL_ID: - REPLY_MESSAGE_RETURN(message, message.GetChannelId(), {}); - - // Return the channel id for the test channel. - case TEST_OP_GET_TEST_CHANNEL_ID: - if (test_channel_) - REPLY_MESSAGE_RETURN(message, test_channel_->channel_id(), {}); - else - REPLY_ERROR_RETURN(message, ENOENT, {}); - - // Test check channel feature. - case TEST_OP_CHECK_CHANNEL_ID: { - ChannelReference ref = 0; - if (!message.ReadAll(&ref, sizeof(ref))) - REPLY_ERROR_RETURN(message, EIO, {}); - - const Status<int> ret = message.CheckChannel<TestChannel>(ref, nullptr); - REPLY_MESSAGE_RETURN(message, ret, {}); - } - - case TEST_OP_CHECK_CHANNEL_OBJECT: { - std::shared_ptr<TestChannel> channel; - ChannelReference ref = 0; - if (!message.ReadAll(&ref, sizeof(ref))) - REPLY_ERROR_RETURN(message, EIO, {}); - - const Status<int> ret = - message.CheckChannel<TestChannel>(ref, &channel); - if (!ret) - REPLY_MESSAGE_RETURN(message, ret, {}); - - if (channel != nullptr) - REPLY_MESSAGE_RETURN(message, channel->channel_id(), {}); - else - REPLY_ERROR_RETURN(message, ENODATA, {}); - } - - case TEST_OP_CHECK_CHANNEL_FROM_OTHER_SERVICE: { - ChannelReference ref = 0; - if (!message.ReadAll(&ref, sizeof(ref))) - REPLY_ERROR_RETURN(message, EIO, {}); - - const Status<int> ret = message.CheckChannel<TestChannel>( - other_service_.get(), ref, nullptr); - REPLY_MESSAGE_RETURN(message, ret, {}); - } - - case TEST_OP_GET_NEW_CHANNEL: { - auto channel = std::make_shared<TestChannel>(-1); - Status<RemoteChannelHandle> channel_handle = - message.PushChannel(0, channel, &channel->channel_id_); - REPLY_MESSAGE_RETURN(message, channel_handle, {}); - } - - case TEST_OP_GET_NEW_CHANNEL_FROM_OTHER_SERVICE: { - if (!other_service_) - REPLY_ERROR_RETURN(message, EINVAL, {}); - - auto channel = std::make_shared<TestChannel>(-1); - Status<RemoteChannelHandle> channel_handle = message.PushChannel( - other_service_.get(), 0, channel, &channel->channel_id_); - REPLY_MESSAGE_RETURN(message, channel_handle, {}); - } - - case TEST_OP_GET_THIS_PROCESS_ID: - REPLY_MESSAGE_RETURN(message, message.GetProcessId(), {}); - - case TEST_OP_GET_THIS_THREAD_ID: - REPLY_MESSAGE_RETURN(message, message.GetThreadId(), {}); - - case TEST_OP_GET_THIS_EUID: - REPLY_MESSAGE_RETURN(message, message.GetEffectiveUserId(), {}); - - case TEST_OP_GET_THIS_EGID: - REPLY_MESSAGE_RETURN(message, message.GetEffectiveGroupId(), {}); - - case TEST_OP_POLLIN_FROM_SERVICE: - REPLY_MESSAGE_RETURN(message, message.ModifyChannelEvents(0, EPOLLIN), - {}); - - case TEST_OP_SEND_LARGE_DATA_RETURN_SUM: { - std::array<int, kLargeDataSize> data_array; - size_t size_to_read = data_array.size() * sizeof(int); - if (!message.ReadAll(data_array.data(), size_to_read)) { - REPLY_ERROR_RETURN(message, EIO, {}); - } - int sum = std::accumulate(data_array.begin(), data_array.end(), 0); - REPLY_MESSAGE_RETURN(message, sum, {}); - } - - default: - return Service::DefaultHandleMessage(message); - } - } - - const ImpulsePayload& GetImpulsePayload() const { return impulse_payload_; } - - private: - friend BASE; - - std::shared_ptr<TestChannel> test_channel_; - std::shared_ptr<TestService> other_service_; - int service_id_; - ImpulsePayload impulse_payload_; - - static std::atomic<int> service_counter_; - - TestService(const std::string& name, - const std::shared_ptr<TestService>& other_service) - : TestService(name, other_service, false) {} - - TestService(const std::string& name, - const std::shared_ptr<TestService>& other_service, bool blocking) - : BASE(std::string("TestService") + name, - Endpoint::CreateAndBindSocket(kTestServicePath + name, blocking)), - other_service_(other_service), - service_id_(service_counter_++) {} - - explicit TestService(const std::string& name) : TestService(name, nullptr) {} - - TestService(const TestService&) = delete; - void operator=(const TestService&) = delete; -}; - -std::atomic<int> TestService::service_counter_; - -// Test client to send messages to the test service. -class TestClient : public ClientBase<TestClient> { - public: - // Requests the service id of the service this channel is connected to. - int GetServiceId() { - Transaction trans{*this}; - return ReturnStatusOrError(trans.Send<int>(TEST_OP_GET_SERVICE_ID)); - } - - // Requests the test channel to be set to this client's channel. - int SetTestChannel() { - Transaction trans{*this}; - return ReturnStatusOrError(trans.Send<int>(TEST_OP_SET_TEST_CHANNEL)); - } - - // Request the test channel to be set to this client's channel using an async - // message. - int SetTestChannelAsync() { - return ReturnStatusOrError(SendImpulse(TEST_OP_SET_TEST_CHANNEL)); - } - - // Sends a test async message with payload. - int SendAsync(const void* buffer, size_t length) { - Transaction trans{*this}; - return ReturnStatusOrError(SendImpulse(TEST_OP_IMPULSE, buffer, length)); - } - - // Requests the channel id for this client. - int GetThisChannelId() { - Transaction trans{*this}; - return ReturnStatusOrError(trans.Send<int>(TEST_OP_GET_THIS_CHANNEL_ID)); - } - - // Requests the channel id of the test channel. - int GetTestChannelId() { - Transaction trans{*this}; - return ReturnStatusOrError(trans.Send<int>(TEST_OP_GET_TEST_CHANNEL_ID)); - } - - // Checks whether the fd |channel_id| is a channel to the test service. - // Returns the channel id of the channel. - int CheckChannelIdArgument(BorrowedChannelHandle channel) { - Transaction trans{*this}; - ChannelReference ref = trans.PushChannelHandle(channel).get(); - return ReturnStatusOrError(trans.Send<int>(TEST_OP_CHECK_CHANNEL_ID, &ref, - sizeof(ref), nullptr, 0)); - } - - // Checks whether the fd |channel_id| is a channel to the test service. - // Returns the channel id of the channel exercising the context pointer. - int CheckChannelObjectArgument(BorrowedChannelHandle channel) { - Transaction trans{*this}; - ChannelReference ref = trans.PushChannelHandle(channel).get(); - return ReturnStatusOrError(trans.Send<int>(TEST_OP_CHECK_CHANNEL_OBJECT, - &ref, sizeof(ref), nullptr, 0)); - } - - // Checks whether the fd |channel_fd| is a channel to the other test service. - // Returns 0 on success. - int CheckChannelFromOtherService(BorrowedChannelHandle channel) { - Transaction trans{*this}; - ChannelReference ref = trans.PushChannelHandle(channel).get(); - return ReturnStatusOrError( - trans.Send<int>(TEST_OP_CHECK_CHANNEL_FROM_OTHER_SERVICE, &ref, - sizeof(ref), nullptr, 0)); - } - - // Requests a new channel to the service. - std::unique_ptr<TestClient> GetNewChannel() { - Transaction trans{*this}; - auto status = trans.Send<LocalChannelHandle>(TEST_OP_GET_NEW_CHANNEL); - if (status) - return TestClient::Create(status.take()); - else - return nullptr; - } - - // Requests a new channel to the other service. - std::unique_ptr<TestClient> GetNewChannelFromOtherService() { - Transaction trans{*this}; - auto status = trans.Send<LocalChannelHandle>( - TEST_OP_GET_NEW_CHANNEL_FROM_OTHER_SERVICE); - if (status) - return TestClient::Create(status.take()); - else - return nullptr; - } - - // Requests an id from the message description. - pid_t GetThisProcessId() { - Transaction trans{*this}; - return ReturnStatusOrError(trans.Send<int>(TEST_OP_GET_THIS_PROCESS_ID)); - } - pid_t GetThisThreadId() { - Transaction trans{*this}; - return ReturnStatusOrError(trans.Send<int>(TEST_OP_GET_THIS_THREAD_ID)); - } - uid_t GetThisEffectiveUserId() { - Transaction trans{*this}; - return ReturnStatusOrError(trans.Send<int>(TEST_OP_GET_THIS_EUID)); - } - gid_t GetThisEffectiveGroupId() { - Transaction trans{*this}; - return ReturnStatusOrError(trans.Send<int>(TEST_OP_GET_THIS_EGID)); - } - - int SendPollHupEvent() { - return ReturnStatusOrError(SendImpulse(TEST_OP_POLLHUP_FROM_SERVICE)); - } - - int SendPollInEvent() { - Transaction trans{*this}; - return ReturnStatusOrError(trans.Send<int>(TEST_OP_POLLIN_FROM_SERVICE)); - } - - int SendLargeDataReturnSum( - const std::array<int, kLargeDataSize>& data_array) { - Transaction trans{*this}; - return ReturnStatusOrError( - trans.Send<int>(TEST_OP_SEND_LARGE_DATA_RETURN_SUM, data_array.data(), - data_array.size() * sizeof(int), nullptr, 0)); - } - - Status<int> GetEventMask(int events) { - if (auto* client_channel = GetChannel()) { - return client_channel->GetEventMask(events); - } else { - return ErrorStatus(EINVAL); - } - } - - using ClientBase<TestClient>::event_fd; - - enum : size_t { kMaxPayload = MAX_IMPULSE_LENGTH }; - - private: - friend BASE; - - explicit TestClient(const std::string& name) - : BASE{android::pdx::uds::ClientChannelFactory::Create(kTestServicePath + - name)} {} - - explicit TestClient(LocalChannelHandle channel) - : BASE{android::pdx::uds::ClientChannel::Create(std::move(channel))} {} - - TestClient(const TestClient&) = delete; - void operator=(const TestClient&) = delete; -}; - -} // anonymous namespace - -// Use a test fixture to ensure proper order of cleanup between clients, -// services, and the dispatcher. These objects are cleaned up in the same -// thread, order is important; either the service or the client must be -// destroyed before the dispatcher is stopped. The reason for this is that -// clients send blocking "close" messages to their respective services on -// destruction. If this happens after the dispatcher is stopped the client -// destructor will get blocked waiting for a reply that will never come. In -// normal use of the service framework this is never an issue because clients -// and the dispatcher for the same service are never destructed in the same -// thread (they live in different processes). -class ServiceFrameworkTest : public ::testing::Test { - protected: - std::unique_ptr<ServiceDispatcher> dispatcher_; - std::thread dispatch_thread_; - - void SetUp() override { - // Create a dispatcher to handle messages to services. - dispatcher_ = android::pdx::ServiceDispatcher::Create(); - ASSERT_NE(nullptr, dispatcher_); - - // Start the message dispatch loop in a separate thread. - dispatch_thread_ = std::thread( - std::bind(&ServiceDispatcher::EnterDispatchLoop, dispatcher_.get())); - } - - void TearDown() override { - if (dispatcher_) { - // Cancel the dispatcher and wait for the thread to terminate. Explicitly - // join the thread so that destruction doesn't deallocate the dispatcher - // before the thread finishes. - dispatcher_->SetCanceled(true); - dispatch_thread_.join(); - } - } -}; - -// Test basic operation of TestService/TestClient classes. -TEST_F(ServiceFrameworkTest, BasicClientService) { - // Create a test service and add it to the dispatcher. - auto service = TestService::Create(kTestService1); - ASSERT_NE(nullptr, service); - ASSERT_EQ(0, dispatcher_->AddService(service)); - - // Create a client to service. - auto client = TestClient::Create(kTestService1); - ASSERT_NE(nullptr, client); - - // Get the channel id that will be returned by the next tests. - const int channel_id = client->GetThisChannelId(); - EXPECT_LE(0, channel_id); - - // Check return value before test channel is set. - EXPECT_EQ(-ENOENT, client->GetTestChannelId()); - - // Set test channel and perform the test again. - EXPECT_EQ(0, client->SetTestChannel()); - EXPECT_EQ(channel_id, client->GetTestChannelId()); -} - -// Test impulses. -TEST_F(ServiceFrameworkTest, Impulse) { - // Create a test service and add it to the dispatcher. - auto service = TestService::Create(kTestService1); - ASSERT_NE(nullptr, service); - ASSERT_EQ(0, dispatcher_->AddService(service)); - - auto client = TestClient::Create(kTestService1); - ASSERT_NE(nullptr, client); - - // Get the channel id that will be returned by the next tests. - const int channel_id = client->GetThisChannelId(); - EXPECT_LE(0, channel_id); - - // Check return value before test channel is set. - EXPECT_EQ(-ENOENT, client->GetTestChannelId()); - - // Set test channel with an impulse and perform the test again. - EXPECT_EQ(0, client->SetTestChannelAsync()); - EXPECT_EQ(channel_id, client->GetTestChannelId()); - - ImpulsePayload expected_payload = {{'a', 'b', 'c'}}; - EXPECT_EQ(0, client->SendAsync(expected_payload.data(), 3)); - // Send a synchronous message to make sure the async message is handled before - // we check the payload. - client->GetThisChannelId(); - EXPECT_EQ(expected_payload, service->GetImpulsePayload()); - - // Impulse payloads are limited to 4 machine words. - EXPECT_EQ( - 0, client->SendAsync(expected_payload.data(), TestClient::kMaxPayload)); - EXPECT_EQ(-EINVAL, client->SendAsync(expected_payload.data(), - TestClient::kMaxPayload + 1)); - - // Test invalid pointer. - const std::uint8_t* invalid_pointer = nullptr; - EXPECT_EQ(-EINVAL, client->SendAsync(invalid_pointer, sizeof(int))); -} - -// Test impulses. -TEST_F(ServiceFrameworkTest, ImpulseHangup) { - // Create a test service and add it to the dispatcher. - auto service = TestService::Create(kTestService1); - ASSERT_NE(nullptr, service); - ASSERT_EQ(0, dispatcher_->AddService(service)); - - auto client = TestClient::Create(kTestService1); - ASSERT_NE(nullptr, client); - - const int kMaxIterations = 1000; - for (int i = 0; i < kMaxIterations; i++) { - auto impulse_client = TestClient::Create(kTestService1); - ASSERT_NE(nullptr, impulse_client); - - const uint8_t a = (i >> 0) & 0xff; - const uint8_t b = (i >> 8) & 0xff; - const uint8_t c = (i >> 16) & 0xff; - const uint8_t d = (i >> 24) & 0xff; - ImpulsePayload expected_payload = {{a, b, c, d}}; - EXPECT_EQ(0, impulse_client->SendAsync(expected_payload.data(), 4)); - - // Hangup the impulse test client, then send a sync message over client to - // make sure the hangup message is handled before checking the impulse - // payload. - impulse_client = nullptr; - client->GetThisChannelId(); - EXPECT_EQ(expected_payload, service->GetImpulsePayload()); - } -} - -// Test Message::PushChannel/Service::PushChannel API. -TEST_F(ServiceFrameworkTest, PushChannel) { - // Create a test service and add it to the dispatcher. - auto other_service = TestService::Create(kTestService1); - ASSERT_NE(nullptr, other_service); - ASSERT_EQ(0, dispatcher_->AddService(other_service)); - - // Create a second test service and add it to the dispatcher. - auto service = TestService::Create(kTestService2, other_service); - ASSERT_NE(nullptr, service); - ASSERT_EQ(0, dispatcher_->AddService(service)); - - // Create a client to the second test service. - auto client1 = TestClient::Create(kTestService2); - ASSERT_NE(nullptr, client1); - - // Test the creation of new channels using the push APIs. - const int channel_id1 = client1->GetThisChannelId(); - EXPECT_LE(0, channel_id1); - - auto client2 = client1->GetNewChannel(); - EXPECT_NE(nullptr, client2); - EXPECT_NE(client1->event_fd(), client2->event_fd()); - - const int channel_id2 = client2->GetThisChannelId(); - EXPECT_LE(0, channel_id2); - EXPECT_NE(channel_id1, channel_id2); - - auto client3 = client1->GetNewChannelFromOtherService(); - EXPECT_NE(nullptr, client3); - EXPECT_NE(client1->event_fd(), client3->event_fd()); - - const int channel_id3 = client3->GetThisChannelId(); - EXPECT_LE(0, channel_id3); - - // Test which services the channels are connected to. - const int service_id1 = client1->GetServiceId(); - EXPECT_LE(0, service_id1); - - const int service_id2 = client2->GetServiceId(); - EXPECT_LE(0, service_id2); - - const int service_id3 = client3->GetServiceId(); - EXPECT_LE(0, service_id3); - - EXPECT_EQ(service_id1, service_id2); - EXPECT_NE(service_id1, service_id3); -} - -// Tests process id, thread id, effective user id, and effective group id -// returned in the message description. -TEST_F(ServiceFrameworkTest, Ids) { - // Create a test service and add it to the dispatcher. - auto service = TestService::Create(kTestService1); - ASSERT_NE(nullptr, service); - ASSERT_EQ(0, dispatcher_->AddService(service)); - - // Create a client to service. - auto client = TestClient::Create(kTestService1); - ASSERT_NE(nullptr, client); - - // Pids 0-2 are defined, no user task should have them. - - const pid_t process_id1 = client->GetThisProcessId(); - EXPECT_LT(2, process_id1); - - pid_t process_id2; - - std::thread thread([&]() { process_id2 = client->GetThisProcessId(); }); - thread.join(); - - EXPECT_LT(2, process_id2); - EXPECT_EQ(process_id1, process_id2); - - // This test must run as root for the rest of these tests to work. - const int euid1 = client->GetThisEffectiveUserId(); - ASSERT_EQ(0, euid1); - - const int egid1 = client->GetThisEffectiveGroupId(); - EXPECT_EQ(0, egid1); - - // Set effective uid/gid to system. - ASSERT_EQ(0, setegid(AID_SYSTEM)); - ASSERT_EQ(0, seteuid(AID_SYSTEM)); - - const int euid2 = client->GetThisEffectiveUserId(); - EXPECT_EQ(AID_SYSTEM, euid2); - - const int egid2 = client->GetThisEffectiveGroupId(); - EXPECT_EQ(AID_SYSTEM, egid2); - - // Set the euid/egid back to root. - ASSERT_EQ(0, setegid(0)); - ASSERT_EQ(0, seteuid(0)); -} - -TEST_F(ServiceFrameworkTest, PollIn) { - // Create a test service and add it to the dispatcher. - auto service = TestService::Create(kTestService1); - ASSERT_NE(nullptr, service); - ASSERT_EQ(0, dispatcher_->AddService(service)); - - // Create a client to service. - auto client = TestClient::Create(kTestService1); - ASSERT_NE(nullptr, client); - - pollfd pfd{client->event_fd(), POLLIN, 0}; - int count = poll(&pfd, 1, 0); - ASSERT_EQ(0, count); - - client->SendPollInEvent(); - - count = poll(&pfd, 1, 10000 /*10s*/); - ASSERT_EQ(1, count); - ASSERT_TRUE((POLLIN & pfd.revents) != 0); -} - -TEST_F(ServiceFrameworkTest, PollHup) { - // Create a test service and add it to the dispatcher. - auto service = TestService::Create(kTestService1); - ASSERT_NE(nullptr, service); - ASSERT_EQ(0, dispatcher_->AddService(service)); - - // Create a client to service. - auto client = TestClient::Create(kTestService1); - ASSERT_NE(nullptr, client); - - pollfd pfd{client->event_fd(), POLLIN, 0}; - int count = poll(&pfd, 1, 0); - ASSERT_EQ(0, count); - - client->SendPollHupEvent(); - - count = poll(&pfd, 1, 10000 /*10s*/); - ASSERT_EQ(1, count); - auto event_status = client->GetEventMask(pfd.revents); - ASSERT_TRUE(event_status.ok()); - ASSERT_TRUE((EPOLLHUP & event_status.get()) != 0); -} - -TEST_F(ServiceFrameworkTest, LargeDataSum) { - // Create a test service and add it to the dispatcher. - auto service = TestService::Create(kTestService1); - ASSERT_NE(nullptr, service); - ASSERT_EQ(0, dispatcher_->AddService(service)); - - // Create a client to service. - auto client = TestClient::Create(kTestService1); - ASSERT_NE(nullptr, client); - - std::array<int, kLargeDataSize> data_array; - std::iota(data_array.begin(), data_array.end(), 0); - int expected_sum = std::accumulate(data_array.begin(), data_array.end(), 0); - int sum = client->SendLargeDataReturnSum(data_array); - ASSERT_EQ(expected_sum, sum); -} - -TEST_F(ServiceFrameworkTest, Cancel) { - // Create a test service and add it to the dispatcher. - auto service = TestService::Create(kTestService1, nullptr, true); - ASSERT_NE(nullptr, service); - ASSERT_EQ(0, dispatcher_->AddService(service)); - - // Create a client to service. - auto client = TestClient::Create(kTestService1); - ASSERT_NE(nullptr, client); - - auto previous_time = std::chrono::system_clock::now(); - dispatcher_->ReceiveAndDispatch(100); // 0.1 seconds should block. - auto time = std::chrono::system_clock::now(); - ASSERT_LE(100, std::chrono::duration_cast<std::chrono::milliseconds>( - time - previous_time) - .count()); - service->Cancel(); - // Non-blocking. Return immediately. - dispatcher_->ReceiveAndDispatch(-1); - dispatcher_->ReceiveAndDispatch(-1); -} diff --git a/libs/vr/libperformance/Android.bp b/libs/vr/libperformance/Android.bp deleted file mode 100644 index 38bf4ea522..0000000000 --- a/libs/vr/libperformance/Android.bp +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (C) 2016 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "frameworks_native_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["frameworks_native_license"], -} - -sourceFiles = [ - "performance_client.cpp", - "performance_rpc.cpp", -] - -includeFiles = [ "include" ] - -sharedLibraries = [ - "libbase", - "libbinder", - "libcutils", - "liblog", - "libutils", - "libpdx_default_transport", -] - -cc_library { - srcs: sourceFiles, - cflags: [ - "-DLOG_TAG=\"libperformance\"", - "-DTRACE=0", - "-Wall", - "-Werror", - ], - export_include_dirs: includeFiles, - shared_libs: sharedLibraries, - name: "libperformance", -} diff --git a/libs/vr/libperformance/include/CPPLINT.cfg b/libs/vr/libperformance/include/CPPLINT.cfg deleted file mode 100644 index 2f8a3c018c..0000000000 --- a/libs/vr/libperformance/include/CPPLINT.cfg +++ /dev/null @@ -1 +0,0 @@ -filter=-build/header_guard diff --git a/libs/vr/libperformance/include/dvr/performance_client_api.h b/libs/vr/libperformance/include/dvr/performance_client_api.h deleted file mode 100644 index 9d617cbaba..0000000000 --- a/libs/vr/libperformance/include/dvr/performance_client_api.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef ANDROID_DVR_PERFORMANCE_CLIENT_API_H_ -#define ANDROID_DVR_PERFORMANCE_CLIENT_API_H_ - -#include <stddef.h> -#include <unistd.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/// Sets the scheduler policy for a task. -/// -/// Sets the scheduler policy for a task to the class described by a semantic -/// string. -/// -/// Supported policies are device-specific. -/// -/// @param task_id The task id of task to set the policy for. When task_id is 0 -/// the current task id is substituted. -/// @param scheduler_policy NULL-terminated ASCII string containing the desired -/// scheduler policy. -/// @returns Returns 0 on success or a negative errno error code on error. -int dvrSetSchedulerPolicy(pid_t task_id, const char* scheduler_policy); - -/// Sets the CPU partition for a task. -/// -/// Sets the CPU partition for a task to the partition described by a CPU -/// partition path. -/// -/// TODO(eieio): Describe supported partitions and rules governing assignment. -/// -/// @param task_id The task id of task to attach to a partition. When task_id is -/// 0 the current task id is substituted. -/// @param partition NULL-terminated ASCII string describing the CPU partition -/// to attach the task to. -/// @returns Returns 0 on success or a negative errno error code on error. -int dvrSetCpuPartition(pid_t task_id, const char* partition); - -/// Sets the scheduler class for a task. -/// -/// Sets the scheduler class for a task to the class described by a semantic -/// string. -/// -/// Supported classes for applications are: audio, graphics, normal, and -/// background. Additional options following a ':' to be supported in the -/// future. -/// -/// @param task_id The task id of task to attach to a partition. When task_id is -/// 0 the current task id is substituted. -/// @param scheduler_class NULL-terminated ASCII string containing the desired -/// scheduler class. -/// @returns Returns 0 on success or a negative errno error code on error. -int dvrSetSchedulerClass(pid_t task_id, const char* scheduler_class); - -/// Gets the CPU partition for a task. -/// -/// Gets the CPU partition path for a task as a NULL-terminated ASCII string. If -/// the path is too large to fit in the supplied buffer, -ENOBUFS is returned. -/// -/// @param task_id The task id of the task to retrieve the partition for. When -/// task_id is 0 the current task id is substituted. -/// @param partition Pointer to an ASCII string buffer to store the partition -/// path. -/// @param size Size of the string buffer in bytes, including space for the NULL -/// terminator. -/// @returns Returns 0 on success or a negative errno error code on error. -int dvrGetCpuPartition(pid_t task_id, char* partition, size_t size); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // ANDROID_DVR_PERFORMANCE_CLIENT_API_H_ diff --git a/libs/vr/libperformance/include/private/dvr/performance_client.h b/libs/vr/libperformance/include/private/dvr/performance_client.h deleted file mode 100644 index 3bd90dc1f3..0000000000 --- a/libs/vr/libperformance/include/private/dvr/performance_client.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef ANDROID_DVR_PERFORMANCE_CLIENT_H_ -#define ANDROID_DVR_PERFORMANCE_CLIENT_H_ - -#include <sys/types.h> - -#include <cstddef> -#include <string> -#include <tuple> - -#include <pdx/client.h> - -namespace android { -namespace dvr { - -class PerformanceClient : public pdx::ClientBase<PerformanceClient> { - public: - int SetSchedulerPolicy(pid_t task_id, const std::string& scheduler_policy); - int SetSchedulerPolicy(pid_t task_id, const char* scheduler_policy); - - // TODO(eieio): Consider deprecating this API. - int SetCpuPartition(pid_t task_id, const std::string& partition); - int SetCpuPartition(pid_t task_id, const char* partition); - int SetSchedulerClass(pid_t task_id, const std::string& scheduler_class); - int SetSchedulerClass(pid_t task_id, const char* scheduler_class); - int GetCpuPartition(pid_t task_id, std::string* partition_out); - int GetCpuPartition(pid_t task_id, char* partition_out, std::size_t size); - - private: - friend BASE; - - explicit PerformanceClient(int* error); - - PerformanceClient(const PerformanceClient&) = delete; - void operator=(const PerformanceClient&) = delete; -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_PERFORMANCE_CLIENT_H_ diff --git a/libs/vr/libperformance/include/private/dvr/performance_rpc.h b/libs/vr/libperformance/include/private/dvr/performance_rpc.h deleted file mode 100644 index d57bbe8361..0000000000 --- a/libs/vr/libperformance/include/private/dvr/performance_rpc.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef ANDROID_DVR_PERFORMANCE_RPC_H_ -#define ANDROID_DVR_PERFORMANCE_RPC_H_ - -#include <sys/types.h> - -#include <string> - -#include <pdx/rpc/remote_method_type.h> - -namespace android { -namespace dvr { - -// Performance Service RPC interface. Defines the endpoint paths, op codes, and -// method type signatures supported by performanced. -struct PerformanceRPC { - // Service path. - static constexpr char kClientPath[] = "system/performance/client"; - - // Op codes. - enum { - kOpSetCpuPartition = 0, - kOpSetSchedulerClass, - kOpGetCpuPartition, - kOpSetSchedulerPolicy, - }; - - // Methods. - PDX_REMOTE_METHOD(SetCpuPartition, kOpSetCpuPartition, - void(pid_t, const std::string&)); - PDX_REMOTE_METHOD(SetSchedulerClass, kOpSetSchedulerClass, - void(pid_t, const std::string&)); - PDX_REMOTE_METHOD(GetCpuPartition, kOpGetCpuPartition, std::string(pid_t)); - PDX_REMOTE_METHOD(SetSchedulerPolicy, kOpSetSchedulerPolicy, - void(pid_t, const std::string&)); -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_PERFORMANCE_RPC_H_ diff --git a/libs/vr/libperformance/performance_client.cpp b/libs/vr/libperformance/performance_client.cpp deleted file mode 100644 index bf3726e346..0000000000 --- a/libs/vr/libperformance/performance_client.cpp +++ /dev/null @@ -1,148 +0,0 @@ -#include "include/private/dvr/performance_client.h" - -#include <sys/types.h> - -#include <pdx/default_transport/client_channel_factory.h> -#include <pdx/rpc/remote_method.h> -#include <pdx/rpc/string_wrapper.h> -#include <private/dvr/performance_rpc.h> - -using android::pdx::rpc::WrapString; - -namespace android { -namespace dvr { - -PerformanceClient::PerformanceClient(int* error) - : BASE(pdx::default_transport::ClientChannelFactory::Create( - PerformanceRPC::kClientPath)) { - if (error) - *error = Client::error(); -} - -int PerformanceClient::SetCpuPartition(pid_t task_id, - const std::string& partition) { - if (task_id == 0) - task_id = gettid(); - - return ReturnStatusOrError( - InvokeRemoteMethod<PerformanceRPC::SetCpuPartition>(task_id, partition)); -} - -int PerformanceClient::SetCpuPartition(pid_t task_id, const char* partition) { - if (task_id == 0) - task_id = gettid(); - - return ReturnStatusOrError( - InvokeRemoteMethod<PerformanceRPC::SetCpuPartition>( - task_id, WrapString(partition))); -} - -int PerformanceClient::SetSchedulerPolicy(pid_t task_id, - const std::string& scheduler_policy) { - if (task_id == 0) - task_id = gettid(); - - return ReturnStatusOrError( - InvokeRemoteMethod<PerformanceRPC::SetSchedulerPolicy>(task_id, - scheduler_policy)); -} - -int PerformanceClient::SetSchedulerPolicy(pid_t task_id, - const char* scheduler_policy) { - if (task_id == 0) - task_id = gettid(); - - return ReturnStatusOrError( - InvokeRemoteMethod<PerformanceRPC::SetSchedulerPolicy>( - task_id, WrapString(scheduler_policy))); -} - -int PerformanceClient::SetSchedulerClass(pid_t task_id, - const std::string& scheduler_class) { - if (task_id == 0) - task_id = gettid(); - - return ReturnStatusOrError( - InvokeRemoteMethod<PerformanceRPC::SetSchedulerClass>(task_id, - scheduler_class)); -} - -int PerformanceClient::SetSchedulerClass(pid_t task_id, - const char* scheduler_class) { - if (task_id == 0) - task_id = gettid(); - - return ReturnStatusOrError( - InvokeRemoteMethod<PerformanceRPC::SetSchedulerClass>( - task_id, WrapString(scheduler_class))); -} - -int PerformanceClient::GetCpuPartition(pid_t task_id, - std::string* partition_out) { - if (partition_out == nullptr) - return -EINVAL; - - if (task_id == 0) - task_id = gettid(); - - auto status = InvokeRemoteMethodInPlace<PerformanceRPC::GetCpuPartition>( - partition_out, task_id); - return status ? 0 : -status.error(); -} - -int PerformanceClient::GetCpuPartition(pid_t task_id, char* partition_out, - std::size_t size) { - if (partition_out == nullptr) - return -EINVAL; - - if (task_id == 0) - task_id = gettid(); - - auto wrapper = WrapString(partition_out, size); - auto status = InvokeRemoteMethodInPlace<PerformanceRPC::GetCpuPartition>( - &wrapper, task_id); - if (!status) - return -status.error(); - - if (wrapper.size() < size) - partition_out[wrapper.size()] = '\0'; - - return 0; -} - -} // namespace dvr -} // namespace android - -extern "C" int dvrSetCpuPartition(pid_t task_id, const char* partition) { - int error; - if (auto client = android::dvr::PerformanceClient::Create(&error)) - return client->SetCpuPartition(task_id, partition); - else - return error; -} - -extern "C" int dvrSetSchedulerPolicy(pid_t task_id, - const char* scheduler_policy) { - int error; - if (auto client = android::dvr::PerformanceClient::Create(&error)) - return client->SetSchedulerPolicy(task_id, scheduler_policy); - else - return error; -} - -extern "C" int dvrSetSchedulerClass(pid_t task_id, - const char* scheduler_class) { - int error; - if (auto client = android::dvr::PerformanceClient::Create(&error)) - return client->SetSchedulerClass(task_id, scheduler_class); - else - return error; -} - -extern "C" int dvrGetCpuPartition(pid_t task_id, char* partition, size_t size) { - int error; - if (auto client = android::dvr::PerformanceClient::Create(&error)) - return client->GetCpuPartition(task_id, partition, size); - else - return error; -} diff --git a/libs/vr/libperformance/performance_rpc.cpp b/libs/vr/libperformance/performance_rpc.cpp deleted file mode 100644 index 9135349ca2..0000000000 --- a/libs/vr/libperformance/performance_rpc.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "include/private/dvr/performance_rpc.h" - -namespace android { -namespace dvr { - -constexpr char PerformanceRPC::kClientPath[]; - -} // namespace dvr -} // namespace android diff --git a/libs/vr/libvr_manager/Android.bp b/libs/vr/libvr_manager/Android.bp deleted file mode 100644 index 6f2ada4633..0000000000 --- a/libs/vr/libvr_manager/Android.bp +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (C) 2017 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "frameworks_native_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["frameworks_native_license"], -} - -cc_library_static { - name: "libvr_manager", - srcs: [ - "vr_manager.cpp", - "trusted_uids.cpp", - ], - include_dirs: ["frameworks/native/include/vr/vr_manager"], - export_include_dirs: [ "include" ], - cflags: ["-Wall", "-Werror", "-Wunused", "-Wunreachable-code"], - shared_libs: [ - "libutils", - "libbinder", - ], -} diff --git a/libs/vr/libvr_manager/include/private/dvr/trusted_uids.h b/libs/vr/libvr_manager/include/private/dvr/trusted_uids.h deleted file mode 100644 index 4496fbff7a..0000000000 --- a/libs/vr/libvr_manager/include/private/dvr/trusted_uids.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef ANDROID_DVR_TRUSTED_UIDS_H_ -#define ANDROID_DVR_TRUSTED_UIDS_H_ - -#include <sys/types.h> - -namespace android { -namespace dvr { - -/** - * Tells if a provided UID can be trusted to access restricted VR APIs. - * - * UID trust is based on the android.permission.RESTRICTED_VR_ACCESS permission. - * AID_SYSTEM and AID_ROOT are automatically trusted by Android. - * - * UIDs are guaranteed not to be reused until the next reboot even in case - * of package reinstall. For performance reasons this method caches results by - * default, as otherwise every check would trigger a Java call. - * - * This function is thread-safe. - * - * @param uid The uid to check. - * @param use_cache If true any cached result for the provided uid will be - * reused. If false this call will reach the Application Manager Service - * in Java to get updated values. Any updates will be stored in the cache. - * @return true if the uid is trusted, false if not or if the VR Manager Service - * could not be reached to verify the uid. - */ -bool IsTrustedUid(uid_t uid, bool use_cache = true); - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_TRUSTED_UIDS_H_ diff --git a/libs/vr/libvr_manager/trusted_uids.cpp b/libs/vr/libvr_manager/trusted_uids.cpp deleted file mode 100644 index 4228a050db..0000000000 --- a/libs/vr/libvr_manager/trusted_uids.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include "private/dvr/trusted_uids.h" - -#include <mutex> -#include <unordered_map> - -#include <binder/IPermissionController.h> -#include <binder/IServiceManager.h> -#include <private/android_filesystem_config.h> -#include <utils/String16.h> -#include <vr/vr_manager/vr_manager.h> - -namespace android { -namespace dvr { - -bool IsTrustedUid(uid_t uid, bool use_cache) { - static std::unordered_map<uid_t, bool> uid_cache; - static std::mutex uid_cache_mutex; - - // Whitelist requests from the system UID. - // These are already whitelisted by the permission service, but it might not - // be available if the ActivityManagerService is up during boot. - // This ensures the correct result for system services while booting up. - if (uid == AID_SYSTEM) - return true; - - std::lock_guard<std::mutex> lock(uid_cache_mutex); - - if (use_cache) { - auto it = uid_cache.find(uid); - if (it != uid_cache.end()) - return it->second; - } - - sp<IBinder> binder = defaultServiceManager()->getService(String16("permission")); - if (binder == 0) { - ALOGW("Could not access permission service"); - return false; - } - - // Note: we ignore the pid because it's only used to automatically reply - // true if the caller is the Activity Manager Service. - bool trusted = interface_cast<IPermissionController>(binder)->checkPermission( - String16("android.permission.RESTRICTED_VR_ACCESS"), -1, uid); - - // Cache the information for this uid to avoid future Java calls. - uid_cache[uid] = trusted; - return trusted; -} - -} // namespace dvr -} // namespace android diff --git a/libs/vr/libvr_manager/vr_manager.cpp b/libs/vr/libvr_manager/vr_manager.cpp deleted file mode 100644 index 5cfc22eec3..0000000000 --- a/libs/vr/libvr_manager/vr_manager.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "VrManager" -#include <utils/Log.h> - -#include <vr/vr_manager/vr_manager.h> -#include <stdint.h> -#include <sys/types.h> -#include <binder/Parcel.h> - -namespace android { - -// Must be kept in sync with interface defined in IVrStateCallbacks.aidl. - -class BpVrStateCallbacks : public BpInterface<IVrStateCallbacks> { - public: - explicit BpVrStateCallbacks(const sp<IBinder>& impl) - : BpInterface<IVrStateCallbacks>(impl) {} - - void onVrStateChanged(bool enabled) { - Parcel data, reply; - data.writeInterfaceToken(IVrStateCallbacks::getInterfaceDescriptor()); - data.writeBool(enabled); - remote()->transact(ON_VR_STATE_CHANGED, data, &reply, IBinder::FLAG_ONEWAY); - } -}; - -IMPLEMENT_META_INTERFACE(VrStateCallbacks, "android.service.vr.IVrStateCallbacks"); - -status_t BnVrStateCallbacks::onTransact(uint32_t code, const Parcel& data, - Parcel* reply, uint32_t flags) { - switch(code) { - case ON_VR_STATE_CHANGED: { - CHECK_INTERFACE(IVrStateCallbacks, data, reply); - onVrStateChanged(data.readBool()); - return OK; - } - } - return BBinder::onTransact(code, data, reply, flags); -} - -// Must be kept in sync with interface defined in -// IPersistentVrStateCallbacks.aidl. - -class BpPersistentVrStateCallbacks - : public BpInterface<IPersistentVrStateCallbacks> { - public: - explicit BpPersistentVrStateCallbacks(const sp<IBinder>& impl) - : BpInterface<IPersistentVrStateCallbacks>(impl) {} - - void onPersistentVrStateChanged(bool enabled) { - Parcel data, reply; - data.writeInterfaceToken( - IPersistentVrStateCallbacks::getInterfaceDescriptor()); - data.writeBool(enabled); - remote()->transact(ON_PERSISTENT_VR_STATE_CHANGED, - data, &reply, IBinder::FLAG_ONEWAY); - } -}; - -IMPLEMENT_META_INTERFACE(PersistentVrStateCallbacks, - "android.service.vr.IPersistentVrStateCallbacks"); - -status_t BnPersistentVrStateCallbacks::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { - switch(code) { - case ON_PERSISTENT_VR_STATE_CHANGED: { - CHECK_INTERFACE(IPersistentVrStateCallbacks, data, reply); - onPersistentVrStateChanged(data.readBool()); - return OK; - } - } - return BBinder::onTransact(code, data, reply, flags); -} - -// Must be kept in sync with interface defined in IVrManager.aidl. - -class BpVrManager : public BpInterface<IVrManager> { - public: - explicit BpVrManager(const sp<IBinder>& impl) - : BpInterface<IVrManager>(impl) {} - - void registerListener(const sp<IVrStateCallbacks>& cb) override { - Parcel data; - data.writeInterfaceToken(IVrManager::getInterfaceDescriptor()); - data.writeStrongBinder(IInterface::asBinder(cb)); - remote()->transact(REGISTER_LISTENER, data, NULL); - } - - void unregisterListener(const sp<IVrStateCallbacks>& cb) override { - Parcel data; - data.writeInterfaceToken(IVrManager::getInterfaceDescriptor()); - data.writeStrongBinder(IInterface::asBinder(cb)); - remote()->transact(UNREGISTER_LISTENER, data, NULL); - } - - void registerPersistentVrStateListener( - const sp<IPersistentVrStateCallbacks>& cb) override { - Parcel data; - data.writeInterfaceToken(IVrManager::getInterfaceDescriptor()); - data.writeStrongBinder(IInterface::asBinder(cb)); - remote()->transact(REGISTER_PERSISTENT_VR_STATE_LISTENER, data, NULL); - } - - void unregisterPersistentVrStateListener( - const sp<IPersistentVrStateCallbacks>& cb) override { - Parcel data; - data.writeInterfaceToken(IVrManager::getInterfaceDescriptor()); - data.writeStrongBinder(IInterface::asBinder(cb)); - remote()->transact(UNREGISTER_PERSISTENT_VR_STATE_LISTENER, data, NULL); - } - - bool getVrModeState() override { - Parcel data, reply; - data.writeInterfaceToken(IVrManager::getInterfaceDescriptor()); - remote()->transact(GET_VR_MODE_STATE, data, &reply); - int32_t ret = reply.readExceptionCode(); - if (ret != 0) { - return false; - } - return reply.readBool(); - } -}; - -IMPLEMENT_META_INTERFACE(VrManager, "android.service.vr.IVrManager"); - -} // namespace android diff --git a/libs/vr/public.libraries-google.txt b/libs/vr/public.libraries-google.txt deleted file mode 100644 index 8271b9421f..0000000000 --- a/libs/vr/public.libraries-google.txt +++ /dev/null @@ -1 +0,0 @@ -libdvr.google.so
\ No newline at end of file diff --git a/services/surfaceflinger/surfaceflinger.rc b/services/surfaceflinger/surfaceflinger.rc index 39d7bd948d..dfdd4aa38c 100644 --- a/services/surfaceflinger/surfaceflinger.rc +++ b/services/surfaceflinger/surfaceflinger.rc @@ -5,6 +5,3 @@ service surfaceflinger /system/bin/surfaceflinger capabilities SYS_NICE onrestart restart --only-if-running zygote task_profiles HighPerformance - socket pdx/system/vr/display/client stream 0666 system graphics u:object_r:pdx_display_client_endpoint_socket:s0 - socket pdx/system/vr/display/manager stream 0666 system graphics u:object_r:pdx_display_manager_endpoint_socket:s0 - socket pdx/system/vr/display/vsync stream 0666 system graphics u:object_r:pdx_display_vsync_endpoint_socket:s0 diff --git a/services/vr/.clang-format b/services/vr/.clang-format deleted file mode 100644 index 04d7970bbe..0000000000 --- a/services/vr/.clang-format +++ /dev/null @@ -1,5 +0,0 @@ -BasedOnStyle: Google -DerivePointerAlignment: false -PointerAlignment: Left -AllowShortIfStatementsOnASingleLine: false -AllowShortLoopsOnASingleLine: false diff --git a/services/vr/Android.bp b/services/vr/Android.bp deleted file mode 100644 index 980dcf4616..0000000000 --- a/services/vr/Android.bp +++ /dev/null @@ -1,13 +0,0 @@ -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "frameworks_native_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - // SPDX-license-identifier-MIT - default_applicable_licenses: ["frameworks_native_license"], -} - -subdirs = [ - "*", -] diff --git a/services/vr/bufferhubd/Android.bp b/services/vr/bufferhubd/Android.bp deleted file mode 100644 index f5491cfada..0000000000 --- a/services/vr/bufferhubd/Android.bp +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (C) 2016 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "frameworks_native_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["frameworks_native_license"], -} - -sharedLibraries = [ - "libbase", - "libcutils", - "libgui", - "liblog", - "libpdx_default_transport", - "libsync", - "libui", - "libutils", -] - -cc_library_static { - name: "libbufferhubd", - srcs: [ - "buffer_hub.cpp", - "consumer_channel.cpp", - "consumer_queue_channel.cpp", - "producer_channel.cpp", - "producer_queue_channel.cpp", - ], - cflags: [ - "-DLOG_TAG=\"libbufferhubd\"", - "-DTRACE=0", - "-DATRACE_TAG=ATRACE_TAG_GRAPHICS", - ], - export_include_dirs: ["include"], - header_libs: ["libdvr_headers"], - shared_libs: sharedLibraries, - static_libs: [ - "libbufferhub", - ], -} - -cc_binary { - srcs: ["bufferhubd.cpp"], - system_ext_specific: true, - cflags: [ - "-DLOG_TAG=\"bufferhubd\"", - "-DTRACE=0", - "-DATRACE_TAG=ATRACE_TAG_GRAPHICS", - ], - header_libs: ["libdvr_headers"], - shared_libs: sharedLibraries, - static_libs: [ - "libbufferhub", - "libbufferhubd", - "libperformance", - ], - name: "bufferhubd", - init_rc: ["bufferhubd.rc"], -} diff --git a/services/vr/bufferhubd/buffer_hub.cpp b/services/vr/bufferhubd/buffer_hub.cpp deleted file mode 100644 index 64092656e3..0000000000 --- a/services/vr/bufferhubd/buffer_hub.cpp +++ /dev/null @@ -1,349 +0,0 @@ -#include <inttypes.h> -#include <poll.h> - -#include <iomanip> -#include <memory> -#include <sstream> -#include <string> -#include <thread> - -#include <log/log.h> -#include <pdx/default_transport/service_endpoint.h> -#include <private/dvr/bufferhub_rpc.h> -#include <private/dvr/buffer_hub.h> -#include <private/dvr/consumer_channel.h> -#include <private/dvr/producer_channel.h> -#include <private/dvr/producer_queue_channel.h> -#include <utils/Trace.h> - -using android::pdx::Channel; -using android::pdx::ErrorStatus; -using android::pdx::Message; -using android::pdx::Status; -using android::pdx::default_transport::Endpoint; -using android::pdx::rpc::DispatchRemoteMethod; - -namespace android { -namespace dvr { - -BufferHubService::BufferHubService() - : BASE("BufferHub", Endpoint::Create(BufferHubRPC::kClientPath)) {} - -BufferHubService::~BufferHubService() {} - -bool BufferHubService::IsInitialized() const { return BASE::IsInitialized(); } - -std::string BufferHubService::DumpState(size_t /*max_length*/) { - std::ostringstream stream; - auto channels = GetChannels<BufferHubChannel>(); - - std::sort(channels.begin(), channels.end(), - [](const std::shared_ptr<BufferHubChannel>& a, - const std::shared_ptr<BufferHubChannel>& b) { - return a->buffer_id() < b->buffer_id(); - }); - - stream << "Active Producer Buffers:\n"; - stream << std::right; - stream << std::setw(6) << "Id"; - stream << " "; - stream << std::setw(9) << "Consumers"; - stream << " "; - stream << std::setw(14) << "Geometry"; - stream << " "; - stream << std::setw(6) << "Format"; - stream << " "; - stream << std::setw(10) << "Usage"; - stream << " "; - stream << std::setw(18) << "State"; - stream << " "; - stream << std::setw(18) << "Signaled"; - stream << " "; - stream << std::setw(10) << "Index"; - stream << std::endl; - - for (const auto& channel : channels) { - if (channel->channel_type() == BufferHubChannel::kProducerType) { - BufferHubChannel::BufferInfo info = channel->GetBufferInfo(); - - stream << std::right; - stream << std::setw(6) << info.id; - stream << " "; - stream << std::setw(9) << info.consumer_count; - stream << " "; - if (info.format == HAL_PIXEL_FORMAT_BLOB) { - std::string size = std::to_string(info.width) + " B"; - stream << std::setw(14) << size; - } else { - std::string dimensions = std::to_string(info.width) + "x" + - std::to_string(info.height) + "x" + - std::to_string(info.layer_count); - stream << std::setw(14) << dimensions; - } - stream << " "; - stream << std::setw(6) << info.format; - stream << " "; - stream << "0x" << std::hex << std::setfill('0'); - stream << std::setw(8) << info.usage; - stream << std::dec << std::setfill(' '); - stream << " "; - stream << "0x" << std::hex << std::setfill('0'); - stream << std::setw(16) << info.state; - stream << " "; - stream << "0x" << std::setw(16) << info.signaled_mask; - stream << std::dec << std::setfill(' '); - stream << " "; - stream << std::setw(8) << info.index; - stream << std::endl; - } - - if (channel->channel_type() == BufferHubChannel::kDetachedBufferType) { - BufferHubChannel::BufferInfo info = channel->GetBufferInfo(); - - stream << std::right; - stream << std::setw(6) << info.id; - stream << " "; - stream << std::setw(9) << "N/A"; - stream << " "; - if (info.format == HAL_PIXEL_FORMAT_BLOB) { - std::string size = std::to_string(info.width) + " B"; - stream << std::setw(14) << size; - } else { - std::string dimensions = std::to_string(info.width) + "x" + - std::to_string(info.height) + "x" + - std::to_string(info.layer_count); - stream << std::setw(14) << dimensions; - } - stream << " "; - stream << std::setw(6) << info.format; - stream << " "; - stream << "0x" << std::hex << std::setfill('0'); - stream << std::setw(8) << info.usage; - stream << std::dec << std::setfill(' '); - stream << " "; - stream << std::setw(9) << "N/A"; - stream << " "; - stream << std::hex << std::setfill(' '); - stream << std::setw(18) << "Detached"; - stream << " "; - stream << std::setw(18) << "N/A"; - stream << " "; - stream << std::setw(10) << "N/A"; - stream << std::endl; - } - } - - stream << std::endl; - stream << "Active Producer Queues:\n"; - stream << std::right << std::setw(6) << "Id"; - stream << std::right << std::setw(12) << " Capacity"; - stream << std::right << std::setw(12) << " Consumers"; - stream << " UsageSetMask"; - stream << " UsageClearMask"; - stream << " UsageDenySetMask"; - stream << " UsageDenyClearMask"; - stream << " "; - stream << std::endl; - - for (const auto& channel : channels) { - if (channel->channel_type() == BufferHubChannel::kProducerQueueType) { - BufferHubChannel::BufferInfo info = channel->GetBufferInfo(); - - stream << std::dec << std::setfill(' '); - stream << std::right << std::setw(6) << info.id; - stream << std::right << std::setw(12) << info.capacity; - stream << std::right << std::setw(12) << info.consumer_count; - stream << std::setw(5) << std::setfill(' ') << "0x"; - stream << std::hex << std::setfill('0'); - stream << std::setw(8) << info.usage_policy.usage_set_mask; - stream << std::setw(7) << std::setfill(' ') << "0x"; - stream << std::hex << std::setfill('0'); - stream << std::setw(8) << info.usage_policy.usage_clear_mask; - stream << std::setw(9) << std::setfill(' ') << "0x"; - stream << std::hex << std::setfill('0'); - stream << std::setw(8) << info.usage_policy.usage_deny_set_mask; - stream << std::setw(11) << std::setfill(' ') << "0x"; - stream << std::hex << std::setfill('0'); - stream << std::setw(8) << info.usage_policy.usage_deny_clear_mask; - stream << std::hex << std::setfill('0'); - stream << std::endl; - } - } - - stream << std::endl; - stream << "Active Consumer Queues:\n"; - stream << std::dec << std::setfill(' '); - stream << std::right << std::setw(6) << "Id"; - stream << std::right << std::setw(12) << " Imported"; - stream << " "; - stream << std::endl; - - for (const auto& channel : channels) { - if (channel->channel_type() == BufferHubChannel::kConsumerQueueType) { - BufferHubChannel::BufferInfo info = channel->GetBufferInfo(); - - stream << std::right << std::setw(6) << info.id; - stream << std::right << std::setw(12) << info.capacity; - stream << std::endl; - } - } - - stream << std::endl; - stream << "Orphaned Consumer Buffers:\n"; - stream << std::right; - stream << std::setw(6) << "Id"; - stream << " "; - stream << std::setw(14) << "Info"; - stream << std::endl; - - for (const auto& channel : channels) { - BufferHubChannel::BufferInfo info = channel->GetBufferInfo(); - // consumer_count is tracked by producer. When it's zero, producer must have - // already hung up and the consumer is orphaned. - if (channel->channel_type() == BufferHubChannel::kConsumerType && - info.consumer_count == 0) { - stream << std::right; - stream << std::setw(6) << info.id; - stream << " "; - - stream << std::setw(14) << "Orphaned."; - stream << (" channel_id=" + std::to_string(channel->channel_id())); - stream << std::endl; - } - } - - return stream.str(); -} - -void BufferHubService::HandleImpulse(Message& message) { - ATRACE_NAME("BufferHubService::HandleImpulse"); - if (auto channel = message.GetChannel<BufferHubChannel>()) - channel->HandleImpulse(message); -} - -pdx::Status<void> BufferHubService::HandleMessage(Message& message) { - ATRACE_NAME("BufferHubService::HandleMessage"); - auto channel = message.GetChannel<BufferHubChannel>(); - - ALOGD_IF( - TRACE, - "BufferHubService::HandleMessage: channel=%p channel_id=%d opcode=%d", - channel.get(), message.GetChannelId(), message.GetOp()); - - // If the channel is already set up, let it handle the message. - if (channel && !channel->HandleMessage(message)) - return DefaultHandleMessage(message); - - // This channel has not been set up yet, the following are valid operations. - switch (message.GetOp()) { - case BufferHubRPC::CreateBuffer::Opcode: - DispatchRemoteMethod<BufferHubRPC::CreateBuffer>( - *this, &BufferHubService::OnCreateBuffer, message); - return {}; - - case BufferHubRPC::CreateProducerQueue::Opcode: - DispatchRemoteMethod<BufferHubRPC::CreateProducerQueue>( - *this, &BufferHubService::OnCreateProducerQueue, message); - return {}; - - default: - return DefaultHandleMessage(message); - } -} - -Status<void> BufferHubService::OnCreateBuffer(Message& message, uint32_t width, - uint32_t height, uint32_t format, - uint64_t usage, - size_t meta_size_bytes) { - // Use the producer channel id as the global buffer id. - const int buffer_id = message.GetChannelId(); - ALOGD_IF(TRACE, - "BufferHubService::OnCreateBuffer: buffer_id=%d width=%u height=%u " - "format=%u usage=%" PRIx64 " meta_size_bytes=%zu", - buffer_id, width, height, format, usage, meta_size_bytes); - - // See if this channel is already attached to a buffer. - if (const auto channel = message.GetChannel<BufferHubChannel>()) { - ALOGE("BufferHubService::OnCreateBuffer: Buffer already created: buffer=%d", - buffer_id); - return ErrorStatus(EALREADY); - } - const uint32_t kDefaultLayerCount = 1; - auto status = ProducerChannel::Create(this, buffer_id, width, height, - kDefaultLayerCount, format, usage, - meta_size_bytes); - if (status) { - message.SetChannel(status.take()); - return {}; - } else { - ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer: %s", - status.GetErrorMessage().c_str()); - return status.error_status(); - } -} - -Status<QueueInfo> BufferHubService::OnCreateProducerQueue( - pdx::Message& message, const ProducerQueueConfig& producer_config, - const UsagePolicy& usage_policy) { - // Use the producer channel id as the global queue id. - const int queue_id = message.GetChannelId(); - ALOGD_IF(TRACE, "BufferHubService::OnCreateProducerQueue: queue_id=%d", - queue_id); - - // See if this channel is already attached to another object. - if (const auto channel = message.GetChannel<BufferHubChannel>()) { - ALOGE("BufferHubService::OnCreateProducerQueue: already created: queue=%d", - queue_id); - return ErrorStatus(EALREADY); - } - - auto status = ProducerQueueChannel::Create(this, queue_id, producer_config, - usage_policy); - if (status) { - message.SetChannel(status.take()); - return {{producer_config, queue_id}}; - } else { - ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!"); - return status.error_status(); - } -} - -void BufferHubChannel::SignalAvailable() { - ATRACE_NAME("BufferHubChannel::SignalAvailable"); - ALOGD_IF(TRACE, - "BufferHubChannel::SignalAvailable: channel_id=%d buffer_id=%d", - channel_id(), buffer_id()); - signaled_ = true; - const auto status = service_->ModifyChannelEvents(channel_id_, 0, POLLIN); - ALOGE_IF(!status, - "BufferHubChannel::SignalAvailable: failed to signal availability " - "channel_id=%d: %s", - channel_id_, status.GetErrorMessage().c_str()); -} - -void BufferHubChannel::ClearAvailable() { - ATRACE_NAME("BufferHubChannel::ClearAvailable"); - ALOGD_IF(TRACE, - "BufferHubChannel::ClearAvailable: channel_id=%d buffer_id=%d", - channel_id(), buffer_id()); - signaled_ = false; - const auto status = service_->ModifyChannelEvents(channel_id_, POLLIN, 0); - ALOGE_IF(!status, - "BufferHubChannel::ClearAvailable: failed to clear availability " - "channel_id=%d: %s", - channel_id_, status.GetErrorMessage().c_str()); -} - -void BufferHubChannel::Hangup() { - ATRACE_NAME("BufferHubChannel::Hangup"); - ALOGD_IF(TRACE, "BufferHubChannel::Hangup: channel_id=%d buffer_id=%d", - channel_id(), buffer_id()); - const auto status = service_->ModifyChannelEvents(channel_id_, 0, POLLHUP); - ALOGE_IF( - !status, - "BufferHubChannel::Hangup: failed to signal hangup channel_id=%d: %s", - channel_id_, status.GetErrorMessage().c_str()); -} - -} // namespace dvr -} // namespace android diff --git a/services/vr/bufferhubd/bufferhubd.cpp b/services/vr/bufferhubd/bufferhubd.cpp deleted file mode 100644 index 50cb3b7beb..0000000000 --- a/services/vr/bufferhubd/bufferhubd.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include <sched.h> -#include <sys/resource.h> -#include <unistd.h> - -#include <dvr/performance_client_api.h> -#include <log/log.h> -#include <pdx/service_dispatcher.h> -#include <private/dvr/buffer_hub.h> - -int main(int, char**) { - int ret = -1; - std::shared_ptr<android::dvr::BufferHubService> pdx_service; - std::unique_ptr<android::pdx::ServiceDispatcher> dispatcher; - - // We need to be able to create endpoints with full perms. - umask(0000); - - // Bump up the soft limit of open fd to the hard limit. - struct rlimit64 rlim; - ret = getrlimit64(RLIMIT_NOFILE, &rlim); - LOG_ALWAYS_FATAL_IF(ret != 0, "Failed to get nofile limit."); - - ALOGI("Current nofile limit is %llu/%llu.", rlim.rlim_cur, rlim.rlim_max); - rlim.rlim_cur = rlim.rlim_max; - ret = setrlimit64(RLIMIT_NOFILE, &rlim); - ALOGE_IF(ret < 0, "Failed to set nofile limit, error=%s", strerror(errno)); - - rlim.rlim_cur = -1; - rlim.rlim_max = -1; - if (getrlimit64(RLIMIT_NOFILE, &rlim) < 0) - ALOGE("Failed to get nofile limit."); - else - ALOGI("New nofile limit is %llu/%llu.", rlim.rlim_cur, rlim.rlim_max); - - dispatcher = android::pdx::ServiceDispatcher::Create(); - CHECK_ERROR(!dispatcher, error, "Failed to create service dispatcher\n"); - - pdx_service = android::dvr::BufferHubService::Create(); - CHECK_ERROR(!pdx_service, error, "Failed to create bufferhub pdx service\n"); - dispatcher->AddService(pdx_service); - - ret = dvrSetSchedulerClass(0, "graphics"); - CHECK_ERROR(ret < 0, error, "Failed to set thread priority"); - - ALOGI("Entering message loop."); - - ret = dispatcher->EnterDispatchLoop(); - CHECK_ERROR(ret < 0, error, "Dispatch loop exited because: %s\n", - strerror(-ret)); - -error: - return -ret; -} diff --git a/services/vr/bufferhubd/bufferhubd.rc b/services/vr/bufferhubd/bufferhubd.rc deleted file mode 100644 index c470de5c4a..0000000000 --- a/services/vr/bufferhubd/bufferhubd.rc +++ /dev/null @@ -1,5 +0,0 @@ -service bufferhubd /system/bin/bufferhubd - class core - user system - group system - socket pdx/system/buffer_hub/client stream 0660 system system u:object_r:pdx_bufferhub_client_endpoint_socket:s0 diff --git a/services/vr/bufferhubd/consumer_channel.cpp b/services/vr/bufferhubd/consumer_channel.cpp deleted file mode 100644 index c7695bc51f..0000000000 --- a/services/vr/bufferhubd/consumer_channel.cpp +++ /dev/null @@ -1,179 +0,0 @@ -#include <thread> - -#include <log/log.h> -#include <private/dvr/bufferhub_rpc.h> -#include <private/dvr/consumer_channel.h> -#include <private/dvr/producer_channel.h> -#include <utils/Trace.h> - -using android::pdx::BorrowedHandle; -using android::pdx::Channel; -using android::pdx::ErrorStatus; -using android::pdx::Message; -using android::pdx::Status; -using android::pdx::rpc::DispatchRemoteMethod; - -namespace android { -namespace dvr { - -ConsumerChannel::ConsumerChannel(BufferHubService* service, int buffer_id, - int channel_id, uint32_t client_state_mask, - const std::shared_ptr<Channel> producer) - : BufferHubChannel(service, buffer_id, channel_id, kConsumerType), - client_state_mask_(client_state_mask), - producer_(producer) { - GetProducer()->AddConsumer(this); -} - -ConsumerChannel::~ConsumerChannel() { - ALOGD_IF(TRACE, - "ConsumerChannel::~ConsumerChannel: channel_id=%d buffer_id=%d", - channel_id(), buffer_id()); - - if (auto producer = GetProducer()) { - producer->RemoveConsumer(this); - } -} - -BufferHubChannel::BufferInfo ConsumerChannel::GetBufferInfo() const { - BufferHubChannel::BufferInfo info; - if (auto producer = GetProducer()) { - // If producer has not hung up, copy most buffer info from the producer. - info = producer->GetBufferInfo(); - } else { - info.signaled_mask = client_state_mask(); - } - info.id = buffer_id(); - return info; -} - -std::shared_ptr<ProducerChannel> ConsumerChannel::GetProducer() const { - return std::static_pointer_cast<ProducerChannel>(producer_.lock()); -} - -void ConsumerChannel::HandleImpulse(Message& message) { - ATRACE_NAME("ConsumerChannel::HandleImpulse"); - switch (message.GetOp()) { - case BufferHubRPC::ConsumerAcquire::Opcode: - OnConsumerAcquire(message); - break; - case BufferHubRPC::ConsumerRelease::Opcode: - OnConsumerRelease(message, {}); - break; - } -} - -bool ConsumerChannel::HandleMessage(Message& message) { - ATRACE_NAME("ConsumerChannel::HandleMessage"); - auto producer = GetProducer(); - if (!producer) - REPLY_ERROR_RETURN(message, EPIPE, true); - - switch (message.GetOp()) { - case BufferHubRPC::GetBuffer::Opcode: - DispatchRemoteMethod<BufferHubRPC::GetBuffer>( - *this, &ConsumerChannel::OnGetBuffer, message); - return true; - - case BufferHubRPC::NewConsumer::Opcode: - DispatchRemoteMethod<BufferHubRPC::NewConsumer>( - *producer, &ProducerChannel::OnNewConsumer, message); - return true; - - case BufferHubRPC::ConsumerAcquire::Opcode: - DispatchRemoteMethod<BufferHubRPC::ConsumerAcquire>( - *this, &ConsumerChannel::OnConsumerAcquire, message); - return true; - - case BufferHubRPC::ConsumerRelease::Opcode: - DispatchRemoteMethod<BufferHubRPC::ConsumerRelease>( - *this, &ConsumerChannel::OnConsumerRelease, message); - return true; - - default: - return false; - } -} - -Status<BufferDescription<BorrowedHandle>> ConsumerChannel::OnGetBuffer( - Message& /*message*/) { - ATRACE_NAME("ConsumerChannel::OnGetBuffer"); - ALOGD_IF(TRACE, "ConsumerChannel::OnGetBuffer: buffer=%d", buffer_id()); - if (auto producer = GetProducer()) { - return {producer->GetBuffer(client_state_mask_)}; - } else { - return ErrorStatus(EPIPE); - } -} - -Status<LocalFence> ConsumerChannel::OnConsumerAcquire(Message& message) { - ATRACE_NAME("ConsumerChannel::OnConsumerAcquire"); - auto producer = GetProducer(); - if (!producer) - return ErrorStatus(EPIPE); - - if (acquired_ || released_) { - ALOGE( - "ConsumerChannel::OnConsumerAcquire: Acquire when not posted: " - "acquired=%d released=%d channel_id=%d buffer_id=%d", - acquired_, released_, message.GetChannelId(), producer->buffer_id()); - return ErrorStatus(EBUSY); - } else { - auto status = producer->OnConsumerAcquire(message); - if (status) { - ClearAvailable(); - acquired_ = true; - } - return status; - } -} - -Status<void> ConsumerChannel::OnConsumerRelease(Message& message, - LocalFence release_fence) { - ATRACE_NAME("ConsumerChannel::OnConsumerRelease"); - auto producer = GetProducer(); - if (!producer) - return ErrorStatus(EPIPE); - - if (!acquired_ || released_) { - ALOGE( - "ConsumerChannel::OnConsumerRelease: Release when not acquired: " - "acquired=%d released=%d channel_id=%d buffer_id=%d", - acquired_, released_, message.GetChannelId(), producer->buffer_id()); - return ErrorStatus(EBUSY); - } else { - auto status = - producer->OnConsumerRelease(message, std::move(release_fence)); - if (status) { - ClearAvailable(); - acquired_ = false; - released_ = true; - } - return status; - } -} - -void ConsumerChannel::OnProducerGained() { - // Clear the signal if exist. There is a possiblity that the signal still - // exist in consumer client when producer gains the buffer, e.g. newly added - // consumer fail to acquire the previous posted buffer in time. Then, when - // producer gains back the buffer, posts the buffer again and signal the - // consumer later, there won't be an signal change in eventfd, and thus, - // consumer will miss the posted buffer later. Thus, we need to clear the - // signal in consumer clients if the signal exist. - ClearAvailable(); -} - -void ConsumerChannel::OnProducerPosted() { - acquired_ = false; - released_ = false; - SignalAvailable(); -} - -void ConsumerChannel::OnProducerClosed() { - producer_.reset(); - Hangup(); -} - -} // namespace dvr -} // namespace android diff --git a/services/vr/bufferhubd/consumer_queue_channel.cpp b/services/vr/bufferhubd/consumer_queue_channel.cpp deleted file mode 100644 index 5d7d4e9057..0000000000 --- a/services/vr/bufferhubd/consumer_queue_channel.cpp +++ /dev/null @@ -1,166 +0,0 @@ -#include <pdx/channel_handle.h> -#include <private/dvr/consumer_queue_channel.h> -#include <private/dvr/producer_channel.h> - -using android::pdx::ErrorStatus; -using android::pdx::RemoteChannelHandle; -using android::pdx::Status; -using android::pdx::rpc::DispatchRemoteMethod; -using android::pdx::rpc::RemoteMethodError; - -namespace android { -namespace dvr { - -ConsumerQueueChannel::ConsumerQueueChannel( - BufferHubService* service, int buffer_id, int channel_id, - const std::shared_ptr<Channel>& producer, bool silent) - : BufferHubChannel(service, buffer_id, channel_id, kConsumerQueueType), - producer_(producer), - capacity_(0), - silent_(silent) { - GetProducer()->AddConsumer(this); -} - -ConsumerQueueChannel::~ConsumerQueueChannel() { - ALOGD_IF(TRACE, "ConsumerQueueChannel::~ConsumerQueueChannel: channel_id=%d", - channel_id()); - - if (auto producer = GetProducer()) { - producer->RemoveConsumer(this); - } -} - -bool ConsumerQueueChannel::HandleMessage(Message& message) { - ATRACE_NAME("ConsumerQueueChannel::HandleMessage"); - auto producer = GetProducer(); - if (!producer) { - RemoteMethodError(message, EPIPE); - return true; - } - - switch (message.GetOp()) { - case BufferHubRPC::CreateConsumerQueue::Opcode: - DispatchRemoteMethod<BufferHubRPC::CreateConsumerQueue>( - *producer, &ProducerQueueChannel::OnCreateConsumerQueue, message); - return true; - - case BufferHubRPC::GetQueueInfo::Opcode: - DispatchRemoteMethod<BufferHubRPC::GetQueueInfo>( - *producer, &ProducerQueueChannel::OnGetQueueInfo, message); - return true; - - case BufferHubRPC::ConsumerQueueImportBuffers::Opcode: - DispatchRemoteMethod<BufferHubRPC::ConsumerQueueImportBuffers>( - *this, &ConsumerQueueChannel::OnConsumerQueueImportBuffers, message); - return true; - - default: - return false; - } -} - -std::shared_ptr<ProducerQueueChannel> ConsumerQueueChannel::GetProducer() - const { - return std::static_pointer_cast<ProducerQueueChannel>(producer_.lock()); -} - -void ConsumerQueueChannel::HandleImpulse(Message& /* message */) { - ATRACE_NAME("ConsumerQueueChannel::HandleImpulse"); -} - -BufferHubChannel::BufferInfo ConsumerQueueChannel::GetBufferInfo() const { - BufferHubChannel::BufferInfo info; - if (auto producer = GetProducer()) { - // If producer has not hung up, copy most buffer info from the producer. - info = producer->GetBufferInfo(); - } - info.id = buffer_id(); - info.capacity = capacity_; - return info; -} - -void ConsumerQueueChannel::RegisterNewBuffer( - const std::shared_ptr<ProducerChannel>& producer_channel, - size_t producer_slot) { - ALOGD_IF(TRACE, "%s: queue_id=%d buffer_id=%d slot=%zu silent=%d", - __FUNCTION__, buffer_id(), producer_channel->buffer_id(), - producer_slot, silent_); - // Only register buffers if the queue is not silent. - if (silent_) { - return; - } - - auto status = producer_channel->CreateConsumerStateMask(); - if (!status.ok()) { - ALOGE("%s: Failed to create consumer state mask: %s", __FUNCTION__, - status.GetErrorMessage().c_str()); - return; - } - uint64_t consumer_state_mask = status.get(); - - pending_buffer_slots_.emplace(producer_channel, producer_slot, - consumer_state_mask); - // Signal the client that there is new buffer available. - SignalAvailable(); -} - -Status<std::vector<std::pair<RemoteChannelHandle, size_t>>> -ConsumerQueueChannel::OnConsumerQueueImportBuffers(Message& message) { - std::vector<std::pair<RemoteChannelHandle, size_t>> buffer_handles; - ATRACE_NAME(__FUNCTION__); - ALOGD_IF(TRACE, "%s: pending_buffer_slots=%zu", __FUNCTION__, - pending_buffer_slots_.size()); - - // Indicate this is a silent queue that will not import buffers. - if (silent_) - return ErrorStatus(EBADR); - - while (!pending_buffer_slots_.empty()) { - auto producer_channel = - pending_buffer_slots_.front().producer_channel.lock(); - size_t producer_slot = pending_buffer_slots_.front().producer_slot; - uint64_t consumer_state_mask = - pending_buffer_slots_.front().consumer_state_mask; - pending_buffer_slots_.pop(); - - // It's possible that the producer channel has expired. When this occurs, - // ignore the producer channel. - if (producer_channel == nullptr) { - ALOGW("%s: producer channel has already been expired.", __FUNCTION__); - continue; - } - - auto status = - producer_channel->CreateConsumer(message, consumer_state_mask); - - // If no buffers are imported successfully, clear available and return an - // error. Otherwise, return all consumer handles already imported - // successfully, but keep available bits on, so that the client can retry - // importing remaining consumer buffers. - if (!status) { - ALOGE("%s: Failed create consumer: %s", __FUNCTION__, - status.GetErrorMessage().c_str()); - if (buffer_handles.empty()) { - ClearAvailable(); - return status.error_status(); - } else { - return {std::move(buffer_handles)}; - } - } - - buffer_handles.emplace_back(status.take(), producer_slot); - } - - ClearAvailable(); - return {std::move(buffer_handles)}; -} - -void ConsumerQueueChannel::OnProducerClosed() { - ALOGD_IF(TRACE, "ConsumerQueueChannel::OnProducerClosed: queue_id=%d", - buffer_id()); - producer_.reset(); - Hangup(); -} - -} // namespace dvr -} // namespace android diff --git a/services/vr/bufferhubd/include/private/dvr/buffer_hub.h b/services/vr/bufferhubd/include/private/dvr/buffer_hub.h deleted file mode 100644 index 909d69b12c..0000000000 --- a/services/vr/bufferhubd/include/private/dvr/buffer_hub.h +++ /dev/null @@ -1,158 +0,0 @@ -#ifndef ANDROID_DVR_BUFFERHUBD_BUFFER_HUB_H_ -#define ANDROID_DVR_BUFFERHUBD_BUFFER_HUB_H_ - -#include <memory> -#include <string> -#include <unordered_map> - -#include <hardware/gralloc.h> -#include <pdx/service.h> -#include <private/dvr/bufferhub_rpc.h> - -namespace android { -namespace dvr { - -class BufferHubService; -class ConsumerChannel; -class ProducerChannel; -class ConsumerQueueChannel; -class ProducerQueueChannel; - -class BufferHubChannel : public pdx::Channel { - public: - enum ChannelType { - kProducerType, - kConsumerType, - kDetachedBufferType, - kProducerQueueType, - kConsumerQueueType, - }; - - BufferHubChannel(BufferHubService* service, int buffer_id, int channel_id, - ChannelType channel_type) - : service_(service), - buffer_id_(buffer_id), - channel_id_(channel_id), - channel_type_(channel_type) {} - virtual ~BufferHubChannel() {} - - virtual bool HandleMessage(pdx::Message& message) = 0; - virtual void HandleImpulse(pdx::Message& message) = 0; - - // Captures buffer info for use by BufferHubService::DumpState(). - struct BufferInfo { - // Common data field shared by ProducerBuffer and ProducerQueue. - int id = -1; - int type = -1; - size_t consumer_count = 0; - - // Data field for producer buffer. - uint32_t width = 0; - uint32_t height = 0; - uint32_t layer_count = 0; - uint32_t format = 0; - uint64_t usage = 0; - uint64_t state = 0; - uint64_t signaled_mask = 0; - uint64_t index = 0; - - // Data filed for producer queue. - size_t capacity = 0; - UsagePolicy usage_policy{0, 0, 0, 0}; - - BufferInfo(int id, size_t consumer_count, uint32_t width, uint32_t height, - uint32_t layer_count, uint32_t format, uint64_t usage, - uint64_t state, uint64_t signaled_mask, uint64_t index) - : id(id), - type(kProducerType), - consumer_count(consumer_count), - width(width), - height(height), - layer_count(layer_count), - format(format), - usage(usage), - state(state), - signaled_mask(signaled_mask), - index(index) {} - - BufferInfo(int id, size_t consumer_count, size_t capacity, - const UsagePolicy& usage_policy) - : id(id), - type(kProducerQueueType), - consumer_count(consumer_count), - capacity(capacity), - usage_policy(usage_policy) {} - - BufferInfo() {} - }; - - // Returns the buffer info for this buffer. - virtual BufferInfo GetBufferInfo() const = 0; - - // Signal the client fd that an ownership change occurred using POLLIN. - void SignalAvailable(); - - // Clear the ownership change event. - void ClearAvailable(); - - // Signal hangup event. - void Hangup(); - - BufferHubService* service() const { return service_; } - ChannelType channel_type() const { return channel_type_; } - int buffer_id() const { return buffer_id_; } - - int channel_id() const { return channel_id_; } - - bool signaled() const { return signaled_; } - - private: - BufferHubService* service_; - - // Static id of the buffer for logging and informational purposes. This id - // does not change for the life of the buffer. - // TODO(eieio): Consider using an id allocator instead of the originating - // channel id; channel ids wrap after 2^31 ids, but this is not a problem in - // general because channel ids are not used for any lookup in this service. - int buffer_id_; - - // The channel id of the buffer. - int channel_id_; - - bool signaled_; - - ChannelType channel_type_; - - BufferHubChannel(const BufferHubChannel&) = delete; - void operator=(const BufferHubChannel&) = delete; -}; - -class BufferHubService : public pdx::ServiceBase<BufferHubService> { - public: - BufferHubService(); - ~BufferHubService() override; - - pdx::Status<void> HandleMessage(pdx::Message& message) override; - void HandleImpulse(pdx::Message& message) override; - - bool IsInitialized() const override; - std::string DumpState(size_t max_length) override; - - private: - friend BASE; - - pdx::Status<void> OnCreateBuffer(pdx::Message& message, uint32_t width, - uint32_t height, uint32_t format, - uint64_t usage, size_t meta_size_bytes); - pdx::Status<QueueInfo> OnCreateProducerQueue( - pdx::Message& message, const ProducerQueueConfig& producer_config, - const UsagePolicy& usage_policy); - - BufferHubService(const BufferHubService&) = delete; - void operator=(const BufferHubService&) = delete; -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_BUFFERHUBD_BUFFER_HUB_H_ diff --git a/services/vr/bufferhubd/include/private/dvr/consumer_channel.h b/services/vr/bufferhubd/include/private/dvr/consumer_channel.h deleted file mode 100644 index 5ee551f115..0000000000 --- a/services/vr/bufferhubd/include/private/dvr/consumer_channel.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef ANDROID_DVR_BUFFERHUBD_CONSUMER_CHANNEL_H_ -#define ANDROID_DVR_BUFFERHUBD_CONSUMER_CHANNEL_H_ - -#include <pdx/rpc/buffer_wrapper.h> -#include <private/dvr/bufferhub_rpc.h> -#include <private/dvr/buffer_hub.h> - -namespace android { -namespace dvr { - -// Consumer channels are attached to a Producer channel -class ConsumerChannel : public BufferHubChannel { - public: - using BorrowedHandle = pdx::BorrowedHandle; - using Channel = pdx::Channel; - using Message = pdx::Message; - - ConsumerChannel(BufferHubService* service, int buffer_id, int channel_id, - uint32_t client_state_mask, - const std::shared_ptr<Channel> producer); - ~ConsumerChannel() override; - - bool HandleMessage(Message& message) override; - void HandleImpulse(Message& message) override; - - uint32_t client_state_mask() const { return client_state_mask_; } - BufferInfo GetBufferInfo() const override; - - void OnProducerGained(); - void OnProducerPosted(); - void OnProducerClosed(); - - private: - std::shared_ptr<ProducerChannel> GetProducer() const; - - pdx::Status<BufferDescription<BorrowedHandle>> OnGetBuffer(Message& message); - - pdx::Status<LocalFence> OnConsumerAcquire(Message& message); - pdx::Status<void> OnConsumerRelease(Message& message, - LocalFence release_fence); - - uint32_t client_state_mask_{0U}; - bool acquired_{false}; - bool released_{true}; - std::weak_ptr<Channel> producer_; - - ConsumerChannel(const ConsumerChannel&) = delete; - void operator=(const ConsumerChannel&) = delete; -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_BUFFERHUBD_CONSUMER_CHANNEL_H_ diff --git a/services/vr/bufferhubd/include/private/dvr/consumer_queue_channel.h b/services/vr/bufferhubd/include/private/dvr/consumer_queue_channel.h deleted file mode 100644 index 3a81b03761..0000000000 --- a/services/vr/bufferhubd/include/private/dvr/consumer_queue_channel.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef ANDROID_DVR_BUFFERHUBD_CONSUMER_QUEUE_CHANNEL_H_ -#define ANDROID_DVR_BUFFERHUBD_CONSUMER_QUEUE_CHANNEL_H_ - -#include <queue> - -#include <private/dvr/buffer_hub.h> -#include <private/dvr/bufferhub_rpc.h> -#include <private/dvr/consumer_channel.h> -#include <private/dvr/producer_queue_channel.h> - -namespace android { -namespace dvr { - -class ConsumerQueueChannel : public BufferHubChannel { - public: - using Message = pdx::Message; - using RemoteChannelHandle = pdx::RemoteChannelHandle; - - ConsumerQueueChannel(BufferHubService* service, int buffer_id, int channel_id, - const std::shared_ptr<Channel>& producer, bool silent); - ~ConsumerQueueChannel() override; - - bool HandleMessage(Message& message) override; - void HandleImpulse(Message& message) override; - - BufferInfo GetBufferInfo() const override; - - // Called by ProdcuerQueueChannel to notify consumer queue that a new - // buffer has been allocated. - void RegisterNewBuffer( - const std::shared_ptr<ProducerChannel>& producer_channel, - size_t producer_slot); - - // Called after clients been signaled by service that new buffer has been - // allocated. Clients uses kOpConsumerQueueImportBuffers to import new - // consumer buffers and this handler returns a vector of fd representing - // BufferConsumers that clients can import. - pdx::Status<std::vector<std::pair<RemoteChannelHandle, size_t>>> - OnConsumerQueueImportBuffers(Message& message); - - void OnProducerClosed(); - - private: - // Data structure to store relavant info of a newly allocated producer buffer - // so that consumer channel and buffer can be created later. - struct PendingBuffer { - PendingBuffer(std::shared_ptr<ProducerChannel> channel, size_t slot, - uint64_t mask) { - producer_channel = channel; - producer_slot = slot; - consumer_state_mask = mask; - } - PendingBuffer() = delete; - - std::weak_ptr<ProducerChannel> producer_channel; - size_t producer_slot; - uint64_t consumer_state_mask; - }; - - std::shared_ptr<ProducerQueueChannel> GetProducer() const; - - // Pointer to the producer channel. - std::weak_ptr<Channel> producer_; - - // Tracks newly allocated buffer producers along with it's slot number. - std::queue<PendingBuffer> pending_buffer_slots_; - - // Tracks how many buffers have this queue imported. - size_t capacity_; - - // A silent queue does not signal or export buffers. It is only used to spawn - // another consumer queue. - bool silent_; - - ConsumerQueueChannel(const ConsumerQueueChannel&) = delete; - void operator=(const ConsumerQueueChannel&) = delete; -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_BUFFERHUBD_CONSUMER_QUEUE_CHANNEL_H_ diff --git a/services/vr/bufferhubd/include/private/dvr/producer_channel.h b/services/vr/bufferhubd/include/private/dvr/producer_channel.h deleted file mode 100644 index 45593ad955..0000000000 --- a/services/vr/bufferhubd/include/private/dvr/producer_channel.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef ANDROID_DVR_BUFFERHUBD_PRODUCER_CHANNEL_H_ -#define ANDROID_DVR_BUFFERHUBD_PRODUCER_CHANNEL_H_ - -#include <functional> -#include <memory> -#include <vector> - -#include <pdx/channel_handle.h> -#include <pdx/file_handle.h> -#include <pdx/rpc/buffer_wrapper.h> -#include <private/dvr/buffer_hub.h> -#include <private/dvr/bufferhub_rpc.h> -#include <private/dvr/ion_buffer.h> - -namespace android { -namespace dvr { - -// The buffer changes ownership according to the following sequence: -// POST -> ACQUIRE/RELEASE (all consumers) -> GAIN (producer acquires) -> POST - -// The producer channel is owned by a single app that writes into buffers and -// calls POST when drawing is complete. This channel has a set of consumer -// channels associated with it that are waiting for notifications. -class ProducerChannel : public BufferHubChannel { - public: - using Message = pdx::Message; - using BorrowedHandle = pdx::BorrowedHandle; - using RemoteChannelHandle = pdx::RemoteChannelHandle; - template <typename T> - using BufferWrapper = pdx::rpc::BufferWrapper<T>; - - static std::unique_ptr<ProducerChannel> Create(BufferHubService* service, - int buffer_id, int channel_id, - IonBuffer buffer, - IonBuffer metadata_buffer, - size_t user_metadata_size); - - static pdx::Status<std::shared_ptr<ProducerChannel>> Create( - BufferHubService* service, int channel_id, uint32_t width, - uint32_t height, uint32_t layer_count, uint32_t format, uint64_t usage, - size_t user_metadata_size); - - ~ProducerChannel() override; - - uint32_t buffer_state() const { - return buffer_state_->load(std::memory_order_acquire); - } - - bool HandleMessage(Message& message) override; - void HandleImpulse(Message& message) override; - - BufferInfo GetBufferInfo() const override; - - BufferDescription<BorrowedHandle> GetBuffer(uint32_t client_state_mask); - - pdx::Status<RemoteChannelHandle> CreateConsumer(Message& message, - uint32_t consumer_state_mask); - pdx::Status<uint32_t> CreateConsumerStateMask(); - pdx::Status<RemoteChannelHandle> OnNewConsumer(Message& message); - - pdx::Status<LocalFence> OnConsumerAcquire(Message& message); - pdx::Status<void> OnConsumerRelease(Message& message, - LocalFence release_fence); - - void OnConsumerOrphaned(const uint32_t& consumer_state_mask); - - void AddConsumer(ConsumerChannel* channel); - void RemoveConsumer(ConsumerChannel* channel); - - bool CheckParameters(uint32_t width, uint32_t height, uint32_t layer_count, - uint32_t format, uint64_t usage, - size_t user_metadata_size) const; - - private: - std::vector<ConsumerChannel*> consumer_channels_; - - IonBuffer buffer_; - - // IonBuffer that is shared between bufferhubd, producer, and consumers. - IonBuffer metadata_buffer_; - BufferHubDefs::MetadataHeader* metadata_header_ = nullptr; - std::atomic<uint32_t>* buffer_state_ = nullptr; - std::atomic<uint32_t>* fence_state_ = nullptr; - std::atomic<uint32_t>* active_clients_bit_mask_ = nullptr; - - // All orphaned consumer bits. Valid bits are the lower 63 bits, while the - // highest bit is reserved for the producer and should not be set. - uint32_t orphaned_consumer_bit_mask_{0U}; - - LocalFence post_fence_; - LocalFence returned_fence_; - size_t user_metadata_size_; // size of user requested buffer buffer size. - size_t metadata_buf_size_; // size of the ion buffer that holds metadata. - - pdx::LocalHandle acquire_fence_fd_; - pdx::LocalHandle release_fence_fd_; - pdx::LocalHandle dummy_fence_fd_; - - ProducerChannel(BufferHubService* service, int buffer_id, int channel_id, - IonBuffer buffer, IonBuffer metadata_buffer, - size_t user_metadata_size, int* error); - ProducerChannel(BufferHubService* service, int channel, uint32_t width, - uint32_t height, uint32_t layer_count, uint32_t format, - uint64_t usage, size_t user_metadata_size, int* error); - - int InitializeBuffer(); - pdx::Status<BufferDescription<BorrowedHandle>> OnGetBuffer(Message& message); - pdx::Status<void> OnProducerPost(Message& message, LocalFence acquire_fence); - pdx::Status<LocalFence> OnProducerGain(Message& message); - - // Remove consumer from atomics in shared memory based on consumer_state_mask. - // This function is used for clean up for failures in CreateConsumer method. - void RemoveConsumerClientMask(uint32_t consumer_state_mask); - - // Checks whether the buffer is released by all active clients, excluding - // orphaned consumers. - bool IsBufferReleasedByAllActiveClientsExceptForOrphans() const; - - ProducerChannel(const ProducerChannel&) = delete; - void operator=(const ProducerChannel&) = delete; -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_BUFFERHUBD_PRODUCER_CHANNEL_H_ diff --git a/services/vr/bufferhubd/include/private/dvr/producer_queue_channel.h b/services/vr/bufferhubd/include/private/dvr/producer_queue_channel.h deleted file mode 100644 index 0456ad8a39..0000000000 --- a/services/vr/bufferhubd/include/private/dvr/producer_queue_channel.h +++ /dev/null @@ -1,94 +0,0 @@ -#ifndef ANDROID_DVR_BUFFERHUBD_PRODUCER_QUEUE_CHANNEL_H_ -#define ANDROID_DVR_BUFFERHUBD_PRODUCER_QUEUE_CHANNEL_H_ - -#include <pdx/status.h> -#include <private/dvr/bufferhub_rpc.h> -#include <private/dvr/buffer_hub.h> - -namespace android { -namespace dvr { - -class ProducerQueueChannel : public BufferHubChannel { - public: - static pdx::Status<std::shared_ptr<ProducerQueueChannel>> Create( - BufferHubService* service, int channel_id, - const ProducerQueueConfig& config, const UsagePolicy& usage_policy); - ~ProducerQueueChannel() override; - - bool HandleMessage(pdx::Message& message) override; - void HandleImpulse(pdx::Message& message) override; - - BufferInfo GetBufferInfo() const override; - - // Handles client request to create a new consumer queue attached to current - // producer queue. - // Returns a handle for the service channel, as well as the size of the - // metadata associated with the queue. - pdx::Status<pdx::RemoteChannelHandle> OnCreateConsumerQueue( - pdx::Message& message, bool silent); - - pdx::Status<QueueInfo> OnGetQueueInfo(pdx::Message& message); - - // Allocate a new BufferHubProducer according to the input spec. Client may - // handle this as if a new producer is created through kOpCreateBuffer. - pdx::Status<std::vector<std::pair<pdx::RemoteChannelHandle, size_t>>> - OnProducerQueueAllocateBuffers(pdx::Message& message, uint32_t width, - uint32_t height, uint32_t layer_count, - uint32_t format, uint64_t usage, - size_t buffer_count); - - // Inserts a ProducerBuffer into the queue. Note that the buffer must be in - // Gain'ed state for the operation to succeed. - pdx::Status<size_t> OnProducerQueueInsertBuffer(pdx::Message& message, int buffer_cid); - - // Removes a ProducerBuffer indicated by |slot|. Note that the buffer must be - // in Gain'ed state for the operation to succeed. - pdx::Status<void> OnProducerQueueRemoveBuffer(pdx::Message& message, - size_t slot); - - void AddConsumer(ConsumerQueueChannel* channel); - void RemoveConsumer(ConsumerQueueChannel* channel); - - private: - ProducerQueueChannel(BufferHubService* service, int channel_id, - const ProducerQueueConfig& config, - const UsagePolicy& usage_policy, int* error); - - // Allocate one single producer buffer by |OnProducerQueueAllocateBuffers|. - // Note that the newly created buffer's file handle will be pushed to client - // and our return type is a RemoteChannelHandle. - // Returns the remote channel handle and the slot number for the newly - // allocated buffer. - pdx::Status<std::pair<pdx::RemoteChannelHandle, size_t>> AllocateBuffer( - pdx::Message& message, uint32_t width, uint32_t height, - uint32_t layer_count, uint32_t format, uint64_t usage); - - // The producer queue's configuration. Now we assume the configuration is - // immutable once the queue is created. - ProducerQueueConfig config_; - - // A set of variables to control what |usage| bits can this ProducerQueue - // allocate. - UsagePolicy usage_policy_; - - // Provides access to the |channel_id| of all consumer channels associated - // with this producer. - std::vector<ConsumerQueueChannel*> consumer_channels_; - - // Tracks how many buffers have this queue allocated. - size_t capacity_; - - // Tracks of all buffer producer allocated through this buffer queue. Once - // a buffer get allocated, it will take a logical slot in the |buffers_| array - // and the slot number will stay unchanged during the entire life cycle of the - // queue. - std::weak_ptr<ProducerChannel> buffers_[BufferHubRPC::kMaxQueueCapacity]; - - ProducerQueueChannel(const ProducerQueueChannel&) = delete; - void operator=(const ProducerQueueChannel&) = delete; -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_BUFFERHUBD_PRODUCER_QUEUE_CHANNEL_H_ diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp deleted file mode 100644 index b71964ba00..0000000000 --- a/services/vr/bufferhubd/producer_channel.cpp +++ /dev/null @@ -1,673 +0,0 @@ -#include <sys/epoll.h> -#include <sys/eventfd.h> -#include <sys/poll.h> - -#include <algorithm> -#include <atomic> -#include <thread> - -#include <log/log.h> -#include <private/dvr/bufferhub_rpc.h> -#include <private/dvr/consumer_channel.h> -#include <private/dvr/producer_channel.h> -#include <sync/sync.h> -#include <utils/Trace.h> - -using android::pdx::BorrowedHandle; -using android::pdx::ErrorStatus; -using android::pdx::Message; -using android::pdx::RemoteChannelHandle; -using android::pdx::Status; -using android::pdx::rpc::BufferWrapper; -using android::pdx::rpc::DispatchRemoteMethod; -using android::pdx::rpc::WrapBuffer; - -namespace android { -namespace dvr { - -ProducerChannel::ProducerChannel(BufferHubService* service, int buffer_id, - int channel_id, IonBuffer buffer, - IonBuffer metadata_buffer, - size_t user_metadata_size, int* error) - : BufferHubChannel(service, buffer_id, channel_id, kProducerType), - buffer_(std::move(buffer)), - metadata_buffer_(std::move(metadata_buffer)), - user_metadata_size_(user_metadata_size), - metadata_buf_size_(BufferHubDefs::kMetadataHeaderSize + - user_metadata_size) { - if (!buffer_.IsValid()) { - ALOGE("ProducerChannel::ProducerChannel: Invalid buffer."); - *error = -EINVAL; - return; - } - if (!metadata_buffer_.IsValid()) { - ALOGE("ProducerChannel::ProducerChannel: Invalid metadata buffer."); - *error = -EINVAL; - return; - } - - *error = InitializeBuffer(); -} - -ProducerChannel::ProducerChannel(BufferHubService* service, int channel_id, - uint32_t width, uint32_t height, - uint32_t layer_count, uint32_t format, - uint64_t usage, size_t user_metadata_size, - int* error) - : BufferHubChannel(service, channel_id, channel_id, kProducerType), - user_metadata_size_(user_metadata_size), - metadata_buf_size_(BufferHubDefs::kMetadataHeaderSize + - user_metadata_size) { - if (int ret = buffer_.Alloc(width, height, layer_count, format, usage)) { - ALOGE("ProducerChannel::ProducerChannel: Failed to allocate buffer: %s", - strerror(-ret)); - *error = ret; - return; - } - - if (int ret = metadata_buffer_.Alloc(metadata_buf_size_, /*height=*/1, - /*layer_count=*/1, - BufferHubDefs::kMetadataFormat, - BufferHubDefs::kMetadataUsage)) { - ALOGE("ProducerChannel::ProducerChannel: Failed to allocate metadata: %s", - strerror(-ret)); - *error = ret; - return; - } - - *error = InitializeBuffer(); -} - -int ProducerChannel::InitializeBuffer() { - void* metadata_ptr = nullptr; - if (int ret = metadata_buffer_.Lock(BufferHubDefs::kMetadataUsage, /*x=*/0, - /*y=*/0, metadata_buf_size_, - /*height=*/1, &metadata_ptr)) { - ALOGE("ProducerChannel::ProducerChannel: Failed to lock metadata."); - return ret; - } - metadata_header_ = - reinterpret_cast<BufferHubDefs::MetadataHeader*>(metadata_ptr); - - // Using placement new here to reuse shared memory instead of new allocation - // and also initialize the value to zero. - buffer_state_ = new (&metadata_header_->bufferState) std::atomic<uint32_t>(0); - fence_state_ = new (&metadata_header_->fenceState) std::atomic<uint32_t>(0); - active_clients_bit_mask_ = - new (&metadata_header_->activeClientsBitMask) std::atomic<uint32_t>(0); - - // Producer channel is never created after consumer channel, and one buffer - // only have one fixed producer for now. Thus, it is correct to assume - // producer state bit is kFirstClientBitMask for now. - active_clients_bit_mask_->store(BufferHubDefs::kFirstClientBitMask, - std::memory_order_release); - - acquire_fence_fd_.Reset(epoll_create1(EPOLL_CLOEXEC)); - release_fence_fd_.Reset(epoll_create1(EPOLL_CLOEXEC)); - if (!acquire_fence_fd_ || !release_fence_fd_) { - ALOGE("ProducerChannel::ProducerChannel: Failed to create shared fences."); - return -EIO; - } - - dummy_fence_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK)); - if (!dummy_fence_fd_) { - ALOGE("ProducerChannel::ProducerChannel: Failed to create dummy fences."); - return EIO; - } - - epoll_event event; - event.events = 0; - event.data.u32 = 0U; - if (epoll_ctl(release_fence_fd_.Get(), EPOLL_CTL_ADD, dummy_fence_fd_.Get(), - &event) < 0) { - ALOGE( - "ProducerChannel::ProducerChannel: Failed to modify the shared " - "release fence to include the dummy fence: %s", - strerror(errno)); - return -EIO; - } - - // Success. - return 0; -} - -std::unique_ptr<ProducerChannel> ProducerChannel::Create( - BufferHubService* service, int buffer_id, int channel_id, IonBuffer buffer, - IonBuffer metadata_buffer, size_t user_metadata_size) { - int error = 0; - std::unique_ptr<ProducerChannel> producer(new ProducerChannel( - service, buffer_id, channel_id, std::move(buffer), - std::move(metadata_buffer), user_metadata_size, &error)); - - if (error < 0) - return nullptr; - else - return producer; -} - -Status<std::shared_ptr<ProducerChannel>> ProducerChannel::Create( - BufferHubService* service, int channel_id, uint32_t width, uint32_t height, - uint32_t layer_count, uint32_t format, uint64_t usage, - size_t user_metadata_size) { - int error; - std::shared_ptr<ProducerChannel> producer( - new ProducerChannel(service, channel_id, width, height, layer_count, - format, usage, user_metadata_size, &error)); - if (error < 0) - return ErrorStatus(-error); - else - return {std::move(producer)}; -} - -ProducerChannel::~ProducerChannel() { - ALOGD_IF(TRACE, - "ProducerChannel::~ProducerChannel: channel_id=%d buffer_id=%d " - "state=%" PRIx32 ".", - channel_id(), buffer_id(), - buffer_state_->load(std::memory_order_acquire)); - for (auto consumer : consumer_channels_) { - consumer->OnProducerClosed(); - } - Hangup(); -} - -BufferHubChannel::BufferInfo ProducerChannel::GetBufferInfo() const { - // Derive the mask of signaled buffers in this producer / consumer set. - uint32_t signaled_mask = signaled() ? BufferHubDefs::kFirstClientBitMask : 0; - for (const ConsumerChannel* consumer : consumer_channels_) { - signaled_mask |= consumer->signaled() ? consumer->client_state_mask() : 0; - } - - return BufferInfo(buffer_id(), consumer_channels_.size(), buffer_.width(), - buffer_.height(), buffer_.layer_count(), buffer_.format(), - buffer_.usage(), - buffer_state_->load(std::memory_order_acquire), - signaled_mask, metadata_header_->queueIndex); -} - -void ProducerChannel::HandleImpulse(Message& message) { - ATRACE_NAME("ProducerChannel::HandleImpulse"); - switch (message.GetOp()) { - case BufferHubRPC::ProducerGain::Opcode: - OnProducerGain(message); - break; - case BufferHubRPC::ProducerPost::Opcode: - OnProducerPost(message, {}); - break; - } -} - -bool ProducerChannel::HandleMessage(Message& message) { - ATRACE_NAME("ProducerChannel::HandleMessage"); - switch (message.GetOp()) { - case BufferHubRPC::GetBuffer::Opcode: - DispatchRemoteMethod<BufferHubRPC::GetBuffer>( - *this, &ProducerChannel::OnGetBuffer, message); - return true; - - case BufferHubRPC::NewConsumer::Opcode: - DispatchRemoteMethod<BufferHubRPC::NewConsumer>( - *this, &ProducerChannel::OnNewConsumer, message); - return true; - - case BufferHubRPC::ProducerPost::Opcode: - DispatchRemoteMethod<BufferHubRPC::ProducerPost>( - *this, &ProducerChannel::OnProducerPost, message); - return true; - - case BufferHubRPC::ProducerGain::Opcode: - DispatchRemoteMethod<BufferHubRPC::ProducerGain>( - *this, &ProducerChannel::OnProducerGain, message); - return true; - - default: - return false; - } -} - -BufferDescription<BorrowedHandle> ProducerChannel::GetBuffer( - uint32_t client_state_mask) { - return {buffer_, - metadata_buffer_, - buffer_id(), - channel_id(), - client_state_mask, - acquire_fence_fd_.Borrow(), - release_fence_fd_.Borrow()}; -} - -Status<BufferDescription<BorrowedHandle>> ProducerChannel::OnGetBuffer( - Message& /*message*/) { - ATRACE_NAME("ProducerChannel::OnGetBuffer"); - ALOGD_IF(TRACE, "ProducerChannel::OnGetBuffer: buffer=%d, state=%" PRIx32 ".", - buffer_id(), buffer_state_->load(std::memory_order_acquire)); - return {GetBuffer(BufferHubDefs::kFirstClientBitMask)}; -} - -Status<uint32_t> ProducerChannel::CreateConsumerStateMask() { - // Try find the next consumer state bit which has not been claimed by any - // consumer yet. - // memory_order_acquire is chosen here because all writes in other threads - // that release active_clients_bit_mask_ need to be visible here. - uint32_t current_active_clients_bit_mask = - active_clients_bit_mask_->load(std::memory_order_acquire); - uint32_t consumer_state_mask = - BufferHubDefs::findNextAvailableClientStateMask( - current_active_clients_bit_mask | orphaned_consumer_bit_mask_); - if (consumer_state_mask == 0U) { - ALOGE("%s: reached the maximum mumber of consumers per producer: 63.", - __FUNCTION__); - return ErrorStatus(E2BIG); - } - uint32_t updated_active_clients_bit_mask = - current_active_clients_bit_mask | consumer_state_mask; - // Set the updated value only if the current value stays the same as what was - // read before. If the comparison succeeds, update the value without - // reordering anything before or after this read-modify-write in the current - // thread, and the modification will be visible in other threads that acquire - // active_clients_bit_mask_. If the comparison fails, load the result of - // all writes from all threads to updated_active_clients_bit_mask. - // Keep on finding the next available slient state mask until succeed or out - // of memory. - while (!active_clients_bit_mask_->compare_exchange_weak( - current_active_clients_bit_mask, updated_active_clients_bit_mask, - std::memory_order_acq_rel, std::memory_order_acquire)) { - ALOGE("%s: Current active clients bit mask is changed to %" PRIx32 - ", which was expected to be %" PRIx32 - ". Trying to generate a new client state mask to resolve race " - "condition.", - __FUNCTION__, updated_active_clients_bit_mask, - current_active_clients_bit_mask); - consumer_state_mask = BufferHubDefs::findNextAvailableClientStateMask( - current_active_clients_bit_mask | orphaned_consumer_bit_mask_); - if (consumer_state_mask == 0U) { - ALOGE("%s: reached the maximum mumber of consumers per producer: %d.", - __FUNCTION__, (BufferHubDefs::kMaxNumberOfClients - 1)); - return ErrorStatus(E2BIG); - } - updated_active_clients_bit_mask = - current_active_clients_bit_mask | consumer_state_mask; - } - - return {consumer_state_mask}; -} - -void ProducerChannel::RemoveConsumerClientMask(uint32_t consumer_state_mask) { - // Clear up the buffer state and fence state in case there is already - // something there due to possible race condition between producer post and - // consumer failed to create channel. - buffer_state_->fetch_and(~consumer_state_mask, std::memory_order_release); - fence_state_->fetch_and(~consumer_state_mask, std::memory_order_release); - - // Restore the consumer state bit and make it visible in other threads that - // acquire the active_clients_bit_mask_. - active_clients_bit_mask_->fetch_and(~consumer_state_mask, - std::memory_order_release); -} - -Status<RemoteChannelHandle> ProducerChannel::CreateConsumer( - Message& message, uint32_t consumer_state_mask) { - ATRACE_NAME(__FUNCTION__); - ALOGD("%s: buffer_id=%d", __FUNCTION__, buffer_id()); - - int channel_id; - auto status = message.PushChannel(0, nullptr, &channel_id); - if (!status) { - ALOGE("%s: Failed to push consumer channel: %s", __FUNCTION__, - status.GetErrorMessage().c_str()); - RemoveConsumerClientMask(consumer_state_mask); - return ErrorStatus(ENOMEM); - } - - auto consumer = std::make_shared<ConsumerChannel>( - service(), buffer_id(), channel_id, consumer_state_mask, - shared_from_this()); - const auto channel_status = service()->SetChannel(channel_id, consumer); - if (!channel_status) { - ALOGE("%s: failed to set new consumer channel: %s.", __FUNCTION__, - channel_status.GetErrorMessage().c_str()); - RemoveConsumerClientMask(consumer_state_mask); - return ErrorStatus(ENOMEM); - } - - uint32_t current_buffer_state = - buffer_state_->load(std::memory_order_acquire); - // Return the consumer channel handle without signal when adding the new - // consumer to a buffer that is available to producer (a.k.a a fully-released - // buffer) or a gained buffer. - if (current_buffer_state == 0U || - BufferHubDefs::isAnyClientGained(current_buffer_state)) { - return {status.take()}; - } - - // Signal the new consumer when adding it to a posted producer. - bool update_buffer_state = true; - if (!BufferHubDefs::isClientPosted(current_buffer_state, - consumer_state_mask)) { - uint32_t updated_buffer_state = - current_buffer_state ^ - (consumer_state_mask & BufferHubDefs::kHighBitsMask); - while (!buffer_state_->compare_exchange_weak( - current_buffer_state, updated_buffer_state, std::memory_order_acq_rel, - std::memory_order_acquire)) { - ALOGV( - "%s: Failed to post to the new consumer. " - "Current buffer state was changed to %" PRIx32 - " when trying to acquire the buffer and modify the buffer state to " - "%" PRIx32 - ". About to try again if the buffer is still not gained nor fully " - "released.", - __FUNCTION__, current_buffer_state, updated_buffer_state); - if (current_buffer_state == 0U || - BufferHubDefs::isAnyClientGained(current_buffer_state)) { - ALOGI("%s: buffer is gained or fully released, state=%" PRIx32 ".", - __FUNCTION__, current_buffer_state); - update_buffer_state = false; - break; - } - updated_buffer_state = - current_buffer_state ^ - (consumer_state_mask & BufferHubDefs::kHighBitsMask); - } - } - if (update_buffer_state || BufferHubDefs::isClientPosted( - buffer_state_->load(std::memory_order_acquire), - consumer_state_mask)) { - consumer->OnProducerPosted(); - } - - return {status.take()}; -} - -Status<RemoteChannelHandle> ProducerChannel::OnNewConsumer(Message& message) { - ATRACE_NAME("ProducerChannel::OnNewConsumer"); - ALOGD_IF(TRACE, "ProducerChannel::OnNewConsumer: buffer_id=%d", buffer_id()); - auto status = CreateConsumerStateMask(); - if (!status.ok()) { - return status.error_status(); - } - return CreateConsumer(message, /*consumer_state_mask=*/status.get()); -} - -Status<void> ProducerChannel::OnProducerPost(Message&, - LocalFence acquire_fence) { - ATRACE_NAME("ProducerChannel::OnProducerPost"); - ALOGD_IF(TRACE, "%s: buffer_id=%d, state=0x%x", __FUNCTION__, buffer_id(), - buffer_state_->load(std::memory_order_acquire)); - - epoll_event event; - event.events = 0; - event.data.u32 = 0U; - int ret = epoll_ctl(release_fence_fd_.Get(), EPOLL_CTL_MOD, - dummy_fence_fd_.Get(), &event); - ALOGE_IF(ret < 0, - "ProducerChannel::OnProducerPost: Failed to modify the shared " - "release fence to include the dummy fence: %s", - strerror(errno)); - - eventfd_t dummy_fence_count = 0U; - if (eventfd_read(dummy_fence_fd_.Get(), &dummy_fence_count) < 0) { - const int error = errno; - if (error != EAGAIN) { - ALOGE( - "ProducerChannel::ProducerChannel: Failed to read dummy fence, " - "error: %s", - strerror(error)); - return ErrorStatus(error); - } - } - - ALOGW_IF(dummy_fence_count > 0, - "ProducerChannel::ProducerChannel: %" PRIu64 - " dummy fence(s) was signaled during last release/gain cycle " - "buffer_id=%d.", - dummy_fence_count, buffer_id()); - - post_fence_ = std::move(acquire_fence); - - // Signal any interested consumers. If there are none, the buffer will stay - // in posted state until a consumer comes online. This behavior guarantees - // that no frame is silently dropped. - for (auto& consumer : consumer_channels_) { - consumer->OnProducerPosted(); - } - - return {}; -} - -Status<LocalFence> ProducerChannel::OnProducerGain(Message& /*message*/) { - ATRACE_NAME("ProducerChannel::OnGain"); - ALOGD_IF(TRACE, "%s: buffer_id=%d", __FUNCTION__, buffer_id()); - - ClearAvailable(); - post_fence_.close(); - for (auto& consumer : consumer_channels_) { - consumer->OnProducerGained(); - } - return {std::move(returned_fence_)}; -} - -// TODO(b/112338294) Keep here for reference. Remove it after new logic is -// written. -/* Status<RemoteChannelHandle> ProducerChannel::OnProducerDetach( - Message& message) { - ATRACE_NAME("ProducerChannel::OnProducerDetach"); - ALOGD_IF(TRACE, "ProducerChannel::OnProducerDetach: buffer_id=%d", - buffer_id()); - - uint32_t buffer_state = buffer_state_->load(std::memory_order_acquire); - if (!BufferHubDefs::isClientGained( - buffer_state, BufferHubDefs::kFirstClientStateMask)) { - // Can only detach a ProducerBuffer when it's in gained state. - ALOGW( - "ProducerChannel::OnProducerDetach: The buffer (id=%d, state=%" - PRIx32 - ") is not in gained state.", - buffer_id(), buffer_state); - return {}; - } - - int channel_id; - auto status = message.PushChannel(0, nullptr, &channel_id); - if (!status) { - ALOGE( - "ProducerChannel::OnProducerDetach: Failed to push detached buffer " - "channel: %s", - status.GetErrorMessage().c_str()); - return ErrorStatus(ENOMEM); - } - - // Make sure we unlock the buffer. - if (int ret = metadata_buffer_.Unlock()) { - ALOGE("ProducerChannel::OnProducerDetach: Failed to unlock metadata."); - return ErrorStatus(-ret); - }; - - std::unique_ptr<BufferChannel> channel = - BufferChannel::Create(service(), buffer_id(), channel_id, - std::move(buffer_), user_metadata_size_); - if (!channel) { - ALOGE("ProducerChannel::OnProducerDetach: Invalid buffer."); - return ErrorStatus(EINVAL); - } - - const auto channel_status = - service()->SetChannel(channel_id, std::move(channel)); - if (!channel_status) { - // Technically, this should never fail, as we just pushed the channel. - // Note that LOG_FATAL will be stripped out in non-debug build. - LOG_FATAL( - "ProducerChannel::OnProducerDetach: Failed to set new detached " - "buffer channel: %s.", channel_status.GetErrorMessage().c_str()); - } - - return status; -} */ - -Status<LocalFence> ProducerChannel::OnConsumerAcquire(Message& /*message*/) { - ATRACE_NAME("ProducerChannel::OnConsumerAcquire"); - ALOGD_IF(TRACE, "ProducerChannel::OnConsumerAcquire: buffer_id=%d", - buffer_id()); - - // Return a borrowed fd to avoid unnecessary duplication of the underlying - // fd. Serialization just needs to read the handle. - return {std::move(post_fence_)}; -} - -Status<void> ProducerChannel::OnConsumerRelease(Message&, - LocalFence release_fence) { - ATRACE_NAME("ProducerChannel::OnConsumerRelease"); - ALOGD_IF(TRACE, "ProducerChannel::OnConsumerRelease: buffer_id=%d", - buffer_id()); - - // Attempt to merge the fences if necessary. - if (release_fence) { - if (returned_fence_) { - LocalFence merged_fence(sync_merge("bufferhub_merged", - returned_fence_.get_fd(), - release_fence.get_fd())); - const int error = errno; - if (!merged_fence) { - ALOGE("ProducerChannel::OnConsumerRelease: Failed to merge fences: %s", - strerror(error)); - return ErrorStatus(error); - } - returned_fence_ = std::move(merged_fence); - } else { - returned_fence_ = std::move(release_fence); - } - } - - if (IsBufferReleasedByAllActiveClientsExceptForOrphans()) { - buffer_state_->store(0U); - SignalAvailable(); - if (orphaned_consumer_bit_mask_) { - ALOGW( - "%s: orphaned buffer detected during the this acquire/release cycle: " - "id=%d orphaned=0x%" PRIx32 " queue_index=%" PRId64 ".", - __FUNCTION__, buffer_id(), orphaned_consumer_bit_mask_, - metadata_header_->queueIndex); - orphaned_consumer_bit_mask_ = 0; - } - } - - return {}; -} - -void ProducerChannel::OnConsumerOrphaned(const uint32_t& consumer_state_mask) { - // Remember the ignored consumer so that newly added consumer won't be - // taking the same state mask as this orphaned consumer. - ALOGE_IF(orphaned_consumer_bit_mask_ & consumer_state_mask, - "%s: Consumer (consumer_state_mask=%" PRIx32 - ") is already orphaned.", - __FUNCTION__, consumer_state_mask); - orphaned_consumer_bit_mask_ |= consumer_state_mask; - - if (IsBufferReleasedByAllActiveClientsExceptForOrphans()) { - buffer_state_->store(0U); - SignalAvailable(); - } - - // Atomically clear the fence state bit as an orphaned consumer will never - // signal a release fence. - fence_state_->fetch_and(~consumer_state_mask, std::memory_order_release); - - // Atomically set the buffer state of this consumer to released state. - buffer_state_->fetch_and(~consumer_state_mask, std::memory_order_release); - - ALOGW( - "%s: detected new orphaned consumer buffer_id=%d " - "consumer_state_mask=%" PRIx32 " queue_index=%" PRId64 - " buffer_state=%" PRIx32 " fence_state=%" PRIx32 ".", - __FUNCTION__, buffer_id(), consumer_state_mask, - metadata_header_->queueIndex, - buffer_state_->load(std::memory_order_acquire), - fence_state_->load(std::memory_order_acquire)); -} - -void ProducerChannel::AddConsumer(ConsumerChannel* channel) { - consumer_channels_.push_back(channel); -} - -void ProducerChannel::RemoveConsumer(ConsumerChannel* channel) { - consumer_channels_.erase( - std::find(consumer_channels_.begin(), consumer_channels_.end(), channel)); - // Restore the consumer state bit and make it visible in other threads that - // acquire the active_clients_bit_mask_. - uint32_t consumer_state_mask = channel->client_state_mask(); - uint32_t current_active_clients_bit_mask = - active_clients_bit_mask_->load(std::memory_order_acquire); - uint32_t updated_active_clients_bit_mask = - current_active_clients_bit_mask & (~consumer_state_mask); - while (!active_clients_bit_mask_->compare_exchange_weak( - current_active_clients_bit_mask, updated_active_clients_bit_mask, - std::memory_order_acq_rel, std::memory_order_acquire)) { - ALOGI( - "%s: Failed to remove consumer state mask. Current active clients bit " - "mask is changed to %" PRIx32 - " when trying to acquire and modify it to %" PRIx32 - ". About to try again.", - __FUNCTION__, current_active_clients_bit_mask, - updated_active_clients_bit_mask); - updated_active_clients_bit_mask = - current_active_clients_bit_mask & (~consumer_state_mask); - } - - const uint32_t current_buffer_state = - buffer_state_->load(std::memory_order_acquire); - if (BufferHubDefs::isClientPosted(current_buffer_state, - consumer_state_mask) || - BufferHubDefs::isClientAcquired(current_buffer_state, - consumer_state_mask)) { - // The consumer client is being destoryed without releasing. This could - // happen in corner cases when the consumer crashes. Here we mark it - // orphaned before remove it from producer. - OnConsumerOrphaned(consumer_state_mask); - return; - } - - if (BufferHubDefs::isClientReleased(current_buffer_state, - consumer_state_mask) || - BufferHubDefs::isAnyClientGained(current_buffer_state)) { - // The consumer is being close while it is suppose to signal a release - // fence. Signal the dummy fence here. - if (fence_state_->load(std::memory_order_acquire) & consumer_state_mask) { - epoll_event event; - event.events = EPOLLIN; - event.data.u32 = consumer_state_mask; - if (epoll_ctl(release_fence_fd_.Get(), EPOLL_CTL_MOD, - dummy_fence_fd_.Get(), &event) < 0) { - ALOGE( - "%s: Failed to modify the shared release fence to include the " - "dummy fence: %s", - __FUNCTION__, strerror(errno)); - return; - } - ALOGW("%s: signal dummy release fence buffer_id=%d", __FUNCTION__, - buffer_id()); - eventfd_write(dummy_fence_fd_.Get(), 1); - } - } -} - -// Returns true if the given parameters match the underlying buffer -// parameters. -bool ProducerChannel::CheckParameters(uint32_t width, uint32_t height, - uint32_t layer_count, uint32_t format, - uint64_t usage, - size_t user_metadata_size) const { - return user_metadata_size == user_metadata_size_ && - buffer_.width() == width && buffer_.height() == height && - buffer_.layer_count() == layer_count && buffer_.format() == format && - buffer_.usage() == usage; -} - -bool ProducerChannel::IsBufferReleasedByAllActiveClientsExceptForOrphans() - const { - return (buffer_state_->load(std::memory_order_acquire) & - ~orphaned_consumer_bit_mask_ & - active_clients_bit_mask_->load(std::memory_order_acquire)) == 0U; -} - -} // namespace dvr -} // namespace android diff --git a/services/vr/bufferhubd/producer_queue_channel.cpp b/services/vr/bufferhubd/producer_queue_channel.cpp deleted file mode 100644 index 004dc7cb4f..0000000000 --- a/services/vr/bufferhubd/producer_queue_channel.cpp +++ /dev/null @@ -1,397 +0,0 @@ -#include <inttypes.h> - -#include <private/dvr/consumer_queue_channel.h> -#include <private/dvr/producer_channel.h> -#include <private/dvr/producer_queue_channel.h> - -using android::pdx::ErrorStatus; -using android::pdx::Message; -using android::pdx::RemoteChannelHandle; -using android::pdx::Status; -using android::pdx::rpc::DispatchRemoteMethod; - -namespace android { -namespace dvr { - -ProducerQueueChannel::ProducerQueueChannel(BufferHubService* service, - int channel_id, - const ProducerQueueConfig& config, - const UsagePolicy& usage_policy, - int* error) - : BufferHubChannel(service, channel_id, channel_id, kProducerQueueType), - config_(config), - usage_policy_(usage_policy), - capacity_(0) { - *error = 0; -} - -ProducerQueueChannel::~ProducerQueueChannel() { - ALOGD_IF(TRACE, "ProducerQueueChannel::~ProducerQueueChannel: queue_id=%d", - buffer_id()); - for (auto* consumer : consumer_channels_) - consumer->OnProducerClosed(); -} - -/* static */ -Status<std::shared_ptr<ProducerQueueChannel>> ProducerQueueChannel::Create( - BufferHubService* service, int channel_id, - const ProducerQueueConfig& config, const UsagePolicy& usage_policy) { - // Configuration between |usage_deny_set_mask| and |usage_deny_clear_mask| - // should be mutually exclusive. - if ((usage_policy.usage_deny_set_mask & usage_policy.usage_deny_clear_mask)) { - ALOGE( - "BufferHubService::OnCreateProducerQueue: illegal usage mask " - "configuration: usage_deny_set_mask=%" PRIx64 - " usage_deny_clear_mask=%" PRIx64, - usage_policy.usage_deny_set_mask, usage_policy.usage_deny_clear_mask); - return ErrorStatus(EINVAL); - } - - int error = 0; - std::shared_ptr<ProducerQueueChannel> producer(new ProducerQueueChannel( - service, channel_id, config, usage_policy, &error)); - if (error < 0) - return ErrorStatus(-error); - else - return {std::move(producer)}; -} - -bool ProducerQueueChannel::HandleMessage(Message& message) { - ATRACE_NAME("ProducerQueueChannel::HandleMessage"); - switch (message.GetOp()) { - case BufferHubRPC::CreateConsumerQueue::Opcode: - DispatchRemoteMethod<BufferHubRPC::CreateConsumerQueue>( - *this, &ProducerQueueChannel::OnCreateConsumerQueue, message); - return true; - - case BufferHubRPC::GetQueueInfo::Opcode: - DispatchRemoteMethod<BufferHubRPC::GetQueueInfo>( - *this, &ProducerQueueChannel::OnGetQueueInfo, message); - return true; - - case BufferHubRPC::ProducerQueueAllocateBuffers::Opcode: - DispatchRemoteMethod<BufferHubRPC::ProducerQueueAllocateBuffers>( - *this, &ProducerQueueChannel::OnProducerQueueAllocateBuffers, - message); - return true; - - case BufferHubRPC::ProducerQueueInsertBuffer::Opcode: - DispatchRemoteMethod<BufferHubRPC::ProducerQueueInsertBuffer>( - *this, &ProducerQueueChannel::OnProducerQueueInsertBuffer, message); - return true; - - case BufferHubRPC::ProducerQueueRemoveBuffer::Opcode: - DispatchRemoteMethod<BufferHubRPC::ProducerQueueRemoveBuffer>( - *this, &ProducerQueueChannel::OnProducerQueueRemoveBuffer, message); - return true; - - default: - return false; - } -} - -void ProducerQueueChannel::HandleImpulse(Message& /* message */) { - ATRACE_NAME("ProducerQueueChannel::HandleImpulse"); -} - -BufferHubChannel::BufferInfo ProducerQueueChannel::GetBufferInfo() const { - return BufferInfo(channel_id(), consumer_channels_.size(), capacity_, - usage_policy_); -} - -Status<RemoteChannelHandle> ProducerQueueChannel::OnCreateConsumerQueue( - Message& message, bool silent) { - ATRACE_NAME("ProducerQueueChannel::OnCreateConsumerQueue"); - ALOGD_IF( - TRACE, - "ProducerQueueChannel::OnCreateConsumerQueue: channel_id=%d slient=%d", - channel_id(), silent); - - int channel_id; - auto status = message.PushChannel(0, nullptr, &channel_id); - if (!status) { - ALOGE( - "ProducerQueueChannel::OnCreateConsumerQueue: failed to push consumer " - "channel: %s", - status.GetErrorMessage().c_str()); - return ErrorStatus(ENOMEM); - } - - auto consumer_queue_channel = std::make_shared<ConsumerQueueChannel>( - service(), buffer_id(), channel_id, shared_from_this(), silent); - - // Register the existing buffers with the new consumer queue. - for (size_t slot = 0; slot < BufferHubRPC::kMaxQueueCapacity; slot++) { - if (auto buffer = buffers_[slot].lock()) - consumer_queue_channel->RegisterNewBuffer(buffer, slot); - } - - const auto channel_status = - service()->SetChannel(channel_id, consumer_queue_channel); - if (!channel_status) { - ALOGE( - "ProducerQueueChannel::OnCreateConsumerQueue: Failed to set channel: " - "%s", - channel_status.GetErrorMessage().c_str()); - return ErrorStatus(ENOMEM); - } - - return {status.take()}; -} - -Status<QueueInfo> ProducerQueueChannel::OnGetQueueInfo(Message&) { - return {{config_, buffer_id()}}; -} - -Status<std::vector<std::pair<RemoteChannelHandle, size_t>>> -ProducerQueueChannel::OnProducerQueueAllocateBuffers( - Message& message, uint32_t width, uint32_t height, uint32_t layer_count, - uint32_t format, uint64_t usage, size_t buffer_count) { - ATRACE_NAME("ProducerQueueChannel::OnProducerQueueAllocateBuffers"); - ALOGD_IF(TRACE, - "ProducerQueueChannel::OnProducerQueueAllocateBuffers: " - "producer_channel_id=%d", - channel_id()); - - std::vector<std::pair<RemoteChannelHandle, size_t>> buffer_handles; - - // Deny buffer allocation violating preset rules. - if (usage & usage_policy_.usage_deny_set_mask) { - ALOGE( - "ProducerQueueChannel::OnProducerQueueAllocateBuffers: usage: %" PRIx64 - " is not permitted. Violating usage_deny_set_mask, the following bits " - "shall not be set: %" PRIx64 ".", - usage, usage_policy_.usage_deny_set_mask); - return ErrorStatus(EINVAL); - } - - if (~usage & usage_policy_.usage_deny_clear_mask) { - ALOGE( - "ProducerQueueChannel::OnProducerQueueAllocateBuffers: usage: %" PRIx64 - " is not permitted. Violating usage_deny_clear_mask, the following " - "bits must be set: %" PRIx64 ".", - usage, usage_policy_.usage_deny_clear_mask); - return ErrorStatus(EINVAL); - } - - // Force set mask and clear mask. Note that |usage_policy_.usage_set_mask_| - // takes precedence and will overwrite |usage_policy_.usage_clear_mask|. - uint64_t effective_usage = - (usage & ~usage_policy_.usage_clear_mask) | usage_policy_.usage_set_mask; - - for (size_t i = 0; i < buffer_count; i++) { - auto status = AllocateBuffer(message, width, height, layer_count, format, - effective_usage); - if (!status) { - ALOGE( - "ProducerQueueChannel::OnProducerQueueAllocateBuffers: Failed to " - "allocate new buffer."); - return ErrorStatus(status.error()); - } - buffer_handles.push_back(status.take()); - } - - return {std::move(buffer_handles)}; -} - -Status<std::pair<RemoteChannelHandle, size_t>> -ProducerQueueChannel::AllocateBuffer(Message& message, uint32_t width, - uint32_t height, uint32_t layer_count, - uint32_t format, uint64_t usage) { - ATRACE_NAME("ProducerQueueChannel::AllocateBuffer"); - ALOGD_IF(TRACE, - "ProducerQueueChannel::AllocateBuffer: producer_channel_id=%d", - channel_id()); - - if (capacity_ >= BufferHubRPC::kMaxQueueCapacity) { - ALOGE("ProducerQueueChannel::AllocateBuffer: reaches kMaxQueueCapacity."); - return ErrorStatus(E2BIG); - } - - // Here we are creating a new BufferHubBuffer, initialize the producer - // channel, and returning its file handle back to the client. - // buffer_id is the id of the producer channel of BufferHubBuffer. - int buffer_id; - auto status = message.PushChannel(0, nullptr, &buffer_id); - - if (!status) { - ALOGE("ProducerQueueChannel::AllocateBuffer: failed to push channel: %s", - status.GetErrorMessage().c_str()); - return ErrorStatus(status.error()); - } - - ALOGD_IF(TRACE, - "ProducerQueueChannel::AllocateBuffer: buffer_id=%d width=%u " - "height=%u layer_count=%u format=%u usage=%" PRIx64, - buffer_id, width, height, layer_count, format, usage); - auto buffer_handle = status.take(); - - auto producer_channel_status = - ProducerChannel::Create(service(), buffer_id, width, height, layer_count, - format, usage, config_.user_metadata_size); - if (!producer_channel_status) { - ALOGE( - "ProducerQueueChannel::AllocateBuffer: Failed to create producer " - "buffer: %s", - producer_channel_status.GetErrorMessage().c_str()); - return ErrorStatus(ENOMEM); - } - auto producer_channel = producer_channel_status.take(); - - ALOGD_IF( - TRACE, - "ProducerQueueChannel::AllocateBuffer: buffer_id=%d, buffer_handle=%d", - buffer_id, buffer_handle.value()); - - const auto channel_status = - service()->SetChannel(buffer_id, producer_channel); - if (!channel_status) { - ALOGE( - "ProducerQueueChannel::AllocateBuffer: failed to set producer channel " - "for new BufferHubBuffer: %s", - channel_status.GetErrorMessage().c_str()); - return ErrorStatus(ENOMEM); - } - - // Register the newly allocated buffer's channel_id into the first empty - // buffer slot. - size_t slot = 0; - for (; slot < BufferHubRPC::kMaxQueueCapacity; slot++) { - if (buffers_[slot].expired()) - break; - } - if (slot == BufferHubRPC::kMaxQueueCapacity) { - ALOGE( - "ProducerQueueChannel::AllocateBuffer: Cannot find empty slot for new " - "buffer allocation."); - return ErrorStatus(E2BIG); - } - - buffers_[slot] = producer_channel; - capacity_++; - - // Notify each consumer channel about the new buffer. - for (auto* consumer_channel : consumer_channels_) { - ALOGD( - "ProducerQueueChannel::AllocateBuffer: Notified consumer with new " - "buffer, buffer_id=%d", - buffer_id); - consumer_channel->RegisterNewBuffer(producer_channel, slot); - } - - return {{std::move(buffer_handle), slot}}; -} - -Status<size_t> ProducerQueueChannel::OnProducerQueueInsertBuffer( - pdx::Message& message, int buffer_cid) { - ATRACE_NAME("ProducerQueueChannel::InsertBuffer"); - ALOGD_IF(TRACE, - "ProducerQueueChannel::InsertBuffer: channel_id=%d, buffer_cid=%d", - channel_id(), buffer_cid); - - if (capacity_ >= BufferHubRPC::kMaxQueueCapacity) { - ALOGE("ProducerQueueChannel::InsertBuffer: reaches kMaxQueueCapacity."); - return ErrorStatus(E2BIG); - } - auto producer_channel = std::static_pointer_cast<ProducerChannel>( - service()->GetChannel(buffer_cid)); - if (producer_channel == nullptr || - producer_channel->channel_type() != BufferHubChannel::kProducerType) { - // Rejects the request if the requested buffer channel is invalid and/or - // it's not a ProducerChannel. - ALOGE( - "ProducerQueueChannel::InsertBuffer: Invalid buffer_cid=%d, " - "producer_buffer=0x%p, channel_type=%d.", - buffer_cid, producer_channel.get(), - producer_channel == nullptr ? -1 : producer_channel->channel_type()); - return ErrorStatus(EINVAL); - } - if (producer_channel->GetActiveProcessId() != message.GetProcessId()) { - // Rejects the request if the requested buffer channel is not currently - // connected to the caller this is IPC request. This effectively prevents - // fake buffer_cid from being injected. - ALOGE( - "ProducerQueueChannel::InsertBuffer: Requested buffer channel " - "(buffer_cid=%d) is not connected to the calling process (pid=%d). " - "It's connected to a different process (pid=%d).", - buffer_cid, message.GetProcessId(), - producer_channel->GetActiveProcessId()); - return ErrorStatus(EINVAL); - } - uint64_t buffer_state = producer_channel->buffer_state(); - // TODO(b/112007999) add an atomic variable in metadata header in shared - // memory to indicate which client is the last producer of the buffer. - // Currently, the first client is the only producer to the buffer. - // Thus, it checks whether the first client gains the buffer below. - if (!BufferHubDefs::isClientGained(buffer_state, - BufferHubDefs::kFirstClientBitMask)) { - // Rejects the request if the requested buffer is not in Gained state. - ALOGE( - "ProducerQueueChannel::InsertBuffer: The buffer (cid=%d, " - "state=0x%" PRIx64 ") is not in gained state.", - buffer_cid, buffer_state); - return ErrorStatus(EINVAL); - } - - // Register the to-be-inserted buffer's channel_id into the first empty - // buffer slot. - size_t slot = 0; - for (; slot < BufferHubRPC::kMaxQueueCapacity; slot++) { - if (buffers_[slot].expired()) - break; - } - if (slot == BufferHubRPC::kMaxQueueCapacity) { - ALOGE( - "ProducerQueueChannel::AllocateBuffer: Cannot find empty slot for new " - "buffer allocation."); - return ErrorStatus(E2BIG); - } - - buffers_[slot] = producer_channel; - capacity_++; - - // Notify each consumer channel about the new buffer. - for (auto* consumer_channel : consumer_channels_) { - ALOGD( - "ProducerQueueChannel::AllocateBuffer: Notified consumer with new " - "buffer, buffer_cid=%d", - buffer_cid); - consumer_channel->RegisterNewBuffer(producer_channel, slot); - } - - return {slot}; -} - -Status<void> ProducerQueueChannel::OnProducerQueueRemoveBuffer( - Message& /*message*/, size_t slot) { - if (buffers_[slot].expired()) { - ALOGE( - "ProducerQueueChannel::OnProducerQueueRemoveBuffer: trying to remove " - "an invalid buffer producer at slot %zu", - slot); - return ErrorStatus(EINVAL); - } - - if (capacity_ == 0) { - ALOGE( - "ProducerQueueChannel::OnProducerQueueRemoveBuffer: trying to remove a " - "buffer producer while the queue's capacity is already zero."); - return ErrorStatus(EINVAL); - } - - buffers_[slot].reset(); - capacity_--; - return {}; -} - -void ProducerQueueChannel::AddConsumer(ConsumerQueueChannel* channel) { - consumer_channels_.push_back(channel); -} - -void ProducerQueueChannel::RemoveConsumer(ConsumerQueueChannel* channel) { - consumer_channels_.erase( - std::find(consumer_channels_.begin(), consumer_channels_.end(), channel)); -} - -} // namespace dvr -} // namespace android diff --git a/services/vr/performanced/Android.bp b/services/vr/performanced/Android.bp deleted file mode 100644 index 5eca88b1f9..0000000000 --- a/services/vr/performanced/Android.bp +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (C) 2016 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "frameworks_native_license" - // to get the below license kinds: - // SPDX-license-identifier-MIT - default_applicable_licenses: ["frameworks_native_license"], -} - -cc_defaults { - name: "performanced_defaults", - static_libs: [ - "libperformance", - "libvr_manager", - ], - shared_libs: [ - "libbinder", - "libbase", - "libcutils", - "liblog", - "libutils", - "libpdx_default_transport", - ], -} - -cc_binary { - name: "performanced", - system_ext_specific: true, - defaults: ["performanced_defaults"], - srcs: [ - "cpu_set.cpp", - "main.cpp", - "performance_service.cpp", - "task.cpp", - ], - cflags: [ - "-DLOG_TAG=\"performanced\"", - "-DTRACE=0", - "-Wall", - "-Werror", - ], - init_rc: ["performanced.rc"], -} - -cc_test { - name: "performance_service_tests", - defaults: ["performanced_defaults"], - srcs: ["performance_service_tests.cpp"], -} diff --git a/services/vr/performanced/CPPLINT.cfg b/services/vr/performanced/CPPLINT.cfg deleted file mode 100644 index fd379dabb5..0000000000 --- a/services/vr/performanced/CPPLINT.cfg +++ /dev/null @@ -1 +0,0 @@ -filter=-runtime/int diff --git a/services/vr/performanced/cpu_set.cpp b/services/vr/performanced/cpu_set.cpp deleted file mode 100644 index d940b79086..0000000000 --- a/services/vr/performanced/cpu_set.cpp +++ /dev/null @@ -1,290 +0,0 @@ -#include "cpu_set.h" - -#include <log/log.h> - -#include <algorithm> -#include <iomanip> -#include <iostream> -#include <sstream> -#include <string> - -#include <android-base/file.h> - -#include "directory_reader.h" -#include "stdio_filebuf.h" -#include "task.h" -#include "unique_file.h" - -using android::pdx::ErrorStatus; -using android::pdx::Status; - -namespace { - -constexpr int kDirectoryFlags = O_RDONLY | O_DIRECTORY | O_CLOEXEC; -constexpr pid_t kKernelThreadDaemonPid = 2; - -} // anonymous namespace - -namespace android { -namespace dvr { - -bool CpuSet::prefix_enabled_ = false; - -void CpuSetManager::Load(const std::string& cpuset_root) { - if (!root_set_) - root_set_ = Create(cpuset_root); -} - -std::unique_ptr<CpuSet> CpuSetManager::Create(const std::string& path) { - base::unique_fd root_cpuset_fd(open(path.c_str(), kDirectoryFlags)); - if (root_cpuset_fd.get() < 0) { - ALOGE("CpuSet::Create: Failed to open \"%s\": %s", path.c_str(), - strerror(errno)); - return nullptr; - } - - return Create(std::move(root_cpuset_fd), "/", nullptr); -} - -std::unique_ptr<CpuSet> CpuSetManager::Create(base::unique_fd base_fd, - const std::string& name, - CpuSet* parent) { - DirectoryReader directory(base::unique_fd(dup(base_fd))); - if (!directory) { - ALOGE("CpuSet::Create: Failed to opendir %s cpuset: %s", name.c_str(), - strerror(directory.GetError())); - return nullptr; - } - - std::unique_ptr<CpuSet> group( - new CpuSet(parent, name, base::unique_fd(dup(base_fd)))); - path_map_.insert(std::make_pair(group->path(), group.get())); - - while (dirent* entry = directory.Next()) { - if (entry->d_type == DT_DIR) { - std::string directory_name(entry->d_name); - - if (directory_name == "." || directory_name == "..") - continue; - - base::unique_fd entry_fd( - openat(base_fd.get(), directory_name.c_str(), kDirectoryFlags)); - if (entry_fd.get() >= 0) { - auto child = - Create(std::move(entry_fd), directory_name.c_str(), group.get()); - - if (child) - group->AddChild(std::move(child)); - else - return nullptr; - } else { - ALOGE("CpuSet::Create: Failed to openat \"%s\": %s", entry->d_name, - strerror(errno)); - return nullptr; - } - } - } - - return group; -} - -CpuSet* CpuSetManager::Lookup(const std::string& path) { - auto search = path_map_.find(path); - if (search != path_map_.end()) - return search->second; - else - return nullptr; -} - -std::vector<CpuSet*> CpuSetManager::GetCpuSets() { - std::vector<CpuSet*> sets(path_map_.size()); - - for (const auto& pair : path_map_) { - sets.push_back(pair.second); - } - - return sets; -} - -void CpuSetManager::DumpState(std::ostringstream& stream) const { - size_t max_path = 0; - std::vector<CpuSet*> sets; - - for (const auto& pair : path_map_) { - max_path = std::max(max_path, pair.second->path().length()); - sets.push_back(pair.second); - } - - std::sort(sets.begin(), sets.end(), [](const CpuSet* a, const CpuSet* b) { - return a->path() < b->path(); - }); - - stream << std::left; - stream << std::setw(max_path) << "Path"; - stream << " "; - stream << std::setw(6) << "CPUs"; - stream << " "; - stream << std::setw(6) << "Tasks"; - stream << std::endl; - - stream << std::string(max_path, '_'); - stream << " "; - stream << std::string(6, '_'); - stream << " "; - stream << std::string(6, '_'); - stream << std::endl; - - for (const auto set : sets) { - stream << std::left; - stream << std::setw(max_path) << set->path(); - stream << " "; - stream << std::right; - stream << std::setw(6) << set->GetCpuList(); - stream << " "; - stream << std::setw(6) << set->GetTasks().size(); - stream << std::endl; - } -} - -void CpuSetManager::MoveUnboundTasks(const std::string& target_set) { - auto root = Lookup("/"); - if (!root) { - ALOGE("CpuSetManager::MoveUnboundTasks: Failed to find root cpuset!"); - return; - } - - auto target = Lookup(target_set); - if (!target) { - ALOGE( - "CpuSetManager::MoveUnboundTasks: Failed to find target cpuset \"%s\"!", - target_set.c_str()); - return; - } - - auto cpu_list = root->GetCpuList(); - - for (auto task_id : root->GetTasks()) { - Task task(task_id); - - // Move only unbound kernel threads to the target cpuset. - if (task.cpus_allowed_list() == cpu_list && - task.parent_process_id() == kKernelThreadDaemonPid) { - ALOGD_IF(TRACE, - "CpuSetManager::MoveUnboundTasks: Moving task_id=%d name=%s to " - "target_set=%s tgid=%d ppid=%d.", - task_id, task.name().c_str(), target_set.c_str(), - task.thread_group_id(), task.parent_process_id()); - - auto status = target->AttachTask(task_id); - ALOGW_IF(!status && status.error() != EINVAL, - "CpuSetManager::MoveUnboundTasks: Failed to attach task_id=%d " - "to cpuset=%s: %s", - task_id, target_set.c_str(), status.GetErrorMessage().c_str()); - } else { - ALOGD_IF(TRACE, - "CpuSet::MoveUnboundTasks: Skipping task_id=%d name=%s cpus=%s.", - task_id, task.name().c_str(), task.cpus_allowed_list().c_str()); - } - } -} - -CpuSet::CpuSet(CpuSet* parent, const std::string& name, - base::unique_fd&& cpuset_fd) - : parent_(parent), name_(name), cpuset_fd_(std::move(cpuset_fd)) { - if (parent_ == nullptr) - path_ = name_; - else if (parent_->IsRoot()) - path_ = parent_->name() + name_; - else - path_ = parent_->path() + "/" + name_; - - ALOGI("CpuSet::CpuSet: path=%s", path().c_str()); -} - -base::unique_fd CpuSet::OpenPropertyFile(const std::string& name) const { - return OpenFile(prefix_enabled_ ? "cpuset." + name : name); -} - -UniqueFile CpuSet::OpenPropertyFilePointer(const std::string& name) const { - return OpenFilePointer(prefix_enabled_ ? "cpuset." + name : name); -} - -base::unique_fd CpuSet::OpenFile(const std::string& name, int flags) const { - const std::string relative_path = "./" + name; - return base::unique_fd( - openat(cpuset_fd_.get(), relative_path.c_str(), flags)); -} - -UniqueFile CpuSet::OpenFilePointer(const std::string& name, int flags) const { - const std::string relative_path = "./" + name; - base::unique_fd fd(openat(cpuset_fd_.get(), relative_path.c_str(), flags)); - if (fd.get() < 0) { - ALOGE("CpuSet::OpenPropertyFilePointer: Failed to open %s/%s: %s", - path_.c_str(), name.c_str(), strerror(errno)); - return nullptr; - } - - UniqueFile fp(fdopen(fd.release(), "r")); - if (!fp) - ALOGE("CpuSet::OpenPropertyFilePointer: Failed to fdopen %s/%s: %s", - path_.c_str(), name.c_str(), strerror(errno)); - - return fp; -} - -Status<void> CpuSet::AttachTask(pid_t task_id) const { - auto file = OpenFile("tasks", O_RDWR); - if (file.get() >= 0) { - std::ostringstream stream; - stream << task_id; - std::string value = stream.str(); - - const bool ret = base::WriteStringToFd(value, file.get()); - if (!ret) - return ErrorStatus(errno); - else - return {}; - } else { - const int error = errno; - ALOGE("CpuSet::AttachTask: Failed to open %s/tasks: %s", path_.c_str(), - strerror(error)); - return ErrorStatus(error); - } -} - -std::vector<pid_t> CpuSet::GetTasks() const { - std::vector<pid_t> tasks; - - if (auto file = OpenFilePointer("tasks")) { - stdio_filebuf<char> filebuf(file.get()); - std::istream file_stream(&filebuf); - - for (std::string line; std::getline(file_stream, line);) { - pid_t task_id = std::strtol(line.c_str(), nullptr, 10); - tasks.push_back(task_id); - } - } - - return tasks; -} - -std::string CpuSet::GetCpuList() const { - if (auto file = OpenPropertyFilePointer("cpus")) { - stdio_filebuf<char> filebuf(file.get()); - std::istream file_stream(&filebuf); - - std::string line; - if (std::getline(file_stream, line)) - return line; - } - - ALOGE("CpuSet::GetCpuList: Failed to read cpu list!!!"); - return ""; -} - -void CpuSet::AddChild(std::unique_ptr<CpuSet> child) { - children_.push_back(std::move(child)); -} - -} // namespace dvr -} // namespace android diff --git a/services/vr/performanced/cpu_set.h b/services/vr/performanced/cpu_set.h deleted file mode 100644 index 4c25e9ec4a..0000000000 --- a/services/vr/performanced/cpu_set.h +++ /dev/null @@ -1,108 +0,0 @@ -#ifndef ANDROID_DVR_PERFORMANCED_CPU_SET_H_ -#define ANDROID_DVR_PERFORMANCED_CPU_SET_H_ - -#include <fcntl.h> - -#include <memory> -#include <mutex> -#include <sstream> -#include <string> -#include <unordered_map> -#include <vector> - -#include <android-base/unique_fd.h> - -#include <pdx/status.h> - -#include "unique_file.h" - -namespace android { -namespace dvr { - -class CpuSet { - public: - // Returns the parent group for this group, if any. This pointer is owned by - // the group hierarchy and is only valid as long as the hierarchy is valid. - CpuSet* parent() const { return parent_; } - std::string name() const { return name_; } - std::string path() const { return path_; } - - bool IsRoot() const { return parent_ == nullptr; } - - std::string GetCpuList() const; - - pdx::Status<void> AttachTask(pid_t task_id) const; - std::vector<pid_t> GetTasks() const; - - private: - friend class CpuSetManager; - - CpuSet(CpuSet* parent, const std::string& name, base::unique_fd&& cpuset_fd); - - void AddChild(std::unique_ptr<CpuSet> child); - - base::unique_fd OpenPropertyFile(const std::string& name) const; - UniqueFile OpenPropertyFilePointer(const std::string& name) const; - - base::unique_fd OpenFile(const std::string& name, int flags = O_RDONLY) const; - UniqueFile OpenFilePointer(const std::string& name, - int flags = O_RDONLY) const; - - CpuSet* parent_; - std::string name_; - std::string path_; - base::unique_fd cpuset_fd_; - std::vector<std::unique_ptr<CpuSet>> children_; - - static void SetPrefixEnabled(bool enabled) { prefix_enabled_ = enabled; } - static bool prefix_enabled_; - - CpuSet(const CpuSet&) = delete; - void operator=(const CpuSet&) = delete; -}; - -class CpuSetManager { - public: - CpuSetManager() {} - - // Creats a CpuSet hierarchy by walking the directory tree starting at - // |cpuset_root|. This argument must be the path to the root cpuset for the - // system, which is usually /dev/cpuset. - void Load(const std::string& cpuset_root); - - // Lookup and return a CpuSet from a cpuset path. Ownership of the pointer - // DOES NOT pass to the caller; the pointer remains valid as long as the - // CpuSet hierarchy is valid. - CpuSet* Lookup(const std::string& path); - - // Returns a vector of all the cpusets found at initializaiton. Ownership of - // the pointers to CpuSets DOES NOT pass to the caller; the pointers remain - // valid as long as the CpuSet hierarchy is valid. - std::vector<CpuSet*> GetCpuSets(); - - // Moves all unbound tasks from the root set into the target set. This is used - // to shield the system from interference from unbound kernel threads. - void MoveUnboundTasks(const std::string& target_set); - - void DumpState(std::ostringstream& stream) const; - - operator bool() const { return root_set_ != nullptr; } - - private: - // Creates a CpuSet from a path to a cpuset cgroup directory. Recursively - // creates child groups for each directory found under |path|. - std::unique_ptr<CpuSet> Create(const std::string& path); - std::unique_ptr<CpuSet> Create(base::unique_fd base_fd, - const std::string& name, CpuSet* parent); - - std::unique_ptr<CpuSet> root_set_; - std::unordered_map<std::string, CpuSet*> path_map_; - - CpuSetManager(const CpuSetManager&) = delete; - void operator=(const CpuSetManager&) = delete; -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_PERFORMANCED_CPU_SET_H_ diff --git a/services/vr/performanced/directory_reader.h b/services/vr/performanced/directory_reader.h deleted file mode 100644 index f8359c4538..0000000000 --- a/services/vr/performanced/directory_reader.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef ANDROID_DVR_PERFORMANCED_DIRECTORY_READER_H_ -#define ANDROID_DVR_PERFORMANCED_DIRECTORY_READER_H_ - -#include <dirent.h> -#include <errno.h> -#include <fcntl.h> -#include <sys/stat.h> -#include <sys/types.h> - -#include <android-base/unique_fd.h> - -namespace android { -namespace dvr { - -// Utility class around readdir() that handles automatic cleanup. -class DirectoryReader { - public: - explicit DirectoryReader(base::unique_fd directory_fd) { - int fd = directory_fd.release(); - directory_ = fdopendir(fd); - error_ = errno; - if (directory_ == nullptr) - close(fd); - } - - ~DirectoryReader() { - if (directory_) - closedir(directory_); - } - - bool IsValid() const { return directory_ != nullptr; } - explicit operator bool() const { return IsValid(); } - int GetError() const { return error_; } - - // Returns a pointer to a dirent describing the next directory entry. The - // pointer is only valid unitl the next call to Next() or the DirectoryReader - // is destroyed. Returns nullptr when the end of the directory is reached. - dirent* Next() { - if (directory_) - return readdir(directory_); - else - return nullptr; - } - - private: - DIR* directory_; - int error_; - - DirectoryReader(const DirectoryReader&) = delete; - void operator=(const DirectoryReader&) = delete; -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_PERFORMANCED_DIRECTORY_READER_H_ diff --git a/services/vr/performanced/main.cpp b/services/vr/performanced/main.cpp deleted file mode 100644 index d7dc8f6afe..0000000000 --- a/services/vr/performanced/main.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#include <errno.h> -#include <sys/capability.h> -#include <sys/prctl.h> -#include <sys/stat.h> - -#include <cutils/properties.h> -#include <cutils/sched_policy.h> -#include <log/log.h> -#include <sys/resource.h> -#include <utils/threads.h> - -#include <pdx/service_dispatcher.h> -#include <private/android_filesystem_config.h> - -#include "performance_service.h" - -namespace { - -// Annoying that sys/capability.h doesn't define this directly. -constexpr int kMaxCapNumber = (CAP_TO_INDEX(CAP_LAST_CAP) + 1); - -} // anonymous namespace - -int main(int /*argc*/, char** /*argv*/) { - int ret = -1; - - struct __user_cap_header_struct capheader; - struct __user_cap_data_struct capdata[kMaxCapNumber]; - - std::shared_ptr<android::pdx::Service> service; - std::unique_ptr<android::pdx::ServiceDispatcher> dispatcher; - - ALOGI("Starting up..."); - - // We need to be able to create endpoints with full perms. - umask(0000); - - // Keep capabilities when switching UID to AID_SYSTEM. - ret = prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); - CHECK_ERROR(ret < 0, error, "Failed to set KEEPCAPS: %s", strerror(errno)); - - // Set UID and GID to system. - ret = setresgid(AID_SYSTEM, AID_SYSTEM, AID_SYSTEM); - CHECK_ERROR(ret < 0, error, "Failed to set GID: %s", strerror(errno)); - ret = setresuid(AID_SYSTEM, AID_SYSTEM, AID_SYSTEM); - CHECK_ERROR(ret < 0, error, "Failed to set UID: %s", strerror(errno)); - - // Keep CAP_SYS_NICE, allowing control of scheduler class, priority, and - // cpuset for other tasks in the system. - memset(&capheader, 0, sizeof(capheader)); - memset(&capdata, 0, sizeof(capdata)); - capheader.version = _LINUX_CAPABILITY_VERSION_3; - capdata[CAP_TO_INDEX(CAP_SYS_NICE)].effective |= CAP_TO_MASK(CAP_SYS_NICE); - capdata[CAP_TO_INDEX(CAP_SYS_NICE)].permitted |= CAP_TO_MASK(CAP_SYS_NICE); - - // Drop all caps but the ones configured above. - ret = capset(&capheader, capdata); - CHECK_ERROR(ret < 0, error, "Could not set capabilities: %s", - strerror(errno)); - - dispatcher = android::pdx::ServiceDispatcher::Create(); - CHECK_ERROR(!dispatcher, error, "Failed to create service dispatcher."); - - service = android::dvr::PerformanceService::Create(); - CHECK_ERROR(!service, error, "Failed to create performance service service."); - dispatcher->AddService(service); - - ALOGI("Entering message loop."); - - ret = dispatcher->EnterDispatchLoop(); - CHECK_ERROR(ret < 0, error, "Dispatch loop exited because: %s\n", - strerror(-ret)); - -error: - return ret; -} diff --git a/services/vr/performanced/performance_service.cpp b/services/vr/performanced/performance_service.cpp deleted file mode 100644 index 73dcf76fd0..0000000000 --- a/services/vr/performanced/performance_service.cpp +++ /dev/null @@ -1,461 +0,0 @@ -#include "performance_service.h" - -#include <sstream> - -#include <sched.h> -#include <sys/prctl.h> -#include <unistd.h> - -#include <pdx/default_transport/service_endpoint.h> -#include <pdx/rpc/argument_encoder.h> -#include <pdx/rpc/message_buffer.h> -#include <pdx/rpc/remote_method.h> -#include <private/android_filesystem_config.h> -#include <private/dvr/performance_rpc.h> -#include <private/dvr/trusted_uids.h> - -#include "task.h" - -// This prctl is only available in Android kernels. -#define PR_SET_TIMERSLACK_PID 41 - -using android::dvr::IsTrustedUid; -using android::dvr::Task; -using android::pdx::ErrorStatus; -using android::pdx::Message; -using android::pdx::Status; -using android::pdx::default_transport::Endpoint; -using android::pdx::rpc::DispatchRemoteMethod; - -namespace { - -const char kCpuSetBasePath[] = "/dev/cpuset"; - -const char kRootCpuSet[] = "/"; - -const char kVrAppRenderPolicy[] = "vr:app:render"; - -const bool kAllowAppsToRequestVrAppRenderPolicy = false; - -constexpr unsigned long kTimerSlackForegroundNs = 50000; -constexpr unsigned long kTimerSlackBackgroundNs = 40000000; - -// Expands the given parameter pack expression using an initializer list to -// guarantee ordering and a comma expression to guarantee even void expressions -// are valid elements of the initializer list. -#define EXPAND_PACK(...) \ - std::initializer_list<int> { (__VA_ARGS__, 0)... } - -// Returns true if the sender's euid matches any of the uids in |UIDs|. -template <uid_t... UIDs> -struct UserId { - static bool Check(const Message& sender, const Task&) { - const uid_t uid = sender.GetEffectiveUserId(); - bool allow = false; - EXPAND_PACK(allow |= (uid == UIDs)); - return allow; - } -}; - -// Returns true if the sender's egid matches any of the gids in |GIDs|. -template <gid_t... GIDs> -struct GroupId { - static bool Check(const Message& sender, const Task&) { - const gid_t gid = sender.GetEffectiveGroupId(); - bool allow = false; - EXPAND_PACK(allow |= (gid == GIDs)); - return allow; - } -}; - -// Returns true if the sender's euid is trusted according to VR manager service. -struct Trusted { - static bool Check(const Message& sender, const Task&) { - return IsTrustedUid(sender.GetEffectiveUserId()); - } -}; - -// Returns returns true if the task belongs to the sending process. -struct SameProcess { - static bool Check(const Message& sender, const Task& task) { - return sender.GetProcessId() == task.thread_group_id(); - } -}; - -// Returns true if any of the checks in |Allows| pass, false otherwise. -template <typename... Allows> -struct CheckOr { - static bool Check(const Message& sender, const Task& task) { - bool allow = false; - EXPAND_PACK(allow |= Allows::Check(sender, task)); - return allow; - } -}; - -// Returns true if all of the checks in |Allows| pass, false otherwise. -template <typename... Allows> -struct CheckAnd { - static bool Check(const Message& sender, const Task& task) { - bool allow = true; - EXPAND_PACK(allow &= Allows::Check(sender, task)); - return allow; - } -}; - -} // anonymous namespace - -namespace android { -namespace dvr { - -PerformanceService::PerformanceService() - : BASE("PerformanceService", - Endpoint::Create(PerformanceRPC::kClientPath)) { - cpuset_.Load(kCpuSetBasePath); - - Task task(getpid()); - ALOGI("Running in cpuset=%s uid=%d gid=%d", task.GetCpuSetPath().c_str(), - task.user_id()[Task::kUidReal], task.group_id()[Task::kUidReal]); - - // Errors here are checked in IsInitialized(). - sched_fifo_min_priority_ = sched_get_priority_min(SCHED_FIFO); - sched_fifo_max_priority_ = sched_get_priority_max(SCHED_FIFO); - - const int fifo_range = sched_fifo_max_priority_ - sched_fifo_min_priority_; - const int fifo_low = sched_fifo_min_priority_; - const int fifo_medium = sched_fifo_min_priority_ + fifo_range / 5; - - // TODO(eieio): Make this configurable on the command line or config file. - cpuset_.MoveUnboundTasks("/kernel"); - - // TODO(eieio): Replace this witha device-specific config file. This is just a - // hack for now to put some form of permission logic in place while a longer - // term solution is developed. - using AllowRootSystemGraphics = - CheckAnd<SameProcess, CheckOr<UserId<AID_ROOT, AID_SYSTEM, AID_GRAPHICS>, - GroupId<AID_SYSTEM, AID_GRAPHICS>>>; - using AllowRootSystemAudio = - CheckAnd<SameProcess, CheckOr<UserId<AID_ROOT, AID_SYSTEM, AID_AUDIO>, - GroupId<AID_SYSTEM, AID_AUDIO>>>; - using AllowRootSystemTrusted = - CheckOr<Trusted, UserId<AID_ROOT, AID_SYSTEM>, GroupId<AID_SYSTEM>>; - - auto vr_app_render_permission_check = []( - const pdx::Message& sender, const Task& task) { - // For vr:app:render, in addition to system/root apps and VrCore, we - // also allow apps to request vr:app:render if - // kAllowAppsToRequestVrAppRenderPolicy == true, but not for other - // apps, only for themselves. - return (task && task.thread_group_id() == sender.GetProcessId() && - kAllowAppsToRequestVrAppRenderPolicy) - || AllowRootSystemTrusted::Check(sender, task); - }; - - partition_permission_check_ = AllowRootSystemTrusted::Check; - - // Setup the scheduler classes. - // TODO(eieio): Replace this with a device-specific config file. - scheduler_policies_ = { - {"audio:low", - {.timer_slack = kTimerSlackForegroundNs, - .scheduler_policy = SCHED_FIFO | SCHED_RESET_ON_FORK, - .priority = fifo_medium, - .permission_check = AllowRootSystemAudio::Check}}, - {"audio:high", - {.timer_slack = kTimerSlackForegroundNs, - .scheduler_policy = SCHED_FIFO | SCHED_RESET_ON_FORK, - .priority = fifo_medium + 3, - .permission_check = AllowRootSystemAudio::Check}}, - {"graphics", - {.timer_slack = kTimerSlackForegroundNs, - .scheduler_policy = SCHED_FIFO | SCHED_RESET_ON_FORK, - .priority = fifo_medium, - .permission_check = AllowRootSystemGraphics::Check}}, - {"graphics:low", - {.timer_slack = kTimerSlackForegroundNs, - .scheduler_policy = SCHED_FIFO | SCHED_RESET_ON_FORK, - .priority = fifo_medium, - .permission_check = AllowRootSystemGraphics::Check}}, - {"graphics:high", - {.timer_slack = kTimerSlackForegroundNs, - .scheduler_policy = SCHED_FIFO | SCHED_RESET_ON_FORK, - .priority = fifo_medium + 2, - .permission_check = AllowRootSystemGraphics::Check}}, - {"sensors", - {.timer_slack = kTimerSlackForegroundNs, - .scheduler_policy = SCHED_FIFO | SCHED_RESET_ON_FORK, - .priority = fifo_low, - .permission_check = AllowRootSystemTrusted::Check}}, - {"sensors:low", - {.timer_slack = kTimerSlackForegroundNs, - .scheduler_policy = SCHED_FIFO | SCHED_RESET_ON_FORK, - .priority = fifo_low, - .permission_check = AllowRootSystemTrusted::Check}}, - {"sensors:high", - {.timer_slack = kTimerSlackForegroundNs, - .scheduler_policy = SCHED_FIFO | SCHED_RESET_ON_FORK, - .priority = fifo_low + 1, - .permission_check = AllowRootSystemTrusted::Check}}, - {"vr:system:arp", - {.timer_slack = kTimerSlackForegroundNs, - .scheduler_policy = SCHED_FIFO | SCHED_RESET_ON_FORK, - .priority = fifo_medium + 2, - .permission_check = AllowRootSystemTrusted::Check, - "/system/performance"}}, - {kVrAppRenderPolicy, - {.timer_slack = kTimerSlackForegroundNs, - .scheduler_policy = SCHED_FIFO | SCHED_RESET_ON_FORK, - .priority = fifo_medium + 1, - .permission_check = vr_app_render_permission_check, - "/application/performance"}}, - {"normal", - {.timer_slack = kTimerSlackForegroundNs, - .scheduler_policy = SCHED_NORMAL, - .priority = 0}}, - {"foreground", - {.timer_slack = kTimerSlackForegroundNs, - .scheduler_policy = SCHED_NORMAL, - .priority = 0}}, - {"background", - {.timer_slack = kTimerSlackBackgroundNs, - .scheduler_policy = SCHED_BATCH, - .priority = 0}}, - {"batch", - {.timer_slack = kTimerSlackBackgroundNs, - .scheduler_policy = SCHED_BATCH, - .priority = 0}}, - }; -} - -bool PerformanceService::IsInitialized() const { - return BASE::IsInitialized() && cpuset_ && sched_fifo_min_priority_ >= 0 && - sched_fifo_max_priority_ >= 0; -} - -std::string PerformanceService::DumpState(size_t /*max_length*/) { - std::ostringstream stream; - stream << "vr_app_render_thread: " << vr_app_render_thread_ << std::endl; - cpuset_.DumpState(stream); - return stream.str(); -} - -Status<void> PerformanceService::OnSetSchedulerPolicy( - Message& message, pid_t task_id, const std::string& scheduler_policy) { - ALOGI( - "PerformanceService::OnSetSchedulerPolicy: task_id=%d " - "scheduler_policy=%s", - task_id, scheduler_policy.c_str()); - - Task task(task_id); - if (!task) { - ALOGE( - "PerformanceService::OnSetSchedulerPolicy: Unable to access /proc/%d " - "to gather task information.", - task_id); - return ErrorStatus(EINVAL); - } - - auto search = scheduler_policies_.find(scheduler_policy); - if (search != scheduler_policies_.end()) { - auto config = search->second; - - // Make sure the sending process is allowed to make the requested change to - // this task. - if (!config.IsAllowed(message, task)) - return ErrorStatus(EPERM); - - if (scheduler_policy == kVrAppRenderPolicy) { - // We only allow one vr:app:render thread at a time - SetVrAppRenderThread(task_id); - } - - // Get the thread group's cpu set. Policies that do not specify a cpuset - // should default to this cpuset. - std::string thread_group_cpuset; - Task thread_group{task.thread_group_id()}; - if (thread_group) { - thread_group_cpuset = thread_group.GetCpuSetPath(); - } else { - ALOGE( - "PerformanceService::OnSetSchedulerPolicy: Failed to get thread " - "group tgid=%d for task_id=%d", - task.thread_group_id(), task_id); - thread_group_cpuset = kRootCpuSet; - } - - std::string target_cpuset; - if (config.cpuset.empty()) { - target_cpuset = thread_group_cpuset; - } else { - target_cpuset = config.cpuset; - } - ALOGI("PerformanceService::OnSetSchedulerPolicy: Using cpuset=%s", - target_cpuset.c_str()); - - auto target_set = cpuset_.Lookup(target_cpuset); - if (target_set) { - auto attach_status = target_set->AttachTask(task_id); - ALOGW_IF(!attach_status, - "PerformanceService::OnSetSchedulerPolicy: Failed to attach " - "task=%d to cpuset=%s: %s", - task_id, target_cpuset.c_str(), - attach_status.GetErrorMessage().c_str()); - } else { - ALOGW( - "PerformanceService::OnSetSchedulerPolicy: Failed to lookup " - "cpuset=%s", - target_cpuset.c_str()); - } - - struct sched_param param; - param.sched_priority = config.priority; - - sched_setscheduler(task_id, config.scheduler_policy, ¶m); - prctl(PR_SET_TIMERSLACK_PID, config.timer_slack, task_id); - return {}; - } else { - ALOGE( - "PerformanceService::OnSetSchedulerPolicy: Invalid scheduler_policy=%s " - "requested by task=%d.", - scheduler_policy.c_str(), task_id); - return ErrorStatus(EINVAL); - } -} - -Status<void> PerformanceService::OnSetCpuPartition( - Message& message, pid_t task_id, const std::string& partition) { - Task task(task_id); - if (!task) - return ErrorStatus(EINVAL); - if (task.thread_group_id() != message.GetProcessId()) - return ErrorStatus(EPERM); - - // Temporary permission check. - // TODO(eieio): Replace this with a configuration file. - if (partition_permission_check_ && - !partition_permission_check_(message, task)) { - return ErrorStatus(EPERM); - } - - auto target_set = cpuset_.Lookup(partition); - if (!target_set) - return ErrorStatus(ENOENT); - - auto attach_status = target_set->AttachTask(task_id); - if (!attach_status) - return attach_status; - - return {}; -} - -Status<void> PerformanceService::OnSetSchedulerClass( - Message& message, pid_t task_id, const std::string& scheduler_class) { - Task task(task_id); - if (!task) - return ErrorStatus(EINVAL); - - auto search = scheduler_policies_.find(scheduler_class); - if (search != scheduler_policies_.end()) { - auto config = search->second; - - // Make sure the sending process is allowed to make the requested change to - // this task. - if (!config.IsAllowed(message, task)) - return ErrorStatus(EPERM); - - if (scheduler_class == kVrAppRenderPolicy) { - // We only allow one vr:app:render thread at a time - SetVrAppRenderThread(task_id); - } - - struct sched_param param; - param.sched_priority = config.priority; - - sched_setscheduler(task_id, config.scheduler_policy, ¶m); - prctl(PR_SET_TIMERSLACK_PID, config.timer_slack, task_id); - ALOGI("PerformanceService::OnSetSchedulerClass: Set task=%d to class=%s.", - task_id, scheduler_class.c_str()); - return {}; - } else { - ALOGE( - "PerformanceService::OnSetSchedulerClass: Invalid class=%s requested " - "by task=%d.", - scheduler_class.c_str(), task_id); - return ErrorStatus(EINVAL); - } -} - -Status<std::string> PerformanceService::OnGetCpuPartition(Message& message, - pid_t task_id) { - // Make sure the task id is valid and belongs to the sending process. - Task task(task_id); - if (!task) - return ErrorStatus(EINVAL); - if (task.thread_group_id() != message.GetProcessId()) - return ErrorStatus(EPERM); - - return task.GetCpuSetPath(); -} - -Status<void> PerformanceService::HandleMessage(Message& message) { - ALOGD_IF(TRACE, "PerformanceService::HandleMessage: op=%d", message.GetOp()); - switch (message.GetOp()) { - case PerformanceRPC::SetSchedulerPolicy::Opcode: - DispatchRemoteMethod<PerformanceRPC::SetSchedulerPolicy>( - *this, &PerformanceService::OnSetSchedulerPolicy, message); - return {}; - - case PerformanceRPC::SetCpuPartition::Opcode: - DispatchRemoteMethod<PerformanceRPC::SetCpuPartition>( - *this, &PerformanceService::OnSetCpuPartition, message); - return {}; - - case PerformanceRPC::SetSchedulerClass::Opcode: - DispatchRemoteMethod<PerformanceRPC::SetSchedulerClass>( - *this, &PerformanceService::OnSetSchedulerClass, message); - return {}; - - case PerformanceRPC::GetCpuPartition::Opcode: - DispatchRemoteMethod<PerformanceRPC::GetCpuPartition>( - *this, &PerformanceService::OnGetCpuPartition, message); - return {}; - - default: - return Service::HandleMessage(message); - } -} - -void PerformanceService::SetVrAppRenderThread(pid_t new_vr_app_render_thread) { - ALOGI("SetVrAppRenderThread old=%d new=%d", - vr_app_render_thread_, new_vr_app_render_thread); - - if (vr_app_render_thread_ >= 0 && - vr_app_render_thread_ != new_vr_app_render_thread) { - // Restore the default scheduler policy and priority on the previous - // vr:app:render thread. - struct sched_param param; - param.sched_priority = 0; - if (sched_setscheduler(vr_app_render_thread_, SCHED_NORMAL, ¶m) < 0) { - if (errno == ESRCH) { - ALOGI("Failed to revert %s scheduler policy. Couldn't find thread %d." - " Was the app killed?", kVrAppRenderPolicy, vr_app_render_thread_); - } else { - ALOGE("Failed to revert %s scheduler policy: %s", - kVrAppRenderPolicy, strerror(errno)); - } - } - - // Restore the default timer slack on the previous vr:app:render thread. - prctl(PR_SET_TIMERSLACK_PID, kTimerSlackForegroundNs, - vr_app_render_thread_); - } - - // We could also reset the thread's cpuset here, but the cpuset is already - // managed by Android. Better to let Android adjust the cpuset as the app - // moves to the background, rather than adjust it ourselves here, and risk - // stomping on the value set by Android. - - vr_app_render_thread_ = new_vr_app_render_thread; -} - -} // namespace dvr -} // namespace android diff --git a/services/vr/performanced/performance_service.h b/services/vr/performanced/performance_service.h deleted file mode 100644 index fe63756dbd..0000000000 --- a/services/vr/performanced/performance_service.h +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef ANDROID_DVR_PERFORMANCED_PERFORMANCE_SERVICE_H_ -#define ANDROID_DVR_PERFORMANCED_PERFORMANCE_SERVICE_H_ - -#include <functional> -#include <string> -#include <unordered_map> - -#include <pdx/service.h> - -#include "cpu_set.h" -#include "task.h" - -namespace android { -namespace dvr { - -// PerformanceService manages compute partitions usings cpusets. Different -// cpusets are assigned specific purposes and performance characteristics; -// clients may request for threads to be moved into these cpusets to help -// achieve system performance goals. -class PerformanceService : public pdx::ServiceBase<PerformanceService> { - public: - pdx::Status<void> HandleMessage(pdx::Message& message) override; - bool IsInitialized() const override; - - std::string DumpState(size_t max_length) override; - - private: - friend BASE; - - PerformanceService(); - - pdx::Status<void> OnSetSchedulerPolicy(pdx::Message& message, pid_t task_id, - const std::string& scheduler_class); - - pdx::Status<void> OnSetCpuPartition(pdx::Message& message, pid_t task_id, - const std::string& partition); - pdx::Status<void> OnSetSchedulerClass(pdx::Message& message, pid_t task_id, - const std::string& scheduler_class); - pdx::Status<std::string> OnGetCpuPartition(pdx::Message& message, - pid_t task_id); - - // Set which thread gets the vr:app:render policy. Only one thread at a time - // is allowed to have vr:app:render. If multiple threads are allowed - // vr:app:render, and those threads busy loop, the system can freeze. When - // SetVrAppRenderThread() is called, the thread which we had previously - // assigned vr:app:render will have its scheduling policy reset to default - // values. - void SetVrAppRenderThread(pid_t new_vr_app_render_thread); - - CpuSetManager cpuset_; - - int sched_fifo_min_priority_; - int sched_fifo_max_priority_; - - struct SchedulerPolicyConfig { - unsigned long timer_slack; - int scheduler_policy; - int priority; - std::function<bool(const pdx::Message& message, const Task& task)> - permission_check; - std::string cpuset; - - // Check the permisison of the given task to use this scheduler class. If a - // permission check function is not set then operations are only allowed on - // tasks in the sender's process. - bool IsAllowed(const pdx::Message& sender, const Task& task) const { - if (permission_check) - return permission_check(sender, task); - else if (!task || task.thread_group_id() != sender.GetProcessId()) - return false; - else - return true; - } - }; - - std::unordered_map<std::string, SchedulerPolicyConfig> scheduler_policies_; - - std::function<bool(const pdx::Message& message, const Task& task)> - partition_permission_check_; - - pid_t vr_app_render_thread_ = -1; - - PerformanceService(const PerformanceService&) = delete; - void operator=(const PerformanceService&) = delete; -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_PERFORMANCED_PERFORMANCE_SERVICE_H_ diff --git a/services/vr/performanced/performance_service_tests.cpp b/services/vr/performanced/performance_service_tests.cpp deleted file mode 100644 index a24c88979a..0000000000 --- a/services/vr/performanced/performance_service_tests.cpp +++ /dev/null @@ -1,529 +0,0 @@ -#include <errno.h> -#include <sched.h> -#include <stdio.h> -#include <sys/types.h> -#include <unistd.h> - -#include <condition_variable> -#include <cstdlib> -#include <iostream> -#include <mutex> -#include <sstream> -#include <thread> -#include <utility> - -#include <android-base/strings.h> -#include <android-base/unique_fd.h> -#include <dvr/performance_client_api.h> -#include <gtest/gtest.h> -#include <private/android_filesystem_config.h> - -#include "stdio_filebuf.h" -#include "unique_file.h" - -using android::base::Trim; -using android::dvr::UniqueFile; -using android::dvr::stdio_filebuf; - -namespace { - -const char kTrustedUidEnvironmentVariable[] = "GTEST_TRUSTED_UID"; - -const char kProcBase[] = "/proc"; - -std::pair<UniqueFile, int> OpenTaskFile(pid_t task_id, - const std::string& name) { - std::ostringstream stream; - stream << kProcBase << "/" << task_id << "/" << name; - - UniqueFile file{fopen(stream.str().c_str(), "r")}; - const int error = file ? 0 : errno; - return {std::move(file), error}; -} - -std::string GetTaskCpuSet(pid_t task_id) { - int error; - UniqueFile file; - - std::tie(file, error) = OpenTaskFile(task_id, "cpuset"); - if (!file) - return std::string("errno:") + strerror(error); - - stdio_filebuf<char> filebuf(file.get()); - std::istream file_stream(&filebuf); - - std::string line; - std::getline(file_stream, line); - return Trim(line); -} - -} // anonymous namespace - -TEST(PerformanceTest, SetCpuPartition) { - int error; - - // Test setting the the partition for the current task. - error = dvrSetCpuPartition(0, "/application/background"); - EXPECT_EQ(0, error); - - error = dvrSetCpuPartition(0, "/application/performance"); - EXPECT_EQ(0, error); - - // Test setting the partition for one of our tasks. - bool done = false; - pid_t task_id = 0; - std::mutex mutex; - std::condition_variable done_condition, id_condition; - - std::thread thread([&] { - std::unique_lock<std::mutex> lock(mutex); - - task_id = gettid(); - id_condition.notify_one(); - - done_condition.wait(lock, [&done] { return done; }); - }); - - { - std::unique_lock<std::mutex> lock(mutex); - id_condition.wait(lock, [&task_id] { return task_id != 0; }); - } - EXPECT_NE(0, task_id); - - error = dvrSetCpuPartition(task_id, "/application"); - EXPECT_EQ(0, error); - - { - std::lock_guard<std::mutex> lock(mutex); - done = true; - done_condition.notify_one(); - } - thread.join(); - - // Test setting the partition for a task that doesn't belong to us. - error = dvrSetCpuPartition(1, "/application"); - EXPECT_EQ(-EINVAL, error); - - // Test setting the partition to one that doesn't exist. - error = dvrSetCpuPartition(0, "/foobar"); - EXPECT_EQ(-ENOENT, error); - - // Set the test back to the root partition. - error = dvrSetCpuPartition(0, "/"); - EXPECT_EQ(0, error); -} - -TEST(PerformanceTest, SetSchedulerClass) { - int error; - - // TODO(eieio): Test all supported scheduler classes and priority levels. - - error = dvrSetSchedulerClass(0, "background"); - EXPECT_EQ(0, error); - EXPECT_EQ(SCHED_BATCH, sched_getscheduler(0)); - - error = dvrSetSchedulerClass(0, "audio:low"); - EXPECT_EQ(0, error); - EXPECT_EQ(SCHED_FIFO | SCHED_RESET_ON_FORK, sched_getscheduler(0)); - - error = dvrSetSchedulerClass(0, "normal"); - EXPECT_EQ(0, error); - EXPECT_EQ(SCHED_NORMAL, sched_getscheduler(0)); - - error = dvrSetSchedulerClass(0, "foobar"); - EXPECT_EQ(-EINVAL, error); -} - -TEST(PerformanceTest, SetSchedulerPolicy) { - int error; - - error = dvrSetSchedulerPolicy(0, "background"); - EXPECT_EQ(0, error); - EXPECT_EQ(SCHED_BATCH, sched_getscheduler(0)); - - error = dvrSetSchedulerPolicy(0, "audio:low"); - EXPECT_EQ(0, error); - EXPECT_EQ(SCHED_FIFO | SCHED_RESET_ON_FORK, sched_getscheduler(0)); - - error = dvrSetSchedulerPolicy(0, "normal"); - EXPECT_EQ(0, error); - EXPECT_EQ(SCHED_NORMAL, sched_getscheduler(0)); - - error = dvrSetSchedulerPolicy(0, "foobar"); - EXPECT_EQ(-EINVAL, error); - - // Set the test back to the root partition. - error = dvrSetCpuPartition(0, "/"); - EXPECT_EQ(0, error); - - const std::string original_cpuset = GetTaskCpuSet(gettid()); - EXPECT_EQ("/", original_cpuset); - - error = dvrSetSchedulerPolicy(0, "vr:system:arp"); - EXPECT_EQ(0, error); - EXPECT_EQ(SCHED_FIFO | SCHED_RESET_ON_FORK, sched_getscheduler(0)); - - const std::string new_cpuset = GetTaskCpuSet(gettid()); - EXPECT_NE(original_cpuset, new_cpuset); - - // The cpuset for the thread group is now new_cpuset. Scheduler profiles that - // do not specify a cpuset should not change the cpuset of a thread, except to - // restore it to the thread group cpuset. - std::string thread_original_cpuset; - std::string thread_new_cpuset; - std::string thread_final_cpuset; - - std::thread thread{ - [&thread_original_cpuset, &thread_new_cpuset, &thread_final_cpuset]() { - thread_original_cpuset = GetTaskCpuSet(gettid()); - - int error = dvrSetSchedulerPolicy(0, "vr:app:render"); - EXPECT_EQ(0, error); - - thread_new_cpuset = GetTaskCpuSet(gettid()); - - error = dvrSetSchedulerPolicy(0, "normal"); - EXPECT_EQ(0, error); - - thread_final_cpuset = GetTaskCpuSet(gettid()); - }}; - thread.join(); - - EXPECT_EQ(new_cpuset, thread_original_cpuset); - EXPECT_NE(new_cpuset, thread_new_cpuset); - EXPECT_EQ(new_cpuset, thread_final_cpuset); - - error = dvrSetCpuPartition(0, original_cpuset.c_str()); - EXPECT_EQ(0, error); -} - -TEST(PerformanceTest, SchedulerClassResetOnFork) { - int error; - - error = dvrSetSchedulerClass(0, "graphics:high"); - EXPECT_EQ(0, error); - EXPECT_EQ(SCHED_FIFO | SCHED_RESET_ON_FORK, sched_getscheduler(0)); - - int scheduler = -1; - std::thread thread([&]() { scheduler = sched_getscheduler(0); }); - thread.join(); - - EXPECT_EQ(SCHED_NORMAL, scheduler); - - // Return to SCHED_NORMAL. - error = dvrSetSchedulerClass(0, "normal"); - EXPECT_EQ(0, error); - EXPECT_EQ(SCHED_NORMAL, sched_getscheduler(0)); -} - -TEST(PerformanceTest, GetCpuPartition) { - int error; - char partition[PATH_MAX + 1]; - - error = dvrSetCpuPartition(0, "/"); - ASSERT_EQ(0, error); - - error = dvrGetCpuPartition(0, partition, sizeof(partition)); - EXPECT_EQ(0, error); - EXPECT_EQ("/", std::string(partition)); - - error = dvrSetCpuPartition(0, "/application"); - EXPECT_EQ(0, error); - - error = dvrGetCpuPartition(0, partition, sizeof(partition)); - EXPECT_EQ(0, error); - EXPECT_EQ("/application", std::string(partition)); - - // Test passing a buffer that is too short. - error = dvrGetCpuPartition(0, partition, 5); - EXPECT_EQ(-ENOBUFS, error); - - // Test getting the partition for a task that doesn't belong to us. - error = dvrGetCpuPartition(1, partition, sizeof(partition)); - EXPECT_EQ(-EINVAL, error); - - // Test passing a nullptr value for partition buffer. - error = dvrGetCpuPartition(0, nullptr, sizeof(partition)); - EXPECT_EQ(-EINVAL, error); -} - -TEST(PerformanceTest, Permissions) { - int error; - - const int original_uid = getuid(); - const int original_gid = getgid(); - int trusted_uid = -1; - - // See if the environment variable GTEST_TRUSTED_UID is set. If it is enable - // testing the ActivityManager trusted uid permission checks using that uid. - const char* trusted_uid_env = std::getenv(kTrustedUidEnvironmentVariable); - if (trusted_uid_env) - trusted_uid = std::atoi(trusted_uid_env); - - ASSERT_EQ(AID_ROOT, original_uid) - << "This test must run as root to function correctly!"; - - // Test unprivileged policies on a task that does not belong to this process. - // Use the init process (task_id=1) as the target. - error = dvrSetSchedulerPolicy(1, "batch"); - EXPECT_EQ(-EINVAL, error); - error = dvrSetSchedulerPolicy(1, "background"); - EXPECT_EQ(-EINVAL, error); - error = dvrSetSchedulerPolicy(1, "foreground"); - EXPECT_EQ(-EINVAL, error); - error = dvrSetSchedulerPolicy(1, "normal"); - EXPECT_EQ(-EINVAL, error); - - // Switch the uid/gid to an id that should not have permission to access any - // privileged actions. - ASSERT_EQ(0, setresgid(AID_NOBODY, AID_NOBODY, -1)) - << "Failed to set gid: " << strerror(errno); - ASSERT_EQ(0, setresuid(AID_NOBODY, AID_NOBODY, -1)) - << "Failed to set uid: " << strerror(errno); - - // Unprivileged policies. - error = dvrSetSchedulerPolicy(0, "batch"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "background"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "foreground"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "normal"); - EXPECT_EQ(0, error); - - // Privileged policies. - error = dvrSetSchedulerPolicy(0, "audio:low"); - EXPECT_EQ(-EINVAL, error); - error = dvrSetSchedulerPolicy(0, "audio:high"); - EXPECT_EQ(-EINVAL, error); - error = dvrSetSchedulerPolicy(0, "graphics"); - EXPECT_EQ(-EINVAL, error); - error = dvrSetSchedulerPolicy(0, "graphics:low"); - EXPECT_EQ(-EINVAL, error); - error = dvrSetSchedulerPolicy(0, "graphics:high"); - EXPECT_EQ(-EINVAL, error); - error = dvrSetSchedulerPolicy(0, "sensors"); - EXPECT_EQ(-EINVAL, error); - error = dvrSetSchedulerPolicy(0, "sensors:low"); - EXPECT_EQ(-EINVAL, error); - error = dvrSetSchedulerPolicy(0, "sensors:high"); - EXPECT_EQ(-EINVAL, error); - error = dvrSetSchedulerPolicy(0, "vr:system:arp"); - EXPECT_EQ(-EINVAL, error); - error = dvrSetSchedulerPolicy(0, "vr:app:render"); - EXPECT_EQ(-EINVAL, error); - - // uid=AID_SYSTEM / gid=AID_NOBODY - ASSERT_EQ(0, setresuid(original_uid, original_uid, -1)) - << "Failed to restore uid: " << strerror(errno); - ASSERT_EQ(0, setresuid(AID_SYSTEM, AID_SYSTEM, -1)) - << "Failed to set uid: " << strerror(errno); - - // Unprivileged policies. - error = dvrSetSchedulerPolicy(0, "batch"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "background"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "foreground"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "normal"); - EXPECT_EQ(0, error); - - // Privileged policies. - error = dvrSetSchedulerPolicy(0, "audio:low"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "audio:high"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "graphics"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "graphics:low"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "graphics:high"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "sensors"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "sensors:low"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "sensors:high"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "vr:system:arp"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "vr:app:render"); - EXPECT_EQ(0, error); - - // uid=AID_NOBODY / gid=AID_SYSTEM - ASSERT_EQ(0, setresuid(original_uid, original_uid, -1)) - << "Failed to restore uid: " << strerror(errno); - ASSERT_EQ(0, setresgid(original_gid, original_gid, -1)) - << "Failed to restore gid: " << strerror(errno); - ASSERT_EQ(0, setresgid(AID_SYSTEM, AID_SYSTEM, -1)) - << "Failed to set gid: " << strerror(errno); - ASSERT_EQ(0, setresuid(AID_SYSTEM, AID_NOBODY, -1)) - << "Failed to set uid: " << strerror(errno); - - // Unprivileged policies. - error = dvrSetSchedulerPolicy(0, "batch"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "background"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "foreground"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "normal"); - EXPECT_EQ(0, error); - - // Privileged policies. - error = dvrSetSchedulerPolicy(0, "audio:low"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "audio:high"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "graphics"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "graphics:low"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "graphics:high"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "sensors"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "sensors:low"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "sensors:high"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "vr:system:arp"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "vr:app:render"); - EXPECT_EQ(0, error); - - // uid=AID_GRAPHICS / gid=AID_NOBODY - ASSERT_EQ(0, setresuid(original_uid, original_uid, -1)) - << "Failed to restore uid: " << strerror(errno); - ASSERT_EQ(0, setresgid(original_gid, original_gid, -1)) - << "Failed to restore gid: " << strerror(errno); - ASSERT_EQ(0, setresgid(AID_NOBODY, AID_NOBODY, -1)) - << "Failed to set gid: " << strerror(errno); - ASSERT_EQ(0, setresuid(AID_GRAPHICS, AID_GRAPHICS, -1)) - << "Failed to set uid: " << strerror(errno); - - // Unprivileged policies. - error = dvrSetSchedulerPolicy(0, "batch"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "background"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "foreground"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "normal"); - EXPECT_EQ(0, error); - - // Privileged policies. - error = dvrSetSchedulerPolicy(0, "audio:low"); - EXPECT_EQ(-EINVAL, error); - error = dvrSetSchedulerPolicy(0, "audio:high"); - EXPECT_EQ(-EINVAL, error); - error = dvrSetSchedulerPolicy(0, "graphics"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "graphics:low"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "graphics:high"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "sensors"); - EXPECT_EQ(-EINVAL, error); - error = dvrSetSchedulerPolicy(0, "sensors:low"); - EXPECT_EQ(-EINVAL, error); - error = dvrSetSchedulerPolicy(0, "sensors:high"); - EXPECT_EQ(-EINVAL, error); - error = dvrSetSchedulerPolicy(0, "vr:system:arp"); - EXPECT_EQ(-EINVAL, error); - error = dvrSetSchedulerPolicy(0, "vr:app:render"); - EXPECT_EQ(-EINVAL, error); - - // uid=AID_NOBODY / gid=AID_GRAPHICS - ASSERT_EQ(0, setresuid(original_uid, original_uid, -1)) - << "Failed to restore uid: " << strerror(errno); - ASSERT_EQ(0, setresgid(original_gid, original_gid, -1)) - << "Failed to restore gid: " << strerror(errno); - ASSERT_EQ(0, setresgid(AID_GRAPHICS, AID_GRAPHICS, -1)) - << "Failed to set gid: " << strerror(errno); - ASSERT_EQ(0, setresuid(AID_NOBODY, AID_NOBODY, -1)) - << "Failed to set uid: " << strerror(errno); - - // Unprivileged policies. - error = dvrSetSchedulerPolicy(0, "batch"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "background"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "foreground"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "normal"); - EXPECT_EQ(0, error); - - // Privileged policies. - error = dvrSetSchedulerPolicy(0, "audio:low"); - EXPECT_EQ(-EINVAL, error); - error = dvrSetSchedulerPolicy(0, "audio:high"); - EXPECT_EQ(-EINVAL, error); - error = dvrSetSchedulerPolicy(0, "graphics"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "graphics:low"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "graphics:high"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "sensors"); - EXPECT_EQ(-EINVAL, error); - error = dvrSetSchedulerPolicy(0, "sensors:low"); - EXPECT_EQ(-EINVAL, error); - error = dvrSetSchedulerPolicy(0, "sensors:high"); - EXPECT_EQ(-EINVAL, error); - error = dvrSetSchedulerPolicy(0, "vr:system:arp"); - EXPECT_EQ(-EINVAL, error); - error = dvrSetSchedulerPolicy(0, "vr:app:render"); - EXPECT_EQ(-EINVAL, error); - - if (trusted_uid != -1) { - // uid=<trusted uid> / gid=AID_NOBODY - ASSERT_EQ(0, setresuid(original_uid, original_uid, -1)) - << "Failed to restore uid: " << strerror(errno); - ASSERT_EQ(0, setresgid(original_gid, original_gid, -1)) - << "Failed to restore gid: " << strerror(errno); - ASSERT_EQ(0, setresgid(AID_NOBODY, AID_NOBODY, -1)) - << "Failed to set gid: " << strerror(errno); - ASSERT_EQ(0, setresuid(trusted_uid, trusted_uid, -1)) - << "Failed to set uid: " << strerror(errno); - - // Unprivileged policies. - error = dvrSetSchedulerPolicy(0, "batch"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "background"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "foreground"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "normal"); - EXPECT_EQ(0, error); - - // Privileged policies. - error = dvrSetSchedulerPolicy(0, "audio:low"); - EXPECT_EQ(-EINVAL, error); - error = dvrSetSchedulerPolicy(0, "audio:high"); - EXPECT_EQ(-EINVAL, error); - error = dvrSetSchedulerPolicy(0, "graphics"); - EXPECT_EQ(-EINVAL, error); - error = dvrSetSchedulerPolicy(0, "graphics:low"); - EXPECT_EQ(-EINVAL, error); - error = dvrSetSchedulerPolicy(0, "graphics:high"); - EXPECT_EQ(-EINVAL, error); - error = dvrSetSchedulerPolicy(0, "sensors"); - EXPECT_EQ(-EINVAL, error); - error = dvrSetSchedulerPolicy(0, "sensors:low"); - EXPECT_EQ(-EINVAL, error); - error = dvrSetSchedulerPolicy(0, "sensors:high"); - EXPECT_EQ(-EINVAL, error); - error = dvrSetSchedulerPolicy(0, "vr:system:arp"); - EXPECT_EQ(0, error); - error = dvrSetSchedulerPolicy(0, "vr:app:render"); - EXPECT_EQ(0, error); - } - - // Restore original effective uid/gid. - ASSERT_EQ(0, setresgid(original_gid, original_gid, -1)) - << "Failed to restore gid: " << strerror(errno); - ASSERT_EQ(0, setresuid(original_uid, original_uid, -1)) - << "Failed to restore uid: " << strerror(errno); -} diff --git a/services/vr/performanced/performanced.rc b/services/vr/performanced/performanced.rc deleted file mode 100644 index af9760eba3..0000000000 --- a/services/vr/performanced/performanced.rc +++ /dev/null @@ -1,5 +0,0 @@ -service performanced /system/bin/performanced - class core - user root - group system readproc - socket pdx/system/performance/client stream 0666 system system u:object_r:pdx_performance_client_endpoint_socket:s0 diff --git a/services/vr/performanced/stdio_filebuf.h b/services/vr/performanced/stdio_filebuf.h deleted file mode 100644 index 5988aa8525..0000000000 --- a/services/vr/performanced/stdio_filebuf.h +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT -// Copyright (c) 2016 Google, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -#ifndef ANDROID_DVR_PERFORMANCED_STDIO_FILEBUF_H_ -#define ANDROID_DVR_PERFORMANCED_STDIO_FILEBUF_H_ - -#include <cstdio> -#include <istream> -#include <locale> -#include <streambuf> - -namespace android { -namespace dvr { - -// An implementation of std::basic_streambuf backed by a FILE pointer. This is -// ported from the internal llvm-libc++ support for std::cin. It's really -// unfortunate that we have to do this, but the C++11 standard is too pendantic -// to support creating streams from file descriptors or FILE pointers. This -// implementation uses all standard interfaces, except for the call to -// std::__throw_runtime_error(), which is only needed to deal with exceeding -// locale encoding limits. This class is meant to be used for reading system -// files, which don't require exotic locale support, so this call could be -// removed in the future, if necessary. -// -// Original source file: llvm-libcxx/llvm-libc++/include/__std_stream -// Original class name: __stdinbuf -// -template <class _CharT> -class stdio_filebuf - : public std::basic_streambuf<_CharT, std::char_traits<_CharT> > { - public: - typedef _CharT char_type; - typedef std::char_traits<char_type> traits_type; - typedef typename traits_type::int_type int_type; - typedef typename traits_type::pos_type pos_type; - typedef typename traits_type::off_type off_type; - typedef typename traits_type::state_type state_type; - - explicit stdio_filebuf(FILE* __fp); - ~stdio_filebuf() override; - - protected: - virtual int_type underflow() override; - virtual int_type uflow() override; - virtual int_type pbackfail(int_type __c = traits_type::eof()) override; - virtual void imbue(const std::locale& __loc) override; - - private: - FILE* __file_; - const std::codecvt<char_type, char, state_type>* __cv_; - state_type __st_; - int __encoding_; - int_type __last_consumed_; - bool __last_consumed_is_next_; - bool __always_noconv_; - - stdio_filebuf(const stdio_filebuf&); - stdio_filebuf& operator=(const stdio_filebuf&); - - int_type __getchar(bool __consume); - - static const int __limit = 8; -}; - -template <class _CharT> -stdio_filebuf<_CharT>::stdio_filebuf(FILE* __fp) - : __file_(__fp), - __last_consumed_(traits_type::eof()), - __last_consumed_is_next_(false) { - imbue(this->getloc()); -} - -template <class _CharT> -stdio_filebuf<_CharT>::~stdio_filebuf() { - if (__file_) - fclose(__file_); -} - -template <class _CharT> -void stdio_filebuf<_CharT>::imbue(const std::locale& __loc) { - __cv_ = &std::use_facet<std::codecvt<char_type, char, state_type> >(__loc); - __encoding_ = __cv_->encoding(); - __always_noconv_ = __cv_->always_noconv(); - if (__encoding_ > __limit) - std::__throw_runtime_error("unsupported locale for standard io"); -} - -template <class _CharT> -typename stdio_filebuf<_CharT>::int_type stdio_filebuf<_CharT>::underflow() { - return __getchar(false); -} - -template <class _CharT> -typename stdio_filebuf<_CharT>::int_type stdio_filebuf<_CharT>::uflow() { - return __getchar(true); -} - -template <class _CharT> -typename stdio_filebuf<_CharT>::int_type stdio_filebuf<_CharT>::__getchar( - bool __consume) { - if (__last_consumed_is_next_) { - int_type __result = __last_consumed_; - if (__consume) { - __last_consumed_ = traits_type::eof(); - __last_consumed_is_next_ = false; - } - return __result; - } - char __extbuf[__limit]; - int __nread = std::max(1, __encoding_); - for (int __i = 0; __i < __nread; ++__i) { - int __c = getc(__file_); - if (__c == EOF) - return traits_type::eof(); - __extbuf[__i] = static_cast<char>(__c); - } - char_type __1buf; - if (__always_noconv_) - __1buf = static_cast<char_type>(__extbuf[0]); - else { - const char* __enxt; - char_type* __inxt; - std::codecvt_base::result __r; - do { - state_type __sv_st = __st_; - __r = __cv_->in(__st_, __extbuf, __extbuf + __nread, __enxt, &__1buf, - &__1buf + 1, __inxt); - switch (__r) { - case std::codecvt_base::ok: - break; - case std::codecvt_base::partial: - __st_ = __sv_st; - if (__nread == sizeof(__extbuf)) - return traits_type::eof(); - { - int __c = getc(__file_); - if (__c == EOF) - return traits_type::eof(); - __extbuf[__nread] = static_cast<char>(__c); - } - ++__nread; - break; - case std::codecvt_base::error: - return traits_type::eof(); - case std::codecvt_base::noconv: - __1buf = static_cast<char_type>(__extbuf[0]); - break; - } - } while (__r == std::codecvt_base::partial); - } - if (!__consume) { - for (int __i = __nread; __i > 0;) { - if (ungetc(traits_type::to_int_type(__extbuf[--__i]), __file_) == EOF) - return traits_type::eof(); - } - } else - __last_consumed_ = traits_type::to_int_type(__1buf); - return traits_type::to_int_type(__1buf); -} - -template <class _CharT> -typename stdio_filebuf<_CharT>::int_type stdio_filebuf<_CharT>::pbackfail( - int_type __c) { - if (traits_type::eq_int_type(__c, traits_type::eof())) { - if (!__last_consumed_is_next_) { - __c = __last_consumed_; - __last_consumed_is_next_ = - !traits_type::eq_int_type(__last_consumed_, traits_type::eof()); - } - return __c; - } - if (__last_consumed_is_next_) { - char __extbuf[__limit]; - char* __enxt; - const char_type __ci = traits_type::to_char_type(__last_consumed_); - const char_type* __inxt; - switch (__cv_->out(__st_, &__ci, &__ci + 1, __inxt, __extbuf, - __extbuf + sizeof(__extbuf), __enxt)) { - case std::codecvt_base::ok: - break; - case std::codecvt_base::noconv: - __extbuf[0] = static_cast<char>(__last_consumed_); - __enxt = __extbuf + 1; - break; - case std::codecvt_base::partial: - case std::codecvt_base::error: - return traits_type::eof(); - } - while (__enxt > __extbuf) - if (ungetc(*--__enxt, __file_) == EOF) - return traits_type::eof(); - } - __last_consumed_ = __c; - __last_consumed_is_next_ = true; - return __c; -} - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_PERFORMANCED_STDIO_FILEBUF_H_ diff --git a/services/vr/performanced/task.cpp b/services/vr/performanced/task.cpp deleted file mode 100644 index 2fc96bf3f5..0000000000 --- a/services/vr/performanced/task.cpp +++ /dev/null @@ -1,166 +0,0 @@ -#include "task.h" - -#include <errno.h> -#include <fcntl.h> -#include <log/log.h> -#include <stdio.h> - -#include <cctype> -#include <cstdlib> -#include <memory> -#include <sstream> - -#include <android-base/strings.h> -#include <android-base/unique_fd.h> - -#include "stdio_filebuf.h" - -namespace { - -const char kProcBase[] = "/proc"; - -android::base::unique_fd OpenTaskDirectory(pid_t task_id) { - std::ostringstream stream; - stream << kProcBase << "/" << task_id; - - return android::base::unique_fd( - open(stream.str().c_str(), O_RDONLY | O_DIRECTORY)); -} - -void ParseUidStatusField(const std::string& value, std::array<int, 4>& ids) { - const char* start = value.c_str(); - - ids[0] = std::strtol(start, const_cast<char**>(&start), 10); - ids[1] = std::strtol(start, const_cast<char**>(&start), 10); - ids[2] = std::strtol(start, const_cast<char**>(&start), 10); - ids[3] = std::strtol(start, const_cast<char**>(&start), 10); -} - -} // anonymous namespace - -namespace android { -namespace dvr { - -Task::Task(pid_t task_id) - : task_id_(task_id), - thread_group_id_(-1), - parent_process_id_(-1), - thread_count_(0), - cpus_allowed_mask_(0) { - task_fd_ = OpenTaskDirectory(task_id_); - const int error = errno; - ALOGE_IF(task_fd_.get() < 0 && error != EACCES, - "Task::Task: Failed to open task directory for task_id=%d: %s", - task_id, strerror(error)); - - if (IsValid()) { - ReadStatusFields(); - ALOGD_IF(TRACE, - "Task::Task: task_id=%d name=%s tgid=%d ppid=%d cpu_mask=%x", - task_id_, name_.c_str(), thread_group_id_, parent_process_id_, - cpus_allowed_mask_); - } -} - -base::unique_fd Task::OpenTaskFile(const std::string& name) const { - const std::string relative_path = "./" + name; - return base::unique_fd( - openat(task_fd_.get(), relative_path.c_str(), O_RDONLY)); -} - -UniqueFile Task::OpenTaskFilePointer(const std::string& name) const { - const std::string relative_path = "./" + name; - base::unique_fd fd(openat(task_fd_.get(), relative_path.c_str(), O_RDONLY)); - if (fd.get() < 0) { - ALOGE("Task::OpenTaskFilePointer: Failed to open /proc/%d/%s: %s", task_id_, - name.c_str(), strerror(errno)); - return nullptr; - } - - UniqueFile fp(fdopen(fd.release(), "r")); - if (!fp) - ALOGE("Task::OpenTaskFilePointer: Failed to fdopen /proc/%d/%s: %s", - task_id_, name.c_str(), strerror(errno)); - - return fp; -} - -std::string Task::GetStatusField(const std::string& field) const { - if (auto file = OpenTaskFilePointer("status")) { - stdio_filebuf<char> filebuf(file.get()); - std::istream file_stream(&filebuf); - - for (std::string line; std::getline(file_stream, line);) { - auto offset = line.find(field); - - ALOGD_IF(TRACE, - "Task::GetStatusField: field=\"%s\" line=\"%s\" offset=%zd", - field.c_str(), line.c_str(), offset); - - if (offset == std::string::npos) - continue; - - // The status file has lines with the format <field>:<value>. Extract the - // value after the colon. - return android::base::Trim(line.substr(offset + field.size() + 1)); - } - } - - return "[unknown]"; -} - -void Task::ReadStatusFields() { - if (auto file = OpenTaskFilePointer("status")) { - stdio_filebuf<char> filebuf(file.get()); - std::istream file_stream(&filebuf); - - for (std::string line; std::getline(file_stream, line);) { - auto offset = line.find(':'); - if (offset == std::string::npos) { - ALOGW("ReadStatusFields: Failed to find delimiter \":\" in line=\"%s\"", - line.c_str()); - continue; - } - - std::string key = line.substr(0, offset); - std::string value = android::base::Trim(line.substr(offset + 1)); - - ALOGD_IF(TRACE, "Task::ReadStatusFields: key=\"%s\" value=\"%s\"", - key.c_str(), value.c_str()); - - if (key == "Name") - name_ = value; - else if (key == "Tgid") - thread_group_id_ = std::strtol(value.c_str(), nullptr, 10); - else if (key == "PPid") - parent_process_id_ = std::strtol(value.c_str(), nullptr, 10); - else if (key == "Uid") - ParseUidStatusField(value, user_id_); - else if (key == "Gid") - ParseUidStatusField(value, group_id_); - else if (key == "Threads") - thread_count_ = std::strtoul(value.c_str(), nullptr, 10); - else if (key == "Cpus_allowed") - cpus_allowed_mask_ = std::strtoul(value.c_str(), nullptr, 16); - else if (key == "Cpus_allowed_list") - cpus_allowed_list_ = value; - } - } -} - -std::string Task::GetCpuSetPath() const { - if (auto file = OpenTaskFilePointer("cpuset")) { - stdio_filebuf<char> filebuf(file.get()); - std::istream file_stream(&filebuf); - - std::string line = ""; - std::getline(file_stream, line); - - return android::base::Trim(line); - } else { - return ""; - } -} - -} // namespace dvr -} // namespace android diff --git a/services/vr/performanced/task.h b/services/vr/performanced/task.h deleted file mode 100644 index 4a3b7f23bc..0000000000 --- a/services/vr/performanced/task.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef ANDROID_DVR_PERFORMANCED_TASK_H_ -#define ANDROID_DVR_PERFORMANCED_TASK_H_ - -#include <sys/types.h> - -#include <array> -#include <cstdio> -#include <memory> -#include <string> -#include <unordered_map> -#include <vector> - -#include <android-base/unique_fd.h> - -#include "unique_file.h" - -namespace android { -namespace dvr { - -// Task provides access to task-related information from the procfs -// pseudo-filesystem. -class Task { - public: - explicit Task(pid_t task_id); - - bool IsValid() const { return task_fd_.get() >= 0; } - explicit operator bool() const { return IsValid(); } - - pid_t task_id() const { return task_id_; } - std::string name() const { return name_; } - pid_t thread_group_id() const { return thread_group_id_; } - pid_t parent_process_id() const { return parent_process_id_; } - size_t thread_count() const { return thread_count_; } - uint32_t cpus_allowed_mask() const { return cpus_allowed_mask_; } - const std::string& cpus_allowed_list() const { return cpus_allowed_list_; } - const std::array<int, 4>& user_id() const { return user_id_; } - const std::array<int, 4>& group_id() const { return group_id_; } - - // Indices into user and group id arrays. - enum { - kUidReal = 0, - kUidEffective, - kUidSavedSet, - kUidFilesystem, - }; - - std::string GetCpuSetPath() const; - - private: - pid_t task_id_; - base::unique_fd task_fd_; - - // Fields read from /proc/<task_id_>/status. - std::string name_; - pid_t thread_group_id_; - pid_t parent_process_id_; - std::array<int, 4> user_id_; - std::array<int, 4> group_id_; - size_t thread_count_; - uint32_t cpus_allowed_mask_; - std::string cpus_allowed_list_; - - // Opens the file /proc/<task_id_>/|name| and returns the open file - // descriptor. - base::unique_fd OpenTaskFile(const std::string& name) const; - - // Similar to OpenTaskFile() but returns a file pointer. - UniqueFile OpenTaskFilePointer(const std::string& name) const; - - // Reads the field named |field| from /proc/<task_id_>/status. - std::string GetStatusField(const std::string& field) const; - - // Reads a subset of the fields in /proc/<task_id_>/status. - void ReadStatusFields(); - - Task(const Task&) = delete; - void operator=(const Task&) = delete; -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_PERFORMANCED_TASK_H_ diff --git a/services/vr/performanced/unique_file.h b/services/vr/performanced/unique_file.h deleted file mode 100644 index 86e487a83a..0000000000 --- a/services/vr/performanced/unique_file.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef ANDROID_DVR_PERFORMANCED_UNIQUE_FILE_H_ -#define ANDROID_DVR_PERFORMANCED_UNIQUE_FILE_H_ - -#include <stdio.h> - -#include <memory> - -namespace android { -namespace dvr { - -// Utility to manage the lifetime of a file pointer. -struct FileDeleter { - void operator()(FILE* fp) { fclose(fp); } -}; -using UniqueFile = std::unique_ptr<FILE, FileDeleter>; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_PERFORMANCED_UNIQUE_FILE_H_ diff --git a/services/vr/virtual_touchpad/Android.bp b/services/vr/virtual_touchpad/Android.bp deleted file mode 100644 index f2ec5a42b1..0000000000 --- a/services/vr/virtual_touchpad/Android.bp +++ /dev/null @@ -1,140 +0,0 @@ - - -// Touchpad implementation. - -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "frameworks_native_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["frameworks_native_license"], -} - -src = [ - "EvdevInjector.cpp", - "VirtualTouchpadEvdev.cpp", -] - -shared_libs = [ - "libbase", - "liblog", - "libutils", -] - -header_libraries = [ - "jni_headers", - "libdvr_headers", -] - -cc_library { - srcs: src, - export_include_dirs: ["include"], - shared_libs: shared_libs, - header_libs: header_libraries, - cflags: [ - "-DLOG_TAG=\"VrVirtualTouchpad\"", - "-Wall", - "-Werror", - ], - name: "libvirtualtouchpad", -} - -// Touchpad unit tests. - -test_static_libs = [ - "libcutils", - "libvirtualtouchpad", - "libbase", - "liblog", - "libutils", -] - -test_src_files = ["tests/VirtualTouchpad_test.cpp"] - -cc_test { - srcs: test_src_files, - static_libs: test_static_libs, - header_libs: header_libraries, - cflags: [ - "-Wall", - "-Werror", - ], - host_ldlibs: [ - "-llog", - ], - name: "VirtualTouchpad_test", - stl: "libc++_static", -} - -// Service. - -service_src = [ - "main.cpp", - "VirtualTouchpadService.cpp", - ":virtualtouchpad_aidl", -] - -service_static_libs = [ - "libcutils", - "libvirtualtouchpad", -] - -service_shared_libs = [ - "libbase", - "libbinder", - "liblog", - "libutils", -] - -cc_binary { - srcs: service_src, - static_libs: service_static_libs, - shared_libs: service_shared_libs, - header_libs: header_libraries, - cflags: [ - "-DLOG_TAG=\"VrVirtualTouchpad\"", - "-Wall", - "-Werror", - ], - host_ldlibs: ["-llog"], - name: "virtual_touchpad", - init_rc: ["virtual_touchpad.rc"], - compile_multilib: "64", - stl: "libc++_static", -} - -// Touchpad client library. - -client_src = [ - "VirtualTouchpadClient.cpp", - "DvrVirtualTouchpadClient.cpp", - ":virtualtouchpad_aidl", -] - -client_shared_libs = [ - "libbase", - "libbinder", - "liblog", - "libutils", -] - -cc_library { - srcs: client_src, - shared_libs: client_shared_libs, - header_libs: header_libraries, - cflags: [ - "-DLOG_TAG=\"VirtualTouchpadClient\"", - "-Wall", - "-Werror", - ], - host_ldlibs: ["-llog"], - name: "libvirtualtouchpadclient", - export_include_dirs: ["include"], -} - -filegroup { - name: "virtualtouchpad_aidl", - srcs: ["aidl/android/dvr/IVirtualTouchpadService.aidl"], - path: "aidl", -} diff --git a/services/vr/virtual_touchpad/DvrVirtualTouchpadClient.cpp b/services/vr/virtual_touchpad/DvrVirtualTouchpadClient.cpp deleted file mode 100644 index 3ab77a7132..0000000000 --- a/services/vr/virtual_touchpad/DvrVirtualTouchpadClient.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include "VirtualTouchpadClient.h" -#include "dvr/virtual_touchpad_client.h" - -struct DvrVirtualTouchpad {}; - -#ifdef __cplusplus -extern "C" { -#endif - -namespace { -android::dvr::VirtualTouchpad* FromC(DvrVirtualTouchpad* client) { - return reinterpret_cast<android::dvr::VirtualTouchpad*>(client); -} -} // namespace - -DvrVirtualTouchpad* dvrVirtualTouchpadCreate() { - return reinterpret_cast<DvrVirtualTouchpad*>( - android::dvr::VirtualTouchpadClient::Create().release()); -} - -void dvrVirtualTouchpadDestroy(DvrVirtualTouchpad* client) { - delete FromC(client); -} - -int dvrVirtualTouchpadAttach(DvrVirtualTouchpad* client) { - return FromC(client)->Attach(); -} - -int dvrVirtualTouchpadDetach(DvrVirtualTouchpad* client) { - return FromC(client)->Detach(); -} - -int dvrVirtualTouchpadTouch(DvrVirtualTouchpad* client, int touchpad, float x, - float y, float pressure) { - return FromC(client)->Touch(touchpad, x, y, pressure); -} - -int dvrVirtualTouchpadButtonState(DvrVirtualTouchpad* client, int touchpad, - int buttons) { - return FromC(client)->ButtonState(touchpad, buttons); -} - -int dvrVirtualTouchpadScroll(DvrVirtualTouchpad* client, int touchpad, float x, - float y) { - return FromC(client)->Scroll(touchpad, x, y); -} - -#ifdef __cplusplus -} // extern "C" -#endif diff --git a/services/vr/virtual_touchpad/EvdevInjector.cpp b/services/vr/virtual_touchpad/EvdevInjector.cpp deleted file mode 100644 index 7fad37943a..0000000000 --- a/services/vr/virtual_touchpad/EvdevInjector.cpp +++ /dev/null @@ -1,339 +0,0 @@ -#include "EvdevInjector.h" - -#include <errno.h> -#include <inttypes.h> -#include <linux/input.h> -#include <log/log.h> -#include <string.h> -#include <sys/fcntl.h> -#include <unistd.h> - -namespace android { -namespace dvr { - -int EvdevInjector::UInput::Open() { - errno = 0; - fd_.reset(open("/dev/uinput", O_WRONLY | O_NONBLOCK)); - if (fd_.get() < 0) { - ALOGE("couldn't open uinput (r=%d errno=%d)", fd_.get(), errno); - } - return errno; -} - -int EvdevInjector::UInput::Close() { - errno = 0; - fd_.reset(); - return errno; -} - -int EvdevInjector::UInput::Write(const void* buf, size_t count) { - ALOGV("UInput::Write(%zu, %02X...)", count, *static_cast<const char*>(buf)); - errno = 0; - ssize_t r = write(fd_.get(), buf, count); - if (r != static_cast<ssize_t>(count)) { - ALOGE("write(%zu) failed (r=%zd errno=%d)", count, r, errno); - } - return errno; -} - -int EvdevInjector::UInput::IoctlSetInt(int request, int value) { - ALOGV("UInput::IoctlSetInt(0x%X, 0x%X)", request, value); - errno = 0; - if (const int status = ioctl(fd_.get(), request, value)) { - ALOGE("ioctl(%d, 0x%X, 0x%X) failed (r=%d errno=%d)", fd_.get(), request, - value, status, errno); - } - return errno; -} - -int EvdevInjector::UInput::IoctlVoid(int request) { - ALOGV("UInput::IoctlVoid(0x%X)", request); - errno = 0; - if (const int status = ioctl(fd_.get(), request)) { - ALOGE("ioctl(%d, 0x%X) failed (r=%d errno=%d)", fd_.get(), request, status, - errno); - } - return errno; -} - -void EvdevInjector::Close() { - uinput_->Close(); - state_ = State::CLOSED; -} - -int EvdevInjector::ConfigureBegin(const char* device_name, int16_t bustype, - int16_t vendor, int16_t product, - int16_t version) { - ALOGV("ConfigureBegin %s 0x%04" PRIX16 " 0x%04" PRIX16 " 0x%04" PRIX16 - " 0x%04" PRIX16 "", - device_name, bustype, vendor, product, version); - if (!device_name || strlen(device_name) >= UINPUT_MAX_NAME_SIZE) { - return Error(ERROR_DEVICE_NAME); - } - if (const int status = RequireState(State::NEW)) { - return status; - } - if (!uinput_) { - owned_uinput_.reset(new EvdevInjector::UInput()); - uinput_ = owned_uinput_.get(); - } - if (const int status = uinput_->Open()) { - // Without uinput we're dead in the water. - state_ = State::CLOSED; - return Error(status); - } - state_ = State::CONFIGURING; - // Initialize device setting structure. - memset(&uidev_, 0, sizeof(uidev_)); - strncpy(uidev_.name, device_name, UINPUT_MAX_NAME_SIZE); - uidev_.id.bustype = bustype; - uidev_.id.vendor = vendor; - uidev_.id.product = product; - uidev_.id.version = version; - return 0; -} - -int EvdevInjector::ConfigureInputProperty(int property) { - ALOGV("ConfigureInputProperty %d", property); - if (property < 0 || property >= INPUT_PROP_CNT) { - ALOGE("property 0x%X out of range [0,0x%X)", property, INPUT_PROP_CNT); - return Error(ERROR_PROPERTY_RANGE); - } - if (const int status = RequireState(State::CONFIGURING)) { - return status; - } - if (const int status = uinput_->IoctlSetInt(UI_SET_PROPBIT, property)) { - ALOGE("failed to set property %d", property); - return Error(status); - } - return 0; -} - -int EvdevInjector::ConfigureKey(uint16_t key) { - ALOGV("ConfigureKey 0x%02" PRIX16 "", key); - if (key < 0 || key >= KEY_CNT) { - ALOGE("key 0x%X out of range [0,0x%X)", key, KEY_CNT); - return Error(ERROR_KEY_RANGE); - } - if (const int status = RequireState(State::CONFIGURING)) { - return status; - } - if (const int status = EnableEventType(EV_KEY)) { - return status; - } - if (const int status = uinput_->IoctlSetInt(UI_SET_KEYBIT, key)) { - ALOGE("failed to enable EV_KEY 0x%02" PRIX16 "", key); - return Error(status); - } - return 0; -} - -int EvdevInjector::ConfigureAbs(uint16_t abs_type, int32_t min, int32_t max, - int32_t fuzz, int32_t flat) { - ALOGV("ConfigureAbs 0x%" PRIX16 " %" PRId32 " %" PRId32 " %" PRId32 - " %" PRId32 "", - abs_type, min, max, fuzz, flat); - if (abs_type < 0 || abs_type >= ABS_CNT) { - ALOGE("EV_ABS type 0x%" PRIX16 " out of range [0,0x%X)", abs_type, ABS_CNT); - return Error(ERROR_ABS_RANGE); - } - if (const int status = RequireState(State::CONFIGURING)) { - return status; - } - if (const int status = EnableEventType(EV_ABS)) { - return status; - } - if (const int status = uinput_->IoctlSetInt(UI_SET_ABSBIT, abs_type)) { - ALOGE("failed to enable EV_ABS 0x%" PRIX16 "", abs_type); - return Error(status); - } - uidev_.absmin[abs_type] = min; - uidev_.absmax[abs_type] = max; - uidev_.absfuzz[abs_type] = fuzz; - uidev_.absflat[abs_type] = flat; - return 0; -} - -int EvdevInjector::ConfigureMultiTouchXY(int x0, int y0, int x1, int y1) { - if (const int status = ConfigureAbs(ABS_MT_POSITION_X, x0, x1, 0, 0)) { - return status; - } - if (const int status = ConfigureAbs(ABS_MT_POSITION_Y, y0, y1, 0, 0)) { - return status; - } - return 0; -} - -int EvdevInjector::ConfigureAbsSlots(int slots) { - return ConfigureAbs(ABS_MT_SLOT, 0, slots, 0, 0); -} - -int EvdevInjector::ConfigureRel(uint16_t rel_type) { - ALOGV("ConfigureRel 0x%" PRIX16 "", rel_type); - if (rel_type < 0 || rel_type >= REL_CNT) { - ALOGE("EV_REL type 0x%" PRIX16 " out of range [0,0x%X)", rel_type, REL_CNT); - return Error(ERROR_REL_RANGE); - } - if (const int status = RequireState(State::CONFIGURING)) { - return status; - } - if (const int status = EnableEventType(EV_REL)) { - return status; - } - if (const int status = uinput_->IoctlSetInt(UI_SET_RELBIT, rel_type)) { - ALOGE("failed to enable EV_REL 0x%" PRIX16 "", rel_type); - return Error(status); - } - return 0; -} - -int EvdevInjector::ConfigureEnd() { - ALOGV("ConfigureEnd:"); - ALOGV(" name=\"%s\"", uidev_.name); - ALOGV(" id.bustype=0x%04" PRIX16, uidev_.id.bustype); - ALOGV(" id.vendor=0x%04" PRIX16, uidev_.id.vendor); - ALOGV(" id.product=0x%04" PRIX16, uidev_.id.product); - ALOGV(" id.version=0x%04" PRIX16, uidev_.id.version); - ALOGV(" ff_effects_max=%" PRIu32, uidev_.ff_effects_max); - for (int i = 0; i < ABS_CNT; ++i) { - if (uidev_.absmin[i]) { - ALOGV(" absmin[%d]=%" PRId32, i, uidev_.absmin[i]); - } - if (uidev_.absmax[i]) { - ALOGV(" absmax[%d]=%" PRId32, i, uidev_.absmax[i]); - } - if (uidev_.absfuzz[i]) { - ALOGV(" absfuzz[%d]=%" PRId32, i, uidev_.absfuzz[i]); - } - if (uidev_.absflat[i]) { - ALOGV(" absflat[%d]=%" PRId32, i, uidev_.absflat[i]); - } - } - - if (const int status = RequireState(State::CONFIGURING)) { - return status; - } - // Write out device settings. - if (const int status = uinput_->Write(&uidev_, sizeof uidev_)) { - ALOGE("failed to write device settings"); - return Error(status); - } - // Create device node. - if (const int status = uinput_->IoctlVoid(UI_DEV_CREATE)) { - ALOGE("failed to create device node"); - return Error(status); - } - state_ = State::READY; - return 0; -} - -int EvdevInjector::Send(uint16_t type, uint16_t code, int32_t value) { - ALOGV("Send(0x%" PRIX16 ", 0x%" PRIX16 ", 0x%" PRIX32 ")", type, code, value); - if (const int status = RequireState(State::READY)) { - return status; - } - struct input_event event; - memset(&event, 0, sizeof(event)); - event.type = type; - event.code = code; - event.value = value; - if (const int status = uinput_->Write(&event, sizeof(event))) { - ALOGE("failed to write event 0x%" PRIX16 ", 0x%" PRIX16 ", 0x%" PRIX32, - type, code, value); - return Error(status); - } - return 0; -} - -int EvdevInjector::SendSynReport() { return Send(EV_SYN, SYN_REPORT, 0); } - -int EvdevInjector::SendKey(uint16_t code, int32_t value) { - return Send(EV_KEY, code, value); -} - -int EvdevInjector::SendAbs(uint16_t code, int32_t value) { - return Send(EV_ABS, code, value); -} - -int EvdevInjector::SendRel(uint16_t code, int32_t value) { - return Send(EV_REL, code, value); -} - -int EvdevInjector::SendMultiTouchSlot(int32_t slot) { - if (latest_slot_ != slot) { - if (const int status = SendAbs(ABS_MT_SLOT, slot)) { - return status; - } - latest_slot_ = slot; - } - return 0; -} - -int EvdevInjector::SendMultiTouchXY(int32_t slot, int32_t id, int32_t x, - int32_t y) { - if (const int status = SendMultiTouchSlot(slot)) { - return status; - } - if (const int status = SendAbs(ABS_MT_TRACKING_ID, id)) { - return status; - } - if (const int status = SendAbs(ABS_MT_POSITION_X, x)) { - return status; - } - if (const int status = SendAbs(ABS_MT_POSITION_Y, y)) { - return status; - } - return 0; -} - -int EvdevInjector::SendMultiTouchLift(int32_t slot) { - if (const int status = SendMultiTouchSlot(slot)) { - return status; - } - if (const int status = SendAbs(ABS_MT_TRACKING_ID, -1)) { - return status; - } - return 0; -} - -int EvdevInjector::Error(int code) { - if (!error_) { - error_ = code; - } - return code; -} - -int EvdevInjector::RequireState(State required_state) { - if (error_) { - return error_; - } - if (state_ != required_state) { - ALOGE("in state %d but require state %d", static_cast<int>(state_), - static_cast<int>(required_state)); - return Error(ERROR_SEQUENCING); - } - return 0; -} - -int EvdevInjector::EnableEventType(uint16_t type) { - if (const int status = RequireState(State::CONFIGURING)) { - return status; - } - if (enabled_event_types_.count(type) > 0) { - return 0; - } - if (const int status = uinput_->IoctlSetInt(UI_SET_EVBIT, type)) { - ALOGE("failed to enable event type 0x%X", type); - return Error(status); - } - enabled_event_types_.insert(type); - return 0; -} - -void EvdevInjector::dumpInternal(String8& result) { - result.appendFormat("injector_state = %d\n", static_cast<int>(state_)); - result.appendFormat("injector_error = %d\n", error_); -} - -} // namespace dvr -} // namespace android diff --git a/services/vr/virtual_touchpad/EvdevInjector.h b/services/vr/virtual_touchpad/EvdevInjector.h deleted file mode 100644 index e87c959418..0000000000 --- a/services/vr/virtual_touchpad/EvdevInjector.h +++ /dev/null @@ -1,148 +0,0 @@ -#ifndef ANDROID_DVR_EVDEV_INJECTOR_H -#define ANDROID_DVR_EVDEV_INJECTOR_H - -#include <android-base/unique_fd.h> -#include <linux/uinput.h> -#include <utils/String8.h> - -#include <cstdint> -#include <memory> -#include <unordered_set> - -namespace android { -namespace dvr { - -// Simulated evdev input device. -// -class EvdevInjector { - public: - // EvdevInjector-specific error codes are negative integers; other non-zero - // values returned from public routines are |errno| codes from underlying I/O. - // EvdevInjector maintains a 'sticky' error state, similar to |errno|, so that - // a caller can perform a sequence of operations and check for errors at the - // end using |GetError()|. In general, the first such error will be recorded - // and will suppress effects of further device operations until |ResetError()| - // is called. - // - enum : int { - ERROR_DEVICE_NAME = -1, // Invalid device name. - ERROR_PROPERTY_RANGE = -2, // |INPUT_PROP_*| code out of range. - ERROR_KEY_RANGE = -3, // |KEY_*|/|BTN_*| code out of range. - ERROR_ABS_RANGE = -4, // |ABS_*| code out of range. - ERROR_SEQUENCING = -5, // Configure/Send out of order. - ERROR_REL_RANGE = -6, // |REL_*| code out of range. - }; - - // Key event |value| is not defined in <linux/input.h>. - enum : int32_t { KEY_RELEASE = 0, KEY_PRESS = 1, KEY_REPEAT = 2 }; - - // UInput provides a shim to intercept /dev/uinput operations - // just above the system call level, for testing. - // - class UInput { - public: - UInput() {} - virtual ~UInput() {} - virtual int Open(); - virtual int Close(); - virtual int Write(const void* buf, size_t count); - virtual int IoctlVoid(int request); - virtual int IoctlSetInt(int request, int value); - - private: - base::unique_fd fd_; - }; - - EvdevInjector() {} - ~EvdevInjector() { Close(); } - void Close(); - - int GetError() const { return error_; } - void ResetError() { error_ = 0; } - - // Configuration must be performed before sending any events. - // |ConfigureBegin()| must be called first, and |ConfigureEnd()| last, - // with zero or more other |Configure...()| calls in between in any order. - - // Configure the basic evdev device properties; must be called first. - int ConfigureBegin(const char* device_name, int16_t bustype, int16_t vendor, - int16_t product, int16_t version); - - // Configure an optional input device property. - // @param property One of the |INPUT_PROP_*| constants from <linux/input.h>. - int ConfigureInputProperty(int property); - - // Configure an input key. - // @param key One of the |KEY_*| or |BTN_*| constants from <linux/input.h>. - int ConfigureKey(uint16_t key); - - // Configure an absolute axis. - // @param abs_type One of the |KEY_*| or |BTN_*| constants from - // <linux/input.h>. - int ConfigureAbs(uint16_t abs_type, int32_t min, int32_t max, int32_t fuzz, - int32_t flat); - - // Configure the number of multitouch slots. - int ConfigureAbsSlots(int slots); - - // Configure multitouch coordinate range. - int ConfigureMultiTouchXY(int32_t x0, int32_t y0, int32_t x1, int32_t y1); - - // Configure a relative axis. - // @param rel_type One of the |REL_*| constants from <linux/input.h>. - int ConfigureRel(uint16_t rel_type); - - // Complete configuration and create the input device. - int ConfigureEnd(); - - // Send various events. - // - int Send(uint16_t type, uint16_t code, int32_t value); - int SendSynReport(); - int SendKey(uint16_t code, int32_t value); - int SendAbs(uint16_t code, int32_t value); - int SendRel(uint16_t code, int32_t value); - int SendMultiTouchSlot(int32_t slot); - int SendMultiTouchXY(int32_t slot, int32_t id, int32_t x, int32_t y); - int SendMultiTouchLift(int32_t slot); - - void dumpInternal(String8& result); - - protected: - // Must be called only between construction and ConfigureBegin(). - inline void SetUInputForTesting(UInput* uinput) { uinput_ = uinput; } - // Caller must not retain pointer longer than EvdevInjector. - inline const uinput_user_dev* GetUiDevForTesting() const { return &uidev_; } - - private: - // Phase to enforce that configuration is complete before events are sent. - enum class State { NEW, CONFIGURING, READY, CLOSED }; - - // Sets |error_| if it is not already set; returns |code|. - int Error(int code); - - // Returns a nonzero error if the injector is not in the required |state|. - int RequireState(State state); - - // Configures an event type if necessary. - // @param type One of the |EV_*| constants from <linux/input.h>. - int EnableEventType(uint16_t type); - - // Active pointer to owned or testing UInput. - UInput* uinput_ = nullptr; - std::unique_ptr<UInput> owned_uinput_; - - State state_ = State::NEW; - int error_ = 0; - uinput_user_dev uidev_; - std::unordered_set<uint16_t> enabled_event_types_; - int32_t latest_slot_ = -1; - - EvdevInjector(const EvdevInjector&) = delete; - void operator=(const EvdevInjector&) = delete; -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_EVDEV_INJECTOR_H diff --git a/services/vr/virtual_touchpad/VirtualTouchpadClient.cpp b/services/vr/virtual_touchpad/VirtualTouchpadClient.cpp deleted file mode 100644 index 00e4ce61f8..0000000000 --- a/services/vr/virtual_touchpad/VirtualTouchpadClient.cpp +++ /dev/null @@ -1,87 +0,0 @@ -#include "VirtualTouchpadClient.h" - -#include <android/dvr/IVirtualTouchpadService.h> -#include <binder/IServiceManager.h> - -namespace android { -namespace dvr { - -namespace { - -class VirtualTouchpadClientImpl : public VirtualTouchpadClient { - public: - VirtualTouchpadClientImpl() {} - ~VirtualTouchpadClientImpl() override { - if (service_ != nullptr) { - Detach(); - } - } - - status_t Attach() { - if (service_ != nullptr) { - return ALREADY_EXISTS; - } - sp<IServiceManager> sm = defaultServiceManager(); - if (sm == nullptr) { - ALOGE("no service manager"); - return NO_INIT; - } - sp<IVirtualTouchpadService> service = - interface_cast<IVirtualTouchpadService>( - sm->getService(IVirtualTouchpadService::SERVICE_NAME())); - if (service == nullptr) { - ALOGE("failed to get service"); - return NAME_NOT_FOUND; - } - service_ = service; - return service_->attach().transactionError(); - } - - status_t Detach() { - if (service_ == nullptr) { - return NO_INIT; - } - status_t status = service_->detach().transactionError(); - service_ = nullptr; - return status; - } - - status_t Touch(int touchpad, float x, float y, float pressure) override { - if (service_ == nullptr) { - return NO_INIT; - } - return service_->touch(touchpad, x, y, pressure).transactionError(); - } - - status_t ButtonState(int touchpad, int buttons) override { - if (service_ == nullptr) { - return NO_INIT; - } - return service_->buttonState(touchpad, buttons).transactionError(); - } - - status_t Scroll(int touchpad, float x, float y) override { - if (service_ == nullptr) { - return NO_INIT; - } - return service_->scroll(touchpad, x, y).transactionError(); - } - - void dumpInternal(String8& result) override { - result.append("[virtual touchpad]\n"); - result.appendFormat("connected = %s\n\n", - service_ != nullptr ? "true" : "false"); - } - - private: - sp<IVirtualTouchpadService> service_; -}; - -} // anonymous namespace - -std::unique_ptr<VirtualTouchpad> VirtualTouchpadClient::Create() { - return std::unique_ptr<VirtualTouchpad>(new VirtualTouchpadClientImpl()); -} - -} // namespace dvr -} // namespace android diff --git a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp deleted file mode 100644 index bcfdad3ef9..0000000000 --- a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp +++ /dev/null @@ -1,218 +0,0 @@ -#include "VirtualTouchpadEvdev.h" - -#include <android/input.h> -#include <inttypes.h> -#include <linux/input.h> -#include <log/log.h> - -// References: -// [0] Multi-touch (MT) Protocol, -// https://www.kernel.org/doc/Documentation/input/multi-touch-protocol.txt - -namespace android { -namespace dvr { - -namespace { - -// Virtual evdev device properties. The name is arbitrary, but Android can -// use it to look up device configuration, so it must be unique. Vendor and -// product values must be 0 to indicate an internal device and prevent a -// similar lookup that could conflict with a physical device. -static const char* const kDeviceNameFormat = "vr-virtual-touchpad-%d"; -static constexpr int16_t kDeviceBusType = BUS_VIRTUAL; -static constexpr int16_t kDeviceVendor = 0; -static constexpr int16_t kDeviceProduct = 0; -static constexpr int16_t kDeviceVersion = 0x0001; - -static constexpr int32_t kWidth = 0x10000; -static constexpr int32_t kHeight = 0x10000; -static constexpr int32_t kSlots = 2; - -static constexpr float kScrollScale = 100.0f; - -int32_t scale_relative_scroll(float x) { - return kScrollScale * x; -} - -} // anonymous namespace - -std::unique_ptr<VirtualTouchpad> VirtualTouchpadEvdev::Create() { - std::unique_ptr<VirtualTouchpadEvdev> touchpad(new VirtualTouchpadEvdev()); - touchpad->Reset(); - return touchpad; -} - -void VirtualTouchpadEvdev::Reset() { - for (auto& touchpad : touchpad_) { - if (touchpad.injector) { - touchpad.injector->Close(); - } - touchpad.injector = nullptr; - touchpad.owned_injector.reset(); - touchpad.last_device_x = INT32_MIN; - touchpad.last_device_y = INT32_MIN; - touchpad.touches = 0; - touchpad.last_motion_event_buttons = 0; - } -} - -status_t VirtualTouchpadEvdev::Attach() { - status_t status = OK; - for (int i = 0; i < kTouchpads; ++i) { - Touchpad& touchpad = touchpad_[i]; - if (!touchpad.injector) { - touchpad.owned_injector.reset(new EvdevInjector()); - touchpad.injector = touchpad.owned_injector.get(); - } - String8 DeviceName; - DeviceName.appendFormat(kDeviceNameFormat, i); - touchpad.injector->ConfigureBegin(DeviceName, kDeviceBusType, - kDeviceVendor, kDeviceProduct, - kDeviceVersion); - touchpad.injector->ConfigureInputProperty(INPUT_PROP_DIRECT); - touchpad.injector->ConfigureMultiTouchXY(0, 0, kWidth - 1, kHeight - 1); - touchpad.injector->ConfigureAbsSlots(kSlots); - touchpad.injector->ConfigureRel(REL_WHEEL); - touchpad.injector->ConfigureRel(REL_HWHEEL); - touchpad.injector->ConfigureKey(BTN_TOUCH); - touchpad.injector->ConfigureKey(BTN_BACK); - touchpad.injector->ConfigureEnd(); - if (const status_t configuration_status = touchpad.injector->GetError()) { - status = configuration_status; - } - } - return status; -} - -status_t VirtualTouchpadEvdev::Detach() { - Reset(); - return OK; -} - -int VirtualTouchpadEvdev::Touch(int touchpad_id, float x, float y, - float pressure) { - if (touchpad_id < 0 || touchpad_id >= kTouchpads) { - return EINVAL; - } - int32_t device_x = x * kWidth; - int32_t device_y = y * kHeight; - Touchpad& touchpad = touchpad_[touchpad_id]; - touchpad.touches = ((touchpad.touches & 1) << 1) | (pressure > 0); - ALOGV("(%f,%f) %f -> (%" PRId32 ",%" PRId32 ") %d", x, y, pressure, device_x, - device_y, touchpad.touches); - - if (!touchpad.injector) { - return EvdevInjector::ERROR_SEQUENCING; - } - touchpad.injector->ResetError(); - switch (touchpad.touches) { - case 0b00: // Hover continues. - if (device_x != touchpad.last_device_x || - device_y != touchpad.last_device_y) { - touchpad.injector->SendMultiTouchXY(0, 0, device_x, device_y); - touchpad.injector->SendSynReport(); - } - break; - case 0b01: // Touch begins. - // Press. - touchpad.injector->SendMultiTouchXY(0, 0, device_x, device_y); - touchpad.injector->SendKey(BTN_TOUCH, EvdevInjector::KEY_PRESS); - touchpad.injector->SendSynReport(); - break; - case 0b10: // Touch ends. - touchpad.injector->SendKey(BTN_TOUCH, EvdevInjector::KEY_RELEASE); - touchpad.injector->SendMultiTouchLift(0); - touchpad.injector->SendSynReport(); - break; - case 0b11: // Touch continues. - if (device_x != touchpad.last_device_x || - device_y != touchpad.last_device_y) { - touchpad.injector->SendMultiTouchXY(0, 0, device_x, device_y); - touchpad.injector->SendSynReport(); - } - break; - } - touchpad.last_device_x = device_x; - touchpad.last_device_y = device_y; - - return touchpad.injector->GetError(); -} - -int VirtualTouchpadEvdev::ButtonState(int touchpad_id, int buttons) { - if (touchpad_id < 0 || touchpad_id >= kTouchpads) { - return EINVAL; - } - Touchpad& touchpad = touchpad_[touchpad_id]; - const int changes = touchpad.last_motion_event_buttons ^ buttons; - if (!changes) { - return 0; - } - if (buttons & ~AMOTION_EVENT_BUTTON_BACK) { - return ENOTSUP; - } - ALOGV("change %X from %X to %X", changes, touchpad.last_motion_event_buttons, - buttons); - - if (!touchpad.injector) { - return EvdevInjector::ERROR_SEQUENCING; - } - touchpad.injector->ResetError(); - if (changes & AMOTION_EVENT_BUTTON_BACK) { - touchpad.injector->SendKey(BTN_BACK, (buttons & AMOTION_EVENT_BUTTON_BACK) - ? EvdevInjector::KEY_PRESS - : EvdevInjector::KEY_RELEASE); - touchpad.injector->SendSynReport(); - } - touchpad.last_motion_event_buttons = buttons; - return touchpad.injector->GetError(); -} - -int VirtualTouchpadEvdev::Scroll(int touchpad_id, float x, float y) { - if (touchpad_id < 0 || touchpad_id >= kTouchpads) { - return EINVAL; - } - if ((x < -1.0f) || (x > 1.0f) || (y < -1.0f) || (y > 1.0f)) { - return EINVAL; - } - Touchpad& touchpad = touchpad_[touchpad_id]; - if (!touchpad.injector) { - return EvdevInjector::ERROR_SEQUENCING; - } - touchpad.injector->ResetError(); - const int32_t scaled_x = scale_relative_scroll(x); - const int32_t scaled_y = scale_relative_scroll(y); - ALOGV("(%f,%f) -> (%" PRId32 ",%" PRId32 ")", x, y, scaled_x, scaled_y); - if (scaled_x) { - touchpad.injector->SendRel(REL_HWHEEL, scaled_x); - } - if (scaled_y) { - touchpad.injector->SendRel(REL_WHEEL, scaled_y); - } - if (scaled_x || scaled_y) { - touchpad.injector->SendSynReport(); - } - return touchpad.injector->GetError(); -} - -void VirtualTouchpadEvdev::dumpInternal(String8& result) { - for (int i = 0; i < kTouchpads; ++i) { - const auto& touchpad = touchpad_[i]; - result.appendFormat("[virtual touchpad %d]\n", i); - if (!touchpad.injector) { - result.append("injector = none\n"); - return; - } - result.appendFormat("injector = %s\n", - touchpad.owned_injector ? "normal" : "test"); - result.appendFormat("touches = %d\n", touchpad.touches); - result.appendFormat("last_position = (%" PRId32 ", %" PRId32 ")\n", - touchpad.last_device_x, touchpad.last_device_y); - result.appendFormat("last_buttons = 0x%" PRIX32 "\n", - touchpad.last_motion_event_buttons); - touchpad.injector->dumpInternal(result); - result.append("\n"); - } -} - -} // namespace dvr -} // namespace android diff --git a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.h b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.h deleted file mode 100644 index c9578bf001..0000000000 --- a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef ANDROID_DVR_VIRTUAL_TOUCHPAD_EVDEV_H -#define ANDROID_DVR_VIRTUAL_TOUCHPAD_EVDEV_H - -#include "EvdevInjector.h" -#include "VirtualTouchpad.h" - -namespace android { -namespace dvr { - -class EvdevInjector; - -// VirtualTouchpadEvdev implements a VirtualTouchpad by injecting evdev events. -// -class VirtualTouchpadEvdev : public VirtualTouchpad { - public: - static std::unique_ptr<VirtualTouchpad> Create(); - ~VirtualTouchpadEvdev() override {} - - // VirtualTouchpad implementation: - status_t Attach() override; - status_t Detach() override; - status_t Touch(int touchpad, float x, float y, float pressure) override; - status_t ButtonState(int touchpad, int buttons) override; - status_t Scroll(int touchpad, float x, float y) override; - void dumpInternal(String8& result) override; - - protected: - static constexpr int kTouchpads = 2; - - VirtualTouchpadEvdev() {} - void Reset(); - - // Must be called only between construction (or Detach()) and Attach(). - inline void SetEvdevInjectorForTesting(int touchpad, - EvdevInjector* injector) { - touchpad_[touchpad].injector = injector; - } - - private: - // Per-touchpad state. - struct Touchpad { - // Except for testing, the |EvdevInjector| used to inject evdev events. - std::unique_ptr<EvdevInjector> owned_injector; - - // Active pointer to |owned_injector_| or to a testing injector. - EvdevInjector* injector = nullptr; - - // Previous (x, y) position in device space, to suppress redundant events. - int32_t last_device_x; - int32_t last_device_y; - - // Records current touch state (0=up 1=down) in bit 0, and previous state - // in bit 1, to track transitions. - int touches; - - // Previous injected button state, to detect changes. - int32_t last_motion_event_buttons; - }; - Touchpad touchpad_[kTouchpads]; - - VirtualTouchpadEvdev(const VirtualTouchpadEvdev&) = delete; - void operator=(const VirtualTouchpadEvdev&) = delete; -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_VIRTUAL_TOUCHPAD_EVDEV_H diff --git a/services/vr/virtual_touchpad/VirtualTouchpadService.cpp b/services/vr/virtual_touchpad/VirtualTouchpadService.cpp deleted file mode 100644 index d0a9da1ff5..0000000000 --- a/services/vr/virtual_touchpad/VirtualTouchpadService.cpp +++ /dev/null @@ -1,145 +0,0 @@ -#include "VirtualTouchpadService.h" - -#include <inttypes.h> - -#include <binder/IPCThreadState.h> -#include <binder/PermissionCache.h> -#include <binder/Status.h> -#include <cutils/log.h> -#include <linux/input.h> -#include <private/android_filesystem_config.h> -#include <utils/Errors.h> - -namespace android { -namespace dvr { - -namespace { -const String16 kDumpPermission("android.permission.DUMP"); -const String16 kTouchPermission("android.permission.RESTRICTED_VR_ACCESS"); -} // anonymous namespace - -VirtualTouchpadService::~VirtualTouchpadService() { - if (client_pid_) { - client_pid_ = 0; - touchpad_->Detach(); - } -} - -binder::Status VirtualTouchpadService::attach() { - pid_t pid; - if (!CheckTouchPermission(&pid)) { - return binder::Status::fromStatusT(PERMISSION_DENIED); - } - if (client_pid_ == pid) { - // The same client has called attach() twice with no intervening detach(). - // This indicates a problem with the client, so return an error. - // However, since the client is already attached, any touchpad actions - // it takes will still work. - ALOGE("pid=%ld attached twice", static_cast<long>(pid)); - return binder::Status::fromStatusT(ALREADY_EXISTS); - } - if (client_pid_ != 0) { - // Attach while another client is attached. This can happen if the client - // dies without cleaning up after itself, so move ownership to the current - // caller. If two actual clients have connected, the problem will be - // reported when the previous client performs any touchpad action. - ALOGE("pid=%ld replaces %ld", static_cast<long>(pid), - static_cast<long>(client_pid_)); - client_pid_ = pid; - return binder::Status::ok(); - } - client_pid_ = pid; - if (const status_t error = touchpad_->Attach()) { - return binder::Status::fromStatusT(error); - } - return binder::Status::ok(); -} - -binder::Status VirtualTouchpadService::detach() { - if (!CheckPermissions()) { - return binder::Status::fromStatusT(PERMISSION_DENIED); - } - client_pid_ = 0; - if (const status_t error = touchpad_->Detach()) { - return binder::Status::fromStatusT(error); - } - return binder::Status::ok(); -} - -binder::Status VirtualTouchpadService::touch(int touchpad, float x, float y, - float pressure) { - if (!CheckPermissions()) { - return binder::Status::fromStatusT(PERMISSION_DENIED); - } - if (const status_t error = touchpad_->Touch(touchpad, x, y, pressure)) { - return binder::Status::fromStatusT(error); - } - return binder::Status::ok(); -} - -binder::Status VirtualTouchpadService::buttonState(int touchpad, int buttons) { - if (!CheckPermissions()) { - return binder::Status::fromStatusT(PERMISSION_DENIED); - } - if (const status_t error = touchpad_->ButtonState(touchpad, buttons)) { - return binder::Status::fromStatusT(error); - } - return binder::Status::ok(); -} - -binder::Status VirtualTouchpadService::scroll(int touchpad, float x, float y) { - if (!CheckPermissions()) { - return binder::Status::fromStatusT(PERMISSION_DENIED); - } - if (const status_t error = touchpad_->Scroll(touchpad, x, y)) { - return binder::Status::fromStatusT(error); - } - return binder::Status::ok(); -} - -status_t VirtualTouchpadService::dump( - int fd, const Vector<String16>& args[[gnu::unused]]) { - String8 result; - const android::IPCThreadState* ipc = android::IPCThreadState::self(); - const pid_t pid = ipc->getCallingPid(); - const uid_t uid = ipc->getCallingUid(); - if ((uid != AID_SHELL) && - !PermissionCache::checkPermission(kDumpPermission, pid, uid)) { - result.appendFormat("Permission denial: can't dump " LOG_TAG - " from pid=%ld, uid=%ld\n", - static_cast<long>(pid), static_cast<long>(uid)); - } else { - result.appendFormat("[service]\nclient_pid = %ld\n\n", - static_cast<long>(client_pid_)); - touchpad_->dumpInternal(result); - } - write(fd, result.c_str(), result.size()); - return OK; -} - -bool VirtualTouchpadService::CheckPermissions() { - pid_t pid; - if (!CheckTouchPermission(&pid)) { - return false; - } - if (client_pid_ != pid) { - ALOGE("pid=%ld is not owner", static_cast<long>(pid)); - return false; - } - return true; -} - -bool VirtualTouchpadService::CheckTouchPermission(pid_t* out_pid) { - const android::IPCThreadState* ipc = android::IPCThreadState::self(); - *out_pid = ipc->getCallingPid(); - const uid_t uid = ipc->getCallingUid(); - const bool permission = PermissionCache::checkPermission(kTouchPermission, *out_pid, uid); - if (!permission) { - ALOGE("permission denied to pid=%ld uid=%ld", static_cast<long>(*out_pid), - static_cast<long>(uid)); - } - return permission; -} - -} // namespace dvr -} // namespace android diff --git a/services/vr/virtual_touchpad/VirtualTouchpadService.h b/services/vr/virtual_touchpad/VirtualTouchpadService.h deleted file mode 100644 index 2c88aecba0..0000000000 --- a/services/vr/virtual_touchpad/VirtualTouchpadService.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef ANDROID_DVR_VIRTUAL_TOUCHPAD_SERVICE_H -#define ANDROID_DVR_VIRTUAL_TOUCHPAD_SERVICE_H - -#include <android/dvr/BnVirtualTouchpadService.h> - -#include "VirtualTouchpad.h" - -namespace android { -namespace dvr { - -// VirtualTouchpadService implements the service side of -// the Binder interface defined in VirtualTouchpadService.aidl. -// -class VirtualTouchpadService : public BnVirtualTouchpadService { - public: - explicit VirtualTouchpadService(std::unique_ptr<VirtualTouchpad> touchpad) - : touchpad_(std::move(touchpad)), client_pid_(0) {} - ~VirtualTouchpadService() override; - - protected: - // Implements IVirtualTouchpadService. - binder::Status attach() override; - binder::Status detach() override; - binder::Status touch(int touchpad, float x, float y, float pressure) override; - binder::Status buttonState(int touchpad, int buttons) override; - binder::Status scroll(int touchpad, float x, float y) override; - - // Implements BBinder::dump(). - status_t dump(int fd, const Vector<String16>& args) override; - - private: - bool CheckPermissions(); - bool CheckTouchPermission(pid_t* out_pid); - - std::unique_ptr<VirtualTouchpad> touchpad_; - - // Only one client at a time can use the virtual touchpad. - pid_t client_pid_; - - VirtualTouchpadService(const VirtualTouchpadService&) = delete; - void operator=(const VirtualTouchpadService&) = delete; -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_VIRTUAL_TOUCHPAD_SERVICE_H diff --git a/services/vr/virtual_touchpad/aidl/android/dvr/IVirtualTouchpadService.aidl b/services/vr/virtual_touchpad/aidl/android/dvr/IVirtualTouchpadService.aidl deleted file mode 100644 index 89aa44a722..0000000000 --- a/services/vr/virtual_touchpad/aidl/android/dvr/IVirtualTouchpadService.aidl +++ /dev/null @@ -1,48 +0,0 @@ -package android.dvr; - -/** @hide */ -interface IVirtualTouchpadService -{ - const String SERVICE_NAME = "virtual_touchpad"; - - /** - * Initialize the virtual touchpad. - */ - void attach() = 0; - - /** - * Shut down the virtual touchpad. - */ - void detach() = 1; - - /** - * Generate a simulated touch event. - * - * @param touchpad Selects touchpad. - * @param x Horizontal touch position. - * @param y Vertical touch position. - * @param pressure Touch pressure; use 0.0 for no touch (lift or hover). - * - * Position values in the range [0.0, 1.0) map to the screen. - */ - void touch(int touchpad, float x, float y, float pressure) = 2; - - /** - * Generate a simulated touchpad button state event. - * - * @param touchpad Selects touchpad. - * @param buttons A union of MotionEvent BUTTON_* values. - */ - void buttonState(int touchpad, int buttons) = 3; - - /** - * Generate a simulated scroll event. - * - * @param touchpad Selects touchpad. - * @param x Horizontal scroll increment. - * @param y Vertical scroll increment. - * - * Scroll values are in the range [-1.0, 1.0]. - */ - void scroll(int touchpad, float x, float y) = 4; -} diff --git a/services/vr/virtual_touchpad/idc/vr-virtual-touchpad-0.idc b/services/vr/virtual_touchpad/idc/vr-virtual-touchpad-0.idc deleted file mode 100644 index 205e8b901f..0000000000 --- a/services/vr/virtual_touchpad/idc/vr-virtual-touchpad-0.idc +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright (C) 2017 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# -# Virtual touchpad for the primary display -device.internal = 1 - -touch.deviceType = touchScreen - -# Have input flinger treat injected scroll events like a G1 ball -# rather than the default mouse wheel, because the latter requires -# a visible pointer for targeting. -device.type = rotaryEncoder -device.res = 1.0e+2 -device.scalingFactor = 1.0e-2 diff --git a/services/vr/virtual_touchpad/idc/vr-virtual-touchpad-1.idc b/services/vr/virtual_touchpad/idc/vr-virtual-touchpad-1.idc deleted file mode 100644 index d9714e0364..0000000000 --- a/services/vr/virtual_touchpad/idc/vr-virtual-touchpad-1.idc +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright (C) 2017 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# -# Virtual touchpad for the VR virtual display -device.internal = 1 - -touch.deviceType = touchScreen - -# Have input flinger treat injected scroll events like a G1 ball -# rather than the default mouse wheel, because the latter requires -# a visible pointer for targeting. -device.type = rotaryEncoder -device.res = 1.0e+2 -device.scalingFactor = 1.0e-2 - -# This displayID matches the unique ID of the virtual display created for VR. -# This will indicate to input flinger than it should link this input device -# with the virtual display. -touch.displayId = virtual:android:277f1a09-b88d-4d1e-8716-796f114d080b diff --git a/services/vr/virtual_touchpad/include/VirtualTouchpad.h b/services/vr/virtual_touchpad/include/VirtualTouchpad.h deleted file mode 100644 index 99b72fc0d0..0000000000 --- a/services/vr/virtual_touchpad/include/VirtualTouchpad.h +++ /dev/null @@ -1,88 +0,0 @@ -#ifndef ANDROID_DVR_VIRTUAL_TOUCHPAD_INTERFACE_H -#define ANDROID_DVR_VIRTUAL_TOUCHPAD_INTERFACE_H - -#include "dvr/virtual_touchpad_client.h" - -#include <memory> -#include <utils/Errors.h> -#include <utils/String8.h> - -namespace android { -namespace dvr { - -// Provides a virtual touchpad for injecting events into the input system. -// -class VirtualTouchpad { - public: - enum : int { - PRIMARY = DVR_VIRTUAL_TOUCHPAD_PRIMARY, - VIRTUAL = DVR_VIRTUAL_TOUCHPAD_VIRTUAL, - }; - - virtual ~VirtualTouchpad() {} - - // Create a virtual touchpad. - // Implementations should provide this, and hide their constructors. - // For the user, switching implementations should be as simple as changing - // the class whose |Create()| is called. - // Implementations should be minimial; major resource allocation should - // be performed in Attach(). - static std::unique_ptr<VirtualTouchpad> Create() { - return nullptr; - } - - // Initialize a virtual touchpad. - virtual status_t Attach() = 0; - - // Shut down a virtual touchpad. - virtual status_t Detach() = 0; - - // Generate a simulated touch event. - // - // @param touchpad Touchpad selector index. - // @param x Horizontal touch position. - // @param y Vertical touch position. - // Values must be in the range [0.0, 1.0). - // @param pressure Touch pressure. - // Positive values represent contact; use 1.0f if contact - // is binary. Use 0.0f for no contact. - // @returns OK on success. - // - virtual status_t Touch(int touchpad, float x, float y, float pressure) = 0; - - // Generate a simulated touchpad button state. - // - // @param touchpad Touchpad selector index. - // @param buttons A union of MotionEvent BUTTON_* values. - // @returns OK on success. - // - // Currently only BUTTON_BACK is supported, as the implementation - // restricts itself to operations actually required by VrWindowManager. - // - virtual status_t ButtonState(int touchpad, int buttons) = 0; - - // Generate a simulated scroll event. - // - // @param touchpad Touchpad selector index. - // @param x Horizontal scroll increment. - // @param y Vertical scroll increment. - // Values must be in the range [-1.0, 1.0]. - // @returns OK on success. - // - virtual status_t Scroll(int touchpad, float x, float y) = 0; - - // Report state for 'dumpsys'. - virtual void dumpInternal(String8& result) = 0; - - protected: - VirtualTouchpad() {} - - private: - VirtualTouchpad(const VirtualTouchpad&) = delete; - void operator=(const VirtualTouchpad&) = delete; -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_VIRTUAL_TOUCHPAD_INTERFACE_H diff --git a/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h b/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h deleted file mode 100644 index 268e4bde73..0000000000 --- a/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef ANDROID_DVR_VIRTUAL_TOUCHPAD_CLIENT_H -#define ANDROID_DVR_VIRTUAL_TOUCHPAD_CLIENT_H - -#include "VirtualTouchpad.h" - -namespace android { -namespace dvr { - -// VirtualTouchpadClient implements a VirtualTouchpad by connecting to -// a VirtualTouchpadService over Binder. -// -class VirtualTouchpadClient : public VirtualTouchpad { - public: - // VirtualTouchpad implementation: - static std::unique_ptr<VirtualTouchpad> Create(); - - protected: - VirtualTouchpadClient() {} - ~VirtualTouchpadClient() override {} - - private: - VirtualTouchpadClient(const VirtualTouchpadClient&) = delete; - void operator=(const VirtualTouchpadClient&) = delete; -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_VIRTUAL_TOUCHPAD_CLIENT_H diff --git a/services/vr/virtual_touchpad/include/dvr/virtual_touchpad_client.h b/services/vr/virtual_touchpad/include/dvr/virtual_touchpad_client.h deleted file mode 100644 index 09fb1cca56..0000000000 --- a/services/vr/virtual_touchpad/include/dvr/virtual_touchpad_client.h +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef ANDROID_DVR_VIRTUAL_TOUCHPAD_C_CLIENT_H -#define ANDROID_DVR_VIRTUAL_TOUCHPAD_C_CLIENT_H - -#include <dvr/dvr_api.h> - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct DvrVirtualTouchpad DvrVirtualTouchpad; - -// Creates a new virtual touchpad client. -// -// @return Pointer to the created virtual touchpad client; nullptr on failure. -// -DvrVirtualTouchpad* dvrVirtualTouchpadCreate(); - -// Destroys a virtual touchpad client. -// -// @param client Pointer to the virtual touchpad client to be destroyed. -// -void dvrVirtualTouchpadDestroy(DvrVirtualTouchpad* client); - -// Initialize the virtual touchpad. -// -// In the current server implementation, attachment creates and configures -// the kernel virtual touchpad device(s). A single client may be attached -// and detached repeatedly, e.g. on entering and leaving VR mode. -// -// @param client Pointer to the virtual touchpad client to be attached. -// @return Zero on success, status_t-style error code on failure. -// -int dvrVirtualTouchpadAttach(DvrVirtualTouchpad* client); - -// Shut down the virtual touchpad. -// -// @param client Pointer to the virtual touchpad client to be detached. -// @return Zero on success, status_t-style error code on failure. -// -int dvrVirtualTouchpadDetach(DvrVirtualTouchpad* client); - -// Generate a simulated touch event. -// -// @param client Pointer to the virtual touchpad client. -// @param touchpad Selects touchpad. -// @param x Horizontal touch position. -// @param y Vertical touch position. -// @param pressure Touch pressure; use 0.0 for no touch (lift or hover). -// @return Zero on success, status_t-style error code on failure. -// -int dvrVirtualTouchpadTouch(DvrVirtualTouchpad* client, int touchpad, float x, - float y, float pressure); - -// Generate a simulated touchpad button state event. -// -// @param client Pointer to the virtual touchpad client. -// @param touchpad Selects touchpad. -// @param buttons A union of MotionEvent BUTTON_* values. -// @return Zero on success, status_t-style error code on failure. -// -int dvrVirtualTouchpadButtonState(DvrVirtualTouchpad* client, int touchpad, - int buttons); - -// Generate a simulated scroll event. -// -// @param client Pointer to the virtual touchpad client. -// @param touchpad Selects touchpad. -// @param x Horizontal scroll increment. -// @param y Vertical scroll increment. -// @return Zero on success, status_t-style error code on failure. -// -int dvrVirtualTouchpadScroll(DvrVirtualTouchpad* client, int touchpad, float x, - float y); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // ANDROID_DVR_VIRTUAL_TOUCHPAD_CLIENT_H diff --git a/services/vr/virtual_touchpad/main.cpp b/services/vr/virtual_touchpad/main.cpp deleted file mode 100644 index 55ac9bf764..0000000000 --- a/services/vr/virtual_touchpad/main.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include <binder/IPCThreadState.h> -#include <binder/IServiceManager.h> -#include <binder/ProcessState.h> -#include <log/log.h> - -#include "VirtualTouchpadEvdev.h" -#include "VirtualTouchpadService.h" - -int main() { - ALOGI("Starting"); - android::sp<android::dvr::VirtualTouchpadService> touchpad_service = - new android::dvr::VirtualTouchpadService( - android::dvr::VirtualTouchpadEvdev::Create()); - - signal(SIGPIPE, SIG_IGN); - android::sp<android::ProcessState> ps(android::ProcessState::self()); - ps->setThreadPoolMaxThreadCount(4); - ps->startThreadPool(); - ps->giveThreadPoolName(); - - android::sp<android::IServiceManager> sm(android::defaultServiceManager()); - const android::status_t service_status = - sm->addService(android::String16(touchpad_service->SERVICE_NAME()), - touchpad_service, false /*allowIsolated*/); - if (service_status != android::OK) { - ALOGE("virtual touchpad service not added: %d", - static_cast<int>(service_status)); - exit(2); - } - - android::IPCThreadState::self()->joinThreadPool(); - return 0; -} diff --git a/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp b/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp deleted file mode 100644 index 198ed0611b..0000000000 --- a/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp +++ /dev/null @@ -1,320 +0,0 @@ -#include <android/input.h> -#include <gtest/gtest.h> -#include <linux/input.h> -#include <cstdio> -#include <cstdlib> -#include <cstring> - -#include "EvdevInjector.h" -#include "VirtualTouchpadEvdev.h" - -namespace android { -namespace dvr { - -namespace { - -class UInputForTesting : public EvdevInjector::UInput { - public: - ~UInputForTesting() override {} - void WriteInputEvent(uint16_t type, uint16_t code, int32_t value) { - struct input_event event; - memset(&event, 0, sizeof(event)); - event.type = type; - event.code = code; - event.value = value; - Write(&event, sizeof(event)); - } -}; - -// Recording test implementation of UInput. -// -class UInputRecorder : public UInputForTesting { - public: - UInputRecorder() {} - ~UInputRecorder() override {} - - const std::string& GetString() const { return s_; } - void Reset() { s_.clear(); } - - // UInput overrides: - - int Open() override { - s_ += "o;"; - return 0; - } - - int Close() override { - s_ += "c;"; - return 0; - } - - int Write(const void* buf, size_t count) override { - s_ += "w("; - s_ += Encode(&count, sizeof(count)); - s_ += ","; - s_ += Encode(buf, count); - s_ += ");"; - return 0; - } - - int IoctlVoid(int request) override { - s_ += "i("; - s_ += Encode(&request, sizeof(request)); - s_ += ");"; - return 0; - } - - int IoctlSetInt(int request, int value) override { - s_ += "i("; - s_ += Encode(&request, sizeof(request)); - s_ += ","; - s_ += Encode(&value, sizeof(value)); - s_ += ");"; - return 0; - } - - private: - std::string s_; - - std::string Encode(const void* buf, size_t count) { - const char* in = static_cast<const char*>(buf); - char out[2 * count + 1]; - for (size_t i = 0; i < count; ++i) { - snprintf(&out[2 * i], 3, "%02X", in[i]); - } - return out; - } -}; - -class EvdevInjectorForTesting : public EvdevInjector { - public: - EvdevInjectorForTesting() { SetUInputForTesting(&record); } - const uinput_user_dev* GetUiDev() const { return GetUiDevForTesting(); } - UInputRecorder record; -}; - -class VirtualTouchpadForTesting : public VirtualTouchpadEvdev { - public: - static std::unique_ptr<VirtualTouchpad> Create() { - return std::unique_ptr<VirtualTouchpad>(New()); - } - static VirtualTouchpadForTesting* New() { - VirtualTouchpadForTesting* const touchpad = new VirtualTouchpadForTesting(); - touchpad->Reset(); - for (int t = 0; t < kTouchpads; ++t) { - touchpad->SetEvdevInjectorForTesting(t, &touchpad->injector[t]); - } - return touchpad; - } - int GetTouchpadCount() const { return kTouchpads; } - EvdevInjectorForTesting injector[kTouchpads]; -}; - -} // anonymous namespace - -class VirtualTouchpadTest : public testing::Test {}; - -TEST_F(VirtualTouchpadTest, Goodness) { - std::unique_ptr<VirtualTouchpadForTesting> touchpad( - VirtualTouchpadForTesting::New()); - UInputRecorder expect; - - status_t touch_status = touchpad->Attach(); - EXPECT_EQ(0, touch_status); - - // Check some aspects of uinput_user_dev. - const uinput_user_dev* uidev; - for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) { - SCOPED_TRACE(t); - uidev = touchpad->injector[t].GetUiDev(); - String8 name; - name.appendFormat("vr-virtual-touchpad-%d", t); - EXPECT_EQ(name, uidev->name); - for (int i = 0; i < ABS_CNT; ++i) { - EXPECT_EQ(0, uidev->absmin[i]); - EXPECT_EQ(0, uidev->absfuzz[i]); - EXPECT_EQ(0, uidev->absflat[i]); - if (i != ABS_MT_POSITION_X && i != ABS_MT_POSITION_Y && - i != ABS_MT_SLOT) { - EXPECT_EQ(0, uidev->absmax[i]); - } - } - } - const int32_t width = 1 + uidev->absmax[ABS_MT_POSITION_X]; - const int32_t height = 1 + uidev->absmax[ABS_MT_POSITION_Y]; - - for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) { - SCOPED_TRACE(t); - // Check the system calls performed by initialization. - expect.Reset(); - // From ConfigureBegin(): - expect.Open(); - // From ConfigureInputProperty(INPUT_PROP_DIRECT): - expect.IoctlSetInt(UI_SET_PROPBIT, INPUT_PROP_DIRECT); - // From ConfigureMultiTouchXY(0, 0, kWidth - 1, kHeight - 1): - expect.IoctlSetInt(UI_SET_EVBIT, EV_ABS); - expect.IoctlSetInt(UI_SET_ABSBIT, ABS_MT_POSITION_X); - expect.IoctlSetInt(UI_SET_ABSBIT, ABS_MT_POSITION_Y); - // From ConfigureAbsSlots(kSlots): - expect.IoctlSetInt(UI_SET_ABSBIT, ABS_MT_SLOT); - // From ConfigureRel(REL_WHEEL): - expect.IoctlSetInt(UI_SET_EVBIT, EV_REL); - expect.IoctlSetInt(UI_SET_RELBIT, REL_WHEEL); - // From ConfigureRel(REL_HWHEEL): - expect.IoctlSetInt(UI_SET_RELBIT, REL_HWHEEL); - // From ConfigureKey(BTN_TOUCH): - expect.IoctlSetInt(UI_SET_EVBIT, EV_KEY); - expect.IoctlSetInt(UI_SET_KEYBIT, BTN_TOUCH); - expect.IoctlSetInt(UI_SET_KEYBIT, BTN_BACK); - // From ConfigureEnd(): - expect.Write(touchpad->injector[t].GetUiDev(), sizeof(uinput_user_dev)); - expect.IoctlVoid(UI_DEV_CREATE); - EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString()); - } - - expect.Reset(); - expect.WriteInputEvent(EV_ABS, ABS_MT_SLOT, 0); - expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, 0); - expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_X, 0); - expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_Y, 0); - expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0); - for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) { - SCOPED_TRACE(t); - touchpad->injector[t].record.Reset(); - touch_status = touchpad->Touch(t, 0, 0, 0); - EXPECT_EQ(0, touch_status); - EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString()); - } - - expect.Reset(); - expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, 0); - expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_X, 0.25f * width); - expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_Y, 0.75f * height); - expect.WriteInputEvent(EV_KEY, BTN_TOUCH, EvdevInjector::KEY_PRESS); - expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0); - for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) { - SCOPED_TRACE(t); - touchpad->injector[t].record.Reset(); - touch_status = touchpad->Touch(t, 0.25f, 0.75f, 0.5f); - EXPECT_EQ(0, touch_status); - EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString()); - } - - expect.Reset(); - expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, 0); - expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_X, 0.99f * width); - expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_Y, 0.99f * height); - expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0); - for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) { - SCOPED_TRACE(t); - touchpad->injector[t].record.Reset(); - touch_status = touchpad->Touch(t, 0.99f, 0.99f, 0.99f); - EXPECT_EQ(0, touch_status); - EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString()); - } - - expect.Reset(); - for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) { - SCOPED_TRACE(t); - touchpad->injector[t].record.Reset(); - touch_status = touchpad->Touch(t, 1.0f, 1.0f, 1.0f); - EXPECT_EQ(EINVAL, touch_status); - EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString()); - } - - expect.Reset(); - expect.WriteInputEvent(EV_KEY, BTN_TOUCH, EvdevInjector::KEY_RELEASE); - expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, -1); - expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0); - for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) { - SCOPED_TRACE(t); - touchpad->injector[t].record.Reset(); - touch_status = touchpad->Touch(t, 0.25f, 0.75f, -0.01f); - EXPECT_EQ(0, touch_status); - EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString()); - } - - expect.Reset(); - expect.WriteInputEvent(EV_KEY, BTN_BACK, EvdevInjector::KEY_PRESS); - expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0); - for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) { - SCOPED_TRACE(t); - touchpad->injector[t].record.Reset(); - touch_status = touchpad->ButtonState(t, AMOTION_EVENT_BUTTON_BACK); - EXPECT_EQ(0, touch_status); - EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString()); - } - - expect.Reset(); - for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) { - SCOPED_TRACE(t); - touchpad->injector[t].record.Reset(); - touch_status = touchpad->ButtonState(t, AMOTION_EVENT_BUTTON_BACK); - EXPECT_EQ(0, touch_status); - EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString()); - } - - expect.Reset(); - expect.WriteInputEvent(EV_KEY, BTN_BACK, EvdevInjector::KEY_RELEASE); - expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0); - for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) { - SCOPED_TRACE(t); - touchpad->injector[t].record.Reset(); - touch_status = touchpad->ButtonState(t, 0); - EXPECT_EQ(0, touch_status); - EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString()); - } - - expect.Reset(); - expect.Close(); - for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) { - SCOPED_TRACE(t); - touchpad->injector[t].record.Reset(); - } - touch_status = touchpad->Detach(); - EXPECT_EQ(0, touch_status); - for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) { - SCOPED_TRACE(t); - EXPECT_EQ(expect.GetString(), touchpad->injector[t].record.GetString()); - } -} - -TEST_F(VirtualTouchpadTest, Badness) { - std::unique_ptr<VirtualTouchpadForTesting> touchpad( - VirtualTouchpadForTesting::New()); - UInputRecorder expect; - UInputRecorder& record = touchpad->injector[VirtualTouchpad::PRIMARY].record; - - status_t touch_status = touchpad->Attach(); - EXPECT_EQ(0, touch_status); - - // Touch off-screen should return an error, - // and should not result in any system calls. - expect.Reset(); - record.Reset(); - touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, -0.25f, 0.75f, 1.0f); - EXPECT_NE(OK, touch_status); - touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 0.25f, -0.75f, 1.0f); - EXPECT_NE(OK, touch_status); - touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 1.25f, 0.75f, 1.0f); - EXPECT_NE(OK, touch_status); - touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 0.25f, 1.75f, 1.0f); - EXPECT_NE(OK, touch_status); - EXPECT_EQ(expect.GetString(), record.GetString()); - - // Unsupported button should return an error, - // and should not result in any system calls. - expect.Reset(); - record.Reset(); - touch_status = touchpad->ButtonState(VirtualTouchpad::PRIMARY, - AMOTION_EVENT_BUTTON_FORWARD); - EXPECT_NE(OK, touch_status); - EXPECT_EQ(expect.GetString(), record.GetString()); - - // Repeated attach is an error. - touch_status = touchpad->Attach(); - EXPECT_NE(0, touch_status); -} - -} // namespace dvr -} // namespace android diff --git a/services/vr/virtual_touchpad/virtual_touchpad.rc b/services/vr/virtual_touchpad/virtual_touchpad.rc deleted file mode 100644 index 1612743867..0000000000 --- a/services/vr/virtual_touchpad/virtual_touchpad.rc +++ /dev/null @@ -1,5 +0,0 @@ -service virtual_touchpad /system/bin/virtual_touchpad - class core - user system - group system input uhid - task_profiles VrServiceCapacityNormal |