본문 바로가기

개발관련/안드로이드

[ Android ] native service 제작하기

1. native service interface 생성
/frameworks/base/libs/hellonative/IHelloNativeService.cpp

#include <hellonative/IHelloNativeService.h>

namespace android {

enum {
    HW_HELLONATIVE = IBinder::FIRST_CALL_TRANSACTION,
};

IMPLEMENT_META_INTERFACE(HelloNativeService,
     "android.apps.IHelloNativeService");

// proxy code

// stub code

}; // namespace android

/frameworks/base/include/hellonative/IHelloNativeService.h

#include <binder/IInterface.h>
#include <binder/Parcel.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>

namespace android {
class IHelloNativeService : public IInterface {
    public:
    DECLARE_META_INTERFACE(HelloNativeService);
    virtual status_t print(const char *str)=0;

// proxy code

// stub code

};

2. make-file 생성
/frameworks/base/libs/hellonative/Android.mk

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

LOCAL_SRC_FILES:= \
    IHelloNativeService.cpp \
    HelloNativeService.cpp

LOCAL_SHARED_LIBRARIES := \
    libcutils \
    libutils \
    libbinder \

LOCAL_PRELINK_MODULE := false

LOCAL_MODULE:=libhellonative

include $(BUILD_SHARED_LIBRARY)

3. service proxy, stub 생성
/frameworks/base/libs/hellonative/IHelloNativeService.cpp

BpHelloNativeService::BpHelloNativeService (const sp<IBinder>& impl)
    : BpInterface<IHelloNativeService>(impl)
{}

status_t BpHelloNativeService::print(const char *str) {
    Parcel data, reply;
    data.writeInterfaceToken(
        IHelloNativeService::getInterfaceDescriptor());
    data.writeCString(str);
    status_t status = remote()->transact(HW_HELLONATIVE, data, &reply);
    if (status != NO_ERROR) {
    } else {
        status = reply.readInt32();
    }
}

status_t BnHelloNativeService::ontransact(uint32_t code,
    const Parcel &data,
    Parcel *reply,
    uint32_t flags)
{
    switch(code) {
    case HW_HELLONATIVE: {
        CHECK_INTERFACE(IHelloNativeService, data, reply);
        const char *str;
        str = data.readCString();
        reply->writeInt32(print(str));
        return NO_ERROR;
    } break;
    default:
        return BBinder::onTransact(code, data, reply, flags);
    }
}

/frameworks/base/include/hellonative/IHelloNativeService.h


class BpHelloNativeService: public BpInterface<IHelloNativeService>
{
public:
    BpHelloNativeService (const sp<IBinder>& impl);
    virtual status_t hellonative(const char *str);
};

class BnHelloNativeService: public BnInterface<IHelloNativeService>
{
    public:
    virtual status_t onTransact( uint32_t code,
        const Parcel& data,
        Parcel* reply,
        uint32_t flags = 0);
}

4. service class 생성
/frameworks/base/libs/hellonative/HelloNativeService.cpp

#include <hellonative/HelloNativeService.h>

namespace android {

HelloNativeService::HelloNativeService() {};

HelloNativeService::~HelloNativeService() {};

void HelloNativeService::instantiate() {
    defaultServiceManager()->addService(
        String16("android.apps.IHelloNativeService"), new HelloNativeService());

status_t HelloNativeService::print(const char* str) {
    return NO_ERROR;
}

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

}; // namespace android

/frameworks/base/include/hellonative/HelloNativeService.h

#include <hellonative/IHelloNativeService.h>

namespace android {

class HelloNativeService : public BnHelloNativeService
{
public:
    static void instantiate();
    virtual status_t print(const char *str);
    virtual status_t onTransact(
        uint32_t code,
        const Parcel& data,
        Parcel* reply,
        uint32_t flags);
private:
    HelloNativeService();
    virtual ~HelloNativeService();
};

};  // namespace android

5. 서비스 서버 생성
/frameworks/base/hellonative/main_hellonativeservice.cpp

#include <binder/ProcessState.h>
#include <hellonative/HelloNativeService.h>

using namespace android;

int main(int argc, char *argv[])
{
    HelloNativeService::instantiate();
    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();
    return 0;
}

/*
    위와 같이 할 경우 서버를 따로 실행 시켜 줘야 함

    시작하면서 바로 실행되게 할 경우 init 루틴에 추가하거나, 별도의 작업이 필요함

    테스트 할 경우 그냥 main_mediaserver.cpp 에

    HelloNativeService::instantiate();  추가해주면 됨
*/

6. 서비스 클라이언트 생성
/frameworks/base/hellonative/main_hellonativeclient.cpp

#include <binder/IServiceManager.h>
#include <utils/RefBase.h>
#include <hellonative/IHelloNativeService.h>

using namespace android;

int main(int argc, char *argv[])
{
    sp<IServiceManager> sm = defaultServiceManager();
    sp<IBinder> b;
    sp<IHelloNativeServic> sHelloNativeService;

    do {
        b = sm->getService(String16("android.apps.IHelloNativeService"));
        if (b != 0)
            break;
        usleep(500000);
    } while(true);

    sHelloNativeService = interface_cast<IHelloNativeService>(b);
    sHelloNativeService->print("Hello NativeService!");

    return 0;
}

7. make-file 생성
/frameworks/base/hellonative/Android.mk

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

LOCAL_SRC_FILES:= \
    main_hellonativeservice.cpp

LOCAL_SHARED_LIBRARIES:=\
    libutils \
    libbinder \
    libhellonative

base := $(LOCAL_PATH)/..

LOCAL_MODULE:=hellonativeservice

include $(BUILD_EXECUTABLE)

include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \
    main_hellonativeclient.cpp

LOCAL_SHARED_LIBRARIES:= \
    libutils \
    libbinder \
    libhellonative

base := $(LOCAL_PATH)/..

LOCAL_MODULE:= hellonativeclient

include $(BUILD_EXECUTABLE)

======================================================================

테스트 방법

$ adb shell
# cd system
cd system
# cd bin
cd bin
# ./hellonativeservice &
./hellonativeservice &
# ./hellonativeclient &
./hellonativeclient &
Hello NativeService!