| /* |
| * 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. |
| */ |
| |
| #pragma once |
| |
| #include <android/binder_ibinder.h> |
| #include <android/binder_shell.h> |
| #include "ibinder_internal.h" |
| |
| #include <atomic> |
| #include <mutex> |
| #include <optional> |
| #include <vector> |
| |
| #include <binder/Binder.h> |
| #include <binder/IBinder.h> |
| #include <utils/Vector.h> |
| |
| inline bool isUserCommand(transaction_code_t code) { |
| return code >= FIRST_CALL_TRANSACTION && code <= LAST_CALL_TRANSACTION; |
| } |
| |
| struct ABBinder; |
| struct ABpBinder; |
| |
| struct AIBinder : public virtual ::android::RefBase { |
| explicit AIBinder(const AIBinder_Class* clazz); |
| virtual ~AIBinder(); |
| |
| bool associateClass(const AIBinder_Class* clazz); |
| const AIBinder_Class* getClass() const { return mClazz; } |
| |
| virtual ::android::sp<::android::IBinder> getBinder() = 0; |
| virtual ABBinder* asABBinder() { return nullptr; } |
| virtual ABpBinder* asABpBinder() { return nullptr; } |
| |
| bool isRemote() const { |
| ::android::sp<::android::IBinder> binder = const_cast<AIBinder*>(this)->getBinder(); |
| return binder->remoteBinder() != nullptr; |
| } |
| |
| private: |
| // AIBinder instance is instance of this class for a local object. In order to transact on a |
| // remote object, this also must be set for simplicity (although right now, only the |
| // interfaceDescriptor from it is used). |
| // |
| // WARNING: When multiple classes exist with the same interface descriptor in different |
| // linkernamespaces, the first one to be associated with mClazz becomes the canonical one |
| // and the only requirement on this is that the interface descriptors match. If this |
| // is an ABpBinder, no other state can be referenced from mClazz. |
| const AIBinder_Class* mClazz; |
| std::mutex mClazzMutex; |
| }; |
| |
| // This is a local AIBinder object with a known class. |
| struct ABBinder : public AIBinder, public ::android::BBinder { |
| virtual ~ABBinder(); |
| |
| void* getUserData() { return mUserData; } |
| |
| ::android::sp<::android::IBinder> getBinder() override { return this; } |
| ABBinder* asABBinder() override { return this; } |
| |
| const ::android::String16& getInterfaceDescriptor() const override; |
| ::android::status_t dump(int fd, const ::android::Vector<::android::String16>& args) override; |
| ::android::status_t onTransact(uint32_t code, const ::android::Parcel& data, |
| ::android::Parcel* reply, binder_flags_t flags) override; |
| |
| private: |
| ABBinder(const AIBinder_Class* clazz, void* userData); |
| |
| // only thing that should create an ABBinder |
| friend AIBinder* AIBinder_new(const AIBinder_Class*, void*); |
| |
| // Can contain implementation if this is a local binder. This can still be nullptr for a local |
| // binder. If it is nullptr, the implication is the implementation state is entirely external to |
| // this object and the functionality provided in the AIBinder_Class is sufficient. |
| void* mUserData; |
| }; |
| |
| // This binder object may be remote or local (even though it is 'Bp'). The implication if it is |
| // local is that it is an IBinder object created outside of the domain of libbinder_ndk. |
| struct ABpBinder : public AIBinder { |
| // Looks up to see if this object has or is an existing ABBinder or ABpBinder object, otherwise |
| // it creates an ABpBinder object. |
| static ::android::sp<AIBinder> lookupOrCreateFromBinder( |
| const ::android::sp<::android::IBinder>& binder); |
| |
| virtual ~ABpBinder(); |
| |
| ::android::sp<::android::IBinder> getBinder() override { return mRemote; } |
| ABpBinder* asABpBinder() override { return this; } |
| |
| bool isServiceFuzzing() const { return mServiceFuzzing; } |
| void setServiceFuzzing() { mServiceFuzzing = true; } |
| |
| private: |
| friend android::sp<ABpBinder>; |
| explicit ABpBinder(const ::android::sp<::android::IBinder>& binder); |
| ::android::sp<::android::IBinder> mRemote; |
| bool mServiceFuzzing = false; |
| }; |
| |
| struct AIBinder_Class { |
| AIBinder_Class(const char* interfaceDescriptor, AIBinder_Class_onCreate onCreate, |
| AIBinder_Class_onDestroy onDestroy, AIBinder_Class_onTransact onTransact); |
| |
| const ::android::String16& getInterfaceDescriptor() const { return mWideInterfaceDescriptor; } |
| const char* getInterfaceDescriptorUtf8() const { return mInterfaceDescriptor.c_str(); } |
| |
| // whether a transaction header should be written |
| bool writeHeader = true; |
| |
| // required to be non-null, implemented for every class |
| const AIBinder_Class_onCreate onCreate = nullptr; |
| const AIBinder_Class_onDestroy onDestroy = nullptr; |
| const AIBinder_Class_onTransact onTransact = nullptr; |
| |
| // optional methods for a class |
| AIBinder_onDump onDump = nullptr; |
| AIBinder_handleShellCommand handleShellCommand = nullptr; |
| |
| private: |
| // Copy of the raw char string for when we don't have to return UTF-16 |
| const std::string mInterfaceDescriptor; |
| // This must be a String16 since BBinder virtual getInterfaceDescriptor returns a reference to |
| // one. |
| const ::android::String16 mWideInterfaceDescriptor; |
| }; |
| |
| // Ownership is like this (when linked to death): |
| // |
| // AIBinder_DeathRecipient -sp-> TransferDeathRecipient <-wp-> IBinder |
| // |
| // When the AIBinder_DeathRecipient is dropped, so are the actual underlying death recipients. When |
| // the IBinder dies, only a wp to it is kept. |
| struct AIBinder_DeathRecipient : ::android::RefBase { |
| // One of these is created for every linkToDeath. This is to be able to recover data when a |
| // binderDied receipt only gives us information about the IBinder. |
| struct TransferDeathRecipient : ::android::IBinder::DeathRecipient { |
| TransferDeathRecipient(const ::android::wp<::android::IBinder>& who, void* cookie, |
| const ::android::wp<AIBinder_DeathRecipient>& parentRecipient, |
| const AIBinder_DeathRecipient_onBinderDied onDied, |
| const AIBinder_DeathRecipient_onBinderUnlinked onUnlinked) |
| : mWho(who), |
| mCookie(cookie), |
| mParentRecipient(parentRecipient), |
| mOnDied(onDied), |
| mOnUnlinked(onUnlinked) {} |
| ~TransferDeathRecipient(); |
| |
| void binderDied(const ::android::wp<::android::IBinder>& who) override; |
| |
| const ::android::wp<::android::IBinder>& getWho() { return mWho; } |
| void* getCookie() { return mCookie; } |
| |
| private: |
| ::android::wp<::android::IBinder> mWho; |
| void* mCookie; |
| |
| ::android::wp<AIBinder_DeathRecipient> mParentRecipient; |
| |
| // This is kept separately from AIBinder_DeathRecipient in case the death recipient is |
| // deleted while the death notification is fired |
| const AIBinder_DeathRecipient_onBinderDied mOnDied; |
| const AIBinder_DeathRecipient_onBinderUnlinked mOnUnlinked; |
| }; |
| |
| explicit AIBinder_DeathRecipient(AIBinder_DeathRecipient_onBinderDied onDied); |
| binder_status_t linkToDeath(const ::android::sp<::android::IBinder>&, void* cookie); |
| binder_status_t unlinkToDeath(const ::android::sp<::android::IBinder>& binder, void* cookie); |
| void setOnUnlinked(AIBinder_DeathRecipient_onBinderUnlinked onUnlinked); |
| |
| private: |
| // When the user of this API deletes a Bp object but not the death recipient, the |
| // TransferDeathRecipient object can't be cleaned up. This is called whenever a new |
| // TransferDeathRecipient is linked, and it ensures that mDeathRecipients can't grow unbounded. |
| void pruneDeadTransferEntriesLocked(); |
| |
| std::mutex mDeathRecipientsMutex; |
| std::vector<::android::sp<TransferDeathRecipient>> mDeathRecipients; |
| AIBinder_DeathRecipient_onBinderDied mOnDied; |
| AIBinder_DeathRecipient_onBinderUnlinked mOnUnlinked; |
| }; |