一、Android系统中运行没有GUI的java程序的方法
1.Android系统中的虚拟机不是java了,而是dalvikvm,它接收的是.dex格式的文件,所有.class文件需要转换成.dex
文件后才能在Android上运行。使用dx命令可以将.class文件转换为.dex格式的文件,这个命令是Android编译环境自带的,使用前需要先配置
Android的编译环境。
测试程序Hello.java
public class Hello { public static void main(String args[]) { System.out.println("Hello SunFaliang!"); while(true) { try { Thread.sleep(100); } catch(Exception e) {} } } }
转换: # dx --dex --output=Hello.jar Hello.class 执行: # dalvikvm -cp ./Hello.jar Hello //-cp: 指定class path 另一种方法是使用app_process去执行: # CLASSPATH=./Hello.jar app_process ./ Hello //可以-h查看帮助,‘./’是指定父目录 app_process的用法: # app_process [java-options] cmd-dir start-class-name [options] cmd-dir: 指定要读取文件时基于此目录。 CLASSPATH:指定需要的类从哪里找。 # dx --dex --output=Hello.jar . //将当前目录下的所有class都打包成Hello.jar
2.若多个java文件,简易的编译方法如下
参考frameworks/base/cmds/am/Android.mk LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := $(call all-subdir-java-files) LOCAL_MODULE := your_jar_file_name include $(BUILD_JAVA_LIBRARY)
编译成库是可以的,若是指定编译成可执行文件,报AndroidManifest.xml找不到(适合编译AS写的App)
3.使用dalvikvm和app_process运行程序的区别
可以看其进程的/proc文件,使用app_process启动的进程里面会创建2个binder线程(comm为binder_1和binder_2),而dalvikvm是没有的。最常用的也是app_process做测
试。app_process对应的源码文件是frameworks/base/cmds/app_process/app_main.cpp
二、Java实现Hello服务的Demo
1.实现Hello.aidl文件,作为一个接口来使用,编译生成的文件中会包含声明的接口,定义了Stub类,定义了Proxy类。Service和Client都要
基于它来实现。Service端需要继承于Stub类. Client端直接使用Proxy类。
2.编写IHelloService.aidl文件编译生成IHelloService.java文件
参考core/java/android/os/ILedService.aidl实现,目的是生成的IHelloService.java
在Service收到数据后就会调用其onTransaction(),根据参数code值来决定是调用其提供的哪个服务函数。
注意到Stub类中并没有实现服务提供的接口里面的函数,所以Service继承Stub类后要去实现。
IHelloService.java里面实现了代理类,之后我们写Client程序的时候就不用去实现代理类了,直接使用就可以了。
3.参考SystemServer.java怎么打印log信息,System.out.println();会把log打印到串口,Slog.i();会把log打印到日志中。
4.自己实现的HelloService.java的while(1)循环中就可以什么都不做,app_process在启动HelloService的时候创建了两个线程binder_1和
binder_2,这两个线程负责读数据,解析数据,处理和reply。
5.代码路径:
git clone https://github.com/weidongshan/APP_0005_Binder_JAVA_App.git
Android.mk参考:frameworks/base/cmds/am/Android.mk
IHelloService.java
/* * This file is auto-generated. DO NOT MODIFY. * Original file: frameworks/base/core/java/android/os/IHelloService.aidl */ /** {@hide} */ public interface IHelloService extends android.os.IInterface { /** Local-side IPC implementation stub class. */ /* * extends一个,implements一个,约等于多继承 * 静态内部类的唯一好处就是可以直接访问外部类的static成员变量 * */ public static abstract class Stub extends android.os.Binder implements IHelloService { private static final java.lang.String DESCRIPTOR = "IHelloService"; /** Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an IHelloService interface, * generating a proxy if needed. */ public static IHelloService asInterface(android.os.IBinder obj) { if ((obj==null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin!=null) && (iin instanceof IHelloService))) { return ((IHelloService)iin); } return new IHelloService.Stub.Proxy(obj); } @Override public android.os.IBinder asBinder() { return this; } /* * 这个是HelloService的onTransact实现体, 是供Service程序使用的, * HelloService收到数据后会调用这个函数。注意首先要确保, * HelloService能收到数据才行(与C/C++实现的数据格式一致才行)。 */ @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException { switch (code) { case INTERFACE_TRANSACTION: { reply.writeString(DESCRIPTOR); return true; } case TRANSACTION_sayhello: { /*这面会读取出Client写入的DESCRIPTOR*/ data.enforceInterface(DESCRIPTOR); this.sayhello(); /*调用Service的sayhello函数*/ reply.writeNoException(); return true; } case TRANSACTION_sayhello_to: { data.enforceInterface(DESCRIPTOR); java.lang.String _arg0; _arg0 = data.readString(); /*读取Client发来的参数*/ int _result = this.sayhello_to(_arg0); /*调用Service的sayhello函数*/ /* * 先写入异常值,然后才写入返回结果 * Client端的实现也要先读取会异常值,判断没有异常发生时再调用获取结果的函数 */ reply.writeNoException(); reply.writeInt(_result); /*将执行结果写回给Client*/ return true; } } return super.onTransact(code, data, reply, flags); /*调用父类的onTransact函数回复数据*/ } /* * Proxy类是IHelloService的实现类,是供Client端使用的. * 这个Proxy类已经实现好了,cilent程序直接使用就可以了。 */ private static class Proxy implements IHelloService { private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) { mRemote = remote; } @Override public android.os.IBinder asBinder() { return mRemote; } public java.lang.String getInterfaceDescriptor() { return DESCRIPTOR; } @Override public void sayhello() throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); try { /*会先写入"IHelloService",Service端必须要先把它读取出来*/ _data.writeInterfaceToken(DESCRIPTOR); mRemote.transact(Stub.TRANSACTION_sayhello, _data, _reply, 0); /*还会在读取出一个异常,Service必须要写入一个uint_32的0,表示无异常*/ _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } @Override public int sayhello_to(java.lang.String name) throws android.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); /*构造参数*/ /*会导致Service端的onTransact()被调用*/ mRemote.transact(Stub.TRANSACTION_sayhello_to, _data, _reply, 0); _reply.readException(); _result = _reply.readInt(); /*读回返回值*/ } finally { _reply.recycle(); _data.recycle(); } return _result; } } /* * 这个常量用于保证Client端和Service端相同,若是使用C/C++实现Service/Client,这个 * 值要和Java值保持一致。 */ 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); /*Stub类中implements了IHelloService,但是没有实现其接口函数,留给HelloService来实现*/ } public void sayhello() throws android.os.RemoteException; public int sayhello_to(java.lang.String name) throws android.os.RemoteException; }
TestClient.java
import android.util.Slog; import android.os.ServiceManager; import android.os.IBinder; /* 1. getService * 2. 调用服务的sayhello,sayhello_to */ /* test_client <hello|goodbye> [name] */ public class TestClient { private static final String TAG = "TestClient"; public static void main(String args[]) { if (args.length == 0) { System.out.println("Usage: need parameter: <hello|goodbye> [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) {} } } } }
TestServer.java
import android.util.Slog; import android.os.ServiceManager; /* 1. addService * 2. while(true) { read data, parse data, call function, reply } */ public class TestServer { private static final String TAG = "TestServer"; public static void main(String args[]) { /* add Service */ Slog.i(TAG, "add hello service"); ServiceManager.addService("hello", new HelloService()); /* * 这里什么都不用做,因为在使用app_process启动这个服务的时候会 * 创建两个binder线程(/proc/../task/comm为binder_1和binder_2) * 然后由这两个线程支持read-parse-process-reply的流程。 */ while (true) { try { Thread.sleep(100); } catch (Exception e){} } } }
编译:
a.先将IHelloService.aidl仿照Vibrator的放到frameworks/base/core/java/android/os下,执行mm编译后获得IHelloService.java.
b.将测试程序放到frameworks/test目录下,mm .编译
测试:
将生成的文件是test_client.jar和test_service.jar拷贝到开发板上
# logcat TestServer:* TestClient:* HelloService:* *:S &
# CLASSPATH=./TestServer.jar app_process ./ TestServer &
# CLASSPATH=./TestClient.jar app_process ./ TestClient hello
# CLASSPATH=./TestClient.jar app_process ./ TestClient hello ZhangShan
三、Binder系统分层
1.对于同一个服务,在SM中的handle值和在Client中的handle值是不同的。handle是per进程的,每个进程获得的handle都是从1(0是SM特有的)开始的!
2.所有的服务在内核中都是使用binder_node结构表示的,不同服务的binder_node的区别是ptr和cookie域不同。因此client在使用对应服务时,binder驱动会将指定服务的binder_node的ptr和cookie赋值给Client传给Service的数据中的对应的域。
3.Binder系统过程分析
(1)addService("Hello", *ptr),在C实现的Demo中调用bio_put_obj(),将ptr赋值给flat_binder_object.binder,cookie赋值为0。内核中
表示服务的binder_node结构的*ptr和*cookie的值就是由Service应用程序传参控制的,可用于区分不同的Service。
void bio_put_obj(struct binder_io *bio, void *ptr) { /*内核中根据这个结构体创建binder_node结构体*/ struct flat_binder_object *obj; obj = bio_alloc_obj(bio); if (!obj) return; obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS; obj->type = BINDER_TYPE_BINDER; obj->binder = (uintptr_t)ptr; obj->cookie = 0; /*这里的binder和cookie都是由Service决定的*/ }
a.binder驱动收到flat_binder_object结构体,且其type = BINDER_TYPE_BINDER(表示Service),就会在内核中创建一个binder_node结构体,
其target.ptr和cookie来自Service传入的flat_binder_object结构体。
b.由于addService()时指定的handle=0,binder驱动会将收到的数据转发给SM进程,并为SM进程构造一个binder_ref结构体,其node指向Hello
Service的binder_node结构体,其desc域为1(假设Hello Servie是系统中第一个向SM注册的服务)表示此Service是第一个注册进SM的服务。SM用
户空间程序会在svlist链表上创建一个svcinfo结构记录下这个Hello服务,其name="hello",handle就等于binder_ref中的desc(就是1)。
(2)getService("hello")
c.cilent向SM获取服务(构造数据handle=0),SM在svlist通过名字"hello"进行查找,找到对应的Hello服务,其handle为1,然后就构造一个flat_binder_object结构体
其type=BINDER_TYPE_HANDLE(表示引用),然后发给驱动。驱动检测数数据中有一个flat_binder_object结构体且type=BINDER_TYPE_HANDLE(表示引用)
就会为Client进程也创建一个binder_ref结构体,其node域指向表示Hello服务的binder_node结构体,其desc为1(假定Hello服务是Client进程中获取
的第一个服务),表示Hello服务是Client获取的第一个服务。然后返回handle=1给到Client用户空间程序,之后Client程序就可以通过handle来使用Hello
服务了。
(3)Client端使用Hello服务
d.构造数据(handle=1, 要使用Service的函数编号,参数),然后发给驱动。驱动根据handle=1在本进程的binder_ref树中找到对应的binder_ref结构体,然后
根据binder_ref.node找到表示Hello服务的binder_node结构体,然后根据binder_node.proc找到Hello服务的binder_proc结构体,然后根据binder_proc.tsk
找到Hello服务进程。然后驱动构造一个binder_transaction_data,并使Hello服务的binder_node.ptr域赋值给binder_transaction_data.target.ptr,
binder_node.cookie赋值给binder_transaction_data.cookie,然后binder驱动把数据发给Hello服务进程。
e.Hello服务进程收到数据解析出binder_transaction_data结构,根据其target.ptr和(或)cookie域知道Client要使用哪个服务(因为一个进程可能注册多个服务,
只不过这个Hello服务进程只注册了一个服务而已)。然后根据binder_transaction_data.code知道Client要调用服务的哪个函数。然后调用对应的函数,并把执行
结果返回给Client。
然后释放buffer。
binder_ref是区分进程的,binder_node表示服务是不区分进程的。用户空间的handle来源于binder_ref,所以它也是per进程的(除了SM的恒为0)。
4.Java的Binder系统分为3层
服务层 -------------- RPC层 ------------- IPC层(最核心的类是IPCThreadState) -------------
若是使用C++实现一个服务的话,只有IPC不需要自己写,RPC层和服务层都需要自己写。若是使用Java来实现一个服务我们就只需要实现服务层。
ptr在C例子实现中用于区分同一进程中注册的不同服务。在framework中的C++实现中cookie保存的是BnBinder派生的HelloService对象,
用于调用onTransact().
Java的实现中发送数据也是通过IPCThreadState(C++实现)提供的函数来发送的,这就涉及到了JNI的使用。
四、java实现内部机制_Client端
1.Client端的实现 包括TestServer向SM发送addService请求、TestClient向SM发送getService请求、TestClient向TestServer发送调用say_hello()的请求。 (1)addService/getService请求 ServiceManager.addService("hello", new HelloService()); //TestServer.java ServiceManagerProxy(obj).addService(name, service, false); //ServiceManagerNative.java mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0); //ServiceManagerNative.java 调用它发送数据 IBinder binder = ServiceManager.getService("hello"); //TestClient.java ServiceManagerProxy(obj).getService(name); //ServiceManagerNative.java mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0); //ServiceManagerNative.java 调用它发送数据 (2)Client使用sayhello()/sayhello_to() IHelloService svr = IHelloService.Stub.asInterface(binder); //TestClient.java svr.sayhello(); //TestClient.java IHelloService.Stub.Proxy(obj).sayhello(); //IHelloService.java Client端和Service端最终都是调用IBinder mRemote来发送数据,Client端和Service端就统一起来了。 调用mRemote.transact(Stub.TRANSACTION_sayhello, _data, _reply, 0);来发送数据 数据传输3要素: 源:调用mRemote.transact的进程 目的:mRemote 数据本身:参数 Binder中的目的是使用handle表示的,对于addService()/getService()这个mRemote中肯定有handle=0这个成员。 mRemote是一个java BinderProxy对象(但是看代码是IBinder对象),它的 mObject指向一个C++的BpBinder对象,这个BpBInder的mHandle=0表示要发给SM进程。 对于Client使用sayhello()/sayhello_to(),mRemote是一个java BinderProxy对象(但是看代码是IBinder对象),它的 mObject指向一个C++的BpBinder对象,这个BpBInder的mHandle=1(来自getService("hello"))表示要发给HelloService进程。 1.ServiceManagerProxy中mRemote的构造 (用于addService/getService) 猜测:使用0直接构造出一个java BinderProxy对象 ServiceManager.addService("hello", new HelloService()); 或 ServiceManager.getService("hello"); //TestServer.java getIServiceManager().addService(name, service, false); //ServiceManager.java a. getIServiceManager() ServiceManagerNative.asInterface(BinderInternal.getContextObject()); a1. 分析BinderInternal.getContextObject() //BinderInternal.java,getContextObject()是一个native函数 //这个函数最终得到一个java BinderProxy对象, 其中mObject指向new BpBinder(0);。 android_os_BinderInternal_getContextObject //android_util_Binder.cpp sp<IBinder> b = ProcessState::self()->getContextObject(NULL); //android_util_Binder.cpp return getStrongProxyForHandle(0); //ProcessState.cpp,直接指定的是handle=0,是SM b = new BpBinder(0); //BpBinder.cpp BpBinder.mHandle=0 return javaObjectForIBinder(env, b); //android_util_Binder.cpp b = new BpBinder(0), mHandle = 0 object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor); //android_util_Binder.cpp //JNI代码中使用NewObject()来创建Java的BinderProxy对象。 const char* const kBinderProxyPathName = "android/os/BinderProxy"; clazz = env->FindClass(kBinderProxyPathName); gBinderProxyOffsets.mConstructor = env->GetMethodID(clazz, "<init>", "()V"); //调用的是BinderProxy的构造函数。 a2.分析ServiceManagerNative.asInterface new ServiceManagerProxy(obj); // obj = BinderProxy对象 mRemote = obj = BinderProxy对象, 其中mObject指向new BpBinder(0), 0表示是SM。 所以getService/setService使用的mRemote已经构造出来了。 2.Hello服务里面的mRemote如何构造的 a. IBinder binder = ServiceManager.getService("hello"); //猜测: 它的返回值就是一个java BinderProxy对象, 其中的mObject=new BpBinder(handle) new ServiceManagerProxy().getService("hello"); //ServiceManagerNative.java //构造数据通过mRemote发送出去,从返回的结果中得到 IBinder binder = reply.readStrongBinder(); //ServiceManagerNative.java return nativeReadStrongBinder(mNativePtr); //Parcel.java 它标注为native,是一个JNI函数 // 把java Parce对象转换为c++ Parcel对象 // client程序向sevice_manager发出getService请求, // 得到一个回复reply, 它里面含有flat_binder_object // 它被封装成一个c++ Parcel对象 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); //它应该会把上面的flat_binder_object转换成一个BpBinder对象。 //它会创建一个java BinderProxy对象, 其中的mObject=new BpBinder(handle)对象 return javaObjectForIBinder(env, parcel->readStrongBinder()); //android_os_Parcel.cpp a1. parcel->readStrongBinder()返回一个 new BpBinder(handle)对象,其中handle是HelloService的handle unflatten_binder(ProcessState::self(), *this, &val); //Parcel.cpp finish_unflatten_binder //Parcel.cpp b = new BpBinder(handle); b. IHelloService svr = IHelloService.Stub.asInterface(binder); //TestClient.java return new IHelloService.Stub.Proxy(obj); //IHelloService.java mRemote = obj; //那么,a中返回的就是一个BinderProxy对象。 3.现在知道了mRemote就是一个java的BinderProxy对象(定义在Binder.java中),mRemote.transact()的实现方法如下 BinderProxy.transact(int code, Parcel data, Parcel reply, int flags); //Binder.java return transactNative(code, data, reply, flags); //它是一个JNI调用,对应android_os_BinderProxy_transact android_os_BinderProxy_transact //android_util_Binder.cpp //取出data和reply, 把java对象转换为C++对象。 Parcel* data = parcelForJavaObject(env, dataObj); Parcel* reply = parcelForJavaObject(env, replyObj); //从java BinderProxy对象中把mObject取出, 它就是一个BpBinder对象 IBinder* target = (IBinder*)env->GetLongField(obj, gBinderProxyOffsets.mObject); //然后调用BpBinder的transact status_t err = target->transact(code, *data, reply, flags); 4."怎么发"结论如下 对于getService/setService,会得到一个ServiceManagerProxy代理类,对应Hello服务也会得到一个 代理类IHelloService.Stub.Proxy。这些代理类中都有一个mRemote成员, 它是一个java的BinderProxy对象,它的mObject成员指向一个C++的BpBinder对象, BpBinder中有一个mHandle(对于addService/getService它是0,对于Hello服务,它 来自getService的结果)。 发送数据时,调用mRemote.transact(),它会从mObject中取出BpBinder对象,调用它的 transact函数,从而实现了Java实现的RPC对C++实现的IPC的调用。
五、Java实现内部机制_Service端实现
1. Server怎么读到数据 看HelloService.java源码,它addService()之后就去睡眠去了,那是谁在读取处理数据呢,是使用app_process创建的两个binder线程binder_1和binder_2做的, 源码: app_process: frameworksasecmdsapp_processapp_main.cpp app_process来启动server进程,它会先创建子线程: AppRuntime::onStarted() proc->startThreadPool(); spawnPooledThread(true); sp<Thread> t = new PoolThread(isMain); t->run(name.string()); //它会创建子线程, 并执行threadLoop IPCThreadState::self()->joinThreadPool(mIsMain); { do { result = getAndExecuteCommand(); result = talkWithDriver(); result = executeCommand(cmd); 对于BR_TRANSACTION数据, sp<BBinder> b((BBinder*)tr.cookie); //cookie来区分是哪个服务,一个进程可能注册了多个Service。 error = b->transact(tr.code, buffer, &reply, tr.flags); } while(...) } 2. server读到数据后怎么调用服务PRC层的onTransact函数 a. 在addService时设置.ptr/.cookie ServiceManager.addService("hello", new HelloService()); 分析: a.1 new HelloService()是JAVA对象 a.2 处理数据时把.cookie转换成BBinder对象, 它是c++对象 所以: addService中肯定会把JAVA对象转换成一个BBinder派生类对象,存在.cookie里 结论: a.1 addService会通过JNI调用c++函数: 创建一个BBinder派生类JavaBBinder对象, 它的.mObject指向JAVA对象: new HelloService() 它含有onTransact函数 把这个对象存入.cookie(最终存入binder驱动中该服务对应的binder_node.cookie) a.2 server进程从驱动中读到数据,里面含有.cookie 把它转换为BBinder对象, 调用它的transact函数 它会调用到派生类JavaBBinder中定义的onTransact函数 a.3 JavaBBinder中定义的onTransact函数(c++) 它通过JNI调用java Binder的execTransact方法, 然后调用Binder派生类IHelloService.Stub中定义的onTransact函数(JAVA) a.4 IHelloService.Stub中定义的onTransact函数(JAVA): 分析数据 调用sayhello/sayhello_to 源码阅读: a.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++实现) a.2 android_os_Parcel_writeStrongBinder(c++) 它会构造一个JavaBBinder对象(c++),.mObject=new HelloService() JAVA对象 然后让.cookie=JavaBBinder对象(c++) //把Java Parcel转换为c++ Parcel Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); //.cookie = ibinderForJavaObject(env, object)得到一个JavaBBinder对象 parcel->writeStrongBinder(ibinderForJavaObject(env, object)) a.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() a.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<jlong>(&data), reinterpret_cast<jlong>(reply), flags); a.5 java Binder execTransact: res = onTransact(code, data, reply, flags); 调用HelloService中的onTransact方法(来自IHelloService.Stube) 分辨数据 调用sayhello/sayhello_to
六、修改C/C++实现与Java实现兼容
1.aidl文件生成的IHelloService.java的onTransact()是在Service收到数据后调用的。Client需要先获取IHelloService.java中的Proxy类,通过它来发送数据。
2.ILedService在SystemServer.java中add_service的,SystemServer中没有read-parse-process-reply循环。system_server进程也是使用app_process进程来创建
的,/proc/下也有binder_X线程执行循环。
# cat init.zygote32.rc | grep app_process
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
3.要是C/C++/Java程序实现的Client和Servie兼容,需要确保发送和接收的数据格式是一样的。由于IHelloService.java是根据aidl文件自动生成的,所以以java
文件为准修改C/C++文件。
要点:保证Service和Clicent双方数据(发送和获取)一致!
4.Parcel.cpp主要用于对Binder数据的构造和读写操作。