calling Android remote services from C++

4,392 views
Skip to first unread message

Brad Justice

unread,
Nov 18, 2011, 3:41:28 PM11/18/11
to android-ndk
As part of a porting project I would like to call an Android remote
service from c++. I found some example code here:
http://www.androidenea.com/2010/03/share-memory-using-ashmem-and-binder-in.html
- though I have not been able to build it. I found numerous code
examples by downloading Android source and have focused my attention
on the code in frameworks/base/libs.

Using this code as an example, I have coded an implementation that
makes use of resources not exposed in the standard NDK SYSROOT,
primarily binder (using binder.h). This code compiles, but I am
struggling with linkage.

I have an issue with Lunch, so I cannot currently build the Android
sources. As an alternative, I have pulled /system/lib from a 3.1 AVD
(my target platform) and am linking against those libraries along with
those in SYSROOT. At this point I have two unresolved references, both
from the Android shared libraries:

home/parallels/jack/android_3.1_libs/libutils.so: undefined reference
to `pread64'
/home/parallels/jack/android_3.1_libs/libcutils.so: undefined
reference to `__system_property_set'
collect2: ld returned 1 exit status
make: *** [/media/JACKUBUNTU/eclipse_workspace/SemaphoreClientC/obj/
local/armeabi/SemaphoreClientC++] Error 1

libutils and libcutils are required by libbinder. I have tried various
corrections, including adding -lc to the library list.

First - being new to Android - I am hoping for a sanity check that
there is not some simpler way to achieve my goal of calling remote
services from c++. Failing that, perhaps someone could assist me in
resolving my linkage problem.

Thanking all in advance,

Brad

My Android.mk
-------------------

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := SemaphoreClientC++

LOCAL_SRC_FILES := \
SemaphoreClientC++.cpp \
SemaphoreClient.cpp \
ISemServerInterface.cpp

LOCAL_LDLIBS := \
-L/home/parallels/jack/android_3.1_libs \
-lbinder \
-lcutils \
-lutils \
-llog


include $(BUILD_EXECUTABLE)


My Application.mk
------------------------

APP_ABI := armeabi
APP_PROJECT_PATH := /home/parallels/jack/eclipse_workspace/
SemaphoreClientC
APP_CFLAGS := --sysroot=/home/parallels/android-ndk-r6b/platforms/
android-9/arch-arm -v -g -I/home/parallels/WORKING_DIRECTORY/system/
core/include -I/home/parallels/WORKING_DIRECTORY/frameworks/base/
include

David Turner

unread,
Nov 20, 2011, 8:31:37 AM11/20/11
to andro...@googlegroups.com
Neither of libcutils, libutils, libbinder are exposed by the NDK, which means that applications should never link against them.
Because they are not exposed, their implementation can heavily be modified between platform releases. This probably explain why you have a linking problem.

I'm sorry but applications should never use the Binder from native code, its binary interface is (intentionally) not stable to allow this.

Whatever hacks you may find on the internet, they are just that: fragile hacks that will break (or are already broken) in the future without notice.


--
You received this message because you are subscribed to the Google Groups "android-ndk" group.
To post to this group, send email to andro...@googlegroups.com.
To unsubscribe from this group, send email to android-ndk...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/android-ndk?hl=en.


Brad Justice

unread,
Nov 21, 2011, 10:43:49 AM11/21/11
to android-ndk
So what is the recommended way to call a remote service from a C or C+
+ executable? I still need to accomplish this goal.

On Nov 20, 5:31 am, David Turner <di...@android.com> wrote:
> Neither of libcutils, libutils, libbinder are exposed by the NDK, which
> means that applications should never link against them.
> Because they are not exposed, their implementation can heavily be modified
> between platform releases. This probably explain why you have a linking
> problem.
>
> I'm sorry but applications should never use the Binder from native code,
> its binary interface is (intentionally) not stable to allow this.
>
> Whatever hacks you may find on the internet, they are just that: fragile
> hacks that will break (or are already broken) in the future without notice.
>

> On Fri, Nov 18, 2011 at 9:41 PM, Brad Justice <bradleypjust...@gmail.com>wrote:
>
>
>
>
>
>
>
> > As part of a porting project I would like to call an Android remote
> > service from c++. I found some example code here:
>

> >http://www.androidenea.com/2010/03/share-memory-using-ashmem-and-bind...

David Turner

