AOSP-AIDL 分析

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
  1. 要声明(或者是手动diy创建)AIDL性质的接口,就要继承IInterface
  2. 代表远程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.调用方法
​
}
相关推荐
千里马学框架3 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台3 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone3 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc3 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo3 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077003 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼4 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone4 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen4 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone4 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui