Binder的机制和AIDL源码分析

1.Binder的原理
Binder主要是解决跨进程通信。分为Client和Server两个进程。
Client和Server是相对的,也就是说谁发消息谁就是Client,然后收消息就是Server。ServiceManager负责吧Binder Server注册到一个容器中。

Binder的通信过程。
①首先Server在ServerManager容器中注册。
②如果Client若要调用Server的方法,首先要获取到Server对象,但是ServerManager不会把真正的Server对象返回给Client,而是返回Service的一个代理对象Proxy。
③Client调用Proxy的方法,ServiceManager会帮它调用Server的方法,并且返回到Client中。

2.AIDL的原理
AIDL的使用: https://blog.csdn.net/yuezheyue123/article/details/83029018
学习AIDL需要知道的几个类

IBinder
IInterface
Binder
Proxy
Stub

自动生成的AIDL的代码:

public interface IMyAidlInterface extends android.os.IInterface {
/**
 * Local-side IPC implementation stub class.
 */
public static abstract class Stub extends android.os.Binder implements com.example.aldltest1.IMyAidlInterface {
    private static final java.lang.String DESCRIPTOR = "com.example.aldltest1.IMyAidlInterface";

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

    /**
     * Cast an IBinder object into an com.example.aldltest1.IMyAidlInterface interface,
     * generating a proxy if needed.
     */
    public static com.example.aldltest1.IMyAidlInterface asInterface(android.os.IBinder obj) {
        if ((obj == null)) {
            return null;
        }
        android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
        if (((iin != null) && (iin instanceof com.example.aldltest1.IMyAidlInterface))) {
            return ((com.example.aldltest1.IMyAidlInterface) iin);
        }
        return new com.example.aldltest1.IMyAidlInterface.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_getNameOut: {
                data.enforceInterface(descriptor);
                java.lang.String _result = this.getNameOut();
                reply.writeNoException();
                reply.writeString(_result);
                return true;
            }
            case TRANSACTION_getUserBeanOut: {
                data.enforceInterface(descriptor);
                com.example.aldltest1.bean.User _result = this.getUserBeanOut();
                reply.writeNoException();
                if ((_result != null)) {
                    reply.writeInt(1);
                    _result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
                } else {
                    reply.writeInt(0);
                }
                return true;
            }
            case TRANSACTION_setUserIn: {
                data.enforceInterface(descriptor);
                com.example.aldltest1.bean.User _arg0;
                if ((0 != data.readInt())) {
                    _arg0 = com.example.aldltest1.bean.User.CREATOR.createFromParcel(data);
                } else {
                    _arg0 = null;
                }
                this.setUserIn(_arg0);
                reply.writeNoException();
                return true;
            }
            case TRANSACTION_getUserOut: {
                data.enforceInterface(descriptor);
                com.example.aldltest1.bean.User _arg0;
                _arg0 = new com.example.aldltest1.bean.User();
                this.getUserOut(_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_getUserInOut: {
                data.enforceInterface(descriptor);
                com.example.aldltest1.bean.User _arg0;
                if ((0 != data.readInt())) {
                    _arg0 = com.example.aldltest1.bean.User.CREATOR.createFromParcel(data);
                } else {
                    _arg0 = null;
                }
                this.getUserInOut(_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;
            }
            default: {
                return super.onTransact(code, data, reply, flags);
            }
        }
    }

    private static class Proxy implements com.example.aldltest1.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;
        }

        @Override
        public java.lang.String getNameOut() throws android.os.RemoteException {
            android.os.Parcel _data = android.os.Parcel.obtain();
            android.os.Parcel _reply = android.os.Parcel.obtain();
            java.lang.String _result;
            try {
                _data.writeInterfaceToken(DESCRIPTOR);
                mRemote.transact(Stub.TRANSACTION_getNameOut, _data, _reply, 0);
                _reply.readException();
                _result = _reply.readString();
            } finally {
                _reply.recycle();
                _data.recycle();
            }
            return _result;
        }

        @Override
        public com.example.aldltest1.bean.User getUserBeanOut() throws android.os.RemoteException {
            android.os.Parcel _data = android.os.Parcel.obtain();
            android.os.Parcel _reply = android.os.Parcel.obtain();
            com.example.aldltest1.bean.User _result;
            try {
                _data.writeInterfaceToken(DESCRIPTOR);
                mRemote.transact(Stub.TRANSACTION_getUserBeanOut, _data, _reply, 0);
                _reply.readException();
                if ((0 != _reply.readInt())) {
                    _result = com.example.aldltest1.bean.User.CREATOR.createFromParcel(_reply);
                } else {
                    _result = null;
                }
            } finally {
                _reply.recycle();
                _data.recycle();
            }
            return _result;
        }
//跨进程 从当前进程向Service中传递数据
//注意in out inout的使用  双向通讯

        @Override
        public void setUserIn(com.example.aldltest1.bean.User user) 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 ((user != null)) {
                    _data.writeInt(1);
                    user.writeToParcel(_data, 0);
                } else {
                    _data.writeInt(0);
                }
                mRemote.transact(Stub.TRANSACTION_setUserIn, _data, _reply, 0);
                _reply.readException();
            } finally {
                _reply.recycle();
                _data.recycle();
            }
        }

