一、简介
这将是一个围绕AIDL的系列文章,内容含AIDL简单使用、进阶使用、AIDL源码探索,希望从简单开始再到复杂,在这个过程中使大家既能掌握AIDL的使用方法和需要注意的细节,同时也能通过对AIDL源码的探索,使各位理解AIDL的处理原理。这篇文章为第三篇,会在前两篇的基础上,根据例子中的AIDL接口,深入源码探索AIDL的实现原理。
- Android IPC之AIDL使用(一)
- Android IPC之AIDL使用(二)
- Android IPC之AIDL源码探索(三) 文章词汇解释:
- AS:AndroidStudio开发工具
- AIDL文件:指在aidl目录下创建的aidl接口
- AIDL类:指由aidl文件Build生成的类
二、AIDL文件结构
先回顾一下,前两篇文章中定义的AIDL文件。
interface MyAIDLInterface {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void commonMethod();
void setStringText(String text);
void setObjectMethodIn(in MethodObject o);
void setObjectMethodOut(out MethodObject o);
void setObjectMethodInout(inout MethodObject o);
MethodObject getObjectMethod();
void register(CallBackAIDLInterface aidl);
void unregister(CallBackAIDLInterface aidl);
}
为了全面了解AIDL对不同类型函数的处理逻辑,这里定义了8个函数,register()和unregister()情况一样,所以总体有7种不同类型。现在去看AIDL类,真正的幕后黑手,类内容有些长,你可能会反感,但相信我你需要耐心的浏览一下。
public interface MyAIDLInterface extends android.os.IInterface
{
/** Default implementation for MyAIDLInterface. */
public static class Default implements com.zhukai.aidlservice.MyAIDLInterface
{
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
@Override public void commonMethod() throws android.os.RemoteException
{
}
@Override public void setStringText(java.lang.String text) throws android.os.RemoteException
{
}
@Override public void setObjectMethodIn(com.zhukai.aidlservice.MethodObject o) throws android.os.RemoteException
{
}
@Override public void setObjectMethodOut(com.zhukai.aidlservice.MethodObject o) throws android.os.RemoteException
{
}
@Override public void setObjectMethodInout(com.zhukai.aidlservice.MethodObject o) throws android.os.RemoteException
{
}
@Override public com.zhukai.aidlservice.MethodObject getObjectMethod() throws android.os.RemoteException
{
return null;
}
@Override public void register(com.zhukai.aidlservice.CallBackAIDLInterface aidl) throws android.os.RemoteException
{
}
@Override public void unregister(com.zhukai.aidlservice.CallBackAIDLInterface aidl) throws android.os.RemoteException
{
}
@Override
public android.os.IBinder asBinder() {
return null;
}
}
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.zhukai.aidlservice.MyAIDLInterface
{
private static final java.lang.String DESCRIPTOR = "com.zhukai.aidlservice.MyAIDLInterface";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.zhukai.aidlservice.MyAIDLInterface interface,
* generating a proxy if needed.
*/
public static com.zhukai.aidlservice.MyAIDLInterface asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.zhukai.aidlservice.MyAIDLInterface))) {
return ((com.zhukai.aidlservice.MyAIDLInterface)iin);
}
return new com.zhukai.aidlservice.MyAIDLInterface.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
{
java.lang.String descriptor = DESCRIPTOR;
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(descriptor);
return true;
}
case TRANSACTION_commonMethod:
{
data.enforceInterface(descriptor);
this.commonMethod();
reply.writeNoException();
return true;
}
case TRANSACTION_setStringText:
{
data.enforceInterface(descriptor);
java.lang.String _arg0;
_arg0 = data.readString();
this.setStringText(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_setObjectMethodIn:
{
data.enforceInterface(descriptor);
com.zhukai.aidlservice.MethodObject _arg0;
if ((0!=data.readInt())) {
_arg0 = com.zhukai.aidlservice.MethodObject.CREATOR.createFromParcel(data);
}
else {
_arg0 = null;
}
this.setObjectMethodIn(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_setObjectMethodOut:
{
data.enforceInterface(descriptor);
com.zhukai.aidlservice.MethodObject _arg0;
_arg0 = new com.zhukai.aidlservice.MethodObject();
this.setObjectMethodOut(_arg0);
reply.writeNoException();
if ((_arg0!=null)) {
reply.writeInt(1);
_arg0.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
return true;
}
case TRANSACTION_setObjectMethodInout:
{
data.enforceInterface(descriptor);
com.zhukai.aidlservice.MethodObject _arg0;
if ((0!=data.readInt())) {
_arg0 = com.zhukai.aidlservice.MethodObject.CREATOR.createFromParcel(data);
}
else {
_arg0 = null;
}
this.setObjectMethodInout(_arg0);
reply.writeNoException();
if ((_arg0!=null)) {
reply.writeInt(1);
_arg0.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
return true;
}
case TRANSACTION_getObjectMethod:
{
data.enforceInterface(descriptor);
com.zhukai.aidlservice.MethodObject _result = this.getObjectMethod();
reply.writeNoException();
if ((_result!=null)) {
reply.writeInt(1);
_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
return true;
}
case TRANSACTION_register:
{
data.enforceInterface(descriptor);
com.zhukai.aidlservice.CallBackAIDLInterface _arg0;
_arg0 = com.zhukai.aidlservice.CallBackAIDLInterface.Stub.asInterface(data.readStrongBinder());
this.register(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_unregister:
{
data.enforceInterface(descriptor);
com.zhukai.aidlservice.CallBackAIDLInterface _arg0;
_arg0 = com.zhukai.aidlservice.CallBackAIDLInterface.Stub.asInterface(data.readStrongBinder());
this.unregister(_arg0);
reply.writeNoException();
return true;
}
default:
{
return super.onTransact(code, data, reply, flags);
}
}
}
private static class Proxy implements com.zhukai.aidlservice.MyAIDLInterface
{
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 commonMethod() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
boolean _status = mRemote.transact(Stub.TRANSACTION_commonMethod, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
getDefaultImpl().commonMethod();
return;
}
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
@Override public void setStringText(java.lang.String text) 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.writeString(text);
boolean _status = mRemote.transact(Stub.TRANSACTION_setStringText, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
getDefaultImpl().setStringText(text);
return;
}
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
@Override public void setObjectMethodIn(com.zhukai.aidlservice.MethodObject o) 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 ((o!=null)) {
_data.writeInt(1);
o.writeToParcel(_data, 0);
}
else {
_data.writeInt(0);
}
boolean _status = mRemote.transact(Stub.TRANSACTION_setObjectMethodIn, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
getDefaultImpl().setObjectMethodIn(o);
return;
}
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
@Override public void setObjectMethodOut(com.zhukai.aidlservice.MethodObject o) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
boolean _status = mRemote.transact(Stub.TRANSACTION_setObjectMethodOut, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
getDefaultImpl().setObjectMethodOut(o);
return;
}
_reply.readException();
if ((0!=_reply.readInt())) {
o.readFromParcel(_reply);
}
}
finally {
_reply.recycle();
_data.recycle();
}
}
@Override public void setObjectMethodInout(com.zhukai.aidlservice.MethodObject o) 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 ((o!=null)) {
_data.writeInt(1);
o.writeToParcel(_data, 0);
}
else {
_data.writeInt(0);
}
boolean _status = mRemote.transact(Stub.TRANSACTION_setObjectMethodInout, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
getDefaultImpl().setObjectMethodInout(o);
return;
}
_reply.readException();
if ((0!=_reply.readInt())) {
o.readFromParcel(_reply);
}
}
finally {
_reply.recycle();
_data.recycle();
}
}
@Override public com.zhukai.aidlservice.MethodObject getObjectMethod() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
com.zhukai.aidlservice.MethodObject _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
boolean _status = mRemote.transact(Stub.TRANSACTION_getObjectMethod, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
return getDefaultImpl().getObjectMethod();
}
_reply.readException();
if ((0!=_reply.readInt())) {
_result = com.zhukai.aidlservice.MethodObject.CREATOR.createFromParcel(_reply);
}
else {
_result = null;
}
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override public void register(com.zhukai.aidlservice.CallBackAIDLInterface aidl) 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.writeStrongBinder((((aidl!=null))?(aidl.asBinder()):(null)));
boolean _status = mRemote.transact(Stub.TRANSACTION_register, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
getDefaultImpl().register(aidl);
return;
}
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
@Override public void unregister(com.zhukai.aidlservice.CallBackAIDLInterface aidl) 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.writeStrongBinder((((aidl!=null))?(aidl.asBinder()):(null)));
boolean _status = mRemote.transact(Stub.TRANSACTION_unregister, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
getDefaultImpl().unregister(aidl);
return;
}
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
public static com.zhukai.aidlservice.MyAIDLInterface sDefaultImpl;
}
static final int TRANSACTION_commonMethod = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_setStringText = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_setObjectMethodIn = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
static final int TRANSACTION_setObjectMethodOut = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
static final int TRANSACTION_setObjectMethodInout = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4);
static final int TRANSACTION_getObjectMethod = (android.os.IBinder.FIRST_CALL_TRANSACTION + 5);
static final int TRANSACTION_register = (android.os.IBinder.FIRST_CALL_TRANSACTION + 6);
static final int TRANSACTION_unregister = (android.os.IBinder.FIRST_CALL_TRANSACTION + 7);
public static boolean setDefaultImpl(com.zhukai.aidlservice.MyAIDLInterface impl) {
// Only one user of this interface can use this function
// at a time. This is a heuristic to detect if two different
// users in the same process use this function.
if (Stub.Proxy.sDefaultImpl != null) {
throw new IllegalStateException("setDefaultImpl() called twice");
}
if (impl != null) {
Stub.Proxy.sDefaultImpl = impl;
return true;
}
return false;
}
public static com.zhukai.aidlservice.MyAIDLInterface getDefaultImpl() {
return Stub.Proxy.sDefaultImpl;
}
}
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
public void commonMethod() throws android.os.RemoteException;
public void setStringText(java.lang.String text) throws android.os.RemoteException;
public void setObjectMethodIn(com.zhukai.aidlservice.MethodObject o) throws android.os.RemoteException;
public void setObjectMethodOut(com.zhukai.aidlservice.MethodObject o) throws android.os.RemoteException;
public void setObjectMethodInout(com.zhukai.aidlservice.MethodObject o) throws android.os.RemoteException;
public com.zhukai.aidlservice.MethodObject getObjectMethod() throws android.os.RemoteException;
public void register(com.zhukai.aidlservice.CallBackAIDLInterface aidl) throws android.os.RemoteException;
public void unregister(com.zhukai.aidlservice.CallBackAIDLInterface aidl) throws android.os.RemoteException;
}
看到这里,我深怕劝退了很多小伙伴,这个类也太长了,但是我相信看到这里的你还是对这个类有了一点印象,现在只需要我们整理一下思路,先弄清楚类的结构,然后再以实际使用作为入口去追踪,一切都会云开雾散!下面我会把代码极简化,让大家看清类的整体结构。
public interface MyAIDLInterface extends android.os.IInterface
{
//默认的实现类
public static class Default implements com.zhukai.aidlservice.MyAIDLInterface
{
... //省略了继承实现的函数
}
//服务端的Binder对象
public static abstract class Stub extends android.os.Binder implements com.zhukai.aidlservice.MyAIDLInterface
{
... //省略了内容
//客户端代理对象
private static class Proxy implements com.zhukai.aidlservice.MyAIDLInterface
{
}
... //省略了内容
}
//AIDL文件中定义的所有函数
public void commonMethod() throws android.os.RemoteException;
public void setStringText(java.lang.String text) throws android.os.RemoteException;
public void setObjectMethodIn(com.zhukai.aidlservice.MethodObject o) throws android.os.RemoteException;
public void setObjectMethodOut(com.zhukai.aidlservice.MethodObject o) throws android.os.RemoteException;
public void setObjectMethodInout(com.zhukai.aidlservice.MethodObject o) throws android.os.RemoteException;
public com.zhukai.aidlservice.MethodObject getObjectMethod() throws android.os.RemoteException;
public void register(com.zhukai.aidlservice.CallBackAIDLInterface aidl) throws android.os.RemoteException;
public void unregister(com.zhukai.aidlservice.CallBackAIDLInterface aidl) throws android.os.RemoteException;
}
现在这个类结构就简单清晰多了,AS根据我们定义的AIDL文件,构建了最外层MyAIDLInterface类,包含了所有AIDL文件中定义的函数。再在内部构建了3个实现类Default、Stub、Proxy(Stub内部类),Default就很好理解了,一个默认实现类;Stub、Proxy(Stub内部类)可以说是整个AIDL类中最重要的两个类,Stub是服务端的,所以它同时还继承了Binder类(Binder类实现了IBinde接口),Proxy是客户端的。弄清楚了结构,现在就可以回到使用,通过使用的流程来追踪内部实现逻辑。
三、源码追踪
1.服务端创建Binder对象
应该还记得在服务端Service中,onBind方法返回了Stub对象。
@Nullable
@Override
public IBinder onBind(Intent intent) {
return stub;
}
MyAIDLInterface.Stub stub = new MyAIDLInterface.Stub() {...}
这里需要看一下Stub对象创建时做了什么。
private static final java.lang.String DESCRIPTOR = "com.zhukai.aidlservice.MyAIDLInterface";
/** Construct the stub at attach it to the interface. */
private IInterface mOwner;
private String mDescriptor;
public Stub()
{
this.attachInterface(this, DESCRIPTOR);//调用了Binder的函数
}
public void attachInterface(@Nullable IInterface owner, @Nullable String descriptor) {
mOwner = owner;//Stub对象
mDescriptor = descriptor;//描述符
}
通过调用父类Binder的attachInterface()函数,把自己和一段描述符绑定在了Binder对象中。这样在onBind()函数中返回的Binder对象就携带了Stub对象和一段描述符,这个描述符就是自己完整的类名。
这个Binder对象最终被返回到哪儿去了呢?会不会是绑定Service的地方,那就去看客户端。
2.客户端获取操作对象
private void bind() {
Intent intent = new Intent();
intent.setAction("com.zhukai.aidlservice.startService");
intent.setComponent(new ComponentName("com.zhukai.aidlservice","com.zhukai.aidlservice.MyService"));
bindService(intent, new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
myAIDLInterface = MyAIDLInterface.Stub.asInterface(service);//核心方法
...
}
@Override
public void onServiceDisconnected(ComponentName name) {
myAIDLInterface = null;
}
}, Service.BIND_AUTO_CREATE);
}
在客户端绑定方法中,ServiceConnection接口的onServiceConnected回调方法返回了一个IBinder对象,这个IBinder对象,就是刚刚服务端Service中返回的Binder对象。这里需要注意,根据Binder机制特性,如果我们绑定的服务没有另起进程,那这个Binder对象和服务端是同一个;另起进程了,这个Binder对象就只是服务端返回Binder对象的一个BinderProxy代理对象。现在Binder已经从服务端传递到了客户端,再看客户端后续操作。
接着调用MyAIDLInterface.Stub.asInterface(service)函数传入Binder对象,这是一个专门获取客户端操作对象的函数。
//描述符就是AIDL类的完整类名
private static final java.lang.String DESCRIPTOR = "com.zhukai.aidlservice.MyAIDLInterface";
/**
* Cast an IBinder object into an com.zhukai.aidlservice.MyAIDLInterface interface,
* generating a proxy if needed.
*/
public static com.zhukai.aidlservice.MyAIDLInterface asInterface(android.os.IBinder obj)
{
if ((obj==null)) {//判空
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);//核心
if (((iin!=null)&&(iin instanceof com.zhukai.aidlservice.MyAIDLInterface))) {
return ((com.zhukai.aidlservice.MyAIDLInterface)iin);
}
return new com.zhukai.aidlservice.MyAIDLInterface.Stub.Proxy(obj);
}
在函数内,先判断了Binder是否为null,紧接着调用Binder对象的queryLocalInterface()函数,传入了客户端的描述符DESCRIPTOR。
public @Nullable IInterface queryLocalInterface(@NonNull String descriptor) {
if (mDescriptor != null && mDescriptor.equals(descriptor)) {//和Binder缓存的描述符做比较
return mOwner;
}
return null;
}
因为Binder对象的不同,在这个函数中就会出现两种情况,如果这个Binder对象和服务端是同一个,在服务端是有绑定了描述符(mDescriptor)和Stub对象(mOwner)的,再同传入的客户端的描述符比较相等,那就会返回绑定的服务端Stub对象。如果这个Binder对像是代理对象,那这个mDescriptor肯定是null,那就直接返回null。
执行跳出这个方法回到asInterface()函数中。
public static com.zhukai.aidlservice.MyAIDLInterface asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.zhukai.aidlservice.MyAIDLInterface))) {//不为null且类型匹配
return ((com.zhukai.aidlservice.MyAIDLInterface)iin);//把Stub对象转换成实现的AIDL类 类型
}
//否则返回代理对象,传入了Binder代理对象。
return new com.zhukai.aidlservice.MyAIDLInterface.Stub.Proxy(obj);
}
如果iin对象是服务端Stub对象,就直接转换成AIDL类类型返回,为null,就会传入Binder代理对象创建Proxy代理对象返回。反正,最终客户端会拿到一个AIDL类对象,是受Binder对象的不同,返回对象有差异。本篇文章重点是围绕Service另起进程的情况,也就是Binder为代理对象,那么此方法将执行到最后一步,返回Proxy代理对象。因为服务端Service是在同一进程的情况下,客户端拿到的是服务端Stub对象,就不存在IPC了,也就没有往后分析的必要。
3.各类型函数内部实现分析
客户端拿到Proxy代理对象,就可以调用所有函数与服务端进行通信。
if (null != myAIDLInterface){
myAIDLInterface.commonMethod();
myAIDLInterface.setStringText("test");
myAIDLInterface.setObjectMethodIn(new MethodObject());
myAIDLInterface.setObjectMethodInout(new MethodObject());
myAIDLInterface.setObjectMethodInout(new MethodObject());
myAIDLInterface.getObjectMethod();
myAIDLInterface.register(callBackAIDLInterface);
myAIDLInterface.unregister(callBackAIDLInterface);
}
CallBackAIDLInterface callBackAIDLInterface = new CallBackAIDLInterface.Stub() {
@Override
public void callBack() throws RemoteException {
}
};
commonMethod()
点击进入commonMethod()函数,确是MyAIDLInterface接口的commonMethod()函数,但是因为myAIDLInterface对象实际是Proxy类对象,所以实际上是Proxy类中的实现方法,看下具体实现。
@Override public void commonMethod() throws android.os.RemoteException
{
//序列化操作对象Parcel准备
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);//写入描述符
boolean _status = mRemote.transact(Stub.TRANSACTION_commonMethod, _data, _reply, 0);//通过Binder调用服务端onTransact()函数,客户端进入阻塞状态。
if (!_status && getDefaultImpl() != null) {//返回false,代表Binder通信失败,反之成功。
getDefaultImpl().commonMethod();//调用默认实现
return;
}
_reply.readException();//读取服务端执行是否有异常
}
finally {//释放序列化操作对象
_reply.recycle();
_data.recycle();
}
}
因为是IPC的过程,所以传输数据都需要进行序列化,所以开始创建了两个序列化操作对象(_data,_reply)。 然后写入了一段描述符,接着就直接调用了mRemote的transact()函数,传入了一个标识(Stub.TRANSACTION_commonMethod)和两个序列化对象(_data,_reply)以及一个int(flags)值。这个标识就是用于区分函数的,称它为函数标识吧。
static final int TRANSACTION_commonMethod = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_setStringText = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_setObjectMethodIn = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
static final int TRANSACTION_setObjectMethodOut = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
static final int TRANSACTION_setObjectMethodInout = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4);
static final int TRANSACTION_getObjectMethod = (android.os.IBinder.FIRST_CALL_TRANSACTION + 5);
static final int TRANSACTION_register = (android.os.IBinder.FIRST_CALL_TRANSACTION + 6);
static final int TRANSACTION_unregister = (android.os.IBinder.FIRST_CALL_TRANSACTION + 7);
mRemote就是初始化Proxy对象时传入的Binder对象;忘记了可以回顾一下前面asInterface()函数的分析。执行到mRemote.transact()这一步其实就堵塞了,Binder机制会通知服务端Stub对象中的onTransact()函数(mRemote.transact()->服务端Binder.onTransact()->Stub类中重写的onTransact()),现在我们去Stub类中onTransact()函数看下做了什么。
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
java.lang.String descriptor = DESCRIPTOR;
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(descriptor);
return true;
}
case TRANSACTION_commonMethod:
{
data.enforceInterface(descriptor);
this.commonMethod();
reply.writeNoException();
return true;
}
case TRANSACTION_setStringText:
{
data.enforceInterface(descriptor);
java.lang.String _arg0;
_arg0 = data.readString();
this.setStringText(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_setObjectMethodIn:
{
data.enforceInterface(descriptor);
com.zhukai.aidlservice.MethodObject _arg0;
if ((0!=data.readInt())) {
_arg0 = com.zhukai.aidlservice.MethodObject.CREATOR.createFromParcel(data);
}
else {
_arg0 = null;
}
this.setObjectMethodIn(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_setObjectMethodOut:
{
data.enforceInterface(descriptor);
com.zhukai.aidlservice.MethodObject _arg0;
_arg0 = new com.zhukai.aidlservice.MethodObject();
this.setObjectMethodOut(_arg0);
reply.writeNoException();
if ((_arg0!=null)) {
reply.writeInt(1);
_arg0.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
return true;
}
case TRANSACTION_setObjectMethodInout:
{
data.enforceInterface(descriptor);
com.zhukai.aidlservice.MethodObject _arg0;
if ((0!=data.readInt())) {
_arg0 = com.zhukai.aidlservice.MethodObject.CREATOR.createFromParcel(data);
}
else {
_arg0 = null;
}
this.setObjectMethodInout(_arg0);
reply.writeNoException();
if ((_arg0!=null)) {
reply.writeInt(1);
_arg0.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
return true;
}
case TRANSACTION_getObjectMethod:
{
data.enforceInterface(descriptor);
com.zhukai.aidlservice.MethodObject _result = this.getObjectMethod();
reply.writeNoException();
if ((_result!=null)) {
reply.writeInt(1);
_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
return true;
}
case TRANSACTION_register:
{
data.enforceInterface(descriptor);
com.zhukai.aidlservice.CallBackAIDLInterface _arg0;
_arg0 = com.zhukai.aidlservice.CallBackAIDLInterface.Stub.asInterface(data.readStrongBinder());
this.register(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_unregister:
{
data.enforceInterface(descriptor);
com.zhukai.aidlservice.CallBackAIDLInterface _arg0;
_arg0 = com.zhukai.aidlservice.CallBackAIDLInterface.Stub.asInterface(data.readStrongBinder());
this.unregister(_arg0);
reply.writeNoException();
return true;
}
default:
{
return super.onTransact(code, data, reply, flags);
}
}
}
整体看下来,是通过不同的函数标识做了不同的逻辑处理。分析commonMethod()函数,根据函数标识判断是TRANSACTION_commonMethod分支。
case TRANSACTION_commonMethod:
{
data.enforceInterface(descriptor);//对描述符进行了校验
this.commonMethod();//调用了自己的commonMethod()函数,也就是服务端Stub对象的commonMethod()函数。
reply.writeNoException();//写入无异常
return true;
}
首先对描述符进行了校验,再调用了this.commonMethod()函数。这个this就是Stub对象,既调用了服务端Stub对象的commonMethod()函数。后面再写入无异常,返回true代表执行成功。服务端执行完毕,客户端阻塞恢复运行继续执行下面代码。
if (!_status && getDefaultImpl() != null) {
getDefaultImpl().commonMethod();
return;
}
_reply.readException();
失败了一般也是不会有设置默认实现,所以后续就是执行读取服务端写入的异常,进行异常检测,如果服务端写入了异常,那客户端将抛出异常。感兴趣可以点入源码查看一下。这样一次完整的通信就完成了。
注:分析完commonMethod()函数,我们对AIDL基本的通讯逻辑已经清楚了,后续不同类型函数实现只是在处理细节上有所差异,差异都是存在客户端Proxy实现函数和服务端Stub类onTransact()函数中。故后续只分析这两个函数即可,并且直接把客服端和服务端两个函数放在一起,便于直观。
setStringText(String text)
//客户端Proxy类
@Override public void setStringText(java.lang.String text) throws android.os.RemoteException
{
//序列化操作对象Parcel准备
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);//写入描述符
_data.writeString(text);//写入传入的数据
boolean _status = mRemote.transact(Stub.TRANSACTION_setStringText, _data, _reply, 0);//通过Binder调用服务端onTransact()函数,客户端进入阻塞状态。
if (!_status && getDefaultImpl() != null) {//返回false,代表Binder通信失败,反之成功。
getDefaultImpl().setStringText(text);//调用默认实现
return;
}
_reply.readException();//读取服务端执行是否有异常
}
finally {//释放序列化操作对象
_reply.recycle();
_data.recycle();
}
}
//服务端Stub类
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
java.lang.String descriptor = DESCRIPTOR;
switch (code) {
case TRANSACTION_setStringText:
{
data.enforceInterface(descriptor);//对描述符进行了校验
java.lang.String _arg0;
_arg0 = data.readString();//读取客户端写入的数据
this.setStringText(_arg0);//调用自己的函数,并传入读取的数据
reply.writeNoException();//写入无异常
return true;
}
}
}
差异主要是客户端多了一步写入数据,服务端相应的就多了一步读取数据。
void setObjectMethodIn(in MethodObject o)
//客户端Proxy类
@Override public void setObjectMethodIn(com.zhukai.aidlservice.MethodObject o) throws android.os.RemoteException
{
//序列化操作对象Parcel准备
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);//写入描述符
if ((o!=null)) {//数据对象不为null
_data.writeInt(1);//写入1,表示序列化对象不为null
o.writeToParcel(_data, 0);//写入序列化对象
}
else {
_data.writeInt(0);//写入0,表示序列化数据对象为null
}
boolean _status = mRemote.transact(Stub.TRANSACTION_setObjectMethodIn, _data, _reply, 0);//通过Binder调用服务端onTransact()函数,客户端进入阻塞状态。
if (!_status && getDefaultImpl() != null) {//返回false,代表Binder通信失败,反之成功。
getDefaultImpl().setObjectMethodIn(o);//调用默认实现
return;
}
_reply.readException();//读取服务端执行是否有异常
}
finally {//释放序列化操作对象
_reply.recycle();
_data.recycle();
}
}
//服务端Stub类
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
java.lang.String descriptor = DESCRIPTOR;
switch (code) {
case TRANSACTION_setObjectMethodIn:
{
data.enforceInterface(descriptor);//对描述符进行了校验
com.zhukai.aidlservice.MethodObject _arg0;
if ((0!=data.readInt())) {//客户端有写入0或1,非0代表序列化对象不为null
_arg0 = com.zhukai.aidlservice.MethodObject.CREATOR.createFromParcel(data);//进行反序列化
}
else {
_arg0 = null;
}
this.setObjectMethodIn(_arg0);//调用自己的函数,传入数据对象。
reply.writeNoException();//写入无异常
return true;
}
}
}
setObjectMethodIn()函数参数是一个对象类型,并在AIDL文件中进行了in修饰前缀修饰,参数的数据对象只能从客户端传入服务端,所以在逻辑上只在客户端进行了序列化,在服务端进行反序列化,服务端的修改并不能影响到客户端。
setObjectMethodOut(out MethodObject o)
//客户端Proxy类
@Override public void setObjectMethodOut(com.zhukai.aidlservice.MethodObject o) throws android.os.RemoteException
{
//序列化操作对象Parcel准备
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);//写入描述符
boolean _status = mRemote.transact(Stub.TRANSACTION_setObjectMethodOut, _data, _reply, 0);//通过Binder调用服务端onTransact()函数,客户端进入阻塞状态。
if (!_status && getDefaultImpl() != null) {//返回false,代表Binder通信失败,反之成功。
getDefaultImpl().setObjectMethodOut(o);//调用默认实现
return;
}
_reply.readException();//读取服务端执行是否有异常
if ((0!=_reply.readInt())) {//服务端有写入0或1,非0代表序列化对象不为null
o.readFromParcel(_reply);//反序列化修改参数中数据对象o的数据
}
}
finally {//释放序列化操作对象
_reply.recycle();
_data.recycle();
}
}
//服务端Stub类
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
java.lang.String descriptor = DESCRIPTOR;
switch (code) {
case TRANSACTION_setObjectMethodOut:
{
data.enforceInterface(descriptor);//对描述符进行了校验
com.zhukai.aidlservice.MethodObject _arg0;
_arg0 = new com.zhukai.aidlservice.MethodObject();//创建一个数据对象
this.setObjectMethodOut(_arg0);//调用自己的函数,传入刚刚创建的对象。
reply.writeNoException();//写入无异常
if ((_arg0!=null)) {//数据对象不为null
reply.writeInt(1);//写入1,表示序列化数据对象不为null
_arg0.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);//写入序列化对象
}
else {
reply.writeInt(0);//写入0,表示序列化数据对象为null
}
return true;
}
}
}
setObjectMethodOut()函数参数也是一个对象类型,并在AIDL文件中进行了out修饰前缀修饰,客户端参数数据对象无法传输到服务端,所以在客户端调用mRemote.transact()函数之前,并没有进行序列化写入操作;但是因为服务端的修改是可以影响到客户端的,所以在服务端的处理上直接创建了一个数据对象,并调用函数时传入,使服务端进行操作,在方法执行完后,又进行了序列化写入操作。当服务端无异常执行完成后,客户端阻塞停止,反而客户端通过反序列化对原本传入的数据对象进行了数据修改。
setObjectMethodInout(inout MethodObject o)
客户端Proxy类
@Override public void setObjectMethodInout(com.zhukai.aidlservice.MethodObject o) throws android.os.RemoteException
{
//序列化操作类对象Pracel准备
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);//写入描述符
if ((o!=null)) {//数据对象不为null
_data.writeInt(1);//写入1,表示序列化数据对象不为null
o.writeToParcel(_data, 0);//写入序列化对象
}
else {
_data.writeInt(0);//写入0,表示序列化数据对象为null
}
boolean _status = mRemote.transact(Stub.TRANSACTION_setObjectMethodInout, _data, _reply, 0);//通过Binder调用服务端onTransact()函数,客户端进入阻塞状态。
if (!_status && getDefaultImpl() != null) {//返回false,代表Binder通信失败,反之成功。
getDefaultImpl().setObjectMethodInout(o);//调用默认实现
return;
}
_reply.readException();//读取服务端执行是否有异常
if ((0!=_reply.readInt())) {//服务端有写入0或1,非0代表序列化对象不为null
o.readFromParcel(_reply);//反序列化修改参数中数据对象o的数据
}
}
finally {//释放序列化操作对象
_reply.recycle();
_data.recycle();
}
}
//服务端Stub类
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
java.lang.String descriptor = DESCRIPTOR;
switch (code) {
case TRANSACTION_setObjectMethodInout:
{
data.enforceInterface(descriptor);//对描述符进行了校验
com.zhukai.aidlservice.MethodObject _arg0;
if ((0!=data.readInt())) {//客户端有写入0或1,非0代表序列化对象不为null
_arg0 = com.zhukai.aidlservice.MethodObject.CREATOR.createFromParcel(data);//进行反序列化
}
else {
_arg0 = null;
}
this.setObjectMethodInout(_arg0);//调用自己的函数,传入刚刚的数据对象。
reply.writeNoException();//写入无异常
if ((_arg0!=null)) {//数据对象不为null
reply.writeInt(1);//写入1,表示序列化数据对象不为null
_arg0.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);//写入序列化对象
}
else {
reply.writeInt(0);//写入0,表示序列化数据对象为null
}
return true;
}
}
}
setObjectMethodInout()函数参数同样是一个对象类型,并在AIDL文件中进行了inout修饰前缀修饰,参数的数据对象既能传输到服务端,同时服务端对数据对象的修改也能同步到客户端,所以在逻辑处理上客服端在调用mRemote.transact()函数之前,进行了序列化处理,在服务端进行了反序列化处理。服务端在调用自己函数时传入了这个反序列化得来的数据对象,同时函数执行完又将这个数据对象再进行序列化;等到服务端执行完毕后,客户端阻塞停止,客户端也进行一次反序列化,修改了参数传入的数据对象数据。整体上就是前面两个函数的逻辑结合,在客服端到服务端一次序列化和反序列化操作,从服务端回到客户端也是一次序列化和反序列化操作。
MethodObject getObjectMethod()
前面函数都是没有带返回值的,这个函数是无参带返回值。
//客户端Proxy类
@Override public com.zhukai.aidlservice.MethodObject getObjectMethod() throws android.os.RemoteException
{
//序列化操作对象Parcel准备
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
com.zhukai.aidlservice.MethodObject _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);//写入描述符
boolean _status = mRemote.transact(Stub.TRANSACTION_getObjectMethod, _data, _reply, 0);//通过Binder调用服务端onTransact()函数,客户端进入阻塞状态
if (!_status && getDefaultImpl() != null) {//返回false,代表Binder通信失败,反之成功。
return getDefaultImpl().getObjectMethod();//调用默认实现
}
_reply.readException();//读取服务端执行是否有异常
if ((0!=_reply.readInt())) {//服务端有写入0或1,非0代表序列化对象不为null
_result = com.zhukai.aidlservice.MethodObject.CREATOR.createFromParcel(_reply);//进行反序列化
}
else {
_result = null;
}
}
finally {//释放序列化操作对象
_reply.recycle();
_data.recycle();
}
return _result;//返回数据对象
}
//服务端Stub类
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
java.lang.String descriptor = DESCRIPTOR;
switch (code) {
case TRANSACTION_getObjectMethod:
{
data.enforceInterface(descriptor);//进行描述符校验
com.zhukai.aidlservice.MethodObject _result = this.getObjectMethod();//调用自己的函数活的数据对象。
reply.writeNoException();//写入无异常
if ((_result!=null)) {//数据对象不为null
reply.writeInt(1);//写入1,标识序列化数据对象不为null
_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);//进行序列化操作
}
else {
reply.writeInt(0);//写入0,标识序列化数据对象为null
}
return true;
}
}
}
MethodObject getObjectMethod()和setObjectMethodOut(out MethodObject o)函数在逻辑上有些相似,差异是客户端在对服务端写入的序列化对象进行反序列化处理时,因为setObjectMethodOut(out MethodObject o)函数原本参数中就有一个数据对象,所以直接调用了数据对象的readFromParcel()函数,通过反序列化修改了数据对象的数据;而MethodObject getObjectMethod()函数,则是要通过调用createFromParcel()函数,反序列化重新创建一个对象。但两者在实现效果上都是一样的。
register(CallBackAIDLInterface aidl)
//客户端Proxy类
@Override public void register(com.zhukai.aidlservice.CallBackAIDLInterface aidl) throws android.os.RemoteException
{
//序列化操作对象Parcel准备
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);//写入操作符
_data.writeStrongBinder((((aidl!=null))?(aidl.asBinder()):(null)));//写入AIDl类的Binder对象
boolean _status = mRemote.transact(Stub.TRANSACTION_register, _data, _reply, 0);//通过Binder调用服务端onTransact()函数,客户端进入阻塞状态
if (!_status && getDefaultImpl() != null) {//返回false,代表Binder通信失败,反之成功。
getDefaultImpl().register(aidl);//调用默认实现
return;
}
_reply.readException();//读取服务端操作有无异常
}
finally {//释放序列化操作对象
_reply.recycle();
_data.recycle();
}
}
//服务端Stub类
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
java.lang.String descriptor = DESCRIPTOR;
switch (code) {
case TRANSACTION_register:
{
data.enforceInterface(descriptor);//对描述符进行校验
com.zhukai.aidlservice.CallBackAIDLInterface _arg0;
//读取客户端传入的Binder对象并通过Stub.asInterface()函数获取了Proxy代理对象
_arg0 = com.zhukai.aidlservice.CallBackAIDLInterface.Stub.asInterface(data.readStrongBinder());
this.register(_arg0);//调用自己的方法,传入代理对象
reply.writeNoException();//写入无异常
return true;
}
}
}
register(CallBackAIDLInterface aidl)函数参数是AIDL类类型,在实际的逻辑中并不是传入的本身,而是传入了自己的Binder对象(既客户端创建的Stub对象的Binder对象,此时客户端在角色上变成了服务端)。服务端读取了传入的Binder对象后,通过Stub.asInterface(data.readStrongBinder())函数完成了Proxy代理对象的获取(此时服务端在角色上变成了客户端),再调用自己的函数,把这个代理对象给服务端使用。
unregister(CallBackAIDLInterface aidl)函数不需要做额外的讲解,跟register(CallBackAIDLInterface aidl)是一样的。
四、总结
看完这个系列,希望能让大家对AIDL有一个较深入的理解,篇幅较长,十分感谢大家能耐心看完!欢迎关注点赞,继续阅读AIDL系列文章,后续将努力学习输出更高质量文章。