You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
android-notes/blogs/Android/Framework/Interview/进程间通信相关/Binder 对象跨进程传递原理.md

5.5 KiB

Binder 对象跨进程传递的原理是怎样的?
  1. binder 传递有哪些方式?
  2. binder 在传递过程中是怎么存储的?
  3. binder 对象序列化和反序列化过程?
  4. binder 对象传递过程中驱动层做了什么?

先从 AIDL 入口:

interface IRemoteCaller{
	void publishBinder(ICallback callback);
}
public void publishBinder(ICallback callback){
    Parcel_data = Parcel.obtain();
    Parcel _reply = Parcel.obtain();
    try{
        _data.writeInterfaceToken(DESCRIPTOR);
        _data.writeStrongBinder(callback!=null?callback.asBinder():null);
        mRemote.transact(Stub.TRANSACTION_publishBinder, _data, _reply, 0);
        _reply.readException();
    }finally{
        _reply.recycle();
        _data.recycle();
    }
}
public boolean onTransact(int code, Parcel data, Parcel reply, int flags){
    String descriptor = DESCRIPTOR;
    switch(code){
        case TRANSACTION_publishBinder:{
            data.enforceInterface(descriptor);
            ICallback _arg0;
            _arg0 = ICallback.Stub.asInterface(data.readStrongBinder());
            this.publishBinder(_arg0);
            reply.writeNoException();
            return true;
        }
    }
}
public final void writeStrongBinder(IBinder val){
	nativeWriteStrongBinder(mNativePtr, val);
}
void Parcel writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object){
    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    if(parcel!=NULL){
        const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
        if(err!=NO_ERROR){
            signalExceptionForError(env, clazz, err);
        }
    }
}
sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj){
    if(env->IsInterfaceOf(obj, gBinderOffsets.mClass)){
        env->GetLongField(obj, gBinderOffsets.mObject);
        return jbh!=NULL?jbh->get(env, obj):NULL;
    }
    if(env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)){
        return (IBinder*)
            env->GetLongField(obj, gBinderProxyOffsets.mObject);
    }
    return NULL;
}
status_t Parcel:writeStrongBinder(const sp<IBinder>&val){
	return flatten_binder(ProcessState::self(), val, this);
}
status_t flatten_binder(sp<ProcessState>&proc, sp<IBinder>&binder, Parcel* out){
    flat_binder_object obj;
    IBinder *local = binder->localBinder();
    obj.type = BINDER_TYPE_BINDER;
    obj.cookie = reinterpret_cast<uintptr_t>(local);
    return finish_flatten_binder(binder, obj, out);
}
status_t finish_flatten_binder(sp<IBinder>& binder, flat_binder_object& flat, Parcel* out){
    return out->writeObject(flat, false);
}
status_t Parcel::writeObject(const flat_binder_object& val, bool nullMetaData){
    *reinterpret_cast<flat_binder_object*>(mData+mDataPos)=val;
    mObjectsSize++;
    return finishWrite(sizeof(flat_binder_object));
}
status_t Parcel::finishWrite(size_t len){
    mDataPos += len;
    return NO_ERROR;
}

Parce 到了驱动层是如何处理的?

static void binder_transaction(struct binder_proc *proc, ...){
	for(;offp<off_end;offp++){
        fp=(struct flat_binder_object *)(t->buffer->data+*offp);
        switch(fp->type){
            case BINDER_TYPE_BINDER:{
                struct binder_node *node = binder_get_node(proc, fp->binder);
                if(node==NULL){
                    node=binder_new_node(proc,fp->binder,fp->cookie);
                }
                ref = binder_get_ref_for_node(target_proc,node);
                if(fp->type==BINDER_TYPE_BINDER)
                    fp->type=BINDER_TYPE_HANDLE;
                fp->handle=ref->desc;
            }break;
        }
    }
}

读:

public final IBinder readStrongBinder(){
	return nativeReadStrongBinder(mNativePtr);
}
jobject Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr){
	Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
	if(parcel!=NULL){
		return javaObjectForIBinder(env, parcel->readStrongBinder());
	}
	return NULL;
}
sp<IBinder> Parcel::readStrongBinder() const{
    sp<IBinder> val;
    unflatten_binder(ProcessState::self(), *this, &val);
    return val;
}
status_t unflatten_binder(sp<ProcessState>& proc, Parcel& in,sp<IBinder>* out){
    const flat_binder_object* flat = in.readObject(false);
    switch(flat->type){
        case BINDER_TYPE_BINDER:
        	*out = reinterpret_cast<IBinder*>(flat->cookie);
            return ...;
        case BINDER_TYPE_HANDLE:
            *out = proc->getStrongProxyForHandle(flat->handle);
            return ...;
    }
}
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle){
    sp<IBinder> result;
    handle_entry* e = lookupHandleLocked(handle);
    IBinder* b = e->binder;
    if(b == NULL){
        b = new BpBinder(handle);
        e->binder = b;
        result = b;
    }
    return result;
}
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val){
    if(val->checkSubclass(&gBinderOffsets)){
        jobject object = static_cast<JavaBBinder*>(val.get())->object();
        return object;
    }
    object = env->NewObject(gBinderProxyOffsets.mClass, ...);
    env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
    return object;
}

binder 是怎么跨进程传输的?

  1. Parcel 的 writeStrongBinder 和 readStrongBinder
  2. binder 在 Parcel 中存储原理,flat_binder_object
  3. 说清楚 binder_node,binder_ref
  4. 目标进程根据 binder_ref 的 handle 创建 BpBinder
  5. 由 BpBinder 再往上到 BinderProxy 到业务层的 Proxy