        @Override
        public void getUserOut(com.example.aldltest1.bean.User user) throws android.os.RemoteException {
            android.os.Parcel _data = android.os.Parcel.obtain();
            android.os.Parcel _reply = android.os.Parcel.obtain();
            try {
                _data.writeInterfaceToken(DESCRIPTOR);
                mRemote.transact(Stub.TRANSACTION_getUserOut, _data, _reply, 0);
                _reply.readException();
                if ((0 != _reply.readInt())) {
                    user.readFromParcel(_reply);
                }
            } finally {
                _reply.recycle();
                _data.recycle();
            }
        }

        @Override
        public void getUserInOut(com.example.aldltest1.bean.User user) 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 ((user != null)) {
                    _data.writeInt(1);
                    user.writeToParcel(_data, 0);
                } else {
                    _data.writeInt(0);
                }
                mRemote.transact(Stub.TRANSACTION_getUserInOut, _data, _reply, 0);
                _reply.readException();
                if ((0 != _reply.readInt())) {
                    user.readFromParcel(_reply);
                }
            } finally {
                _reply.recycle();
                _data.recycle();
            }
        }
    }

    static final int TRANSACTION_getNameOut = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    static final int TRANSACTION_getUserBeanOut = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    static final int TRANSACTION_setUserIn = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
    static final int TRANSACTION_getUserOut = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
    static final int TRANSACTION_getUserInOut = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4);
}

public java.lang.String getNameOut() throws android.os.RemoteException;

public com.example.aldltest1.bean.User getUserBeanOut() throws android.os.RemoteException;
//跨进程 从当前进程向Service中传递数据
//注意in out inout的使用  双向通讯

public void setUserIn(com.example.aldltest1.bean.User user) throws android.os.RemoteException;

public void getUserOut(com.example.aldltest1.bean.User user) throws android.os.RemoteException;

public void getUserInOut(com.example.aldltest1.bean.User user) throws android.os.RemoteException;

}

①从Client看,对于AIDL的使用者:
MyAidl.Stub.asInterface(binder).xxxx();
asInterface方法的作用就是判断IBinder对象是否和自己处于同一个进程
如果是,那么就直接将转换使用,接下来和Binder的跨进程通讯无关
如果不是,那么就要把IBinder包装成一个Proxy对象,这时候通过Proxy来调用其中的方法。
Binder的机制和AIDL源码分析_第1张图片

②直接使用的情况:
首先可以发现Stub是实现了IMyAidlInterface接口,然后在MyService类中,已经自定义了类Stub类,并且重写了getNameOut()等方法。因此在activity中直接就可以进行使用。
Binder的机制和AIDL源码分析_第2张图片
③转化成Proxy的情况
在代理类中,已经自动生成了相应的方法的代码,比如getNameOut()方法,这里的mRemote其实就是Stub的对象。然后调用的是Stub的transact()方法。这样将数据传递给Service端。
Binder的机制和AIDL源码分析_第3张图片
具体的实现是在Binder类中,它会默认调用自身的onTransact()方法。
Binder的机制和AIDL源码分析_第4张图片
④从Server上看,会通过onTransact方法接受Client进程传递过来的数据。
这里应该会调用Stub的onTransact方法
Binder的机制和AIDL源码分析_第5张图片

注意:在service中的binder对象和再activity中接受的binder对象是不一致的
Binder的机制和AIDL源码分析_第6张图片
在activity中返回的是一个BinderProxy
Binder的机制和AIDL源码分析_第7张图片

你可能感兴趣的:(源码)