binder java_Android : 跟我学Binder --- (6) JAVA实现

目录:

一、Java程序的编译和运行

1.单步操作

PC:Hello.java 编译成 Hello.class,运行于 jvm。

javac Hello.java

java Hello

Android:Hello.java 编译成 Hello.class,通过dx指令转换成.dex格式,运行于 dalvikvm。

javac Hello.java

dx--dex --output=Hello.jar Hello.classdalvikvm-cp /mnt/android_fs/pack.jar Pack (启动方法1)

CLASSPATH=/mnt/android_fs/pack.jar app_process /mnt/android_fs Pack(启动方法2)

启动方式的差别:

dalvikvm

app_process :会创建2个binder线程: Binder_1, Binder_2 (实现读数据、解析数据、返回等操作)

2.Android编译系统(Android.mk)

把代码放到android源码中编译:

添加Androd.mk,内容类似:  // 参考frameworks/base/cmds/am/Android.mk

include $(CLEAR_VARS)

LOCAL_SRC_FILES := $(call all-subdir-java-files)

LOCAL_MODULE :=pack

include $(BUILD_JAVA_LIBRARY)

3.使用java代码实现hello服务

(1)IHelloService.aidl

接口定义,编译生成IHelloService.java,里面有Stub  : onTransact, 它会分辨收到数据然后调用sayhello, sayhello_to;

Proxy : 提供有sayhello, sayhello_to两个函数, 它们会构造数据然后发送给server。

/**{@hide} */

interfaceIHelloService

{

voidsayhello();

intsayhello_to(String name);

}

(2)IHelloService.java

/** This file is auto-generated. DO NOT MODIFY.

* Original file: frameworks/base/core/java/android/os/IHelloService.aidl*/

/**{@hide}*/

public interface IHelloService extendsandroid.os.IInterface

{/**Local-side IPC implementation stub class.*/

public static abstract class Stub extends android.os.Binder implementsIHelloService

{private static final java.lang.String DESCRIPTOR = "IHelloService";/**Construct the stub at attach it to the interface.*/

publicStub()

{this.attachInterface(this, DESCRIPTOR);

}/*** Cast an IBinder object into an IHelloService interface,

* generating a proxy if needed.*/

public staticIHelloService asInterface(android.os.IBinder obj)

{if ((obj==null)) {return null;

}

android.os.IInterface iin=obj.queryLocalInterface(DESCRIPTOR);if (((iin!=null)&&(iin instanceofIHelloService))) {return((IHelloService)iin);

}return newIHelloService.Stub.Proxy(obj);

}

@Overridepublicandroid.os.IBinder asBinder()

{return this;

}

@Overridepublic boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throwsandroid.os.RemoteException

{switch(code)

{caseINTERFACE_TRANSACTION:

{

reply.writeString(DESCRIPTOR);return true;

}caseTRANSACTION_sayhello:

{

data.enforceInterface(DESCRIPTOR);this.sayhello();

reply.writeNoException();return true;

}caseTRANSACTION_sayhello_to:

{

data.enforceInterface(DESCRIPTOR);

java.lang.String _arg0;

_arg0=data.readString();int _result = this.sayhello_to(_arg0);

reply.writeNoException();

reply.writeInt(_result);return true;

}

}return super.onTransact(code, data, reply, flags);

}private static class Proxy implementsIHelloService

{privateandroid.os.IBinder mRemote;

Proxy(android.os.IBinder remote)

{

mRemote=remote;

}

@Overridepublicandroid.os.IBinder asBinder()

{returnmRemote;

}publicjava.lang.String getInterfaceDescriptor()

{returnDESCRIPTOR;

}

@Overridepublic void sayhello() throwsandroid.os.RemoteException

{

android.os.Parcel _data=android.os.Parcel.obtain();

android.os.Parcel _reply=android.os.Parcel.obtain();try{

_data.writeInterfaceToken(DESCRIPTOR);

mRemote.transact(Stub.TRANSACTION_sayhello, _data, _reply,0);

_reply.readException();

}finally{

_reply.recycle();

_data.recycle();

}

}

@Overridepublic int sayhello_to(java.lang.String name) throwsandroid.os.RemoteException

{

android.os.Parcel _data=android.os.Parcel.obtain();

android.os.Parcel _reply=android.os.Parcel.obtain();int_result;try{

_data.writeInterfaceToken(DESCRIPTOR);

_data.writeString(name);

mRemote.transact(Stub.TRANSACTION_sayhello_to, _data, _reply,0);

_reply.readException();

_result=_reply.readInt();

}finally{

_reply.recycle();

_data.recycle();

}return_result;

}

}static final int TRANSACTION_sayhello = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);static final int TRANSACTION_sayhello_to = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);

}public void sayhello() throwsandroid.os.RemoteException;public int sayhello_to(java.lang.String name) throwsandroid.os.RemoteException;

}

