• HIDL学习笔记


    一、HIDL简单介绍

    HIDL是Android8.0新出的一个技能,以service和client的方式实现hal接口,目的是想使Android系统和BSP解绑,使系统升级更加方便。HIDL的使用方法一般是先提供.hal文件,然后使用hidl-gen工具生成 框架源文件和Android.bp编译工具文件,之后填充生成的源文件和定制Android.bp编译文件。

    二、修改源HIDL文件添加hal接口

    以Qucomm蓝牙模块额外提供BT MAC地址访问接口为例进行机介绍

    [ubuntu @fm]$ tree
    .
    ├── 1.0
    │   ├── Android.bp
    │   ├── Android.mk
    │   ├── hidl-gen.sh
    │   ├── IFmHciCallbacks.hal
    │   ├── IFmHci.hal
    │   └── types.hal
    └── Android.bp

    1.修改提供.hal文件

    # cat vendor/qcom/proprietaryinterfaces/fm/1.0/IFmHci.hal
    package vendor.qti.hardware.fm@1.0;
    interface IFmHci {
         sendHciCommand(HciPacket command);
    +    getBluetoothMacAddress() generates (MacRet mret); //添加这个接口,MacRet (void)类型
    };
    
    # cat vendor/qcom/proprietaryinterfaces/fm/1.0/types.hal
    package vendor.qti.hardware.fm@1.0;
    struct MacRet {     //添加这个结构体
       uint8_t mac0;    //写成数组测试不行,hidl不自持吧。
       uint8_t mac1;
       uint8_t mac2;
       uint8_t mac3;
       uint8_t mac4;
       uint8_t mac5;
       int8_t ret;
    };

    2.重新生成1.0目录下的Android.bp和Android.mk
    这两个文件是hidl-gen根据hal文件自动生成的,用户不要去改。因为hal文件变了,因此需要重新生成。

    # rm 1.0/Android.mk
    # rm 1.0/Android.bp
    # hidl-gen -Landroidbp -r vendor.qti.hardware:vendor/qcom/proprietary/interfaces -r android.hidl:system/libhidl/transport vendor.qti.hardware.fm@1.0
    # hidl-gen -Lmakefile -r vendor.qti.hardware:vendor/qcom/proprietary/interfaces -r android.hidl:system/libhidl/transport vendor.qti.hardware.fm@1.0    //一般情况下只需要重新生成Android.bp就可以了。

    3.生成hal文件中新添加函数的C++代码实现框架
    可以根据hal文件生成cpp文件,然后从新生成的cpp文件中拷贝出getBluetoothMacAddress的cpp实现框架,然后将其拷贝到原cpp文件中。注意,需要在指定在一个临时的目录中生成C++实现框架文件,以免将已经存在原来的C++文件覆盖掉。
    # hidl-gen -o tmp_dir -Lc++-impl -r vendor.qti.hardware:vendor/qcom/proprietary/interfaces -r android.hidl:system/libhidl/transport vendor.qti.hardware.fm@1.0
    此时会在tmp_dir中生成FmHci.cpp文件和FmHci.h文件,拷贝这两个文件中getBluetoothMacAddress()到原来的C++实现文件的对应位置

    # cat FmHci.h
    struct FmHci : public IFmHci {
        ...
        Return<void> getBluetoothMacAddress(getBluetoothMacAddress_cb _hidl_cb) override; //拷贝过来
        ...
    };
    
    # cat FmHci.cpp
    Return<void> FmHci::getBluetoothMacAddress(getBluetoothMacAddress_cb _hidl_cb) { //参数是个回调函数
        bool ret;
        MacRet mret; //这里不需要加struct
    
        ret = BluetoothAddress::GetLocalAddress((uint8_t *)&mret);
        if (ret == true) {
            mret.ret = true;
        } else {
            memset(&mret, 0, sizeof(mret));
            mret.ret = false;
        }
         _hidl_cb(mret); //给回调函数传参,回调的函数来自client
    
         return Void();
    }

    4.收尾工作
    (1)使用using导入使用的元素
    FmHci.h中:
    using android::hardware::bluetooth::V1_0::implementation::BluetoothAddress; //导入FmHci.cpp文件中使用到的BluetoothAddress::GetLocalAddress()所在的类。
    (2)添加头文件搜索路径
    在Android.mk中:

    LOCAL_C_INCLUDES += vendor/qcom/proprietary/qmi-framework/inc
    LOCAL_C_INCLUDES += vendor/qcom/proprietary/qmi/inc
    LOCAL_C_INCLUDES += vendor/qcom/proprietary/bt/hci_qcomm_init

    若此时能编译成功,则Service端添加的这个hal接口就添加好了。

    5.编写测试程序进行验证
    一般测试程序放在/external/tools目录下,也可以放在hal实现目录下的vts目录下
    (1)编写测试cpp文件

    //[ubuntu @btaddr_test]$ cat btaddr_client.cpp 
    #include <stdio.h>
    #include <android/hardware/btaddr/1.0/IBtaddr.h>
    #include <android/hardware/btaddr/1.0/types.h>
    
    using ::android::hardware::btaddr::V1_0::IBtaddr;
    using ::android::hardware::btaddr::V1_0::MacRet;
    using namespace std;
    
    MacRet g_mret;
    
    IBtaddr::getBluetoothMacAddress_cb get_mac_addr(android::hardware::btaddr::V1_0::MacRet mret)
    {
        g_mret = mret;
    
        return nullptr;
    }
    
    int main()
    {
        android::sp<IBtaddr> service = IBtaddr::getService();
        if (service == nullptr){
            printf("SFL: Failed to get service
    ");
            return -1;
        }
        service->getBluetoothMacAddress(get_mac_addr);
    
        printf("MAC=0x%x 0x%x 0x%x 0x%x 0x%x 0x%x
    ", g_mret.mac0, g_mret.mac1, g_mret.mac2, g_mret.mac3, g_mret.mac4, g_mret.mac5);
    
        return 0;
    }


    (2)编写Android.bp

    //[ubuntu @btaddr_test]$ cat Android.bp 
    cc_binary {
        name: "btaddr_test",
        vendor: true,
        srcs: ["btaddr_client.cpp"],
        cflags: ["-Wall"],
        shared_libs: [
            "liblog",
            "libutils",
            "libhidltransport",
            "android.hardware.btaddr@1.0",
            "libhidlbase",
            "libbase",
        ],
    }

    (3)将测试程序btaddr_test安装到文件系统
    在device/qcom/common/base.mk中添加
    XX_TEST_APPS += demo_client  //XX_TEST_APPS环境变量里面的所有可执行程序都会被编译进文件系统

    然后就可以重新烧录验证了。

    三、独立实现HIDL文件

    1.实现.hal文件

    /media/ubuntu/work/g6pa_mount/G6PA_NEW/LINUX/android/hardware/interfaces/btaddr
    [hardware/interfaces/btaddr: @btaddr]$ tree
    .
    ├── 1.0
        ├── IBtaddr.hal
        └── types.hal
    
    //# cat 1.0/IBtaddr.hal 
    package android.hardware.btaddr@1.0;
    
    interface IBtaddr {
        getBluetoothMacAddress() generates (MacRet mret);
    };
    
    
    //# cat 1.0/types.hal
    package android.hardware.btaddr@1.0;
    
    struct MacRet {
       uint8_t mac0;
       uint8_t mac1;
       uint8_t mac2;
       uint8_t mac3;
       uint8_t mac4;
       uint8_t mac5;
       int8_t ret;
    };


    2.由hal文件生成C++实现文件

    # hidl-gen -o hardware/interfaces/btaddr/1.0/default -Lc++-impl -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.btaddr@1.0
    会在1.0/default下生成Btaddr.cpp 和Btaddr.h
    
    # hidl-gen -o hardware/interfaces/btaddr/1.0/default -Landroidbp-impl -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.btaddr@1.0
    会在1.0/default下生成Android.bp
    
    # ./hardware/interfaces/update-makefiles.sh
    会在btaddr下生成Android.bp 1.0下生成Android.bp和Android.mk
    
    此时:
    [ubuntu @btaddr]$ tree
    .
    ├── 1.0
    │   ├── Android.bp
    │   ├── Android.mk
    │   ├── default
    │   │   ├── Android.bp
    │   │   ├── Btaddr.cpp
    │   │   └── Btaddr.h
    │   ├── IBtaddr.hal
    │   └── types.hal
    └── Android.bp

    3.实现生成C++文件

    //[ubuntu @btaddr]$ cat 1.0/default/Btaddr.cpp 
    #define LOG_TAG "android.hardware.btaddr@1.0-impl"
    
    #include <string.h>
    #include <errno.h>
    
    #include "Btaddr.h"
    
    namespace android {
    namespace hardware {
    namespace btaddr {
    namespace V1_0 {
    namespace implementation {
    
    // Methods from IBtaddr follow.
    Return<void> Btaddr::getBluetoothMacAddress(getBluetoothMacAddress_cb _hidl_cb) {
        MacRet mret;
        mret.ret = 0;
        mret.mac0 = 0x11;
        mret.mac1 = 0x22;
        mret.mac2 = 0x33;
        mret.mac3 = 0x44;
        mret.mac4 = 0x55;
        mret.mac5 = 0x66;
    
        _hidl_cb(mret);
    
        return Void();
    }
    
    
    // Methods from ::android::hidl::base::V1_0::IBase follow.
    
    IBtaddr* HIDL_FETCH_IBtaddr(const char* /* name */) {
        return new Btaddr();
    }
    
    }  // namespace implementation
    }  // namespace V1_0
    }  // namespace btaddr
    }  // namespace hardware
    }  // namespace android
    //[ubuntu @btaddr]$ cat 1.0/default/Btaddr.h
    #ifndef ANDROID_HARDWARE_BTADDR_V1_0_BTADDR_H
    #define ANDROID_HARDWARE_BTADDR_V1_0_BTADDR_H
    
    #include <android/hardware/btaddr/1.0/IBtaddr.h>
    #include <hidl/MQDescriptor.h>
    #include <hidl/Status.h>
    
    namespace android {
    namespace hardware {
    namespace btaddr {
    namespace V1_0 {
    namespace implementation {
    
    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;
    
    using ::android::hardware::btaddr::V1_0::IBtaddr;
    using ::android::hardware::btaddr::V1_0::MacRet;
    
    struct Btaddr : public IBtaddr {
        // Methods from IBtaddr follow.
        Return<void> getBluetoothMacAddress(getBluetoothMacAddress_cb _hidl_cb) override;
    
        // Methods from ::android::hidl::base::V1_0::IBase follow.
    
    };
    
    // FIXME: most likely delete, this is only for passthrough implementations
    // extern "C" IBtaddr* HIDL_FETCH_IBtaddr(const char* name);
    
    }  // namespace implementation
    }  // namespace V1_0
    }  // namespace btaddr
    }  // namespace hardware
    }  // namespace android
    
    #endif  // ANDROID_HARDWARE_BTADDR_V1_0_BTADDR_H

    4.添加service.cpp和启动此service的android.hardware.btaddr@1.0-service.rc文件

    //[ubuntu @btaddr]# cat 1.0/default/service.cpp
    [ubuntu @btaddr]$ cat 1.0/default/service.cpp 
    #define LOG_TAG "android.hardware.btaddr@1.0-service"
    
    #include <android-base/logging.h>
    #include <hidl/HidlTransportSupport.h>
    #include <android/hardware/btaddr/1.0/IBtaddr.h>
    #include <hidl/LegacySupport.h>
    
    #include "Btaddr.h"
    
    using android::hardware::configureRpcThreadpool;
    using android::hardware::joinRpcThreadpool;
    using android::hardware::btaddr::V1_0::implementation::Btaddr;
    
    int main()
    {
        configureRpcThreadpool(1, true);
    
        Btaddr addr;
        auto status = addr.registerAsService();
        CHECK_EQ(status, android::OK) << "Failed to register btaddr HAL implementation";
    
        joinRpcThreadpool();
    
        return 1;
    }
    
    
    [ubuntu @btaddr]# cat 1.0/default/android.hardware.btaddr@1.0-service.rc 
    service btaddr-hal-1-0 /vendor/bin/hw/android.hardware.btaddr@1.0-service
        class core
        user root
        group root

    5.修改编译service的Android.bp

    [ubuntu @btaddr]# cat 1.0/default/Android.bp 
    cc_binary {
        name: "android.hardware.btaddr@1.0-service",
        vendor: true,
        relative_install_path: "hw",
        init_rc: ["android.hardware.btaddr@1.0-service.rc"],
        srcs: [
            "Btaddr.cpp",
            "service.cpp",
        ],
        cflags: [
            "-Wall",
        ],
        shared_libs: [
            "libhidlbase",
            "libhidltransport",
            "libutils",
            "android.hardware.btaddr@1.0",
            "liblog",
            "libutils",
            "libbase",
        ],
    }

    在btaddr下mm,若能build过,Service端就实现好了

    6.将编译出的service可执行程序编译进文件系统
    在/device/$(Vender)/$(Product)/$(Product).mk中添加: PRODUCT_PACKAGES += android.hardware.btaddr@1.0-service

    7.将这个hwservice注册到系统(这样getService()才能找到它) 在/device/$(Vender)/$(Product)/manifest.xml中添加:

    <hal format="hidl">
        <name>android.hardware.btaddr</name>
        <transport>hwbinder</transport>
        <version>1.0</version>
        <interface>
            <name>IBtaddr</name>
            <instance>default</instance>
        </interface>
    </hal>


    8.添加selinux权限
    在device/qcom/sepolicy/common/hwservice_contexts中添加:

    android.hardware.btaddr::IBtaddr     u:object_r:hal_btaddr_hwservice:s0
    android.hardware.btaddr::MacRet      u:object_r:hal_btaddr_hwservice:s0

    在device/qcom/sepolicy/common/hwservice.te中添加:

    type hal_btaddr_hwservice, hwservice_manager_type;

    在device/qcom/sepolicy/msm8996/file_contexts中添加:

    /(vendor|system/vendor)/bin/hw/android.hardware.btaddr@1.0-service    u:object_r:hal_btaddr_default_exec:s0

    添加文件:device/qcom/sepolicy/msm8996/hal_btaddr_default.te

    # cat device/qcom/sepolicy/msm8996/hal_btaddr_default.te 
    
    type hal_btaddr_default, domain;
    type hal_btaddr_default_exec, exec_type, vendor_file_type, file_type;
    
    allow hal_btaddr_default sysfs:file rw_file_perms;
    allow hal_btaddr_default hwservicemanager_prop:file r_file_perms;
    allow hal_btaddr_default hwservicemanager:binder { transfer call };
    
    allow hal_btaddr_default hal_btaddr_hwservice:binder call;
    allow hal_btaddr_default hal_btaddr_hwservice:hwservice_manager { add find };
    
    allow hal_btaddr_default hidl_base_hwservice:hwservice_manager add;
    
    init_daemon_domain(hal_btaddr_default)

    在/device/qcom/sepolicy/msm8996/hwservicemanager.te中添加:

    allow hwservicemanager hal_btaddr_default:process getattr;
    allow hwservicemanager hal_btaddr_default:binder { transfer call };
    allow hwservicemanager hal_btaddr_default:file r_file_perms;
    allow hwservicemanager hal_btaddr_default:dir search;

    重新编译系统进行验证。

  • 相关阅读:
    制作计算器的代码(C#)
    Oracle如何实现创建数据库、备份数据库及数据导出导入操作
    XmlDocument类
    Android强大的开源库与系统架构工具
    IO
    胎压监测设备
    福施福、爱乐维、玛特纳各成分比较(已换算成同一单位)
    用车不容忽视的细节
    汽车必备车饰和常用物品
    j2ee指导型框架或示例
  • 原文地址:https://www.cnblogs.com/hellokitty2/p/10598227.html
Copyright © 2020-2023  润新知