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 小时前
[cisco 模拟器] ftp服务器配置
android·运维·服务器
van叶~3 小时前
探索未来编程:仓颉语言的优雅设计与无限可能
android·java·数据库·仓颉
Crossoads7 小时前
【汇编语言】端口 —— 「从端口到时间:一文了解CMOS RAM与汇编指令的交汇」
android·java·汇编·深度学习·网络协议·机器学习·汇编语言
li_liuliu8 小时前
Android4.4 在系统中添加自己的System Service
android
C4rpeDime10 小时前
自建MD5解密平台-续
android
鲤籽鲲12 小时前
C# Random 随机数 全面解析
android·java·c#
m0_5485147716 小时前
2024.12.10——攻防世界Web_php_include
android·前端·php
凤邪摩羯16 小时前
Android-性能优化-03-启动优化-启动耗时
android
凤邪摩羯16 小时前
Android-性能优化-02-内存优化-LeakCanary原理解析
android
喀什酱豆腐17 小时前
Handle
android