blob: f59bb75cc1aa754f55293527fed7b51be268f734 [file] [log] [blame]
Steven Moreland2648d202018-08-28 01:23:02 -07001/*
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
Elliott Hughes05565472019-10-29 08:59:39 -070024 * @brief These objects provide a more C++-like thin interface to the binder.
Steven Moreland2648d202018-08-28 01:23:02 -070025 */
26
27#pragma once
28
29#include <android/binder_ibinder.h>
30#include <android/binder_parcel.h>
31#include <android/binder_status.h>
32
Steven Morelande97106a2018-10-08 17:53:48 -070033#include <assert.h>
Steven Moreland86ae9e72018-11-05 11:12:40 -080034
Steven Moreland063f2362018-10-18 12:49:11 -070035#include <unistd.h>
Steven Moreland2648d202018-08-28 01:23:02 -070036#include <cstddef>
Steven Moreland74772162019-12-11 16:42:43 -080037#include <string>
Steven Moreland2648d202018-08-28 01:23:02 -070038
Steven Moreland8b4f48a2018-10-08 14:30:42 -070039namespace ndk {
Steven Moreland2648d202018-08-28 01:23:02 -070040
41/**
42 * Represents one strong pointer to an AIBinder object.
43 */
Steven Moreland8b4f48a2018-10-08 14:30:42 -070044class SpAIBinder {
Steven Moreland6cf66ac2018-11-02 18:14:54 -070045 public:
Steven Moreland2648d202018-08-28 01:23:02 -070046 /**
47 * Takes ownership of one strong refcount of binder.
48 */
Steven Moreland8b4f48a2018-10-08 14:30:42 -070049 explicit SpAIBinder(AIBinder* binder = nullptr) : mBinder(binder) {}
Steven Moreland2648d202018-08-28 01:23:02 -070050
51 /**
Steven Moreland8b4f48a2018-10-08 14:30:42 -070052 * Convenience operator for implicitly constructing an SpAIBinder from nullptr. This is not
Steven Moreland2648d202018-08-28 01:23:02 -070053 * explicit because it is not taking ownership of anything.
54 */
Chih-Hung Hsieh5ca1ea42018-12-20 15:42:22 -080055 SpAIBinder(std::nullptr_t) : SpAIBinder() {} // NOLINT(google-explicit-constructor)
Steven Moreland2648d202018-08-28 01:23:02 -070056
57 /**
58 * This will delete the underlying object if it exists. See operator=.
59 */
Steven Moreland8b4f48a2018-10-08 14:30:42 -070060 SpAIBinder(const SpAIBinder& other) { *this = other; }
Steven Moreland2648d202018-08-28 01:23:02 -070061
62 /**
63 * This deletes the underlying object if it exists. See set.
64 */
Steven Moreland8b4f48a2018-10-08 14:30:42 -070065 ~SpAIBinder() { set(nullptr); }
Steven Moreland2648d202018-08-28 01:23:02 -070066
67 /**
68 * This takes ownership of a binder from another AIBinder object but it does not affect the
69 * ownership of that other object.
70 */
Steven Moreland8b4f48a2018-10-08 14:30:42 -070071 SpAIBinder& operator=(const SpAIBinder& other) {
Steven Moreland2648d202018-08-28 01:23:02 -070072 AIBinder_incStrong(other.mBinder);
73 set(other.mBinder);
74 return *this;
75 }
76
77 /**
78 * Takes ownership of one strong refcount of binder
79 */
80 void set(AIBinder* binder) {
Steven Morelande97106a2018-10-08 17:53:48 -070081 AIBinder* old = *const_cast<AIBinder* volatile*>(&mBinder);
82 if (old != nullptr) AIBinder_decStrong(old);
83 if (old != *const_cast<AIBinder* volatile*>(&mBinder)) {
84 __assert(__FILE__, __LINE__, "Race detected.");
85 }
Steven Moreland2648d202018-08-28 01:23:02 -070086 mBinder = binder;
87 }
88
89 /**
90 * This returns the underlying binder object for transactions. If it is used to create another
Steven Moreland8b4f48a2018-10-08 14:30:42 -070091 * SpAIBinder object, it should first be incremented.
Steven Moreland2648d202018-08-28 01:23:02 -070092 */
93 AIBinder* get() const { return mBinder; }
94
95 /**
96 * This allows the value in this class to be set from beneath it. If you call this method and
97 * then change the value of T*, you must take ownership of the value you are replacing and add
98 * ownership to the object that is put in here.
99 *
100 * Recommended use is like this:
Steven Moreland8b4f48a2018-10-08 14:30:42 -0700101 * SpAIBinder a; // will be nullptr
Steven Moreland2648d202018-08-28 01:23:02 -0700102 * SomeInitFunction(a.getR()); // value is initialized with refcount
103 *
104 * Other usecases are discouraged.
105 *
106 */
107 AIBinder** getR() { return &mBinder; }
108
Steven Moreland6cf66ac2018-11-02 18:14:54 -0700109 private:
Steven Moreland2648d202018-08-28 01:23:02 -0700110 AIBinder* mBinder = nullptr;
111};
112
Steven Moreland26c4df12019-01-30 12:29:53 -0800113namespace impl {
114
Steven Moreland2648d202018-08-28 01:23:02 -0700115/**
116 * This baseclass owns a single object, used to make various classes RAII.
117 */
Steven Moreland063f2362018-10-18 12:49:11 -0700118template <typename T, typename R, R (*Destroy)(T), T DEFAULT>
Steven Moreland1630c192018-10-09 11:54:52 -0700119class ScopedAResource {
Steven Moreland6cf66ac2018-11-02 18:14:54 -0700120 public:
Steven Moreland2648d202018-08-28 01:23:02 -0700121 /**
122 * Takes ownership of t.
123 */
Steven Moreland063f2362018-10-18 12:49:11 -0700124 explicit ScopedAResource(T t = DEFAULT) : mT(t) {}
Steven Moreland2648d202018-08-28 01:23:02 -0700125
126 /**
127 * This deletes the underlying object if it exists. See set.
128 */
Steven Moreland063f2362018-10-18 12:49:11 -0700129 ~ScopedAResource() { set(DEFAULT); }
Steven Moreland2648d202018-08-28 01:23:02 -0700130
131 /**
132 * Takes ownership of t.
133 */
Steven Moreland063f2362018-10-18 12:49:11 -0700134 void set(T t) {
Steven Moreland2648d202018-08-28 01:23:02 -0700135 Destroy(mT);
136 mT = t;
137 }
138
139 /**
140 * This returns the underlying object to be modified but does not affect ownership.
141 */
Steven Moreland063f2362018-10-18 12:49:11 -0700142 T get() { return mT; }
Steven Moreland2648d202018-08-28 01:23:02 -0700143
144 /**
145 * This returns the const underlying object but does not affect ownership.
146 */
Steven Moreland063f2362018-10-18 12:49:11 -0700147 const T get() const { return mT; }
Steven Moreland2648d202018-08-28 01:23:02 -0700148
149 /**
150 * This allows the value in this class to be set from beneath it. If you call this method and
151 * then change the value of T*, you must take ownership of the value you are replacing and add
152 * ownership to the object that is put in here.
153 *
154 * Recommended use is like this:
Steven Moreland1630c192018-10-09 11:54:52 -0700155 * ScopedAResource<T> a; // will be nullptr
Steven Moreland2648d202018-08-28 01:23:02 -0700156 * SomeInitFunction(a.getR()); // value is initialized with refcount
157 *
158 * Other usecases are discouraged.
159 *
160 */
Steven Moreland063f2362018-10-18 12:49:11 -0700161 T* getR() { return &mT; }
Steven Moreland2648d202018-08-28 01:23:02 -0700162
Steven Morelandd329d052019-11-05 18:28:47 -0800163 // copy-constructing/assignment is disallowed
Steven Moreland1630c192018-10-09 11:54:52 -0700164 ScopedAResource(const ScopedAResource&) = delete;
165 ScopedAResource& operator=(const ScopedAResource&) = delete;
Steven Moreland2648d202018-08-28 01:23:02 -0700166
Steven Morelandd329d052019-11-05 18:28:47 -0800167 // move-constructing/assignment is okay
Steven Morelandcd056e42018-12-11 11:31:12 -0800168 ScopedAResource(ScopedAResource&& other) : mT(std::move(other.mT)) { other.mT = DEFAULT; }
Steven Morelandd329d052019-11-05 18:28:47 -0800169 ScopedAResource& operator=(ScopedAResource&& other) {
170 set(other.mT);
171 other.mT = DEFAULT;
172 return *this;
173 }
Steven Moreland2648d202018-08-28 01:23:02 -0700174
Steven Moreland6cf66ac2018-11-02 18:14:54 -0700175 private:
Steven Moreland063f2362018-10-18 12:49:11 -0700176 T mT;
Steven Moreland2648d202018-08-28 01:23:02 -0700177};
178
Steven Moreland26c4df12019-01-30 12:29:53 -0800179} // namespace impl
180
Steven Moreland2648d202018-08-28 01:23:02 -0700181/**
182 * Convenience wrapper. See AParcel.
183 */
Steven Moreland26c4df12019-01-30 12:29:53 -0800184class ScopedAParcel : public impl::ScopedAResource<AParcel*, void, AParcel_delete, nullptr> {
Steven Moreland6cf66ac2018-11-02 18:14:54 -0700185 public:
Steven Moreland2648d202018-08-28 01:23:02 -0700186 /**
187 * Takes ownership of a.
188 */
Steven Moreland1630c192018-10-09 11:54:52 -0700189 explicit ScopedAParcel(AParcel* a = nullptr) : ScopedAResource(a) {}
Steven Moreland8b4f48a2018-10-08 14:30:42 -0700190 ~ScopedAParcel() {}
191 ScopedAParcel(ScopedAParcel&&) = default;
Devin Moore02686ea2020-07-28 18:44:23 -0700192 ScopedAParcel& operator=(ScopedAParcel&&) = default;
Steven Moreland2648d202018-08-28 01:23:02 -0700193};
194
195/**
196 * Convenience wrapper. See AStatus.
197 */
Steven Moreland26c4df12019-01-30 12:29:53 -0800198class ScopedAStatus : public impl::ScopedAResource<AStatus*, void, AStatus_delete, nullptr> {
Steven Moreland6cf66ac2018-11-02 18:14:54 -0700199 public:
Steven Moreland2648d202018-08-28 01:23:02 -0700200 /**
201 * Takes ownership of a.
202 */
Steven Moreland1630c192018-10-09 11:54:52 -0700203 explicit ScopedAStatus(AStatus* a = nullptr) : ScopedAResource(a) {}
Steven Moreland8b4f48a2018-10-08 14:30:42 -0700204 ~ScopedAStatus() {}
205 ScopedAStatus(ScopedAStatus&&) = default;
Steven Morelandd329d052019-11-05 18:28:47 -0800206 ScopedAStatus& operator=(ScopedAStatus&&) = default;
Steven Moreland2648d202018-08-28 01:23:02 -0700207
208 /**
209 * See AStatus_isOk.
210 */
Steven Moreland190f4f22019-10-16 16:27:26 -0700211 bool isOk() const { return get() != nullptr && AStatus_isOk(get()); }
212
213 /**
214 * See AStatus_getExceptionCode
215 */
216 binder_exception_t getExceptionCode() const { return AStatus_getExceptionCode(get()); }
217
218 /**
219 * See AStatus_getServiceSpecificError
220 */
221 int32_t getServiceSpecificError() const { return AStatus_getServiceSpecificError(get()); }
222
223 /**
224 * See AStatus_getStatus
225 */
226 binder_status_t getStatus() const { return AStatus_getStatus(get()); }
Steven Moreland9450a482018-11-15 15:17:53 -0800227
228 /**
Steven Moreland09773672019-10-30 16:59:06 -0700229 * See AStatus_getMessage
230 */
231 const char* getMessage() const { return AStatus_getMessage(get()); }
232
Steven Moreland74772162019-12-11 16:42:43 -0800233 std::string getDescription() const {
234 const char* cStr = AStatus_getDescription(get());
235 std::string ret = cStr;
236 AStatus_deleteDescription(cStr);
237 return ret;
238 }
239
Steven Moreland09773672019-10-30 16:59:06 -0700240 /**
241 * Convenience methods for creating scoped statuses.
Steven Moreland9450a482018-11-15 15:17:53 -0800242 */
243 static ScopedAStatus ok() { return ScopedAStatus(AStatus_newOk()); }
Steven Moreland09773672019-10-30 16:59:06 -0700244 static ScopedAStatus fromExceptionCode(binder_exception_t exception) {
245 return ScopedAStatus(AStatus_fromExceptionCode(exception));
246 }
247 static ScopedAStatus fromExceptionCodeWithMessage(binder_exception_t exception,
248 const char* message) {
249 return ScopedAStatus(AStatus_fromExceptionCodeWithMessage(exception, message));
250 }
251 static ScopedAStatus fromServiceSpecificError(int32_t serviceSpecific) {
252 return ScopedAStatus(AStatus_fromServiceSpecificError(serviceSpecific));
253 }
254 static ScopedAStatus fromServiceSpecificErrorWithMessage(int32_t serviceSpecific,
255 const char* message) {
256 return ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(serviceSpecific, message));
257 }
258 static ScopedAStatus fromStatus(binder_status_t status) {
259 return ScopedAStatus(AStatus_fromStatus(status));
260 }
Steven Moreland2648d202018-08-28 01:23:02 -0700261};
262
263/**
264 * Convenience wrapper. See AIBinder_DeathRecipient.
265 */
Steven Moreland8b4f48a2018-10-08 14:30:42 -0700266class ScopedAIBinder_DeathRecipient
Steven Moreland26c4df12019-01-30 12:29:53 -0800267 : public impl::ScopedAResource<AIBinder_DeathRecipient*, void, AIBinder_DeathRecipient_delete,
268 nullptr> {
Steven Moreland6cf66ac2018-11-02 18:14:54 -0700269 public:
Steven Moreland2648d202018-08-28 01:23:02 -0700270 /**
271 * Takes ownership of a.
272 */
Steven Moreland1630c192018-10-09 11:54:52 -0700273 explicit ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient* a = nullptr)
Steven Moreland6cf66ac2018-11-02 18:14:54 -0700274 : ScopedAResource(a) {}
Steven Moreland8b4f48a2018-10-08 14:30:42 -0700275 ~ScopedAIBinder_DeathRecipient() {}
276 ScopedAIBinder_DeathRecipient(ScopedAIBinder_DeathRecipient&&) = default;
Devin Moore02686ea2020-07-28 18:44:23 -0700277 ScopedAIBinder_DeathRecipient& operator=(ScopedAIBinder_DeathRecipient&&) = default;
Steven Moreland2648d202018-08-28 01:23:02 -0700278};
279
280/**
281 * Convenience wrapper. See AIBinder_Weak.
282 */
Steven Moreland063f2362018-10-18 12:49:11 -0700283class ScopedAIBinder_Weak
Steven Moreland26c4df12019-01-30 12:29:53 -0800284 : public impl::ScopedAResource<AIBinder_Weak*, void, AIBinder_Weak_delete, nullptr> {
Steven Moreland6cf66ac2018-11-02 18:14:54 -0700285 public:
Steven Moreland2648d202018-08-28 01:23:02 -0700286 /**
287 * Takes ownership of a.
288 */
Steven Moreland1630c192018-10-09 11:54:52 -0700289 explicit ScopedAIBinder_Weak(AIBinder_Weak* a = nullptr) : ScopedAResource(a) {}
Steven Moreland8b4f48a2018-10-08 14:30:42 -0700290 ~ScopedAIBinder_Weak() {}
291 ScopedAIBinder_Weak(ScopedAIBinder_Weak&&) = default;
Devin Moore02686ea2020-07-28 18:44:23 -0700292 ScopedAIBinder_Weak& operator=(ScopedAIBinder_Weak&&) = default;
Steven Moreland2648d202018-08-28 01:23:02 -0700293
294 /**
295 * See AIBinder_Weak_promote.
296 */
Steven Moreland8b4f48a2018-10-08 14:30:42 -0700297 SpAIBinder promote() { return SpAIBinder(AIBinder_Weak_promote(get())); }
Steven Moreland2648d202018-08-28 01:23:02 -0700298};
299
Steven Moreland063f2362018-10-18 12:49:11 -0700300/**
301 * Convenience wrapper for a file descriptor.
302 */
Steven Moreland26c4df12019-01-30 12:29:53 -0800303class ScopedFileDescriptor : public impl::ScopedAResource<int, int, close, -1> {
Steven Moreland6cf66ac2018-11-02 18:14:54 -0700304 public:
Steven Moreland063f2362018-10-18 12:49:11 -0700305 /**
306 * Takes ownership of a.
307 */
308 explicit ScopedFileDescriptor(int a = -1) : ScopedAResource(a) {}
309 ~ScopedFileDescriptor() {}
310 ScopedFileDescriptor(ScopedFileDescriptor&&) = default;
Devin Moore02686ea2020-07-28 18:44:23 -0700311 ScopedFileDescriptor& operator=(ScopedFileDescriptor&&) = default;
Steven Moreland063f2362018-10-18 12:49:11 -0700312};
313
Steven Moreland6cf66ac2018-11-02 18:14:54 -0700314} // namespace ndk
Steven Moreland2648d202018-08-28 01:23:02 -0700315
Steven Moreland2648d202018-08-28 01:23:02 -0700316/** @} */