1、Android系統中運行沒有GUI的java程序的方法java
1.Android系統中的虛擬機不是java了,而是dalvikvm,它接收的是.dex格式的文件,全部.class文件須要轉換成.dex
文件後才能在Android上運行。使用dx命令能夠將.class文件轉換爲.dex格式的文件,這個命令是Android編譯環境自帶的,使用前須要先配置
Android的編譯環境。node
測試程序Hello.javaandroid
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文件,簡易的編譯方法以下c++
參考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)git
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.cppgithub
2、Java實現Hello服務的Democookie
1.實現Hello.aidl文件,做爲一個接口來使用,編譯生成的文件中會包含聲明的接口,定義了Stub類,定義了Proxy類。Service和Client都要
基於它來實現。Service端須要繼承於Stub類. Client端直接使用Proxy類。app
2.編寫IHelloService.aidl文件編譯生成IHelloService.java文件
參考core/java/android/os/ILedService.aidl實現,目的是生成的IHelloService.java
在Service收到數據後就會調用其onTransaction(),根據參數code值來決定是調用其提供的哪一個服務函數。
注意到Stub類中並無實現服務提供的接口裏面的函數,因此Service繼承Stub類後要去實現。
IHelloService.java裏面實現了代理類,以後咱們寫Client程序的時候就不用去實現代理類了,直接使用就能夠了。ide
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
3、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的使用。
4、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的調用。
5、Java實現內部機制_Service端實現
1. Server怎麼讀到數據 看HelloService.java源碼,它addService()以後就去睡眠去了,那是誰在讀取處理數據呢,是使用app_process建立的兩個binder線程binder_1和binder_2作的, 源碼: app_process: frameworks\base\cmds\app_process\app_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
6、修改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數據的構造和讀寫操做。