Android adhesive 'Binder'

background knowledge

To grasp the details of Android Binder communication mechanisms need to understand some basic knowledge of communication principles and Linux systems in advance.

RPC

RPC (Remote Procedure Call), that is, remote procedure calls, also known as Remote Method Invocation.

RPC is a computer communications protocol, Client is the definition of a computer terminal to call another program Server computer, initiated by a number of requests from Client to Server, Server operates in accordance with information received Client. RPC is a typical Client / Server mode .

AIDL

RPC is just a computer communication protocol, IDL provides rules for communication.

IDL (Interface Define Language), i.e., an interface definition language, to describe the interface by a neutral way that objects running on different platforms and programs written in different languages can communicate with each exchange .

User space / kernel space / system calls

Process space into user space and kernel space (Kernel). Android is based on Linux, Linux Kernel is the core of the operating system, the core of the operating system certainly can not allow free access to the application, you can only access the system allows access to resources, access to resources can not be refused access, so it is divided into the process space and kernel space. User space access the kernel space this operation, known as system calls . All these visits are under the control of the kernel space, to ensure that no unauthorized access occurs, to ensure the security and stability of the system.

The difference between the two:

  • Inter-process data can not be shared user space, user space is not a shared space
  • Inter-process data can be shared kernel space, kernel space is a shared space

LKM / Binder drive

User space access the kernel space for the system call, if the user space access to user space, in fact, cross-process communication on the user level. Linux support traditional methods are pipes, Socket, etc. are supported by the kernel. Then the user space is how to access the user space it? By "install driver" approach.

  • Dynamically loadable Linux kernel module (Loadable Kernel Module, LKM) is the aforementioned drive, the function module is an independent program that can be compiled separately, can be run separately. It is linked to the kernel as part of the kernel running in the kernel space at run time. Thus, Android system by the addition of a dynamically loadable kernel module to run between kernel space and user process by this module as a bridge, the communication can be done, of course, this is a dynamically loadable kernel modules Binder drive.

IPC and process isolation

  • I.e., IPC Inter-Process Communication (interprocess communication).

  • Process isolation
    in order to guarantee the security and independence, a user-space process or operation can not be directly accessed by another process, namely Android processes are independent, isolated

Traditional way communication process:

image

Shortcomings and deficiencies:

  • Efficiency is not high, data from the user space -> kernel space -> user space, made two copies of the data, a waste of time
  • Buffer receive data not know the exact size, the receiver does not know how much cache it needs

Binder communication flow

Binder communication with the analogy of a popular event called:
Mike phoned Wang, Wang Li must know the phone number, an address book so it is necessary to inform Li, Wang's phone number, the address book that is, a table, a record of the names and telephone Wang. Know the phone, dial the phone of course, need to transmit information through the base station

  • Binder cross-process communication mechanism based on Client - Server

  • Binder role model

Roles Explanation analogy
Client Process Use process services Mike
Server process Process serving Wang
ServerManage Management Server registration and inquiry Contacts
Binder driver Virtual device drivers, are connected to each other bridges The base station
  • Binder communication flow

    image

    1. Server processes registered in ServerManager, the registration they need to be fun objects Client-process communication object and method ();
    2. Client processes the query object corresponding to the object and fun method to ServerManager (), but Binder driver returns a "puppet" proxy object objectProxy and the method, but no Server process in that capacity.
    3. Client process to get the driver to return a proxy object Binder, due process Client not true and false identification method of the proxy object objectProxy immediate caller.
    4. After Binder driver received a message to call the proxy object method, a look-up table is a proxy object found, before they sent to the Client process objectProxy replaced with a proxy object. It really is fun object you want to access the object (); then drive Binder notification Server process, call your object fun object (), then the results sent to me, Sever process receives this message, then return the results did drive, drive and process the results returned to the Client; so the whole process is complete.
  • to sum up

    • Binder core mechanism is a proxy mechanism, the core principle is memory map
    • Binder for access, if it is in the same process (do not need cross-process), then directly back to the original Binder entity; if in a different process, then give him a proxy object
    • Client Server process is only held by the end of proxy; proxy objects help drive the completion of the cross-process communication.

Memory map

  • In this paper, but more to say, it is only a few copies of the data than the ordinary process of communication. Linux memory map

Drive in the Binder

  • Server processes inside Binder Binder object refers to a local object, Client inside Binder Binder proxy object is an object worth, at the time of inter-process communication, Binder driver will automatically convert two data types. Accordingly, in the local object storage Binder called binder_node data structure, Binder proxy object is stored in a data structure called the binder_ref.

Source understand Java layer Binder

AIDL interfaces simple definition, the compiler program is generated by AIDL AIDL interface communication class. Generation of interface inheritance IInterface, IInterface is common interprocess communication interfaces , while exposure of the two methods for external calls, the generated code will add a note of personal understanding.

image

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: /Users/Rocka/Desktop/rocka_workspace/DEMO_AIDL/server/src/main/aidl/com/rocka/aidl/AnimalManager.aidl
 */
package com.rocka.aidl 大专栏  Android 粘合剂'Binder';

