2020-08-21 AIDL 生成的IInterface接口代码解析

2,087 阅读4分钟

AIDL 生成的IInterface接口代码解析

前言

在android 中跨进程通信,我们需要用AIDL,而在Android Studio中,我们编写通信的AIDL时候,只需要简单的定义相关方法,Andrdoid Studio就会给开发者生存对应的Java Interface接口,不过作为开发者我们需要了解这些自动生成的代码的作用。

如下定义个 IPet的AIDL 接口,自动生成了 IDEA自动生成了 IPet.java类。

在IPet java类中,主要有三个类 Default、Stub、Proxy类。其中Default类没什么作用可以忽略,重点是Stub和Stub的子类Proxy。

Stub 类继承了 Binder类且实现了 IPet的接口。 Stub类中有两个重点方法:

  1. asInterface(android.os.IBinder obj) 方法,用于将Binder对象转发为具体的接口对象,如果在同一进程则强制obj为binder,否则返回一个代理对象。
  2. onTransact 方法,服务端调用,读取Parcle中客户端传入的参数,执行客户端的指令并且 向Parcle写入执行客户端要求的方法后得到的返回值。 Proxy类是被客户端使用。

Proxy 类中实现了IPet接口中的方法,在方法中向Parcle写入客户端要传入的数据,调用Binder反回结果后,再从Parcle中读取结果(服务端向Parcle写入的方法执行结果),然后将该结果作为该方法的返回值。

显然Proxy类中实现的具体方法对Parcle的操作与onTransact中的操作是一一对应的。

代码解析

/*
 * This file is auto-generated.  DO NOT MODIFY.
 */
package com.chl.pservice;

public interface IPet extends android.os.IInterface {
    /**
     * Default implementation for IPet.
     */
    public static class Default implements com.chl.pservice.IPet {
        @Override
        public java.util.List< com.yrj.pservice.Pet > getPets(com.yrj.pservice.Person owner) throws android.os.RemoteException {
            return null;
        }

        @Override
        public java.util.List< com.yrj.pservice.Pet > getAllPets() throws android.os.RemoteException {
            return null;
        }

        @Override
        public android.os.IBinder asBinder() {
            return null;
        }
    }

    /**
     * Local-side IPC implementation stub class.
     */
    public static abstract class Stub extends android.os.Binder implements com.chl.pservice.IPet {
        //唯一标识,一般为完整路径,一般通过该类来判断是否是同一个接口
        private static final java.lang.String DESCRIPTOR = "com.chl.pservice.IPet";


        // binder 中的方法,将具体的接口、描述符和Binder进行绑定
        public Stub() {
            /**
             * Convenience method for associating a specific interface with the Binder.
             * After calling, queryLocalInterface() will be implemented for you
             * to return the given owner IInterface when the corresponding
             * descriptor is requested.
             */
            this.attachInterface(this, DESCRIPTOR);
        }

        /**
         * Cast an IBinder object into an com.chl.pservice.IPet interface,
         * generating a proxy if needed.
         */
        //将Binder对象转化为具体的接口,判断如果不在一个进程,则返回一个代理对象
        public static com.chl.pservice.IPet asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            // 通过描述符查询本地接口,返回本地的对象
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
//            判断本地对象是否存在,如果存在说明是同一个进程,返回该对象
            if (((iin != null) && (iin instanceof com.chl.pservice.IPet))) {
                return ((com.chl.pservice.IPet) iin);
            }
//          本地对象不存在,说明是快进程,生成一个代理对象
            return new com.chl.pservice.IPet.Stub.Proxy(obj);
        }

        // IInterface接口方法具体实现,返回一个binder
        @Override
        public android.os.IBinder asBinder() {
            return this;
        }

        // 操作标识符,在onTransact方法中根据这些code来进行相应的操作
        static final int TRANSACTION_getPets = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_getAllPets = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);

        //        事务处理类,写入标识符以及执行接口定义的方法
        @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;
