1 /*
2  * Copyright (C) 2018 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  * @addtogroup NdkBinder
19  * @{
20  */
21 
22 /**
23  * @file binder_auto_utils.h
24  * @brief These objects provide a more C++-like thin interface to the binder.
25  */
26 
27 #pragma once
28 
29 #include <android/binder_ibinder.h>
30 #include <android/binder_internal_logging.h>
31 #include <android/binder_parcel.h>
32 #include <android/binder_status.h>
33 #include <assert.h>
34 #include <string.h>
35 #include <unistd.h>
36 
37 #include <cstddef>
38 #include <iostream>
39 #include <string>
40 
41 namespace ndk {
42 
43 /**
44  * Represents one strong pointer to an AIBinder object.
45  */
46 class SpAIBinder {
47    public:
48     /**
49      * Default constructor.
50      */
SpAIBinder()51     SpAIBinder() : mBinder(nullptr) {}
52 
53     /**
54      * Takes ownership of one strong refcount of binder.
55      */
SpAIBinder(AIBinder * binder)56     explicit SpAIBinder(AIBinder* binder) : mBinder(binder) {}
57 
58     /**
59      * Convenience operator for implicitly constructing an SpAIBinder from nullptr. This is not
60      * explicit because it is not taking ownership of anything.
61      */
SpAIBinder(std::nullptr_t)62     SpAIBinder(std::nullptr_t) : SpAIBinder() {}  // NOLINT(google-explicit-constructor)
63 
64     /**
65      * This will delete the underlying object if it exists. See operator=.
66      */
SpAIBinder(const SpAIBinder & other)67     SpAIBinder(const SpAIBinder& other) { *this = other; }
68 
69     /**
70      * This deletes the underlying object if it exists. See set.
71      */
~SpAIBinder()72     ~SpAIBinder() { set(nullptr); }
73 
74     /**
75      * This takes ownership of a binder from another AIBinder object but it does not affect the
76      * ownership of that other object.
77      */
78     SpAIBinder& operator=(const SpAIBinder& other) {
79         if (this == &other) {
80             return *this;
81         }
82         AIBinder_incStrong(other.mBinder);
83         set(other.mBinder);
84         return *this;
85     }
86 
87     /**
88      * Takes ownership of one strong refcount of binder
89      */
set(AIBinder * binder)90     void set(AIBinder* binder) {
91         AIBinder* old = *const_cast<AIBinder* volatile*>(&mBinder);
92         if (old != nullptr) AIBinder_decStrong(old);
93         if (old != *const_cast<AIBinder* volatile*>(&mBinder)) {
94             __assert(__FILE__, __LINE__, "Race detected.");
95         }
96         mBinder = binder;
97     }
98 
99     /**
100      * This returns the underlying binder object for transactions. If it is used to create another
101      * SpAIBinder object, it should first be incremented.
102      */
get()103     AIBinder* get() const { return mBinder; }
104 
105     /**
106      * This allows the value in this class to be set from beneath it. If you call this method and
107      * then change the value of T*, you must take ownership of the value you are replacing and add
108      * ownership to the object that is put in here.
109      *
110      * Recommended use is like this:
111      *   SpAIBinder a;  // will be nullptr
112      *   SomeInitFunction(a.getR());  // value is initialized with refcount
113      *
114      * Other usecases are discouraged.
115      *
116      */
getR()117     AIBinder** getR() { return &mBinder; }
118 
119    private:
120     AIBinder* mBinder = nullptr;
121 };
122 
123 #define SP_AIBINDER_COMPARE(_op_)                                                    \
124     static inline bool operator _op_(const SpAIBinder& lhs, const SpAIBinder& rhs) { \
125         return lhs.get() _op_ rhs.get();                                             \
126     }                                                                                \
127     static inline bool operator _op_(const SpAIBinder& lhs, const AIBinder* rhs) {   \
128         return lhs.get() _op_ rhs;                                                   \
129     }                                                                                \
130     static inline bool operator _op_(const AIBinder* lhs, const SpAIBinder& rhs) {   \
131         return lhs _op_ rhs.get();                                                   \
132     }
133 
134 SP_AIBINDER_COMPARE(!=)
135 SP_AIBINDER_COMPARE(<)
136 SP_AIBINDER_COMPARE(<=)
137 SP_AIBINDER_COMPARE(==)
138 SP_AIBINDER_COMPARE(>)
139 SP_AIBINDER_COMPARE(>=)
140 #undef SP_AIBINDER_COMPARE
141 
142 namespace impl {
143 
144 /**
145  * This baseclass owns a single object, used to make various classes RAII.
146  */
147 template <typename T, void (*Destroy)(T), T DEFAULT>
148 class ScopedAResource {
149    public:
150     /**
151      * Takes ownership of t.
152      */
mT(t)153     explicit ScopedAResource(T t = DEFAULT) : mT(t) {}
154 
155     /**
156      * This deletes the underlying object if it exists. See set.
157      */
~ScopedAResource()158     ~ScopedAResource() { set(DEFAULT); }
159 
160     /**
161      * Takes ownership of t.
162      */
set(T t)163     void set(T t) {
164         Destroy(mT);
165         mT = t;
166     }
167 
168     /**
169      * This returns the underlying object to be modified but does not affect ownership.
170      */
get()171     T get() { return mT; }
172 
173     /**
174      * This returns the const underlying object but does not affect ownership.
175      */
get()176     const T get() const { return mT; }
177 
178     /**
179      * Release the underlying resource.
180      */
release()181     [[nodiscard]] T release() {
182         T a = mT;
183         mT = DEFAULT;
184         return a;
185     }
186 
187     /**
188      * This allows the value in this class to be set from beneath it. If you call this method and
189      * then change the value of T*, you must take ownership of the value you are replacing and add
190      * ownership to the object that is put in here.
191      *
192      * Recommended use is like this:
193      *   ScopedAResource<T> a; // will be nullptr
194      *   SomeInitFunction(a.getR()); // value is initialized with refcount
195      *
196      * Other usecases are discouraged.
197      *
198      */
getR()199     T* getR() { return &mT; }
200 
201     // copy-constructing/assignment is disallowed
202     ScopedAResource(const ScopedAResource&) = delete;
203     ScopedAResource& operator=(const ScopedAResource&) = delete;
204 
205     // move-constructing/assignment is okay
ScopedAResource(ScopedAResource && other)206     ScopedAResource(ScopedAResource&& other) noexcept : mT(std::move(other.mT)) {
207         other.mT = DEFAULT;
208     }
209     ScopedAResource& operator=(ScopedAResource&& other) noexcept {
210         set(other.mT);
211         other.mT = DEFAULT;
212         return *this;
213     }
214 
215    private:
216     T mT;
217 };
218 
219 }  // namespace impl
220 
221 /**
222  * Convenience wrapper. See AParcel.
223  */
224 class ScopedAParcel : public impl::ScopedAResource<AParcel*, AParcel_delete, nullptr> {
225    public:
226     /**
227      * Takes ownership of a.
228      */
ScopedAResource(a)229     explicit ScopedAParcel(AParcel* a = nullptr) : ScopedAResource(a) {}
~ScopedAParcel()230     ~ScopedAParcel() {}
231     ScopedAParcel(ScopedAParcel&&) = default;
232     ScopedAParcel& operator=(ScopedAParcel&&) = default;
233 
234     bool operator!=(const ScopedAParcel& rhs) const { return get() != rhs.get(); }
235     bool operator<(const ScopedAParcel& rhs) const { return get() < rhs.get(); }
236     bool operator<=(const ScopedAParcel& rhs) const { return get() <= rhs.get(); }
237     bool operator==(const ScopedAParcel& rhs) const { return get() == rhs.get(); }
238     bool operator>(const ScopedAParcel& rhs) const { return get() > rhs.get(); }
239     bool operator>=(const ScopedAParcel& rhs) const { return get() >= rhs.get(); }
240 };
241 
242 /**
243  * Convenience wrapper. See AStatus.
244  */
245 class ScopedAStatus : public impl::ScopedAResource<AStatus*, AStatus_delete, nullptr> {
246    public:
247     /**
248      * Takes ownership of a.
249      *
250      * WARNING: this constructor is only expected to be used when reading a
251      *     status value. Use `ScopedAStatus::ok()` instead.
252      */
ScopedAResource(a)253     explicit ScopedAStatus(AStatus* a = nullptr) : ScopedAResource(a) {}
~ScopedAStatus()254     ~ScopedAStatus() {}
255     ScopedAStatus(ScopedAStatus&&) = default;
256     ScopedAStatus& operator=(ScopedAStatus&&) = default;
257 
258     /**
259      * See AStatus_isOk.
260      */
isOk()261     bool isOk() const { return get() != nullptr && AStatus_isOk(get()); }
262 
263     /**
264      * See AStatus_getExceptionCode
265      */
getExceptionCode()266     binder_exception_t getExceptionCode() const { return AStatus_getExceptionCode(get()); }
267 
268     /**
269      * See AStatus_getServiceSpecificError
270      */
getServiceSpecificError()271     int32_t getServiceSpecificError() const { return AStatus_getServiceSpecificError(get()); }
272 
273     /**
274      * See AStatus_getStatus
275      */
getStatus()276     binder_status_t getStatus() const { return AStatus_getStatus(get()); }
277 
278     /**
279      * See AStatus_getMessage
280      */
getMessage()281     const char* getMessage() const { return AStatus_getMessage(get()); }
282 
getDescription()283     std::string getDescription() const {
284 #ifdef __ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__
285         if (__builtin_available(android 30, *)) {
286 #endif
287 
288 #if defined(__ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__) || __ANDROID_API__ >= 30
289             const char* cStr = AStatus_getDescription(get());
290             std::string ret = cStr;
291             AStatus_deleteDescription(cStr);
292             return ret;
293 #endif
294 
295 #ifdef __ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__
296         }
297 #endif
298 
299         binder_exception_t exception = getExceptionCode();
300         std::string desc = std::to_string(exception);
301         if (exception == EX_SERVICE_SPECIFIC) {
302             desc += " (" + std::to_string(getServiceSpecificError()) + ")";
303         } else if (exception == EX_TRANSACTION_FAILED) {
304             desc += " (" + std::to_string(getStatus()) + ")";
305         }
306         if (const char* msg = getMessage(); msg != nullptr) {
307             desc += ": ";
308             desc += msg;
309         }
310         return desc;
311     }
312 
313     /**
314      * Convenience methods for creating scoped statuses.
315      */
ok()316     static ScopedAStatus ok() { return ScopedAStatus(AStatus_newOk()); }
fromExceptionCode(binder_exception_t exception)317     static ScopedAStatus fromExceptionCode(binder_exception_t exception) {
318         return ScopedAStatus(AStatus_fromExceptionCode(exception));
319     }
fromExceptionCodeWithMessage(binder_exception_t exception,const char * message)320     static ScopedAStatus fromExceptionCodeWithMessage(binder_exception_t exception,
321                                                       const char* message) {
322         return ScopedAStatus(AStatus_fromExceptionCodeWithMessage(exception, message));
323     }
fromServiceSpecificError(int32_t serviceSpecific)324     static ScopedAStatus fromServiceSpecificError(int32_t serviceSpecific) {
325         return ScopedAStatus(AStatus_fromServiceSpecificError(serviceSpecific));
326     }
fromServiceSpecificErrorWithMessage(int32_t serviceSpecific,const char * message)327     static ScopedAStatus fromServiceSpecificErrorWithMessage(int32_t serviceSpecific,
328                                                              const char* message) {
329         return ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(serviceSpecific, message));
330     }
fromStatus(binder_status_t status)331     static ScopedAStatus fromStatus(binder_status_t status) {
332         return ScopedAStatus(AStatus_fromStatus(status));
333     }
334 };
335 
336 static inline std::ostream& operator<<(std::ostream& os, const ScopedAStatus& status) {
337     return os << status.getDescription();
338     return os;
339 }
340 
341 /**
342  * Convenience wrapper. See AIBinder_DeathRecipient.
343  */
344 class ScopedAIBinder_DeathRecipient
345     : public impl::ScopedAResource<AIBinder_DeathRecipient*, AIBinder_DeathRecipient_delete,
346                                    nullptr> {
347    public:
348     /**
349      * Takes ownership of a.
350      */
351     explicit ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient* a = nullptr)
ScopedAResource(a)352         : ScopedAResource(a) {}
~ScopedAIBinder_DeathRecipient()353     ~ScopedAIBinder_DeathRecipient() {}
354     ScopedAIBinder_DeathRecipient(ScopedAIBinder_DeathRecipient&&) = default;
355     ScopedAIBinder_DeathRecipient& operator=(ScopedAIBinder_DeathRecipient&&) = default;
356 };
357 
358 /**
359  * Convenience wrapper. See AIBinder_Weak.
360  */
361 class ScopedAIBinder_Weak
362     : public impl::ScopedAResource<AIBinder_Weak*, AIBinder_Weak_delete, nullptr> {
363    public:
364     /**
365      * Takes ownership of a.
366      */
ScopedAResource(a)367     explicit ScopedAIBinder_Weak(AIBinder_Weak* a = nullptr) : ScopedAResource(a) {}
~ScopedAIBinder_Weak()368     ~ScopedAIBinder_Weak() {}
369     ScopedAIBinder_Weak(ScopedAIBinder_Weak&&) = default;
370     ScopedAIBinder_Weak& operator=(ScopedAIBinder_Weak&&) = default;
371 
372     /**
373      * See AIBinder_Weak_promote.
374      */
promote()375     SpAIBinder promote() const { return SpAIBinder(AIBinder_Weak_promote(get())); }
376 };
377 
378 namespace internal {
379 
closeWithError(int fd)380 inline void closeWithError(int fd) {
381     if (fd == -1) return;
382     int ret = close(fd);
383     if (ret != 0) {
384         syslog(LOG_ERR, "Could not close FD %d: %s", fd, strerror(errno));
385     }
386 }
387 
388 }  // namespace internal
389 
390 /**
391  * Convenience wrapper for a file descriptor.
392  */
393 class ScopedFileDescriptor : public impl::ScopedAResource<int, internal::closeWithError, -1> {
394    public:
395     /**
396      * Takes ownership of a.
397      */
ScopedFileDescriptor()398     ScopedFileDescriptor() : ScopedFileDescriptor(-1) {}
ScopedFileDescriptor(int a)399     explicit ScopedFileDescriptor(int a) : ScopedAResource(a) {}
~ScopedFileDescriptor()400     ~ScopedFileDescriptor() {}
401     ScopedFileDescriptor(ScopedFileDescriptor&&) = default;
402     ScopedFileDescriptor& operator=(ScopedFileDescriptor&&) = default;
403 
dup()404     ScopedFileDescriptor dup() const { return ScopedFileDescriptor(::dup(get())); }
405 
406     bool operator!=(const ScopedFileDescriptor& rhs) const { return get() != rhs.get(); }
407     bool operator<(const ScopedFileDescriptor& rhs) const { return get() < rhs.get(); }
408     bool operator<=(const ScopedFileDescriptor& rhs) const { return get() <= rhs.get(); }
409     bool operator==(const ScopedFileDescriptor& rhs) const { return get() == rhs.get(); }
410     bool operator>(const ScopedFileDescriptor& rhs) const { return get() > rhs.get(); }
411     bool operator>=(const ScopedFileDescriptor& rhs) const { return get() >= rhs.get(); }
412 };
413 
414 }  // namespace ndk
415 
416 /** @} */
417