1 /* 2 * Copyright (C) 2024 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 17 #pragma once 18 #include <android/hardware/common/fmq/MQDescriptor.h> 19 #include <android/hardware/common/fmq/SynchronizedReadWrite.h> 20 #include <android/hardware/common/fmq/UnsynchronizedWrite.h> 21 #include <fmq/MQDescriptorBase.h> 22 #include "AidlMQDescriptorShimCpp.h" 23 #include "AidlMessageQueueBase.h" 24 namespace android { 25 26 template <> 27 struct FlavorTypeToValue<android::hardware::common::fmq::SynchronizedReadWrite> { 28 static constexpr MQFlavor value = hardware::kSynchronizedReadWrite; 29 }; 30 31 template <> 32 struct FlavorTypeToValue<android::hardware::common::fmq::UnsynchronizedWrite> { 33 static constexpr MQFlavor value = hardware::kUnsynchronizedWrite; 34 }; 35 36 struct BackendTypesStoreCpp { 37 template <typename T, MQFlavor flavor> 38 using AidlMQDescriptorShimType = android::details::AidlMQDescriptorShimCpp<T, flavor>; 39 using GrantorDescriptorType = android::hardware::common::fmq::GrantorDescriptor; 40 template <typename T, typename flavor> 41 using MQDescriptorType = android::hardware::common::fmq::MQDescriptor<T, flavor>; 42 using FileDescriptorType = os::ParcelFileDescriptor; 43 static FileDescriptorType createFromInt(int fd) { 44 return FileDescriptorType(binder::unique_fd(fd)); 45 } 46 }; 47 48 template <typename T, typename U> 49 struct AidlMessageQueueCpp final : public AidlMessageQueueBase<T, U, BackendTypesStoreCpp> { 50 AidlMessageQueueCpp(const android::hardware::common::fmq::MQDescriptor<T, U>& desc, 51 bool resetPointers = true); 52 ~AidlMessageQueueCpp() = default; 53 54 /** 55 * This constructor uses Ashmem shared memory to create an FMQ 56 * that can contain a maximum of 'numElementsInQueue' elements of type T. 57 * 58 * @param numElementsInQueue Capacity of the AidlMessageQueueCpp in terms of T. 59 * @param configureEventFlagWord Boolean that specifies if memory should 60 * also be allocated and mapped for an EventFlag word. 61 * @param bufferFd User-supplied file descriptor to map the memory for the ringbuffer 62 * By default, bufferFd=-1 means library will allocate ashmem region for ringbuffer. 63 * MessageQueue takes ownership of the file descriptor. 64 * @param bufferSize size of buffer in bytes that bufferFd represents. This 65 * size must be larger than or equal to (numElementsInQueue * sizeof(T)). 66 * Otherwise, operations will cause out-of-bounds memory access. 67 */ 68 AidlMessageQueueCpp(size_t numElementsInQueue, bool configureEventFlagWord, 69 android::base::unique_fd bufferFd, size_t bufferSize); 70 71 AidlMessageQueueCpp(size_t numElementsInQueue, bool configureEventFlagWord = false) 72 : AidlMessageQueueCpp(numElementsInQueue, configureEventFlagWord, 73 android::base::unique_fd(), 0) {} 74 75 template <typename V = T> 76 AidlMessageQueueCpp(size_t numElementsInQueue, bool configureEventFlagWord = false, 77 std::enable_if_t<std::is_same_v<V, MQErased>, size_t> quantum = sizeof(T)) 78 : AidlMessageQueueCpp(numElementsInQueue, configureEventFlagWord, 79 android::base::unique_fd(), 0, quantum) {} 80 81 template <typename V = T> 82 AidlMessageQueueCpp(size_t numElementsInQueue, bool configureEventFlagWord, 83 android::base::unique_fd bufferFd, size_t bufferSize, 84 std::enable_if_t<std::is_same_v<V, MQErased>, size_t> quantum); 85 }; 86 87 template <typename T, typename U> 88 AidlMessageQueueCpp<T, U>::AidlMessageQueueCpp( 89 const android::hardware::common::fmq::MQDescriptor<T, U>& desc, bool resetPointers) 90 : AidlMessageQueueBase<T, U, BackendTypesStoreCpp>(desc, resetPointers) {} 91 92 template <typename T, typename U> 93 AidlMessageQueueCpp<T, U>::AidlMessageQueueCpp(size_t numElementsInQueue, 94 bool configureEventFlagWord, 95 android::base::unique_fd bufferFd, size_t bufferSize) 96 : AidlMessageQueueBase<T, U, BackendTypesStoreCpp>(numElementsInQueue, configureEventFlagWord, 97 std::move(bufferFd), bufferSize) {} 98 99 template <typename T, typename U> 100 template <typename V> 101 AidlMessageQueueCpp<T, U>::AidlMessageQueueCpp( 102 size_t numElementsInQueue, bool configureEventFlagWord, android::base::unique_fd bufferFd, 103 size_t bufferSize, std::enable_if_t<std::is_same_v<V, MQErased>, size_t> quantum) 104 : AidlMessageQueueBase<T, U, BackendTypesStoreCpp>(numElementsInQueue, configureEventFlagWord, 105 std::move(bufferFd), bufferSize, quantum) {} 106 107 } // namespace android