概述
文章仅仅用于个人的学习记录,基本上内容都是网上各个大神的杰作,此处摘录过来以自己的理解学习方式记录一下。
个人最为认可和推崇的大神文章:
http://blog.csdn.net/luoshengyang/article/details/6618363 罗升阳Binder系列文章
http://blog.csdn.net/innost/article/details/47208049 Innost的Binder讲解
https://my.oschina.net/youranhongcha/blog/149575 侯 亮的Binder系列文章.
1、native层的Parcel.
1)、writeStrongBinder(service)分析
这感觉是最最最重要的一个函数了,在Parcel中,对于理解整个Binder流程也是至关重要的。从函数的名字皆可以看出,它是要往Parcel中写
入
一个Binder的引用或者实体. 位于android/frameworks/native/libs/binder/Parcel.cpp这个文件当中.
此处的service参数按照是一个MediaPlayerService对象它继承BnInterface、BBinder两个类。
status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{
return flatten_binder(ProcessState::self(), val, this);
}
status_t flatten_binder(const sp<ProcessState>& /*proc*/, //这里
const sp<IBinder>& binder, Parcel* out)
{
flat_binder_object obj; // 描述传输过程中的Binder.flatten使光滑,打包等等.
//0x7f表示处理本Binder实体请求数据包的线程的最低优先级,
//FLAT_BINDER_FLAG_ACCEPTS_FDS表示这个Binder实体可以接受文件描述符,
//Binder实体在收到文件描述符时,就会在本进程中打开这个文件
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; Binder引用的时候flat_binder_object 中的type = BINDER_TYPE_HANDLE.
obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */
obj.handle = handle;//引用的时候为handle赋值,这个Handler就是初始化BpBinder的时候设置的.
obj.cookie = 0;
} else {
//又由于MediaPlayerService继承自BBinder类,它是一个本地Binder实体,因此binder->localBinder返回一个BBinder指针,
//就是服务端走这边.
obj.type = BINDER_TYPE_BINDER;//Binder实体的时候flat_binder_object 中的type = BINDER_TYPE_BINDER.
obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());//实体的时候为binder赋值.
//果然只有在binder实体的时候才会有值,是Binder实体地址的指针.
obj.cookie = reinterpret_cast<uintptr_t>(local);//指向这个Binder实体地址的指针local保存在flat_binder_obj的成员变量cookie中。
}
} else {
obj.type = BINDER_TYPE_BINDER;//Binder == null 的时候flat_binder_object 中的type = BINDER_TYPE_BINDER.
obj.binder = 0;
obj.cookie = 0;
}
return finish_flatten_binder(binder, obj, out);//进一步调用这个.
}
此时有个知识点就是IBinder中定义了
localBinder、
remoteBinder两个virtual的方法,但是它都自己实现了,默认都是返回null的.
BBinder* IBinder::localBinder()
{
return NULL;
}
BpBinder* IBinder::remoteBinder()
{
return NULL;
}
而在BBinder中实现了
localBinder返回this,在BBinder中实现了
remoteBinder返回this,从名字上我们也可以很轻松的记住每个函数的用意.
先是调用binder->localBinder(),注意此时的binder传入的是
MediaPlayerService它是一个BBinder对象。它的
localBinder返回的是this,(
BpBinder中没有看来是不会走到这里).
BBinder* BBinder::localBinder()
{
return this;
}
此时拿到这个BBinder对象,然后会走到else,但是我们都要分析一下:
结构体flat_binder_object进行对应的赋值,这个结构体我们在别的地方也有总结
它是用来描述一个传输中的binder对象.其中比较重要的一
个联合体,当是一个binder实体的时候binder_uintptr_t binder起作用。当
是一个binder引用的时候联合体的__u32 handle起作用,并且只
有当为binder实体的时候binder_uintptr_t cookie才起作用,那么究竟是怎
么实现的那?接下来就分析一下
struct flat_binder_object obj;
在if (!local)这个条件下:
此时是传入的这个IBinder对象是一个BpBinder对象,取出BpBinder对象的句柄handle然后obj.handle = handle。此时obj.binder = 0、
obj.cookie = 0都不起作用。还有一个很重要的赋值:obj.type = BINDER_TYPE_HANDLE.在传入的是Binder的引用也就是BpBinder对
象的时候进行的都是这些的赋值.
在else条件下:(此时是binder实体也就是BBinder对象)
和上面类似也是对一些自己想要的变量进行赋值操作:obj.type = BINDER_TYPE_BINDER、obj.binder = reinterpret_cast<uintptr_t>
(local->getWeakRefs())、obj.cookie = reinterpret_cast<uintptr_t>(local)。把
local->getWeakRefs()强制转换然后存入到
obj.binder
然后就很关键了把这个Binder实体的地址强制转换然后保存在
flat_binder_object的cookie变量当中!!(难道客户端通过这个去取?)
最后调用finish_flatten_binder(binder, obj, out)这个就是把
obj也就是我们封装好的
flat_binder_object
写入到Pracel out当中。
inline static status_t finish_flatten_binder(
const sp<IBinder>& /*binder*/, const flat_binder_object& flat, Parcel* out)
{
return out->writeObject(flat, false);//将这个flat_binder_obj写入到Parcel中去.
}
接下来就是writeObject()了,把flat_binder_obj写到Parcel里面之内,还要记录这个flat_binder_obj在Parcel里面的偏移位置.
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;
// Need to write meta-data?
if (nullMetaData || val.binder != 0) {//如果有binder对象
mObjects[mObjectsSize] = mDataPos;//记录这个flat_binder_obj在Parcel里面的偏移位置,(mDataPos前面普通数据存入的量,)
//,如果进程间传输的数据间带有Binder对象的时候,Binder驱动程序需要作进一步的处理,以维护各个Binder实体的一致性,
acquire_object(ProcessState::self(), val, this);
mObjectsSize++;
}
// remember if it's a file descriptor
if (val.type == BINDER_TYPE_FD) {
if (!mAllowFds) {
return FDS_NOT_ALLOWED;
}
mHasFds = mFdsKnown = true;
}
return finishWrite(sizeof(flat_binder_object));//完成最终处理.
}
if (!enoughData) {
//......空间不足时候的一些处理
}
if (!enoughObjects) {
//......空间不足时候的一些处理
}
goto restart_write;
}
最后
以上就是开朗红牛为你收集整理的Android5.0中Binder机制相关的native层的Parcel分析的全部内容,希望文章能够帮你解决Android5.0中Binder机制相关的native层的Parcel分析所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复