Android Binder實現示例(C/C++層)

瀟瀟獨行俠發表於2019-01-15

本文參考前輩文章,記錄自己學習瞭解Binder的一個過程;以一個例子來看下Binder的一個實現過程。

Java層的實現可參看另一篇文章:Android系統服務編寫例項-Binder(Java層AIDL)

一、示例

C層Binder開發的架構圖

BinderTest

├── client//客戶端目錄
│   ├── Android.mk
│   ├── BpBinderTest.cpp
│   ├── BpBinderTest.h
│   └── main_client.cpp
├── common//通用介面
│   ├── IBinderTest.cpp
│   └── IBinderTest.h
└── server//服務端目錄
    ├── Android.mk
    ├── BinderTestService.cpp
    ├── BinderTestService.h
    ├── BnBinderTest.cpp
    ├── BnBinderTest.h
    └── main_server.cpp

1、common分析

1.1 IBinderTest.h

#ifndef ANDROID_IHELLOWORLDSERVICE_H
#define ANDROID_IHELLOWORLDSERVICE_H

#include <binder/IInterface.h>

namespace android{

enum {
    HW_HELLOWORLD2=IBinder::FIRST_CALL_TRANSACTION,
};

class IBinderTest: public IInterface//繼承自IInterface,用於提供C/S的統一介面
{
public:
    DECLARE_META_INTERFACE(BinderTest);//這是一個巨集定義
    virtual status_t binderTest(const char *str)=0;//一個簡單的測試函式
};
    
};

#endif

2、Server分析

2.1 BnBinderTest.h

#include "../common/IBinderTest.h"

namespace android{

class BnBinderTest: public BnInterface<IBinderTest>//繼承BnInterface
{
public:
    //onTransact此函式在BnBinderTest.cpp中具體實現,它用於處理來自client端對應的請求
    virtual status_t onTransact(uint32_t code,const Parcel &data,Parcel *reply,uint32_t flags =0);
};
};

2.2 BnBinderTest.cpp

#include <binder/Parcel.h>
#include "BnBinderTest.h"

namespace android {
//對BnBinderTest的onTransact實現,還會在後面其子類BnBinderTestService中重寫此方法
status_t BnBinderTest::onTransact(uint32_t code,const Parcel &data,Parcel *reply,uint32_t flags)
{
    switch(code){
        case HW_HELLOWORLD2:{//在IBinderTest.h介面中定義
            CHECK_INTERFACE(IBinderTest,data,reply);//檢查介面
            const char *str;
            str = data.readCString();
            reply->writeInt32(binderTest(str));//這裡呼叫執行我們定義的binderTest函式
            return NO_ERROR;
        }break;
        default:
            return BBinder::onTransact(code,data,reply,flags);
    }
}
};

2.3 BinderTestService.h

#include<binder/Parcel.h>
#include"BnBinderTest.h"
#include<utils/Log.h>

namespace android {

class BinderTestService: public BnBinderTest//繼承
{
public:
    static void instantiate();
    virtual status_t binderTest(const char *str);//實現介面IBinderTest的函式,這些是我們自己需要實現的一些功能函式
    virtual status_t onTransact(uint32_t code,const Parcel &data,Parcel *reply,uint32_t flags = 0);

private:
    BinderTestService();
    virtual ~BinderTestService();
};
};

2.4 BinderTestService.cpp

#include<binder/IServiceManager.h>
#include<binder/IPCThreadState.h>
#include<utils/Log.h>
#include"BinderTestService.h"

namespace android{
//這個函式是將自己註冊進servicemanager
void BinderTestService::instantiate(){
    defaultServiceManager()->addService(String16("android.test.IBinderTest"),new BinderTestService);
}
//這個函式是我們要實現的功能,其在BnBinderTest的onTransact中被呼叫
status_t BinderTestService::binderTest(const char *str)
{
    ALOGI("receive string:%s\n",str);
    printf("print string:%s\n",str);//簡單的列印一個字串
    return NO_ERROR;
}

BinderTestService::BinderTestService()
{
    ALOGI("BinderTestService is created");
    printf("BinderTestService is created\n");
}
BinderTestService::~BinderTestService()
{
    ALOGI("BinderTestService is destroyed");
    printf("BinderTestService is destroyed\n");
}

status_t BinderTestService::onTransact(uint32_t code,const Parcel &data,Parcel *reply,uint32_t flags)
{
    ALOGI("BinderTestService onTransact");
    printf("BinderTestService onTransact\n");
    return BnBinderTest::onTransact(code,data,reply,flags);//呼叫父類的函式
}
};

2.5 main_server.cpp(server端的啟動程式)

#define LOG_TAG "main_server"

#include<binder/IPCThreadState.h>
#include<binder/ProcessState.h>
#include<binder/IServiceManager.h>
#include<utils/Log.h>
#include"BinderTestService.h"

using namespace android;

