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也是一样。