您的位置:首页 > 移动开发 > Android开发

Android binder -- Binder应用实例

2014-03-01 00:43 489 查看


Binder应用实例

前一篇文章我们从进程的C/C++层面讲解了binder机制的服务代理对象BpBinder的获取,和Binder底层处理方法。整个服务代理的获取过程也是binder机制的的核心内容,它涉及到了客户请求,请求的传递和处理,服务代理的生成和转换(封装)过程。当客户端获取到对应服务的代理后,就可以通过这个服务代理和服务端通讯了。
本文我们将以binder机制在android中的应用实例,来分析客户端与服务器端的通讯整个流程。不过,在介绍实例前,我们还要花点时间来分析一下binder机制在进程的Java层面服务代理对象的创建和使用。


(一)binder机制中的Java层

我们知道Android中的应用程序基本上都是java开发,对Android的框架了解的朋友都知道,Java的本地实现都是通过JNI层的接口来调用C++/C代码的,这里也不例外。在android的binder机制中,Java层面的binder机制的应用,你可以简单看作是底层binder机制的封装。
Binder客户程序的C/C++层面的对象和原理我们在前面我们已经学习过,下面我们将介绍客户程序怎样在Java层面通过JNI调用底层C/C++代码的创建服务代理的。


(1)ServiceManager类型和对象

