Sure thing. Before I put down the code, I should mention that the native 
side runs as root and the other end (an Android/Java service) runs as 
android.uid.system-- we bundle both with our images.

On the native side, the relevant part is this. I'm cheating with 
SAMPLE_REQUEST_CODE-- I didn't get the base from somewhere authoritative 
like I did in the service, and just declared it as a constant instead. I 
may have missed some includes on the native side-- I still haven't cleaned 
up.

#include <binder/Binder.h>
#include <binder/IBinder.h>
#include <binder/IServiceManager.h>
#include <binder/Parcel.h>

const char* SERVICE_NAME = "org.demo.helloworldservice";
int helloworld() {
    android::sp<android::IServiceManager> sm = 
android::defaultServiceManager();
    android::String16* service_name = new android::String16(SERVICE_NAME);
    android::sp<android::IBinder> mBinder = sm->getService(*service_name);
    delete service_name;

    android::Parcel data;
    android::Parcel reply;
    unsigned int flags = 0;

    mBinder->transact(SAMPLE_REQUEST_CODE, data, &reply, flags);
    return 0;
}

And in the service:

package org.demo.helloworldservice;

import android.app.Service;

import android.os.Binder;
import android.os.IBinder;
import android.os.Parcel;
import android.os.ServiceManager;
import android.util.Log;


public class HelloworldService extends Service {
    private static final String SERVICE_NAME = "org.demo.helloworldservice";
    
    private static final int SAMPLE_REQUEST_CODE = 
IBinder.FIRST_CALL_TRANSACTION + 0;
    
    private IBinder mBinder = null;
    private IHelloworldService mHelloworldService = null;
    
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }
    
    @Override
    public void onCreate(){
        super.onCreate();
        
        mHelloworldService = new IHelloworldService();
        mBinder = mHelloworldService.asBinder();
        ServiceManager.addService(SERVICE_NAME, mBinder);
    }
    
    class IHelloworldService extends Binder {
        protected boolean onTransact(int code, Parcel data, Parcel reply, 
int flags){
            switch(code) {
            case SAMPLE_REQUEST_CODE:
                //Parcel data is the same one that was passed from native 
transact()
                reply.write(1);
                break;
            default:
                reply.write(0);
            }
            return true;
        }
        
        public IBinder asBinder() {
            return this;
        }
    }
}

I don't know what significance, if any, the return value from onTransact 
bears. As far as I can tell, it doesn't have any effect from this side. For 
the communication with other Android-side apps, you could do another 
service with .aidl and have it talk to this one. I haven't tried 
communication the other direction (e.g. HelloworldService -> native), but I 
doubt it's much more complicated than this was (just implement a Binder on 
the native side and register it with IServiceManager). There's probably 
some way to get .aidl to work on both sides, but for my purposes, it wasn't 
worth the effort.

You have a couple of options for getting non-root apps to talk to the root 
HelloworldService, but those aren't hard to find information on (in the 
Android Developers guide on services and on Binder). I'm not sure there's 
any way around having to have another class for apps to talk to, which can 
then talk to the package-local HelloworldService, though.

Testing is pretty easy. HelloworldService has to be signed, but after that 
you can uninstall/reinstall/start with am, and the native component can be 
built, pushed, and started from adb shell. We're building the native 
component in-tree, so it was a matter of a couple of seconds to build with 
mm and push.

Latency-wise it's proving to be pretty good. Even with the added overhead 
of a Settings check, creation/broadcast/reception of a broadcast intent, 
and copying of the intent payload into a text element, it can push out 
easily 20-30 barcodes a second.

Hope this helps.

Jay

