HIDL Service creation process - based on Android 12 S analysis

Table of contents

How to add HIDL service

1. Add hidl service folder

2. Add .hal file

3. Compile hidl-gen

4. Configure the package root of hidl

5. Generate .cpp and .h files under 1.0/default/

6. Generate Android.bp under 1.0/default/

7. Generate Android.bp under 1.0

8. Execute the following command in the main directory android to generate current.txt

9. Add vendor.qti.hardware.customizehidl-service.rc under 1.0/default/

10. Add vendor.qti.hardware.customizehidl-service.xml under 1.0/default/

11. Add the following content in device/qcom/common/vendor_compatibility_matrix.xml

12. Add service.cpp under 1.0/default/

13. Write a test bin program

14. Test

14.1 Single compilation method:

14.2 Test method:

15. Possible problems

15.1 Error 1

15.2 Add a new directory to put hal service

16. Add custom Hal service Selinux


The purpose of the HIDL mechanism is mainly to isolate the framework (framework) from the HAL, so that the framework part can be directly overwritten and updated without recompiling the HAL. Parts of the HAL will be placed in the /vendor partition of the device and built by the device vendors (vendors) or the SOC manufacturer. This allows framework parts to be updated OTA without recompiling the HAL.

This design is called the Treble mechanism, introduced from Android 8.0. Before this, the framework needs to call dlopen to open the .so compiled by HAL in order to communicate with the HAL layer. In this way, the framework and HAL are in the same process, and the coupling between the two is serious, which causes the supplier to do a lot of adaptation work when the version is upgraded.

       The Treble mechanism solves the problem of troublesome upgrades between Android versions. It separates the part of the vendor adapted by OEM from the part of the system part that google upgrades to the android framework. Once the vendor information of a version is adapted, subsequent versions can When upgrading, you can directly upgrade the system, which will not bring too much workload to the OEM manufacturer to upgrade, and directly upgrade the latest functions, which can solve the problem that the current Android version on the market is too messy.

The Treble mechanism has two modes in the Vendor partition, passthrough mode (Passthrough) and binding mode (Binderized). The general framework diagram is as follows. For devices before Android O, it corresponds to Figure 1. For the version upgraded from the previous device to O , corresponding to Figure 2 and Figure 3. For devices developed directly based on Android O, it corresponds to Figure 4.

Generally, new HIDL services are added under the vendor directory. It is best to add folders under your own product name and create corresponding HIDL services. Assuming that you want to add HIDL services under qcom, the process is as follows:

How to add HIDL service

1. Add hidl service folder

Add a new folder under vendor/qcom/opensource/interfaces, add a customizehidl folder here

Create a new 1.0 folder under customizehidl

Add a default folder under 1.0

2. Add .hal file

Add ICustomizehidl.hal and types.hal files under customizehidl

vendor/qcom/opensource/interfaces/ICustomizehidl.hal
package [email protected];

interface ICustomizeHidl{
    resetOption(int32_t side) generates (Result result);
};
vendor/qcom/opensource/interfaces/types.hal
package [email protected];

enum Result : int32_t {
    OK = 0,
    ERR,
    OUT_OF_RANGE,
};

3. Compile hidl-gen

    source build/envsetup.sh

    lunch xx

    make filter-gen

In this way, the hidl-gen tool can be used later ,

4. Configure the package root of hidl

    PACKAGE=vendor.qti.hardware.customizehidl@1.0

    LOC=vendor/qcom/opensource/interfaces/customizehidl/1.0/default/

If there is an error as follows

ERROR: Package root not specified for [email protected]

ERROR: Could not get sources for [email protected].

You need to add the following code in the following directory:

vendor/qcom/opensource/interfaces/Android.bp

hidl_package_root {
    name:"vendor.qti.hardware.customizehidl",
    path:"vendor/qcom/opensource/interfaces/customizehidl",
}  

5. Generate .cpp and .h files under 1.0/default/

Generate .cpp and .h files under vendor/qcom/opensource/interfaces/ customizehidl /1.0/default/:

hidl-gen -o $LOC -Lc++-impl -rvendor.qti.hardware:vendor/qcom/opensource/interfaces -randroid.hidl:system/libhidl/transport $PACKAGE

or

hidl-gen -o vendor/qcom/opensource/interfaces/customizehidl/1.0/default -Lc++-impl -rvendor.qti.hardware:vendor/qcom/opensource/interfaces –randroid.hidl:system/libhidl/transport vendor.qti.hardware.customizehidl@1.0