我们都知道,作为客户端要想获得服务代理,首先要向ServiceManager查询Service,然后创建并返回服务代理对象,再通过代理对象和Service通讯。当然,在Java层面也是这样,所以客户端首先也要获取ServiceManager这个系统服务的服务代理,再同这个代理来查询并请求服务,所以我们首先分析Java层面ServiceManager类。
Framework\base\core\android\os\ServiceManager.java
publicfinalclassServiceManager{

privatestaticfinalStringTAG="ServiceManager";

privatestaticIServiceManagersServiceManager;

……


上面是ServiceManager类定义,可以看出来ServiceManager也是一个Singleton类型。(成员函数代码暂不贴出来,可以参考源码)所有的方法都是静态方法,包括上面的sServiceManager成员变量(这意味着所有的ServiceManager对象,共享这个变量)。而所有静态方法都是通过调用它的IServiceManager类型的静态变量sServiceManager来实现的。

所以可以理解ServiceManager就是IServiceManager对象的一个代理,它就是一个对sServiceManager封装的一个类。因为创建和访问这个变量都是通过ServiceManager的getIServiceManager方法,定义如下:
privatestaticIServiceManagergetIServiceManager(){

if(sServiceManager!=null){

returnsServiceManager;

}


//Findtheservicemanager

sServiceManager=ServiceManagerNative.asInterface(BinderInternal.getContextObject());

returnsServiceManager;

}

sServiceManager是一个IserviceManager类型,如果它已经创建,就直接返回,否则,创建并返回。当然第一次进入这个函数,是要创建的了,下面就来看看它的具体创建过程吧!
sServiceManager=ServiceManagerNative.asInterface(BinderInternal.getContextObject());

还是老规矩,首先分析asInterface的参数BinderInternal.getContextObject(),哇,好长的参数,必须把丫解了。看到BinderInternal没有,这是什么呢?呵呵,用鼠标就知道了(用sourceinsight的都知道)。
Framework\base\core\com\java\android\os\BinderInternal.java
publicclassBinderInternal{

……



publicstaticfinalnativeIBindergetContextObject();

……


这里可以看到BinderInternal类的getContextObject方法的代码,惊奇的发现是Native代码,这不就是Java的本地接口嘛!这下好了,它通过调用JNI层的某个文件的代码(而且是C++的代码),来和底层的C++/C实现挂钩。至于它怎么和JNI层的的函数对应的调用的,我相信你早已心知肚明了,这里不做介绍。
BinderInternal类中的本地接口的JNI实现文件,就是android_util_binder.cpp文件,getContextObject方法在该文件中对应的函数是android_os_BinderInternal_getContextObject函数,代码如下:
Framework\base\core\jni\android_util_binder.cpp
staticjobjectandroid_os_BinderInternal_getContextObject(JNIEnv*env,jobjectclazz)

{

spb=ProcessState::self()->getContextObject(NULL);

returnjavaObjectForIBinder(env,b);

}

还记得这个ProcessState对象吗?就是那个管理整个进程的服务代理对象的那个玩意,一个进程只能有一个该类对象的。既然它管理服务代理对象,那这个服务代理对象创建也应该跟她有关系了,事实上,从前文的分析已经看出来的却是这样。虽然前文已经有所述,这里再加强下记忆吧,我们再去查看ProcessState对象的getContextObject方法,代码如下:
spProcessState::getContextObject(constsp&caller)

{

if(supportsProcesses()){

returngetStrongProxyForHandle(0);

}else{

returngetContextObject(String16("default"),caller);

}


就是这里,我们看到在当前进程的ProcessState对象,其实是调用getStrongProxyForHandle方法,来创建binder句柄为0的服务代理对象——BpBinder对象的,我们知道ServiceManager的binder句柄就是这个个闻名句柄0。
哦,这里不又是回到前文的内容里了嘛!再说一边就没有意思了,如果忘记了,可以回头看看,呵呵,还是要“经常回头看看自己走过的路。”
我们可以看出Java调用C/C++,创建一个服务代理对象BpBinder,在查看BpBinder的定义我们发现继承自IBinder接口,然后在android_util_binder.cpp中的方法android_os_BinderInternal_getContextObject中,把C/C++层面的IBinder对象封装成Java层面的IBinder对象。
至此我们已经清楚BinderInternal.getContextObject(),返回的是ServiceManager的服务代理对象——BpBinder对象。那么ServiceManagerNative类的静态方法asInterface做什么用呢?这个貌似和我们前面讲过的内容不太一样。还记得在C/C++层面的获取服务代理的流程吧,在创建了一个BpBinder代理对象后,是不是通过一个类型转换函数将这个代理对象转换成了IserviceManager对象(当然,这里是C++类的对象),我们还重点分析了那个转换函数,其实你知道的,那是个宏定义:
gDefaultServiceManager=interface_cast(ProcessState::self()->getContextObject(NULL));//创建代理对象

就是这段代码,既然也走到了这里,他们的参数一样,唯一不同的就是这个主体函数喽!那么我们Java层面的这段代码:
sServiceManager=ServiceManagerNative.asInterface(BinderInternal.getContextObject());

是不是也实现了一个同样转换呢?答案是肯定的,那就来看看这个asInterface()是做了什么。我们还是通过代码来分析,在ServiceManagerNative.java中,asInterface的代码如下:
staticpublicIServiceManagerasInterface(IBinderobj)

{

if(obj==null){

returnnull;

}

IServiceManagerin=(IServiceManager)obj.queryLocalInterface(descriptor);

if(in!=null){

returnin;

}


returnnewServiceManagerProxy(obj);//如果没有查询到,创建一个本地服务代理对象

}

如果本地服务代理对象没有创建过,就新创建一个服务代理ServiceManangerPorxy的对象。这个服务代理对象实现了IServiceMananger的接口,ServiceManangerPorxy的构造函数如下:
publicServiceManagerProxy(IBinderremote){

mRemote=remote;

}//底层传来的IBinder对象赋给自己的成员变量,以备后用


再来看看ServiceManager中的那个转换函数:
sServiceManager=ServiceManagerNative.asInterface(BinderInternal.getContextObject());

这样sServiceMananger就指向一个ServiceManagerProxy的对象,Java程序的客户端就获得了一个服务管家的服务代理对象,通过这个代理对象可以向服务管家查询想要的服务。下面就简单举个例子,假如此时Java客户端想要和一个XXX的服务进程通讯,那么它首先通过代理对象发送一个获取服务的命令给服务管家,调用流程如下:
publicIBindergetService(Stringname)throwsRemoteException{

Parceldata=Parcel.obtain();

Parcelreply=Parcel.obtain();

data.writeInterfaceToken(IServiceManager.descriptor);

data.writeString(name);

mRemote.transact(GET_SERVICE_TRANSACTION,data,reply,0);

IBinderbinder=reply.readStrongBinder();

reply.recycle();

data.recycle();

returnbinder;

}

mRemote就是那个Bpbinder对象,在ServiceManagerProxy的构造函数中的初始化了这个变量。然后就是调用它的transact()函数,后面的内容不做介绍,不然背离了我们这篇文章的主题。总之,我们获得了服务代理对象,通过这个代理对象就可以和服务端通讯了。
下面将以Camera模块为例,分析binder机制在android中的实例应用。


(二)Camera模块binder机制分析


(1)服务端的启动

Binder作为android系统中的IPC通讯机制,提供了一个轻量级的IPC通讯服务,一般来说,binder用于客户服务器模式,就是说使用binder机制通讯的两个进程,一个作为服务器端,另一个作为客户端,当然,可能这两个进程互为客户服务器端。

Camera模块属于Android系统中的多媒体的一部分,它的服务器端是在Main_mediaserver.cpp中被实例化的,在我们的一文中,详细分析了这个文件的整个代码流程,这里就不做详细介绍,只是把调用流程简单列出来。
intmain(intargc,char**argv)

{

spproc(ProcessState::self());

spsm=defaultServiceManager();

LOGI("ServiceManager:%p",sm.get());

AudioFlinger::instantiate();

MediaPlayerService::instantiate();

CameraService::instantiate();

AudioPolicyService::instantiate();

ProcessState::self()->startThreadPool();

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

}

首先,主进程生成了一个ProcessState对象,用来管理本进程产生的所有服务代理;再调用defaultServiceManager()函数获取服务管家的代理对象,因为后面的所有服务的实例化添加服务动作,都要通过这个服务代理对象来完成;然后就是CameraService::instantiate()函数的调用(这里只讲述CameraService的动作),它的调用流程如下:


CameraService::instantiate()—>IServiceManager::defaultServiceManager()àIServiceManager::addService()//将服务加入服务管理系统

最后调用IPCThreadState::jionThreadPool()函数使线程进入循环操作,循环读取并处理来自客户端的请求。下面我们以Camera的客户端请求CameraService服务为例,来分析binder机制的使用情况。


(2)客户服务端联系的建立

在Camera客户端与服务器端的通讯过程中,主要通过对CameraService类中的Client对象的接口的调用与底层的多媒体库通讯的,Client类是在CameraService被定义的,而且作为它的一个成员被使用,对于Client类的每一个成员函数,在Camera类中都有对应的函数接口,这些Camera的成员函数通过调用Client对象的成员函数实现的。因为他们在两个不同的进程中,那么Camera对象是怎么同Client通讯的呢?其实,Camera模块在启动后,在上层的Java代码中,会有一个连接函数的调用connect()(我们只需要知道这些就好,不做重点介绍),这个函数最终调用Camera的connect()函数,这个函数就是建立Camera对象和Client对象之间联系的桥梁。


spCamera::connect()

{

LOGV("connect");

spc=newCamera();

constsp&cs=getCameraService();

if(cs!=0){

c->mCamera=cs->connect(c);

}

if(c->mCamera!=0){

c->mCamera->asBinder()->linkToDeath(c);

c->mStatus=NO_ERROR;

}else{

c.clear();

}

returnc;

}

首先创建一个Camera对象,看看Camera的构造函数,以防遗漏什么重要的信息:
Camera::Camera()

{

init();

}


voidCamera::init()

{

mStatus=UNKNOWN_ERROR;

}

就这么简单,几乎什么都没做。然后调用了一个重要的函数getCameraService(),这个函数究竟做了什么?来看看吧!
constsp&Camera::getCameraService()

{

Mutex::Autolock_l(mLock);

if(mCameraService.get()==0){

spsm=defaultServiceManager();//获取服务管家代理,//这在前面已经详细介绍过

spbinder;

do{

binder=sm->getService(String16("media.camera"));//通过描述符调用获取CameraService服务的代理对象,这个前面也已经详细介绍过了,可以回头看看

if(binder!=0)

break;

LOGW("CameraServicenotpublished,waiting...");

usleep(500000);//0.5s

}while(true);

if(mDeathNotifier==NULL){

mDeathNotifier=newDeathNotifier();//创建死亡通知对象,就是当该代理//对象消亡时,用来做进一步处理的东西

}

binder->linkToDeath(mDeathNotifier);//将这个通知对象绑定到特定的代理对象

mCameraService=interface_cast(binder);//哦,这个很熟悉//了,就是将BpBinder对象转换成BpCameraService类型,再赋值给其父类指针,多态的//使用

}

LOGE_IF(mCameraService==0,"noCameraService!?");

returnmCameraService;

}

这样Camera就获取了CameraService的一个代理对象,然后调用代理对象的连接函数:
if(cs!=0){

c->mCamera=cs->connect(c);

}

最后调用CameraService::connect()函数,进而获得Client的对象,并将这个返回的对象赋给自己的成员变量,这样就和Client对象建立联系,下面是CameraService的connect()函数:
spCameraService::connect(constsp&cameraClient)

{

……

……

//createanewClientobject

client=newClient(this,cameraClient,callingPid);//创建Client对象

mClient=client;//初始化CameraService的成员变量

#ifDEBUG_CLIENT_REFERENCES

//Enabletrackingforthisobject,andtrackincrementsanddecrementsof

//therefcount.

client->trackMe(true,true);

#endif

LOGV("CameraService::connectX");

returnclient;

}

最后返回了Client对象,这样在Camera的客户端就有了和服务端Client对象通讯的条件了,通讯应该是双向的,来看看Client的构造函数的这部分重要内容:

mCameraService=cameraService;//这是建立Client和CameraService的联系


mCameraClient=cameraClient;//这是建立Camera与Client的联系,因为在Camera模块的//通讯中下层实现也会调用上层,这样才是双向通讯嘛,所以这里存放以备后用
调用关系就是这么建立的,可是上面的代码中,我们没有看见binder在这个应用中起的作用啊!我调用了CameraService代理对象的connect()函数,怎么就能直接找到CameraService的connect()函数了呢?这就是binder机制在android中的伟大作用,下面就来看看,服务代理对象函数是怎么样和服务对象中的对应函数产生调用关系的。
为方便理解,在介绍binder机制中函数调用流程(其实就是binder机制中数据传输)之前,我们要先了解一下CameraService的由来。


(3)CameraService之由来

在前面文章中已经详细介绍过,在android中使用binder机制时,你首先要做出一个基本的binder通讯的框架。这个框架我们会在下一篇文章中单独介绍,这里还是从这个CameraService的产生过程来了解一下这个框架。
1)ICameraService
这是一个IIterface的继承类,其实Binder机制中的每一个IXXX类都是继承了这个IIterface类的,然后这里面定义了一个connect()虚拟函数(纯虚函数偶)。
Framework\base\include\camera\ICameraService.cpp
classICameraService:publicIInterface

{

public:

enum{

CONNECT=IBinder::FIRST_CALL_TRANSACTION,

};


public:

DECLARE_META_INTERFACE(CameraService);


virtualspconnect(constsp&cameraClient)=0;

};

这个纯虚函数在BpCameraService中被实现,所以你可以把这个类看成一个统一接口类,它本来就是一个抽象类嘛。
2)BpCameraService
classBpCameraService:publicBpInterface

//这表明同时继承了BpInterface和ICameraService两个类

{

public:

BpCameraService(constsp&impl)//这里用服务代理对象BpBinder作为参

//数,这个是一定的需要的

:BpInterface(impl)

{

}


//connecttocameraservice

virtualspconnect(constsp&cameraClient)

{

Parceldata,reply;

data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());

data.writeStrongBinder(cameraClient->asBinder());

remote()->transact(BnCameraService::CONNECT,data,&reply);

returninterface_cast(reply.readStrongBinder());

}

};