On Friday, June 22, 2012 9:28:40 AM UTC-4, neuron wrote:
>
> Hi
>
> Can you share any code on that project? I'm still in the start phase, and 
> there are a few areas which I'm not too certain about. We need to allow 
> other people access to this library, (aka building a sdk for this 
> hardware). I'm having some permission issues going between our native 
> daemon and building a non root installable library to connect to it.
>
> How do you do your testing by the way? Did you add your service 
> to frameworks/base/cmds/servicemanager/service_manager.c and have to push 
> the entire framework, or have you found another way of doing it?
>
> Best regards
> Anders
> On Thu, Jun 21, 2012 at 10:30 PM, Jay Slater <[email protected]>wrote:
>
>> As luck would have it, I actually just did exactly what you're talking 
>> about, though we're only moving barcodes around, and on account of the 
>> simplicity of the data we just used Binder to move everything. Native -> 
>> Java was simple enough; we just implemented a Binder on the Java side and 
>> put it into ServiceManager. The native daemon grabs the binder via the 
>> native side of ServiceManager, and it's that simple. I'm not sure if we're 
>> being entirely kosher with our usage, or if the latency would be low enough 
>> to be useful for you, but it's certainly lower latency than the keyboard 
>> wedge we were using before.
>>
>>
>> On Thursday, June 21, 2012 1:56:25 AM UTC-4, neuron wrote:
>>>
>>> Hi
>>>
>>> We are planning to bundle this with devices. So the highest performance 
>>> lowest latency option is to send the ashmem fd through a binder? This was 
>>> my original plan, but I had several people saying dont link directly to 
>>> cutils, use the binder api instead, as it's a more stable interface. 
>>>
>>> On Thursday, June 21, 2012 4:22:11 AM UTC+2, Dianne Hackborn wrote:
>>>>
>>>> Are you intending this to be a regular third party app that you build 
>>>> against the SDK, or as something built against a specific version of the 
>>>> source code that is bundled with the device?  If the latter, why have you 
>>>> been told to never touch it?  (Though truth be told you will probably want 
>>>> to use binder to transfer references to the ashmem region.)
>>>>
>>>> If the former, you can't do this as pure native code, you need to use 
>>>> the SDK facilities like Service and the Binder interfaces in the Java 
>>>> language, and you definitely aren't going to be running as anything like 
>>>> root.
>>>>
>>>> On Wed, Jun 20, 2012 at 6:32 AM, neuron <[email protected]> wrote:
>>>>
>>>>> Hi
>>>>>
>>>>> I'm currently working on a project to port some hardware to android. 
>>>>> We need to run it as a native daemon, (as root is fine), and to build a 
>>>>> SDK 
>>>>> so people can communicate with it.
>>>>> I've found a lot of different into on how to get this working. The 
>>>>> hardware relies on low latency between hardware and client application. 
>>>>> We've looked into ashmem, (and been recommended to not ever touch it), 
>>>>> and 
>>>>> the android Binder.
>>>>>
>>>>> My current attempt is building https://github.com/keesj/**
>>>>> Android-HelloWorldService<https://github.com/keesj/Android-HelloWorldService>
>>>>>  into 
>>>>> android_source/packages/apps/**Android-HelloWorldService. Building 
>>>>> this produces two c++ native applications. If I as root run them both 
>>>>> they 
>>>>> can communicate, but I can't get that to build an apk for a client side 
>>>>> app, and I'm not sure how to go about doing it either.
>>>>>
>>>>> Am I doing about this the right way? We need low latency communication 
>>>>> between the daemon and the client side applications.
>>>>>
>>>>> I think what I'll eventually end up with is:
>>>>> 1. Our current library, cross compiled to a shared library using 
>>>>> gcc4.6 for arm. (GCC 4.5 or higher is a build requirement, current NDK is 
>>>>> 4.4).
>>>>> 2. A daemon that links to the library above + has binder code. I was 
>>>>> thinking just using init.d to start this on boot.
>>>>> 3. A client native library that connects to the binder above. (The one 
>>>>> from HelloWorldService works, but I have to run it as root to get it to 
>>>>> connect).
>>>>> 4. A java wrapper for the library above.
>>>>> 5. A demo app using our library.
>>>>>
>>>>> And I guess per device we put the hardware in we'll need to build step 
>>>>> 2 and 3 and push them to the device. Installing #2 and possibly something 
>>>>> in #3 as root.
>>>>>
>>>>> Best regards
>>>>> N
>>>>>
>>>>> -- 
>>>>> unsubscribe: 
>>>>> android-porting+unsubscribe@**googlegroups.com<android-porting%[email protected]>
>>>>> website: 
>>>>> http://groups.google.com/**group/android-porting<http://groups.google.com/group/android-porting>
>>>>>
>>>>
>>>>
>>>>
>>>> -- 
>>>> Dianne Hackborn
>>>> Android framework engineer
>>>> [email protected]
>>>>
>>>> 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.
>>>>
>>>>  
>
>
> -- 
> Weeks of coding can save you hours of planning.
> - http://code.google.com/p/aagaande/
>  

-- 
unsubscribe: [email protected]
website: http://groups.google.com/group/android-porting

Reply via email to