| /* |
| * Copyright (C) 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /** |
| * @addtogroup NdkBinder |
| * @{ |
| */ |
| |
| /** |
| * @file binder_auto_utils.h |
| * @brief These objects provide a more C++-like thin interface to the . |
| */ |
| |
| #pragma once |
| |
| #include <android/binder_ibinder.h> |
| #include <android/binder_parcel.h> |
| #include <android/binder_status.h> |
| |
| #include <assert.h> |
| |
| #include <unistd.h> |
| #include <cstddef> |
| |
| namespace ndk { |
| |
| /** |
| * Represents one strong pointer to an AIBinder object. |
| */ |
| class SpAIBinder { |
| public: |
| /** |
| * Takes ownership of one strong refcount of binder. |
| */ |
| explicit SpAIBinder(AIBinder* binder = nullptr) : mBinder(binder) {} |
| |
| /** |
| * Convenience operator for implicitly constructing an SpAIBinder from nullptr. This is not |
| * explicit because it is not taking ownership of anything. |
| */ |
| SpAIBinder(std::nullptr_t) : SpAIBinder() {} // NOLINT(google-explicit-constructor) |
| |
| /** |
| * This will delete the underlying object if it exists. See operator=. |
| */ |
| SpAIBinder(const SpAIBinder& other) { *this = other; } |
| |
| /** |
| * This deletes the underlying object if it exists. See set. |
| */ |
| ~SpAIBinder() { set(nullptr); } |
| |
| /** |
| * This takes ownership of a binder from another AIBinder object but it does not affect the |
| * ownership of that other object. |
| */ |
| SpAIBinder& operator=(const SpAIBinder& other) { |
| AIBinder_incStrong(other.mBinder); |
| set(other.mBinder); |
| return *this; |
| } |
| |
| /** |
| * Takes ownership of one strong refcount of binder |
| */ |
| void set(AIBinder* binder) { |
| AIBinder* old = *const_cast<AIBinder* volatile*>(&mBinder); |
| if (old != nullptr) AIBinder_decStrong(old); |
| if (old != *const_cast<AIBinder* volatile*>(&mBinder)) { |
| __assert(__FILE__, __LINE__, "Race detected."); |
| } |
| mBinder = binder; |
| } |
| |
| /** |
| * This returns the underlying binder object for transactions. If it is used to create another |
| * SpAIBinder object, it should first be incremented. |
| */ |
| AIBinder* get() const { return mBinder; } |
| |
| /** |
| * This allows the value in this class to be set from beneath it. If you call this method and |
| * then change the value of T*, you must take ownership of the value you are replacing and add |
| * ownership to the object that is put in here. |
| * |
| * Recommended use is like this: |
| * SpAIBinder a; // will be nullptr |
| * SomeInitFunction(a.getR()); // value is initialized with refcount |
| * |
| * Other usecases are discouraged. |
| * |
| */ |
| AIBinder** getR() { return &mBinder; } |
| |
| private: |
| AIBinder* mBinder = nullptr; |
| }; |
| |
| namespace impl { |
| |
| /** |
| * This baseclass owns a single object, used to make various classes RAII. |
| */ |
| template <typename T, typename R, R (*Destroy)(T), T DEFAULT> |
| class ScopedAResource { |
| public: |
| /** |
| * Takes ownership of t. |
| */ |
| explicit ScopedAResource(T t = DEFAULT) : mT(t) {} |
| |
| /** |
| * This deletes the underlying object if it exists. See set. |
| */ |
| ~ScopedAResource() { set(DEFAULT); } |
| |
| /** |
| * Takes ownership of t. |
| */ |
| void set(T t) { |
| Destroy(mT); |
| mT = t; |
| } |
| |
| /** |
| * This returns the underlying object to be modified but does not affect ownership. |
| */ |
| T get() { return mT; } |
| |
| /** |
| * This returns the const underlying object but does not affect ownership. |
| */ |
| const T get() const { return mT; } |
| |
| /** |
| * This allows the value in this class to be set from beneath it. If you call this method and |
| * then change the value of T*, you must take ownership of the value you are replacing and add |
| * ownership to the object that is put in here. |
| * |
| * Recommended use is like this: |
| * ScopedAResource<T> a; // will be nullptr |
| * SomeInitFunction(a.getR()); // value is initialized with refcount |
| * |
| * Other usecases are discouraged. |
| * |
| */ |
| T* getR() { return &mT; } |
| |
| // copy-constructing, or move/copy assignment is disallowed |
| ScopedAResource(const ScopedAResource&) = delete; |
| ScopedAResource& operator=(const ScopedAResource&) = delete; |
| ScopedAResource& operator=(ScopedAResource&&) = delete; |
| |
| // move-constructing is okay |
| ScopedAResource(ScopedAResource&& other) : mT(std::move(other.mT)) { other.mT = DEFAULT; } |
| |
| private: |
| T mT; |
| }; |
| |
| } // namespace impl |
| |
| /** |
| * Convenience wrapper. See AParcel. |
| */ |
| class ScopedAParcel : public impl::ScopedAResource<AParcel*, void, AParcel_delete, nullptr> { |
| public: |
| /** |
| * Takes ownership of a. |
| */ |
| explicit ScopedAParcel(AParcel* a = nullptr) : ScopedAResource(a) {} |
| ~ScopedAParcel() {} |
| ScopedAParcel(ScopedAParcel&&) = default; |
| }; |
| |
| /** |
| * Convenience wrapper. See AStatus. |
| */ |
| class ScopedAStatus : public impl::ScopedAResource<AStatus*, void, AStatus_delete, nullptr> { |
| public: |
| /** |
| * Takes ownership of a. |
| */ |
| explicit ScopedAStatus(AStatus* a = nullptr) : ScopedAResource(a) {} |
| ~ScopedAStatus() {} |
| ScopedAStatus(ScopedAStatus&&) = default; |
| |
| /** |
| * See AStatus_isOk. |
| */ |
| bool isOk() { return get() != nullptr && AStatus_isOk(get()); } |
| |
| /** |
| * Convenience method for okay status. |
| */ |
| static ScopedAStatus ok() { return ScopedAStatus(AStatus_newOk()); } |
| }; |
| |
| /** |
| * Convenience wrapper. See AIBinder_DeathRecipient. |
| */ |
| class ScopedAIBinder_DeathRecipient |
| : public impl::ScopedAResource<AIBinder_DeathRecipient*, void, AIBinder_DeathRecipient_delete, |
| nullptr> { |
| public: |
| /** |
| * Takes ownership of a. |
| */ |
| explicit ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient* a = nullptr) |
| : ScopedAResource(a) {} |
| ~ScopedAIBinder_DeathRecipient() {} |
| ScopedAIBinder_DeathRecipient(ScopedAIBinder_DeathRecipient&&) = default; |
| }; |
| |
| /** |
| * Convenience wrapper. See AIBinder_Weak. |
| */ |
| class ScopedAIBinder_Weak |
| : public impl::ScopedAResource<AIBinder_Weak*, void, AIBinder_Weak_delete, nullptr> { |
| public: |
| /** |
| * Takes ownership of a. |
| */ |
| explicit ScopedAIBinder_Weak(AIBinder_Weak* a = nullptr) : ScopedAResource(a) {} |
| ~ScopedAIBinder_Weak() {} |
| ScopedAIBinder_Weak(ScopedAIBinder_Weak&&) = default; |
| |
| /** |
| * See AIBinder_Weak_promote. |
| */ |
| SpAIBinder promote() { return SpAIBinder(AIBinder_Weak_promote(get())); } |
| }; |
| |
| /** |
| * Convenience wrapper for a file descriptor. |
| */ |
| class ScopedFileDescriptor : public impl::ScopedAResource<int, int, close, -1> { |
| public: |
| /** |
| * Takes ownership of a. |
| */ |
| explicit ScopedFileDescriptor(int a = -1) : ScopedAResource(a) {} |
| ~ScopedFileDescriptor() {} |
| ScopedFileDescriptor(ScopedFileDescriptor&&) = default; |
| }; |
| |
| } // namespace ndk |
| |
| /** @} */ |