(3)HelloService.java

实现服务类: HelloService.java,在里面定义sayhello, sayhello_to;

importandroid.util.Slog;

/*实现Hello服务的函数 */

public class HelloService extendsIHelloService.Stub {

private static final String TAG = "HelloService";

private int cnt1 = 0;

private int cnt2 = 0;

public void sayhello() throwsandroid.os.RemoteException {

cnt1++;

Slog.i(TAG, "sayhello : cnt = "+cnt1);

}

public int sayhello_to(java.lang.String name) throwsandroid.os.RemoteException {

cnt2++;

Slog.i(TAG, "sayhello_to "+name+" : cnt = "+cnt2);

returncnt2;

}

}

(4)IGoodbyeService.aidl (同HelloService)

/**{@hide} */

interfaceIGoodbyeService

{

voidsaygoodbye();

intsaygoodbye_to(String name);

}

(5)IGoodbyeService.java

/** This file is auto-generated. DO NOT MODIFY.

* Original file: frameworks/base/core/java/android/os/IGoodbyeService.aidl

*/

/**{@hide} */

public interface IGoodbyeService extendsandroid.os.IInterface

{

/**Local-side IPC implementation stub class. */

public static abstract class Stub extends android.os.Binder implementsIGoodbyeService

{

private static final java.lang.String DESCRIPTOR = "IGoodbyeService";

/**Construct the stub at attach it to the interface. */

publicStub()

{

this.attachInterface(this, DESCRIPTOR);

}

/*** Cast an IBinder object into an IGoodbyeService interface,

* generating a proxy if needed.

*/

public staticIGoodbyeService asInterface(android.os.IBinder obj)

{

if ((obj==null)) {

return null;

}

android.os.IInterface iin =obj.queryLocalInterface(DESCRIPTOR);

if (((iin!=null)&&(iin instanceofIGoodbyeService))) {

return((IGoodbyeService)iin);

}

return newIGoodbyeService.Stub.Proxy(obj);

}

@Override publicandroid.os.IBinder asBinder()

{

return this;

}

@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throwsandroid.os.RemoteException

{

switch(code)

{

caseINTERFACE_TRANSACTION:

{

reply.writeString(DESCRIPTOR);

return true;

}

caseTRANSACTION_saygoodbye:

{

data.enforceInterface(DESCRIPTOR);

this.saygoodbye();

reply.writeNoException();

return true;

}

caseTRANSACTION_saygoodbye_to:

{

data.enforceInterface(DESCRIPTOR);

java.lang.String _arg0;

_arg0 =data.readString();

int _result = this.saygoodbye_to(_arg0);

reply.writeNoException();

reply.writeInt(_result);

return true;

}

}

return super.onTransact(code, data, reply, flags);

}

private static class Proxy implementsIGoodbyeService

{

privateandroid.os.IBinder mRemote;

Proxy(android.os.IBinder remote)

{

mRemote =remote;

}

@Override publicandroid.os.IBinder asBinder()

{

returnmRemote;

}

publicjava.lang.String getInterfaceDescriptor()

{

returnDESCRIPTOR;

}

@Override public void saygoodbye() throwsandroid.os.RemoteException

{

android.os.Parcel _data =android.os.Parcel.obtain();

android.os.Parcel _reply =android.os.Parcel.obtain();

try{

_data.writeInterfaceToken(DESCRIPTOR);

mRemote.transact(Stub.TRANSACTION_saygoodbye, _data, _reply, 0);

_reply.readException();

}

finally{

_reply.recycle();

_data.recycle();

}

}

@Override public int saygoodbye_to(java.lang.String name) throwsandroid.os.RemoteException

{

android.os.Parcel _data =android.os.Parcel.obtain();

android.os.Parcel _reply =android.os.Parcel.obtain();

int_result;

try{

_data.writeInterfaceToken(DESCRIPTOR);

_data.writeString(name);

mRemote.transact(Stub.TRANSACTION_saygoodbye_to, _data, _reply, 0);

_reply.readException();

_result =_reply.readInt();

}

finally{

_reply.recycle();

_data.recycle();

}

return_result;

}

}

static final int TRANSACTION_saygoodbye = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);

static final int TRANSACTION_saygoodbye_to = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);

}

