接hidl

1.编写hal文件并编译
在hardware/interfaces/目录下创建test文件夹和基版本1.0,这个版本号分为两部分,major.minor。major版本不变得话,只能添加api,不能修改。

创建ITest.hal和types.hal
hardware/interfaces/test/1.0/ITest.hal

package android.hardware.test@1.0;
 
interface ITest
{
  //get led status 
  get() generates (LedStatus result);
  
  
  //set led status 
  set(LedStatus  val) generates(int32_t  ret);
  
  getBrightnessRange() generates(bool ret,BrightnessRange range);
  
  setBrightnessValue(vec<int32_t> range) generates(bool ret);
  
  on() ;
  
  off() ;
 
};

hardware/interfaces/test/1.0/types.hal

package android.hardware.test@1.0;
 
 
enum LedStatus : uint32_t {
    LED_ON,
    LED_OFF,
    LED_BAD_VALUE,
};
 
 
struct BrightnessRange {
    uint32_t min;
 
    uint32_t max;
};

添加完后,设置环境变量之后,执行./hardware/interfaces/update-makefiles.sh 会自动生成编译编译脚本,然后在

hardware/interfaces/test/1.0/ 路径下执行mm,会生成所需要得hidl库,接下来我们需要实现hidl interface,供client调用。

2. 实现Hidl Interface
首先实现ITest interface的子类testImpl 得头文件和对应得cpp。

hardware/interfaces/test/1.0/default/testImpl.h

#ifndef ANDROID_HARDWARE_LED_V1_0_LED_H
#define ANDROID_HARDWARE_LED_V1_0_LED_H
#include <android/hardware/test/1.0/ITest.h>
 
#include <hidl/Status.h>
 
#include <hidl/MQDescriptor.h>
 
 
 
 
namespace android {
namespace hardware {
namespace test {
namespace V1_0 {
namespace implementation {
 
using ::android::hardware::test::V1_0::LedStatus;
using ::android::hardware::test::V1_0::BrightnessRange;
using ::android::hardware::test::V1_0::ITest;
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::sp;
    
    
struct testImpl : public ITest {
    public:
        testImpl();
        Return<LedStatus>  get() override ;
        Return<int32_t> set(LedStatus val) override;
        Return<void> on() override;
        Return<void> off() override;
        Return<void> getBrightnessRange(getBrightnessRange_cb _hidl_cb) override;
        Return<bool> setBrightnessValue(const hidl_vec<int32_t>& range) override;
    private:
        LedStatus state;
};
    
extern "C" ITest* HIDL_FETCH_ITest(const char* name);
}  // namespace implementation
}  // namespace V1_0
}  // namespace test
}  // namespace hardware
}  // namespace android
 
#endif //ANDROID_HARDWARE_LED_V1_0_LED_H

testImpl.cpp

#define LOG_TAG "TestService"
 
#include <log/log.h>
#include "testImpl.h"
 
namespace android {
namespace hardware {
namespace test {
namespace V1_0 {
namespace implementation {
 
testImpl::testImpl() {
    state = LedStatus::LED_BAD_VALUE;
    ALOGE("testImpl Init status:%d", state);
}
 
Return<void> testImpl::on() {
    state = LedStatus::LED_ON;
    ALOGE("testImpl on status:%d", state);
    return Void();
}
 
Return<void> testImpl::off() {
    state = LedStatus::LED_OFF;
    ALOGE("testImpl off status:%d", state);    
    return Void();
}
 
Return<LedStatus>  testImpl::get() {
    return state;
}
Return<int32_t> testImpl::set(LedStatus val) {
    if(val == LedStatus::LED_OFF || val == LedStatus::LED_ON)
        state = val;
    else
        return -1;
    return 0;
}
 
Return<void> testImpl::getBrightnessRange(getBrightnessRange_cb _hidl_cb)
{
    ALOGE("testImpl getBrightnessRange ");
    BrightnessRange range;
    range.max = 100;
    range.min = 1;
    _hidl_cb(true,range);
    return Void();
    
}
  
Return<bool> testImpl::setBrightnessValue(const hidl_vec<int32_t>& range)
{
    ALOGE("testImpl getBrightnessValue ");
    auto iter = range.begin();
    ALOGE("testImpl getBrightnessValue range.begin: %d",*iter);
    iter = range.end();
    ALOGE("testImpl getBrightnessValue range.end: %d",*iter);
    ALOGE("testImpl getBrightnessValue range.size: %zu",range.size());
    return true;
}
 
ITest* HIDL_FETCH_ITest(const char * /*name*/) {
    ALOGE("testImpl HIDL_FETCH_ITest ");    
    return new testImpl();
}
 
}  // namespace implementation
}  // namespace V1_0
}  // namespace test
}  // namespace hardware
}  // namespace android

