How to connect to a binder c++ service?

8,514 views
Skip to first unread message

Samuel Skånberg

unread,
Oct 20, 2010, 9:33:58 AM10/20/10
to android-porting
Hello,

I want to create a binder service in C++ and be able to bind to that
service from java. My question is how? I have mimicked the
implementation in frameworks/base/camera/tests/CameraServiceTest/
CameraServiceTest.cpp. It compiles nicely without any warnings and I
can run it. But how do I connect to it?

The code for the service is here:

------------------------------------------------------------------------------------------------------------------------------------------
/* Imitating frameworks/base/camera/tests/CameraServiceTest/
CameraServiceTest.cpp */

#include <binder/IInterface.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
#include <binder/IBinder.h>

using namespace android;


class IPokeService : public IInterface {
protected:
enum {
POKE = IBinder::FIRST_CALL_TRANSACTION
};

public:
DECLARE_META_INTERFACE(PokeService);
virtual void poke() = 0;
};

class BnPokeService : public BnInterface<IPokeService> {
virtual status_t onTransact(uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags = 0);
};

class BpPokeService : public BpInterface<IPokeService> {
public:
BpPokeService(const sp<IBinder>& impl) :
BpInterface<IPokeService>(impl) {
}

virtual void poke() {
Parcel data, reply;
remote()->transact(POKE, data, &reply);
}
};

IMPLEMENT_META_INTERFACE(PokeService, "PokeService");

