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