public void saygoodbye() throwsandroid.os.RemoteException;

public int saygoodbye_to(java.lang.String name) throwsandroid.os.RemoteException;

}

(6)GoodbyeService.java

importandroid.util.Slog;/*实现Goodbye服务的函数*/

public class GoodbyeService extendsIGoodbyeService.Stub {private static final String TAG = "GoodbyeService";private int cnt1 = 0;private int cnt2 = 0;public void saygoodbye() throwsandroid.os.RemoteException {

cnt1++;

Slog.i(TAG,"saygoodbye : cnt = "+cnt1);

}public int saygoodbye_to(java.lang.String name) throwsandroid.os.RemoteException {

cnt2++;

Slog.i(TAG,"saygoodbye_to "+name+" : cnt = "+cnt2);returncnt2;

}

}

(7)TestServer.java (addService, 循环)

importandroid.util.Slog;

importandroid.os.ServiceManager;

/*1. addService

* 2. while(true) { read data, parse data, call function, reply }

*/

public classTestServer {

private static final String TAG = "TestServer";

public static voidmain(String args[])

{

/*add Service */Slog.i(TAG, "add hello service");

ServiceManager.addService("hello", newHelloService());

Slog.i(TAG, "add goodbye service");

ServiceManager.addService("goodbye", newGoodbyeService());

while (true)

{

try{

Thread.sleep(100);

} catch(Exception e){}

}

}

}

(8)TestClient.java (getService, 调用sayhello,sayhello_to(来自Proxy))

importandroid.util.Slog;importandroid.os.ServiceManager;importandroid.os.IBinder;/*1. getService

* 2. 调用服务的sayhello,sayhello_to

**/

/*test_client [name]*/

public classTestClient {private static final String TAG = "TestClient";public static voidmain(String args[])

{if (args.length == 0)

{

System.out.println("Usage: need parameter: [name]");return;

}if (args[0].equals("hello"))

{/*1. getService*/IBinder binder= ServiceManager.getService("hello");if (binder == null)

{

System.out.println("can not get hello service");

Slog.i(TAG,"can not get hello service");return;

}

IHelloService svr=IHelloService.Stub.asInterface(binder);if (args.length == 1)

{try{

svr.sayhello();

System.out.println("call sayhello");

Slog.i(TAG,"call sayhello");

}catch(Exception e) {}

}else{try{int cnt = svr.sayhello_to(args[1]);

System.out.println("call sayhello_to "+args[1]+" : cnt = "+cnt);

Slog.i(TAG,"call sayhello_to "+args[1]+" : cnt = "+cnt);

}catch(Exception e) {

System.out.println("call sayhello_to , err :"+e);

Slog.i(TAG,"call sayhello_to , err : "+e);

}

}

}else if (args[0].equals("goodbye"))

{/*1. getService*/IBinder binder= ServiceManager.getService("goodbye");if (binder == null)

{

System.out.println("can not get goodbye service");

Slog.i(TAG,"can not get goodbye service");return;

}

IGoodbyeService svr=IGoodbyeService.Stub.asInterface(binder);if (args.length == 1)

{try{

svr.saygoodbye();

System.out.println("call saygoodbye");

Slog.i(TAG,"call saygoodbye");

}catch(Exception e) {}

}else{try{int cnt = svr.saygoodbye_to(args[1]);

System.out.println("call saygoodbye_to "+args[1]+" : cnt = "+cnt);

Slog.i(TAG,"call saygoodbye_to "+args[1]+" : cnt = "+cnt);

}catch(Exception e) {}

}

}

}

}

(9)Android.mk

# Copyright 2008The Android Open Source Project

#

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_SRC_FILES :=HelloService.java IHelloService.java GoodbyeService.java IGoodbyeService.java TestServer.java

LOCAL_MODULE :=TestServer

include $(BUILD_JAVA_LIBRARY)

include $(CLEAR_VARS)

LOCAL_SRC_FILES :=HelloService.java IHelloService.java GoodbyeService.java IGoodbyeService.java TestClient.java

LOCAL_MODULE :=TestClient

include $(BUILD_JAVA_LIBRARY)

编译&测试说明:

(1) AIDL

