文章目录

  • 前言
  • 一、分析 AIDL 文件生成的 Java 源文件
    • 1、IMyAidlInterface.java 中的类结构
    • 2、DESCRIPTOR 描述符
    • 3、Stub 构造方法
    • 4、Stub.asInterface 方法
    • 5、Stub.onTransact 方法
    • 6、Stub.Proxy 代理类

前言

在上一篇博客 【Binder 机制】AIDL 分析 ( 创建 AIDL 文件 | 创建 Parcelable 类 | AIDL 中使用 Parcelable 类 | 编译工程生成 AIDL 对应的Java源文件 ) 创建了 AIDL 文件 , 并编译生成了 AIDL 文件对应的 Java 源文件 , 现在开始分析生成在 " AIDL_Demo\app\build\generated\aidl_source_output_dir\debug\out\kim\hsl\aidl_demo " 目录 中的 " IMyAidlInterface.java " 源文件 ;

一、分析 AIDL 文件生成的 Java 源文件


分析 【Binder 机制】AIDL 分析 ( 创建 AIDL 文件 | 创建 Parcelable 类 | AIDL 中使用 Parcelable 类 | 编译工程生成 AIDL 对应的Java源文件 ) 二、编译工程生成 AIDL 文件对应的 Java 源文件 2、生成的 AIDL 对应 Java 源文件 章节中 , 编译 AIDL 文件生成的源码 ;

1、IMyAidlInterface.java 中的类结构

生成的类是 IMyAidlInterface.java , 继承了 android.os.IInterface 接口 ;

public interface IMyAidlInterface extends android.os.IInterface

其中定义了两个内部类 ,

  • 内部类 1 1 1 如下 : IMyAidlInterface 的默认实现 ;
  /** Default implementation for IMyAidlInterface. */public static class Default implements kim.hsl.aidl_demo.IMyAidlInterface
  • 内部类 2 2 2 如下 : IPC 机制的本地实现 ;
  /** Local-side IPC implementation stub class. */public static abstract class Stub extends android.os.Binder implements kim.hsl.aidl_demo.IMyAidlInterface

2、DESCRIPTOR 描述符

在 Stub 内部类中 , 定义的常量 DESCRIPTOR 是 AIDL 文件的 " 包名.类名 " , 用于查找 Binder 用的 ;

private static final java.lang.String DESCRIPTOR = "kim.hsl.aidl_demo.IMyAidlInterface";

3、Stub 构造方法

Stub 的构造方法中 , 调用了 BinderattachInterface 方法 , 传入了 AIDL 文件的全类名 ; 作用是将该 AIDL 接口与 Binder 进行关联 ;

    /** Construct the stub at attach it to the interface. */public Stub(){this.attachInterface(this, DESCRIPTOR);}

4、Stub.asInterface 方法

Stub 中定义了 asInterface 方法 , 该方法的作用是将 android.os.IBinder 对象转为 AIDL 接口对象 ; 传入的 DESCRIPTOR 描述符 , 用于描述用户想要哪个 Binder , android.os.IBinder 对象调用 queryLocalInterface 方法 , 检查本地服务是否存在 ;

  • 如果可以找到本地服务对应的接口 , 可以直接返回本地服务 ;
  • 如果没有找到本地服务 , 就会返回一个 Stub 代理 ;

详细的过程参考下面的代码 :

    /*** 将IBinder对象强制转换为kim.hsl.aidl_demo.IMyAidlInterface接口,必要时生成代理。*/public static kim.hsl.aidl_demo.IMyAidlInterface asInterface(android.os.IBinder obj){if ((obj==null)) {return null;}// 传入 DESCRIPTOR 描述符 , 用于描述用户想要哪个 Binder// android.os.IBinder 对象调用 queryLocalInterface 方法 , 检查本地服务android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);// 如果可以找到本地服务对应的接口 , 可以直接返回本地服务 if (((iin!=null)&&(iin instanceof kim.hsl.aidl_demo.IMyAidlInterface))) {return ((kim.hsl.aidl_demo.IMyAidlInterface)iin);}// 如果没有找到本地服务 , 就会返回一个 Stub 代理 return new kim.hsl.aidl_demo.IMyAidlInterface.Stub.Proxy(obj);}

IBinder 是一个接口 , 其中定义了一堆常量标识符 ;

transact 方法对应 Binder 底层发起 IPC 的请求函数 ;

public interface IBinder {/*** 对对象执行常规操作。* * @param code 要执行的操作。*       这应该是介于{@link #FIRST_CALL_TRANSACTION}和{@link #LAST_CALL_TRANSACTION}之间的数字。* @param data 要发送到目标的封送数据。不能为null。*        如果不发送任何数据,则必须创建此处给出的空地块。* @param reply 要从目标接收的封送数据。如果您对返回值不感兴趣,则可能为null。* @param flags 其他操作标志。正常RPC为0,单向RPC为{@link#FLAG_ONEWAY}。** @return 从{@link Binder#onTransact}返回结果。成功的调用通常返回true;false通常表示未理解事务代码。*/public boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags)throws RemoteException;
}

