1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #pragma once 17 #include <aidl/android/hardware/common/fmq/MQDescriptor.h> 18 #include <aidl/android/hardware/common/fmq/SynchronizedReadWrite.h> 19 #include <aidl/android/hardware/common/fmq/UnsynchronizedWrite.h> 20 #include "AidlMQDescriptorShim.h" 21 #include "AidlMessageQueueBase.h" 22 23 namespace android { 24 using aidl::android::hardware::common::fmq::MQDescriptor; 25 using aidl::android::hardware::common::fmq::SynchronizedReadWrite; 26 using aidl::android::hardware::common::fmq::UnsynchronizedWrite; 27 using android::details::AidlMQDescriptorShim; 28 using android::hardware::MQFlavor; 29 30 template <> 31 struct FlavorTypeToValue<aidl::android::hardware::common::fmq::SynchronizedReadWrite> { 32 static constexpr MQFlavor value = hardware::kSynchronizedReadWrite; 33 }; 34 35 template <> 36 struct FlavorTypeToValue<aidl::android::hardware::common::fmq::UnsynchronizedWrite> { 37 static constexpr MQFlavor value = hardware::kUnsynchronizedWrite; 38 }; 39 40 struct BackendTypesStore { 41 template <typename T, MQFlavor flavor> 42 using AidlMQDescriptorShimType = android::details::AidlMQDescriptorShim<T, flavor>; 43 using GrantorDescriptorType = aidl::android::hardware::common::fmq::GrantorDescriptor; 44 template <typename T, typename flavor> 45 using MQDescriptorType = aidl::android::hardware::common::fmq::MQDescriptor<T, flavor>; 46 using FileDescriptorType = ndk::ScopedFileDescriptor; 47 static FileDescriptorType createFromInt(int fd) { return FileDescriptorType(fd); } 48 }; 49 50 template <typename T, typename U> 51 struct AidlMessageQueue final : public AidlMessageQueueBase<T, U, BackendTypesStore> { 52 AidlMessageQueue(const MQDescriptor<T, U>& desc, bool resetPointers = true); 53 ~AidlMessageQueue() = default; 54 55 /** 56 * This constructor uses Ashmem shared memory to create an FMQ 57 * that can contain a maximum of 'numElementsInQueue' elements of type T. 58 * 59 * @param numElementsInQueue Capacity of the AidlMessageQueue in terms of T. 60 * @param configureEventFlagWord Boolean that specifies if memory should 61 * also be allocated and mapped for an EventFlag word. 62 * @param bufferFd User-supplied file descriptor to map the memory for the ringbuffer 63 * By default, bufferFd=-1 means library will allocate ashmem region for ringbuffer. 64 * MessageQueue takes ownership of the file descriptor. 65 * @param bufferSize size of buffer in bytes that bufferFd represents. This 66 * size must be larger than or equal to (numElementsInQueue * sizeof(T)). 67 * Otherwise, operations will cause out-of-bounds memory access. 68 */ 69 AidlMessageQueue(size_t numElementsInQueue, bool configureEventFlagWord, 70 android::base::unique_fd bufferFd, size_t bufferSize); 71 72 AidlMessageQueue(size_t numElementsInQueue, bool configureEventFlagWord = false) 73 : AidlMessageQueue(numElementsInQueue, configureEventFlagWord, android::base::unique_fd(), 74 0) {} 75 76 template <typename V = T> 77 AidlMessageQueue(size_t numElementsInQueue, bool configureEventFlagWord = false, 78 std::enable_if_t<std::is_same_v<V, MQErased>, size_t> quantum = sizeof(T)) 79 : AidlMessageQueue(numElementsInQueue, configureEventFlagWord, android::base::unique_fd(), 80 0, quantum) {} 81 82 template <typename V = T> 83 AidlMessageQueue(size_t numElementsInQueue, bool configureEventFlagWord, 84 android::base::unique_fd bufferFd, size_t bufferSize, 85 std::enable_if_t<std::is_same_v<V, MQErased>, size_t> quantum); 86 }; 87 88 template <typename T, typename U> 89 AidlMessageQueue<T, U>::AidlMessageQueue(const MQDescriptor<T, U>& desc, bool resetPointers) 90 : AidlMessageQueueBase<T, U, BackendTypesStore>(desc, resetPointers) {} 91 92 template <typename T, typename U> 93 AidlMessageQueue<T, U>::AidlMessageQueue(size_t numElementsInQueue, bool configureEventFlagWord, 94 android::base::unique_fd bufferFd, size_t bufferSize) 95 : AidlMessageQueueBase<T, U, BackendTypesStore>(numElementsInQueue, configureEventFlagWord, 96 std::move(bufferFd), bufferSize) {} 97 98 template <typename T, typename U> 99 template <typename V> 100 AidlMessageQueue<T, U>::AidlMessageQueue( 101 size_t numElementsInQueue, bool configureEventFlagWord, android::base::unique_fd bufferFd, 102 size_t bufferSize, std::enable_if_t<std::is_same_v<V, MQErased>, size_t> quantum) 103 : AidlMessageQueueBase<T, U, BackendTypesStore>(numElementsInQueue, configureEventFlagWord, 104 std::move(bufferFd), bufferSize, quantum) {} 105 106 } // namespace android 107