status_t BnPokeService::onTransact(uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags) {
switch(code) {
case POKE: {
poke();
return NO_ERROR;
} break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}

class PokeService : public BnPokeService {
virtual void poke() {
printf("Poked\n");
}
};

int main(int argc, char **argv)
{
defaultServiceManager()->addService(String16("PokeService"), new
PokeService());
ProcessState::self()->startThreadPool();

android::ProcessState::self()->startThreadPool();
LOGI("Poke service is now ready");
IPCThreadState::self()->joinThreadPool();

return 0;
}
------------------------------------------------------------------------------------------------------------------------------------------

And here is my Android.mk
------------------------------------------------------------------------------------------------------------------------------------------
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_SRC_FILES := main.cpp

LOCAL_CFLAGS += -DPLATFORM_ANDROID

LOCAL_MODULE := poke

# for now, until I do a full rebuild.
LOCAL_PRELINK_MODULE := false

LOCAL_SHARED_LIBRARIES += liblog
LOCAL_SHARED_LIBRARIES += libutils libui libcutils
LOCAL_SHARED_LIBRARIES += libbinder

include $(BUILD_EXECUTABLE)
------------------------------------------------------------------------------------------------------------------------------------------


The service won't show up when I do a listing in java:

------------------------------------------------------------------------------------------------------------------------------------------
Context context = getBaseContext();
ActivityManager am = (ActivityManager)
context.getSystemService(Activity.ACTIVITY_SERVICE);

List<RunningServiceInfo> serviceInfos = am.getRunningServices(50);

for (RunningServiceInfo service : serviceInfos) {
Log.i("Service", "Process " + service.process + " with component " +
service.service.getClassName());
}
------------------------------------------------------------------------------------------------------------------------------------------

That will only give me from logcat:
I/Service ( 715): Process system with component
com.android.internal.service.wallpaper.ImageWallpaper
I/Service ( 715): Process com.android.phone with component
com.android.phone.BluetoothHeadsetService
I/Service ( 715): Process com.android.inputmethod.latin with
component com.android.inputmethod.latin.LatinIME

Any help would be appreciated!

Kind regards,
Samuel



Hamilton Vera

unread,
Oct 20, 2010, 11:06:24 AM10/20/10
to dt0...@student.lth.se, android-porting

Samuel Skånberg

unread,
Oct 21, 2010, 2:51:08 AM10/21/10
to android-porting
Well, those links were about JNI. I don't think I should have to use
JNI, do you? My service is implemented in C++, linked with binder and
the client I want to connect with is a normal android app so I should
be able to do

-------------------------------------------------------------------------------------
Intent i = new Intent();
i.setClassName("com.example.cppservice",
"com.example.cppservice.PokeService");
if (bindService(i, clientConnection, Context.BIND_AUTO_CREATE)) {
Log.d(getClass().getSimpleName(), "bindService()");
} else {
Log.e(getClass().getSimpleName(), "Could not bindService()");
}
-------------------------------------------------------------------------------------

I have no problems compiling the C++ program, that works nicely with
the android build system and my Android.mk file. But for some reason,
when I run it, it won't show up among the other services in android.
Am I missing some fundamental piece, like hooking onto the android
systems ServiceManager or something similar?


On Oct 20, 5:06 pm, Hamilton Vera <hamilton.lis...@gmail.com> wrote:
> Maybe you can find some information here:
>
> http://www.google.com.br/url?sa=t&source=web&cd=5&ved=0CDwQFjAE&url=h...
>
> http://davanum.wordpress.com/2007/12/09/android-invoke-jni-based-meth...
>
> []'s
>
> Hamilton Vera
>
> 2010/10/20 Samuel Skånberg <dt05...@student.lth.se>:

Dianne Hackborn

unread,
Oct 21, 2010, 12:59:31 PM10/21/10
to dt0...@student.lth.se, android-porting
I would recommend keeping all of the Binder stuff in C++, and implementing your Java APIs as JNI calls on the C++ Binder interface.  Until aidl can generate C++ stubs, I think it is easier than maintaining both C++ and Java interfaces.

2010/10/20 Samuel Skånberg <dt0...@student.lth.se>



--
Dianne Hackborn
Android framework engineer
hac...@android.com

Note: please don't send private questions to me, as I don't have time to provide private support, and so won't reply to such e-mails.  All such questions should be posted on public forums, where I and others can see and answer them.

Samuel Skånberg

unread,
Oct 22, 2010, 5:12:18 AM10/22/10
to Dianne Hackborn, dt0...@student.lth.se, android-porting
Hello Dianne,

Thanks for you quick response!

In another post a developer asked how one should go about to publish an
IBinder interface of a native service with the system manager. There you
said one should follow four steps

"1. Declares a shared user ID with the system process, and that its
components will run in the system process.
2. Has a Service component that implements your "system" service.
3. Has an intent receiver for BOOT_COMPLETED that, when run, starts the
service.
4. In the Service implementation publishes its IBinder interface with the
private ServiceManager API."

http://groups.google.com/group/android-porting/browse_thread/thread/f9a383ce949d1557

That seemed like the "right" way to do it because then it integrates
nicely with the rest of the android environment and is being started
automatically after boot.

I was successful doing the first 3 but can't get it to work with the 4th
and that's what I'm trying to figure out now. In your previous message you
said I should keep all the binder stuff in C++ but from the post I linked
to it seems that it's possible to have a java class that extends the
Service class but that the onBind method return the C++ Binder interface.

Have I understood it correctly? If so, how do I return the C++ Binder
interface? I have no idea.

> I would recommend keeping all of the Binder stuff in C++, and implementing
> your Java APIs as JNI calls on the C++ Binder interface. Until aidl can
> generate C++ stubs, I think it is easier than maintaining both C++ and
> Java
> interfaces.
>

> 2010/10/20 Samuel Sk�nberg <dt0...@student.lth.se>


>
>> Well, those links were about JNI. I don't think I should have to use
>> JNI, do you? My service is implemented in C++, linked with binder and
>> the client I want to connect with is a normal android app so I should
>> be able to do
>>
>>
>> -------------------------------------------------------------------------------------
>> Intent i = new Intent();
>> i.setClassName("com.example.cppservice",
>> "com.example.cppservice.PokeService");
>> if (bindService(i, clientConnection, Context.BIND_AUTO_CREATE)) {
>> Log.d(getClass().getSimpleName(), "bindService()");
>> } else {
>> Log.e(getClass().getSimpleName(), "Could not bindService()");
>> }
>>
>> -------------------------------------------------------------------------------------
>>
>> I have no problems compiling the C++ program, that works nicely with
>> the android build system and my Android.mk file. But for some reason,
>> when I run it, it won't show up among the other services in android.
>> Am I missing some fundamental piece, like hooking onto the android
>> systems ServiceManager or something similar?
>>
>>
>> On Oct 20, 5:06 pm, Hamilton Vera <hamilton.lis...@gmail.com> wrote:
>> > Maybe you can find some information here:
>> >
>> > http://www.google.com.br/url?sa=t&source=web&cd=5&ved=0CDwQFjAE&url=h...
>> >
>> > http://davanum.wordpress.com/2007/12/09/android-invoke-jni-based-meth...
>> >
>> > []'s
>> >
>> > Hamilton Vera
>> >

>> > 2010/10/20 Samuel Sk�nberg <dt05...@student.lth.se>:

>> android-porti...@googlegroups.com<android-porting%2Bunsu...@googlegroups.com>


>> > > website:http://groups.google.com/group/android-porting
>> >
>> > --
>> > Hamilton Vera
>> > int Administrator (char Network[],char ComputationalSystems[])
>> http://hvera.wordpress.com
>>
>> --
>> unsubscribe:

>> android-porti...@googlegroups.com<android-porting%2Bunsu...@googlegroups.com>

Dianne Hackborn

unread,
Oct 22, 2010, 7:29:06 PM10/22/10
to Samuel Skånberg, android-porting
The Java runtime has wrappers around C++ IBinder.  This is what Java's Binder is.  You can write a JNI function that returns a Java Binder and in its implementation instantiate a C++ IBinder interface and return it.  You will need to use this magic function in libandroid_runtime to do this:

extern jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val);