5、Stub.onTransact 方法

onTransact 方法用于处理不同的 IPC 请求 , 根据不同的值 , 处理不同的 IPC 请求 ;

要处理的 IPC 请求对应的常量值定义 : 将要调用的方法变成 int 类型的 ID 常量值 , 根据传入的常量值执行相应的方法 , 方便 IPC 跨进程调用 ;

    static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);static final int TRANSACTION_addStudent = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);static final int TRANSACTION_getStudents = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);

TRANSACTION_basicTypes 常量值对应如下 AIDL 方法 :

    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,double aDouble, String aString);

TRANSACTION_addStudent 常量值对应如下 AIDL 方法 :

    /*** in 写入, out 输出, inout 写入和输出*/void addStudent(inout Student student);

TRANSACTION_getStudents 常量值对应如下 AIDL 方法 :

    /*** 获取 Student 集合*/List<Student> getStudents();

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_basicTypes:{data.enforceInterface(descriptor);int _arg0;_arg0 = data.readInt();long _arg1;_arg1 = data.readLong();boolean _arg2;_arg2 = (0!=data.readInt());float _arg3;_arg3 = data.readFloat();double _arg4;_arg4 = data.readDouble();java.lang.String _arg5;_arg5 = data.readString();this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5);reply.writeNoException();return true;}case TRANSACTION_addStudent:{data.enforceInterface(descriptor);kim.hsl.aidl_demo.Student _arg0;if ((0!=data.readInt())) {_arg0 = kim.hsl.aidl_demo.Student.CREATOR.createFromParcel(data);}else {_arg0 = null;}this.addStudent(_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_getStudents:{data.enforceInterface(descriptor);java.util.List<kim.hsl.aidl_demo.Student> _result = this.getStudents();reply.writeNoException();reply.writeTypedList(_result);return true;}default:{return super.onTransact(code, data, reply, flags);}}}

主要分析 TRANSACTION_addStudent 方法 : kim.hsl.aidl_demo.Student 类中 , 实现了序列化与反序列化的方法 , 这里传递参数时 , _arg0 = kim.hsl.aidl_demo.Student.CREATOR.createFromParcel(data) , 调用了 Student 类的反序列化方法 , 将参数先进行反序列化 , 然后赋值给 arg0 , 这样才能得到 Student 类型对象 ;

