1 /* 2 * Copyright 2022 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 /** 18 * @file hardware_buffer_aidl.h 19 * @brief HardwareBuffer NDK AIDL glue code 20 */ 21 22 /** 23 * @addtogroup AHardwareBuffer 24 * 25 * Parcelable support for AHardwareBuffer. Can be used with libbinder_ndk 26 * 27 * @{ 28 */ 29 30 #ifndef ANDROID_HARDWARE_BUFFER_AIDL_H 31 #define ANDROID_HARDWARE_BUFFER_AIDL_H 32 33 #include <android/binder_parcel.h> 34 #include <android/hardware_buffer.h> 35 #include <sys/cdefs.h> 36 37 #ifdef __cplusplus 38 #include <string> 39 #endif 40 41 __BEGIN_DECLS 42 43 /** 44 * Read an AHardwareBuffer from a AParcel. The output buffer will have an 45 * initial reference acquired and will need to be released with 46 * AHardwareBuffer_release. 47 * 48 * Available since API level 34. 49 * 50 * \return STATUS_OK on success 51 * STATUS_BAD_VALUE if the parcel or outBuffer is null, or if there's an 52 * issue deserializing (eg, corrupted parcel) 53 * STATUS_BAD_TYPE if the parcel's current data position is not that of 54 * an AHardwareBuffer type 55 * STATUS_NO_MEMORY if an allocation fails 56 */ 57 binder_status_t AHardwareBuffer_readFromParcel(const AParcel* _Nonnull parcel, 58 AHardwareBuffer* _Nullable* _Nonnull outBuffer) __INTRODUCED_IN(34); 59 60 /** 61 * Write an AHardwareBuffer to an AParcel. 62 * 63 * Available since API level 34. 64 * 65 * \return STATUS_OK on success. 66 * STATUS_BAD_VALUE if either buffer or parcel is null, or if the AHardwareBuffer* 67 * fails to serialize (eg, internally corrupted) 68 * STATUS_NO_MEMORY if the parcel runs out of space to store the buffer & is 69 * unable to allocate more 70 * STATUS_FDS_NOT_ALLOWED if the parcel does not allow storing FDs 71 */ 72 binder_status_t AHardwareBuffer_writeToParcel(const AHardwareBuffer* _Nonnull buffer, 73 AParcel* _Nonnull parcel) __INTRODUCED_IN(34); 74 75 __END_DECLS 76 77 // Only enable the AIDL glue helper if this is C++ 78 #ifdef __cplusplus 79 80 namespace aidl::android::hardware { 81 82 /** 83 * Wrapper class that enables interop with AIDL NDK generation 84 * Takes ownership of the AHardwareBuffer* given to it in reset() and will automatically 85 * destroy it in the destructor, similar to a smart pointer container 86 */ 87 class HardwareBuffer { 88 public: HardwareBuffer()89 HardwareBuffer() noexcept {} HardwareBuffer(HardwareBuffer && other)90 HardwareBuffer(HardwareBuffer&& other) noexcept : mBuffer(other.release()) {} 91 ~HardwareBuffer()92 ~HardwareBuffer() { 93 reset(); 94 } 95 readFromParcel(const AParcel * _Nonnull parcel)96 binder_status_t readFromParcel(const AParcel* _Nonnull parcel) { 97 reset(); 98 if (__builtin_available(android __ANDROID_API_U__, *)) { 99 return AHardwareBuffer_readFromParcel(parcel, &mBuffer); 100 } else { 101 return STATUS_FAILED_TRANSACTION; 102 } 103 } 104 writeToParcel(AParcel * _Nonnull parcel)105 binder_status_t writeToParcel(AParcel* _Nonnull parcel) const { 106 if (!mBuffer) { 107 return STATUS_BAD_VALUE; 108 } 109 if (__builtin_available(android __ANDROID_API_U__, *)) { 110 return AHardwareBuffer_writeToParcel(mBuffer, parcel); 111 } else { 112 return STATUS_FAILED_TRANSACTION; 113 } 114 } 115 116 /** 117 * Destroys any currently owned AHardwareBuffer* and takes ownership of the given 118 * AHardwareBuffer* 119 * 120 * @param buffer The buffer to take ownership of 121 */ 122 void reset(AHardwareBuffer* _Nullable buffer = nullptr) noexcept { 123 if (mBuffer) { 124 AHardwareBuffer_release(mBuffer); 125 mBuffer = nullptr; 126 } 127 mBuffer = buffer; 128 } 129 130 inline AHardwareBuffer* _Nullable operator-> () const { return mBuffer; } get()131 inline AHardwareBuffer* _Nullable get() const { return mBuffer; } 132 inline explicit operator bool () const { return mBuffer != nullptr; } 133 134 inline bool operator!=(const HardwareBuffer& rhs) const { return get() != rhs.get(); } 135 inline bool operator<(const HardwareBuffer& rhs) const { return get() < rhs.get(); } 136 inline bool operator<=(const HardwareBuffer& rhs) const { return get() <= rhs.get(); } 137 inline bool operator==(const HardwareBuffer& rhs) const { return get() == rhs.get(); } 138 inline bool operator>(const HardwareBuffer& rhs) const { return get() > rhs.get(); } 139 inline bool operator>=(const HardwareBuffer& rhs) const { return get() >= rhs.get(); } 140 141 HardwareBuffer& operator=(HardwareBuffer&& other) noexcept { 142 reset(other.release()); 143 return *this; 144 } 145 146 /** 147 * Stops managing any contained AHardwareBuffer*, returning it to the caller. Ownership 148 * is released. 149 * @return AHardwareBuffer* or null if this was empty 150 */ release()151 [[nodiscard]] AHardwareBuffer* _Nullable release() noexcept { 152 AHardwareBuffer* _Nullable ret = mBuffer; 153 mBuffer = nullptr; 154 return ret; 155 } 156 toString()157 inline std::string toString() const { 158 if (!mBuffer) { 159 return "<HardwareBuffer: Invalid>"; 160 } 161 if (__builtin_available(android __ANDROID_API_S__, *)) { 162 uint64_t id = 0; 163 AHardwareBuffer_getId(mBuffer, &id); 164 return "<HardwareBuffer " + std::to_string(id) + ">"; 165 } else { 166 return "<HardwareBuffer (unknown)>"; 167 } 168 } 169 170 private: 171 HardwareBuffer(const HardwareBuffer& other) = delete; 172 HardwareBuffer& operator=(const HardwareBuffer& other) = delete; 173 174 AHardwareBuffer* _Nullable mBuffer = nullptr; 175 }; 176 177 } // aidl::android::hardware 178 179 #endif // __cplusplus 180 181 #endif // ANDROID_HARDWARE_BUFFER_AIDL_H 182 183 /** @} */ 184