Android advanced - Binder of Android cross process communication mechanism, successfully joined Tencent

Keywords: Linux Android Design Pattern

Through system call, user space can access kernel space. How does it access kernel space? The dynamic loadable kernel module mechanism of Linux solves this problem. The module is a program with independent functions. It can be compiled separately, but it can not run independently. In this way, the Android system can complete the communication by adding a kernel module to run in the kernel space and using this module as a bridge between user processes. In the Android system, the kernel module running in the kernel space and responsible for the communication of various user processes through Binder is called Binder driver

5, Simple summary

Connecting all the previous concepts will be very easy to digest the knowledge points:

1. The virtual memory mechanism of Linux leads to memory isolation, which leads to process isolation
2. The emergence of process isolation leads to the division of memory operations into user space and kernel space
3. User space needs cross permission to access kernel space, which must be implemented by system call
4. System calls need to be completed with the help of kernel modules / drivers

The first three steps determine that interprocess communication needs to be realized with the help of kernel module / driver, and Binder driver is used to realize interprocess communication in kernel module / driver

###Why use Binder
Linux provides cross process methods such as pipeline, message queue, semaphore, memory sharing and socket. Why does Android choose Binder to start a new business?

1, Good transmission performance

  • Socket: it is a general interface, resulting in low transmission efficiency and high overhead
  • Shared memory: Although there is no need to copy data during transmission, its control mechanism is complex
  • Binder: complex data type transfer can reuse memory and need to copy data once
  • Pipeline and message queue: store and forward mode is adopted, and the data needs to be copied at least twice, which is inefficient

2, High security

  • Traditional process: the communication mode does not strictly verify the identity of both sides of the communication, but only on the upper layer protocol

  • Binder mechanism: from the protocol itself, it supports identity verification for both communication parties, thus greatly improving the security
    ###Binder communication model
    First, familiarize yourself with these concepts before understanding the model:

  • Client process: a client that communicates across processes (running in a process)

  • Server process: the server side of cross process communication (running in a process)
    Binder driver: a medium for cross process communication

  • Service Manager: provides service registration and query in cross process communication (running in System process)

This is just a simple model. You only need to understand the communication process of the model:

1. The server side registers in the ServiceManager through the Binder driver
2. The client side obtains the Server side registered in the ServiceManager through the Binder driver
3. The client side communicates with the Server side through the Binder driver
###Binder communication principle

After understanding the model process, start to understand the communication principle of the model:

1. The service side registers the add method of the Object object in the lookup table of the ServiceManager through the Binder driver
2. The client finds the add method of the Object object in the lookup table of the ServiceManager through the Binder driver and returns the add method of the proxy Object. The add method is an empty implementation, and the proxy Object is not a real Object object. It is the add method of the encapsulated proxy class through the Binder driver
3. when the Client side invokes the add method, the Client will invoke the add method of the proxy object, request ServiceManager through Binder drive to find the real object of the Service end, then call the add method of the Service side.

###Binder objects and binder drivers

  • Binder object: an object for inter process communication in binder mechanism. It is a binder local object for the Service side and a binder proxy object for the Client side
  • Binder driver: the medium for inter process communication in binder mechanism. Binder driver will make special processing for objects with cross process transfer ability, and automatically complete the conversion of proxy objects and local objects

Since the Binder driver will perform special processing on objects with cross process transfer capability and automatically complete the conversion between proxy objects and local objects, the driver saves the relevant information of each Binder object across processes, and the Binder local object (or Binder entity) is saved in the Binder_ The data structure of node, and the Binder proxy object (or Binder reference / handle) is saved in the Binder_ Data structure of ref

###Binder for Java layer

  • Binder class: it is a binder local object
  • BinderProxy class: it is the internal class of the Binder class, which represents the local proxy of the Binder object of the remote process
  • Parcel class: it is a container, which is mainly used to store serialized data, which can then be passed between processes through Binder
  • IBinder interface: it represents the ability of cross process transmission. By implementing this interface, this object can be passed across processes
  • IInterface interface: the calling contract between client and server. Implementing this interface represents the capabilities of remote server objects, because the asBinder method of IInterface interface can return Binder local objects or proxy objects

Both binder class and BinderProxy class inherit from IBinder, so they have the ability of cross process transmission. When crossing processes, the binder driver will automatically complete the conversion of these two objects. IBinder is the basic interface of remote objects and the core part of the lightweight remote call mechanism designed for high performance, but it is not only used for remote calls, but also used for in-process calls. The IBinder interface defines the protocol for interacting with remote objects. It is recommended not to implement this interface directly, but to derive from binder. Binder implements the IBinder interface, but generally does not need to implement this class directly, but is generated by the tool in the development package according to your needs. This tool is called aidi. You define the methods of remote objects through aidi language, then use aidi tools to generate binder derived classes, and then use it

###AIDL
Because the compiler tool will generate a static internal class of Stub for us, this class inherits Binder, indicating that it is a Binder local object, and it implements the IInterface interface, indicating that it has the ability promised by the remote Server to the Client

1, Server

On the server side, we just need to implement the Stub abstract class and its methods

private IBinder myS = new IMyAidlInterface.Stub() {  
    @Override  
    public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {  

    }  

    @Override  
    public int add(int num1, int num2) throws RemoteException {  
        Log.i("Hensen", "From the client AIDL request:num1->" + num1 + "::num2->" + num2);  
        return num1 + num2;  
    }  
}; 

2, Client