调用 this.addStudent(_arg0); 代码执行该方法 , 然后通过返回参数 replay , 将结果写回给调用者用户空间进程 ;

        case TRANSACTION_addStudent:{data.enforceInterface(descriptor);kim.hsl.aidl_demo.Student _arg0;if ((0!=data.readInt())) {_arg0 = kim.hsl.aidl_demo.Student.CREATOR.createFromParcel(data);}else {_arg0 = null;}this.addStudent(_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;}

6、Stub.Proxy 代理类

Stub 类有一个内部 Proxy 代理类 , 只有当前服务非本地服务 , 即跨进程远程服务时 , 才会使用这个类 ;

private static class Proxy implements kim.hsl.aidl_demo.IMyAidlInterface

在代理类中也需要 AIDL 描述符 , 在 getInterfaceDescriptor 方法中 , 传入 DESCRIPTOR 描述符 ;

      public java.lang.String getInterfaceDescriptor(){return DESCRIPTOR;}

代理类内容 :

    private static class Proxy implements kim.hsl.aidl_demo.IMyAidlInterface{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 basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) 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.writeInt(anInt);_data.writeLong(aLong);_data.writeInt(((aBoolean)?(1):(0)));_data.writeFloat(aFloat);_data.writeDouble(aDouble);_data.writeString(aString);boolean _status = mRemote.transact(Stub.TRANSACTION_basicTypes, _data, _reply, 0);if (!_status && getDefaultImpl() != null) {getDefaultImpl().basicTypes(anInt, aLong, aBoolean, aFloat, aDouble, aString);return;}_reply.readException();}finally {_reply.recycle();_data.recycle();}}/*** in 写入, out 输出, inout 写入和输出*/@Override public void addStudent(kim.hsl.aidl_demo.Student student) 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 ((student!=null)) {_data.writeInt(1);student.writeToParcel(_data, 0);}else {_data.writeInt(0);}// 调用 Binder 的 transact 方法 boolean _status = mRemote.transact(Stub.TRANSACTION_addStudent, _data, _reply, 0);if (!_status && getDefaultImpl() != null) {getDefaultImpl().addStudent(student);return;}_reply.readException();if ((0!=_reply.readInt())) {student.readFromParcel(_reply);}}finally {_reply.recycle();_data.recycle();}}/*** 获取 Student 集合*/@Override public java.util.List<kim.hsl.aidl_demo.Student> getStudents() throws android.os.RemoteException{android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();java.util.List<kim.hsl.aidl_demo.Student> _result;try {_data.writeInterfaceToken(DESCRIPTOR);boolean _status = mRemote.transact(Stub.TRANSACTION_getStudents, _data, _reply, 0);if (!_status && getDefaultImpl() != null) {return getDefaultImpl().getStudents();}_reply.readException();_result = _reply.createTypedArrayList(kim.hsl.aidl_demo.Student.CREATOR);}finally {_reply.recycle();_data.recycle();}return _result;}public static kim.hsl.aidl_demo.IMyAidlInterface sDefaultImpl;}

Binder 的 transact 方法 ; 进入该方法后 , 会将原来的线程挂起 , 直到返回 , 原来的线程才会继续执行 , 这里非常容易出现 ANR ;

/*** 远程对象的基类,由{@link IBinder}定义的轻量级远程过程调用机制的核心部分。* 此类是IBinder的一个实现,它提供了此类对象的标准本地实现。** <p>大多数开发人员不会直接实现这个类,* 而是使用<a href=“{@docRoot}guide/components/aidl.html”>aidl</a>工具来描述所需的接口,* 让它生成适当的Binder子类。* 然而,您可以直接从Binder派生来实现您自己的定制RPC协议,* 或者直接实例化一个原始Binder对象,将其用作可以跨进程共享的令牌。** <p>这个类只是一个基本的IPC原语;* 它对应用程序的生命周期没有影响,并且只有创建它的进程继续运行时才有效。* 要正确使用此功能,您必须在顶级应用程序组件(a{@link android.app.Service}、* {@link android.app.Activity}或{@link android.content.ContentProvider})* 的上下文中执行此操作,该组件应保持运行。</p>** <p>您必须记住流程可能会消失的情况,因此需要稍后重新创建新的活页夹,* 并在流程再次启动时重新附加它。* 例如,如果您在{@link android.app.Activity}中使用此函数,* 则您的活动的进程可能会在活动未启动时被终止;* 如果以后重新创建活动,则需要创建新的活页夹,* 并再次将其交回正确的位置;* 您需要注意的是,您的流程可能由于其他原因(例如接收广播)而启动,* 这将不涉及重新创建活动,因此运行其代码以创建新的绑定。</p>** @see IBinder*/
public class Binder implements IBinder {/*** 默认实现回放地块并调用onTransact。在远程端,transact调用绑定器来执行IPC。*/public final boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply,int flags) throws RemoteException {if (false) Log.v("Binder", "Transact: " + code + " to " + this);if (data != null) {data.setDataPosition(0);}boolean r = onTransact(code, data, reply, flags);if (reply != null) {reply.setDataPosition(0);}return r;}
}

