Android Binder communication principle (seven): CS under java

Source code based on: Android R

0. Preface

In the previous blog posts, the communication principle of Android binder was deeply analyzed. These blog posts include: binder introduction , servicemanager startup , service registration , service acquisition , service registration and acquisition .

In the previous article, the principle of CS communication under native is explained in detail through examples .

This paper further analyzes the CS communication under java in the form of examples on the basis of the previous ones.

1

App uses aidl when using binder to communicate. Such use of framework is also very common, and the system will automatically compile the corresponding Java files according to the interface definition of aidl when compiling.

In the latest version, aidl can not only guarantee the C-S communication on the Java side, but also the Java client - native service communication.

Here we take the install of PMS as an example. When PMS installs APK, it will translate dex, which is completed by the daemon process installd.

frameworks/native/cmds/installd/binder/android/os/IInstalld.aidl

package android.os;

/** {@hide} */
interface IInstalld {
    ...
}

2. Java side call

frameworks/base/services/core/java/com/android/server/pm/installer.java

import android.os.IInstalld;

public class Installer extends SystemService {
    private volatile IInstalld mInstalld;
    
    private void connect() {
        IBinder binder = ServiceManager.getService("installd");
        if (binder != null) {
            ...
        }

        if (binder != null) {
            mInstalld = IInstalld.Stub.asInterface(binder);
            ...
        }
    }
    
    public long createAppData(String uuid, String packageName, int userId, int flags, int appId,
            String seInfo, int targetSdkVersion) throws InstallerException {
        if (!checkBeforeRemote()) return -1;
        try {
            return mInstalld.createAppData(uuid, packageName, userId, flags, appId, seInfo,
                    targetSdkVersion);
        } catch (Exception e) {
            throw InstallerException.from(e);
        }
    }
    ...
}

The main attention in the above code:

  • The referenced aidl is android.os.IInstalld;
  • Get IBinder through getService("installd");
  • IInstalld.Stub.asInterface() Get proxy;

The main purpose is to determine the location of the compiled source code of aidl. For Android R, aidl under the framework will be unified under the directory out\soong\.intermediates\frameworks\base\module-lib-api\android_common\gen\aidl .

The JAVA files compiled by aidl will eventually be packaged into aidl*.srcjar , so how to determine the specific files? It needs to depend on the *.aidl.d files in the frameworks folder or system folder.

If the aidl file is defined under frameworks, then you can go to the corresponding directory under the framework to find the corresponding *.aidl.d file. Similarly, if aidl is defined under system, you can search for *.aidl.d files under the system folder. For example, the IInstalld.aidl here is defined under frameworks/native/cmds/installd , then go to the corresponding location under the frameworks folder to find the IIntalld.aidl.d file:

out/soong/.intermediates/frameworks/base/module-lib-api/android_common/gen/aidl/aidl27.tmp/frameworks/native/cmds/installd/binder/android/os/IInstalld.java : \
  frameworks/native/cmds/installd/binder/android/os/IInstalld.aidl \
  frameworks/native/cmds/installd/binder/android/os/storage/CrateMetadata.aidl

frameworks/native/cmds/installd/binder/android/os/IInstalld.aidl :
frameworks/native/cmds/installd/binder/android/os/storage/CrateMetadata.aidl :

The first line specifies that the Java file compiled by IInstalld.aidl is located in aidl27.tmp, which is the aidl27.srcjar file in the above figure. After decompression, IInstalld.java can be found:

package android.os;
/** {@hide} */
public interface IInstalld extends android.os.IInterface
{
    ...
    public static abstract class Stub extends android.os.Binder implements android.os.IInstalld
    {
        ...
        public static android.os.IInstalld asInterface(android.os.IBinder obj)
        {
          if ((obj==null)) {
            return null;
          }
          android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
          if (((iin!=null)&&(iin instanceof android.os.IInstalld))) {
            return ((android.os.IInstalld)iin);
          }
          return new android.os.IInstalld.Stub.Proxy(obj);
        }
    }
    ...
}

3. Communication between Java client and service

There are two ways for binder service, java side and native side. But for the client, it is only responsible to find the proxy of the service through getService, and call the transact communication through this proxy, while for the service, the driver only notifies its BBinder, and processes it through onTransact.

However, BBinder also exists in two ways, java service is JavaBBinder (inherited from BBinder), and native service is BBinder.

Therefore, no matter the client or service is located on the java side or the native side, the root cause is the communication between BpBinder and BBinder.

For the following frame diagram of the binder communication on the Java side,  it will be described in detail in the article on service registration and acquisition on the Java side .

Continuing with the above IInstalld.aidl,  several files will be compiled under the out/soong/.intermediates/frameworks/native/cmds/installd/installd/.../gen/aidl/ directory.

The android/os under this directory are the compiled header files:

frameworks/native/cmds/installd/binder/android/os under this directory is the compiled implementation file:

However, installd has a service in native that inherits BnInstalld:

frameworks/native/cmds/installd/InstalldNativeService.h

class InstalldNativeService : public BinderService<InstalldNativeService>, public os::BnInstalld {
public:
    ...
};

So far, the examples of CS under java have been basically explained, and the communication of binder can be better understood by combining actual operations. 

 

 

Guess you like

Origin blog.csdn.net/jingerppp/article/details/131437274