I can only find examples for Java regarding Parcelable. My goal is to create a simple service and client in native C++ ( not NDK ), that will use Binder to receive and send serialized custom objects.
MyClass
+ std::string
+ enum
+ int
+ bool
I can only find examples for Java regarding Parcelable. My goal is to create a simple service and client in native C++ ( not NDK ), that will use Binder to receive and send serialized custom objects.
MyClass
+ std::string
+ enum
+ int
+ bool
Since you're using Android 5.1 I'll stick to what's available on Lollipop. There are better tools like aidl-cpp to accomplish this which saves a lot of the hassle of hand-rolling boiler-plate codes.
First, craft the Interface for the service in IFooService.h.
class IFooService: public IInterface {
public:
DECLARE_META_INTERFACE(FooService);
virtual int myFunc(const String8& str, int enumParam, int intParam, int boolParam) = 0;
};
Then write the marshalling code for the service, implementing a function as per the requirements in the question
class BnFooService: public BnInterface<IFooService>
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
enum {
MY_FUNC = IBinder::FIRST_CALL_TRANSACTION,
};
/* BinderProxy code, for clients of the service to call into the service and have
the paremeters marshalled properly across the Binder interface. Executes in the
client process context
*/
class BpFooService: public BpInterface<IFooService> {
public:
virtual int myFunc(const String8& str, int enumParam, int intParam, int boolParam) {
//2 Parcel objects, 1 to write the data to and another to receive it in
Parcel data, reply;
//This serves as the token for the Binder framework for a sanity check
data.writeInterfaceToken(IFooService::getInterfaceDescriptor());
data.writeString8(str);
data.writeInt32(enumParam);
data.writeInt32(intParam);
data.writeInt32(boolParam);
return remote()->transact(MY_FUNC, data, &reply);
}
}
IMPLEMENT_META_INTERFACE(MediaPlayerService, "com.somedomain.IFooService");
/* Actual Binder implementation of the service which unpacks the data from the
incoming Parcel and handles the call accordingly
*/
status_t BnFooService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
switch (code) {
case MY_FUNC: {
//The same token is checked
CHECK_INTERFACE(IFooService, data, reply);
//Read off in exact same order as written to the data Parcel above
String8 str = data.readString8();
int enumParam = data.readInt32();
int intParam = data.readInt32();
int boolParam = data.readInt32();
reply->writeInt32(myFunc(str, enumParam, intParam, boolParam));
return NO_ERROR;
}
break;
default:
}
Then create the main_foo.cpp with some code as follows which serves as the entry point for the service process:
int main() {
if(!FooService::publish()) { //Call into your code to register with ServiceManager
ALOGE("Can't instantiate FooService! Exiting");
return 1;
}
ProcessState::self()->startThreadPool(); //Required for the binder threads
IPCThreadState::self()->joinThreadPool(); //Infinite loop that waits for inbound connections
}
And, finally, implement the interface for the service in FooService.cpp
bool FooService::publish() {
defaultServiceManager()->addService(String16("foo_service"), new FooService());
sp<IBinder> binder = defaultServiceManager()->checkService(String16("foo_service"));
while(binder == NULL && /*some upper time limit*/){
ALOGI("Waiting for foo_service");
}
return binder != NULL;
}
int FooService::myFunc(const String8& str, int enumParam, int intParam, int boolParam) {
//business logic
return 0;
}
Please note that this is not code that's meant for regular application developers but instead for native services running in the Android Framework like InputFlinger, SurfaceFlinger etc. This code requires Framework Header files like Parcel.h, IInterface.h etc. which aren't available in an SDK.