The header for this is currently in core/jni/android_util_Binder.h.

2010/10/22 Samuel Skånberg <dt0...@student.lth.se>
> 2010/10/20 Samuel Skånberg <dt0...@student.lth.se>

>
>> Well, those links were about JNI. I don't think I should have to use
>> JNI, do you? My service is implemented in C++, linked with binder and
>> the client I want to connect with is a normal android app so I should
>> be able to do
>>
>>
>> -------------------------------------------------------------------------------------
>> Intent i = new Intent();
>> i.setClassName("com.example.cppservice",
>> "com.example.cppservice.PokeService");
>> if (bindService(i, clientConnection, Context.BIND_AUTO_CREATE)) {
>>        Log.d(getClass().getSimpleName(), "bindService()");
>> } else {
>>        Log.e(getClass().getSimpleName(), "Could not bindService()");
>> }
>>
>> -------------------------------------------------------------------------------------
>>
>> I have no problems compiling the C++ program, that works nicely with
>> the android build system and my Android.mk file. But for some reason,
>> when I run it, it won't show up among the other services in android.
>> Am I missing some fundamental piece, like hooking onto the android
>> systems ServiceManager or something similar?
>>
>>
>> On Oct 20, 5:06 pm, Hamilton Vera <hamilton.lis...@gmail.com> wrote:
>> > Maybe you can find some information here:
>> >
>> > http://www.google.com.br/url?sa=t&source=web&cd=5&ved=0CDwQFjAE&url=h...
>> >
>> > http://davanum.wordpress.com/2007/12/09/android-invoke-jni-based-meth...
>> >
>> > []'s
>> >
>> > Hamilton Vera
>> >
>> > 2010/10/20 Samuel Skånberg <dt05...@student.lth.se>:

Samuel Skånberg

unread,
Nov 4, 2010, 10:38:17 AM11/4/10
to android-porting
Hello again! And thanks for your help!

Now I have tried different approaches and I'm stuck.

What I did was creating a Java service but in the onBind method I call
a native method that instantiate the C++ service and call another one
that returns an IBinder interface.

-----------------------------------------------------
public IBinder onBind(Intent intent) {
System.loadLibrary("jni-lib");
instantiate();
return getIBinder();
}

public native void instantiate();
public native IBinder getIBinder();
-----------------------------------------------------

In the native implementation, jni-lib.cpp I have:
-----------------------------------------------------
#include "android_util_Binder.h"
#include "third.h"

extern "C" {
#include <jni.h>
}

extern "C" {
void
Java_com_example_twolibs_PokeService_instantiate( JNIEnv* env,
jobject thiz )
{
PokeService::instantiate();
ProcessState::self()->startThreadPool();
}

jobject
Java_com_example_twolibs_PokeService_getIBinder( JNIEnv* env,
jobject thiz)
{
return javaObjectForIBinder(env, serviceInstance); //
serviceInstance is a PokeService pointer in third.h
}
}
-----------------------------------------------------

In the file third.cpp I have:
-----------------------------------------------------
#include "third.h"
#include <string>

#include <binder/IInterface.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
#include <binder/IBinder.h>

using namespace android;