还记得客户端获取服务代理对象的过程不?在ProcessState::getContextObject()中调用了getStrongProxyForHandle()创建了一个代理对象BpBinder之后,被作为参数传递给了一个转换函数,最终转换成BpXXX然后赋给了一个IXXX指针。呵呵,也许你已经发觉了,BpCameraSerivce不就是这个BpXXX嘛,没错,这就是上层封装的服务代理对象(为了方便用户使用)。
3)BnCameraService
Framework\base\include\camera\ICameraService.cpp
classBnCameraClient:publicBnInterface//相当于同时继承了BBinder和

//ICameraService两个类

{

public:

virtualstatus_tonTransact(uint32_tcode,

constParcel&data,

Parcel*reply,

uint32_tflags=0);

};

这里只定义了一个onTransact()函数,它也在ICameraService.cpp文件中被实现:
status_tBnCameraService::onTransact(

uint32_tcode,constParcel&data,Parcel*reply,uint32_tflags)

{

switch(code){

caseCONNECT:{

CHECK_INTERFACE(ICameraService,data,reply);

spcameraClient=interface_cast(data.readStrongBinder());

spcamera=connect(cameraClient);

reply->writeStrongBinder(camera->asBinder());

returnNO_ERROR;

}break;

default:

returnBBinder::onTransact(code,data,reply,flags);

}

}

