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