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本地服務例程
參考資料:
2、Android框架揭祕