//            根据通用Binder的一套协议,code的值判断当前读取的是什么作用的值
            switch (code) {
                // 向 parcel写入 标识符,表示是哪个进程写入的回复
                case INTERFACE_TRANSACTION: {
                    reply.writeString(descriptor);
                    return true;
                }
//              执行接口定义的方法
                case TRANSACTION_getPets: {
                    data.enforceInterface(descriptor);
                    com.chl.pservice.Person _arg0;
//                     从 data中读取客户端进程传入的值
                    if ((0 != data.readInt())) {
                        _arg0 = com.chl.pservice.Person.CREATOR.createFromParcel(data);
                    } else {
                        _arg0 = null;
                    }
//                   执行方法,返回接口,并将结果写到 replay中
                    java.util.List< com.chl.pservice.Pet > _result = this.getPets(_arg0);
                    reply.writeNoException();//写入无异常
                    reply.writeTypedList(_result);//
                    return true;
                }
                //              执行接口定义的方法
                case TRANSACTION_getAllPets: {
                    data.enforceInterface(descriptor);
                    java.util.List< com.yrj.pservice.Pet > _result = this.getAllPets();
                    reply.writeNoException();
                    reply.writeTypedList(_result);
                    return true;
                }
                default: {
                    return super.onTransact(code, data, reply, flags);
                }
            }
        }

        // 跨进程通信,生成的代理类,返回给客户端
        private static class Proxy implements com.chl.pservice.IPet {
            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;
            }

            //          客户端调用该代理类的方法,该方法处理客户端写入Parcel的数据
//
            @Override
            public java.util.List< com.chl.pservice.Pet > getPets(com.chl.pservice.Person owner) throws android.os.RemoteException {
                // 该data 即是在 Stub.onTransact参数中的data类,_data在客户端被写入数据,在服务端的onTract方法被读取然后进行处理
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                java.util.List< com.chl.pservice.Pet > _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    if ((owner != null)) {
                        // 写入了 1 表示参数不为空
                        _data.writeInt(1);
                        //写入客户端传入的参数数据
                        owner.writeToParcel(_data, 0);
                    } else {
                        //写入 0表示参数为空
                        _data.writeInt(0);
                    }

                    // mRemote.trasact方法中实现了跨进程通信,服务端调用了onTract()方法,
                    boolean _status = mRemote.transact(Stub.TRANSACTION_getPets, _data, _reply, 0);
                    if (!_status && getDefaultImpl() != null) {
                        return getDefaultImpl().getPets(owner);
                    }
                    _reply.readException();
                    _result = _reply.createTypedArrayList(com.chl.pservice.Pet.CREATOR);
                } finally {
                    //将该Parcle对象放回回收池,主要是减少对象的创建,能够重复利用
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }

            @Override
            public java.util.List< com.yrj.pservice.Pet > getAllPets() throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                java.util.List< com.yrj.pservice.Pet > _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    boolean _status = mRemote.transact(Stub.TRANSACTION_getAllPets, _data, _reply, 0);
                    if (!_status && getDefaultImpl() != null) {
                        return getDefaultImpl().getAllPets();
                    }
                    _reply.readException();
                    _result = _reply.createTypedArrayList(com.yrj.pservice.Pet.CREATOR);
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }

            public static com.chl.pservice.IPet sDefaultImpl;
        }

        public static boolean setDefaultImpl(com.chl.pservice.IPet impl) {
            if (Stub.Proxy.sDefaultImpl == null && impl != null) {
                Stub.Proxy.sDefaultImpl = impl;
                return true;
            }
            return false;
        }

        public static com.chl.pservice.IPet getDefaultImpl() {
            return Stub.Proxy.sDefaultImpl;
        }
    }
    //将复杂对象作为AIDL接口的形参时,记得加上in

    public java.util.List< com.chl.pservice.Pet > getPets(com.chl.pservice.Person owner) throws android.os.RemoteException;

    public java.util.List< com.chl.pservice.Pet > getPetsByName(java.lang.String name) throws android.os.RemoteException;
}

以上是AIDL生成的接口代码解析,通过解析,读者能大概了解到 AIDL通信中的部分过程,不过这些显然只是一些浅显的了解。如果想要了解Binder通信的底层原理和过程,可以点击参考文献中的文章去看下。

参考

  1. 进程间通信之AIDL解析

  2. linux基础——linux进程间通信(IPC)机制总结_千里之行,始于足下-CSDN博客_linuxipc

  3. 写给 Android 应用工程师的 Binder 原理剖析 - 知乎

  4. Android Bander设计与实现 - 设计篇_universus的专栏-CSDN博客_bander设计