zoukankan      html  css  js  c++  java
  • 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;

    重新编译系统进行验证。

  • 相关阅读:
    阿里消息队列中间件 RocketMQ 源码分析 —— Message 拉取与消费(上)
    数据库中间件 ShardingJDBC 源码分析 —— SQL 解析(三)之查询SQL
    数据库分库分表中间件 ShardingJDBC 源码分析 —— SQL 解析(六)之删除SQL
    数据库分库分表中间件 ShardingJDBC 源码分析 —— SQL 解析(五)之更新SQL
    消息队列中间件 RocketMQ 源码分析 —— Message 存储
    源码圈 300 胖友的书单整理
    数据库分库分表中间件 ShardingJDBC 源码分析 —— SQL 路由(一)分库分表配置
    数据库分库分表中间件 ShardingJDBC 源码分析 —— SQL 解析(四)之插入SQL
    数据库分库分表中间件 ShardingJDBC 源码分析 —— SQL 路由(二)之分库分表路由
    C#中Math类的用法
  • 原文地址:https://www.cnblogs.com/hellokitty2/p/10598227.html
Copyright © 2011-2022 走看看