aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierre Langlois <pierre.langlois@arm.com>2015-02-02 17:43:41 +0000
committerPierre Langlois <pierre.langlois@arm.com>2016-03-04 17:50:27 +0000
commit8b80c2bd6822ccf515ae0f02d2d48b47cee4c6fe (patch)
treeb95314025926b5e492049835f64736b9cb0e1334
parentfbdca08f39cf1a5a2aaeccb51b9e17e7aba13cb4 (diff)
downloadkdbinder-8b80c2bd6822ccf515ae0f02d2d48b47cee4c6fe.tar.gz
libkdbinder: import IInterface
This patch imports the necessary abstractions to let a user define their own services. The user will use the IInterface base class to describe a new service interface, commonly named IMyService, and then provide both a native and a remote implementation of it. The code in this commit was imported from libbinder, here is what it allows us to do. * High level usage: The service writer can define his/her own interface: ~~~ class IMyService : public IInterface { public: enum Code { SAY_HELLO = 0xab; }; virtual void sayHello() = 0; }; ~~~ The aim is to use this interface in the server and the client, in order to make a remote call to the server look exactly like a local call: ~~~ sp<IBinder> proxy = // We assume we have a binder object refering to the // server. sp<IMyService> service = interface_cast<IMyService>(proxy); // The remote call happens in the server. service->sayHello(); ~~~ * Implementation code for the server and the client: In the same way that Binder objects have a local or remote implementation, so does a service object. This patch imports two base classes for this: BnInterface (native interface) and BpInterface (proxy interface). The service writer will have to implement both in order to describe what data to send and to receive. On the client's side: ~~~ class BpMyService : public BpInterface<IMyService> { public: void sayHello() override { // Get the underlying Binder object and send the code SAY_HELLO. // This is a blocking call. remote()->transact(SAY_HELLO); } }; ~~~ On the server's side: ~~~ class BnMyService : public BnInterface<IMyService> { public: void sayHello() override { printf("Hello\n"); } protected: // Called when receiving a transaction. status_t onTransact(uint32_t code, uint32_t /*flags*/) override { switch (code) { case SAY_HELLO: { sayHello(); return NO_ERROR; } default: return UNKNOWN_TRANSACTION; } } }; ~~~ Change-Id: I9449cf54e62c687aaaa920c20bfaab6a63130aeb
-rw-r--r--include/kdbinder/binder/IBinder.h4
-rw-r--r--include/kdbinder/binder/IInterface.h121
-rw-r--r--libs/kdbinder/Android.mk1
-rw-r--r--libs/kdbinder/binder/Binder.cpp5
-rw-r--r--libs/kdbinder/binder/IInterface.cpp35
5 files changed, 163 insertions, 3 deletions
diff --git a/include/kdbinder/binder/IBinder.h b/include/kdbinder/binder/IBinder.h
index b2d7b25..40a620b 100644
--- a/include/kdbinder/binder/IBinder.h
+++ b/include/kdbinder/binder/IBinder.h
@@ -48,9 +48,7 @@ class IBinder : public virtual RefBase {
* @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;
+ virtual sp<IInterface> queryLocalInterface(const String16& descriptor);
/**
* Return the canonical name of the interface provided by this IBinder
diff --git a/include/kdbinder/binder/IInterface.h b/include/kdbinder/binder/IInterface.h
new file mode 100644
index 0000000..8e92e9f
--- /dev/null
+++ b/include/kdbinder/binder/IInterface.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_IINTERFACE_H_
+#define INCLUDE_KDBINDER_BINDER_IINTERFACE_H_
+
+#include <binder/Binder.h>
+
+namespace android {
+
+class IInterface : public virtual RefBase {
+ public:
+ IInterface();
+ static sp<IBinder> asBinder(const IInterface* iface);
+ static sp<IBinder> asBinder(const sp<IInterface>& iface);
+
+ protected:
+ virtual ~IInterface();
+ virtual IBinder* onAsBinder() = 0;
+};
+
+template<typename INTERFACE>
+inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj) {
+ return INTERFACE::asInterface(obj);
+}
+
+template<typename INTERFACE>
+class BnInterface : public INTERFACE, public BBinder {
+ public:
+ virtual sp<IInterface> queryLocalInterface(const String16& _descriptor);
+ virtual const String16& getInterfaceDescriptor() const;
+
+ protected:
+ IBinder* onAsBinder() override;
+};
+
+template<typename INTERFACE>
+class BpInterface : public INTERFACE, public BpRefBase {
+ public:
+ explicit BpInterface(const sp<IBinder>& remote);
+
+ protected:
+ IBinder* onAsBinder() override;
+};
+
+#define DECLARE_META_INTERFACE(INTERFACE) \
+ static const android::String16 descriptor; \
+ static android::sp<I##INTERFACE> asInterface( \
+ const android::sp<android::IBinder>& obj); \
+ virtual const android::String16& getInterfaceDescriptor() const; \
+ I##INTERFACE(); \
+ virtual ~I##INTERFACE(); \
+
+
+#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
+ const android::String16 I##INTERFACE::descriptor(NAME); \
+ const android::String16& \
+ I##INTERFACE::getInterfaceDescriptor() const { \
+ return I##INTERFACE::descriptor; \
+ } \
+ android::sp<I##INTERFACE> I##INTERFACE::asInterface( \
+ const android::sp<android::IBinder>& obj) { \
+ android::sp<I##INTERFACE> intr; \
+ if (obj != NULL) { \
+ intr = static_cast<I##INTERFACE*>( \
+ obj->queryLocalInterface( \
+ I##INTERFACE::descriptor).get()); \
+ if (intr == NULL) { \
+ intr = new Bp##INTERFACE(obj); \
+ } \
+ } \
+ return intr; \
+ } \
+ I##INTERFACE::I##INTERFACE() { } \
+ I##INTERFACE::~I##INTERFACE() { } \
+
+#define CHECK_INTERFACE(interface, data, reply) \
+ if (!data.checkInterface(this)) { return PERMISSION_DENIED; } \
+
+template<typename INTERFACE>
+inline sp<IInterface> BnInterface<INTERFACE>::queryLocalInterface(
+ const String16& _descriptor) {
+ if (_descriptor == INTERFACE::descriptor) return this;
+ return NULL;
+}
+
+template<typename INTERFACE>
+inline const String16& BnInterface<INTERFACE>::getInterfaceDescriptor() const {
+ return INTERFACE::getInterfaceDescriptor();
+}
+
+template<typename INTERFACE>
+IBinder* BnInterface<INTERFACE>::onAsBinder() {
+ return this;
+}
+
+template<typename INTERFACE>
+inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)
+ : BpRefBase(remote) {}
+
+template<typename INTERFACE>
+inline IBinder* BpInterface<INTERFACE>::onAsBinder() {
+ return remote();
+}
+
+} // namespace android
+
+#endif // INCLUDE_KDBINDER_BINDER_IINTERFACE_H_
diff --git a/libs/kdbinder/Android.mk b/libs/kdbinder/Android.mk
index 5bc5075..3546d13 100644
--- a/libs/kdbinder/Android.mk
+++ b/libs/kdbinder/Android.mk
@@ -15,6 +15,7 @@
kdbinder_sources := \
binder/Binder.cpp \
binder/BpBinder.cpp \
+ binder/IInterface.cpp \
kdbus/bus.cpp \
kdbus/connection.cpp \
kdbus/iterable.cpp \
diff --git a/libs/kdbinder/binder/Binder.cpp b/libs/kdbinder/binder/Binder.cpp
index 3899de5..62714b5 100644
--- a/libs/kdbinder/binder/Binder.cpp
+++ b/libs/kdbinder/binder/Binder.cpp
@@ -16,6 +16,7 @@
#include <binder/IBinder.h>
#include <binder/Binder.h>
+#include <binder/IInterface.h>
#include <log/log.h>
#include <utils/String16.h>
@@ -26,6 +27,10 @@ IBinder::IBinder() : RefBase() {}
IBinder::~IBinder() {}
+sp<IInterface> IBinder::queryLocalInterface(const String16& /*descriptor*/) {
+ return NULL;
+}
+
BBinder* IBinder::localBinder() {
return nullptr;
}
diff --git a/libs/kdbinder/binder/IInterface.cpp b/libs/kdbinder/binder/IInterface.cpp
new file mode 100644
index 0000000..7e075e6
--- /dev/null
+++ b/libs/kdbinder/binder/IInterface.cpp
@@ -0,0 +1,35 @@
+/*
+ * 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/IInterface.h>
+
+namespace android {
+
+IInterface::IInterface() : RefBase() {}
+
+IInterface::~IInterface() {}
+
+sp<IBinder> IInterface::asBinder(const IInterface* iface) {
+ if (iface == NULL) return NULL;
+ return const_cast<IInterface*>(iface)->onAsBinder();
+}
+
+sp<IBinder> IInterface::asBinder(const sp<IInterface>& iface) {
+ if (iface == NULL) return NULL;
+ return iface->onAsBinder();
+}
+
+} // namespace android