unread,
Nov 21, 2011, 10:46:47 AM11/21/11
to andro...@googlegroups.com
On Mon, Nov 21, 2011 at 4:43 PM, Brad Justice <bradley...@gmail.com> wrote:
So what is the recommended way to call a remote service from a C or C+
+ executable? I still need to accomplish this goal.

You would have to use JNI to call it through the VM.

Luiz Valdetaro

unread,
Nov 21, 2011, 12:07:28 PM11/21/11
to andro...@googlegroups.com

My guess is to call java from your c++ code; however that java method is static... so then the question becomes, how to call an android rpc from a static method?

Brad Justice

unread,
Nov 21, 2011, 2:54:58 PM11/21/11
to android-ndk
In addition, I need access to ashmem to share data between processes.
The Android MemoryFile class is not suitable as I need to access the
data in situ - copying the data will result in an unacceptable
performance penalty. Up till this point I have been assuming that I
could follow the recommendations in this post in android-platform:

>Dave Sparks
> More options Feb 24 2009, 7:14 pm
>For security reasons, you cannot access shared memory by name. You
>pass a file descriptor through the binder interface. See the IMemory
>implementations for examples of how ashmem is used.

Is it possible to follow this recommendation without breaking the rule
regarding use of the Binder interface from NDK code? Has anyone out
there successfully implemented shared memory?

Thanks in advance,

Brad


Adrian Taylor

unread,
Nov 21, 2011, 3:14:42 PM11/21/11
to andro...@googlegroups.com
On 21 Nov 2011, at 19:54, Brad Justice wrote:

Dave Sparks
More options Feb 24 2009, 7:14 pm
For security reasons, you cannot access shared memory by name. You
pass a file descriptor through the binder interface. See the IMemory
implementations for examples of how ashmem is used.

Is it possible to follow this recommendation without breaking the rule
regarding use of the Binder interface from NDK code? Has anyone out
there successfully implemented shared memory?

I *think* you can do it without breaking the rules, but you'll have to do the IPC in Java:

-- Use 'ashmem' to create a shared memory area
-- Create an .aidl interface which passes a ParcelFileDescriptor
-- Implement the .aidl interface in Java rather than C++.
-- Pass in the ashmem FD
-- Retrieve the numeric FD from the ParcelFileDescriptor, and use mmap to access it from the other process.

Before API level 13, you'll need to write your own Java marshalling and unmarshalling code and use Binder.writeFileDescriptor, instead of using aidl and ParcelFileDescriptor.

Cheers

Adrian

Luiz Valdetaro

unread,
Nov 21, 2011, 4:08:10 PM11/21/11
to andro...@googlegroups.com

I don't think it is possible to use shared memory in java

Luiz Valdetaro

unread,
Nov 21, 2011, 4:09:44 PM11/21/11
to andro...@googlegroups.com

How to call an rpc service from a static method?

Brad Justice

unread,
Dec 7, 2011, 7:50:43 PM12/7/11
to android-ndk
I have coded a solution for calling a remote service from native code.
In a nutshell, you create an intermediate Java object that binds to
the remote service via AIDL. It publishes an interface that maps into
the remote service methods you wish to call. The native code
instantiates the object and then calls through this object to invoke
the remote methods.

I have a test app that seems to be working well using this method.

I have published some detail here: http://interprocess-android.blogspot.com/
and plan to follow up with more detail shortly.

As I have mentioned previously, I am new to Android so comments and
advice are appreciated.

Brad Justice

unread,
Sep 5, 2012, 11:05:17 AM9/5/12
to andro...@googlegroups.com
I am afraid that I have no recommendations for you - I have yet to work on a project where the number of calls made the standard "brute force" approach impractical. There may be others on this forum who are familiar with tools to automate the process.

You could build a generic call gate that passed a data blob from which you extract details of the call and parameters yourself, though I am unconvinced it would make the job easier.

On Tuesday, August 28, 2012 7:33:36 AM UTC-7, Emeric Vigier wrote:
Bradley, your work is very inspiring.
I spent a week on making JNI remote calls work both ways: java calling native, and native calling java.
I am most grateful to Jurij Smakov for his fully explained JNI example. But JNI's GetObject, GetField, NewObject, CallMethod, and method signatures are really painful to deal with. I have hundreds of functions to export this way... I need to define an abstraction layer based on JNI to make message and signal sending (Java/Native) easier. Do you have any idea how to abstract that easily?
Reply all
Reply to author
Forward
0 new messages