status_t BnPokeService::onTransact(uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags) {
switch(code) {
case POKE: {
poke();
return NO_ERROR;
} break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}

void PokeService::instantiate() {
serviceInstance = new PokeService(); // serviceInstance is a
PokeService pointer in third.h
defaultServiceManager()-
>addService(String16("com.example.twolibs.PokeService"),
serviceInstance);
LOGI("Poke service is now ready");
ProcessState::self()->startThreadPool();
}
----------------------------------------------------------------------------

However, this doesn't work. When I do bindService to the Java
PokeService the onServiceConnected method in the ServiceConnection I
supply as an argument to bindService never runs.

Is this really the way to go? A colleague of mine suggest I should
only use binder in Java, that I should have a java service that makes
jni calls to do stuff in C++ but to have no binder code in c++. What
do you think?

Kind regards,
Samuel


On Oct 23, 12:29 am, Dianne Hackborn <hack...@android.com> wrote:
> The Java runtime has wrappers around C++ IBinder.  This is what Java's
> Binder is.  You can write a JNI function that returns a Java Binder and in
> its implementation instantiate a C++ IBinder interface and return it.  You
> will need to use this magic function in libandroid_runtime to do this:
>
>    extern jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val);
>
> The header for this is currently in core/jni/android_util_Binder.h.
>
> 2010/10/22 Samuel Skånberg <dt05...@student.lth.se>
>
>
>
> > Hello Dianne,
>
> > Thanks for you quick response!
>
> > In another post a developer asked how one should go about to publish an
> > IBinder interface of a native service with the system manager. There you
> > said one should follow four steps
>
> > "1. Declares a shared user ID with the system process, and that its
> > components will run in the system process.
> > 2. Has a Service component that implements your "system" service.
> > 3. Has an intent receiver for BOOT_COMPLETED that, when run, starts the
> > service.
> > 4. In the Service implementation publishes its IBinder interface with the
> > private ServiceManager API."
>
> >http://groups.google.com/group/android-porting/browse_thread/thread/f...
>
> > That seemed like the "right" way to do it because then it integrates
> > nicely with the rest of the android environment and is being started
> > automatically after boot.
>
> > I was successful doing the first 3 but can't get it to work with the 4th
> > and that's what I'm trying to figure out now. In your previous message you
> > said I should keep all the binder stuff in C++ but from the post I linked
> > to it seems that it's possible to have a java class that extends the
> > Service class but that the onBind method return the C++ Binder interface.
>
> > Have I understood it correctly? If so, how do I return the C++ Binder
> > interface? I have no idea.
>
> > > I would recommend keeping all of the Binder stuff in C++, and
> > implementing
> > > your Java APIs as JNI calls on the C++ Binder interface.  Until aidl can
> > > generate C++ stubs, I think it is easier than maintaining both C++ and
> > > Java
> > > interfaces.
>
> > > 2010/10/20 Samuel Skånberg <dt05...@student.lth.se>
> > >> android-porti...@googlegroups.com<android-porting%2Bunsubscribe@ googlegroups.com>
> > <android-porting%2Bunsu...@googlegroups.com<android-porting%252Bunsubsc ri...@googlegroups.com>
>
> > >> > > website:http://groups.google.com/group/android-porting
>
> > >> > --
> > >> > Hamilton Vera
> > >> > int Administrator (char Network[],char ComputationalSystems[])
> > >>http://hvera.wordpress.com
>
> > >> --
> > >> unsubscribe:
> > >> android-porti...@googlegroups.com<android-porting%2Bunsubscribe@ googlegroups.com>
> > <android-porting%2Bunsu...@googlegroups.com<android-porting%252Bunsubsc ri...@googlegroups.com>
>
> ...
>
> read more »

Nitin Mahajan

unread,
Sep 12, 2011, 9:01:01 PM9/12/11
to android...@googlegroups.com
2010/10/22 Samuel Skånberg <dt0...@student.lth.se>:

> Hello Dianne,
>
> Thanks for you quick response!
>
> In another post a developer asked how one should go about to publish an
> IBinder interface of a native service with the system manager. There you
> said one should follow four steps
>
> "1. Declares a shared user ID with the system process, and that its
> components will run in the system process.
> 2. Has a Service component that implements your "system" service.

There is no ANativeService like, ANativeActivity right? Means it has
to be Service component in Java code right?


> 3. Has an intent receiver for BOOT_COMPLETED that, when run, starts the
> service.

Is it possible to publish an implementation through the <receiver> tag
in native app's AndroidManifest.xml

> 4. In the Service implementation publishes its IBinder interface with the
> private ServiceManager API."

I intend to implement a native service, and bind to it from a Java application.
I came across this post and the links within it, and got a bit confused.

I have some queries inline, also can I get some pointers on how to do this?

Also, as the author of the original post asks, is it possible to do
this without JNI?

regards
-Nitin


>
> http://groups.google.com/group/android-porting/browse_thread/thread/f9a383ce949d1557
>
> That seemed like the "right" way to do it because then it integrates
> nicely with the rest of the android environment and is being started
> automatically after boot.
>
> I was successful doing the first 3 but can't get it to work with the 4th
> and that's what I'm trying to figure out now. In your previous message you
> said I should keep all the binder stuff in C++ but from the post I linked
> to it seems that it's possible to have a java class that extends the
> Service class but that the onBind method return the C++ Binder interface.
>
> Have I understood it correctly? If so, how do I return the C++ Binder
> interface? I have no idea.
>
>
>
>> I would recommend keeping all of the Binder stuff in C++, and implementing
>> your Java APIs as JNI calls on the C++ Binder interface.  Until aidl can
>> generate C++ stubs, I think it is easier than maintaining both C++ and
>> Java
>> interfaces.
>>