Then the CustomizeHidl.cpp and CustomizeHidl.h files are generated. Relevant modifications need to be made after generation. The modified content is as follows:

vendor/qcom/opensource/interfaces/customizehidl/1.0/default/CustomizeHidl.cpp
#include "CustomizeHidl.h"
#include <pthread.h>
#include <sched.h>
#include <map>

#include <fcntl.h>
#include <unistd.h>

namespace vendor {
namespace qti {
namespace hardware {
namespace customizehidl {
namespace V1_0 {
namespace implementation {

CustomizeHidl::CustomizeHidl() {
}

CustomizeHidl::~CustomizeHidl() {
}

Return<::vendor::qti::hardware::customizehidl::V1_0::Result> CustomizeHidl::resetOption(int32_t side) {
    return ::vendor::qti::hardware::customizehidl::V1_0::Result {};
}

// Methods from ::android::hidl::base::V1_0::IBase follow.
//ICustomizeHidl* HIDL_FETCH_ICustomizeHidl(const char* /* name */) {
//    return new CustomizeHidl();
//}
//
}  // implementation
}  // V1_0
}  // customizehidl
}  // hardware
}  // qti
}  // vendor

 The contents of the header file are as follows:

vendor/qcom/opensource/interfaces/customizehidl/1.0/default/CustomizeHidl.h
#include <vendor/qti/hardware/customizehidl/1.0/ICustomizeHidl.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
#include <fstream>
#include <iostream>

namespace vendor {
namespace qti {
namespace hardware {
namespace customizehidl {
namespace V1_0 {
namespace implementation {

using namespace std;
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_memory;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::sp;

struct CustomizeHidl : public ICustomizeHidl {
    CustomizeHidl();
    ~CustomizeHidl();
    Return<::vendor::qti::hardware::customizehidl::V1_0::Result> resetOption(int32_t side) override;

};

// FIXME: most likely delete, this is only for passthrough implementations
// extern "C" ICustomizeHidl* HIDL_FETCH_ICustomizeHidl(const char* name);

}  // implementation
}  //customizehidl
}  // V1_0
}  // hardware
}  // qti
}  // vendor

6. Generate Android.bp under 1.0/default/

Generate Android.bp under vendor/qcom/opensource/interfaces/ customizehidl /1.0/default/:

hidl-gen -o $LOC -Landroidbp-impl -rvendor.qti.hardware:vendor/qcom/opensource/interfaces -randroid.hidl:system/libhidl/transport $PACKAGE

Relevant modifications need to be made after generation. The modified content is as follows:

cc_defaults{
    name: "customizehidl_defaults",
    //relative_install_path: "hw",
    defaults: ["hidl_defaults"],
    //根据项目需求
    //vendor: true,
    proprietary: true,
    cflags: [
       "-Wno-unused-parameter",
       "-Wall",
    ],
    shared_libs: [
            "libcutils",
            "liblog",
            "libbase",
            "libsysutils",
            "libhidlbase",
            "libhidltransport",
            "libutils",
            "[email protected]",
        ],

}

cc_library_shared {
    name: "[email protected]",
    relative_install_path: "hw",
    //根据项目需求
    //vendor: true,
    proprietary: true,
    cflags: [
           "-Wno-unused-parameter",
           "-Wall",
           "-Wunused-variable",
           "-Wunused-const-variable",
           "-Wunused-variable",
    ],
    srcs: [
        "CustomizeHidl.cpp",
    ],
    defaults: ["customizehidl_defaults"],
}

cc_binary {
    name: "[email protected]",
    proprietary: true,
    compile_multilib: "both",
    relative_install_path: "hw",
    defaults: ["customizehidl_defaults"],
    //rc引用
    init_rc: ["vendor.qti.hardware.customizehidl-service.rc"],
    //vintf_fragments引用
    vintf_fragments: ["vendor.qti.hardware.customizehidl-service.xml"],
    srcs: [
        "service.cpp",
    ],
    shared_libs: [
        "libcutils",
        "liblog",
        "libbase",
        "libsysutils",
        "libhidlbase",
        "libhidltransport",
        "libutils",
        "[email protected]",
    ],

}

7. Generate Android.bp under 1.0

Generate Android.bp under vendor/qcom/opensource/interfaces/ customizehidl /1.0

source system/tools/hidl/update-makefiles-helper.sh