In the client, you can get the AIDL interface through the callback of bindService

private ServiceConnection conn = new ServiceConnection() {  
    @Override  
    public void onServiceConnected(ComponentName name, IBinder service) {  
        iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);  
    }  

    @Override  
    public void onServiceDisconnected(ComponentName name) {  
        iMyAidlInterface = null;  
    }  
};

public void add(View view) {  
    try {  
        int res = iMyAidlInterface.add(1, 2);  
        Log.i("Hensen", "Result of successful call from the server:" + res);  
    } catch (RemoteException e) {  
        e.printStackTrace();
    }
}   

Sort out the calling process of the client:

1. Call Stub.asInterface to get BinderProxy object
2. Call the add method of BinderProxy object

3, Analysis principle

1,Stub

The Stub class inherits from Binder, which means that the Stub is actually a Binder local object, and then implements the IMyAidlInterface interface. IMyAidlInterface itself is an iiinterface, so it carries some capabilities required by the client (here is the method add). This class has an internal class Proxy, that is, Binder Proxy object

/* 
 * This file is auto-generated.  DO NOT MODIFY. 
 * Original file: D:\\workspace5\\Boke\\app\\src\\main\\aidl\\com\\handsome\\boke\\IMyAidlInterface.aidl 
 */  
package com.handsome.boke;  
// Declare any non-default types here with import statements  

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

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

        /** 
         * Cast an IBinder object into an com.handsome.boke.IMyAidlInterface interface, 
         * generating a proxy if needed. 
         */  
        public static com.handsome.boke.IMyAidlInterface asInterface(android.os.IBinder obj) {  
            if ((obj == null)) {  
                return null;  
            }  
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);  
            if (((iin != null) && (iin instanceof com.handsome.boke.IMyAidlInterface))) {  
                return ((com.handsome.boke.IMyAidlInterface) iin);  
            }  
            return new com.handsome.boke.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 {  
            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_add: {  
                    data.enforceInterface(DESCRIPTOR);  
                    int _arg0;  
                    _arg0 = data.readInt();  
                    int _arg1;  
                    _arg1 = data.readInt();  
                    int _result = this.add(_arg0, _arg1);  
                    reply.writeNoException();  
                    reply.writeInt(_result);  
                    return true;  
                }  
            }  
            return super.onTransact(code, data, reply, flags);  
        }  

        private static class Proxy implements com.handsome.boke.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);  
                    mRemote.transact(Stub.TRANSACTION_basicTypes, _data, _reply, 0);  
                    _reply.readException();  
                } finally {  
                    _reply.recycle();  
                    _data.recycle();  
                }  
            }  

            @Override  
            public int add(int num1, int num2) throws android.os.RemoteException {  
                android.os.Parcel _data = android.os.Parcel.obtain();  
                android.os.Parcel _reply = android.os.Parcel.obtain();  
                int _result;  
                try {  
                    _data.writeInterfaceToken(DESCRIPTOR);  
                    _data.writeInt(num1);  
                    _data.writeInt(num2);  
                    mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);  
                    _reply.readException();  
                    _result = _reply.readInt();  
                } finally {  
                    _reply.recycle();  
                    _data.recycle();  
                }  
                return _result;  
            }  
        }  

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

    /** 
     * Demonstrates some basic types that you can use as parameters 
     * and return values in AIDL. 
     */  
    public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException;  

    public int add(int num1, int num2) throws android.os.RemoteException;  
}  
### Finally: learning summary - brain map of Android framework architecture knowledge (pure hand drawn xmind document)

After learning, if you want to check and accept the effect, in fact, the best way is to summarize it yourself. For example, I will draw one by myself after learning something xmind The outline brain map of the document can also facilitate the follow-up review, and they are all their own understanding. I believe that a few glances can quickly pass through the complete knowledge and make up for it.

Below is my hand drawn Android Framework architecture knowledge brain map, because it is xmind Files are not easy to upload, so Xiaobian will export them in the form of pictures and pass them here. The details are not particularly clear. But it can provide complete information for interested friends Android Original brain map of framework architecture knowledge (including interview analysis above) xmind (document)
![](https://img-blog.csdnimg.cn/img_convert/66dad9d0544e283a1bdd0ab4c2ac3995.png)

In addition, as mentioned above Alibaba Collection Edition **Android Framework architecture** Handwritten documents and a **<Big talk data structure** Books and other related learning notes and documents can also be shared with recognized friends!

-Thank you for your recognition and support, Free Download Please note: like+give the thumbs-up+give the thumbs-up!!!
Architecture knowledge brain map, because it is xmind Files are not easy to upload, so Xiaobian will export them in the form of pictures and pass them here. The details are not particularly clear. But it can provide complete information for interested friends Android Original brain map of framework architecture knowledge (including interview analysis above) xmind (document)
[External chain picture transfer...(img-61u7Gros-1630510271855)]

In addition, as mentioned above Alibaba Collection Edition **Android Framework architecture** Handwritten documents and a **<Big talk data structure** Books and other related learning notes and documents can also be shared with recognized friends!

-Thank you for your recognition and support, Free Download Please note: like+give the thumbs-up+give the thumbs-up!!!
**[CodeChina Open source projects:< Android Summary of study notes+Mobile architecture video+Real interview questions for large factories+Project practice source code](https://codechina.csdn.net/m0_60958482/android_p7)**

Posted by Lillefix on Thu, 02 Sep 2021 00:14:46 -0700