Actual development of Android Framework - detailed analysis of aidl file of Binder special explanation

csdn online learning course, course consultation and Q & A and new course information: QQ communication group: 422901085 for course discussion

android cross process communication practice video course (add group to get preferential)

When you are doing application development, you often encounter the need for cross process communication. Most of the communication here may answer, that is, using aidl and service. Indeed, the way of aidl and service is that the contact layer of binder in application development should belong to the closest layer. Because other interface methods, such as startActivtiy, ContentProvider and broadcast, are directly done by the system component interface. We can't even see the shadow of the binder. Naturally, we are relatively unfamiliar with the binder.
This section focuses on the in-depth explanation and analysis of the methods and principles of binder communication at the application level. This part belongs to the intermediate part of binder explanation. This class will explain the source code analysis of java files generated by binder's aidl:
Why AIDL? What is its meaning?
When using the binder service for cross process communication, we often write Aidl. First of all, you will have questions. What is Aidl? Aidl is an abbreviation and its full name is Android Interface Definition Language, that is, Android Interface Definition Language. Therefore, Aidl is just a language. Its main purpose is to help the binder define the interface for cross process communication. The suffix is. Aidl. It has its own syntax, but it is basically similar to Java. Finally, the whole Aidl file will be converted into the corresponding java file through an aidl.exe, Because of the compilation interface, when our Java program is in use, of course, it should be changed into Java to modify the class file. Students here will certainly say why not use Java directly and build a new language. In fact, the most critical part is asked here.
Here are the following reasons:
1. If you want to implement it in java language, you will have to write a lot of repeated fixed code. The amount of code written is relatively large, and it is easy to make mistakes if you are not careful
2. This part allows the script to generate the corresponding java code according to some configuration files, and the of this configuration file is similar to the aidl we see today
The essence is shown in the figure below:

Here we will implement step by step according to the above figure:
1. Specify which is the client and which is the service
First of all, we generally define a Service when communicating across processes in the application layer, because the Service component in Android can run in an independent process, that is, the Service code may be under an apk, but the process it runs is not the process corresponding to the package name of the apk. Therefore, it is generally demonstrated that cross process communication can be implemented with an apk, This Service is our real server and business implementation end. The client is the initiator of calling this Service. It is generally possible whether this is implemented in Activity or Service. Generally, we call cross process communication in Activity for convenience, that is, Activity is the client.
2. Determine the interface in the communication process (i.e. the information to be obtained in the communication)
This is the so-called aidl file, which defines the corresponding communication interface. For example, here we define a student information acquisition interface:
IStudentInterface .aidl

interface IStudentInterface {
    int getStudentId(String name);//Define an interface to query student number according to student name
}

Conversion of aidl file
After the Aidl file is written, click make to compile the project. During the compilation process, aidl.exe will convert it into the corresponding java file. To view the java file, click the following path in android studio:

If you want to directly use aidl.exe to generate commands, it is also possible
First, there is aidl.exe under Android SDK \ build tools \ 29.0.2

aidl.exe -IF:\binder_drivers_code\ServiceDemo\app\src\main\aidl\com\example\servicedemo  F:\binder_drivers_code\ServiceDemo\app\src\main\aidl\com\example\servicedemo\IStudentInterface.aidl

There is no space between "- I" and "F:\binder_drivers_code * * *". Finally, it will be in F:\binder_drivers_code\ServiceDemo\app\src\main\aidl\com\example\servicedemo generates an IStudentInterface.java

Here, I believe you have understood what aidl is. Its essential purpose is to help us reduce writing those repeated and unchanged communication protocol codes. This can be generated by the machine according to our description configuration file, which is actually our aidl file

3. Then we have generated this java file. What is the content of my java file?
In fact, the above figure also shows in advance. It mainly includes Stub class and Stub. Proxy class

  public static abstract class Stub extends android.os.Binder implements com.example.servicedemo.IStudentInterface1
  {
       . . ellipsis
    public static com.example.servicedemo.IStudentInterface1 asInterface(android.os.IBinder obj)
    {
         . . ellipsis
      return new com.example.servicedemo.IStudentInterface1.Stub.Proxy(obj);
    }
    @Override public android.os.IBinder asBinder()
    {
      return this;
    }
    //At this time, after the server driver obtains data, a series of calls will be called back to onTransact
    @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)
      {
           . . ellipsis
        case TRANSACTION_getStudentId:
        {
          data.enforceInterface(descriptor);
          java.lang.String _arg0;
          _arg0 = data.readString();
          int _result = this.getStudentId(_arg0);//This place will really call the getStudentId method implemented in the Service
          reply.writeNoException();
          reply.writeInt(_result);
          return true;
        }
            . . ellipsis
      }
    }
    private static class Proxy implements com.example.servicedemo.IStudentInterface1
    {
     . . ellipsis
      @Override public int getStudentId(java.lang.String name) 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.writeString(name);
          boolean _status = mRemote.transact(Stub.TRANSACTION_getStudentId, _data, _reply, 0);//The client calls getStudent. Finally, it calls the remote through mRemote and waits for the result
          if (!_status && getDefaultImpl() != null) {
            return getDefaultImpl().getStudentId(name);
          }
          _reply.readException();
          _result = _reply.readInt();
        }
        finally {
          _reply.recycle();
          _data.recycle();
        }
        return _result;
      }
      public static com.example.servicedemo.IStudentInterface1 sDefaultImpl;
    }
       . . ellipsis
  }

Here, Stub is the specific real implementation of the remote end, which is generally implemented in the server Serivce, while Stub.Proxy class mainly provides the client with the interface to call the remote end. The corresponding actual used Stub class and Stub.Proxy class are as follows:
Screenshot of Stub server implementation:

Specific use and calling procedure of Stub.Proxy:

The asInterface here is also shown in the code above. In fact, it is
new com.example.servicedemo.IStudentInterface1.Stub.Proxy(obj); A stub.proxy local object is constructed.
Finally, summarize a diagram of cross process call after converting aidl into java file:

Keywords: Java Android Framework

Added by Sharkadder on Mon, 04 Oct 2021 21:11:01 +0300