do_makefiles_update vendor.qti.hardware:vendor/qcom/opensource/interfaces android.hardware:hardware/interfaces android.hidl:system/libhidl/transport

Relevant modifications need to be made after generation. The modified content is as follows:

hidl_interface {
    name: "[email protected]",
    root: "vendor.qti.hardware.customizehidl",
    //根据需求进行设置
    //product_specific: true,
    system_ext_specific: true,
    srcs: [
        "types.hal",
        "ICustomizeHidl.hal",
    ],
    interfaces: [
        "[email protected]",
    ],
    gen_java: true,
}

8. Execute the following command in the main directory android to generate current.txt

hidl-gen -Lhash -rvendor.qti.hardware:vendor/qcom/opensource/interfaces -randroid.hidl:system/libhidl/transport vendor.qti.hardware.customizehidl@1.0 > vendor/qcom/opensource/interfaces/customizehidl/current.txt

9. Add vendor.qti.hardware.customizehidl -service.rc under 1.0/default/

Add the following content

service vendor.qti.hardware.customizehidl-1-0 /vendor/bin/hw/[email protected]
class hal
user system
group system

10. Add vendor.qti.hardware.customizehidl-service.xml under 1.0/default/

<manifest version="1.0" type="device">
    <hal format="hidl">
        <name>vendor.qti.hardware.customizehidl</name>
        <transport>hwbinder</transport>
        <version>1.0</version>
        <interface>
            <name>ICustomizeHidl</name>
            <instance>default</instance>
        </interface>
    </hal>
</manifest>

11. Add the following content in device/qcom/common/vendor_compatibility_matrix.xml (I didn’t add it here, it can still run)

    <hal format="hidl" optional="true">
        <name>vendor.qti.hardware.customizehidl</name>
        <transport>hwbinder</transport>
        <version>1.0</version>
        <interface>
            <name>ICustomizeHidl</name>
            <instance>default</instance>
        </interface>
    </hal>

12. Add service.cpp under 1.0/default/

If the Binderized method is used, as follows

#include <android-base/logging.h>
#include <hidl/HidlTransportSupport.h>
#include "CustomizeHidl.h"
#include <utils/Log.h>
#include <hidl/LegacySupport.h>
using namespace android;
using vendor::qti::hardware::customizehidl::V1_0::ICustomizeHidl;
using vendor::qti::hardware::customizehidl::V1_0::implementation::CustomizeHidl;
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
using android::sp;

int main(int /* argc */, char ** /* argv */) {
    sp<ICustomizeHidl> service = new CustomizeHidl();
    configureRpcThreadpool(1, true /*callerWillJoin*/);
    if (::android::OK != service->registerAsService()) {
        return -1;
    }
    joinRpcThreadpool();
    return 0;
}

If you want to use the Passthrough method, you need to write main as follows, but at the same time you need to release the HIDL_FETCH_ICustomizeHidl method in CustomizeHidl.cpp and CustomizeHidl.h.

#include <android-base/logging.h>
#include <hidl/HidlTransportSupport.h>
#include "CustomizeHidl.h"
#include <utils/Log.h>
#include <hidl/LegacySupport.h>
using namespace android;
using vendor::qti::hardware::customizehidl::V1_0::ICustomizeHidl;
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
using android::hardware::defaultPassthroughServiceImplementation;
using android::hardware::registerPassthroughServiceImplementation;

int main() {
	android::status_t status;

	configureRpcThreadpool(10, false);
	status = registerPassthroughServiceImplementation<ICustomizeHidl>();

	LOG_ALWAYS_FATAL_IF(status != OK, "Error while registering ICustomizeHidl: %d", status);

	joinRpcThreadpool();
	return status;
}

13. Write a test bin program

Add a hidl_test_bin directory under vendor/qcom/opensource/interfaces/ customizehidl /, and add Android.bp

cc_binary {
    name: "hidl_test_bin",
                                                                                                                                                                                         
    srcs: [
        "hidl_test_bin.cpp",
    ],  
    shared_libs: [
        "libcutils",
        "libutils",
        "liblog",
//以下so一定要添加,否则可能会有报错
        "libbinder",
        "libhidlbase",
        "libbase",
        "libhidltransport",
        "[email protected]",
    ],  

    cflags: [
        "-Werror",
        "-Wno-error=deprecated-declarations",
        "-Wno-unused-parameter",
        "-Wall",
    ],  
}

Add hidl_test_bin.cpp file

