// Copyright 2024 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/android/binder.h" #include #include #include #include #include #include #include #include #include #include #include "base/android/requires_api.h" #include "base/check.h" #include "base/memory/raw_ptr_exclusion.h" #include "base/no_destructor.h" #include "base/notreached.h" #include "base/numerics/safe_conversions.h" #include "base/types/expected.h" // The Binder NDK library was introduced in Q. #define BINDER_MIN_API 29 // Helper used extensively herein to guard blocks of code on the availability of // Binder NDK functions. #define WITH_BINDER_API(name) \ if (__builtin_available(android BINDER_MIN_API, *)) \ if (GetBinderApi()) \ if (const BinderApi& name = *GetBinderApi(); true) namespace base::android { namespace { // Helper to expose useful functions from libbinder_ndk.so at runtime. Currently // limited to functions supported in Q. struct BASE_EXPORT BinderApi { // Excluded from raw_ptr because this is trivially safe and it keeps BinderApi // from having a destructor in any build configuration. RAW_PTR_EXCLUSION void* const library = dlopen("libbinder_ndk.so", RTLD_LAZY); #define DEFINE_BINDER_API_ENTRY(name) \ REQUIRES_ANDROID_API(BINDER_MIN_API) \ decltype(::name)* const name = \ library ? (decltype(::name)*)dlsym(library, "" #name) : nullptr DEFINE_BINDER_API_ENTRY(AIBinder_Class_define); DEFINE_BINDER_API_ENTRY(AIBinder_Class_setOnDump); DEFINE_BINDER_API_ENTRY(AIBinder_new); DEFINE_BINDER_API_ENTRY(AIBinder_isRemote); DEFINE_BINDER_API_ENTRY(AIBinder_isAlive); DEFINE_BINDER_API_ENTRY(AIBinder_ping); DEFINE_BINDER_API_ENTRY(AIBinder_dump); DEFINE_BINDER_API_ENTRY(AIBinder_linkToDeath); DEFINE_BINDER_API_ENTRY(AIBinder_unlinkToDeath); DEFINE_BINDER_API_ENTRY(AIBinder_getCallingUid); DEFINE_BINDER_API_ENTRY(AIBinder_getCallingPid); DEFINE_BINDER_API_ENTRY(AIBinder_incStrong); DEFINE_BINDER_API_ENTRY(AIBinder_decStrong); DEFINE_BINDER_API_ENTRY(AIBinder_debugGetRefCount); DEFINE_BINDER_API_ENTRY(AIBinder_associateClass); DEFINE_BINDER_API_ENTRY(AIBinder_getClass); DEFINE_BINDER_API_ENTRY(AIBinder_getUserData); DEFINE_BINDER_API_ENTRY(AIBinder_prepareTransaction); DEFINE_BINDER_API_ENTRY(AIBinder_transact); DEFINE_BINDER_API_ENTRY(AIBinder_Weak_new); DEFINE_BINDER_API_ENTRY(AIBinder_Weak_delete); DEFINE_BINDER_API_ENTRY(AIBinder_Weak_promote); DEFINE_BINDER_API_ENTRY(AIBinder_DeathRecipient_new); DEFINE_BINDER_API_ENTRY(AIBinder_DeathRecipient_delete); DEFINE_BINDER_API_ENTRY(AIBinder_fromJavaBinder); DEFINE_BINDER_API_ENTRY(AIBinder_toJavaBinder); DEFINE_BINDER_API_ENTRY(AParcel_delete); DEFINE_BINDER_API_ENTRY(AParcel_setDataPosition); DEFINE_BINDER_API_ENTRY(AParcel_getDataPosition); DEFINE_BINDER_API_ENTRY(AParcel_writeStrongBinder); DEFINE_BINDER_API_ENTRY(AParcel_readStrongBinder); DEFINE_BINDER_API_ENTRY(AParcel_writeParcelFileDescriptor); DEFINE_BINDER_API_ENTRY(AParcel_readParcelFileDescriptor); DEFINE_BINDER_API_ENTRY(AParcel_writeStatusHeader); DEFINE_BINDER_API_ENTRY(AParcel_readStatusHeader); DEFINE_BINDER_API_ENTRY(AParcel_writeString); DEFINE_BINDER_API_ENTRY(AParcel_readString); DEFINE_BINDER_API_ENTRY(AParcel_writeStringArray); DEFINE_BINDER_API_ENTRY(AParcel_readStringArray); DEFINE_BINDER_API_ENTRY(AParcel_writeParcelableArray); DEFINE_BINDER_API_ENTRY(AParcel_readParcelableArray); DEFINE_BINDER_API_ENTRY(AParcel_writeInt32); DEFINE_BINDER_API_ENTRY(AParcel_writeUint32); DEFINE_BINDER_API_ENTRY(AParcel_writeInt64); DEFINE_BINDER_API_ENTRY(AParcel_writeUint64); DEFINE_BINDER_API_ENTRY(AParcel_writeFloat); DEFINE_BINDER_API_ENTRY(AParcel_writeDouble); DEFINE_BINDER_API_ENTRY(AParcel_writeBool); DEFINE_BINDER_API_ENTRY(AParcel_writeChar); DEFINE_BINDER_API_ENTRY(AParcel_writeByte); DEFINE_BINDER_API_ENTRY(AParcel_readInt32); DEFINE_BINDER_API_ENTRY(AParcel_readUint32); DEFINE_BINDER_API_ENTRY(AParcel_readInt64); DEFINE_BINDER_API_ENTRY(AParcel_readUint64); DEFINE_BINDER_API_ENTRY(AParcel_readFloat); DEFINE_BINDER_API_ENTRY(AParcel_readDouble); DEFINE_BINDER_API_ENTRY(AParcel_readBool); DEFINE_BINDER_API_ENTRY(AParcel_readChar); DEFINE_BINDER_API_ENTRY(AParcel_readByte); DEFINE_BINDER_API_ENTRY(AParcel_writeInt32Array); DEFINE_BINDER_API_ENTRY(AParcel_writeUint32Array); DEFINE_BINDER_API_ENTRY(AParcel_writeInt64Array); DEFINE_BINDER_API_ENTRY(AParcel_writeUint64Array); DEFINE_BINDER_API_ENTRY(AParcel_writeFloatArray); DEFINE_BINDER_API_ENTRY(AParcel_writeDoubleArray); DEFINE_BINDER_API_ENTRY(AParcel_writeBoolArray); DEFINE_BINDER_API_ENTRY(AParcel_writeCharArray); DEFINE_BINDER_API_ENTRY(AParcel_writeByteArray); DEFINE_BINDER_API_ENTRY(AParcel_readInt32Array); DEFINE_BINDER_API_ENTRY(AParcel_readUint32Array); DEFINE_BINDER_API_ENTRY(AParcel_readInt64Array); DEFINE_BINDER_API_ENTRY(AParcel_readUint64Array); DEFINE_BINDER_API_ENTRY(AParcel_readFloatArray); DEFINE_BINDER_API_ENTRY(AParcel_readDoubleArray); DEFINE_BINDER_API_ENTRY(AParcel_readBoolArray); DEFINE_BINDER_API_ENTRY(AParcel_readCharArray); DEFINE_BINDER_API_ENTRY(AParcel_readByteArray); #undef DEFINE_BINDER_API_ENTRY }; static BinderApi* GetBinderApi() { static BinderApi api; if (!api.library) { return nullptr; } return &api; } std::unique_ptr>& BindersFromParent() { static NoDestructor>> ptr; return *ptr; } } // namespace ParcelReader::ParcelReader(const AParcel* parcel) : parcel_(parcel) {} ParcelReader::ParcelReader(const Parcel& parcel) : parcel_(parcel.get()) {} ParcelReader::ParcelReader(const ParcelReader&) = default; ParcelReader& ParcelReader::operator=(const ParcelReader&) = default; ParcelReader::~ParcelReader() = default; BinderStatusOr ParcelReader::ReadBinder() const { WITH_BINDER_API(api) { AIBinder* binder; const auto status = api.AParcel_readStrongBinder(parcel_.get(), &binder); if (status != STATUS_OK) { return unexpected(status); } return BinderRef(binder); } return unexpected(STATUS_UNEXPECTED_NULL); } BinderStatusOr ParcelReader::ReadInt32() const { WITH_BINDER_API(api) { int32_t value; const auto status = api.AParcel_readInt32(parcel_.get(), &value); if (status != STATUS_OK) { return unexpected(status); } return ok(value); } return unexpected(STATUS_UNEXPECTED_NULL); } BinderStatusOr ParcelReader::ReadUint32() const { WITH_BINDER_API(api) { uint32_t value; const auto status = api.AParcel_readUint32(parcel_.get(), &value); if (status != STATUS_OK) { return unexpected(status); } return ok(value); } return unexpected(STATUS_UNEXPECTED_NULL); } BinderStatusOr ParcelReader::ReadUint64() const { WITH_BINDER_API(api) { uint64_t value; const auto status = api.AParcel_readUint64(parcel_.get(), &value); if (status != STATUS_OK) { return unexpected(status); } return ok(value); } return unexpected(STATUS_UNEXPECTED_NULL); } BinderStatusOr ParcelReader::ReadByteArrayImpl( AParcel_byteArrayAllocator allocator, void* context) const { WITH_BINDER_API(api) { const auto status = api.AParcel_readByteArray(parcel_.get(), context, allocator); if (status != STATUS_OK) { return unexpected(status); } return ok(); } return unexpected(STATUS_UNEXPECTED_NULL); } BinderStatusOr ParcelReader::ReadFileDescriptor() const { WITH_BINDER_API(api) { int fd; const auto status = api.AParcel_readParcelFileDescriptor(parcel_.get(), &fd); if (status != STATUS_OK) { return unexpected(status); } return ScopedFD(fd); } return unexpected(STATUS_UNEXPECTED_NULL); } ParcelWriter::ParcelWriter(AParcel* parcel) : parcel_(parcel) {} ParcelWriter::ParcelWriter(Parcel& parcel) : parcel_(parcel.get()) {} ParcelWriter::ParcelWriter(const ParcelWriter&) = default; ParcelWriter& ParcelWriter::operator=(const ParcelWriter&) = default; ParcelWriter::~ParcelWriter() = default; BinderStatusOr ParcelWriter::WriteBinder(BinderRef binder) const { binder_status_t status = STATUS_UNEXPECTED_NULL; WITH_BINDER_API(api) { status = api.AParcel_writeStrongBinder(parcel_.get(), binder.get()); if (status == STATUS_OK) { return ok(); } } return unexpected(status); } BinderStatusOr ParcelWriter::WriteInt32(int32_t value) const { binder_status_t status = STATUS_UNEXPECTED_NULL; WITH_BINDER_API(api) { status = api.AParcel_writeInt32(parcel_.get(), value); if (status == STATUS_OK) { return ok(); } } return unexpected(status); } BinderStatusOr ParcelWriter::WriteUint32(uint32_t value) const { binder_status_t status = STATUS_UNEXPECTED_NULL; WITH_BINDER_API(api) { status = api.AParcel_writeUint32(parcel_.get(), value); if (status == STATUS_OK) { return ok(); } } return unexpected(status); } BinderStatusOr ParcelWriter::WriteUint64(uint64_t value) const { binder_status_t status = STATUS_UNEXPECTED_NULL; WITH_BINDER_API(api) { status = api.AParcel_writeUint64(parcel_.get(), value); if (status == STATUS_OK) { return ok(); } } return unexpected(status); } BinderStatusOr ParcelWriter::WriteByteArray( span bytes) const { binder_status_t status = STATUS_UNEXPECTED_NULL; WITH_BINDER_API(api) { status = api.AParcel_writeByteArray( parcel_.get(), reinterpret_cast(bytes.data()), checked_cast(bytes.size())); if (status == STATUS_OK) { return ok(); } } return unexpected(status); } BinderStatusOr ParcelWriter::WriteFileDescriptor(ScopedFD file) const { binder_status_t status = STATUS_UNEXPECTED_NULL; WITH_BINDER_API(api) { status = api.AParcel_writeParcelFileDescriptor(parcel_.get(), file.get()); if (status == STATUS_OK) { return ok(); } } return unexpected(status); } Parcel::Parcel() = default; Parcel::Parcel(AParcel* parcel) : parcel_(parcel) {} Parcel::Parcel(Parcel&& other) : parcel_(other.release()) {} Parcel& Parcel::operator=(Parcel&& other) { reset(); parcel_ = other.release(); return *this; } Parcel::~Parcel() { reset(); } void Parcel::reset() { WITH_BINDER_API(api) { if (AParcel* parcel = release()) { api.AParcel_delete(parcel); } } } BinderRef::BinderRef() = default; BinderRef::BinderRef(AIBinder* binder) : binder_(binder) {} BinderRef::BinderRef(const BinderRef& other) : binder_(other.binder_) { if (binder_) { WITH_BINDER_API(api) { api.AIBinder_incStrong(binder_); } } } BinderRef& BinderRef::operator=(const BinderRef& other) { reset(); binder_ = other.binder_; if (binder_) { WITH_BINDER_API(api) { api.AIBinder_incStrong(binder_); } } return *this; } BinderRef::BinderRef(BinderRef&& other) : binder_(other.release()) {} BinderRef& BinderRef::operator=(BinderRef&& other) { reset(); binder_ = other.release(); return *this; } BinderRef::~BinderRef() { reset(); } void BinderRef::reset() { if (AIBinder* binder = release()) { WITH_BINDER_API(api) { api.AIBinder_decStrong(binder); } } } ScopedJavaLocalRef BinderRef::ToJavaBinder(JNIEnv* env) const { ScopedJavaLocalRef object; if (binder_) { WITH_BINDER_API(api) { object = ScopedJavaLocalRef::Adopt( env, api.AIBinder_toJavaBinder(env, binder_.get())); } } return object; } BinderRef BinderRef::FromJavaBinder(JNIEnv* env, jobject java_binder) { WITH_BINDER_API(api) { if (AIBinder* binder = api.AIBinder_fromJavaBinder(env, java_binder)) { return BinderRef(binder); } } return BinderRef(); } bool BinderRef::AssociateWithClass(AIBinder_Class* binder_class) { if (binder_) { WITH_BINDER_API(api) { return api.AIBinder_associateClass(binder_.get(), binder_class); } } return false; } BinderStatusOr BinderRef::PrepareTransaction() { if (binder_) { WITH_BINDER_API(api) { AParcel* parcel; const auto status = api.AIBinder_prepareTransaction(binder_.get(), &parcel); if (status != STATUS_OK) { return unexpected(status); } return Parcel(parcel); } } return unexpected(STATUS_UNEXPECTED_NULL); } BinderStatusOr BinderRef::TransactImpl(transaction_code_t code, Parcel parcel, binder_flags_t flags) { if (binder_) { WITH_BINDER_API(api) { // NOTE: AIBinder_transact always takes ownership of the input parcel even // in failure modes. Hence it's safe to release here unconditionally. AParcel* in = parcel.release(); AParcel* out; const auto status = api.AIBinder_transact(binder_.get(), code, &in, &out, flags); if (status != STATUS_OK) { return unexpected(status); } return Parcel(out); } } return unexpected(STATUS_UNEXPECTED_NULL); } namespace internal { AIBinder_Class* BinderClassBase::RegisterBinderClass(const char* name) { WITH_BINDER_API(api) { return api.AIBinder_Class_define(name, &SupportsBinderBase::OnIBinderCreate, &SupportsBinderBase::OnIBinderDestroy, &SupportsBinderBase::OnIBinderTransact); } return nullptr; } SupportsBinderBase::SupportsBinderBase(AIBinder_Class* binder_class) : binder_class_(binder_class) {} SupportsBinderBase::~SupportsBinderBase() { #if DCHECK_IS_ON() // If we're being destroyed there must no longer be an IBinder for this // object. And in that case, `weak_binder_` should have already been cleared // by OnIBinderDestroy(). AutoLock lock(lock_); DCHECK(!weak_binder_); #endif } BinderRef SupportsBinderBase::GetBinder() { WITH_BINDER_API(api) { AutoLock lock(lock_); if (weak_binder_) { AIBinder* strong = api.AIBinder_Weak_promote(weak_binder_.get()); if (strong) { return BinderRef(strong); } // Our weak IBinder is no longer valid. api.AIBinder_Weak_delete(weak_binder_.get()); weak_binder_ = nullptr; } // We have no IBinder, so create a new one. AIBinder* binder = api.AIBinder_new(binder_class_.get(), this); CHECK(binder); weak_binder_ = api.AIBinder_Weak_new(binder); self_for_binder_ = this; return BinderRef(binder); } return BinderRef(); } void SupportsBinderBase::OnBinderDestroyed() {} void SupportsBinderBase::OnBinderDestroyedBase() { scoped_refptr self_ref; WITH_BINDER_API(api) { AutoLock lock(lock_); if (weak_binder_) { api.AIBinder_Weak_delete(weak_binder_.get()); weak_binder_ = nullptr; } self_ref.swap(self_for_binder_); } OnBinderDestroyed(); // May delete `this`. self_ref.reset(); } void* SupportsBinderBase::OnIBinderCreate(void* self) { return self; } void SupportsBinderBase::OnIBinderDestroy(void* self) { reinterpret_cast(self)->OnBinderDestroyedBase(); } binder_status_t SupportsBinderBase::OnIBinderTransact(AIBinder* binder, transaction_code_t code, const AParcel* in, AParcel* out) { WITH_BINDER_API(api) { void* const user_data = api.AIBinder_getUserData(binder); auto* const target = reinterpret_cast(user_data); const auto result = target->OnBinderTransaction(code, ParcelReader(in), ParcelWriter(out)); return result.has_value() ? STATUS_OK : result.error(); } // If binder NDK is unsupported, nobody will be calling this method. NOTREACHED(); } } // namespace internal bool IsNativeBinderAvailable() { return GetBinderApi(); } void SetBindersFromParent(std::vector binders) { CHECK(!BindersFromParent()); BindersFromParent() = std::make_unique>(std::move(binders)); } BinderRef TakeBinderFromParent(size_t index) { auto& binders = BindersFromParent(); CHECK(binders); if (index >= binders->size()) { return BinderRef(); } return std::move(binders->at(index)); } } // namespace base::android