至于这个BnCameraService有什么作用,后面我们在进行说明,这里只告诉你它用来接收数据,并根据数据类型调用相应的下层实现函数。
那么现在该轮到CameraService上场了,来看看它的定义部分:
classCameraService:publicBnCameraService//继承了上面的那个BnXXX类

{

classClient;


public:

staticvoidinstantiate();


//ICameraServiceinterface

virtualspconnect(constsp&cameraClient);

//一个connect()函数的声明,在对应的.cpp文件中有具体定义,就是这个连接函数被最后调用的,没错它就是和BpCameraService里的函数一一对应的

……

……

classClient:publicBnCamera{//与Camera类中的函数一一对应,作为Camera的客

//户端的服务,至于为什么叫Client,大概就是服务端里提供的对应Camera请求的服务部

//分意思吧


public:

virtualvoiddisconnect();


//connectnewclientwithexistingcameraremote

virtualstatus_tconnect(constsp&client);

……

……

};

};

到了这里,已经可以清楚的看出:CameraService就是BnCameraService的本地实现,在BnCameraService里面调用的函数,就是在CameraService里面被实现的,而BnCameraService只是一个消息处理的封装罢了。


(四)binder机制的数据传输流程

那么现在我们就可以回到前面的那个问题——-函数调用时怎样通过服务代理到达服务端的。
从代理对象调用Connect()函数出发,在这个connect()函数中能看到什么:
virtualspconnect(constsp&cameraClient)

