diff options
author | Pierre Langlois <pierre.langlois@arm.com> | 2015-01-21 16:01:17 +0000 |
---|---|---|
committer | Pierre Langlois <pierre.langlois@arm.com> | 2016-03-04 17:49:52 +0000 |
commit | fbdca08f39cf1a5a2aaeccb51b9e17e7aba13cb4 (patch) | |
tree | cc538ed907ffedfa355f2c12a8ca216e275efc55 | |
parent | 1f5cc8ec2c7975031357bccec31c3b3894d61e11 (diff) | |
download | kdbinder-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.h | 87 | ||||
-rw-r--r-- | include/kdbinder/binder/BpBinder.h | 68 | ||||
-rw-r--r-- | include/kdbinder/binder/IBinder.h | 121 | ||||
-rw-r--r-- | libs/kdbinder/Android.mk | 17 | ||||
-rw-r--r-- | libs/kdbinder/binder/Binder.cpp | 130 | ||||
-rw-r--r-- | libs/kdbinder/binder/BpBinder.cpp | 72 |
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 |