/* * Copyright (C) 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. */ #pragma once #include #include #include #include #include #include #include #include namespace android { using aidl::android::hardware::common::MQDescriptor; using aidl::android::hardware::common::SynchronizedReadWrite; using aidl::android::hardware::common::UnsynchronizedWrite; using android::details::AidlMQDescriptorShim; using android::hardware::MQFlavor; template struct FlavorTypeToValue; template <> struct FlavorTypeToValue { static constexpr MQFlavor value = hardware::kSynchronizedReadWrite; }; template <> struct FlavorTypeToValue { static constexpr MQFlavor value = hardware::kUnsynchronizedWrite; }; typedef uint64_t RingBufferPosition; /* * AIDL parcelables will have the typedef fixed_size. It is std::true_type when the * parcelable is annotated with @FixedSize, and std::false_type when not. Other types * should not have the fixed_size typedef, so they will always resolve to std::false_type. */ template struct has_typedef_fixed_size : std::false_type {}; template struct has_typedef_fixed_size> : T::fixed_size {}; template struct AidlMessageQueue final : public MessageQueueBase::value> { static_assert(has_typedef_fixed_size::value == true || std::is_fundamental::value || std::is_enum::value, "Only fundamental types, enums, and AIDL parcelables annotated with @FixedSize " "and built for the NDK backend are supported as payload types(T)."); typedef AidlMQDescriptorShim::value> Descriptor; /** * This constructor uses the external descriptor used with AIDL interfaces. * It will create an FMQ based on the descriptor that was obtained from * another FMQ instance for communication. * * @param desc Descriptor from another FMQ that contains all of the * information required to create a new instance of that queue. * @param resetPointers Boolean indicating whether the read/write pointers * should be reset or not. */ AidlMessageQueue(const MQDescriptor& desc, bool resetPointers = true); ~AidlMessageQueue() = default; /** * This constructor uses Ashmem shared memory to create an FMQ * that can contain a maximum of 'numElementsInQueue' elements of type T. * * @param numElementsInQueue Capacity of the AidlMessageQueue in terms of T. * @param configureEventFlagWord Boolean that specifies if memory should * also be allocated and mapped for an EventFlag word. */ AidlMessageQueue(size_t numElementsInQueue, bool configureEventFlagWord = false); MQDescriptor dupeDesc(); private: AidlMessageQueue(const AidlMessageQueue& other) = delete; AidlMessageQueue& operator=(const AidlMessageQueue& other) = delete; AidlMessageQueue() = delete; }; template AidlMessageQueue::AidlMessageQueue(const MQDescriptor& desc, bool resetPointers) : MessageQueueBase::value>(Descriptor(desc), resetPointers) {} template AidlMessageQueue::AidlMessageQueue(size_t numElementsInQueue, bool configureEventFlagWord) : MessageQueueBase::value>( numElementsInQueue, configureEventFlagWord) {} template MQDescriptor AidlMessageQueue::dupeDesc() { auto* shim = MessageQueueBase::value>::getDesc(); if (shim) { std::vector grantors; for (const auto& grantor : shim->grantors()) { grantors.push_back(aidl::android::hardware::common::GrantorDescriptor{ .offset = static_cast(grantor.offset), .extent = static_cast(grantor.extent)}); } return MQDescriptor{ .quantum = static_cast(shim->getQuantum()), .grantors = grantors, .flags = static_cast(shim->getFlags()), .fileDescriptor = ndk::ScopedFileDescriptor(dup(shim->handle()->data[0])), }; } else { return MQDescriptor(); } } } // namespace android