前言
binder通信在Android中一直属于核心机制,前面分析了binder的c层和C++层的通信机制,但是没有分析binder的java层通信机制,但是作为一个资深Android开发人员,这个怎么能不搞懂,这补充一下;
首先要声明一下,Android7.00和8.0的源码其实差别还有点的,binder通信上主要表现在7.0的AMS是继承ActivityManagerNative的,而8.0的AMS是直接实现了IActivityManager.stub接口,也就是直接通过AIDL接口实现的,其实原来的ActivityManagerNative的实现就是一个stub的功能。
三个“搞明白”
想要知道AIDL的底层原理,首先要来三个"搞明白":
(1)搞明白AIDL编译时期生成的文件其中的类和方法的作用
(2)搞明白Java层binder、JavaBBinder、JavaBBinderHolder之间的关系,以及他们的分工和作用
(3)搞明白Parcel在binder机制中的作用
搞明白AIDL编译时期生成的文件其中的类和方法的作用
AIDL是Android interface definition language,因此使用的时候是面向接口的,需要自定义一个接口,例如:
interface IStoreAidl {
int sell(String pencil);
}
public interface IStoreAidl extends android.os.IInterface{(1)
public static abstract class Stub extends android.os.Binder implements com.xx.leo_service.ILeoAidl{(2)
private static final java.lang.String DESCRIPTOR = "com.android.test.IStoreAidl";(2-1)
public android.os.IBinder asBinder(){......}(2-2)
public static com.xx.leo_service.ILeoAidl asInterface(android.os.IBinder obj)
{...... return new com.xx.leo_service.ILeoAidl.Stub.Proxy(obj);}(2-3)
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)){
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_sayhello_to:
{
data.enforceInterface(DESCRIPTOR);
java.lang.String _arg0;
_arg0 = data.readString();
int _result = this.sell(_arg0);
reply.writeNoException();
reply.writeInt(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}(2-4)
private static class Proxy implements com.xx.leo_service.ILeoAidl{}(2-5)
}
}
在编译的时候,自动生成AIDL文件,文件中包含三个部分:
(1)自定义接口IStoreAidl自动继承IInterface接口
(2)自动创建抽象类Stub继承Binder并实现IStoreAidl接口,对于客户端来说,stub代表了服务端,服务端继承了stub并实现接口中的方法,客户端通过暴露出的接口调用服务端的方法,Android7.0中的AcrivityManagerNative就扮演了这个角色。
(3)stub中有五个重要的部分:
- DESCRIPTOR(2-1):定义一个常量描述符,一般用来作为token通过parcel写给binder,binder为啥安全,就因为他们有校验机制
- asBinder()(2-2):通过parcel实现asBinder()方法,服务端通过该方法来获取Ibinder;
- asInterface(IBinder iBinder)(2-3):客户端通过该方法得到服务端的代理,proxy就相当于stub在客户端的一个代理,客户端通过这个代理,并其中的方法,将数据封装成功parcel然后写入到binder底层驱动中,然后发送到服务端;
- onTransact()(2-4):重写onTransact()方法,该方法是binder的方法,用来分发onTransact的,在这里调用服务端实现的方法,并将结果写入parcel的reply中去通过该方法层层传递,返回给客户端;
- Proxy(2-5):stub的静态内部类,实现了IStoreAidl接口,是服务端stub在客户端的一个代理类,主要用来将客户端的消息封装成parcel数据,然后通过remote.transact()与binder驱动进行交互
搞明白Java层binder、JavaBBinder、JavaBBinderHolder之间的关系,以及他们的分工和作用
首先通过一幅图总结一下:
public class StoreService extends IStoreAidl.Stub {......}(1)
ServiceManager.addService("hello", new HelloService())(2)
(1)服务端是继承的IStoreAidl.Stub 其实也就是继承的Binder,因此服务端就是个Binder
(2)从关系图中可以看出,new HelloService()的时候,在Binder的构造中调用init(),调用native层的方法创建JavaBBinderHolder()并将它赋值给Binder的mObject;
(3)JavaBBinderHolder的构造中又创建了JavaBBinder extends BBinder,并赋值给了mBinder
(4)最后又把Binder赋值给了JavaBBinder的mObject
(5)将服务注册到ServiceManager中去,因此这个注册到SM中的Binder,就是JavaBBinder它属于BBinder
因此binder、JavaBBinder、JavaBBinderHolder他们是相互持有,JavaBBinder属于BBinder,IPCThreadState从binder驱动中读取到数据后,调用了注册到SM中的服务端,也就是BBinder
status_t BBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
.....
//实际上就是通过onTransact分发,调用了JavaBBinder中的onTransact方法
//JavaBBinder通过ExecTransact方法分发到了java层binder的onTransact()方法,也就是IHelloService.Stub重写的onTransact()方法,将文章开始部分
err = onTransact(code, data, reply, flags);
....
return err;
}
JavaBBinder中重写了onTransact,其实就是通过ExecTransact方法,继续向java层的binder中的onTransact分发,其实就是调用了IHelloService.Stub中的onTransact()方法,然后再那里调用服务端的接口实现代码:
import android.util.Slog;
public class HelloService extends IHelloService.Stub {
private static final String TAG = "HelloService";
public int sell(java.lang.String shoe) throws android.os.RemoteException {
Slog.i(TAG, "sell "+shoe);
return 100;
}
}
搞明白Parcel在binder机制中的作用
java层的parcel其实就是对C层Parcel的一个封装,Parcel在binder机制中的作用除了能够封装数据之外,主要是因为他有传递binder对象的功能:
parcel.writeStrongBinder():flatten_binder
ReadStringBinder():unFlatten_binder
这两个方法对binder对象进行序列化和反序列化;
parcel.writeStrongBinder(service)
我们在之前讲到,这个service是我们自己的服务,也就是BinderrProxy——>JavaBBinder::BBinder
java层的writeStrongBinder其实就是调用native的android_os_Parcel_writeStrongBinder
static void android_os_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)
{ //gBinderOffsets.mClass指向BinderProxy——>JavaBBinder::BBinder
if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
JavaBBinderHolder* jbh = (JavaBBinderHolder*)
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;
}
所以这个parcel->writeStrongBinder(ibinderForJavaObject(env, object));其实就是parcel->writeStrongBinder(new JavaBBinder(env, obj));
status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{
return flatten_binder(ProcessState::self(), val, this);
}
status_t flatten_binder(const sp<ProcessState>& /*proc*/,
const sp<IBinder>& binder, Parcel* out)
{
flat_binder_object obj;
if (IPCThreadState::self()->backgroundSchedulingDisabled()) {
obj.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS;
} else {
obj.flags = 0x13 | FLAT_BINDER_FLAG_ACCEPTS_FDS;
}
if (binder != NULL) {
IBinder *local = binder->localBinder(); //binder是BBinder,所以得到的时this,所以走的else
if (!local) {
BpBinder *proxy = binder->remoteBinder();
if (proxy == NULL) {
ALOGE("null proxy");
}
const int32_t handle = proxy ? proxy->handle() : 0;
obj.type = BINDER_TYPE_HANDLE;
obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */
obj.handle = handle;
obj.cookie = 0;
} else {
obj.type = BINDER_TYPE_BINDER;
obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
obj.cookie = reinterpret_cast<uintptr_t>(local);
}
} else {
obj.type = BINDER_TYPE_BINDER;
obj.binder = 0;
obj.cookie = 0;
}
return finish_flatten_binder(binder, obj, out);
}
所以服务端的BinderProxy——>JavaBBinder()::BBinder也就被拆分成了type、binder和cookie存到了parcel中
parcel.ReadStringBinder(service)
read其实就是write的逆向走势;
readStrongBinder其实就是调用native层的nativeReadStrongBinder方法,调用C++层的readNullableStrongBinder——>unflatten_binder方法;
static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) {
//readStrongBinder调用了Parcel中的unflatten_binder方法
return javaObjectForIBinder(env, parcel->readStrongBinder());
}
return NULL;
}
status_t unflatten_binder(const sp<ProcessState>& proc,
const Parcel& in, sp<IBinder>* out)
{
const flat_binder_object* flat = in.readObject(false);
if (flat) {
switch (flat->type) {
case BINDER_TYPE_BINDER:
*out = reinterpret_cast<IBinder*>(flat->cookie);
return finish_unflatten_binder(NULL, *flat, in);
case BINDER_TYPE_HANDLE: //这里是从服务端获取,因此走的这个分支
//因为ServiceManager注册的时候,也调用了ProcessState.getStrongProxyHander()方法,返回new BpBinder(0)
//但是new BpBinder(0)的0是SM专属的,因此这里返回的是new BpBinder(handler),handler肯定不为0
*out = proc->getStrongProxyForHandle(flat->handle);
return finish_unflatten_binder(
static_cast<BpBinder*>(out->get()), *flat, in);
}
}
return BAD_TYPE;
}
因为ServiceManager注册的时候,也调用了ProcessState.getStrongProxyHander()方法,返回new BpBinder(0),0是SM专属的,因此这里返回的是new BpBinder(handler),handler肯定不为0;所以
sp<IBinder>* out = proc->getStrongProxyForHandle(flat->handle);
相当于
sp<IBinder>* out = new BpBinder(handler);
所以:
static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) {
return javaObjectForIBinder(env, new BpBinder(handler));
}
return NULL;
}
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{
//如果是服务端的binder也就是BBinder就返回JavaBBinder,这里显然不是了
if (val->checkSubclass(&gBinderOffsets)) {
jobject object = static_cast<JavaBBinder*>(val.get())->object();
return object;
}
AutoMutex _l(mProxyLock);
//如果之前已经获取过,就返回BinderProxy,第一次的话肯定是没有获取过的
jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
if (object != NULL) {
jobject res = jniGetReferent(env, object);
if (res != NULL) {
return res;
}
android_atomic_dec(&gNumProxyRefs);
val->detachObject(&gBinderProxyOffsets);
env->DeleteGlobalRef(object);
}
//如果是第一次进入,就创建一个BinderProxy并将new BpBinder(handler)对象赋值给BinderProxy的object
object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
if (object != NULL) {
env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
val->incStrong((void*)javaObjectForIBinder);
jobject refObject = env->NewGlobalRef(
env->GetObjectField(object, gBinderProxyOffsets.mSelf));
val->attachObject(&gBinderProxyOffsets, refObject,
jnienv_to_javavm(env), proxy_cleanup);
sp<DeathRecipientList> drl = new DeathRecipientList;
drl->incStrong((void*)javaObjectForIBinder);
env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jlong>(drl.get()));
android_atomic_inc(&gNumProxyRefs);
incRefsCreated(env);
}
return object;
}
所以当通过Parcel的unflatten_binder方法拿到远程服务的binder对象(new BpBinder(handler)handler非0)后,然后封装成java层客户端的代理BinderProxy()对象返回给客户端
调用链太长用时序图总结一下:
最后通过之前讲的IstoreAidl.stub.asInterface(BinderProxy())方法得到IstoreAidl.stub.Proxy对象,且BinderProxy中的remote属性指向new BpBinder(handler)