diff options
author | Pierre Langlois <pierre.langlois@arm.com> | 2015-02-02 17:43:41 +0000 |
---|---|---|
committer | Pierre Langlois <pierre.langlois@arm.com> | 2016-03-04 17:50:27 +0000 |
commit | 8b80c2bd6822ccf515ae0f02d2d48b47cee4c6fe (patch) | |
tree | b95314025926b5e492049835f64736b9cb0e1334 | |
parent | fbdca08f39cf1a5a2aaeccb51b9e17e7aba13cb4 (diff) | |
download | kdbinder-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.h | 4 | ||||
-rw-r--r-- | include/kdbinder/binder/IInterface.h | 121 | ||||
-rw-r--r-- | libs/kdbinder/Android.mk | 1 | ||||
-rw-r--r-- | libs/kdbinder/binder/Binder.cpp | 5 | ||||
-rw-r--r-- | libs/kdbinder/binder/IInterface.cpp | 35 |
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 |