#define LOG_TAG "hidl_test_bin"
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
#include <cutils/properties.h>
#include <fcntl.h>
#include <utils/Log.h>
#include <iostream>
#include <vendor/qti/hardware/customizehidl/1.0/ICustomizeHidl.h>
#include <vendor/qti/hardware/customizehidl/1.0/types.h>

using namespace android;
using namespace std;
using vendor::qti::hardware::customizehidl::V1_0::ICustomizeHidl;
using vendor::qti::hardware::customizehidl::V1_0::Result;
using android::hardware::Return;
using android::hardware::details::return_status;
using android::hardware::Void;
sp<ICustomizeHidl> halService;

int main(int argc, char* argv[]) {
    halService = ICustomizeHidl::getService();
    if (halService == NULL){
        cout << "get hal service failed" <<endl;
        return -1; 
    }   
    cout << "get hal service scuess" <<endl;
    float value = stof(argv[1]);
    cout << "value is " << value <<endl;
    halService->resetOption(value);
    return 0;
}

14. Test

14.1 Single compilation method:

    source build/envsetup.sh

    lunch xxx

    cd vendor/qcom/opensource/interfaces/customizehidl

    mma (compiling hidl service related)

    cd vendor/qcom/opensource/interfaces/customizehidl/hidl_test_bin

    mma (compiled test bin related)

14.2 Test method:

1. adb pull vendor/etc/vintf/compatibility_matrix.xml

在最后增加
    <hal format="hidl" optional="true">
        <name>vendor.qti.hardware.customizehidl</name>
        <transport>hwbinder</transport>
        <version>1.0</version>
        <interface>
            <name>ICustomizeHidl</name>
            <instance>default</instance>
        </interface>
    </hal>

2. Push back again

adb root
adb remount

adb push compatibility_matrix.xml vendor/etc/vintf/compatibility_matrix.xml

3. Execute under out/target/product/qssi

adb push ./product/lib/[email protected] product/lib/
adb push ./product/lib64/[email protected] product/lib64/
adb push ./vendor/lib/hw/[email protected] vendor/lib/hw/
adb push ./vendor/lib/[email protected] vendor/lib/
adb push ./vendor/lib64/hw/[email protected] vendor/lib64/hw/
adb push ./vendor/lib64/[email protected] vendor/lib64/
adb push ./vendor/etc/vintf/manifest/vendor.qti.hardware.customizehidl-service.xml vendor/etc/vintf/manifest
adb push ./vendor/bin/hw/[email protected] vendor/bin/hw/
adb push ./system_ext/lib/[email protected] system_ext/lib/
adb push ./system_ext/lib64/[email protected] system_ext/lib64/
adb push system/ bin/hidl_test_bin system/bin (tested bin program)
and then execute
adb reboot
to restart and
close selinux: adb shell setenforce 0
window 1: start hidl service
adb shell
cd vendor/bin/hw
./[email protected] -service


Window 2: Start the test bin program   
adb shell
hidl_test_bin 100


Then observe what is output in window 2.
If the output is as follows, it means the communication between the two is successful.
get hal service scuess
value is 100

15. Possible problems

15.1 Error 1

04-14 12:27:02.103   599   599 I hwservicemanager: getTransport: Cannot find entry [email protected]::ICustomizeHidl/default in either framework or device VINTF manifest.
04-14 12:27:02.104  4169  4169 E HidlServiceManagement: Service [email protected]::ICustomizeHidl/default must be in VINTF manifest in order to register/get

That is, there is a problem with the configuration related to the vintf manifest. You can check whether there is a push corresponding manifest file, whether the content of the interface is written correctly, etc.

15.2 Add a new directory to put hal service

If the newly created directory cannot compile the relevant hidl out related files, you need to add the update-makefiles.sh file, which can be copied from other hidl directories and modify the directory.

set -e

if [ -z "$ANDROID_BUILD_TOP" ]; then
    echo "Missing ANDROID_BUILD_TOP env variable. Run 'lunch' first."
    exit 1
fi

source $ANDROID_BUILD_TOP/system/tools/hidl/update-makefiles-helper.sh

do_makefiles_update \
  "vendor/newname/interfaces/customizehidl"

16. Add custom Hal service Selinux

Please refer to my other article

Add custom Hal service selinux permissions_Come on (◍>∇<◍)ノ゙'s Blog

Guess you like

Origin blog.csdn.net/weixin_41028555/article/details/130424627