>> 2010/10/20 Samuel Skånberg <dt0...@student.lth.se>


>>
>>> Well, those links were about JNI. I don't think I should have to use
>>> JNI, do you? My service is implemented in C++, linked with binder and
>>> the client I want to connect with is a normal android app so I should
>>> be able to do
>>>
>>>
>>> -------------------------------------------------------------------------------------
>>> Intent i = new Intent();
>>> i.setClassName("com.example.cppservice",
>>> "com.example.cppservice.PokeService");
>>> if (bindService(i, clientConnection, Context.BIND_AUTO_CREATE)) {
>>>        Log.d(getClass().getSimpleName(), "bindService()");
>>> } else {
>>>        Log.e(getClass().getSimpleName(), "Could not bindService()");
>>> }
>>>
>>> -------------------------------------------------------------------------------------
>>>
>>> I have no problems compiling the C++ program, that works nicely with
>>> the android build system and my Android.mk file. But for some reason,
>>> when I run it, it won't show up among the other services in android.
>>> Am I missing some fundamental piece, like hooking onto the android
>>> systems ServiceManager or something similar?
>>>
>>>
>>> On Oct 20, 5:06 pm, Hamilton Vera <hamilton.lis...@gmail.com> wrote:
>>> > Maybe you can find some information here:
>>> >
>>> > http://www.google.com.br/url?sa=t&source=web&cd=5&ved=0CDwQFjAE&url=h...
>>> >
>>> > http://davanum.wordpress.com/2007/12/09/android-invoke-jni-based-meth...
>>> >
>>> > []'s
>>> >
>>> > Hamilton Vera
>>> >

>>> > 2010/10/20 Samuel Skånberg <dt05...@student.lth.se>:

Nitin Mahajan

unread,
Sep 13, 2011, 12:56:41 PM9/13/11
to android...@googlegroups.com


On Saturday, October 23, 2010, Dianne Hackborn <hac...@android.com> wrote:
> The Java runtime has wrappers around C++ IBinder.  This is what Java's Binder is.  You can write a JNI function that returns a Java Binder and in its implementation instantiate a C++ IBinder interface and return it.  You will need to use this magic function in libandroid_runtime to do this:
>
> extern jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val);
>
I was able to do it this way, I wil post the link to github for reference.

Regards
Nitin

freakingtux

unread,
Sep 23, 2011, 6:22:08 AM9/23/11
to android...@googlegroups.com


On Tuesday, September 13, 2011 6:56:41 PM UTC+2, Nitin wrote:


On Saturday, October 23, 2010, Dianne Hackborn <hac...@android.com> wrote:
> The Java runtime has wrappers around C++ IBinder.  This is what Java's Binder is.  You can write a JNI function that returns a Java Binder and in its implementation instantiate a C++ IBinder interface and return it.  You will need to use this magic function in libandroid_runtime to do this:
>
> extern jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val);
>
I was able to do it this way, I wil post the link to github for reference.

Nitin If you have more pointer please do tell me so. After cloning your
repository some while ago and documenting the code I started hacking
to get the code running on inside an apk and not running as system
service. This is not really portable but at least it is a start at
getting somewhere (I can ndk-build the code and ant install it).

I don't understand how the javaObjectForIBinder approach should work. My best guess at what was suggested is posted here
https://github.com/keesj/Android-HelloWorldService/blob/pure_apk_hack/jni/main_helloworldservice.cpp#L125

Basically I construct a Binder object (what might as well have been passed to the native code) and try to
replace the native binder. All kinds of alarm bells go of

The code is called from here https://github.com/keesj/Android-HelloWorldService/blob/pure_apk_hack/src/org/credil/helloworldservice/HelloWorldService.java and the binder is bound the process who created the binder this however is the same process the Java code runnig. So what thread will listen to binder? Should I not call android::ProcessState::self()->startThreadPool(); or perhaps first fork or create a Java thread?

any pointer or better patches to make this work are welcome!

Greetings

Braganza Roberts

unread,
Jan 14, 2013, 1:02:16 PM1/14/13
to dt0...@student.lth.se, android-porting
Hello,

I think you can directly use the Service name as string and try it.
Say,
public static final String POKE_SERVICE = "PokeService";
context.getSystemService(POKE_SERVICE)

~Sam.

Reply all
Reply to author
Forward
0 new messages