ibinder和binder
service端有一个ibinder
当client和service处于同一个进程中时,client可以找到service的ibinder,并直接拿它来用
当client和service不在同一个进程中时,client通过bindservice得到一个ibinder,通过ibinder.transact(int code, Parcel data, Parcel reply, int flags)来与service通信。但对于IPC来说,ibinder.transact要做很多工作,但在各式各样的service端实现逻辑之上,却额外有一些通用的东西,将这些东西抽取出来放入binder.transact以复用整体流程(binder是ibinder的子类),而提供binder.ontransact以让service端简洁的实现各自的核心逻辑(一个钩子,IOC)
aidl应该带给开发者什么样的便利
开发者不应该看到ibinder和binder,因为那是java端太底层的东西(在c++端,还存在着bpbinder和bbinder等着你),开发者在乎的是service端的核心逻辑要如何实现。他会说:定义一个接口,我完成了它的实现。
但是对于ipc来说,开发者的核心逻辑的调用必须要经过ontransact
client更不应该看到ibinder和binder,它们只知道:嘿,我知道我在进行一个远程调用,而且我知道开发者给我提供了一个接口和那个接口的一个对象,那么,我开始调用了
但是对于ipc来说,client必须要通过ibinder.transact来开始调用
那么,所有的一切都明了了,client和服务器端都需要代理:stub.proxy和stub
stub.proxy
client要调用函数了,我必须将它转化为ibinder.transact,刚好,client已经将ibinder给我了
好的,给我了实参,我将把它们放入到parcel中
我知道client调用的方法的名字,将它放入到code中
OK,完成了,调用ibinder.transact(int code, Parcel data, Parcel reply, int flags)
等等,为了让client看起来在使用开发者给他提供的那个接口,我必须要假装实现了那个接口
stub
我知道某个家伙在调用transact,所以我将调用ontransact
我知道他提供了哪些参数(parcel data),我也知道他想调用开发者提供的哪个方法(code)
我将调用那个方法,并将方法的返回值写入到parcel reply中
OK,完成了
等等,我必须要在service.onbind中返回,所以我必须继承binder(不原始实现ibinder了);而我需要调用开发者的接口,那么我需要开发者接口的一个对象(采用组合的形式),或者,我声称实现了开发者的接口,让开发者来继承我以填充他的接口实现(继承的方式)