• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 .
25  */
26 
27 #pragma once
28 
29 #include <android/binder_ibinder.h>
30 #include <android/binder_parcel.h>
31 #include <android/binder_status.h>
32 
33 #include <assert.h>
34 
35 #include <unistd.h>
36 #include <cstddef>
37 
38 namespace ndk {
39 
40 /**
41  * Represents one strong pointer to an AIBinder object.
42  */
43 class SpAIBinder {
44    public:
45     /**
46      * Takes ownership of one strong refcount of binder.
47      */
mBinder(binder)48     explicit SpAIBinder(AIBinder* binder = nullptr) : mBinder(binder) {}
49 
50     /**
51      * Convenience operator for implicitly constructing an SpAIBinder from nullptr. This is not
52      * explicit because it is not taking ownership of anything.
53      */
SpAIBinder(std::nullptr_t)54     SpAIBinder(std::nullptr_t) : SpAIBinder() {}  // NOLINT(google-explicit-constructor)
55 
56     /**
57      * This will delete the underlying object if it exists. See operator=.
58      */
SpAIBinder(const SpAIBinder & other)59     SpAIBinder(const SpAIBinder& other) { *this = other; }
60 
61     /**
62      * This deletes the underlying object if it exists. See set.
63      */
~SpAIBinder()64     ~SpAIBinder() { set(nullptr); }
65 
66     /**
67      * This takes ownership of a binder from another AIBinder object but it does not affect the
68      * ownership of that other object.
69      */
70     SpAIBinder& operator=(const SpAIBinder& other) {
71         AIBinder_incStrong(other.mBinder);
72         set(other.mBinder);
73         return *this;
74     }
75 
76     /**
77      * Takes ownership of one strong refcount of binder
78      */
set(AIBinder * binder)79     void set(AIBinder* binder) {
80         AIBinder* old = *const_cast<AIBinder* volatile*>(&mBinder);
81         if (old != nullptr) AIBinder_decStrong(old);
82         if (old != *const_cast<AIBinder* volatile*>(&mBinder)) {
83             __assert(__FILE__, __LINE__, "Race detected.");
84         }
85         mBinder = binder;
86     }
87 
88     /**
89      * This returns the underlying binder object for transactions. If it is used to create another
90      * SpAIBinder object, it should first be incremented.
91      */
get()92     AIBinder* get() const { return mBinder; }
93 
94     /**
95      * This allows the value in this class to be set from beneath it. If you call this method and
96      * then change the value of T*, you must take ownership of the value you are replacing and add
97      * ownership to the object that is put in here.
98      *
99      * Recommended use is like this:
100      *   SpAIBinder a;  // will be nullptr
101      *   SomeInitFunction(a.getR());  // value is initialized with refcount
102      *
103      * Other usecases are discouraged.
104      *
105      */
getR()106     AIBinder** getR() { return &mBinder; }
107 
108    private:
109     AIBinder* mBinder = nullptr;
110 };
111 
112 namespace impl {
113 
114 /**
115  * This baseclass owns a single object, used to make various classes RAII.
116  */
117 template <typename T, typename R, R (*Destroy)(T), T DEFAULT>
118 class ScopedAResource {
119    public:
120     /**
121      * Takes ownership of t.
122      */
mT(t)123     explicit ScopedAResource(T t = DEFAULT) : mT(t) {}
124 
125     /**
126      * This deletes the underlying object if it exists. See set.
127      */
~ScopedAResource()128     ~ScopedAResource() { set(DEFAULT); }
129 
130     /**
131      * Takes ownership of t.
132      */
set(T t)133     void set(T t) {
134         Destroy(mT);
135         mT = t;
136     }
137 
138     /**
139      * This returns the underlying object to be modified but does not affect ownership.
140      */
get()141     T get() { return mT; }
142 
143     /**
144      * This returns the const underlying object but does not affect ownership.
145      */
get()146     const T get() const { return mT; }
147 
148     /**
149      * This allows the value in this class to be set from beneath it. If you call this method and
150      * then change the value of T*, you must take ownership of the value you are replacing and add
151      * ownership to the object that is put in here.
152      *
153      * Recommended use is like this:
154      *   ScopedAResource<T> a; // will be nullptr
155      *   SomeInitFunction(a.getR()); // value is initialized with refcount
156      *
157      * Other usecases are discouraged.
158      *
159      */
getR()160     T* getR() { return &mT; }
161 
162     // copy-constructing, or move/copy assignment is disallowed
163     ScopedAResource(const ScopedAResource&) = delete;
164     ScopedAResource& operator=(const ScopedAResource&) = delete;
165     ScopedAResource& operator=(ScopedAResource&&) = delete;
166 
167     // move-constructing is okay
ScopedAResource(ScopedAResource && other)168     ScopedAResource(ScopedAResource&& other) : mT(std::move(other.mT)) { other.mT = DEFAULT; }
169 
170    private:
171     T mT;
172 };
173 
174 }  // namespace impl
175 
176 /**
177  * Convenience wrapper. See AParcel.
178  */
179 class ScopedAParcel : public impl::ScopedAResource<AParcel*, void, AParcel_delete, nullptr> {
180    public:
181     /**
182      * Takes ownership of a.
183      */
ScopedAResource(a)184     explicit ScopedAParcel(AParcel* a = nullptr) : ScopedAResource(a) {}
~ScopedAParcel()185     ~ScopedAParcel() {}
186     ScopedAParcel(ScopedAParcel&&) = default;
187 };
188 
189 /**
190  * Convenience wrapper. See AStatus.
191  */
192 class ScopedAStatus : public impl::ScopedAResource<AStatus*, void, AStatus_delete, nullptr> {
193    public:
194     /**
195      * Takes ownership of a.
196      */
ScopedAResource(a)197     explicit ScopedAStatus(AStatus* a = nullptr) : ScopedAResource(a) {}
~ScopedAStatus()198     ~ScopedAStatus() {}
199     ScopedAStatus(ScopedAStatus&&) = default;
200 
201     /**
202      * See AStatus_isOk.
203      */
isOk()204     bool isOk() { return get() != nullptr && AStatus_isOk(get()); }
205 
206     /**
207      * Convenience method for okay status.
208      */
ok()209     static ScopedAStatus ok() { return ScopedAStatus(AStatus_newOk()); }
210 };
211 
212 /**
213  * Convenience wrapper. See AIBinder_DeathRecipient.
214  */
215 class ScopedAIBinder_DeathRecipient
216     : public impl::ScopedAResource<AIBinder_DeathRecipient*, void, AIBinder_DeathRecipient_delete,
217                                    nullptr> {
218    public:
219     /**
220      * Takes ownership of a.
221      */
222     explicit ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient* a = nullptr)
ScopedAResource(a)223         : ScopedAResource(a) {}
~ScopedAIBinder_DeathRecipient()224     ~ScopedAIBinder_DeathRecipient() {}
225     ScopedAIBinder_DeathRecipient(ScopedAIBinder_DeathRecipient&&) = default;
226 };
227 
228 /**
229  * Convenience wrapper. See AIBinder_Weak.
230  */
231 class ScopedAIBinder_Weak
232     : public impl::ScopedAResource<AIBinder_Weak*, void, AIBinder_Weak_delete, nullptr> {
233    public:
234     /**
235      * Takes ownership of a.
236      */
ScopedAResource(a)237     explicit ScopedAIBinder_Weak(AIBinder_Weak* a = nullptr) : ScopedAResource(a) {}
~ScopedAIBinder_Weak()238     ~ScopedAIBinder_Weak() {}
239     ScopedAIBinder_Weak(ScopedAIBinder_Weak&&) = default;
240 
241     /**
242      * See AIBinder_Weak_promote.
243      */
promote()244     SpAIBinder promote() { return SpAIBinder(AIBinder_Weak_promote(get())); }
245 };
246 
247 /**
248  * Convenience wrapper for a file descriptor.
249  */
250 class ScopedFileDescriptor : public impl::ScopedAResource<int, int, close, -1> {
251    public:
252     /**
253      * Takes ownership of a.
254      */
ScopedAResource(a)255     explicit ScopedFileDescriptor(int a = -1) : ScopedAResource(a) {}
~ScopedFileDescriptor()256     ~ScopedFileDescriptor() {}
257     ScopedFileDescriptor(ScopedFileDescriptor&&) = default;
258 };
259 
260 }  // namespace ndk
261 
262 /** @} */
263