Android.dp

cc_library_shared {
    name: "android.hardware.test@1.0-impl",
    defaults: ["hidl_defaults"],
    srcs: ["testImpl.cpp"],
    shared_libs: [
        "libhidlbase",
        "libhidltransport",
        "libhardware",
        "liblog",
        "libutils",
        "android.hardware.test@1.0",
    ], 
}
 
cc_binary {
    name: "android.hardware.test@1.0-service",
    init_rc: ["android.hardware.test@1.0-service.rc"],
    srcs: ["service.cpp",
      "testImpl.cpp"],
 
    shared_libs: [
        "liblog",
        "libhardware",
        "libhidlbase",
        "libhidltransport",
        "libutils",
        "android.hardware.test@1.0",
    ], 
 
}

3. 编写hdil service
接下来,使用相应功能填写存根并设置守护进程。可以使用passthrough方式和binder方式,示例:

hardware/interfaces/test/1.0/default/service.cpp

 
 #define LOG_TAG "android.hardware.test@1.0-service"
 
#include <android/hardware/test/1.0/ITest.h>
#include <hidl/LegacySupport.h>
#include "testImpl.h"
using android::hardware::test::V1_0::ITest;
using android::hardware::test::V1_0::implementation::testImpl;
using android::hardware::defaultPassthroughServiceImplementation;
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
using android::sp;
 
 
int main() {
#if 0 
// Passthrough   dlopen so方式
    return defaultPassthroughServiceImplementation<Itest>(); 
#else
// Binder 方式
  sp<ITest> service = new testImpl();
  configureRpcThreadpool(1, true /*callerWillJoin*/);
    if(android::OK !=  service->registerAsService())
      return 1; 
    joinRpcThreadpool();
#endif
}


4. 配置manifest.xml
add the code to the manifest.xm 以至于hwservicemanager 查找到指定的hidl service

About HIDL configures

system/libhidl/manifest.xml

    <hal format="hidl">
    <name>android.hardware.test</name>
    <transport>hwbinder</transport>  <!--//hwbinder 或者passthrough (直通模式)-->  
    <version>1.0</version>
    <interface>
     <name>ITest</name>
     <instance>default</instance>
    </interface>
   </hal>
1
2
3
4
5
6
7
8
9
5. hidl client端调用
hidl service运行后,可以通过C++和Java两种方式调用,非常方便,通过java直接访问,就省去了jni。

5.1 实现java调用hidl service的例子
将以下内容添加到 Android.mk 中:

 LOCAL_JAVA_LIBRARIES += android.hardware.test-V1.0-java
1
或将以下内容添加到 Android.bp 中:

  shared_libs: [
   /* … */
   "android.hardware.test-V1.0-java",
  ],
1
2
3
4
该库还存在静态版:android.hardware.test-V1.0-java-static。

将以下内容添加到您的 Java 文件中:

  import android.hardware.test.V1_0.ITest;
  ...
  // retry to wait until the service starts up if it is in the manifest
  ITest server = ITest.getService(true /* retry */); // throws NoSuchElementException if not available
  server.on();
1
2
3
4
5
5.2 实现C++ 调用hidl service的例子
首先将 HAL 库添加到 makefile 中:

  Make:LOCAL_SHARED_LIBRARIES += android.hardware.test@1.0
  Soong:shared_libs: [ …, android.hardware.test@1.0 ]
1
2
接下来,添加 HAL 头文件:

  #include <android/hardware/test/1.0/ITest.h>
  …
  // in code:
  sp<ITest> client = ITest::getService();
  client->on();
1
2
3
4
5
下面是Demo clinet
 #define LOG_TAG "TEST_CLINET"
#include <android/hardware/test/1.0/ITest.h>
#include <log/log.h>
 
