1*be431cd8SAndroid Build Coastguard Worker /* 2*be431cd8SAndroid Build Coastguard Worker * Copyright (C) 2024 The Android Open Source Project 3*be431cd8SAndroid Build Coastguard Worker * 4*be431cd8SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*be431cd8SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*be431cd8SAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*be431cd8SAndroid Build Coastguard Worker * 8*be431cd8SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*be431cd8SAndroid Build Coastguard Worker * 10*be431cd8SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*be431cd8SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*be431cd8SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*be431cd8SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*be431cd8SAndroid Build Coastguard Worker * limitations under the License. 15*be431cd8SAndroid Build Coastguard Worker */ 16*be431cd8SAndroid Build Coastguard Worker #pragma once 17*be431cd8SAndroid Build Coastguard Worker #include <cutils/native_handle.h> 18*be431cd8SAndroid Build Coastguard Worker #include <fmq/MessageQueueBase.h> 19*be431cd8SAndroid Build Coastguard Worker #include <utils/Log.h> 20*be431cd8SAndroid Build Coastguard Worker #include <type_traits> 21*be431cd8SAndroid Build Coastguard Worker 22*be431cd8SAndroid Build Coastguard Worker using android::hardware::MQFlavor; 23*be431cd8SAndroid Build Coastguard Worker 24*be431cd8SAndroid Build Coastguard Worker typedef uint64_t RingBufferPosition; 25*be431cd8SAndroid Build Coastguard Worker 26*be431cd8SAndroid Build Coastguard Worker namespace android { 27*be431cd8SAndroid Build Coastguard Worker 28*be431cd8SAndroid Build Coastguard Worker template <typename T> 29*be431cd8SAndroid Build Coastguard Worker struct FlavorTypeToValue; 30*be431cd8SAndroid Build Coastguard Worker 31*be431cd8SAndroid Build Coastguard Worker /* 32*be431cd8SAndroid Build Coastguard Worker * AIDL parcelables will have the typedef fixed_size. It is std::true_type when the 33*be431cd8SAndroid Build Coastguard Worker * parcelable is annotated with @FixedSize, and std::false_type when not. Other types 34*be431cd8SAndroid Build Coastguard Worker * should not have the fixed_size typedef, so they will always resolve to std::false_type. 35*be431cd8SAndroid Build Coastguard Worker */ 36*be431cd8SAndroid Build Coastguard Worker template <typename T, typename = void> 37*be431cd8SAndroid Build Coastguard Worker struct has_typedef_fixed_size : std::false_type {}; 38*be431cd8SAndroid Build Coastguard Worker 39*be431cd8SAndroid Build Coastguard Worker template <typename T> 40*be431cd8SAndroid Build Coastguard Worker struct has_typedef_fixed_size<T, std::void_t<typename T::fixed_size>> : T::fixed_size {}; 41*be431cd8SAndroid Build Coastguard Worker 42*be431cd8SAndroid Build Coastguard Worker #define STATIC_AIDL_TYPE_CHECK(T) \ 43*be431cd8SAndroid Build Coastguard Worker static_assert(has_typedef_fixed_size<T>::value == true || std::is_fundamental<T>::value || \ 44*be431cd8SAndroid Build Coastguard Worker std::is_enum<T>::value, \ 45*be431cd8SAndroid Build Coastguard Worker "Only fundamental types, enums, and AIDL parcelables annotated with @FixedSize " \ 46*be431cd8SAndroid Build Coastguard Worker "and built for the NDK backend are supported as payload types(T)."); 47*be431cd8SAndroid Build Coastguard Worker 48*be431cd8SAndroid Build Coastguard Worker template <template <typename> class C1> 49*be431cd8SAndroid Build Coastguard Worker struct Base {}; 50*be431cd8SAndroid Build Coastguard Worker 51*be431cd8SAndroid Build Coastguard Worker template <typename T, typename BaseTypes, typename U> 52*be431cd8SAndroid Build Coastguard Worker struct Queue : Base<BaseTypes::template B> {}; 53*be431cd8SAndroid Build Coastguard Worker 54*be431cd8SAndroid Build Coastguard Worker template <typename T, typename U, typename BackendTypes> 55*be431cd8SAndroid Build Coastguard Worker struct AidlMessageQueueBase 56*be431cd8SAndroid Build Coastguard Worker : public MessageQueueBase<BackendTypes::template AidlMQDescriptorShimType, T, 57*be431cd8SAndroid Build Coastguard Worker FlavorTypeToValue<U>::value> { 58*be431cd8SAndroid Build Coastguard Worker STATIC_AIDL_TYPE_CHECK(T); 59*be431cd8SAndroid Build Coastguard Worker typedef typename BackendTypes::FileDescriptorType FileDescriptorType; 60*be431cd8SAndroid Build Coastguard Worker typedef typename BackendTypes::GrantorDescriptorType GrantorDescriptorType; 61*be431cd8SAndroid Build Coastguard Worker typedef typename BackendTypes::template AidlMQDescriptorShimType<T, FlavorTypeToValue<U>::value> 62*be431cd8SAndroid Build Coastguard Worker Descriptor; 63*be431cd8SAndroid Build Coastguard Worker /** 64*be431cd8SAndroid Build Coastguard Worker * This constructor uses the external descriptor used with AIDL interfaces. 65*be431cd8SAndroid Build Coastguard Worker * It will create an FMQ based on the descriptor that was obtained from 66*be431cd8SAndroid Build Coastguard Worker * another FMQ instance for communication. 67*be431cd8SAndroid Build Coastguard Worker * 68*be431cd8SAndroid Build Coastguard Worker * @param desc Descriptor from another FMQ that contains all of the 69*be431cd8SAndroid Build Coastguard Worker * information required to create a new instance of that queue. 70*be431cd8SAndroid Build Coastguard Worker * @param resetPointers Boolean indicating whether the read/write pointers 71*be431cd8SAndroid Build Coastguard Worker * should be reset or not. 72*be431cd8SAndroid Build Coastguard Worker */ 73*be431cd8SAndroid Build Coastguard Worker AidlMessageQueueBase(const typename BackendTypes::template MQDescriptorType<T, U>& desc, 74*be431cd8SAndroid Build Coastguard Worker bool resetPointers = true); 75*be431cd8SAndroid Build Coastguard Worker ~AidlMessageQueueBase() = default; 76*be431cd8SAndroid Build Coastguard Worker 77*be431cd8SAndroid Build Coastguard Worker /** 78*be431cd8SAndroid Build Coastguard Worker * This constructor uses Ashmem shared memory to create an FMQ 79*be431cd8SAndroid Build Coastguard Worker * that can contain a maximum of 'numElementsInQueue' elements of type T. 80*be431cd8SAndroid Build Coastguard Worker * 81*be431cd8SAndroid Build Coastguard Worker * @param numElementsInQueue Capacity of the AidlMessageQueueBase in terms of T. 82*be431cd8SAndroid Build Coastguard Worker * @param configureEventFlagWord Boolean that specifies if memory should 83*be431cd8SAndroid Build Coastguard Worker * also be allocated and mapped for an EventFlag word. 84*be431cd8SAndroid Build Coastguard Worker * @param bufferFd User-supplied file descriptor to map the memory for the ringbuffer 85*be431cd8SAndroid Build Coastguard Worker * By default, bufferFd=-1 means library will allocate ashmem region for ringbuffer. 86*be431cd8SAndroid Build Coastguard Worker * MessageQueue takes ownership of the file descriptor. 87*be431cd8SAndroid Build Coastguard Worker * @param bufferSize size of buffer in bytes that bufferFd represents. This 88*be431cd8SAndroid Build Coastguard Worker * size must be larger than or equal to (numElementsInQueue * sizeof(T)). 89*be431cd8SAndroid Build Coastguard Worker * Otherwise, operations will cause out-of-bounds memory access. 90*be431cd8SAndroid Build Coastguard Worker */ 91*be431cd8SAndroid Build Coastguard Worker AidlMessageQueueBase(size_t numElementsInQueue, bool configureEventFlagWord, 92*be431cd8SAndroid Build Coastguard Worker android::base::unique_fd bufferFd, size_t bufferSize); 93*be431cd8SAndroid Build Coastguard Worker 94*be431cd8SAndroid Build Coastguard Worker AidlMessageQueueBase(size_t numElementsInQueue, bool configureEventFlagWord = false) 95*be431cd8SAndroid Build Coastguard Worker : AidlMessageQueueBase(numElementsInQueue, configureEventFlagWord, 96*be431cd8SAndroid Build Coastguard Worker android::base::unique_fd(), 0) {} 97*be431cd8SAndroid Build Coastguard Worker 98*be431cd8SAndroid Build Coastguard Worker template <typename V = T> 99*be431cd8SAndroid Build Coastguard Worker AidlMessageQueueBase(size_t numElementsInQueue, bool configureEventFlagWord = false, 100*be431cd8SAndroid Build Coastguard Worker std::enable_if_t<std::is_same_v<V, MQErased>, size_t> quantum = sizeof(T)) 101*be431cd8SAndroid Build Coastguard Worker : AidlMessageQueueBase(numElementsInQueue, configureEventFlagWord, 102*be431cd8SAndroid Build Coastguard Worker android::base::unique_fd(), 0, quantum) {} 103*be431cd8SAndroid Build Coastguard Worker 104*be431cd8SAndroid Build Coastguard Worker template <typename V = T> 105*be431cd8SAndroid Build Coastguard Worker AidlMessageQueueBase(size_t numElementsInQueue, bool configureEventFlagWord, 106*be431cd8SAndroid Build Coastguard Worker android::base::unique_fd bufferFd, size_t bufferSize, 107*be431cd8SAndroid Build Coastguard Worker std::enable_if_t<std::is_same_v<V, MQErased>, size_t> quantum); 108*be431cd8SAndroid Build Coastguard Worker typename BackendTypes::template MQDescriptorType<T, U> dupeDesc() const; 109*be431cd8SAndroid Build Coastguard Worker 110*be431cd8SAndroid Build Coastguard Worker private: 111*be431cd8SAndroid Build Coastguard Worker AidlMessageQueueBase(const AidlMessageQueueBase& other) = delete; 112*be431cd8SAndroid Build Coastguard Worker AidlMessageQueueBase& operator=(const AidlMessageQueueBase& other) = delete; 113*be431cd8SAndroid Build Coastguard Worker AidlMessageQueueBase() = delete; 114*be431cd8SAndroid Build Coastguard Worker }; 115*be431cd8SAndroid Build Coastguard Worker 116*be431cd8SAndroid Build Coastguard Worker template <typename T, typename U, typename BackendTypes> 117*be431cd8SAndroid Build Coastguard Worker AidlMessageQueueBase<T, U, BackendTypes>::AidlMessageQueueBase( 118*be431cd8SAndroid Build Coastguard Worker const typename BackendTypes::template MQDescriptorType<T, U>& desc, bool resetPointers) 119*be431cd8SAndroid Build Coastguard Worker : MessageQueueBase<BackendTypes::template AidlMQDescriptorShimType, T, 120*be431cd8SAndroid Build Coastguard Worker FlavorTypeToValue<U>::value>(Descriptor(desc), resetPointers) {} 121*be431cd8SAndroid Build Coastguard Worker 122*be431cd8SAndroid Build Coastguard Worker template <typename T, typename U, typename BackendTypes> 123*be431cd8SAndroid Build Coastguard Worker AidlMessageQueueBase<T, U, BackendTypes>::AidlMessageQueueBase(size_t numElementsInQueue, 124*be431cd8SAndroid Build Coastguard Worker bool configureEventFlagWord, 125*be431cd8SAndroid Build Coastguard Worker android::base::unique_fd bufferFd, 126*be431cd8SAndroid Build Coastguard Worker size_t bufferSize) 127*be431cd8SAndroid Build Coastguard Worker : MessageQueueBase<BackendTypes::template AidlMQDescriptorShimType, T, 128*be431cd8SAndroid Build Coastguard Worker FlavorTypeToValue<U>::value>(numElementsInQueue, configureEventFlagWord, 129*be431cd8SAndroid Build Coastguard Worker std::move(bufferFd), bufferSize) {} 130*be431cd8SAndroid Build Coastguard Worker 131*be431cd8SAndroid Build Coastguard Worker template <typename T, typename U, typename BackendTypes> 132*be431cd8SAndroid Build Coastguard Worker template <typename V> 133*be431cd8SAndroid Build Coastguard Worker AidlMessageQueueBase<T, U, BackendTypes>::AidlMessageQueueBase( 134*be431cd8SAndroid Build Coastguard Worker size_t numElementsInQueue, bool configureEventFlagWord, android::base::unique_fd bufferFd, 135*be431cd8SAndroid Build Coastguard Worker size_t bufferSize, std::enable_if_t<std::is_same_v<V, MQErased>, size_t> quantum) 136*be431cd8SAndroid Build Coastguard Worker : MessageQueueBase<BackendTypes::template AidlMQDescriptorShimType, T, 137*be431cd8SAndroid Build Coastguard Worker FlavorTypeToValue<U>::value>(numElementsInQueue, configureEventFlagWord, 138*be431cd8SAndroid Build Coastguard Worker std::move(bufferFd), bufferSize, quantum) {} 139*be431cd8SAndroid Build Coastguard Worker 140*be431cd8SAndroid Build Coastguard Worker template <typename T, typename U, typename BackendTypes> 141*be431cd8SAndroid Build Coastguard Worker typename BackendTypes::template MQDescriptorType<T, U> 142*be431cd8SAndroid Build Coastguard Worker AidlMessageQueueBase<T, U, BackendTypes>::dupeDesc() const { 143*be431cd8SAndroid Build Coastguard Worker auto* shim = MessageQueueBase<BackendTypes::template AidlMQDescriptorShimType, T, 144*be431cd8SAndroid Build Coastguard Worker FlavorTypeToValue<U>::value>::getDesc(); 145*be431cd8SAndroid Build Coastguard Worker if (shim) { 146*be431cd8SAndroid Build Coastguard Worker std::vector<GrantorDescriptorType> grantors; 147*be431cd8SAndroid Build Coastguard Worker for (const auto& grantor : shim->grantors()) { 148*be431cd8SAndroid Build Coastguard Worker GrantorDescriptorType gd; 149*be431cd8SAndroid Build Coastguard Worker gd.fdIndex = static_cast<int32_t>(grantor.fdIndex); 150*be431cd8SAndroid Build Coastguard Worker gd.offset = static_cast<int32_t>(grantor.offset); 151*be431cd8SAndroid Build Coastguard Worker gd.extent = static_cast<int64_t>(grantor.extent); 152*be431cd8SAndroid Build Coastguard Worker grantors.push_back(gd); 153*be431cd8SAndroid Build Coastguard Worker } 154*be431cd8SAndroid Build Coastguard Worker std::vector<FileDescriptorType> fds; 155*be431cd8SAndroid Build Coastguard Worker std::vector<int> ints; 156*be431cd8SAndroid Build Coastguard Worker int data_index = 0; 157*be431cd8SAndroid Build Coastguard Worker for (; data_index < shim->handle()->numFds; data_index++) { 158*be431cd8SAndroid Build Coastguard Worker fds.push_back(BackendTypes::createFromInt(dup(shim->handle()->data[data_index]))); 159*be431cd8SAndroid Build Coastguard Worker } 160*be431cd8SAndroid Build Coastguard Worker for (; data_index < shim->handle()->numFds + shim->handle()->numInts; data_index++) { 161*be431cd8SAndroid Build Coastguard Worker ints.push_back(shim->handle()->data[data_index]); 162*be431cd8SAndroid Build Coastguard Worker } 163*be431cd8SAndroid Build Coastguard Worker typename BackendTypes::template MQDescriptorType<T, U> desc; 164*be431cd8SAndroid Build Coastguard Worker 165*be431cd8SAndroid Build Coastguard Worker desc.grantors = grantors; 166*be431cd8SAndroid Build Coastguard Worker desc.handle.fds = std::move(fds); 167*be431cd8SAndroid Build Coastguard Worker desc.handle.ints = ints; 168*be431cd8SAndroid Build Coastguard Worker desc.quantum = static_cast<int32_t>(shim->getQuantum()); 169*be431cd8SAndroid Build Coastguard Worker desc.flags = static_cast<int32_t>(shim->getFlags()); 170*be431cd8SAndroid Build Coastguard Worker return desc; 171*be431cd8SAndroid Build Coastguard Worker } else { 172*be431cd8SAndroid Build Coastguard Worker return typename BackendTypes::template MQDescriptorType<T, U>(); 173*be431cd8SAndroid Build Coastguard Worker } 174*be431cd8SAndroid Build Coastguard Worker } 175*be431cd8SAndroid Build Coastguard Worker 176*be431cd8SAndroid Build Coastguard Worker } // namespace android 177