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