文章目录
问题跨进程交互流程Binder 架构图写对象数据读取数据总结
问题
1. binder 传递有哪些方式
2. binder 在传递过程中是怎样存储的
3. binder 对象序列化和反序列化的过程
4. binder 对象在传递过程中驱动做了什么
跨进程交互流程
点击跳转 Binder 跨进程交互流程
Binder 架构图
![在这里插入图片描述](https://img-blog.csdnimg.cn/c055fc94d5af4b06b4d10298f4d42ee2.png)
写对象数据
先定义一个 aidl 文件
// IMyAidlInterface.aidl
package com.example.server;
import com.example.server.ICallback;
interface IMyAidlInterface {
// ICallback 也是一个 aidl 接口
void go(ICallback callback);
}
// ICallback.aidl
package com.example.server;
interface ICallback {
void callback(int code);
}
build 后的 IMyAidlInterface 代理对象 go() 方法如下
@Override
public void go(com.example.server.ICallback callback) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeStrongBinder((((callback != null)) ? (callback.asBinder()) : (null)));
boolean _status = mRemote.transact(Stub.TRANSACTION_go, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
getDefaultImpl().go(callback);
return;
}
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
对象会用 _data.writeStrongBinder() 函数写出去,然后还是通过 mRemote.transact() 出去。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/78bd6ff2d5a749cbb86071b47476fad7.png)
首先先看 writeStrongBinder()
public final void writeStrongBinder(IBinder val) {
nativeWriteStrongBinder(mNativePtr, val);
}
调用了 nativeWriteStrongBinder() 传入了 mNativePtr 和 callback 的binder 实体对象,mNativePtr 是 Parcel 在 native 层对象的指针。 接下来看 nativeWriteStrongBinder()
frameworks/base/core/jni/android_os_Parcel.cpp 下的 android_os_Parcel_writeStrongBinder() 函数
static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
{
// 通过Parcel 指针 nativePtr 获取到 native 层的Parcel对象
Parcel* parcel = reinterpret_cast(nativePtr);
if (parcel != NULL) {
// 然后通过 java层的 binder 对象 获取到 native 层的 binder 对象,写到 native 层的parcel 对象中。
const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
if (err != NO_ERROR) {
signalExceptionForError(env, clazz, err);
}
}
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/d85cdaff046345158c677a67326949e9.png)
ibinderForJavaObject(env, object) 是如何将 java层的binder 对象 转换为 native 层的 binder 对象的?
// obj 传入的是 java 层的 bidner 对象
sp ibinderForJavaObject(JNIEnv* env, jobject obj)
{
if (obj == NULL) return NULL;
// 后面根据 obj 的类型来处理 对应的逻辑
// Instance of Binder?
// 如果传入的 java层 binder 对象是一个实体对象
if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
// 获取的是 JavaBBinderHolder ,java 层对象中存储了 native JavaBBinderHolder 的指针
JavaBBinderHolder* jbh = (JavaBBinderHolder*)
env->GetLongField(obj, gBinderOffsets.mObject);
if (jbh == nullptr) {
ALOGE("JavaBBinderHolder null on binder");
return nullptr;
}
//通过get() 从 JavaBBinderHolder 中获取到native层的 binder对象:JavaBBinder
// JavaBBinder 继承了 BBinder
return jbh->get(env, obj);
}
// Instance of BinderProxy?
// 如果是 BinderProxy 对象,则获取到 native 层保存的 Proxy 对象
if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
return getBPNativeData(env, obj)->mObject;
}
return NULL;
}
通过 java 层对象转换为 native 层的 binder 对象之后,就通过 writeStrongBinder() 把 native 层的 binder 对象写到 Parcel 里面。
status_t Parcel::writeStrongBinder(const sp& val)
{
return flattenBinder(val);
}
status_t Parcel::flattenBinder(const sp& binder) {
BBinder* local = nullptr;
if (binder) local = binder->localBinder();
flat_binder_object obj;
// 标记成 BINDER_TYPE_BINDER 代表是 binder 实体对象
obj.hdr.type = BINDER_TYPE_BINDER;
obj.binder = reinterpret_cast(local->getWeakRefs());
// local 就是当前binder对象自己
obj.cookie = reinterpret_cast(local);
return finishFlattenBinder(binder);
}
finishFlattenBinder()
status_t Parcel::finishFlattenBinder(const sp& binder)
{
internal::Stability::tryMarkCompilationUnit(binder.get());
int16_t rep = internal::Stability::getRepr(binder.get());
return writeInt32(rep);
}
finishFlattenBinder() 的作用是将 binder 对象写到 Parcel 中writeInt32(rep); 调用了 writeAligned(T val)
status_t Parcel::writeAligned(T val) {
static_assert(PAD_SIZE_UNSAFE(sizeof(T)) == sizeof(T));
static_assert(std::is_trivially_copyable_v);
// 先判断是否需要扩容
if ((mDataPos+sizeof(val))
// 判断是否超过了最大长度
if (len > INT32_MAX) {
return BAD_VALUE;
}
// 更新一下 mDataPos 长度,如果下次再写,mDataPos就是下一个开始的偏移点
mDataPos += len;
if (mDataPos > mDataSize) {
mDataSize = mDataPos;
}
return NO_ERROR;
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/63f38448f8214e50bd0cc41992f5e7a3.png)
接下来 binder 对象写到驱动层以后是怎么处理的
Binder 实体对象传入到 binder 驱动以后,如果是实体对象,先看驱动中有没有实体对象(binder_node 数据结果),如果没有则 new 一个,然后再检查在目标进程有没有对应的引用对象,如果没有则创建一个, 如果是实体对象则转换成代理对象,标记由 BINDER_TYPE_BINDER 转换成 BINDER_BINDER_TYPE_HANDLE。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/fb33add58f024e16bee78a6b7d25c6cd.png)
读取数据
data.readStrongBinder() 读取数据是从 onTransact 中 data.readStrongBinder() 开始的
// mNativePtr 是java层 Parcel 对象对应的 native 层 Parcel 对象的指针
public final IBinder readStrongBinder() {
return nativeReadStrongBinder(mNativePtr);
}
frameworks/base/core/jni/android_os_Parcel.cpp 的 nativeReadStrongBinder() 函数
static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)
{
// 通过 nativePtr Parcel 指针获取 native 层 Parcel 对象
Parcel* parcel = reinterpret_cast(nativePtr);
if (parcel != NULL) {
// 从 Parcel 中 先通过 readStrongBinder() 读出来 native 层的 binder 对象
// 再通过 javaObjectForIBinder 将 native 层的 binder 对象转换为 java 层的 binder 对象返回
return javaObjectForIBinder(env, parcel->readStrongBinder());
}
return NULL;
}
readStrongBinder():从 Parcel 中 先通过 readStrongBinder() 读出来 native 层的 binder 对象。调用了 readNullableStrongBinder() 后又调用了 unflattenBinder(val);
sp Parcel::readStrongBinder() const
{
sp val;
// Note that a lot of code in Android reads binders by hand with this
// method, and that code has historically been ok with getting nullptr
// back (while ignoring error codes).
readNullableStrongBinder(&val);
return val;
}
status_t Parcel::readNullableStrongBinder(sp* val) const
{
return unflattenBinder(val);
}
unflattenBinder(val);
status_t Parcel::unflattenBinder(sp* out) const{
// 首先先从 Parcel 将 flat_binder_object 读取出来
const flat_binder_object* flat = readObject(false);
// 根据 type 区分,上面说了驱动将写到缓冲区的实体对象的 type 从 BINDER_TYPE_BINDER 改为了 BINDER_TYPE_HANDLE(如果是同一个进程的话则还是BINDER_TYPE_BINDER 因为转换之前判断了进程是否含有)
switch (flat->hdr.type) {
case BINDER_TYPE_BINDER: {
// 同一个进程返回的是 cookie 赋值的是 binder 实体对象
sp binder =
sp::fromExisting(reinterpret_cast(flat->cookie));
return finishUnflattenBinder(binder, out);
}
case BINDER_TYPE_HANDLE: {
//根据 handle 值 生成 BPBinder 返回
sp binder =
ProcessState::self()->getStrongProxyForHandle(flat->handle);
return finishUnflattenBinder(binder, out);
}
}
}
getStrongProxyForHandle() 根据 binder代理对象的 handle 值返回binder在native层的对象。
sp ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp result;
// 根据 handle 生成一个 handle_entry 值
handle_entry* e = lookupHandleLocked(handle);
if (e != nullptr) {
IBinder* b = e->binder;
// ...
// 封装成 BpBinder
sp b = BpBinder::PrivateAccessor::create(handle);
e->binder = b.get();
if (b) e->refs = b->getWeakRefs();
result = b;
}
}
return result;
}
getStrongProxyForHandle() 是 handler值来创建一个 BPBinder;接下来继续 javaObjectForIBinder() 函数
javaObjectForIBinder() 根据 native 层的 binder 对象返回 java 层的 binder 对象
// If the argument is a JavaBBinder, return the Java object that was used to create it.
// Otherwise return a BinderProxy for the IBinder. If a previous call was passed the
// same IBinder, and the original BinderProxy is still alive, return the same BinderProxy.
jobject javaObjectForIBinder(JNIEnv* env, const sp& val)
{
// 先判断是不是binder实体
if (val->checkSubclass(&gBinderOffsets)) {
// It's a JavaBBinder created by ibinderForJavaObject. Already has Java object.
// 如果是 binder 实体 返回 java 层的 JavaBBinder
jobject object = static_cast(val.get())->object();
return object;
}
// 如果是代理对象 则需要创建 BinderProxy 对象 内部存储了 native 层 binder 对象的指针
BinderProxyNativeData* nativeData = new BinderProxyNativeData();
nativeData->mOrgue = new DeathRecipientList;
nativeData->mObject = val;
jobject object = env->CallStaticObjectMethod(gBinderProxyOffsets.mClass,
gBinderProxyOffsets.mGetInstance, (jlong) nativeData, (jlong) val.get());
BinderProxyNativeData* actualNativeData = getBPNativeData(env, object);
return object;
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/bd282d38b40f4901a714de9edea2603a.png)
总结
Binder 跨进程传输是通过 Parcel 传输的,先通过 WriteStrongBinder 写到 Parcel 再通过 ReadStrongBinder 读取Parcel。在 Parcel 中存储的结构是 flat_binder_object 根据偏移量来确定保存的位置。然后 Binder 驱动通过读取 Parcel 中的 binder 实体对象 创建了 binder_node 结构,和 binder_ref 引用给到目标进程;目标进程通过 binder_ref 的 handle 创建了 BpBinder 再往上调用到 BinderProxy 再调用到业务层 Proxy
|