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