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.调用方法
​
}
相关推荐
大白要努力!1 小时前
Android opencv使用Core.hconcat 进行图像拼接
android·opencv
天空中的野鸟2 小时前
Android音频采集
android·音视频
小白也想学C3 小时前
Android 功耗分析(底层篇)
android·功耗
曙曙学编程3 小时前
初级数据结构——树
android·java·数据结构
闲暇部落6 小时前
‌Kotlin中的?.和!!主要区别
android·开发语言·kotlin
诸神黄昏EX8 小时前
Android 分区相关介绍
android
大白要努力!9 小时前
android 使用SQLiteOpenHelper 如何优化数据库的性能
android·数据库·oracle
Estar.Lee9 小时前
时间操作[取当前北京时间]免费API接口教程
android·网络·后端·网络协议·tcp/ip
Winston Wood9 小时前
Perfetto学习大全
android·性能优化·perfetto
Dnelic-12 小时前
【单元测试】【Android】JUnit 4 和 JUnit 5 的差异记录
android·junit·单元测试·android studio·自学笔记