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