android binder机制,注册系统服务---native客户端

来源:互联网 发布:apache nginx 比较 编辑:程序博客网 时间:2024/06/05 04:28

前言:

前面的准备工作终于完成差不多了,长舒一口气,看下服务的注册。

1,native客户端

surfaceflinger是android系统中和图形相关的进程,由init进程通过解析init.rc文件创建,对应的文件目录

是frameworks/native/services/surfaceflinger。

init.rc启动surfaceflinger配置如下,

service surfaceflinger /system/bin/surfaceflinger    class core    user system    group graphics drmrpc    onrestart restart zygotewritepid /dev/cpuset/system-background/tasks

main_surfaceflinger.cpp的入口mian方法如下,

int main(int, char**) {    ProcessState::self()->setThreadPoolMaxThreadCount(4);//设置线程池大小    sp<ProcessState> ps(ProcessState::self());//获取ProcessState对象ps->startThreadPool();//启动线程池       //获取SurfaceFlinger对象    sp<SurfaceFlinger> flinger = DisplayUtils::getInstance()->getSFInstance();       //设置进程优先级    setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);    set_sched_policy(0, SP_FOREGROUND);    flinger->init();//SurfaceFlinger初始化    sp<IServiceManager> sm(defaultServiceManager());//获取IserviceManager对象sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);//添加服务    flinger->run();    return 0;}

本章主要论述服务的添加,因此直接看addService方法。

SurfaceFlinger.h的SurfaceFlinger定义如下,

class SurfaceFlinger : public BnSurfaceComposer,                       private IBinder::DeathRecipient,                       private HWComposer::EventHandler

SurfaceFlinger继承于Ibinder。addService方法是通过跨进程调用,运行于系统的binder进程中。

IServiceManager.cpp的内部类BpServiceManager的addService方法如下,

virtual status_t addService(const String16& name, const sp<IBinder>& service,            bool allowIsolated)    {        Parcel data, reply;        data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());        data.writeString16(name);        data.writeStrongBinder(service);        data.writeInt32(allowIsolated ? 1 : 0);        status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);        return err == NO_ERROR ? reply.readExceptionCode() : err;    }

逻辑比较简单,主要做两件事情

1,调用Parcel的writeStrongBinder方法将service对象系列化。

2,调用BpBinder的transact方法。

1.1, 系列化

writeStrongBinder调用流程图如下,


writeStrongBinder方法如下,

status_t Parcel::writeStrongBinder(const sp<IBinder>& val){    return flatten_binder(ProcessState::self(), val, this);}

flatten_binder方法如下,

status_t flatten_binder(const sp<ProcessState>& /*proc*/,    const sp<IBinder>& binder, Parcel* out){    flat_binder_object obj;    obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;    if (binder != NULL) {        IBinder *local = binder->localBinder();        if (!local) {            BpBinder *proxy = binder->remoteBinder();            if (proxy == NULL) {                ALOGE("null proxy");            }            const int32_t handle = proxy ? proxy->handle() : 0;            obj.type = BINDER_TYPE_HANDLE;            obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */            obj.handle = handle;            obj.cookie = 0;        } else {            obj.type = BINDER_TYPE_BINDER;            obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());            obj.cookie = reinterpret_cast<uintptr_t>(local);        }    } else {        obj.type = BINDER_TYPE_BINDER;        obj.binder = 0;        obj.cookie = 0;    }    return finish_flatten_binder(binder, obj, out);}

根据服务以及服务所在进程构造flat_binder_object结构,

对于Binder实体,则cookie记录Binder实体的指针;

对于Binder代理,则binder记录Binder代理的句柄。

 

finish_flatten_binder方法如下,

inline static status_t finish_flatten_binder(    const sp<IBinder>& /*binder*/, const flat_binder_object& flat, Parcel* out){    return out->writeObject(flat, false);}

直接调用writeObject方法将flat_binder_object结构写入。该方法如下,