public interface AnimalManager extends android.os.IInterface {
    /**
     * Local-side IPC implementation stub class.
     */
    public static abstract class Stub extends android.os.Binder implements com.rocka.aidl.AnimalManager {
        //唯一标识,类的具体路径名,用于唯一表示这个 IInterface
        private static final java.lang.String DESCRIPTOR = "com.rocka.aidl.AnimalManager";

        /**
         * Construct the stub at attach it to the interface.
         * 将当前接口与Binder绑定
         */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

        /**
         * Cast an IBinder object into an com.rocka.aidl.AnimalManager interface,
         * generating a proxy if needed.
         * 将一个IBinder 的对象转换成AnimalManger接口,如果不在一个进程创建一个代理
         */
        public static com.rocka.aidl.AnimalManager asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            //通过唯一标识从本地去查询
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.rocka.aidl.AnimalManager))) {
                return ((com.rocka.aidl.AnimalManager) iin);
            }
            //查不到就返回代理
            return new com.rocka.aidl.AnimalManager.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 {
            switch (code) {
                case INTERFACE_TRANSACTION: {
                    reply.writeString(DESCRIPTOR);
                    return true;
                }
                case TRANSACTION_addAnimal: {
                    data.enforceInterface(DESCRIPTOR);
                    com.rocka.aidl.Animal _arg0;
                    if ((0 != data.readInt())) {
                        _arg0 = com.rocka.aidl.Animal.CREATOR.createFromParcel(data);
                    } else {
                        _arg0 = null;
                    }
                    this.addAnimal(_arg0);
                    reply.writeNoException();
                    return true;
                }
                case TRANSACTION_getAnimals: {
                    data.enforceInterface(DESCRIPTOR);
                    java.util.List<com.rocka.aidl.Animal> _result = this.getAnimals();
                    reply.writeNoException();
                    reply.writeTypedList(_result);
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
        }

        private static class Proxy implements com.rocka.aidl.AnimalManager {
            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;
            }

            /**
             * 除了基本数据类型,其他类型的参数都需要标记方向类型,in(输入),out(输出),inout(输入输出)
             */
            @Override
            public void addAnimal(com.rocka.aidl.Animal animal) 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 ((animal != null)) {
                        _data.writeInt(1);
                        animal.writeToParcel(_data, 0);
                    } else {
                        _data.writeInt(0);
                    }
                    mRemote.transact(Stub.TRANSACTION_addAnimal, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }

            @Override
            public java.util.List<com.rocka.aidl.Animal> getAnimals() throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                java.util.List<com.rocka.aidl.Animal> _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(Stub.TRANSACTION_getAnimals, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.createTypedArrayList(com.rocka.aidl.Animal.CREATOR);
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
        }

        static final int TRANSACTION_addAnimal = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_getAnimals = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    }

    /**
     * 除了基本数据类型,其他类型的参数都需要标记方向类型,in(输入),out(输出),inout(输入输出)
     */
    public void addAnimal(com.rocka.aidl.Animal animal) throws android.os.RemoteException;

    public java.util.List<com.rocka.aidl.Animal> getAnimals() throws android.os.RemoteException;
}

Source analysis:

  • Stub's asInterface (android.os.IBinder obj) Parameters IBinder function of the type of obj, the object is the driving to us. By uniquely identify to a query from a local, it will try to find Binder local object, if found, indicating Client and Server are in the same process, this parameter is directly Binder local object, and then return directly cast, if not, Description is BinderProxy remote object (in another process) then you need to create a proxy object Binde, so that the Binder agent for access to remote objects. Generally speaking, if it is to communicate with a remote Service object, then there must be a return Binder proxy object, this parameter is actually IBinder BinderProxy;

  • Proxy Stub class is an abstract class of a category, it represents the remote process Binder local agent. Proxy and Stub are inherited from IBinder, so has the ability to cross-process transmission, at the time of communication, will auto-complete the two data type conversion.

  • Stub class category abstract class implements the abstract method of the above two addAnimal () and getAnimals (). Parcel first with the abstract method of the data sequence, and then iBinder Transact call () method. After the wake Server driver to complete a series of operations; transact the last call to talkWithDriver by JNI function; communication process to complete the drive; this last function by ioctl system call, Client process into kernel mode, Client calling thread hangs waiting to return addAnimal method process, called onTransact Server process local function object (actually completed by the Server-side thread pool).

  • onTransact method (this is Stub class inside this method) Binder we look at local objects. Binder method called addAnimal local objects; This method returns the results to Binder driving, driving wake suspended Client processes inside thread and returns the results. Then a cross-process call is complete.

  • The difference between Proxy and Stub. Although they are both Binder is IInterface, except that Stub uses inheritance (is relationship), Proxy is used in combination (has relations). They have achieved all of IInterface function, except that, Stub and use the strategy pattern called a virtual function (subclass to be realized), and Proxy mode is used in combination.

Binder will summarize here, in fact, there are plenty of further study.

Guess you like

Origin www.cnblogs.com/lijianming180/p/12099809.html