使用AIDL分析Binder的工作机制

在aidl中也可以自定义类型。

写两个aidl文件:

IBookManager.aidl

interface IBookManager {
    void add(in Book book);
    List<Book> getBookList();
}

在aidl中声明Book,Book.aidl

parcelable Book;

在服务端,通过Binder返回远程服务对象Stub。而这个Stub实现了aidl接口中的内容并继承Binder。

而在客户端,通过绑定一个远程服务,在服务连接成功后,得到这个远程服务对象Stub。用一个aidl接口去引用。

这就是利用Service进行IPC的大概内容。

观察aidl文件编译后的java文件的内容:

package com.asule.cn;
public interface IBookManager extends android.os.IInterface{

    //我们在aidl接口
    public java.util.List<com.asule.cn.Book> getBookList() throws android.os.RemoteException;
    public void add(com.asule.cn.Book book) throws android.os.RemoteException;

    //-----------------Stub----------------------->
    public static abstract class Stub extends android.os.Binder implements com.asule.cn.IBookManager{

        static final int TRANSACTION_getBookList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);

        //binder的唯一标识
        private static final java.lang.String DESCRIPTOR = "com.asule.cn.IBookManager";

        public Stub(){
            this.attachInterface(this, DESCRIPTOR);
        }

        public static com.asule.cn.IBookManager asInterface(android.os.IBinder obj){
            if ((obj==null)) {
                return null;
            }

            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin!=null)&&(iin instanceof com.asule.cn.IBookManager))) {
                return ((com.asule.cn.IBookManager)iin);
            }
            return new com.asule.cn.IBookManager.Stub.Proxy(obj);
        }

        //返回Stub句柄
        @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{
            switch (code)
            {
                case INTERFACE_TRANSACTION:{
                    reply.writeString(DESCRIPTOR);
                    return true;
                }
                case TRANSACTION_getBookList:{
                    data.enforceInterface(DESCRIPTOR);
                    java.util.List<com.asule.cn.Book> _result = this.getBookList();
                    reply.writeNoException();
                    reply.writeTypedList(_result);
                    return true;
                }
                case TRANSACTION_addBook:{
                    data.enforceInterface(DESCRIPTOR);
                    com.asule.cn.Book _arg0;
                    if ((0!=data.readInt())) {
                        _arg0 = com.asule.cn.Book.CREATOR.createFromParcel(data);
                    }
                    else {
                        _arg0 = null;
                    }
                    this.addBook(_arg0);
                    reply.writeNoException();
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
        }

        //-----------------Proxy----------------------->
        //Stub的内部类Proxy
        private static class Proxy implements com.asule.cn.IBookManager{
            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 java.util.List<com.asule.cn.Book> getBookList() throws android.os.RemoteException{
                //
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                java.util.List<com.asule.cn.Book> _result;

                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.createTypedArrayList(com.asule.cn.Book.CREATOR);
                }
                finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }

            @Override
            public void add(com.asule.cn.Book book) throws android.os.RemoteException{
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                if ((book!=null)) {
                    _data.writeInt(1);
                    book.writeToParcel(_data, 0);
                }
                else {
                    _data.writeInt(0);
                }

                mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0);
                _reply.readException();
                }
                finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }
        }
        //<-----------------Proxy-----------------------
    }
    //<-----------------Stub-----------------------
}

aidl接口和aidl文件中的内容一致。有两个抽象方法,这就是在aidl文件中定义的方法。

可以发现Stub实现了aidl接口,继承自Binder。

Stub中的两个final类型的静态变量

TRANSACTION_getBookList和TRANSACTION_add

DESCRIPTOR:Stub的唯一标识

先前说,在客户端通过asInterface,把获取的Binder对象转换为Stub远程服务实例,通过一个aidl的接口引用。

但asInterface返回的却不一定是Stub。

在此方法中,会判断客户端和服务端是否位于同一个进程,如果是,返回的是stub对象本身,否则返回的是Stub的Proxy。

在代理模式中,代理Proxy和真实对象往往实现同一个接口,代理对象握有真实对象的引用,以便操作真实对象。

Proxy同样实现了aidl接口,把Stub对象实例传递到Proxy中。

当客户端调用getBookList,实际调用的是Proxy中的getBookList。在方法中,

声明了Parcel的输入对象_data,Parcel的输出对象_reply。

调用transact方法来发起RPC(远程过程调用)请求,同时当前线程挂起,然后服务端的Stub的onTransact执行。(onTransact运行在Binder线程池中)

在onTransact中通过code判断是哪个方法执行,然后就会执行Stub的getBookList方法。当方法执行完毕后,会把结果写入到reply中,返回true表示客户端的远程调用成功,否则失败。

而直到RPC结束,客户端的线程才继续执行,从_reply中取出RPC的返回结果,最后返回_reply中的数据。



当足够了解了Binder,其实也可以不借助aidl工具。写aidl的目的只是为了更方便更快速的实现Binder。

不写aidl的话,需要手写接口,Stub,Proxy。在客户端同样也不需要写aidl,直接拷贝手写的java文件。

时间: 2024-10-08 00:31:01

