xref: /aosp_15_r20/system/libfmq/ErasedMessageQueue.hpp (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 
17*be431cd8SAndroid Build Coastguard Worker #include <fmq/AidlMessageQueue.h>
18*be431cd8SAndroid Build Coastguard Worker 
19*be431cd8SAndroid Build Coastguard Worker using aidl::android::hardware::common::NativeHandle;
20*be431cd8SAndroid Build Coastguard Worker using aidl::android::hardware::common::fmq::GrantorDescriptor;
21*be431cd8SAndroid Build Coastguard Worker using aidl::android::hardware::common::fmq::SynchronizedReadWrite;
22*be431cd8SAndroid Build Coastguard Worker 
23*be431cd8SAndroid Build Coastguard Worker using namespace android;
24*be431cd8SAndroid Build Coastguard Worker 
25*be431cd8SAndroid Build Coastguard Worker struct MemTransaction {
26*be431cd8SAndroid Build Coastguard Worker     AidlMessageQueue<MQErased, SynchronizedReadWrite>::MemRegion first;
27*be431cd8SAndroid Build Coastguard Worker     AidlMessageQueue<MQErased, SynchronizedReadWrite>::MemRegion second;
28*be431cd8SAndroid Build Coastguard Worker };
29*be431cd8SAndroid Build Coastguard Worker 
30*be431cd8SAndroid Build Coastguard Worker typedef MQDescriptor<MQErased, SynchronizedReadWrite> ErasedMessageQueueDesc;
31*be431cd8SAndroid Build Coastguard Worker 
32*be431cd8SAndroid Build Coastguard Worker GrantorDescriptor convertGrantor(int32_t fdIndex, int32_t offset, int64_t extent);
33*be431cd8SAndroid Build Coastguard Worker 
34*be431cd8SAndroid Build Coastguard Worker /**
35*be431cd8SAndroid Build Coastguard Worker  * Construct a C++ AIDL MQDescriptor<MQErased, SynchronizedReadWrite> (aka an
36*be431cd8SAndroid Build Coastguard Worker  * ErasedMessageQueueDesc) from the fields of a Rust AIDL
37*be431cd8SAndroid Build Coastguard Worker  * MQDescriptor<MQErased, SynchronizedReadWrite>.
38*be431cd8SAndroid Build Coastguard Worker  *
39*be431cd8SAndroid Build Coastguard Worker  * These two types are semantically equivalent but come from separate AIDL
40*be431cd8SAndroid Build Coastguard Worker  * codegen backends, so we must convert between them. To convert in the opposite
41*be431cd8SAndroid Build Coastguard Worker  * direction, use the descFoo methods to access each field, and manually build
42*be431cd8SAndroid Build Coastguard Worker  * the Rust AIDL MQDescriptor<MQErased, SynchronizedReadWrite> instance;
43*be431cd8SAndroid Build Coastguard Worker  * see the Rust MessageQueue<T>::dupe_desc method.
44*be431cd8SAndroid Build Coastguard Worker  *
45*be431cd8SAndroid Build Coastguard Worker  * @param grantors Pointer to the start of the MQDescriptor's GrantorDescriptor
46*be431cd8SAndroid Build Coastguard Worker  * array.
47*be431cd8SAndroid Build Coastguard Worker  * @param n_grantors The length of the MQDescriptor's GrantorDescriptor array.
48*be431cd8SAndroid Build Coastguard Worker  * @param handle_fds Pointer to the start of the MQDescriptor's NativeHandle's
49*be431cd8SAndroid Build Coastguard Worker  * file-descriptor array. Ownership of array and contents is not transferred.
50*be431cd8SAndroid Build Coastguard Worker  * @param handle_n_fds The corresponding length.
51*be431cd8SAndroid Build Coastguard Worker  * @param handle_ints Pointer to the start of the MQDescriptor's NativeHandle's
52*be431cd8SAndroid Build Coastguard Worker  * integer array. Ownership of the array is not transferred.
53*be431cd8SAndroid Build Coastguard Worker  * @param handle_n_ints The corresponding length.
54*be431cd8SAndroid Build Coastguard Worker  * @param quantum The MQDescriptor's quantum.
55*be431cd8SAndroid Build Coastguard Worker  * @param flags The MQDescriptor's flags.
56*be431cd8SAndroid Build Coastguard Worker  *
57*be431cd8SAndroid Build Coastguard Worker  * @return A heap-allocated ErasedMessageQueueDesc instance owned by the caller,
58*be431cd8SAndroid Build Coastguard Worker  * which must be freed with freeDesc.
59*be431cd8SAndroid Build Coastguard Worker  */
60*be431cd8SAndroid Build Coastguard Worker ErasedMessageQueueDesc* convertDesc(const GrantorDescriptor* grantors, size_t n_grantors,
61*be431cd8SAndroid Build Coastguard Worker                                     const int* handle_fds, size_t handle_n_fds,
62*be431cd8SAndroid Build Coastguard Worker                                     const int32_t* handle_ints, size_t handle_n_ints,
63*be431cd8SAndroid Build Coastguard Worker                                     int32_t quantum, int32_t flags);
64*be431cd8SAndroid Build Coastguard Worker 
65*be431cd8SAndroid Build Coastguard Worker /**
66*be431cd8SAndroid Build Coastguard Worker  * Free a heap-allocated ErasedMessageQueueDesc. Simply calls delete.
67*be431cd8SAndroid Build Coastguard Worker  *
68*be431cd8SAndroid Build Coastguard Worker  * @param desc The ErasedMessageQueueDesc to free.
69*be431cd8SAndroid Build Coastguard Worker  */
70*be431cd8SAndroid Build Coastguard Worker void freeDesc(ErasedMessageQueueDesc* desc);
71*be431cd8SAndroid Build Coastguard Worker 
72*be431cd8SAndroid Build Coastguard Worker /**
73*be431cd8SAndroid Build Coastguard Worker  * The following functions project out individual fields of an
74*be431cd8SAndroid Build Coastguard Worker  * ErasedMessageQueueDesc as FFI-safe types to enable constructing a Rust AIDL
75*be431cd8SAndroid Build Coastguard Worker  * MQDescriptor<MQErased, SynchronizedReadWrite> from a C++ AIDL one. See the
76*be431cd8SAndroid Build Coastguard Worker  * Rust MessageQueue<T>::dupe_desc method.
77*be431cd8SAndroid Build Coastguard Worker  */
78*be431cd8SAndroid Build Coastguard Worker 
79*be431cd8SAndroid Build Coastguard Worker const GrantorDescriptor* descGrantors(const ErasedMessageQueueDesc& desc);
80*be431cd8SAndroid Build Coastguard Worker size_t descNumGrantors(const ErasedMessageQueueDesc& desc);
81*be431cd8SAndroid Build Coastguard Worker const ndk::ScopedFileDescriptor* descHandleFDs(const ErasedMessageQueueDesc& desc);
82*be431cd8SAndroid Build Coastguard Worker size_t descHandleNumFDs(const ErasedMessageQueueDesc& desc);
83*be431cd8SAndroid Build Coastguard Worker const int* descHandleInts(const ErasedMessageQueueDesc& desc);
84*be431cd8SAndroid Build Coastguard Worker size_t descHandleNumInts(const ErasedMessageQueueDesc& desc);
85*be431cd8SAndroid Build Coastguard Worker int32_t descQuantum(const ErasedMessageQueueDesc& desc);
86*be431cd8SAndroid Build Coastguard Worker int32_t descFlags(const ErasedMessageQueueDesc& desc);
87*be431cd8SAndroid Build Coastguard Worker 
88*be431cd8SAndroid Build Coastguard Worker /**
89*be431cd8SAndroid Build Coastguard Worker  * ErasedMessageQueue is a monomorphized wrapper around AidlMessageQueue that lets
90*be431cd8SAndroid Build Coastguard Worker  * us wrap it in an idiomatic Rust API. It does not statically know its element
91*be431cd8SAndroid Build Coastguard Worker  * type, but treats elements as opaque objects whose size is given by the
92*be431cd8SAndroid Build Coastguard Worker  * MQDescriptor.
93*be431cd8SAndroid Build Coastguard Worker  */
94*be431cd8SAndroid Build Coastguard Worker class ErasedMessageQueue {
95*be431cd8SAndroid Build Coastguard Worker     /* This must be a unique_ptr because bindgen cannot handle by-value fields
96*be431cd8SAndroid Build Coastguard Worker      * of template class type. */
97*be431cd8SAndroid Build Coastguard Worker     std::unique_ptr<AidlMessageQueue<MQErased, SynchronizedReadWrite>> inner;
98*be431cd8SAndroid Build Coastguard Worker 
99*be431cd8SAndroid Build Coastguard Worker   public:
100*be431cd8SAndroid Build Coastguard Worker     ErasedMessageQueue(const ErasedMessageQueueDesc& desc, bool resetPointers = true);
101*be431cd8SAndroid Build Coastguard Worker     ErasedMessageQueue(size_t numElementsInQueue, bool configureEventFlagWord, size_t quantum);
102*be431cd8SAndroid Build Coastguard Worker 
103*be431cd8SAndroid Build Coastguard Worker     /**
104*be431cd8SAndroid Build Coastguard Worker      * Get a MemTransaction object to write `nMessages` elements.
105*be431cd8SAndroid Build Coastguard Worker      * Once the write is performed using the information from MemTransaction,
106*be431cd8SAndroid Build Coastguard Worker      * the write operation is to be committed using a call to commitWrite().
107*be431cd8SAndroid Build Coastguard Worker      *
108*be431cd8SAndroid Build Coastguard Worker      * @param nMessages Number of messages of the element type.
109*be431cd8SAndroid Build Coastguard Worker      * @param Pointer to MemTransaction struct that describes memory to write
110*be431cd8SAndroid Build Coastguard Worker      * `nMessages` items of the element type. If a write of size `nMessages` is
111*be431cd8SAndroid Build Coastguard Worker      * not possible, the base addresses in the `MemTransaction` object will be
112*be431cd8SAndroid Build Coastguard Worker      * set to nullptr.
113*be431cd8SAndroid Build Coastguard Worker      *
114*be431cd8SAndroid Build Coastguard Worker      * @return Whether it is possible to write `nMessages` items into the FMQ.
115*be431cd8SAndroid Build Coastguard Worker      */
116*be431cd8SAndroid Build Coastguard Worker     bool beginWrite(size_t nMessages, MemTransaction* memTx) const;
117*be431cd8SAndroid Build Coastguard Worker 
118*be431cd8SAndroid Build Coastguard Worker     /**
119*be431cd8SAndroid Build Coastguard Worker      * Commit a write of size `nMessages`. To be only used after a call to
120*be431cd8SAndroid Build Coastguard Worker      * `beginWrite()`.
121*be431cd8SAndroid Build Coastguard Worker      *
122*be431cd8SAndroid Build Coastguard Worker      * @param nMessages number of messages of the element type to be written.
123*be431cd8SAndroid Build Coastguard Worker      *
124*be431cd8SAndroid Build Coastguard Worker      * @return Whether the write operation of size `nMessages` succeeded.
125*be431cd8SAndroid Build Coastguard Worker      */
126*be431cd8SAndroid Build Coastguard Worker     bool commitWrite(size_t nMessages);
127*be431cd8SAndroid Build Coastguard Worker 
128*be431cd8SAndroid Build Coastguard Worker     /**
129*be431cd8SAndroid Build Coastguard Worker      * Get a MemTransaction object to read `nMessages` elements.
130*be431cd8SAndroid Build Coastguard Worker      * Once the read is performed using the information from MemTransaction,
131*be431cd8SAndroid Build Coastguard Worker      * the read operation is to be committed using a call to `commitRead()`.
132*be431cd8SAndroid Build Coastguard Worker      *
133*be431cd8SAndroid Build Coastguard Worker      * @param nMessages Number of messages of the element type.
134*be431cd8SAndroid Build Coastguard Worker      * @param pointer to MemTransaction struct that describes memory to read
135*be431cd8SAndroid Build Coastguard Worker      * `nMessages` items of the element type. If a read of size `nMessages` is
136*be431cd8SAndroid Build Coastguard Worker      * not possible, the base pointers in the `MemTransaction` object returned
137*be431cd8SAndroid Build Coastguard Worker      * will be set to nullptr.
138*be431cd8SAndroid Build Coastguard Worker      *
139*be431cd8SAndroid Build Coastguard Worker      * @return bool Whether it is possible to read `nMessages` items from the
140*be431cd8SAndroid Build Coastguard Worker      * FMQ.
141*be431cd8SAndroid Build Coastguard Worker      */
142*be431cd8SAndroid Build Coastguard Worker     bool beginRead(size_t nMessages, MemTransaction* memTx) const;
143*be431cd8SAndroid Build Coastguard Worker 
144*be431cd8SAndroid Build Coastguard Worker     /**
145*be431cd8SAndroid Build Coastguard Worker      * Commit a read of size `nMessages`. To be only used after a call to
146*be431cd8SAndroid Build Coastguard Worker      * `beginRead()`.
147*be431cd8SAndroid Build Coastguard Worker      *
148*be431cd8SAndroid Build Coastguard Worker      * @param nMessages number of messages of the element type to be read.
149*be431cd8SAndroid Build Coastguard Worker      *
150*be431cd8SAndroid Build Coastguard Worker      * @return bool Whether the read operation of size `nMessages` succeeded.
151*be431cd8SAndroid Build Coastguard Worker      */
152*be431cd8SAndroid Build Coastguard Worker     bool commitRead(size_t nMessages);
153*be431cd8SAndroid Build Coastguard Worker 
154*be431cd8SAndroid Build Coastguard Worker     /**
155*be431cd8SAndroid Build Coastguard Worker      * Create a copy of the MQDescriptor for this object. This descriptor can be
156*be431cd8SAndroid Build Coastguard Worker      * sent over IPC to allow constructing a remote object that will access the
157*be431cd8SAndroid Build Coastguard Worker      * same queue over shared memory.
158*be431cd8SAndroid Build Coastguard Worker      *
159*be431cd8SAndroid Build Coastguard Worker      * @return ErasedMessageQueueDesc The copied descriptor, which must be freed
160*be431cd8SAndroid Build Coastguard Worker      * by passing it to freeDesc.
161*be431cd8SAndroid Build Coastguard Worker      */
162*be431cd8SAndroid Build Coastguard Worker     ErasedMessageQueueDesc* dupeDesc() const;
163*be431cd8SAndroid Build Coastguard Worker };
164