{

Parceldata,reply;

data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());

data.writeStrongBinder(cameraClient->asBinder());

remote()->transact(BnCameraService::CONNECT,data,&reply);

//remote()返回传递给BpCameraService的那个代理Bpbinder对象,然后调用了

//这个代理对象的transact()函数

returninterface_cast(reply.readStrongBinder());

}

下面是BpBinder的transact()函数:
status_tBpBinder::transact(

uint32_tcode,constParcel&data,Parcel*reply,uint32_tflags)

{

//Onceabinderhasdied,itwillnevercomebacktolife.

if(mAlive){

status_tstatus=IPCThreadState::self()->transact(

mHandle,code,data,reply,flags);//哦,原来调用了它呀

if(status==DEAD_OBJECT)mAlive=0;

returnstatus;

}


returnDEAD_OBJECT;

}


在binder机制中,IPCThreadState是一个传输数据操作的封装类,binder中的所有上层数据通过IPCThreadState与binder驱动打交道,所以IPCThreadState就相当于一个搬运工的角色,看看他干了什么:

status_tIPCThreadState::transact(int32_thandle,

uint32_tcode,constParcel&data,

Parcel*reply,uint32_tflags)

{

……

……

if(err==NO_ERROR){

LOG_ONEWAY(">>>>SENDfrompid%duid%d%s",getpid(),getuid(),

(flags&TF_ONE_WAY)==0?"READREPLY":"ONEWAY");

//发送数据

err=writeTransactionData(BC_TRANSACTION,flags,handle,code,data,NULL);

}


……


if((flags&TF_ONE_WAY)==0){

if(reply){

err=waitForResponse(reply);

}else{

ParcelfakeReply;

err=waitForResponse(&fakeReply);

}

}else{

err=waitForResponse(NULL,NULL);

}


returnerr;

}