【Binder 机制】AIDL 分析 ( 分析 AIDL 文件生成的 Java 源文件 | Binder | IBinder | Stub | Proxy )相关推荐

  1. cmd 根据xsd文件生成webservice java客户端代码

    根据xsd 转换成java 对象, jdk1.7 自带 xjc 命令,可以根据xjc 命令直接转换成 java 对象 命令格式:xjc -d dir -p packgeName -verbose xx ...

  2. 【Binder 机制】AIDL 分析 ( 创建 AIDL 文件 | 创建 Parcelable 类 | AIDL 中使用 Parcelable 类 | 编译工程生成 AIDL 对应的Java源文件 )

    文章目录 一.创建 AIDL 文件 1.创建 AIDL 目录 2.创建 AIDL 文件 3.创建 Parcelable 类 4.AIDL 目录下声明 Parcelable 类 5.AIDL 中使用 P ...

  3. 【Binder 机制】AIDL 分析 ( AIDL 通信完整流程梳理 )

    文章目录 AIDL 跨进程通信完整流程梳理 1.AIDL 文件编译 2.注册服务 3.IMyAidlInterface.Stub.asInterface 方法获取远程服务 4.IMyAidlInter ...

  4. 一文分析Binder机制和AIDL的理解

    为什么要去理解Android的进程间通信机制 对于Android开发工程师来说,如果不去理解进程间通信机制也可以使用系统提供的API完成应用开发,但如果想要达到更高的层级,那么就不能简单只会调用API ...

  5. 从AIDL一窥Android Binder机制

    Binder机制在Android系统中地位毋庸置疑,system_server就通过Binder来实现进程间的通信,从而达到管理.调用一系列系统服务的能力.本文就AIDL来解读一下Binder机制的. ...

  6. Binder机制之AIDL

    ** 简单说一下,第一次写文章,有点不习惯,从下定决心看一看Android的系统源码开始,看过了简单的系统源码如何修改编译,简单了解了点Linux内核驱动的一点点知识,随后跟着老罗的Android系统 ...

  7. binder 从c到java_Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析...

    在前面几篇文章中,我们详细介绍了Android系统进程间通信机制Binder的原理,并且深入分析了系统提供的Binder运行库和驱动程序的源代码.细心的读者会发现,这几篇文章分析的Binder接口都是 ...

  8. 理解 Android 的 Binder 机制

    Binder机制的工作流程 1.客户端获取服务端的代理对象(proxy).我们需要明确的是客户端进程并不能直接操作服务端中的方法,如果要操作服务端中的方法,那么有一个可行的解决方法就是在客户端建立一个 ...

  9. 理解Android Binder机制(3/3):Java层

    本文是Android Binder机制解析的第三篇,也是最后一篇文章.本文会讲解Binder Framework Java部分的逻辑. Binder机制分析的前面两篇文章,请移步这里: 理解Andro ...

最新文章

  1. RMAN duplicate database到新主机
  2. boost::signals2::trackable相关的测试程序
  3. Pytorch自定义Dataset和DataLoader去除不存在和空的数据
  4. 45张令程序员泪流满面的趣图
  5. 优化 .NET Core logging 中的泛型 logger
  6. python没有代码提示怎么设置_Python Kite 使用教程 轻量级代码提示
  7. mysql 优化 系统_MySQL 优化(一)
  8. Documentum之基础(2)
  9. php socket 执行,PHP异步调用socket实现代码
  10. SwiftyJSON 对网络请求来的数据进行解析或者转为modul
  11. 嵌入式Linux系统的指纹识别,嵌入式指纹识别系统设计
  12. 天玑9200领跑背后,高端芯片掀起蝴蝶效应
  13. 安兔兔html5测试跑分榜,2021年最新安兔兔手机性能跑分排行榜
  14. 如何将eslipse的背景色变为暗黑色
  15. FlinkSQL 读写 MySQL
  16. python面向对象编程实例pdf_Python面向对象编程指南 ([美]StevenFLott洛特) 中文pdf扫描版[52MB]...
  17. shell softech 面料_户外软壳面料及各品牌的技术
  18. DataStory X Kungfu | DemoDay亮点大揭秘
  19. 32位驱动安装到64位操作系统时出错
  20. CodeForces 1000A Codehorses T-shirts

热门文章

  1. Intel 内部指令---AVX编程基础
  2. 二叉树:给后序中序遍历,求前序
  3. linux中grep的用法
  4. SftpGo:一款高性能的sftp server服务
  5. 打印0-100所有3的倍数的数字
  6. 驱动方腔流SIMPLE方法
  7. 关于resharper激活
  8. 像素风放置类游戏-突袭盛宴Raid Party
  9. 送书【新书】 |《Git从入门到精通》
  10. 小论工具类App的盈利之道