1. 把 IHelloService.aidl, IGoodbyeService.aidl 放入 frameworks/base/core/java/android/os

2. 修改 frameworks/base/Android.mk 添加一行

core/java/android/os/IVibratorService.aidl \

+ core/java/android/os/IHelloService.aidl \

+ core/java/android/os/IGoodbyeService.aidl \

3. mmm frameworks/base

4. 它会生成:

./out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/os/IHelloService.java

./out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/os/IGoodbyeService.java

(2) 编译:

把程序放到 /work/android-5.0.2/frameworks/testing/APP_0005_Binder_JAVA_App

执行:

cd /work/android-5.0.2

. setenv

lunch // 选择单板

mmm frameworks/testing/APP_0005_Binder_JAVA_App

它会生成 TestServer.jar, TestClient.jar

复制文件到NFS目录

cp /work/android-5.0.2/out/target/product/tiny4412/system/framework/Test*.jar /work/nfs_root/android_fs/

(3) 测试:

logcat TestServer:* TestClient:* HelloService:* *:S &

CLASSPATH=/mnt/android_fs/TestServer.jar app_process / TestServer &

CLASSPATH=/mnt/android_fs/TestClient.jar app_process / TestClient hello

CLASSPATH=/mnt/android_fs/TestClient.jar app_process / TestClient hello 100ask.taobao.com

CLASSPATH=/mnt/android_fs/TestClient.jar app_process / TestClient goodbye

CLASSPATH=/mnt/android_fs/TestClient.jar app_process / TestClient goodbye weidongshan

二、内部机制

1.Client端1.1 ServiceManagerProxy中mRemote的构造 (用于addService/getService)

使用0直接构造出一个java BinderProxy对象

getIServiceManager().addService  / getIServiceManager().getService

getIServiceManager()

return ServiceManagerNative.asInterface(BinderInternal.getContextObject())

a. BinderInternal.getContextObject()  // 得到了一个Java BinderProxy对象, 其中mObject指向new BpBinder(0);

它是一个JNI调用,对应 android_os_BinderInternal_getContextObject // android_util_Binder.cpp

android_os_BinderInternal_getContextObject

sp b = ProcessState::self()->getContextObject(NULL);

getStrongProxyForHandle(0);

b = new BpBinder(handle);  // mHandle = 0

return javaObjectForIBinder(env, b);        // b = new BpBinder(0), mHandle = 0

// 使用c代码调用NewObject来创建JAVA BinderProxy对象

object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);

// 设置该对象的mObject = val.get = b = new BpBinder(0)

env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());

return object;

b. ServiceManagerNative.asInterface

new ServiceManagerProxy(obj); // obj = BinderProxy对象

mRemote = obj = BinderProxy对象, 其中mObject指向new BpBinder(0);

1.2 hello服务里的mRemote如何构造

a. IBinder binder = ServiceManager.getService("hello");

它的返回值就是一个java BinderProxy对象, 其中的mObject=new BpBinder(handle)

new ServiceManagerProxy().getService("hello")

....

IBinder binder = reply.readStrongBinder();

nativeReadStrongBinder  // Parcel.java

nativeReadStrongBinder是一个JNI调用, 对应的代码是 android_os_Parcel_readStrongBinder

android_os_Parcel_readStrongBinder

// 把java Parce对象转换为c++ Parcel对象

// client程序向sevice_manager发出getService请求,

// 得到一个回复reply, 它里面含有flat_binder_object

// 它被封装成一个c++ Parcel对象

Parcel* parcel = reinterpret_cast(nativePtr);

/* parcel->readStrongBinder()应该是一个 new BpBinder(handle)

*             unflatten_binder(ProcessState::self(), *this, &val);

*                  *out = proc->getStrongProxyForHandle(flat->handle);

*                                  b = new BpBinder(handle);

*/

// 它会创建一个java BinderProxy对象, 其中的mObject=new BpBinder(handle)对象

return javaObjectForIBinder(env, parcel->readStrongBinder());

b. IHelloService svr = IHelloService.Stub.asInterface(binder);

new IHelloService.Stub.Proxy(obj);  // obj = 步骤a得到的binder

mRemote = remote;

1.3 现在知道了:mRemote就是一个java BinderProxy 对象

看一下mRemote.transact()

transactNative(code, data, reply, flags);

它是一个JNI调用,对应android_os_BinderProxy_transact

android_os_BinderProxy_transact

// 从java BinderProxy对象中把mObject取出, 它就是一个BpBinder对象

