Android框架之Camera(3)透過Camera服務看Binder進程間通信

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框架揭祕


發佈了168 篇原創文章 · 獲贊 150 · 訪問量 56萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章