https://www.bilibili.com/video...1.下面的aidl文件是自己写的一个aidl文件包android.os;interfaceIHelloService{voidsetVal(intval);intgetVal();}注意这是一个aidl文件,编译后会生成一个IHelloService.java。让我们来看看隐藏在这个文件内容中的玄机,它能如此神奇地支持进程间通信。java中有一个aidl文件,可以为我们省去很多工作。其实下面一段展开aidl文件其实和C++很像。/*这个文件是自动生成的。不要修改。原始文件:frameworks/base/core/java/android/os/IHelloService.aidl/packageandroid.os;publicinterfaceIHelloServiceextendsandroid.os.IInterface{/*Local-sideIPCimplementationstubclass。/publicstaticabstractclassStubextendsandroid.os.Binderimplementsandroid.os.IHelloService//相当于一个Server端,需要一个子类继续继承它,完成接口的实现{privatestaticfinaljava.lang.StringDESCRIPTOR="android.os.IHelloService";/构造存根并将其附加到接口。/publicStub(){this.attachInterface(this,DESCRIPTOR);}/*将IBinder对象转换为android.os.IHelloService接口,如果需要生成代理。/publicstaticandroid.os.IHelloServiceasInterface(android.os.IBinderobj)//类似c++,如果只在客户端去新代理{if((obj==null)){returnnull;}android.os.IInterfaceiin=(android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);如果(((iin!=null)&&(iininstanceofandroid.os.IHelloService))){返回((android.os.IHelloService)iin);}返回新的android.os.IHelloService.Stub.Proxy(obj);}publicandroid.os.IBinderasBinder(){返回这个;}@OverridepublicbooleanonTransact(intcode,android.os.Parceldata,android.os.Parcelreply,intflags)throwsandroid.os.RemoteException{switch(code){caseINTERFACE_TRANSACTION:{reply.writeString(DESCRIPTOR);}返回真;}caseTRANSACTION_setVal:{data.enforceInterface(DESCRIPTOR);诠释_arg0;_arg0=data.readInt();this.setVal(_arg0);回复.writeNoException();返回真;}caseTRANSACTION_getVal:{data.enforceInterface(DESCRIPTOR);int_result=this.getVal();回复.writeNoException();reply.writeInt(_result);返回真;}}returnsuper.onTransact(code,data,reply,flags);}privatestaticclassProxyimplementsandroid.os.IHelloService//这个内部类,相当于一个客户端和C++类{privateandroid.os.IBindermRemote;代理(android.os.IBinder远程){mRemote=remote;}公共android.os。IBinderasBinder(){返回mRemote;}publicjava.lang.StringgetInterfaceDescriptor(){返回描述符;}publicvoidsetVal(intval)throwsandroid.os.RemoteException{android.os.Parcel_data=android.os.Parcel.obtain();android.os.Parcel_reply=android.os.Parcel.obtain();尝试{_data.writeInterfaceToken(DESCRIPTOR);_data.writeInt(val);mRemote.transact(Stub.TRANSACTION_setVal,_data,_reply,0);_reply.readException();}最后{_reply.recycle();_data.回收();}}publicintgetVal()throwsandroid.os.RemoteException{android.os.Parcel_data=android.os.Parcel.obtain();android.os.Parcel_reply=android.os.Parcel.obtain();诠释_结果;尝试{_data.writeInterfaceToken(DESCRIPTOR);mRemote.transact(Stub.TRANSACTION_getVal,_data,_reply,0);_reply.readException();_result=_reply.readInt();}最后{_reply.recycle();_data.回收();}返回结果;}}staticfinalintTRANSACTION_setVal=(android.os.IBinder.FIRST_CALL_交易+0);staticfinalintTRANSACTION_getVal=(android.os.IBinder.FIRST_CALL_TRANSACTION+1);}publicvoidsetVal(intval)throwsandroid.os.RemoteException;publicintgetVal()throwsandroid.os.RemoteException;}这里我们可以看到编译后的IHelloService.aidl文件的真面目。原来是根据IHelloService接口的定义生成了对应的Stub和Proxy类。这是我们熟悉的Binder机制的内容,即实现这个HelloService的Server必须继续这里的IHelloService.Stub类,而这个HelloService的remote接口就是获取到的IHelloService接口的下一个内容IHelloService.Stub.Proxy对象在这里,我们可以看到IHelloService.Stub和IHelloService.Stub.Proxy是如何创建或使用的。2.HelloService的启动过程在讨论HelloService的启动过程之前,我们先来看看实现HelloService接口的Server是如何定义的。我们在frameworks/base/services/java/com/android/server目录下添加了一个HelloService.java文件:packagecom.android.server;importandroid.content.Context;importandroid.os.IHelloService;importandroid.util.Slog;publicclassHelloServiceextendsIHelloService.Stub{//解析aidl文件后,里面的内部类privatestaticfinalStringTAG="HelloService";HelloService(){init_native();}publicvoidsetVal(intval){setVal_native(val);}publicintgetVal(){返回getVal_native();}privatestaticnativebooleaninit_native();privatestaticnativevoidsetVal_native(intval);privatestaticnativeintgetVal_native();}这里,我们可以看到,HelloService继承了IHelloService.Stub类,通过本地方法调用实现getVal和setVal函数。有了服务器类HelloService,下一步就是考虑如何启动它。在frameworks/base/services/java/com/android/server/SystemServer.java文件中,定义了SystemServer类。SystemServer对象是在系统启动时创建的。创建完成后,会启动一个线程创建HelloService,并将其添加到ServiceManager中。我们来看看这部分代码:classServerThreadextendsThread{......@Overridepublicvoidrun(){............try{Slog.i(TAG,"HelloService");ServiceManager.addService("hello",newHelloService());//添加到serviceManager}catch(Throwablee){Slog.e(TAG,"启动Hello服务失败",e);}......Looper.loop();......}}......publicclassSystemServer{.../*该方法从Zygote调用来初始化系统。这将导致启动本机服务(SurfaceFlinger、AudioFlinger等)。之后它将回调到init2()以启动Android服务。*/nativepublicstaticvoidinit1(String[]args);......publicstaticfinalvoidinit2(){Slog.i(TAG,"进入Android系统服务器!");线程thr=newServerThread();thr.setName("android.server.ServerThread");thr.start();}......}3.Client获取HelloService的Java远程接口的过程下面看看它是如何借助ServiceManager的Java远程接口获取HelloService的远程接口的。在ActivityHello的onCreate函数中,通过IServiceManager.getService函数获取HelloService的远程接口:publicclassHelloextendsActivityimplementsOnClickListener{...privateIHelloServicehelloService=null;......@OverridepublicvoidonCreate(BundlesavedInstanceState){helloService=IHelloService.Stub.asInterface(ServiceManager.getService("hello"));//调用自定义的helloservice,但需要将asInterface转为自己的interface}......}至于,java调用c++的那些JNI就不分析了。4.在c层服务中实现java层回调有时候我们自己写一个c层binder服务,然后通过java调用服务中的代码,这时实际上需要在c层注册回调。这时候可以在C层服务的注册接口中添加binder参数,然后用Java实现aidl文件,然后通过服务调用将binder参数传递给C层服务,然后你可以回调C层服务中的java代码。
