Android框架之Camera(3)透过Camera服务看Binder进程间通信

来源:互联网 发布:杨千嬅歌曲评价知乎 编辑:程序博客网 时间:2024/06/06 11:37

Android 6.0
Android Binder用来管理Android进程,用途有两个:

1、IPC(Inter Process Communication)工具,用于进程间通信。

2、RPC(Remote Procedure Call)远程函数调用,使得当前进程调用另一个进程的函数就像调用自身的函数一样。当然,她也属于IPC范畴。

关于Binder的历史、驱动实现、在Android中的框架实现等内容,参考结尾列出的极好的资料;这里通过Camera服务的实现、使用,熟悉一个本地服务(C服务)的创建。


一个Binder服务大体来说由3个角色构成:

1、服务接口

2、服务实现

3、服务代理

以Camera服务为例,她们之间关系如下图:



Camera服务接口

服务接口声明某个服务需要实现的功能函数,这里只负责声明,然后在服务和代理中实现。比如上图Camera服务的getCameraInfo()函数。

static sp<IBinder>  asBinder(const IInterface*);
接口中的asBinder()函数将服务接口类型转换为IBinder类型,作用是在进行Binder IPC通信时,IBinder对象需要保存到RPC数据中传递给Binder驱动。
asInterface()函数由宏DECLARE_META_INTERFACE/IMPLEMENT_META_INTERFACE生成,用于将IBinder转化为服务接口:
android::sp<ICameraService> ICameraService::asInterface(const android::sp<android::IBinder>& obj){    android::sp<ICameraService> intr;    if (obj != NULL) {        intr = static_cast<ICameraService*>(            obj->queryLocalInterface(                    ICameraService::descriptor).get());        if (intr == NULL) {            intr = new BpCameraService(obj);        }    }    return intr;}
之前在“Android框架之Camera(1)Camera服务的前世今生”Camera服务的C/C++示例中就是通过asInterface()函数获取服务。


Camera服务
服务函数在CameraService类中实现。
CameraService继承BinderService是为了向系统中注册自己(服务),详见:“Android框架之Camera(1)Camera服务的前世今生”
CameraService继承BnCameraService为了实现Camera服务的功能。


Camera服务代理
服务代理用来传递Binder RPC需要的RPC代码/数据,这个需求在具体的服务代理类中实现。

下面通过getCameraInfo()函数的调用过程实地体验之。


1、接口ICameraService定义getCameraInfo()函数

ICameraService.h (frameworks\av\include\camera)class ICameraService : public IInterface {public:// 纯虚函数virtual status_t getCameraInfo(int cameraId, /*out*/ struct CameraInfo* cameraInfo) = 0;};

2、Camera的使用方调用getCameraInfo()函数

// 1、获取服务:private ICameraService mCameraService;IBinder cameraServiceBinder = ServiceManager.getService("media.camera");mCameraService = ICameraService.Stub.asInterface(cameraServiceBinder);// 2、调用getCameraInfo()函数:CameraInfo info = new CameraInfo();cameraService.getCameraInfo(id, /*out*/info);

3、服务代理BpCameraService复写的getCameraInfo()函数得到调用:

ICameraService.cpp (frameworks\av\camera)class BpCameraService: public BpInterface<ICameraService>{public:    BpCameraService(const sp<IBinder>& impl)        : BpInterface<ICameraService>(impl)    {    }    virtual status_t getCameraInfo(int cameraId,                                   struct CameraInfo* cameraInfo) {        Parcel data, reply;        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());        data.writeInt32(cameraId);        remote()->transact(BnCameraService::GET_CAMERA_INFO, data, &reply);        if (readExceptionCode(reply)) return -EPROTO;        status_t result = reply.readInt32();        if (reply.readInt32() != 0) {            cameraInfo->facing = reply.readInt32();            cameraInfo->orientation = reply.readInt32();        }        return result;    }}
还记得,ICameraService::asInterface(binder)操作new出来的就是BpCameraService对象。

BpCameraService继承BpInterface,用来通过remote()获取IBinder对象,然后以函数功能编号(GET_CAMERA_INFO)、数据作参数调用transact()函数。Binder通信的结果、返回数据写入reply变量。

BpCameraService继承ICameraService接口,用来把远程调用请求构成RPC数据,发起远程调用。



4、BnCameraService处理第3不的RPC请求:

ICameraService.cpp (frameworks\av\camera)status_t BnCameraService::onTransact(    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){    switch(code) {        case GET_CAMERA_INFO: {            CHECK_INTERFACE(ICameraService, data, reply);            CameraInfo cameraInfo = CameraInfo();            memset(&cameraInfo, 0, sizeof(cameraInfo));            status_t result = getCameraInfo(data.readInt32(), &cameraInfo);            reply->writeNoException();            reply->writeInt32(result);            // Fake a parcelable object here            reply->writeInt32(1); // means the parcelable is included            reply->writeInt32(cameraInfo.facing);            reply->writeInt32(cameraInfo.orientation);            return NO_ERROR;        } break;        default:            return BBinder::onTransact(code, data, reply, flags);    }}

CHECK_INTERFACE:确定请求的正确性,方法就是通过判断入参(ICameraService::getInterfaceDescriptor())是否为“android.hardware.ICameraService”来确定。

第9行,调用Camera服务实现的getCameraInfo()方法。BnCameraService的RPC处理流程:



5、Camera服务实现getCameraInfo()方法:

CameraService.h (frameworks\av\services\camera\libcameraservice)class CameraService :    public BinderService<CameraService>,    public BnCameraService,{    friend class BinderService<CameraService>;public:virtual status_t getCameraInfo(int cameraId, struct CameraInfo* cameraInfo);}CameraService.cpp (frameworks\av\services\camera\libcameraservice)status_t CameraService::getCameraInfo(int cameraId, struct CameraInfo* cameraInfo) {    struct camera_info info;// HAL的getCameraInfo()函数得到调用    status_t rc = mModule->getCameraInfo(cameraId, &info);    cameraInfo->facing = info.facing;    cameraInfo->orientation = info.orientation;    return rc;}
CameraService继承BinderService是为了项Service Manager注册自己。

CameraService继承BnCameraService:

status_t CameraService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,        uint32_t flags) {return BnCameraService::onTransact(code, data, reply, flags);}

这样,整个IPC就完成了。以自己实现的xxx服务为例,总结下流程:

Bpxxx::func()->xxx::onTransact()->Bnxxx::onTransact()->xxx::func()->返回到Bpxxx::func()

----------remote()->transact()执行------------------------------->transact()执行完


“纸上读来终觉浅,绝知此事要躬行”,下面实现自己的Binder本地服务:OurService,文件列表:



执行测试应用,log:

测试例程源码:Android Binder本地服务例程


参考资料

1、Android深入浅出之Binder机制

2、Android框架揭秘


原创粉丝点击