Initial C library for libbinder.
This creates a simple wrapper around libbinder with a stable C ABI. It
also embeds the concept of an IBinder and IBinder transactions into the
ABI so that parts of their transactions can be changed and considered
implementation details of libbinder. With this basic class, you can
create a service, use it with primitive data types, but it does not yet
suppport the entire range of binder objects.
Follow-up items to handle/things still to consider
- b/112664205: make aidl-gen produce interfaces that use these (and
think about interoperation with existing interfaces).
- using onServiceConnected/onServiceDisconnected in the NDK
- if libbinder/libbinder_ndk classes use the same descriptor, there will
be problems in the same process (libbinder{_ndk} assumes binder class)
- sometimes getService takes 1s since there is a race for it getting
registered
- add generic class which allows for easy implementation of a class like
IFoo in this test.
- Parcel for additional types (and additional APIs, like data available)
- addition of APIs like AIBinder_ping/linkToDeath which all binders have
- embed Status into this API layer (so EX_HAS_REPLY_HEADER is handled)
- make remoteBinder/localBinder is const (and therefore isRemote)
- okay with associateClass or should just use interfaceDescriptor
- potentially changing out incStrong/decStrong
- adding @file/@addtogroup to comments
Bug: 111445392
Test: ndk/runtests.sh
Change-Id: Ifbca8f0fdf70a3213fe0d94320fc31eeb62408c4
diff --git a/libs/binder/ndk/ABinderProcess.cpp b/libs/binder/ndk/ABinderProcess.cpp
new file mode 100644
index 0000000..c89caaf
--- /dev/null
+++ b/libs/binder/ndk/ABinderProcess.cpp
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+#include <android/binder_process.h>
+
+#include <mutex>
+
+#include <android-base/logging.h>
+#include <binder/IPCThreadState.h>
+
+using ::android::IPCThreadState;
+using ::android::ProcessState;
+
+void ABinderProcess_startThreadPool() {
+ ProcessState::self()->startThreadPool();
+ ProcessState::self()->giveThreadPoolName();
+}
+bool ABinderProcess_setThreadPoolMaxThreadCount(uint32_t numThreads) {
+ return ProcessState::self()->setThreadPoolMaxThreadCount(numThreads) == 0;
+}
+void ABinderProcess_joinThreadPool() {
+ IPCThreadState::self()->joinThreadPool();
+}
diff --git a/libs/binder/ndk/AIBinder.cpp b/libs/binder/ndk/AIBinder.cpp
new file mode 100644
index 0000000..d0ce98d
--- /dev/null
+++ b/libs/binder/ndk/AIBinder.cpp
@@ -0,0 +1,345 @@
+/*
+ * 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.
+ */
+
+#include <android/binder_ibinder.h>
+#include "AIBinder_internal.h"
+
+#include <android/binder_status.h>
+#include "AParcel_internal.h"
+
+#include <android-base/logging.h>
+
+using ::android::IBinder;
+using ::android::Parcel;
+using ::android::sp;
+using ::android::String16;
+using ::android::wp;
+
+AIBinder::AIBinder(const AIBinder_Class* clazz) : mClazz(clazz) {}
+AIBinder::~AIBinder() {}
+
+sp<AIBinder> AIBinder::associateClass(const AIBinder_Class* clazz) {
+ using ::android::String8;
+
+ if (clazz == nullptr) return nullptr;
+ if (mClazz == clazz) return this;
+
+ String8 newDescriptor(clazz->getInterfaceDescriptor());
+
+ if (mClazz != nullptr) {
+ String8 currentDescriptor(mClazz->getInterfaceDescriptor());
+ if (newDescriptor == currentDescriptor) {
+ LOG(ERROR) << __func__ << ": Class descriptors '" << currentDescriptor
+ << "' match during associateClass, but they are different class objects. "
+ "Class descriptor collision?";
+ return nullptr;
+ }
+
+ LOG(ERROR) << __func__
+ << ": Class cannot be associated on object which already has a class. Trying to "
+ "associate to '"
+ << newDescriptor.c_str() << "' but already set to '" << currentDescriptor.c_str()
+ << "'.";
+ return nullptr;
+ }
+
+ String8 descriptor(getBinder()->getInterfaceDescriptor());
+ if (descriptor != newDescriptor) {
+ LOG(ERROR) << __func__ << ": Expecting binder to have class '" << newDescriptor.c_str()
+ << "' but descriptor is actually '" << descriptor.c_str() << "'.";
+ return nullptr;
+ }
+
+ // The descriptor matches, so if it is local, this is guaranteed to be the libbinder_ndk class.
+ // An error here can occur if there is a conflict between descriptors (two unrelated classes
+ // define the same descriptor), but this should never happen.
+
+ // if this is a local ABBinder, mClazz should be non-null
+ CHECK(asABBinder() == nullptr);
+ CHECK(asABpBinder() != nullptr);
+
+ if (!isRemote()) {
+ // ABpBinder but proxy to a local object. Therefore that local object must be an ABBinder.
+ ABBinder* binder = static_cast<ABBinder*>(getBinder().get());
+ return binder;
+ }
+
+ // This is a remote object
+ mClazz = clazz;
+
+ return this;
+}
+
+ABBinder::ABBinder(const AIBinder_Class* clazz, void* userData)
+ : AIBinder(clazz), BBinder(), mUserData(userData) {
+ CHECK(clazz != nullptr);
+}
+ABBinder::~ABBinder() {
+ getClass()->onDestroy(mUserData);
+}
+
+const String16& ABBinder::getInterfaceDescriptor() const {
+ return getClass()->getInterfaceDescriptor();
+}
+
+binder_status_t ABBinder::onTransact(transaction_code_t code, const Parcel& data, Parcel* reply,
+ binder_flags_t flags) {
+ if (isUserCommand(code)) {
+ if (!data.checkInterface(this)) {
+ return EX_ILLEGAL_STATE;
+ }
+
+ const AParcel in = AParcel::readOnly(this, &data);
+ AParcel out = AParcel(this, reply, false /*owns*/);
+
+ return getClass()->onTransact(this, code, &in, &out);
+ } else {
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+ABpBinder::ABpBinder(::android::sp<::android::IBinder> binder)
+ : AIBinder(nullptr /*clazz*/), BpRefBase(binder) {
+ CHECK(binder != nullptr);
+}
+ABpBinder::~ABpBinder() {}
+
+struct AIBinder_Weak {
+ wp<AIBinder> binder;
+};
+AIBinder_Weak* AIBinder_Weak_new(AIBinder* binder) {
+ if (binder == nullptr) return nullptr;
+ return new AIBinder_Weak{wp<AIBinder>(binder)};
+}
+void AIBinder_Weak_delete(AIBinder_Weak* weakBinder) {
+ delete weakBinder;
+}
+AIBinder* AIBinder_Weak_promote(AIBinder_Weak* weakBinder) {
+ if (weakBinder == nullptr) return nullptr;
+ sp<AIBinder> binder = weakBinder->binder.promote();
+ AIBinder_incStrong(binder.get());
+ return binder.get();
+}
+
+AIBinder_Class::AIBinder_Class(const char* interfaceDescriptor, AIBinder_Class_onCreate onCreate,
+ AIBinder_Class_onDestroy onDestroy,
+ AIBinder_Class_onTransact onTransact)
+ : onCreate(onCreate),
+ onDestroy(onDestroy),
+ onTransact(onTransact),
+ mInterfaceDescriptor(interfaceDescriptor) {}
+
+AIBinder_Class* AIBinder_Class_define(const char* interfaceDescriptor,
+ AIBinder_Class_onCreate onCreate,
+ AIBinder_Class_onDestroy onDestroy,
+ AIBinder_Class_onTransact onTransact) {
+ if (interfaceDescriptor == nullptr || onCreate == nullptr || onDestroy == nullptr ||
+ onTransact == nullptr) {
+ return nullptr;
+ }
+
+ return new AIBinder_Class(interfaceDescriptor, onCreate, onDestroy, onTransact);
+}
+
+AIBinder* AIBinder_new(const AIBinder_Class* clazz, void* args) {
+ if (clazz == nullptr) {
+ LOG(ERROR) << __func__ << ": Must provide class to construct local binder.";
+ return nullptr;
+ }
+
+ void* userData = clazz->onCreate(args);
+
+ AIBinder* ret = new ABBinder(clazz, userData);
+ AIBinder_incStrong(ret);
+ return ret;
+}
+
+bool AIBinder_isRemote(AIBinder* binder) {
+ if (binder == nullptr) {
+ return true;
+ }
+
+ return binder->isRemote();
+}
+
+void AIBinder_incStrong(AIBinder* binder) {
+ if (binder == nullptr) {
+ LOG(ERROR) << __func__ << ": on null binder";
+ return;
+ }
+
+ binder->incStrong(nullptr);
+}
+void AIBinder_decStrong(AIBinder* binder) {
+ if (binder == nullptr) {
+ LOG(ERROR) << __func__ << ": on null binder";
+ return;
+ }
+
+ binder->decStrong(nullptr);
+}
+int32_t AIBinder_debugGetRefCount(AIBinder* binder) {
+ if (binder == nullptr) {
+ LOG(ERROR) << __func__ << ": on null binder";
+ return -1;
+ }
+
+ return binder->getStrongCount();
+}
+
+void AIBinder_associateClass(AIBinder** binder, const AIBinder_Class* clazz) {
+ if (binder == nullptr || *binder == nullptr) {
+ return;
+ }
+
+ sp<AIBinder> result = (*binder)->associateClass(clazz);
+
+ // This function takes one refcount of 'binder' and delivers one refcount of 'result' to the
+ // callee. First we give the callee their refcount and then take it away from binder. This is
+ // done in this order in order to handle the case that the result and the binder are the same
+ // object.
+ if (result != nullptr) {
+ AIBinder_incStrong(result.get());
+ }
+ AIBinder_decStrong(*binder);
+
+ *binder = result.get(); // Maybe no-op
+}
+
+const AIBinder_Class* AIBinder_getClass(AIBinder* binder) {
+ if (binder == nullptr) {
+ return nullptr;
+ }
+
+ return binder->getClass();
+}
+
+void* AIBinder_getUserData(AIBinder* binder) {
+ if (binder == nullptr) {
+ return nullptr;
+ }
+
+ ABBinder* bBinder = binder->asABBinder();
+ if (bBinder == nullptr) {
+ return nullptr;
+ }
+
+ return bBinder->getUserData();
+}
+
+binder_status_t AIBinder_prepareTransaction(AIBinder* binder, AParcel** in) {
+ if (binder == nullptr || in == nullptr) {
+ LOG(ERROR) << __func__ << ": requires non-null parameters.";
+ return EX_NULL_POINTER;
+ }
+ const AIBinder_Class* clazz = binder->getClass();
+ if (clazz == nullptr) {
+ LOG(ERROR) << __func__
+ << ": Class must be defined for a remote binder transaction. See "
+ "AIBinder_associateClass.";
+ return EX_ILLEGAL_STATE;
+ }
+
+ *in = new AParcel(binder);
+ binder_status_t status = (**in)->writeInterfaceToken(clazz->getInterfaceDescriptor());
+ if (status != EX_NONE) {
+ delete *in;
+ *in = nullptr;
+ }
+
+ return status;
+}
+
+using AutoParcelDestroyer = std::unique_ptr<AParcel*, void (*)(AParcel**)>;
+static void destroy_parcel(AParcel** parcel) {
+ delete *parcel;
+ *parcel = nullptr;
+}
+
+binder_status_t AIBinder_transact(AIBinder* binder, transaction_code_t code, AParcel** in,
+ AParcel** out, binder_flags_t flags) {
+ if (in == nullptr) {
+ LOG(ERROR) << __func__ << ": requires non-null in parameter";
+ return EX_NULL_POINTER;
+ }
+
+ // This object is the input to the transaction. This function takes ownership of it and deletes
+ // it.
+ AutoParcelDestroyer forIn(in, destroy_parcel);
+
+ if (!isUserCommand(code)) {
+ LOG(ERROR) << __func__ << ": Only user-defined transactions can be made from the NDK.";
+ return EX_UNSUPPORTED_OPERATION;
+ }
+
+ if ((flags & ~FLAG_ONEWAY) != 0) {
+ LOG(ERROR) << __func__ << ": Unrecognized flags sent: " << flags;
+ return EX_ILLEGAL_ARGUMENT;
+ }
+
+ if (binder == nullptr || *in == nullptr || out == nullptr) {
+ LOG(ERROR) << __func__ << ": requires non-null parameters.";
+ return EX_NULL_POINTER;
+ }
+
+ if ((*in)->getBinder() != binder) {
+ LOG(ERROR) << __func__ << ": parcel is associated with binder object " << binder
+ << " but called with " << (*in)->getBinder();
+ return EX_ILLEGAL_STATE;
+ }
+
+ *out = new AParcel(binder);
+
+ binder_status_t parcelStatus =
+ binder->getBinder()->transact(code, *(*in)->operator->(), (*out)->operator->(), flags);
+
+ if (parcelStatus != EX_NONE) {
+ delete *out;
+ *out = nullptr;
+ }
+
+ return parcelStatus;
+}
+
+binder_status_t AIBinder_finalizeTransaction(AIBinder* binder, AParcel** out) {
+ if (out == nullptr) {
+ LOG(ERROR) << __func__ << ": requires non-null out parameter";
+ return EX_NULL_POINTER;
+ }
+
+ // This object is the input to the transaction. This function takes ownership of it and deletes
+ // it.
+ AutoParcelDestroyer forOut(out, destroy_parcel);
+
+ if (binder == nullptr || *out == nullptr) {
+ LOG(ERROR) << __func__ << ": requires non-null parameters.";
+ return EX_NULL_POINTER;
+ }
+
+ if ((*out)->getBinder() != binder) {
+ LOG(ERROR) << __func__ << ": parcel is associated with binder object " << binder
+ << " but called with " << (*out)->getBinder();
+ return EX_ILLEGAL_STATE;
+ }
+
+ if ((**out)->dataAvail() != 0) {
+ LOG(ERROR) << __func__
+ << ": Only part of this transaction was read. There is remaining data left.";
+ return EX_ILLEGAL_STATE;
+ }
+
+ return EX_NONE;
+}
diff --git a/libs/binder/ndk/AIBinder_internal.h b/libs/binder/ndk/AIBinder_internal.h
new file mode 100644
index 0000000..d44b937
--- /dev/null
+++ b/libs/binder/ndk/AIBinder_internal.h
@@ -0,0 +1,109 @@
+/*
+ * 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 "AIBinder_internal.h"
+
+#include <atomic>
+
+#include <binder/Binder.h>
+#include <binder/IBinder.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 {
+ AIBinder(const AIBinder_Class* clazz);
+ virtual ~AIBinder();
+
+ // This returns an AIBinder object with this class associated. If the class is already
+ // associated, 'this' will be returned. If there is a local AIBinder implementation, that will
+ // be returned. If this is a remote object, the class will be associated and this will be ready
+ // to be used for transactions.
+ ::android::sp<AIBinder> associateClass(const AIBinder_Class* clazz);
+ const AIBinder_Class* getClass() const { return mClazz; }
+
+ // This does not create the binder if it does not exist in the process.
+ virtual ::android::sp<::android::IBinder> getBinder() = 0;
+ virtual ABBinder* asABBinder() { return nullptr; }
+ virtual ABpBinder* asABpBinder() { return nullptr; }
+
+ bool isRemote() {
+ auto binder = getBinder();
+ // if the binder is nullptr, then it is a local object which hasn't been sent out of process
+ // yet.
+ return binder != nullptr && 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).
+ const AIBinder_Class* mClazz;
+};
+
+// This is a local AIBinder object with a known class.
+struct ABBinder : public AIBinder, public ::android::BBinder {
+ ABBinder(const AIBinder_Class* clazz, void* userData);
+ 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;
+ binder_status_t onTransact(uint32_t code, const ::android::Parcel& data,
+ ::android::Parcel* reply, binder_flags_t flags) override;
+
+private:
+ // 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'). It is not yet associated with
+// a class.
+struct ABpBinder : public AIBinder, public ::android::BpRefBase {
+ ABpBinder(::android::sp<::android::IBinder> binder);
+ virtual ~ABpBinder();
+
+ ::android::sp<::android::IBinder> getBinder() override { return remote(); }
+ ABpBinder* asABpBinder() override { return this; }
+};
+
+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 mInterfaceDescriptor; }
+
+ const AIBinder_Class_onCreate onCreate;
+ const AIBinder_Class_onDestroy onDestroy;
+ const AIBinder_Class_onTransact onTransact;
+
+private:
+ // This must be a String16 since BBinder virtual getInterfaceDescriptor returns a reference to
+ // one.
+ const ::android::String16 mInterfaceDescriptor;
+};
diff --git a/libs/binder/ndk/AParcel.cpp b/libs/binder/ndk/AParcel.cpp
new file mode 100644
index 0000000..b63b138
--- /dev/null
+++ b/libs/binder/ndk/AParcel.cpp
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ */
+
+#include <android/binder_parcel.h>
+#include "AParcel_internal.h"
+
+#include "AIBinder_internal.h"
+
+#include <binder/Parcel.h>
+
+using ::android::IBinder;
+using ::android::Parcel;
+using ::android::sp;
+
+binder_status_t AParcel_writeStrongBinder(AParcel* parcel, AIBinder* binder) {
+ return (*parcel)->writeStrongBinder(binder->getBinder());
+}
+binder_status_t AParcel_readStrongBinder(const AParcel* parcel, AIBinder** binder) {
+ sp<IBinder> readBinder = nullptr;
+ binder_status_t status = (*parcel)->readStrongBinder(&readBinder);
+ if (status != EX_NONE) {
+ return status;
+ }
+ *binder = new ABpBinder(readBinder);
+ AIBinder_incStrong(*binder);
+ return status;
+}
+binder_status_t AParcel_readNullableStrongBinder(const AParcel* parcel, AIBinder** binder) {
+ sp<IBinder> readBinder = nullptr;
+ binder_status_t status = (*parcel)->readNullableStrongBinder(&readBinder);
+ if (status != EX_NONE) {
+ return status;
+ }
+ *binder = new ABpBinder(readBinder);
+ AIBinder_incStrong(*binder);
+ return status;
+}
+
+// See gen_parcel_helper.py. These auto-generated read/write methods use the same types for
+// libbinder and this library.
+// @START
+binder_status_t AParcel_writeInt32(AParcel* parcel, int32_t value) {
+ return (*parcel)->writeInt32(value);
+}
+
+binder_status_t AParcel_writeUint32(AParcel* parcel, uint32_t value) {
+ return (*parcel)->writeUint32(value);
+}
+
+binder_status_t AParcel_writeInt64(AParcel* parcel, int64_t value) {
+ return (*parcel)->writeInt64(value);
+}
+
+binder_status_t AParcel_writeUint64(AParcel* parcel, uint64_t value) {
+ return (*parcel)->writeUint64(value);
+}
+
+binder_status_t AParcel_writeFloat(AParcel* parcel, float value) {
+ return (*parcel)->writeFloat(value);
+}
+
+binder_status_t AParcel_writeDouble(AParcel* parcel, double value) {
+ return (*parcel)->writeDouble(value);
+}
+
+binder_status_t AParcel_writeBool(AParcel* parcel, bool value) {
+ return (*parcel)->writeBool(value);
+}
+
+binder_status_t AParcel_writeChar(AParcel* parcel, char16_t value) {
+ return (*parcel)->writeChar(value);
+}
+
+binder_status_t AParcel_writeByte(AParcel* parcel, int8_t value) {
+ return (*parcel)->writeByte(value);
+}
+
+binder_status_t AParcel_readInt32(const AParcel* parcel, int32_t* value) {
+ return (*parcel)->readInt32(value);
+}
+
+binder_status_t AParcel_readUint32(const AParcel* parcel, uint32_t* value) {
+ return (*parcel)->readUint32(value);
+}
+
+binder_status_t AParcel_readInt64(const AParcel* parcel, int64_t* value) {
+ return (*parcel)->readInt64(value);
+}
+
+binder_status_t AParcel_readUint64(const AParcel* parcel, uint64_t* value) {
+ return (*parcel)->readUint64(value);
+}
+
+binder_status_t AParcel_readFloat(const AParcel* parcel, float* value) {
+ return (*parcel)->readFloat(value);
+}
+
+binder_status_t AParcel_readDouble(const AParcel* parcel, double* value) {
+ return (*parcel)->readDouble(value);
+}
+
+binder_status_t AParcel_readBool(const AParcel* parcel, bool* value) {
+ return (*parcel)->readBool(value);
+}
+
+binder_status_t AParcel_readChar(const AParcel* parcel, char16_t* value) {
+ return (*parcel)->readChar(value);
+}
+
+binder_status_t AParcel_readByte(const AParcel* parcel, int8_t* value) {
+ return (*parcel)->readByte(value);
+}
+
+// @END
diff --git a/libs/binder/ndk/AParcel_internal.h b/libs/binder/ndk/AParcel_internal.h
new file mode 100644
index 0000000..9f30a2f
--- /dev/null
+++ b/libs/binder/ndk/AParcel_internal.h
@@ -0,0 +1,53 @@
+/*
+ * 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_parcel.h>
+
+#include <sys/cdefs.h>
+
+#include <binder/Parcel.h>
+#include "AIBinder_internal.h"
+
+struct AParcel {
+ const ::android::Parcel* operator->() const { return mParcel; }
+ ::android::Parcel* operator->() { return mParcel; }
+
+ AParcel(const AIBinder* binder) : AParcel(binder, new ::android::Parcel, true /*owns*/) {}
+ AParcel(const AIBinder* binder, ::android::Parcel* parcel, bool owns)
+ : mBinder(binder), mParcel(parcel), mOwns(owns) {}
+
+ ~AParcel() {
+ if (mOwns) {
+ delete mParcel;
+ }
+ }
+
+ static const AParcel readOnly(const AIBinder* binder, const ::android::Parcel* parcel) {
+ return AParcel(binder, const_cast<::android::Parcel*>(parcel), false);
+ }
+
+ const AIBinder* getBinder() { return mBinder; }
+
+private:
+ // This object is associated with a calls to a specific AIBinder object. This is used for sanity
+ // checking to make sure that a parcel is one that is expected.
+ const AIBinder* mBinder;
+
+ ::android::Parcel* mParcel;
+ bool mOwns;
+};
diff --git a/libs/binder/ndk/AServiceManager.cpp b/libs/binder/ndk/AServiceManager.cpp
new file mode 100644
index 0000000..f61b914
--- /dev/null
+++ b/libs/binder/ndk/AServiceManager.cpp
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+#include <android/binder_manager.h>
+#include "AIBinder_internal.h"
+
+#include <binder/IServiceManager.h>
+
+using ::android::defaultServiceManager;
+using ::android::IBinder;
+using ::android::IServiceManager;
+using ::android::sp;
+using ::android::String16;
+
+binder_status_t AServiceManager_addService(AIBinder* binder, const char* instance) {
+ if (binder == nullptr || instance == nullptr) {
+ return EX_NULL_POINTER;
+ }
+
+ sp<IServiceManager> sm = defaultServiceManager();
+ return sm->addService(String16(instance), binder->getBinder());
+}
+AIBinder* AServiceManager_getService(const char* instance) {
+ if (instance == nullptr) {
+ return nullptr;
+ }
+
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder = sm->getService(String16(instance));
+
+ AIBinder* ret = new ABpBinder(binder);
+ AIBinder_incStrong(ret);
+ return ret;
+}
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
new file mode 100644
index 0000000..76d5a73
--- /dev/null
+++ b/libs/binder/ndk/Android.bp
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+cc_library {
+ name: "libbinder_ndk",
+ vendor_available: false,
+
+ export_include_dirs: [
+ "include_ndk",
+ "include_apex",
+ ],
+
+ srcs: [
+ "ABinderProcess.cpp",
+ "AIBinder.cpp",
+ "AParcel.cpp",
+ "AServiceManager.cpp",
+ ],
+
+ shared_libs: [
+ "libbase",
+ "libbinder",
+ "libutils",
+ ],
+}
diff --git a/libs/binder/ndk/include_apex/android/binder_manager.h b/libs/binder/ndk/include_apex/android/binder_manager.h
new file mode 100644
index 0000000..b8f38ba
--- /dev/null
+++ b/libs/binder/ndk/include_apex/android/binder_manager.h
@@ -0,0 +1,35 @@
+/*
+ * 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>
+
+__BEGIN_DECLS
+
+/**
+ * This registers the service with the default service manager under this instance name.
+ */
+binder_status_t AServiceManager_addService(AIBinder* binder, const char* instance);
+
+/**
+ * Gets a binder object with this specific instance name. Blocks for a couple of seconds waiting on
+ * it. This also implicitly calls AIBinder_incStrong (so the caller of this function is responsible
+ * for calling AIBinder_decStrong).
+ */
+__attribute__((warn_unused_result)) AIBinder* AServiceManager_getService(const char* instance);
+
+__END_DECLS
diff --git a/libs/binder/ndk/include_apex/android/binder_process.h b/libs/binder/ndk/include_apex/android/binder_process.h
new file mode 100644
index 0000000..69e6387
--- /dev/null
+++ b/libs/binder/ndk/include_apex/android/binder_process.h
@@ -0,0 +1,40 @@
+/*
+ * 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 <stdint.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+/**
+ * This creates a threadpool for incoming binder transactions if it has not already been created.
+ */
+void ABinderProcess_startThreadPool();
+/**
+ * This sets the maximum number of threads that can be started in the threadpool. By default, after
+ * startThreadPool is called, this is one. If it is called additional times, it will only prevent
+ * the kernel from starting new threads and will not delete already existing threads.
+ */
+bool ABinderProcess_setThreadPoolMaxThreadCount(uint32_t numThreads);
+/**
+ * This adds the current thread to the threadpool. This may cause the threadpool to exceed the
+ * maximum size.
+ */
+void ABinderProcess_joinThreadPool();
+
+__END_DECLS
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
new file mode 100644
index 0000000..23136a2
--- /dev/null
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -0,0 +1,247 @@
+/*
+ * 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 <stdint.h>
+#include <sys/cdefs.h>
+
+#include <android/binder_parcel.h>
+#include <android/binder_status.h>
+
+__BEGIN_DECLS
+
+// Also see TF_* in kernel's binder.h
+typedef uint32_t binder_flags_t;
+enum {
+ /**
+ * The transaction will be dispatched and then returned to the caller. The outgoing process
+ * cannot block a call made by this, and execution of the call will not be waited on. An error
+ * can still be returned if the call is unable to be processed by the binder driver. All oneway
+ * calls are guaranteed to be ordered if they are sent on the same AIBinder object.
+ */
+ FLAG_ONEWAY = 0x01,
+};
+
+// Also see IBinder.h in libbinder
+typedef uint32_t transaction_code_t;
+enum {
+ /**
+ * The first transaction code available for user commands (inclusive).
+ */
+ FIRST_CALL_TRANSACTION = 0x00000001,
+ /**
+ * The last transaction code available for user commands (inclusive).
+ */
+ LAST_CALL_TRANSACTION = 0x00ffffff,
+};
+
+/**
+ * Represents a type of AIBinder object which can be sent out.
+ */
+struct AIBinder_Class;
+typedef struct AIBinder_Class AIBinder_Class;
+
+/**
+ * Represents a local or remote object which can be used for IPC or which can itself be sent.
+ *
+ * This object has a refcount associated with it and will be deleted when its refcount reaches zero.
+ * How methods interactive with this refcount is described below. When using this API, it is
+ * intended for a client of a service to hold a strong reference to that service. This also means
+ * that user data typically should hold a strong reference to a local AIBinder object. A remote
+ * AIBinder object automatically holds a strong reference to the AIBinder object in the server's
+ * process. A typically memory layout looks like this:
+ *
+ * Key:
+ * ---> Ownership/a strong reference
+ * ...> A weak reference
+ *
+ * (process boundary)
+ * |
+ * MyInterface ---> AIBinder_Weak | ProxyForMyInterface
+ * ^ . | |
+ * | . | |
+ * | v | v
+ * UserData <--- AIBinder <-|- AIBinder
+ * |
+ *
+ * In this way, you'll notice that a proxy for the interface holds a strong reference to the
+ * implementation and that in the server process, the AIBinder object which was sent can be resent
+ * so that the same AIBinder object always represents the same object. This allows, for instance, an
+ * implementation (usually a callback) to transfer all ownership to a remote process and
+ * automatically be deleted when the remote process is done with it or dies. Other memory models are
+ * possible, but this is the standard one.
+ */
+struct AIBinder;
+typedef struct AIBinder AIBinder;
+
+/**
+ * The AIBinder object associated with this can be retrieved if it is still alive so that it can be
+ * re-used. The intention of this is to enable the same AIBinder object to always represent the same
+ * object.
+ */
+struct AIBinder_Weak;
+typedef struct AIBinder_Weak AIBinder_Weak;
+
+/**
+ * This is called whenever a new AIBinder object is needed of a specific class.
+ *
+ * These arguments are passed from AIBinder_new. The return value is stored and can be retrieved
+ * using AIBinder_getUserData.
+ */
+typedef void* (*AIBinder_Class_onCreate)(void* args);
+
+/**
+ * This is called whenever an AIBinder object is no longer referenced and needs destroyed.
+ *
+ * Typically, this just deletes whatever the implementation is.
+ */
+typedef void (*AIBinder_Class_onDestroy)(void* userData);
+
+/**
+ * This is called whenever a transaction needs to be processed by a local implementation.
+ */
+typedef binder_status_t (*AIBinder_Class_onTransact)(AIBinder* binder, transaction_code_t code,
+ const AParcel* in, AParcel* out);
+
+/**
+ * An interfaceDescriptor uniquely identifies the type of object that is being created. This is used
+ * internally for sanity checks on transactions.
+ *
+ * None of these parameters can be nullptr.
+ *
+ * This is created one time during library initialization and cleaned up when the process exits or
+ * execs.
+ */
+__attribute__((warn_unused_result)) AIBinder_Class* AIBinder_Class_define(
+ const char* interfaceDescriptor, AIBinder_Class_onCreate onCreate,
+ AIBinder_Class_onDestroy onDestroy, AIBinder_Class_onTransact onTransact);
+
+/**
+ * Creates a new binder object of the appropriate class.
+ *
+ * Ownership of args is passed to this object. The lifecycle is implemented with AIBinder_incStrong
+ * and AIBinder_decStrong. When the reference count reaches zero, onDestroy is called.
+ *
+ * When this is called, the refcount is implicitly 1. So, calling decStrong exactly one time is
+ * required to delete this object.
+ */
+__attribute__((warn_unused_result)) AIBinder* AIBinder_new(const AIBinder_Class* clazz, void* args);
+
+/**
+ * If this is hosted in a process other than the current one.
+ */
+bool AIBinder_isRemote(AIBinder* binder);
+
+/**
+ * This can only be called if a strong reference to this object already exists in process.
+ */
+void AIBinder_incStrong(AIBinder* binder);
+
+/**
+ * This will delete the object and call onDestroy once the refcount reaches zero.
+ */
+void AIBinder_decStrong(AIBinder* binder);
+
+/**
+ * For debugging only!
+ */
+int32_t AIBinder_debugGetRefCount(AIBinder* binder);
+
+/**
+ * This sets the class of an AIBinder object. This checks to make sure the remote object is of
+ * the expected class. A class must be set in order to use transactions on an AIBinder object.
+ * However, if an object is just intended to be passed through to another process or used as a
+ * handle this need not be called.
+ *
+ * The binder parameter may or may not be updated. If it is updated, the ownership of the original
+ * object is transferred to the new object. If the class association fails, ownership of the binder
+ * is lost, and it is set to nullptr.
+ */
+void AIBinder_associateClass(AIBinder** binder, const AIBinder_Class* clazz);
+
+/*
+ * Returns the class that this binder was constructed with or associated with.
+ */
+const AIBinder_Class* AIBinder_getClass(AIBinder* binder);
+
+/**
+ * Value returned by onCreate for a local binder. For stateless classes (if onCreate returns
+ * nullptr), this also returns nullptr. For a remote binder, this will always return nullptr.
+ */
+void* AIBinder_getUserData(AIBinder* binder);
+
+/**
+ * A transaction is a series of calls to these functions which looks this
+ * - call AIBinder_prepareTransaction
+ * - fill out parcel with in parameters (lifetime of the 'in' variable)
+ * - call AIBinder_transact
+ * - fill out parcel with out parameters (lifetime of the 'out' variable)
+ * - call AIBinder_finalizeTransaction
+ */
+
+/**
+ * Creates a parcel to start filling out for a transaction. This may add data to the parcel for
+ * security, debugging, or other purposes. This parcel is to be sent via AIBinder_transact and it
+ * represents the input data to the transaction. It is recommended to check if the object is local
+ * and call directly into its user data before calling this as the parceling and unparceling cost
+ * can be avoided. This AIBinder must be either built with a class or associated with a class before
+ * using this API.
+ *
+ * This does not affect the ownership of binder.
+ */
+binder_status_t AIBinder_prepareTransaction(AIBinder* binder, AParcel** in);
+
+/**
+ * Transact using a parcel created from AIBinder_prepareTransaction. This actually communicates with
+ * the object representing this binder object. This also passes out a parcel to be used for the
+ * return transaction. This takes ownership of the in parcel and automatically deletes it after it
+ * is sent to the remote process. The output parcel is the result of the transaction. If the
+ * transaction has FLAG_ONEWAY, the out parcel will be empty. Otherwise, this will block until the
+ * remote process has processed the transaction, and the out parcel will contain the output data
+ * from transaction.
+ *
+ * This does not affect the ownership of binder.
+ */
+binder_status_t AIBinder_transact(AIBinder* binder, transaction_code_t code, AParcel** in,
+ AParcel** out, binder_flags_t flags);
+
+/**
+ * This takes ownership of the out parcel and automatically deletes it. Additional checks for
+ * security or debugging maybe performed internally.
+ *
+ * This does not affect the ownership of binder.
+ */
+binder_status_t AIBinder_finalizeTransaction(AIBinder* binder, AParcel** out);
+
+/*
+ * This does not take any ownership of the input binder, but it can be used to retrieve it if
+ * something else in some process still holds a reference to it.
+ */
+__attribute__((warn_unused_result)) AIBinder_Weak* AIBinder_Weak_new(AIBinder* binder);
+
+/*
+ * Deletes the weak reference. This will have no impact on the lifetime of the binder.
+ */
+void AIBinder_Weak_delete(AIBinder_Weak* weakBinder);
+
+/**
+ * If promotion succeeds, result will have one strong refcount added to it. Otherwise, this returns
+ * nullptr.
+ */
+__attribute__((warn_unused_result)) AIBinder* AIBinder_Weak_promote(AIBinder_Weak* weakBinder);
+
+__END_DECLS
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel.h b/libs/binder/ndk/include_ndk/android/binder_parcel.h
new file mode 100644
index 0000000..091ae8e
--- /dev/null
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel.h
@@ -0,0 +1,147 @@
+/*
+ * 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 <sys/cdefs.h>
+
+#include <android/binder_status.h>
+
+struct AIBinder;
+typedef struct AIBinder AIBinder;
+
+__BEGIN_DECLS
+
+/**
+ * This object represents a package of data that can be sent between processes. When transacting, an
+ * instance of it is automatically created to be used for the transaction. When two processes use
+ * binder to communicate, they must agree on a format of this parcel to be used in order to transfer
+ * data. This is usually done in an IDL (see AIDL, specificially).
+ */
+struct AParcel;
+typedef struct AParcel AParcel;
+
+/**
+ * Writes an AIBinder to the next location in a non-null parcel. Can be null.
+ */
+binder_status_t AParcel_writeStrongBinder(AParcel* parcel, AIBinder* binder);
+
+/**
+ * Reads an AIBinder from the next location in a non-null parcel. This will fail if the binder is
+ * non-null. One strong ref-count of ownership is passed to the caller of this function.
+ */
+binder_status_t AParcel_readStrongBinder(const AParcel* parcel, AIBinder** binder);
+
+/**
+ * Reads an AIBinder from the next location in a non-null parcel. This may read a null. One strong
+ * ref-count of ownership is passed to the caller of this function.
+ */
+binder_status_t AParcel_readNullableStrongBinder(const AParcel* parcel, AIBinder** binder);
+
+// @START
+/**
+ * Writes int32_t value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeInt32(AParcel* parcel, int32_t value);
+
+/**
+ * Writes uint32_t value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeUint32(AParcel* parcel, uint32_t value);
+
+/**
+ * Writes int64_t value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeInt64(AParcel* parcel, int64_t value);
+
+/**
+ * Writes uint64_t value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeUint64(AParcel* parcel, uint64_t value);
+
+/**
+ * Writes float value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeFloat(AParcel* parcel, float value);
+
+/**
+ * Writes double value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeDouble(AParcel* parcel, double value);
+
+/**
+ * Writes bool value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeBool(AParcel* parcel, bool value);
+
+/**
+ * Writes char16_t value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeChar(AParcel* parcel, char16_t value);
+
+/**
+ * Writes int8_t value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeByte(AParcel* parcel, int8_t value);
+
+/**
+ * Reads into int32_t value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readInt32(const AParcel* parcel, int32_t* value);
+
+/**
+ * Reads into uint32_t value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readUint32(const AParcel* parcel, uint32_t* value);
+
+/**
+ * Reads into int64_t value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readInt64(const AParcel* parcel, int64_t* value);
+
+/**
+ * Reads into uint64_t value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readUint64(const AParcel* parcel, uint64_t* value);
+
+/**
+ * Reads into float value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readFloat(const AParcel* parcel, float* value);
+
+/**
+ * Reads into double value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readDouble(const AParcel* parcel, double* value);
+
+/**
+ * Reads into bool value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readBool(const AParcel* parcel, bool* value);
+
+/**
+ * Reads into char16_t value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readChar(const AParcel* parcel, char16_t* value);
+
+/**
+ * Reads into int8_t value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readByte(const AParcel* parcel, int8_t* value);
+
+// @END
+
+__END_DECLS
diff --git a/libs/binder/ndk/include_ndk/android/binder_status.h b/libs/binder/ndk/include_ndk/android/binder_status.h
new file mode 100644
index 0000000..d414c99
--- /dev/null
+++ b/libs/binder/ndk/include_ndk/android/binder_status.h
@@ -0,0 +1,56 @@
+/*
+ * 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 <stdint.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+// Keep the exception codes in sync with android/os/Parcel.java.
+enum {
+ EX_NONE = 0,
+ EX_SECURITY = -1,
+ EX_BAD_PARCELABLE = -2,
+ EX_ILLEGAL_ARGUMENT = -3,
+ EX_NULL_POINTER = -4,
+ EX_ILLEGAL_STATE = -5,
+ EX_NETWORK_MAIN_THREAD = -6,
+ EX_UNSUPPORTED_OPERATION = -7,
+ EX_SERVICE_SPECIFIC = -8,
+ EX_PARCELABLE = -9,
+
+ /**
+ * This is special and Java specific; see Parcel.java.
+ * This should be considered a success, and the next readInt32 bytes can be ignored.
+ */
+ EX_HAS_REPLY_HEADER = -128,
+
+ /**
+ * This is special, and indicates to native binder proxies that the
+ * transaction has failed at a low level.
+ */
+ EX_TRANSACTION_FAILED = -129,
+};
+
+/**
+ * One of the above values or -errno.
+ * By convention, positive values are considered to mean service-specific exceptions.
+ */
+typedef int32_t binder_status_t;
+
+__END_DECLS
diff --git a/libs/binder/ndk/runtests.sh b/libs/binder/ndk/runtests.sh
new file mode 100755
index 0000000..6c8527d
--- /dev/null
+++ b/libs/binder/ndk/runtests.sh
@@ -0,0 +1,40 @@
+#!/usr/bin/env bash
+
+# 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.
+
+if [ -z $ANDROID_BUILD_TOP ]; then
+ echo "You need to source and lunch before you can use this script"
+ exit 1
+fi
+
+set -ex
+
+function run_libbinder_ndk_test() {
+ adb shell /data/nativetest64/libbinder_ndk_test_server/libbinder_ndk_test_server &
+ local pid=$!
+ trap "kill $pid" ERR
+ adb shell /data/nativetest64/libbinder_ndk_test_client/libbinder_ndk_test_client
+ trap '' ERR
+ kill $pid
+}
+
+[ "$1" != "--skip-build" ] && $ANDROID_BUILD_TOP/build/soong/soong_ui.bash --make-mode \
+ MODULES-IN-frameworks-native-libs-binder-ndk
+
+adb root
+adb wait-for-device
+adb sync data
+
+run_libbinder_ndk_test
diff --git a/libs/binder/ndk/scripts/format.sh b/libs/binder/ndk/scripts/format.sh
new file mode 100755
index 0000000..698d291
--- /dev/null
+++ b/libs/binder/ndk/scripts/format.sh
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+
+# 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.
+
+set -e
+
+echo "Formatting code"
+
+bpfmt -w $(find $ANDROID_BUILD_TOP/frameworks/native/libs/binder/ndk/ -name "Android.bp")
+clang-format -i $(find $ANDROID_BUILD_TOP/frameworks/native/libs/binder/ndk/ -\( -name "*.cpp" -o -name "*.h" -\))
diff --git a/libs/binder/ndk/scripts/gen_parcel_helper.py b/libs/binder/ndk/scripts/gen_parcel_helper.py
new file mode 100755
index 0000000..5c0b936
--- /dev/null
+++ b/libs/binder/ndk/scripts/gen_parcel_helper.py
@@ -0,0 +1,89 @@
+#!/usr/bin/env python3
+
+# 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.
+
+import os
+import sys
+
+# list (pretty, cpp)
+data_types = [
+ ("Int32", "int32_t"),
+ ("Uint32", "uint32_t"),
+ ("Int64", "int64_t"),
+ ("Uint64", "uint64_t"),
+ ("Float", "float"),
+ ("Double", "double"),
+ ("Bool", "bool"),
+ ("Char", "char16_t"),
+ ("Byte", "int8_t"),
+]
+
+def replaceFileTags(path, content):
+ print("Updating", path)
+ with open(path, "r+") as f:
+ lines = f.readlines()
+
+ start = lines.index("// @START\n")
+ end = lines.index("// @END\n")
+
+ if end <= start or start < 0 or end < 0:
+ print("Failed to find tags in", path)
+ exit(1)
+
+ f.seek(0)
+ f.write("".join(lines[:start+1]) + content + "".join(lines[end:]))
+ f.truncate()
+
+def main():
+ if len(sys.argv) != 1:
+ print("No arguments.")
+ exit(1)
+
+ ABT = os.environ.get('ANDROID_BUILD_TOP', None)
+ if ABT is None:
+ print("Can't get ANDROID_BUILD_TOP. Lunch?")
+ exit(1)
+ ROOT = ABT + "/frameworks/native/libs/binder/ndk/"
+
+ print("Updating auto-generated code")
+
+ header = ""
+ source = ""
+
+ for pretty, cpp in data_types:
+ header += "/**\n"
+ header += " * Writes " + cpp + " value to the next location in a non-null parcel.\n"
+ header += " */\n"
+ header += "binder_status_t AParcel_write" + pretty + "(AParcel* parcel, " + cpp + " value);\n\n"
+ source += "binder_status_t AParcel_write" + pretty + "(AParcel* parcel, " + cpp + " value) {\n"
+ source += " return (*parcel)->write" + pretty + "(value);\n"
+ source += "}\n\n"
+
+ for pretty, cpp in data_types:
+ header += "/**\n"
+ header += " * Reads into " + cpp + " value from the next location in a non-null parcel.\n"
+ header += " */\n"
+ header += "binder_status_t AParcel_read" + pretty + "(const AParcel* parcel, " + cpp + "* value);\n\n"
+ source += "binder_status_t AParcel_read" + pretty + "(const AParcel* parcel, " + cpp + "* value) {\n"
+ source += " return (*parcel)->read" + pretty + "(value);\n"
+ source += "}\n\n"
+
+ replaceFileTags(ROOT + "include_ndk/android/binder_parcel.h", header)
+ replaceFileTags(ROOT + "AParcel.cpp", source)
+
+ print("Updating DONE.")
+
+if __name__ == "__main__":
+ main()
diff --git a/libs/binder/ndk/test/Android.bp b/libs/binder/ndk/test/Android.bp
new file mode 100644
index 0000000..d242138
--- /dev/null
+++ b/libs/binder/ndk/test/Android.bp
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+// This test is a unit test of the low-level API that is presented here.
+// Actual users should use AIDL to generate these complicated stubs.
+
+cc_defaults {
+ name: "test_libbinder_ndk_defaults",
+ shared_libs: [
+ "libbase",
+ ],
+ strip: {
+ none: true,
+ },
+ cflags: [
+ "-O0",
+ "-g",
+ ],
+}
+
+cc_library_static {
+ name: "test_libbinder_ndk_library",
+ defaults: ["test_libbinder_ndk_defaults"],
+ export_include_dirs: ["include"],
+ shared_libs: ["libbinder_ndk"],
+ export_shared_lib_headers: ["libbinder_ndk"],
+ srcs: ["iface.cpp"],
+}
+
+cc_defaults {
+ name: "test_libbinder_ndk_test_defaults",
+ defaults: ["test_libbinder_ndk_defaults"],
+ shared_libs: [
+ "libbase",
+ "libbinder",
+ "libutils",
+ ],
+ static_libs: [
+ "libbinder_ndk",
+ "test_libbinder_ndk_library",
+ ],
+}
+
+cc_test {
+ name: "libbinder_ndk_test_client",
+ defaults: ["test_libbinder_ndk_test_defaults"],
+ srcs: ["main_client.cpp"],
+}
+
+cc_test {
+ name: "libbinder_ndk_test_server",
+ defaults: ["test_libbinder_ndk_test_defaults"],
+ srcs: ["main_server.cpp"],
+ gtest: false,
+}
diff --git a/libs/binder/ndk/test/iface.cpp b/libs/binder/ndk/test/iface.cpp
new file mode 100644
index 0000000..eed09f0
--- /dev/null
+++ b/libs/binder/ndk/test/iface.cpp
@@ -0,0 +1,145 @@
+/*
+ * 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.
+ */
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <iface/iface.h>
+
+using ::android::sp;
+using ::android::wp;
+
+const char* IFoo::kSomeInstanceName = "libbinder_ndk-test-IFoo";
+const char* kIFooDescriptor = "my-special-IFoo-class";
+
+struct IFoo_Class_Data {
+ sp<IFoo> foo;
+};
+
+void* IFoo_Class_onCreate(void* args) {
+ IFoo_Class_Data* foo = static_cast<IFoo_Class_Data*>(args);
+ // This is a foo, but we're currently not verifying that. So, the method newLocalBinder is
+ // coupled with this.
+ return static_cast<void*>(foo);
+}
+
+void IFoo_Class_onDestroy(void* userData) {
+ delete static_cast<IFoo_Class_Data*>(userData);
+}
+
+binder_status_t IFoo_Class_onTransact(AIBinder* binder, transaction_code_t code, const AParcel* in,
+ AParcel* out) {
+ binder_status_t stat = EX_UNSUPPORTED_OPERATION;
+
+ sp<IFoo> foo = static_cast<IFoo_Class_Data*>(AIBinder_getUserData(binder))->foo;
+ CHECK(foo != nullptr) << "Transaction made on already deleted object";
+
+ switch (code) {
+ case IFoo::DOFOO: {
+ int32_t valueIn;
+ stat = AParcel_readInt32(in, &valueIn);
+ if (stat != EX_NONE) break;
+ int32_t valueOut = foo->doubleNumber(valueIn);
+ stat = AParcel_writeInt32(out, valueOut);
+ break;
+ }
+ }
+
+ return stat;
+}
+
+AIBinder_Class* IFoo::kClass = AIBinder_Class_define(kIFooDescriptor, IFoo_Class_onCreate,
+ IFoo_Class_onDestroy, IFoo_Class_onTransact);
+
+class BpFoo : public IFoo {
+public:
+ BpFoo(AIBinder* binder) : mBinder(binder) {}
+ virtual ~BpFoo() { AIBinder_decStrong(mBinder); }
+
+ virtual int32_t doubleNumber(int32_t in) {
+ AParcel* parcelIn;
+ CHECK(EX_NONE == AIBinder_prepareTransaction(mBinder, &parcelIn));
+
+ CHECK(EX_NONE == AParcel_writeInt32(parcelIn, in));
+
+ AParcel* parcelOut;
+ CHECK(EX_NONE ==
+ AIBinder_transact(mBinder, IFoo::DOFOO, &parcelIn, &parcelOut, 0 /*flags*/));
+
+ int32_t out;
+ CHECK(EX_NONE == AParcel_readInt32(parcelOut, &out));
+
+ CHECK(EX_NONE == AIBinder_finalizeTransaction(mBinder, &parcelOut));
+ return out;
+ }
+
+private:
+ // Always assumes one refcount
+ AIBinder* mBinder;
+};
+
+IFoo::~IFoo() {
+ AIBinder_Weak_delete(mWeakBinder);
+}
+
+binder_status_t IFoo::addService(const char* instance) {
+ AIBinder* binder = nullptr;
+
+ if (mWeakBinder != nullptr) {
+ // one strong ref count of binder
+ binder = AIBinder_Weak_promote(mWeakBinder);
+ }
+ if (binder == nullptr) {
+ // or one strong refcount here
+ binder = AIBinder_new(IFoo::kClass, static_cast<void*>(new IFoo_Class_Data{this}));
+ if (mWeakBinder != nullptr) {
+ AIBinder_Weak_delete(mWeakBinder);
+ }
+ mWeakBinder = AIBinder_Weak_new(binder);
+ }
+
+ binder_status_t status = AServiceManager_addService(binder, instance);
+ // Strong references we care about kept by remote process
+ AIBinder_decStrong(binder);
+ return status;
+}
+
+sp<IFoo> IFoo::getService(const char* instance) {
+ AIBinder* binder = AServiceManager_getService(instance); // maybe nullptr
+ AIBinder_associateClass(&binder, IFoo::kClass);
+
+ if (binder == nullptr) {
+ return nullptr;
+ }
+
+ if (AIBinder_isRemote(binder)) {
+ sp<IFoo> ret = new BpFoo(binder); // takes ownership of binder
+ return ret;
+ }
+
+ IFoo_Class_Data* data = static_cast<IFoo_Class_Data*>(AIBinder_getUserData(binder));
+
+ CHECK(data != nullptr); // always created with non-null data
+
+ sp<IFoo> ret = data->foo;
+
+ AIBinder* held = AIBinder_Weak_promote(ret->mWeakBinder);
+ CHECK(held == binder);
+ AIBinder_decStrong(held);
+
+ // IFoo only keeps a weak reference to AIBinder, so we can drop this
+ AIBinder_decStrong(binder);
+ return ret;
+}
diff --git a/libs/binder/ndk/test/include/iface/iface.h b/libs/binder/ndk/test/include/iface/iface.h
new file mode 100644
index 0000000..4c61e9d
--- /dev/null
+++ b/libs/binder/ndk/test/include/iface/iface.h
@@ -0,0 +1,40 @@
+/*
+ * 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 <utils/RefBase.h>
+
+class IFoo : public virtual ::android::RefBase {
+public:
+ static const char* kSomeInstanceName;
+ static AIBinder_Class* kClass;
+
+ // Takes ownership of IFoo
+ binder_status_t addService(const char* instance);
+ static ::android::sp<IFoo> getService(const char* instance);
+
+ enum Call {
+ DOFOO = FIRST_CALL_TRANSACTION + 0,
+ };
+
+ virtual ~IFoo();
+ virtual int32_t doubleNumber(int32_t in) = 0;
+
+private:
+ AIBinder_Weak* mWeakBinder = nullptr; // maybe owns AIBinder
+};
diff --git a/libs/binder/ndk/test/main_client.cpp b/libs/binder/ndk/test/main_client.cpp
new file mode 100644
index 0000000..7c53e51
--- /dev/null
+++ b/libs/binder/ndk/test/main_client.cpp
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <gtest/gtest.h>
+#include <iface/iface.h>
+
+using ::android::sp;
+
+constexpr char kExistingNonNdkService[] = "SurfaceFlinger";
+
+// This is too slow
+// TEST(NdkBinder, GetServiceThatDoesntExist) {
+// sp<IFoo> foo = IFoo::getService("asdfghkl;");
+// EXPECT_EQ(nullptr, foo.get());
+// }
+
+TEST(NdkBinder, DoubleNumber) {
+ sp<IFoo> foo = IFoo::getService(IFoo::kSomeInstanceName);
+ ASSERT_NE(foo, nullptr);
+ EXPECT_EQ(2, foo->doubleNumber(1));
+}
+
+TEST(NdkBinder, RetrieveNonNdkService) {
+ AIBinder* binder = AServiceManager_getService(kExistingNonNdkService);
+ ASSERT_NE(nullptr, binder);
+ AIBinder_decStrong(binder);
+}
+
+class MyTestFoo : public IFoo {
+ int32_t doubleNumber(int32_t in) override {
+ LOG(INFO) << "doubleNumber " << in;
+ return 2 * in;
+ }
+};
+
+TEST(NdkBinder, GetServiceInProcess) {
+ static const char* kInstanceName = "test-get-service-in-process";
+
+ sp<IFoo> foo = new MyTestFoo;
+ EXPECT_EQ(EX_NONE, foo->addService(kInstanceName));
+
+ sp<IFoo> getFoo = IFoo::getService(kInstanceName);
+ EXPECT_EQ(foo.get(), getFoo.get());
+
+ EXPECT_EQ(2, getFoo->doubleNumber(1));
+}
+
+TEST(NdkBinder, AddServiceMultipleTimes) {
+ static const char* kInstanceName1 = "test-multi-1";
+ static const char* kInstanceName2 = "test-multi-2";
+ sp<IFoo> foo = new MyTestFoo;
+ EXPECT_EQ(EX_NONE, foo->addService(kInstanceName1));
+ EXPECT_EQ(EX_NONE, foo->addService(kInstanceName2));
+ EXPECT_EQ(IFoo::getService(kInstanceName1), IFoo::getService(kInstanceName2));
+}
diff --git a/libs/binder/ndk/test/main_server.cpp b/libs/binder/ndk/test/main_server.cpp
new file mode 100644
index 0000000..f3da7da
--- /dev/null
+++ b/libs/binder/ndk/test/main_server.cpp
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+#include <android-base/logging.h>
+#include <android/binder_process.h>
+#include <iface/iface.h>
+
+using ::android::sp;
+
+class MyFoo : public IFoo {
+ int32_t doubleNumber(int32_t in) override {
+ LOG(INFO) << "doubling " << in;
+ return 2 * in;
+ }
+};
+
+int main() {
+ ABinderProcess_setThreadPoolMaxThreadCount(0);
+
+ // Strong reference to MyFoo kept by service manager.
+ binder_status_t status = (new MyFoo)->addService(IFoo::kSomeInstanceName);
+
+ if (status != EX_NONE) {
+ LOG(FATAL) << "Could not register: " << status;
+ }
+
+ ABinderProcess_joinThreadPool();
+
+ return 1;
+}
diff --git a/libs/binder/ndk/update.sh b/libs/binder/ndk/update.sh
new file mode 100755
index 0000000..1eba892
--- /dev/null
+++ b/libs/binder/ndk/update.sh
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+
+# 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.
+
+
+set -ex
+
+# This script makes sure that the source code is in sync with the various scripts
+./scripts/gen_parcel_helper.py
+./scripts/format.sh