基于Binder机制之AIDL原理分析

上一篇完成了两个项目间的AIDL跨进程通讯demo(这个demo是两个应用之间的通讯,如果是一个项目之间的通讯就更简单了,反正就三要素:沟通C-S的桥梁——AIDL文件,客户端,服务端都放到一个项目就行了),没有分析任何原理,下面来分析AIDL是如何进行跨进程通讯的:
在进行AIDL原理分析之前,先回忆一下Android跨进程通讯总共有几种方式:

  1. 文件
  2. AIDL(基于Binder)
  3. Messenger(基于Binder)
  4. Content Provider(基于Binder)
  5. Socket
  6. Binder

至于说如何选择这几种通讯方式?

《Android开发艺术》中说的很是清晰:基于Binder机制之AIDL原理分析_第1张图片
下面来看看AIDL到底做了什么:
所有资料都告诉我们AIDL是基于Binder机制实现跨进程通讯,显然又得学学Binder是个什么玩意,但是饭要一口口吃,路要一步步走,这里我们再次完全抛开Binder机制,先弄明白AIDL为我们做了什么工作。
大家都知道在使用AIDL机制实现跨进程的时候,我们只是生成了一个aidl文件,copy到客户端和服务端,客户端就能BindService对应的服务端进行通信,显然重点都在编译生成的这个aidl文件中!!看源码

package com.testaidl;
public interface IMyAidl extends android.os.IInterface{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.testaidl.IMyAidl {。。。}
public void addPerson(com.testaidl.model.Person person) throws android.os.RemoteException;
public java.util.List getPersonList() throws android.os.RemoteException;

一、可以看到,在第一步、第二步,会生成接口IMyAidl,继承IInterface,IInterface是进程间通讯定义的通用接口,同时IMyAidl包含我们定义的两个方法
二、IMyAidl中包含Stub,这是一个Binder,同时也实现了IMyAidl接口
三、重点就在Stub上,先看源码

/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.testaidl.IMyAidl {
private static final java.lang.String DESCRIPTOR = "com.testaidl.IMyAidl";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
 * Cast an IBinder object into an com.testaidl.IMyAidl interface,
 * generating a proxy if needed.
 */
public static com.testaidl.IMyAidl asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.testaidl.IMyAidl))) {
return ((com.testaidl.IMyAidl)iin);
}
return new com.testaidl.IMyAidl.Stub.Proxy(obj);
}
@Override public android.os.IBinder asBinder()
{
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_basicTypes:
{
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
long _arg1;
_arg1 = data.readLong();
boolean _arg2;
_arg2 = (0!=data.readInt());
float _arg3;
_arg3 = data.readFloat();
double _arg4;
_arg4 = data.readDouble();
java.lang.String _arg5;
_arg5 = data.readString();
this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5);
reply.writeNoException();
return true;
}
case TRANSACTION_addPerson:
{
data.enforceInterface(DESCRIPTOR);
com.testaidl.model.Person _arg0;
if ((0!=data.readInt())) {
_arg0 = com.testaidl.model.Person.CREATOR.createFromParcel(data);
}
else {
_arg0 = null;
}
this.addPerson(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_getPersonList:
{
data.enforceInterface(DESCRIPTOR);
java.util.List _result = this.getPersonList();
reply.writeNoException();
reply.writeTypedList(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}

代码有点多,这个类的作用:
1、将一个Binder与当前IMyAidl接口绑定(在Stub构造器中,this.attachInterface(this, DESCRIPTOR);)
2、将Ibinder转换为IMyAidl接口(asInterface函数中转换和创建代理,返回给客户端使用),不在同一个进程时就创建代理
3、onTransact函数,是Binder处理事情的关键方法,根据传入的code,调用本地/服务端的不同方法

下面看看代理 Proxy

private static class Proxy implements com.testaidl.IMyAidl{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
/**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
@Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(anInt);
_data.writeLong(aLong);
_data.writeInt(((aBoolean)?(1):(0)));
_data.writeFloat(aFloat);
_data.writeDouble(aDouble);
_data.writeString(aString);
mRemote.transact(Stub.TRANSACTION_basicTypes, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
@Override public void addPerson(com.testaidl.model.Person person) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((person!=null)) {
_data.writeInt(1);
person.writeToParcel(_data, 0);
}
else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_addPerson, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
@Override public java.util.List getPersonList() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.util.List _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getPersonList, _data, _reply, 0);
_reply.readException();
_result = _reply.createTypedArrayList(com.testaidl.model.Person.CREATOR);
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}

Proxy主要就是处理下数据,调用实际的Binder来处理

总结:

IInterface文件:aidl定义的方法、Stub
Stub:是一个Binder,同时实现了IInterface接口

  1. 将Binder转换成IInterface(asInterface方法)
  2. 处理调度的onTransact
  3. Proxy,一个IInterface类型的代理,接口定义方法的伪实现,实现调用的是Binder
    也就是说,AIDL帮我们生成了Binder和跨平台转化类Stub,客户端拿到代理Proxy,调用Binder—通知服务端–服务端调用真正的方法执行

你可能感兴趣的:(android)