使用AIDL分析Binder的工作机制的相关文章

Binder的工作机制浅析

在Android开发中,Binder主要用于Service中,包括AIDL和Messenger,其中Messenger的底层实现就是AIDL,所以我们这里通过AIDL来分析一下Binder的工作机制. 一.在Android Studio中建立AIDL 首先,我们需要建立一个AIDL 1.在建立了对应的实现Parcelable接口的实体类和AIDL接口后,文件结构如下: 2.点击clean Project/reBuild Project,出现如下错误:提示无法找到Book实体类. 3.解决方案 这

Android IPC机制—Binder的工作机制

进程和线程的关系 IPC机制即为跨进程通信,是inter-Process Communication的缩写.是指两个进程之间进行通信.在说进程通信之前,我们的弄明白什么是线程,什么是进程.进程和线程是两个截然不同的概念.按照操作系统中的描述,线程是CPU调度的最小单位,同时线程也是一种有限的系统资源.而进程一般是指一个执行单元,在pc端或者移动端上是指一个程序或者一个应用.一个进程中可以包含一个或者是多个线程.所以他们的关系应该是包含和被包含的关系. 跨进程的种类 在Android中跨进程通信的

从Android源码的角度分析Binder机制

IPC 为了弄懂IPC的来龙去脉,我将从以下三个方面为大家来讲解,希望对大家理解IPC会有帮助 什么是IPC IPC是Inter Process Communication的缩写,其意思就是进程间的通信,也就是两个进程之间的通信过程.我们都知道在Android系统中,每个应用都运行在一个进程上,具有自己的DVM实例,而且进程之间是相互隔离的,也就是说各个进程之间的数据是互相独立,互不影响的,而如果一个进程崩溃了,也不会影响到另一个进程.采取这样的设计是有一定道理的,例如这样的前提下将互相不影响的

Android7.0 Vold 进程工作机制分析之整体流程

Android7.0 Vold 进程工作机制分析之整体流程 一.Vold简介 Vold是Volume Daemon的缩写,负责管理和控制Android平台外部存储设备,包括SD插拨.挂载.卸载.格式化等.它是通过init进程解析init.rc脚本所启动的进程.它处于Native层. 二.基础架构 这里引用Gityuan博客的一张图. SystermServer进程和Vold进程是通过Socket进行通信的,Vold进程和Kernel是通过Netlink 进行通信的,Netlink 是一种特殊的S

Java IO工作机制分析

Java的IO类都在java.io包下,这些类大致可分为以下4种: 基于字节操作的 I/O 接口:InputStream 和 OutputStream 基于字符操作的 I/O 接口:Writer 和 Reader 基于磁盘操作的 I/O 接口:File 基于网络操作的 I/O 接口:Socket 1 IO类库的基本结构 1.1 基于字节操作的IO接口 基于字节操作的IO接口分别是InputStream和OutputStream,InputStream的类结构图如下所示: 同InputStream

深入源码分析Handler的消息处理机制

学习Android的同学注意了!!! 学习过程中遇到什么问题或者想获取学习资源的话,欢迎加入Android学习交流群,群号码:364595326  我们一起学Android! handler的消息处理有三个核心类:Looper,Handler和Message.其实还有一个Message Queue(消息队列),但是MessageQueue被封装到Looper里面了,我们不会直接与MessageQueue打交道,因此我没将其作为核心类.下面一一介绍: 线程的魔法师Looper Looper的字面意

为什么Android要采用Binder作为IPC机制?

作者:Gityuan链接:https://www.zhihu.com/question/39440766/answer/89210950来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 在开始回答 前,先简单概括性地说说Linux现有的所有进程间IPC方式: 1. 管道:在创建时分配一个page大小的内存,缓存区大小比较有限:2. 消息队列:信息复制两次,额外的CPU消耗:不合适频繁或信息量大的通信:3. 共享内存:无须复制,共享缓冲区直接付附加到进程虚拟地址空间,

红茶一杯话Binder(传输机制篇_上)

红茶一杯话Binder (传输机制篇_上) 侯 亮 1 Binder是如何做到精确打击的? 我们先问一个问题,binder机制到底是如何从代理对象找到其对应的binder实体呢?难道它有某种制导装置吗?要回答这个问题,我们只能静下心来研究binder驱动的代码.在本系列文档的初始篇中,我们曾经介绍过ProcessState,这个结构是属于应用层次的东西,仅靠它当然无法完成精确打击.其实,在binder驱动层,还有个与之相对的结构,叫做binder_proc.为了说明问题,我修改了初始篇中的示意图

红茶一杯话Binder (传输机制篇_下)

红茶一杯话Binder (传输机制篇_下) 侯 亮 1 事务的传递和处理 从IPCThreadState的角度看,它的transact()函数是通过向binder驱动发出BC_TRANSACTION语义,来表达其传输意图的,而后如有必要,它会等待从binder发回的回馈,这些回馈语义常常以“BR_”开头.另一方面,当IPCThreadState作为处理命令的一方需要向发起方反馈信息的话,它会调用sendReply()函数,向binder驱动发出BC_REPLY语义.当BC_语义经由binder驱