status_t Parcel::writeObject(const flat_binder_object& val, bool nullMetaData){    const bool enoughData = (mDataPos+sizeof(val)) <= mDataCapacity;    const bool enoughObjects = mObjectsSize < mObjectsCapacity;    if (enoughData && enoughObjects) {restart_write:        *reinterpret_cast<flat_binder_object*>(mData+mDataPos) = val;        // remember if it's a file descriptor        if (val.type == BINDER_TYPE_FD) {            if (!mAllowFds) {                // fail before modifying our object index                return FDS_NOT_ALLOWED;            }            mHasFds = mFdsKnown = true;        }        // Need to write meta-data?        if (nullMetaData || val.binder != 0) {            mObjects[mObjectsSize] = mDataPos;            acquire_object(ProcessState::self(), val, this, &mOpenAshmemSize);            mObjectsSize++;        }        return finishWrite(sizeof(flat_binder_object));}•••

把flat_binder_obj写到Parcel里面之内,还要记录这个flat_binder_obj在Parcel里面的偏移位置示意图如下:


我们将会看到Binder驱动程序是怎么处理这些Binder对象的。

writeStrongBinder方法之后,注意其返回值,接着会处理data数据。

1.2, 注册服务

总体调用流程图如下,


BpBinder.cpp的transact方法如下,

status_t status = IPCThreadState::self()->transact(mHandle, code, data, reply, flags);

IPCThreadState.cpp的transact方法主要包括2个步骤,

if (err == NO_ERROR) {        LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(),            (flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY");        err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);}•••err = waitForResponse(reply);

1,调用writeTransactionData方法传输数据。

2,调用waitForResponse方法等待返回结果。

1.2.1 封装数据

writeTransactionData的部分方法如下,

binder_transaction_data tr;tr.target.ptr = 0; /* Don't pass uninitialized stack data to a remote process */    tr.target.handle = handle;//是servicemanger对应的binder实体对象    tr.code = code;//添加服务请求码, ADD_SERVICE_TRANSACTION    tr.flags = binderFlags;    tr.cookie = 0;    tr.sender_pid = 0;tr.sender_euid = 0;if (err == NO_ERROR) {        tr.data_size = data.ipcDataSize();//待传递数据        tr.data.ptr.buffer = data.ipcData();          // binder对象在数据中的具体位置        tr.offsets_size = data.ipcObjectsCount()*sizeof(binder_size_t);       
        tr.data.ptr.offsets = data.ipcObjects();•••mOut.writeInt32(cmd);mOut.write(&tr, sizeof(tr));

data对应的是所要添加的服务(surfaceflinger),将data转换为binder_transaction_data结构体。这个方法最终

将binder请求码ADD_SERVICE_TRANSACTION和包含surfaceflinger服务的binder_transaction_data结构

体写入到mOut中。

添加服务的请求码是ADD_SERVICE_TRANSACTION

writeTransactionData方法封装为BC_TRANSACTION

其中给tr.data.ptr.offsets赋值,就是记录下“待传数据”中所有binder对象的具体位置,示意图如下:


1.2.2 传输数据

waitForResponse方法首先调用talkWithDriver方法和binder设备交换数据,

if ((err=talkWithDriver()) < NO_ERROR) break;

talkWithDriver方法如下,

binder_write_read bwr;bwr.write_size = outAvail;bwr.write_buffer = (uintptr_t)mOut.data();//从mOut获取上面的传输数据if (doReceive && needRead) {        bwr.read_size = mIn.dataCapacity();//这是需要返回值        bwr.read_buffer = (uintptr_t)mIn.data();//如果从binder中读到数据,直接填在mIn中    } else {        bwr.read_size = 0;        bwr.read_buffer = 0;}do {         if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)            err = NO_ERROR;        •••

通过ioctl不停的读写操作,和binder driver进行通信。

实际上, talkWithDriver方法利用binder_write_read bwr结构体, mIn和mOut输出流和binder驱动进行交互。

mOut中的内容发出去,发送后的回复写进mIn。

Ioctl方法经过系统调用后进入binder驱动。

 

和binder驱动进行通信时,消息类型是BINDER_WRITE_READ

阅读全文
0 0
原创粉丝点击