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