android之binder学习攻克

Binder C++ 库概述

2018-06-28  本文已影响0人  ColdWave

Binder Demo

./common/IFregService.h
./common/IFregService.cpp

./server/FregServer.cpp
./server/Android.mk

./client/FregClient.cpp
./client/Android.mk

IFregService.h

#ifndef MEGA_IFREG_SERVICE_H
#define MEGA_IFREG_SERVICE_H

#include <utils/RefBase.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>

#define FREG_SERVICE "mega.ronny.FregService"

namespace android {

class IFregService : public IInterface
{
public:
    DECLARE_META_INTERFACE(FregService);

public:
    virtual int32_t getVal() = 0;
    virtual void setVal(int32_t val) = 0;
};

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

}; // namespace android

#endif // MEGA_IFREG_SERVICE_H

IFregService.cpp

//#define LOG_NDEBUG 0
#define LOG_TAG "IFregService"
#include <utils/Log.h>

#include "IFregService.h"

namespace android {

enum {
    GET_VAL = IBinder::FIRST_CALL_TRANSACTION,
    SET_VAL
};

class BpFregService : public BpInterface<IFregService>
{
public:
    BpFregService(const sp<IBinder>& impl)
        : BpInterface<IFregService>(impl)
    {
    }

    int32_t getVal()
    {
        Parcel data;
        data.writeInterfaceToken(IFregService::getInterfaceDescriptor());

        Parcel reply;
        remote()->transact(GET_VAL, data, &reply);

        int32_t val = reply.readInt32();

        return val;
    }

    void setVal(int32_t val)
    {
        Parcel data;
        data.writeInterfaceToken(IFregService::getInterfaceDescriptor());
        data.writeInt32(val);

        Parcel reply;
        remote()->transact(SET_VAL, data, &reply);
    }

};

IMPLEMENT_META_INTERFACE(FregService, "mega.ronny.IFregService");

status_t BnFregService::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    switch (code) {
    case GET_VAL: {
        CHECK_INTERFACE(IFregService, data, reply);
        int32_t val = getVal();
        reply->writeInt32(val);
        return NO_ERROR;
    } break;
    case SET_VAL: {
        CHECK_INTERFACE(IFregService, data, reply);
        int32_t val = data.readInt32();
        setVal(val);
        return NO_ERROR;
    } break;
    default:
        return BBinder::onTransact(code, data, reply, flags);
    }
}

}; // namespace android

FregServer.cpp

//#define LOG_NDEBUG 0
#define LOG_TAG "FregServer"
#include <utils/Log.h>

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

#include "../common/IFregService.h"

namespace android {

class FregService : public BnFregService
{
public:
    FregService()
        : mVal(99)
    {
        printf(" %s X ", __func__);
    }

    virtual ~FregService()
    {
        printf(" %s X ", __func__);
    }

    static void instantiate()
    {
        defaultServiceManager()->addService(String16(FREG_SERVICE), new FregService());
    }

    int32_t getVal()
    {
        return mVal;
    }

    void setVal(int32_t val)
    {
        mVal = val;
    }

private:
    int32_t mVal;
};

}; // namespace android

using namespace android;

int main(int argc __unused, char** argv __unused)
{
    FregService::instantiate();

    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();

    return 0;
}

// Android.mk

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_SRC_FILES := \
    ../common/IFregService.cpp \
    FregServer.cpp

LOCAL_SHARED_LIBRARIES := \
    liblog \
    libbinder \
    libutils \
    libcutils

LOCAL_MODULE := FregServer

include $(BUILD_EXECUTABLE)

FregClient.cpp

//#define LOG_NDEBUG 0
#define LOG_TAG "FregClient"
#include <utils/Log.h>

#include <utils/Log.h>
#include <utils/RefBase.h>
#include <binder/IServiceManager.h>

#include "../common/IFregService.h"

using namespace android;

int main()
{
    sp<IBinder> binder = defaultServiceManager()->getService(String16(FREG_SERVICE));
    if (binder == NULL) {
        printf("%s: Failed to get freg service: %s.\n", __func__, FREG_SERVICE);
        return -1;
    }

    sp<IFregService> service = IFregService::asInterface(binder);
    if (service == NULL) {
        ALOGE("Failed to get freg service interface.");
        return -1;
    }

    printf("Read original value from FregService:\n");

    int32_t val = service->getVal();
    printf(" %d .\n", val);

    printf("Add value 1 to FregService.");

    val +=1 ;

    service->setVal(val);

    printf("Read the value from FregService anain:\n");

    val = service->getVal();

    printf(" %d .\n", val);

    return 0;
}

Android.mk

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_SRC_FILES := \
    ../common/IFregService.cpp \
    FregClient.cpp

LOCAL_SHARED_LIBRARIES := \
    liblog \
    libbinder \
    libutils \
    libcutils

LOCAL_MODULE := FregClient

include $(BUILD_EXECUTABLE)

"关系"

从 Demo 就能看出了 Binder 代码的套路. 从这种继承关系就能看出,哪些工作是 User 做的,哪些工作是 Binder Library 做的.

                                 RefBase
                                    |
           ------------------------------------------------
           |                        |                     |
        BpRefBase              IInterface              IBinder
           |                        |                     |
           |                        |             ------------------
           |                        |             |                |
           |                        |           BBinder           BpBinder
           |                        |             |
           |                        |             |
           |                   IxxxService        |
           |                      |   |           |
           -----------------------    -------------
                      |                    |
                 BpInterface          BnInterface
                      |                    |
                 BpxxxService         BnxxxService
上一篇 下一篇

猜你喜欢

热点阅读