看看writeTransactionData()函数:
status_tIPCThreadState::writeTransactionData(int32_tcmd,uint32_tbinderFlags,

int32_thandle,uint32_tcode,constParcel&data,status_t*statusBuffer)

{

binder_transaction_datatr;


tr.target.handle=handle;

tr.code=code;

tr.flags=binderFlags;

//封装数据成binder_transaction_data类型

conststatus_terr=data.errorCheck();

if(err==NO_ERROR){

tr.data_size=data.ipcDataSize();

tr.data.ptr.buffer=data.ipcData();

tr.offsets_size=data.ipcObjectsCount()*sizeof(size_t);

tr.data.ptr.offsets=data.ipcObjects();

}elseif(statusBuffer){

tr.flags|=TF_STATUS_CODE;

*statusBuffer=err;

tr.data_size=sizeof(status_t);

tr.data.ptr.buffer=statusBuffer;

tr.offsets_size=0;

tr.data.ptr.offsets=NULL;

}else{

return(mLastError=err);

}

//将数据写入mOut,但是这里没有和驱动设备的通讯,那肯定不是这个函数的写操作

mOut.writeInt32(cmd);

mOut.write(&tr,sizeof(tr));


returnNO_ERROR;

}

那就看看那个waitForResponse()函数:
status_tIPCThreadState::waitForResponse(Parcel*reply,status_t*acquireResult)

