1.Service的启动:
int main(int argc, char** argv) { sp <ProcessState> proc(ProcessState::self()); PartitionService::instantiate(); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); return 0; }
2.客户端的定义和实现:
namespace android { class PartitionClient: public RefBase { public: static const sp<IPartition> & getPartitionService(); //添加接口。。。 int File_Open(char * fileName); int File_Read(int fd,char * readBuf,int length); int File_Write(int fd,char * writeBuf,int length); int File_Close(int fd); private: static sp<IPartition> mPartitionService; };
namespace android { sp<IPartition> PartitionClient::mPartitionService; const sp<IPartition>& PartitionClient::getPartitionService() { if (mPartitionService.get() == 0) { sp < IServiceManager > sm = defaultServiceManager(); sp < IBinder > binder; do { binder = sm->getService(String16("Partition")); if (binder != 0) { LOGI("Partition client get\n"); break; } LOGE("Partition client is inavailable\n"); usleep(500000); } while (true); mPartitionService = interface_cast<IPartition> (binder); } LOGE("Partition client getPartitionService out.\n"); return mPartitionService; } int PartitionClient::File_Open(char *name) { sp<IPartition> ps = getPartitionService(); int ret = -1; if (ps != 0) { ret = ps->File_open(name); } return ret; }//其余方法省。。 };
3.Binder的接口定义:
namespace android { class IPartition: public IInterface { public: DECLARE_META_INTERFACE(Partition); virtual int File_Open(char * fileName)=0; virtual int File_Read(int fd,char * readBuf,int length)=0; virtual int File_Write(int fd,char * writeBuf,int length)=0; virtual int File_Close(int fd)=0; }; class BnPartition: public BnInterface<IPartition> { public: virtual status_t onTransact(uint32_t code, const Parcel& data,Parcel* reply, uint32_t flags= 0 ); }; };
4.Binder的实现:
#include "IPartition.h" namespace android { enum { FILE_OPEN = IBinder::FIRST_CALL_TRANSACTION, FILE_READ, FILE_WRITE, FILE_CLOSE, }; class BpPartition: public BpInterface<IPartition> { public: BpPartition(const sp<IBinder>& impl) : BpInterface<IPartition> (impl) { } virtual int Porting_Flash_Open(char * name) { Parcel data, reply; data.writeInterfaceToken(IPartition::getInterfaceDescriptor()); data.writeCString(name); remote()->transact(FILE_OPEN, data, &reply); return reply.readInt32(); } virtual int Porting_Flash_Read(int fd,char *readBuf,int length) { Parcel data, reply; data.writeInterfaceToken(IPartition::getInterfaceDescriptor()); data.writeInt32(fd); data.writeInt32(length); remote()->transact(FILE_READ, data, &reply); int ret = reply.readInt32(); if (ret > 0) { const char *result = (const char *)reply.readInplace(ret); memcpy((char *) readBuf, result, ret); } else { memset(readBuf, 0, length); } return ret; } virtual int Porting_Flash_Write(int fd, char *writeBuf, int length) { Parcel data, reply; data.writeInterfaceToken(IPartition::getInterfaceDescriptor()); data.writeInt32(fd); data.writeInt32(length); data.write((const char *) *writeBuf, length); remote()->transact(FILE_WRITE, data, &reply); return reply.readInt32(); } virtual int Porting_Flash_Close(int fd) { Parcel data, reply; data.writeInterfaceToken(IPartition::getInterfaceDescriptor()); data.writeInt32(fd); remote()->transact(FILE_CLOSE, data, &reply); return reply.readInt32(); } }; IMPLEMENT_META_INTERFACE(Partition, "android.os.Partition");//liusl status_t BnPartition::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch (code) { case FILE_OPEN: { CHECK_INTERFACE(IPartition, data, reply); char *pName; int ret; pName = (char *) data.readCString(); ret = File_Open(pName); reply->writeInt32(ret); return NO_ERROR; } break; case FILE_READ: { CHECK_INTERFACE(IPartition, data, reply); int fd; char *pBuf; int length; int ret; fd = data.readInt32(); length = data.readInt32(); pBuf = (char*) malloc(sizeof(char) * length); if (pBuf == NULL) { ret = -1; reply->writeInt32(ret); LOGI("onTransact File_Read malloc result failed.\n"); goto ERR_EXIT; } ret = File_Read(fd, pBuf, length); reply->writeInt32(ret); if(ret >0){ reply->write((char *) pBuf, ret); } free(pBuf); pBuf = NULL; ERR_EXIT: LOGI("onTransact File_Read ,ret =%d out\n", (int)ret); return NO_ERROR; } break; case FILE_WRITE: { CHECK_INTERFACE(IPartition, data, reply); int fd; const char *pBuf; int length; int ret; fd = data.readInt32(); length = data.readInt32(); pBuf = (const char *) data.readInplace(length); ret = File_Write(fd,(char *) pBuf, length); reply->writeInt32(ret); return NO_ERROR; } break; case FILE_CLOSE: { CHECK_INTERFACE(IPartition, data, reply); int fd; int ret; fd = data.readInt32(); ret = Porting_Flash_Close(fd); reply->writeInt32(ret); return NO_ERROR; } break; default: return BBinder::onTransact(code, data, reply, flags); } } } ;5.服务端的定义和实现;直接调用真正的实现方法。
namespace android { class PartitionService: public BnPartition { public: static void instantiate(); virtual int File_Open(char * fileName); virtual int File_Read(int fd,char * readBuf,int length); virtual int File_Write(int fd,char * writeBuf,int length); virtual int File_Close(int fd); private: Mutex mExecuteLock; }; } ;
namespace android { void PartitionService::instantiate() { sp < IServiceManager > sm = defaultServiceManager(); sm->addService(String16("Partition"), new PartitionService()); } int PartitionService::int File_Open(char * name){ Mutex::Autolock _l(mExecuteLock); IPCThreadState* ipcState = IPCThreadState::self(); signed int ret = -1; ret = File_Open_interface(name); return ret; } int PartitionService::File_Read(int fd,char *pBuf,int length) { Mutex::Autolock _l(mExecuteLock); IPCThreadState* ipcState = IPCThreadState::self(); signed int ret = -1; ret = File_Read_interface(fd, pBuf, length); return ret; } int PartitionService::File_Write(int fd, char *pBuf, int length) { Mutex::Autolock _l(mExecuteLock); IPCThreadState* ipcState = IPCThreadState::self(); signed int ret = -1; ret = File_Write_interface( fd,pBuf,length); return ret; } int PartitionService::File_Close(int fd) { Mutex::Autolock _l(mExecuteLock); IPCThreadState* ipcState = IPCThreadState::self(); long ret = -1; ret = File_Close_interface(fd); return ret; } };
6.Andorid MK的编写:
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_PRELINK_MODULE := false LOCAL_MODULE_TAGS := eng LOCAL_SRC_FILES:= \ PartitionClient.cpp \ IPartition.cpp LOCAL_SHARED_LIBRARIES := \ libutils \ libcutils \ libbinder LOCAL_MODULE := libPartitionClient include $(BUILD_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_PRELINK_MODULE := false LOCAL_MODULE_TAGS := eng LOCAL_SRC_FILES:= \ PartitionService.cpp \ 底层实现.cpp LOCAL_SHARED_LIBRARIES := \ libutils \ liblog \ libcutils \ libbinder \ libPartitionClient LOCAL_MODULE := libPartitionService include $(BUILD_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_PRELINK_MODULE := false LOCAL_MODULE_TAGS := eng LOCAL_SRC_FILES:= \ PartitionServer.cpp LOCAL_SHARED_LIBRARIES := \ libui \ libutils \ libcutils \ libbinder \ libPartitionService \ libPartitionClient LOCAL_MODULE := PartitionServer include $(BUILD_EXECUTABLE)
7.注意事项:
以上是对文件操作的一个Binder实现,很简单。但在实现过程中,第一次写C++ 代码,容易忽略namespace的使用,以及Parcel接口中对字符串的读写:
在Parcal接口,对字符串的读写分为
const char* Parcel::readCString()
const char16_t* Parcel::readString16Inplace(size_t* outLen)
若字符串中有0的情况下,readCString是会自动截取的,也就是会出现字符串丢失。write也是一样。