AIDL for HALs in practice

Stable AIDL HAL in practice

background:

Official: https://source.android.com/devices/architecture/aidl/aidl-hals.

Google introduced it in Android 11 AIDL for HALs, aiming to replace the original role of HIDL. In later Android versions, it is recommended to use AIDL to achieve Hal layer access.
The reasons for doing this should be the following:

  1. AIDL has been around longer than HIDL (only from Android 8 to Android 10) and is used in many other places, such as between Android framework components or within applications. Since AIDL has stability support, a single IPC method can be used from the HAL to the framework process or application process.
  2. AIDL also has a better version control system than HIDL.

To expand on it in more detail:

  1. AIDL is more mature and widely used. If the HAL layer also uses AIDL, it can be directly called from the application process to the HAL process. In the past, when HIDL was used, the application process accessed HAL services, which required the intermediary of the system server process. . Here’s a picture:
    Insert image description here
  2. In the past, if HIDL was used, if the subsequent vendor HAL version needed to be iteratively upgraded, then a subdirectory would need to be created. In fact, a lot of repetitive work would be done in the process, which was redundant and inefficient.

It is worth noting that AIDL must be used in the HAL layer Stable AIDL, which is slightly different from what we use in the application layer or framework layer, because the interface design with the vendor must take into account stability, and the update rates of system and vendor are different.

HALs using AIDL to communicate between framework components must use Stable AIDL.

Using AIDL for HALs

1. Define HAL interface

Create the corresponding module directory: /hardware/interfaces/hongxi/aidl/
Create aidl file:/hardware/interfaces/hongxi/aidl/android/hardware/hongxi/IHongxi.aidl

package android.hardware.hongxi;

@VintfStability
interface IHongxi {
    
    
    String getName();
    
    void setName(in String msg);
}

Every type definition must be annotated with @VintfStability.
If you want to define a type, just refer to the definition of the same AIDL. At the same time, there are more enumerations, structures, and parcelable types than the general AIDL (note that these types are related to the Android version, and versions below 13 may not have all of them)

2. Configure Android.bp

Create top-level Android.bp:/hardware/interfaces/hongxi/aidl/Android.bp

aidl_interface {
    
    
   name: "android.hardware.hongxi",
   vendor: true,
   srcs: ["android/hardware/hongxi/*.aidl"],
   stability: "vintf",
   owner: "hongxi.zhu",
   backend: {
    
    
       cpp: {
    
    
           enabled: false,
       },
       java: {
    
    
       	   enabled: false,
       },
   },
}
  1. backend: The backend of the service. AIDL supports four backends, namely C++/JAVA/NDK/RUST. We will use NDK (recommended by Google), so declare the CPP and JAVA backends as false (actually I tried this Two, there is a compilation problem that has not been solved yet. It will be updated later when it is solved).

  2. In order to facilitate testing, set vendor:true and delete vendor_available. Because this is a custom vendor HAL, delete the vndk part. Therefore, this HAL is only located in the vendor partition and is not subject to VNDK restrictions. It is under real development. If you need to enable VNDK, you need to solve it yourself. The limitations are not listed separately here.

3. Compile module

mmm hardware/interfaces/hongxi/

Then an error will be reported:

[ 74% 227/303] echo "API dump for the current version of AIDL interface android.hardware.hongxi does not exist." && echo Run "m android.hardware.hongxi-update-api", or add "unstable: true" to the build ru
FAILED: out/soong/.intermediates/hardware/interfaces/hongxi/aidl/android.hardware.hongxi-api/checkapi_current.timestamp
echo "API dump for the current version of AIDL interface android.hardware.hongxi does not exist." && echo Run "m android.hardware.hongxi-update-api", or add "unstable: true" to the build rule for the inte
rface if it does not need to be versioned && false
API dump for the current version of AIDL interface android.hardware.hongxi does not exist.
Run m android.hardware.hongxi-update-api, or add unstable: true to the build rule for the interface if it does not need to be versioned
19:29:13 ninja failed with: exit status 1

The reason is that the current version does not have this interface, and the API needs to be updated. Follow the prompts:

m android.hardware.hongxi-update-api

Then recompile the module:

mmm hardware/interfaces/hongxi/

4. Implement HAL interface

We will use the ndk_platfrom library, therefore, let check the generated code for ndk_platform. We need to reference the module in the interface compilation script we implement, and the interface we want to ndk_platfromimplement has the corresponding source code generated during compilation, we only need to copy came out and implemented, so let’s take a look at what was generated by the compilation just now:

cd out/soong/.intermediates/hardware/interfaces/hongxi/aidl/android.hardware.hongxi-ndk_platform-source
find .

.
./gen
./gen/android
./gen/android/hardware
./gen/android/hardware/hongxi
./gen/android/hardware/hongxi/IHongxi.cpp.d
./gen/android/hardware/hongxi/IHongxi.cpp
./gen/include
./gen/include/aidl
./gen/include/aidl/android
./gen/include/aidl/android/hardware
./gen/include/aidl/android/hardware/hongxi
./gen/include/aidl/android/hardware/hongxi/BpHongxi.h
./gen/include/aidl/android/hardware/hongxi/BnHongxi.h
./gen/include/aidl/android/hardware/hongxi/IHongxi.h
./gen/timestamp

