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