{

int32_tcmd;

int32_terr;


while(1){

//这个函数看着就像是和驱动打交道的,呵呵,没错就是它

if((err=talkWithDriver())<NO_ERROR)break;

……

cmd=mIn.readInt32();//从mIn中读取命令


switch(cmd){//处理命令

caseBR_TRANSACTION_COMPLETE:

if(!reply&&!acquireResult)gotofinish;

break;


caseBR_DEAD_REPLY:

err=DEAD_OBJECT;

gotofinish;

……

default:

err=executeCommand(cmd);

……

}

那就来看看talkWithDriver()函数,看他怎么和驱动聊天的:
status_tIPCThreadState::talkWithDriver(booldoReceive)

{

LOG_ASSERT(mProcess->mDriverFD>=0,"Binderdriverisnotopened");


binder_write_readbwr;

……

//将bwr初始化后仍给驱动,并从驱动中带回消息,这个mDriverFD就是那个processState

//打开的binder设备文件描述符,这里可是会阻塞等待消息返回的

if(ioctl(mProcess->mDriverFD,BINDER_WRITE_READ,&bwr)>=0)

err=NO_ERROR;

……

if(err>=NO_ERROR){

if(bwr.write_consumed>0){

if(bwr.write_consumed<(ssize_t)mOut.dataSize())

mOut.remove(0,bwr.write_consumed);

else

mOut.setDataSize(0);

}

//把带回的消息数据,放到mIn里面

if(bwr.read_consumed>0){

mIn.setDataSize(bwr.read_consumed);

mIn.setDataPosition(0);

}

}

这个是和驱动交互的函数,负责发送上层数据给binder设备文件,并等待驱动的回应带回驱动传给上层的数据。那么这些数据又是怎样被处理,最后到达上层的呢?似乎走到这里已经无路可走了,没看到有什么函数负得起这个责任,呵呵,当然是有的,回头看看waitForResponse()函数的最后,就是它了executeCommand(cmd)函数:
status_tIPCThreadState::executeCommand(int32_tcmd)//这个函数代码很丰富,只列出重点部分

{

BBinder*obj;

RefBase::weakref_type*refs;

status_tresult=NO_ERROR;

……

switch(cmd){

caseBR_ERROR:

result=mIn.readInt32();

break;

……

caseBR_TRANSACTION:

{

binder_transaction_datatr;

result=mIn.read(&tr,sizeof(tr));//将mIn的内容读入tr

……

If(tr.target.ptr){

spb((BBinder*)tr.cookie);//根据cookie字段获取BBinder对

//象,实际上这是一个类型转换,tr.cookie(这里已经是空指针了)是BnCameraService对

//象的首地址

conststatus_terror=b->transact(tr.code,buffer,&reply,0);//调用

//BBinder对象的函数

if(error<NO_ERROR)reply.setError(error);


}else{

conststatus_terror=the_context_object->transact(tr.code,buffer,&reply,0);

if(error<NO_ERROR)reply.setError(error)

}

……

}

……

}

我们知道BBinder继承自IBinder类,并实现了的transact()函数,函数定义(注意BBinder在Binder.cpp文件中定义):
status_tBBinder::transact(

uint32_tcode,constParcel&data,Parcel*reply,uint32_tflags)

{

data.setDataPosition(0);


status_terr=NO_ERROR;

switch(code){

casePING_TRANSACTION:

reply->writeInt32(pingBinder());

break;

default:

err=onTransact(code,data,reply,flags);//这个函数实际调用了谁?看看BnCameraService类的定义吧!

break;

}


if(reply!=NULL){

reply->setDataPosition(0);

}


returnerr;

}

前面已经说过,BnCameraService继承了ICameraService和BBinder类,这里的onTransact()函数调用的就是BnCameraService的那个成员函数:
status_tBnCameraService::onTransact(

uint32_tcode,constParcel&data,Parcel*reply,uint32_tflags)

{

switch(code){

caseCONNECT:{

CHECK_INTERFACE(ICameraService,data,reply);

spcameraClient=interface_cast(data.readStrongBinder());//这里的参数是从驱动传入的

spcamera=connect(cameraClient);

//调用了CameraService::connect()函数

reply->writeStrongBinder(camera->asBinder());

returnNO_ERROR;

}break;

default:

returnBBinder::onTransact(code,data,reply,flags);

}

}

然后就是调用了前文介绍过的CameraService::connect()函数,这里不再赘述。代码走到这里,binder的数据传输的整个过程总算说完了,当然,我只是对这个流程进行了叙述,其中牵涉的很多数据的封装和解析,偶都没有做多少介绍,那也不是我们这篇文章的重点,如果感兴趣,可以参考源码。
在Camera通过CameraService和Client建立联系后,Camera就可以直接调用Client的函数来实现自己的功能了,对于Camera来说,就像自己带着参数进入服务器端线程运行,并带回结果,这就是Binder机制的特点——线程迁移。这些调用都是与binder分不开的,而且流程都是一样的。


(五)总结

本文介绍了两个重要的内容,一是binder机制在Java层的代码实现;二是以Camera模块为例介绍了Camera客户端与服务器端连接的建立和数据传输过程。后面会有一篇关于使用binder机制在创建实例的过程中,应注意的问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: