xref: /aosp_15_r20/system/libfmq/include/fmq/AidlMessageQueueBase.h (revision be431cd81a9a2349eaea34eb56fcf6d1608da596)
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