IBinder* target = (IBinder*)env->GetLongField(obj, gBinderProxyOffsets.mObject);

// 然后调用BpBinder的transact

status_t err = target->transact(code, *data, reply, flags);

056d6340e74a960b1a2afae7123f78c5.png

2.Server端

2.1 server如何读取数据

使用app_process来启动server进程,

/*测试指令*/

logcat TestServer:* TestClient:* HelloService:* *:S &CLASSPATH=/mnt/android_fs/TestServer.jar app_process / TestServer &CLASSPATH=/mnt/android_fs/TestClient.jar app_process /TestClient hello

CLASSPATH=/mnt/android_fs/TestClient.jar app_process /TestClient hello sheldon/*参考源码*/

//app_process: frameworks\base\cmds\app_process\app_main.cpp

它会先创建子线程(前面示例提到的两个binder线程:Binder_1, Binder_2):

AppRuntime::onStarted()

proc->startThreadPool();

spawnPooledThread(true);

sp t = new PoolThread(isMain);

t->run(name.string());

// 它会创建子线程, 并执行threadLoop

IPCThreadState::self()->joinThreadPool(mIsMain);

{

do {

result = getAndExecuteCommand();

result = talkWithDriver();

result = executeCommand(cmd);

对于BR_TRANSACTION数据,

sp b((BBinder*)tr.cookie); //将.cookie转换成BBinder对象

error = b->transact(tr.code, buffer, &reply, tr.flags); //并调用其transact方法

} while(...)

}

2.2 server读到数据后怎么调用服务PRC层的onTransact函数

在addService时设置.ptr/.cookie

ServiceManager.addService("hello", new HelloService());

结论:

① addService会通过JNI调用c++函数:

创建一个BBinder派生类JavaBBinder对象,

它的.mObject指向JAVA对象: new HelloService()

它含有onTransact函数

把这个对象存入.cookie(最终存入binder驱动中该服务对应的binder_node.cookie)

② server进程从驱动中读到数据,里面含有.cookie

把它转换为BBinder对象,

调用它的transact函数

最终调用到派生类JavaBBinder中定义的onTransact函数

③ JavaBBinder中定义的onTransact函数(c++)

它通过JNI调用java Binder的execTransact方法,

然后调用Binder派生类IHelloService.Stub中定义的onTransact函数(JAVA)

④ IHelloService.Stub中定义的onTransact函数(JAVA):

分析数据

调用sayhello/sayhello_to

源码阅读:

(1) ServiceManager.addService("hello", new HelloService());

ServiceManagerProxy.addService:

// Parcel.java

data.writeStrongBinder(service);

nativeWriteStrongBinder(mNativePtr, val); // val = service = new HelloService()

它是一个JNI调用,对应android_os_Parcel_writeStrongBinder(c++)

(2) android_os_Parcel_writeStrongBinder(c++)

它会构造一个JavaBBinder对象(c++),.mObject=new HelloService() JAVA对象

然后让.cookie=JavaBBinder对象(c++)

// 把Java Parcel转换为c++ Parcel

Parcel* parcel = reinterpret_cast(nativePtr);

// .cookie = ibinderForJavaObject(env, object)得到一个JavaBBinder对象

parcel->writeStrongBinder(ibinderForJavaObject(env, object))

(3) ibinderForJavaObject(env, object) //object = new HelloService()

把一个Java对象(new HelloService())转换为c++ IBinder对象

JavaBBinderHolder* jbh = (JavaBBinderHolder*)env->GetLongField(obj, gBinderOffsets.mObject);

return jbh != NULL ? jbh->get(env, obj) : NULL;

b = new JavaBBinder(env, obj); // obj = new HelloService()

mObject = new HelloService()

(4) 从驱动中得过了.cookie, 它是一个JavaBBinder对象

调用它的transact函数,导致JavaBBinder对象的onTransact被调用

JavaBBinder::onTransact (调用java里的某个函数)

// mObject指向 HelloService对象

// gBinderOffsets.mExecTransact指向: java Binder类中的execTransact方法

// 调用HelloService(派生自Binder)对象中的execTransact方法

jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,

code, reinterpret_cast(&data), reinterpret_cast(reply), flags);

(5) java Binder execTransact:

res = onTransact(code, data, reply, flags);

调用HelloService中的onTransact方法(来自IHelloService.Stube)

分辨数据

调用sayhello/sayhello_to

-end-

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值