int main(int argc,char *argv[]){
    BinderTestService::instantiate();//註冊進servicemanager中
    //開啟執行緒池,接收處理Client傳送的程式間通訊請求
    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();
    return 0;
}

 

2.6 Android.mk

LOCAL_PATH:=$(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES:=\
	../common/IBinderTest.cpp\
	BnBinderTest.cpp\
	BinderTestService.cpp\
	main_server.cpp

LOCAL_SHARED_LIBRARIES:=\
	libcutils\
	libutils\
	libbinder

LOCAL_MODULE:= main_server

include $(BUILD_EXECUTABLE)

3、Client分析

3.1 BpBinderTest.h

#include "../common/IBinderTest.h"

namespace android{

class BpBinderTest: public BpInterface<IBinderTest>
{
public:
    BpBinderTest(const sp<IBinder>& impl);
    virtual status_t binderTest(const char *str);
};
};

3.2 BpBinderTest.cpp

#include <binder/Parcel.h>
#include "BpBinderTest.h"
#include <utils/Log.h>

namespace android{

status_t BpBinderTest::binderTest(const char *str)
{
    Parcel data,reply;
    data.writeInterfaceToken(IBinderTest::getInterfaceDescriptor());
    data.writeCString(str);
    //通過code呼叫遠端BinderTest方法,傳遞data
    status_t status = remote()->transact(HW_HELLOWORLD2,data,&reply);
    if(status != NO_ERROR){
        ALOGE("BinderTest error: %s",strerror(-status));
    }else{
        status = reply.readInt32();
    }
    return status;
}

BpBinderTest::BpBinderTest(const sp<IBinder>& impl): BpInterface<IBinderTest>(impl){}

};

3.3 main_client.cpp

#define LOG_TAG "main_helloworldclient"

#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <utils/Log.h>
#include <utils/RefBase.h>
#include "../common/IBinderTest.h"

using namespace android;

int main(int argc,char *argv[])
{
    ALOGI("HelloWorldSevice client is starting now");
    //獲取ServiceManager,從而能得到遠端IBinder,實現通訊
    sp<IServiceManager> sm =defaultServiceManager();
    sp<IBinder> b;
    sp<IBinderTest> sBinderTest;

    do{
        b=sm->getService(String16("android.test.IBinderTest"));
        if(b != 0){
            break;
        }
        ALOGI("BinderTest is not working,waiting...");
        printf("BinderTest is not working,waiting...\n");
        usleep(500000);
    }while(true);
    sBinderTest = interface_cast<IBinderTest>(b);
    sBinderTest->binderTest("Hello,World!\n");
    return 0;
}

3.4 Android.mk

LOCAL_PATH:=$(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES:=\
	../common/IBinderTest.cpp\
	BpBinderTest.cpp\
	main_client.cpp

LOCAL_SHARED_LIBRARIES:=\
	libcutils\
	libutils\
	libbinder

LOCAL_MODULE:= main_client

include $(BUILD_EXECUTABLE)

DEMO下載:https://download.csdn.net/download/qq_25269161/10918706

 

如下參考

https://www.cnblogs.com/samchen2009/p/3316001.html

歸納一下,

  1.  BBinder 實現了大部分的IBinder 介面,除了onTransact() 和 queryLocalInterface(), getInterfaceDescriptor();
  2.  BnInterface 實現了IBinder的queryLocalInterface()和getInterfaceDescriptor(), 但是其必須藉助實際的介面類。
  3.  BnMediaPlayer只是定義了onTransact(), 沒有實現。
  4.  onTransact()的具體實現在Client類。

為什麼搞得那麼複雜?Google 是希望通過這些封裝儘可能減少開發者的工作量,開發一個native的service 開發者只需要做這麼幾件事(上圖中深色部分):

  1. 定義一個介面檔案, IXXXService, 繼承IInterface
  2. 定義BnXXX(), 繼承 BnInterface<IXXXService>
  3. 實現一個XXXService類,繼承BnXXX(), 並具體實現onTransact() 函式。

Client端的實現:

  1. 使用和Server端同一個 IXXXService, 繼承IInterface
  2. 定義BpXXX(), 繼承 BpInterface<IXXXService)
  3. 實現一個XXXService類,繼承BpXXX(), 並具體實現transact() 函式。

 

Java層Binder的實現是採用了AIDL的方式。

Binder的Native和Java層對比
NativeJavaNote(Java側說明)
IBinderIBinder 
IInterfaceIInterface 
IXXXIXXXAIDL檔案介面定義
BBinderBinder通過JavaVBBinder類作為橋樑
BpBinderBinderProxy通過JNI訪問Native的實現
BnInterfaceN/A 
BpInterfaceN/A 
BnXXXStubAIDL自動生成,需使用者繼承在子類中實現真正的服務端操作
BpXXXProxyAIDL自動生成,用於Client端呼叫

 

相關文章