using android::hardware::test::V1_0::ITest;
using android::hardware::test::V1_0::LedStatus;
using android::hardware::test::V1_0::BrightnessRange;
using android::hardware::hidl_vec;
using android::sp;
 
 
int main(){
    // BrightnessRange range;
    sp<ITest> service = ITest::getService();
    if( service == nullptr ){
        ALOGE("Can't find ITest service...");
        return -1;
    }
    ALOGE("ITest ON");
    service->on();
    
    ALOGE("ITest OFF");
    service->off();
    
    ALOGE("ITest set");
    service->set(LedStatus::LED_ON);
 
    ALOGE("ITest get");
    LedStatus ret = service->get();
    ALOGE("ITest get: %d",ret);
    
    service->getBrightnessRange([](bool ret1,BrightnessRange range){
        ALOGE("ITest getBrightnessRange ret: %d",ret1);
        ALOGE("ITest getBrightnessRange Max: %d",range.max);
        ALOGE("ITest getBrightnessRange Min: %d",range.min);
    });
    int32_t array[] = {5, 6, 7};
    hidl_vec<int32_t> hv1 = std::vector<int32_t>(array, array + 3);
    bool ret2 = service->setBrightnessValue(hv1);
    ALOGE("ITest getBrightnessValue bool: %d",ret2);
    return 0;
}

参考

具体步骤
1. 创建目录
    cd  hardware/interfaces
    mkdir -p test/1.0
2. 定义hal接口Itest.hal
    package android.hardware.test@1.0;
    interface Itest {
        setData(YeData data) generates (YeStatus ret);
        getData() generates (YeData ret);
    };
    
    定义数据类型types.hal
    package android.hardware.test@1.0;

    enum YeStatus : int32_t {
        SUCCESS = 1,
        FAILED,
    };

    struct YeData {
        int32_t x;
        int32_t y;
    };
3. 根据.hal自动生成impl库的cpp实现
    make hidl-gen
    在hardware/interfaces/test/1.0目录执行hidl-gen命令:
    PACKAGE=android.hardware.test@1.0
    LOC= default/impl
    hidl-gen -o $LOC -Lc++-impl -r android.hardware:hardware/interfaces $PACKAGE 
4. 生成impl的Android.bp
    hidl-gen -o default -Landroidbp-impl -r android.hardware:hardware/interfaces $PACKAGE
5. 生成hidl的Android.bp
    执行hardware/interfaces/update-makefiles.sh
6. 修改device/fsl/imx8q/XXX/manifest.xml
    添加以下代码:
        <hal format="hidl">
            <name>android.hardware.test</name>
            <transport>hwbinder</transport>
            <version>1.0</version>
            <interface>
                <name>Itest</name>
                <instance>default</instance>
            </interface>
        </hal>
7. 编写.rc文件
    配置自启动
    service vendor.test-1.0 /vendor/bin/hw/android.hardware.test@1.0-service
        class hal
        user system
        group system
8. 添加PRODUCT_PACKAGES
    在device/fsl/imx8q/XXX/XXX.mk中新增
    打包.so和service到vendor.img
    # Yetest HAL
    PRODUCT_PACKAGES += \
         android.hardware.test@1.0-impl \
         android.hardware.test@1.0-service
9. device/fsl/imx8q/XXX/BoardConfig.mk中指定sepolicy路径:
    BOARD_SEPOLICY_DIRS +=  hardware/interfaces/test/sepolicy
10. 在hardware/interfaces/test/sepolicy目录新增test.te:
    type test, domain;
        
    type test_exec, exec_type, vendor_file_type, file_type;
    hwbinder_use(test);
    init_daemon_domain(test)
    add_hwservice(test,test_hwservice)
        
    allow test hwservicemanager_prop:file {read open getattr map};
    allow test system_file:dir {read open getattr search};
11. hardware/interfaces/test/sepolicy目录下新增file_contexts:
    绑定android.hardware.test@1.0-service与test_exec的关系的关键
    /(vendor|system/vendor)/bin/hw/android\.hardware\.test@1\.0-service    u:object_r:test_exec:s0
    /(vendor|system/vendor)/lib(64)?/hw/android\.hardware\.test@1\.0-impl\.so     u:object_r:same_process_hal_file:s0
12. 新增harware/interfaces/test/sepolicy/hwservice_contexts:
    android.hardware.test::Itest u:object_r:test_hwservice:s0
13. 新增harware/interfaces/test/sepolicy/hwservice.te:
    type test_hwservice, hwservice_manager_type;
————————————————
版权声明:本文为CSDN博主「_dowork」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/q1183345443/article/details/82862811

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值