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