aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierre Langlois <pierre.langlois@arm.com>2015-01-21 16:01:17 +0000
committerPierre Langlois <pierre.langlois@arm.com>2016-03-04 17:49:52 +0000
commitfbdca08f39cf1a5a2aaeccb51b9e17e7aba13cb4 (patch)
treecc538ed907ffedfa355f2c12a8ca216e275efc55
parent1f5cc8ec2c7975031357bccec31c3b3894d61e11 (diff)
downloadkdbinder-fbdca08f39cf1a5a2aaeccb51b9e17e7aba13cb4.tar.gz
libkdbinder: import Binder object abstraction
This patch brings in a minimal implementation of Binder objects, taken from libbinder. It allows for an object to implement the IBinder interface, which represent the entry point for either a remote or local call to a method. A Binder object always implements a `transact` method: ~~~ class IBinder { public: virtual status_t transact(uint32_t code, uint32_t flags = 0) = 0; }; ~~~ It is then specialized in either a remote or local method call with BBinder (local) and BpBinder (remote). BBinder add a `onTransact` method which will be called locally by `transact`: ~~~ class BBinder : public IBinder { public: status_t transact(uint32_t code, uint32_t flags = 0) override { return onTransact(code, flags); } protected: virtual status_t onTransact(uint32_t code, uint32_t flags = 0) { return UNKNOWN_TRANSACTION; } }; ~~~ BpBinder adds an additional member to identify the target process on the bus, refered to as the handle. It will be a connection ID for KDBUS: ~~~ class BpBinder : public IBinder { public: BpBinder(int32_t handle) : mHandle(handle) {} status_t transact(uint32_t code, uint32_t flags = 0) override { // Send the code to the client on the bus with ID mHandle. return NO_ERROR; } private: const int32_t mHandle; }; ~~~ Change-Id: I0c5d126c3bf71d55f8a9f0e1bfb70e0fdce2350e
-rw-r--r--include/kdbinder/binder/Binder.h87
-rw-r--r--include/kdbinder/binder/BpBinder.h68
-rw-r--r--include/kdbinder/binder/IBinder.h121
-rw-r--r--libs/kdbinder/Android.mk17
-rw-r--r--libs/kdbinder/binder/Binder.cpp130
-rw-r--r--libs/kdbinder/binder/BpBinder.cpp72
6 files changed, 490 insertions, 5 deletions
diff --git a/include/kdbinder/binder/Binder.h b/include/kdbinder/binder/Binder.h
new file mode 100644
index 0000000..b08a5dd
--- /dev/null
+++ b/include/kdbinder/binder/Binder.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef INCLUDE_KDBINDER_BINDER_BINDER_H_
+#define INCLUDE_KDBINDER_BINDER_BINDER_H_
+
+#include <binder/IBinder.h>
+#include <utils/Errors.h>
+#include <utils/String16.h>
+
+namespace android {
+
+class BBinder : public IBinder {
+ public:
+ BBinder();
+
+ virtual const String16& getInterfaceDescriptor() const;
+ bool isBinderAlive() const override;
+
+ status_t transact(uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0) override;
+ BBinder* localBinder() override;
+ status_t pingBinder() override;
+
+ status_t linkToDeath(const sp<DeathRecipient>& recipient,
+ void* cookie = NULL,
+ uint32_t flags = 0) override;
+
+ status_t unlinkToDeath(const wp<DeathRecipient>& recipient,
+ void* cookie = NULL,
+ uint32_t flags = 0,
+ wp<DeathRecipient>* outRecipient = NULL) override;
+
+ protected:
+ virtual ~BBinder();
+ virtual status_t onTransact(uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+
+ private:
+ BBinder(const BBinder& o);
+ BBinder& operator=(const BBinder& o);
+};
+
+class BpRefBase : public virtual RefBase {
+ protected:
+ explicit BpRefBase(const sp<IBinder>& o);
+ virtual ~BpRefBase();
+ void onFirstRef() override;
+ void onLastStrongRef(const void* id) override;
+ bool onIncStrongAttempted(uint32_t flags, const void* id) override;
+
+ inline IBinder* remote() {
+ return mRemote;
+ }
+ inline IBinder* remote() const {
+ return mRemote;
+ }
+
+ private:
+ BpRefBase(const BpRefBase& o);
+ BpRefBase& operator=(const BpRefBase& o);
+
+ IBinder* const mRemote;
+ RefBase::weakref_type* mRefs;
+ volatile int32_t mState;
+};
+
+} // namespace android
+
+#endif // INCLUDE_KDBINDER_BINDER_BINDER_H_
diff --git a/include/kdbinder/binder/BpBinder.h b/include/kdbinder/binder/BpBinder.h
new file mode 100644
index 0000000..49fe816
--- /dev/null
+++ b/include/kdbinder/binder/BpBinder.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef INCLUDE_KDBINDER_BINDER_BPBINDER_H_
+#define INCLUDE_KDBINDER_BINDER_BPBINDER_H_
+
+#include <binder/IBinder.h>
+
+#include <utils/Errors.h>
+#include <utils/String16.h>
+
+namespace android {
+
+class BpBinder : public IBinder {
+ public:
+ explicit BpBinder(int32_t handle);
+
+ inline int32_t handle() const {
+ return mHandle;
+ }
+
+ status_t transact(uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0) override;
+
+ bool isBinderAlive() const override;
+
+ BpBinder* remoteBinder() override;
+ status_t pingBinder() override;
+
+ const String16& getInterfaceDescriptor() const override;
+
+ status_t linkToDeath(const sp<DeathRecipient>& recipient,
+ void* cookie = NULL,
+ uint32_t flags = 0) override;
+
+ status_t unlinkToDeath(const wp<DeathRecipient>& recipient,
+ void* cookie = NULL,
+ uint32_t flags = 0,
+ wp<DeathRecipient>* outRecipient = NULL) override;
+
+ void sendObituary();
+
+ protected:
+ virtual ~BpBinder();
+
+ private:
+ mutable String16 mDescriptorCache;
+ const int32_t mHandle;
+};
+
+} // namespace android
+
+#endif // INCLUDE_KDBINDER_BINDER_BPBINDER_H_
diff --git a/include/kdbinder/binder/IBinder.h b/include/kdbinder/binder/IBinder.h
new file mode 100644
index 0000000..b2d7b25
--- /dev/null
+++ b/include/kdbinder/binder/IBinder.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef INCLUDE_KDBINDER_BINDER_IBINDER_H_
+#define INCLUDE_KDBINDER_BINDER_IBINDER_H_
+
+#include <utils/RefBase.h>
+#include <utils/Errors.h>
+#include <utils/String16.h>
+
+#define B_PACK_CHARS(c1, c2, c3, c4) \
+ ((((c1) << 24)) | (((c2) << 16)) | (((c3) << 8)) | (c4))
+
+namespace android {
+
+class BBinder;
+class BpBinder;
+class Parcel;
+class IInterface;
+
+class IBinder : public virtual RefBase {
+ public:
+ enum {
+ FIRST_CALL_TRANSACTION = 0x00000001,
+ LAST_CALL_TRANSACTION = 0x00ffffff,
+ INTERFACE_TRANSACTION = B_PACK_CHARS('_', 'N', 'T', 'F'),
+ PING_TRANSACTION = B_PACK_CHARS('_', 'P', 'N', 'G'),
+ FLAG_ONEWAY = 0x00000001
+ };
+
+ IBinder();
+
+ /**
+ * Check if this IBinder implements the interface named by
+ * @a descriptor. If it does, the base pointer to it is returned,
+ * which you can safely static_cast<> to the concrete C++ interface.
+ */
+ // TODO: import IInterface
+ virtual sp<IInterface> queryLocalInterface(
+ const String16& descriptor) = delete;
+
+ /**
+ * Return the canonical name of the interface provided by this IBinder
+ * object.
+ */
+ virtual const String16& getInterfaceDescriptor() const = 0;
+ virtual bool isBinderAlive() const = 0;
+
+ virtual status_t transact(uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0) = 0;
+
+ virtual status_t pingBinder() = 0;
+
+ class DeathRecipient : public virtual RefBase {
+ public:
+ virtual void binderDied(const wp<IBinder>& who) = 0;
+ };
+
+ /**
+ * Register the @a recipient for a notification if this binder
+ * goes away. If this binder object unexpectedly goes away
+ * (typically because its hosting process has been killed),
+ * then DeathRecipient::binderDied() will be called with a reference
+ * to this.
+ *
+ * The @a cookie is optional -- if non-NULL, it should be a
+ * memory address that you own (that is, you know it is unique).
+ *
+ * @note You will only receive death notifications for remote binders,
+ * as local binders by definition can't die without you dying as well.
+ * Trying to use this function on a local binder will result in an
+ * INVALID_OPERATION code being returned and nothing happening.
+ *
+ * @note This link always holds a weak reference to its recipient.
+ *
+ * @note You will only receive a weak reference to the dead
+ * binder. You should not try to promote this to a strong reference.
+ * (Nor should you need to, as there is nothing useful you can
+ * directly do with it now that it has passed on.)
+ */
+ virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
+ void* cookie = NULL,
+ uint32_t flags = 0) = 0;
+
+ /**
+ * Remove a previously registered death notification.
+ * The @a recipient will no longer be called if this object
+ * dies. The @a cookie is optional. If non-NULL, you can
+ * supply a NULL @a recipient, and the recipient previously
+ * added with that cookie will be unlinked.
+ */
+ virtual status_t unlinkToDeath(const wp<DeathRecipient>& recipient,
+ void* cookie = NULL,
+ uint32_t flags = 0,
+ wp<DeathRecipient>* outRecipient = NULL) = 0;
+
+ virtual BBinder* localBinder();
+ virtual BpBinder* remoteBinder();
+
+ protected:
+ virtual ~IBinder();
+};
+
+} // namespace android
+
+#endif // INCLUDE_KDBINDER_BINDER_IBINDER_H_
diff --git a/libs/kdbinder/Android.mk b/libs/kdbinder/Android.mk
index 1f00add..5bc5075 100644
--- a/libs/kdbinder/Android.mk
+++ b/libs/kdbinder/Android.mk
@@ -13,13 +13,20 @@
# limitations under the License.
kdbinder_sources := \
+ binder/Binder.cpp \
+ binder/BpBinder.cpp \
kdbus/bus.cpp \
kdbus/connection.cpp \
kdbus/iterable.cpp \
kdbus/item.cpp \
kdbus/message.cpp
-kdbinder_libs := libcutils
+kdbinder_libs := \
+ libcutils \
+ libutils
+kdbinder_includes := \
+ external/kdbus \
+ frameworks/native/include/kdbinder
kdbinder_cflags := -Werror -std=c++14
kdbinder_cflags_debug := -ggdb3 -O0 -DDEBUG -UNDEBUG
@@ -30,7 +37,7 @@ include $(CLEAR_VARS)
LOCAL_MODULE := libkdbinder
LOCAL_SRC_FILES := $(kdbinder_sources)
LOCAL_CFLAGS += $(kdbinder_cflags)
-LOCAL_C_INCLUDES += external/kdbus
+LOCAL_C_INCLUDES += $(kdbinder_includes)
LOCAL_SHARED_LIBRARIES := $(kdbinder_libs)
LOCAL_CLANG := true
include $(BUILD_SHARED_LIBRARY)
@@ -40,7 +47,7 @@ LOCAL_MODULE := libkdbinderd
LOCAL_MODULE_TAGS := eng
LOCAL_CFLAGS += $(kdbinder_cflags) $(kdbinder_cflags_debug)
LOCAL_SRC_FILES := $(kdbinder_sources)
-LOCAL_C_INCLUDES += external/kdbus
+LOCAL_C_INCLUDES += $(kdbinder_includes)
LOCAL_SHARED_LIBRARIES := $(kdbinder_libs)
LOCAL_CLANG := true
include $(BUILD_SHARED_LIBRARY)
@@ -49,7 +56,7 @@ include $(CLEAR_VARS)
LOCAL_MODULE := libkdbinder
LOCAL_SRC_FILES := $(kdbinder_sources)
LOCAL_CFLAGS += $(kdbinder_cflags)
-LOCAL_C_INCLUDES += external/kdbus
+LOCAL_C_INCLUDES += $(kdbinder_includes)
LOCAL_STATIC_LIBRARIES := $(kdbinder_libs)
LOCAL_CLANG := true
include $(BUILD_STATIC_LIBRARY)
@@ -59,7 +66,7 @@ LOCAL_MODULE := libkdbinderd
LOCAL_MODULE_TAGS := eng
LOCAL_CFLAGS += $(kdbinder_cflags) $(kdbinder_cflags_debug)
LOCAL_SRC_FILES := $(kdbinder_sources)
-LOCAL_C_INCLUDES += external/kdbus
+LOCAL_C_INCLUDES += $(kdbinder_includes)
LOCAL_STATIC_LIBRARIES := $(kdbinder_libs)
LOCAL_CLANG := true
include $(BUILD_STATIC_LIBRARY)
diff --git a/libs/kdbinder/binder/Binder.cpp b/libs/kdbinder/binder/Binder.cpp
new file mode 100644
index 0000000..3899de5
--- /dev/null
+++ b/libs/kdbinder/binder/Binder.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2015 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 <binder/IBinder.h>
+#include <binder/Binder.h>
+
+#include <log/log.h>
+#include <utils/String16.h>
+
+namespace android {
+
+IBinder::IBinder() : RefBase() {}
+
+IBinder::~IBinder() {}
+
+BBinder* IBinder::localBinder() {
+ return nullptr;
+}
+
+BpBinder* IBinder::remoteBinder() {
+ return nullptr;
+}
+
+BBinder::BBinder() {}
+
+BBinder::~BBinder() {}
+
+const String16& BBinder::getInterfaceDescriptor() const {
+ // This is a local static rather than a global static,
+ // to avoid static initializer ordering issues.
+ static String16 sEmptyDescriptor;
+ ALOGW("reached BBinder::getInterfaceDescriptor (this=%p)", this);
+ return sEmptyDescriptor;
+}
+
+status_t BBinder::transact(uint32_t /*code*/,
+ const Parcel& /*data*/,
+ Parcel* /*reply*/,
+ uint32_t /*flags*/) {
+ // TODO: unimplemented.
+ return UNKNOWN_TRANSACTION;
+}
+
+BBinder* BBinder::localBinder() {
+ return this;
+}
+
+
+status_t BBinder::onTransact(uint32_t /*code*/,
+ const Parcel& /*data*/,
+ Parcel* /*reply*/,
+ uint32_t /*flags*/) {
+ return UNKNOWN_TRANSACTION;
+}
+
+status_t BBinder::pingBinder() {
+ return NO_ERROR;
+}
+
+status_t BBinder::linkToDeath(const sp<DeathRecipient>& /*recipient*/,
+ void * /*cookie*/,
+ uint32_t /*flags*/) {
+ return INVALID_OPERATION;
+}
+
+status_t BBinder::unlinkToDeath(const wp<DeathRecipient>& /*recipient*/,
+ void * /*cookie*/,
+ uint32_t /*flags*/,
+ wp<DeathRecipient>* /*outRecipient*/) {
+ return INVALID_OPERATION;
+}
+
+bool BBinder::isBinderAlive() const {
+ return true;
+}
+
+enum {
+ // This is used to transfer ownership of the remote binder from
+ // the BpRefBase object holding it (when it is constructed), to the
+ // owner of the BpRefBase object when it first acquires that BpRefBase.
+ kRemoteAcquired = 0x00000001
+};
+
+BpRefBase::BpRefBase(const sp<IBinder>& o)
+ : mRemote(o.get()), mRefs(NULL), mState(0) {
+ extendObjectLifetime(OBJECT_LIFETIME_WEAK);
+
+ if (mRemote) {
+ mRemote->incStrong(this); // Removed on first IncStrong().
+ mRefs = mRemote->createWeak(this); // Held for our entire lifetime.
+ }
+}
+
+BpRefBase::~BpRefBase() {
+ if (mRemote) {
+ if (!(mState&kRemoteAcquired)) {
+ mRemote->decStrong(this);
+ }
+ mRefs->decWeak(this);
+ }
+}
+
+void BpRefBase::onFirstRef() {
+ android_atomic_or(kRemoteAcquired, &mState);
+}
+
+void BpRefBase::onLastStrongRef(const void* /*id*/) {
+ if (mRemote) {
+ mRemote->decStrong(this);
+ }
+}
+
+bool BpRefBase::onIncStrongAttempted(uint32_t /*flags*/, const void* /*id*/) {
+ return mRemote ? mRefs->attemptIncStrong(this) : false;
+}
+
+} // namespace android
diff --git a/libs/kdbinder/binder/BpBinder.cpp b/libs/kdbinder/binder/BpBinder.cpp
new file mode 100644
index 0000000..2d9252c
--- /dev/null
+++ b/libs/kdbinder/binder/BpBinder.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2015 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 <binder/BpBinder.h>
+
+namespace android {
+
+BpBinder::BpBinder(int32_t handle)
+ : mHandle(handle) {}
+
+BpBinder::~BpBinder() {}
+
+status_t BpBinder::transact(uint32_t /*code*/,
+ const Parcel& /*data*/,
+ Parcel* /*reply*/,
+ uint32_t /*flags*/) {
+ // TODO: dispatch the transaction to a thread.
+ return NO_ERROR;
+}
+
+bool BpBinder::isBinderAlive() const {
+ // TODO: unimplemented.
+ return false;
+}
+
+BpBinder* BpBinder::remoteBinder() {
+ return this;
+}
+
+status_t BpBinder::pingBinder() {
+ // TODO: unimplemented.
+ return FAILED_TRANSACTION;
+}
+
+const String16& BpBinder::getInterfaceDescriptor() const {
+ // TODO: unimplemented.
+ return mDescriptorCache;
+}
+
+status_t BpBinder::linkToDeath(const sp<DeathRecipient>& /*recipient*/,
+ void * /*cookie*/,
+ uint32_t /*flags*/) {
+ // TODO: unimplemented.
+ return FAILED_TRANSACTION;
+}
+
+status_t BpBinder::unlinkToDeath(const wp<DeathRecipient>& /*recipient*/,
+ void * /*cookie*/,
+ uint32_t /*flags*/,
+ wp<DeathRecipient> * /*outRecipient*/) {
+ // TODO: unimplemented.
+ return FAILED_TRANSACTION;
+}
+
+void BpBinder::sendObituary() {
+ // TODO: unimplemented.
+}
+
+} // namespace android