Android 之 Binder机制HIDL接口

1.HIDL 介绍

HIDL(HAL interface definition language),HAL 接口定义语言是用于指定 HAL 层和其用户之间的

接口的一种接口描述语言(IDL)。HIDL 允许指定类型和方法调用。从更广泛的意义上来说,HIDL

是用于在独立编程的代码库之间通信的系统。

https://source.android.com/devices/architecture/hidl

2.实现自己的一个HIDL

本文以LED为例在aosp上添加HIDL,以熟悉整个过程。

在hardware/interfaces/目录下创建led文件夹和基版本1.0,这个版本号分为两部分,major.minor。

major版本不变得话,只能添加api,不能修改。

创建ILed.hal和types.hal

hardware/interfaces/led/1.0/ILed.hal

package android.hardware.led@1.0;
 
interface ILed
{
  //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/led/1.0/types.hal

package android.hardware.led@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/led/1.0/ 路径下执行mm,会生成所需要得hidl库,接下来我们需要实现hidl

interface,供client调用。

3.实现Hidl Interface

首先实现ILed interface的子类ledImpl 得头文件和对应得cpp。

hardware/interfaces/led/1.0/default/ledImpl.h

#ifndef ANDROID_HARDWARE_LED_V1_0_LED_H
#define ANDROID_HARDWARE_LED_V1_0_LED_H
#include <android/hardware/led/1.0/ILed.h>
 
#include <hidl/Status.h>
 
#include <hidl/MQDescriptor.h>
 
 
 
 
namespace android {
namespace hardware {
namespace led {
namespace V1_0 {
namespace implementation {
 
using ::android::hardware::led::V1_0::LedStatus;
using ::android::hardware::led::V1_0::BrightnessRange;
using ::android::hardware::led::V1_0::ILed;
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 ledImpl : public ILed {
	public:
		ledImpl();
		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" ILed* HIDL_FETCH_ILed(const char* name);
}  // namespace implementation
}  // namespace V1_0
}  // namespace led
}  // namespace hardware
}  // namespace android
 
#endif //ANDROID_HARDWARE_LED_V1_0_LED_H

hardware/interfaces/led/1.0/default/ledImpl.cpp

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

hardware/interfaces/led/1.0/default/Android.bp

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

4.编写hdil service

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

例:hardware/interfaces/led/1.0/default/service.cpp

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

5.配置manifest.xml

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

   About HIDL configures

   device/<vendorxxx>/<devicexxx>/manifest.xml

 <hal format="hidl">
    <name>android.hardware.led</name>
    <transport>hwbinder</transport>  //hwbinder 或者passthrough (直通模式)  
    <version>1.0</version>
    <interface>
     <name>ILed</name>
     <instance>default</instance>
    </interface>
   </hal>

5.hidl client端调用

实现C++ 调用hidl service的例子:首先将 HAL 库添加到 makefile 中

  Make:LOCAL_SHARED_LIBRARIES += android.hardware.led@1.0
  Soong:shared_libs: [ …, android.hardware.led@1.0 ]

接下来,添加 HAL 头文件:

  #include <android/hardware/led/1.0/ILed.h>
  …
  // in code:
  sp<ILed> client = ILed::getService();
  client->on();

下面是我的Demo clinet

 #define LOG_TAG "LED_CLINET"
#include <android/hardware/led/1.0/ILed.h>
#include <log/log.h>
 
using android::hardware::led::V1_0::ILed;
using android::hardware::led::V1_0::LedStatus;
using android::hardware::led::V1_0::BrightnessRange;
using android::hardware::hidl_vec;
using android::sp;
 
 
int main(){
	// BrightnessRange range;
	sp<ILed> service = ILed::getService();
	if( service == nullptr ){
		ALOGE("Can't find ILed service...");
		return -1;
	}
	ALOGE("ILed ON");
	service->on();
	
	ALOGE("ILed OFF");
	service->off();
	
	ALOGE("ILed set");
	service->set(LedStatus::LED_ON);
 
	ALOGE("ILed get");
	LedStatus ret = service->get();
	ALOGE("ILed get: %d",ret);
	
	service->getBrightnessRange([](bool ret1,BrightnessRange range){
		ALOGE("ILed getBrightnessRange ret: %d",ret1);
		ALOGE("ILed getBrightnessRange Max: %d",range.max);
		ALOGE("ILed 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("ILed getBrightnessValue bool: %d",ret2);
	return 0;
}

参考:

在Android 8.0之后版本上添加Hidl Service_anlory的博客-CSDN博客

Android HIDL 介绍学习_Super Jang的博客-CSDN博客_安卓hidl
 

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
添加HIDL接口,你需要按照以下步骤进行操作: 1. 创建一个新的HIDL接口文件,它应该包含你想要添加的新接口的定义。例如,如果你想添加一个名为“IMyInterface”的新接口,则应该创建一个名为“IMyInterface.hidl”的文件。 2. 在该文件中定义你的接口方法,例如: ``` interface IMyInterface { void myMethod(int32_t arg1, int32_t arg2); }; ``` 这将定义一个名为“myMethod”的方法,它接受两个整数参数。 3. 在你的HIDL服务中实现新接口方法。这通常涉及创建一个新的C++类来实现你的接口,并将其添加到你的服务中。 4. 在你的服务的main函数中注册新的接口。这可以通过调用registerAsService函数来完成,例如: ``` sp<IMyInterface> myInterface = new MyInterfaceImpl(); status_t status = myInterface->registerAsService(); if (status != OK) { ALOGE("Could not register MyInterface service (%d).", status); return -1; } ``` 这将创建一个名为“MyInterface”的服务,并将其注册到系统服务管理器中。 5. 在你的客户端应用程序中使用新接口。这通常涉及使用getService函数获取对接口的引用,并调用其方法。例如: ``` sp<IMyInterface> myInterface = IMyInterface::getService(); if (myInterface == nullptr) { ALOGE("Could not get MyInterface service."); return -1; } myInterface->myMethod(42, 24); ``` 这将获取名为“MyInterface”的服务的引用,并调用其“myMethod”方法,将42和24作为参数传递。 以上是添加HIDL接口的基本步骤,你可以根据你的具体需求进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式_笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值