parent
884b45508e
commit
234461c85a
@ -0,0 +1,183 @@ |
||||
--- |
||||
Binder 对象跨进程传递的原理是怎样的? |
||||
--- |
||||
|
||||
1. binder 传递有哪些方式? |
||||
2. binder 在传递过程中是怎么存储的? |
||||
3. binder 对象序列化和反序列化过程? |
||||
4. binder 对象传递过程中驱动层做了什么? |
||||
|
||||
先从 AIDL 入口: |
||||
|
||||
```java |
||||
interface IRemoteCaller{ |
||||
void publishBinder(ICallback callback); |
||||
} |
||||
``` |
||||
|
||||
```java |
||||
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(); |
||||
} |
||||
} |
||||
``` |
||||
|
||||
```java |
||||
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; |
||||
} |
||||
} |
||||
} |
||||
``` |
||||
|
||||
```java |
||||
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; |
||||
} |
||||
``` |
||||
|
||||
```c++ |
||||
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 到了驱动层是如何处理的? |
||||
|
||||
```c++ |
||||
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; |
||||
} |
||||
} |
||||
} |
||||
``` |
||||
|
||||
读: |
||||
|
||||
```java |
||||
public final IBinder readStrongBinder(){ |
||||
return nativeReadStrongBinder(mNativePtr); |
||||
} |
||||
``` |
||||
|
||||
```c++ |
||||
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 |
Loading…
Reference in new issue