Find the interface we want to implement in the IHongxi.h header file:

  virtual ::ndk::ScopedAStatus getName(std::string* _aidl_return) = 0;
  virtual ::ndk::ScopedAStatus setName(const std::string& in_msg) = 0;

Next, you need to create a back-end source code file to implement these interfaces:
/hardware/interfaces/hongxi/aidl/default/Hongxi.h

#pragma once

#include <aidl/android/hardware/hongxi/BnHongxi.h>

namespace aidl {
namespace android {
namespace hardware {
namespace hongxi {

class Hongxi : public BnHongxi {
    public:
        //String getName();
        ndk::ScopedAStatus getName(std::string* _aidl_return);

        //void setName(in String msg);
        ndk::ScopedAStatus setName(const std::string& in_msg);

    private:
        std::string name = "";
};

}  // namespace hongxi
}  // namespace hardware
}  // namespace android
}  // namespace aidl

/hardware/interfaces/hongxi/aidl/default/Hongxi.cpp

#define LOG_TAG "Hongxi"

#include <utils/Log.h>
#include <iostream>
#include "Hongxi.h"

namespace aidl {
namespace android {
namespace hardware {
namespace hongxi {

ndk::ScopedAStatus Hongxi::getName(std::string* _aidl_return) {

    *_aidl_return = name;

    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus Hongxi::setName(const std::string& in_msg) {

    name = in_msg;

    return ndk::ScopedAStatus::ok();
}

}  // namespace hongxi
}  // namespace hardware
}  // namespace android
}  // namespace aidl

5. Implement services:

/hardware/interfaces/hongxi/aidl/default/main.cpp

#define LOG_TAG "Hongxi"

#include <android-base/logging.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include "Hongxi.h"

using aidl::android::hardware::hongxi::Hongxi;
using std::string_literals::operator""s;

int main() {
    // Enable vndbinder to allow vendor-to-venfor binder call
    android::ProcessState::initWithDriver("/dev/vndbinder"); //使用vnbinder的配置

    ABinderProcess_setThreadPoolMaxThreadCount(0); // vnbinder的线程池独立,需要单独配置 
    ABinderProcess_startThreadPool();

    std::shared_ptr<Hongxi> hongxi = ndk::SharedRefBase::make<Hongxi>();
    const std::string desc = Hongxi::descriptor + "/default"s;

    if (hongxi != nullptr) {
        if(AServiceManager_addService(hongxi->asBinder().get(), desc.c_str()) != STATUS_OK) {
            ALOGE("Failed to register IHongxi service");
            return -1;
        }
    } else {
        ALOGE("Failed to get IHongxi instance");
        return -1;
    }

    ALOGD("IHongxi service starts to join service pool");
    ABinderProcess_joinThreadPool();

    return EXIT_FAILURE;  // should not reached
}

8. Write the rc script to start the service

/hardware/interfaces/hongxi/aidl/default/android.hardware.hongxi-service.rc

service android.hardware.hongxi-service /vendor/bin/hw/android.hardware.hongxi-service
        interface aidl android.hardware.hongxi.IHongxi/default
        class hal
        user system
        group system

9. Declare VINTF AIDL interface

/hardware/interfaces/hongxi/aidl/default/android.hardware.hongxi-service.xml

<manifest version="1.0" type="device">
    <hal format="aidl">
        <name>android.hardware.hongxi</name>
        <fqname>IHongxi/default</fqname>
    </hal>
</manifest>

7. Write service build scripts

/hardware/interfaces/hongxi/aidl/default/Android.bp

cc_binary {
    
    
    name: "android.hardware.hongxi-service",
    vendor: true,
    relative_install_path: "hw",
    init_rc: ["android.hardware.hongxi-service.rc"],
    vintf_fragments: ["android.hardware.hongxi-service.xml"],

    srcs: [
        "Hongxi.cpp",
        "main.cpp",
    ],

    cflags: [
        "-Wall",
        "-Werror",
    ],

    shared_libs: [
        "libbase",
        "liblog",
        "libhardware",
        "libbinder_ndk",
        "libbinder",
        "libutils",
        "android.hardware.hongxi-ndk_platform",
    ],
}

Add the module to the system

/build/target/product/base_vendor.mk

# add for Hongxi
PRODUCT_PACKAGES += \
    android.hardware.hongxi \
    android.hardware.hongxi-service \

Add module to compatibility matrix

# (选下标最新的那个)
hardware/interfaces/compatibility_matrices/compatibility_matrix.5.xml
#(这个不一定有,如果没有就不加)
hardware/interfaces/compatibility_matrices/compatibility_matrix.current.xml
    <hal format="aidl" optional="true">
        <name>android.hardware.hongxi</name>
        <version>1.0</version>
        <interface>
            <name>IHongxi</name>
            <instance>default</instance>
        </interface>
    </hal>

Resolving Selinux permissions

This follow-up supplement, during testing, will have a macro version and a directly added version.

client test

  1. cpp-client(user process)
  2. apk-client(user process)
  3. SystemService-client(system server process)

Guess you like

Origin blog.csdn.net/qq_40731414/article/details/126823262