AIDL源码生成分析
定义接口
csharp
interface PersonAidl {
int add(in int x, in int y);
Person loadPerson();
}
跨进程service
kotlin
open class ITestService : Service() {
override fun onBind(intent: Intent): IBinder {
return Stub()
}
}
生成类和拆解
java
package com.nuonuo.workmangertest;
public interface PersonAidl extends android.os.IInterface
{
public static class Default implements com.nuonuo.workmangertest.PersonAidl
{
@Override public int add(int x, int y) throws android.os.RemoteException
{
return 0;
}
@Override public android.app.Person loadPerson() throws android.os.RemoteException
{
return null;
}
@Override
public android.os.IBinder asBinder() {
return null;
}
}
public static abstract class Stub extends android.os.Binder implements com.nuonuo.workmangertest.PersonAidl
{
private static final java.lang.String DESCRIPTOR = "com.nuonuo.workmangertest.PersonAidl";
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
public static com.nuonuo.workmangertest.PersonAidl asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.nuonuo.workmangertest.PersonAidl))) {
return ((com.nuonuo.workmangertest.PersonAidl)iin);
}
return new com.nuonuo.workmangertest.PersonAidl.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_add:
{
data.enforceInterface(descriptor);
int _arg0;
_arg0 = data.readInt();
int _arg1;
_arg1 = data.readInt();
int _result = this.add(_arg0, _arg1);
reply.writeNoException();
reply.writeInt(_result);
return true;
}
case TRANSACTION_loadPerson:
{
data.enforceInterface(descriptor);
android.app.Person _result = this.loadPerson();
reply.writeNoException();
if ((_result!=null)) {
reply.writeInt(1);
_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
return true;
}
default:
{
return super.onTransact(code, data, reply, flags);
}
}
}
private static class Proxy implements com.nuonuo.workmangertest.PersonAidl
{
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;
}
@Override public int add(int x, int y) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(x);
_data.writeInt(y);
boolean _status = mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
return getDefaultImpl().add(x, y);
}
_reply.readException();
_result = _reply.readInt();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override public android.app.Person loadPerson() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
android.app.Person _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
boolean _status = mRemote.transact(Stub.TRANSACTION_loadPerson, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
return getDefaultImpl().loadPerson();
}
_reply.readException();
if ((0!=_reply.readInt())) {
_result = android.app.Person.CREATOR.createFromParcel(_reply);
}
else {
_result = null;
}
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
public static com.nuonuo.workmangertest.PersonAidl sDefaultImpl;
}
static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_loadPerson = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
public static boolean setDefaultImpl(com.nuonuo.workmangertest.PersonAidl 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.nuonuo.workmangertest.PersonAidl getDefaultImpl() {
return Stub.Proxy.sDefaultImpl;
}
}
public int add(int x, int y) throws android.os.RemoteException;
public android.app.Person loadPerson() throws android.os.RemoteException;
}
Stub 类
java
public static abstract class Stub extends android.os.Binder implements com.nuonuo.workmangertest.PersonAidl
{
private static final java.lang.String DESCRIPTOR = "com.nuonuo.workmangertest.PersonAidl";
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
public static com.nuonuo.workmangertest.PersonAidl asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.nuonuo.workmangertest.PersonAidl))) {
return ((com.nuonuo.workmangertest.PersonAidl)iin);
}
return new com.nuonuo.workmangertest.PersonAidl.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_add:
{
data.enforceInterface(descriptor);
int _arg0;
_arg0 = data.readInt();
int _arg1;
_arg1 = data.readInt();
int _result = this.add(_arg0, _arg1);
reply.writeNoException();
reply.writeInt(_result);
return true;
}
case TRANSACTION_loadPerson:
{
data.enforceInterface(descriptor);
android.app.Person _result = this.loadPerson();
reply.writeNoException();
if ((_result!=null)) {
reply.writeInt(1);
_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
return true;
}
default:
{
return super.onTransact(code, data, reply, flags);
}
}
}
static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_loadPerson = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
public static boolean setDefaultImpl(com.nuonuo.workmangertest.PersonAidl 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.nuonuo.workmangertest.PersonAidl getDefaultImpl() {
return Stub.Proxy.sDefaultImpl;
}
}
Default
java
public static class Default implements com.nuonuo.workmangertest.PersonAidl
{
@Override public int add(int x, int y) throws android.os.RemoteException
{
return 0;
}
@Override public android.app.Person loadPerson() throws android.os.RemoteException
{
return null;
}
@Override
public android.os.IBinder asBinder() {
return null;
}
}
proxy
ini
private static class Proxy implements com.nuonuo.workmangertest.PersonAidl
{
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;
}
@Override public int add(int x, int y) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(x);
_data.writeInt(y);
boolean _status = mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
return getDefaultImpl().add(x, y);
}
_reply.readException();
_result = _reply.readInt();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override public android.app.Person loadPerson() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
android.app.Person _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
boolean _status = mRemote.transact(Stub.TRANSACTION_loadPerson, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
return getDefaultImpl().loadPerson();
}
_reply.readException();
if ((0!=_reply.readInt())) {
_result = android.app.Person.CREATOR.createFromParcel(_reply);
}
else {
_result = null;
}
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
public static com.nuonuo.workmangertest.PersonAidl sDefaultImpl;
}
aidl到底是什么
aidl文件其实就是一个方法定义,通过as内部的aidl.exe 将代码编译为一个java类,
方便底层调用跨进程
类文件解析
可以通过实现对应接口的类看到生成三个类
Stub.Proxy.Default
核心类和方法的作用
Binder
为什么要继承binder,因为跨进程 service 的onBind 要返回binder,而且内部封装了很多方法,不用再去写了。直接继承IBinder也行,但是要写的办法太多了
Parcel
跨进程传递使用,可以写基本类型和序列化类型。使用的时候要捕获异常。
scss
Parcel.obtain()//初始化
to.recycle()//回收
IInterface
- 要声明(或者是手动diy创建)AIDL性质的接口,就要继承
IInterface
- 代表远程server对象具有的能力,具体是由
Binder
表达出这个能力。
IBinder.transact
perl
/**
**
code 对应调用方法
data 传递给服务端
replay 服务端使用reply回传
flags 0 -> normal 同步 等待完成
FLAG_ONEWAY oneway 异步
/
transact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags)
attachInterface
Stub 在构造函数中传递this,和标识, 保存在Binder内,这样在调用的时候可以asInterface区分是本地还是跨进程
Proxy根本就没调用,所以获取到的就是null
less
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
public void attachInterface(@Nullable IInterface owner, @Nullable String descriptor) {
mOwner = owner;
mDescriptor = descriptor;
}
asInterface
我们在使用aidl的时候 一般就会调用对应aidl文件的
XXXAidl.Stub.asInterface(service)
这里其实就是获取本地或者异地的服务。
typescript
public static com.nuonuo.workmangertest.PersonAidl asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.nuonuo.workmangertest.PersonAidl))) {
return ((com.nuonuo.workmangertest.PersonAidl)iin);
}
return new com.nuonuo.workmangertest.PersonAidl.Stub.Proxy(obj);
}
attachInterface 方法里 Stub 将自己和标识传入,所以不为null,有标识则调用Stub
否则就将底层代理对象调用出来给客户端使用。
queryLocalInterface
如果符合 条件,则将本地存入的mOwner返回,可以理解为本地Service
less
/**
* Use information supplied to attachInterface() to return the
* associated IInterface if it matches the requested
* descriptor.
*/
public @Nullable IInterface queryLocalInterface(@NonNull String descriptor) {
if (mDescriptor != null && mDescriptor.equals(descriptor)) {
return mOwner;
}
return null;
}
总体流程
kotlin
Stub 启动 构造函数调用 attachInterface(this,DESCRIPTOR) 将自己和标识保存
bindService()--->ServiceConnection.onServiceConnected{
val xService= XXXAidl.Stub.asInterface(service)
--->
{
--> null 返回null
-->queryLocalInterface()service 查下标识和mOwner不为null
返回mOwner,
--->mOwner不是null么而且是实现当前AIDL么{
是 ->那么肯定是本地Service 返回本地Service
否->走底层代理,用Parcel 传递数据
}
}
xService.调用方法
}