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
- android binder机制,注册系统服务---native客户端
- android binder机制,注册系统服务---客户端Binder驱动
- android binder机制,注册系统服务--服务端servicemanager binder驱动
- android binder机制,注册系统服务---服务端servicemanager
- android binder机制,注册系统服务---结果返回
- android binder机制,注册系统服务---Java层注册系统服务
- Android Binder机制的Native应用&&Android系统RPC与Binder && Android Service学习之AIDL, Parcelable和远程服务
- Android Binder机制(3) 本地服务注册过程
- Android系统的Binder机制及其native层应用
- Android Binder机制----实现自定义的系统服务
- Android Binder机制----实现自定义的系统服务
- Android Binder机制----实现自定义的系统服务
- Android Binder机制----实现自定义的系统服务
- Android系统篇之----Binder机制和远程服务调用
- Android Binder机制----实现自定义的系统服务
- Android Binder机制----实现自定义的系统服务
- Android Binder机制的Native应用
- android Binder机制3---Native层
- 操作系统(一):操作系统概述_2(***)
- python的数据分析(2)
- 线性表顺序存储结构
- HotSpot中的对象
- Android上传文件 报java.net.SocketException: sendto failed: EPIPE (Broken pipe)
- android binder机制,注册系统服务---native客户端
- NavMesh技术来改善Unity Navigation
- AM335x bootstrap探索
- HDU 2524 矩形A + B(找规律)
- Java的JAR文件入门篇
- javascript-->>去重
- 打劫房屋II
- POJ 2025 Cubic Rube 笔记
- C++:民主的产物