一、HDI简介

   图 1 OH系统框架图

    HDI(Hardware Device Interface),硬件设备接口,位于基础系统服务层和设备驱动层之间,是连通驱动程序和系统服务进行数据流通的桥梁。是提供给硬件系统服务开发者使用的、统一的硬件设备功能抽象接口,其目的是为系统服务屏蔽南向设备差异。

 

 图 2 HDI原理图

    使用IDL语法描述HDI接口并保存为.idl文件,.idl文件在编译过程中转换为C/C++语言的函数接口声明、客户端与服务端IPC相关过程代码,开发时只需要基于生成的头文件中函数接口实现具体服务功能即可。代码生成与编译功能已经集成在hdi.gni编译模板,基于该编译模板编写idl文件的BUILD.gn就可以简单的生成客户端、服务端代码并编译为共享库。

二、HDI实现

接下来以battery电池接口为例,介绍一下battery HDI接口的实现。

​ 图 3 HDI实现过程

1、使用IDL语法编写 .idl 文件

如drivers/interface/battery/v2_0,是battery2.0版本的接口定义目录。

  • 定义接口IBatteryInterface.idl

//drivers/interface/battery/v2_0/IBatteryInterface.idl
package ohos.hdi.battery.v2_0;

import ohos.hdi.battery.v2_0.Types;
import ohos.hdi.battery.v2_0.IBatteryCallback;

interface IBatteryInterface {

    Register([in] IBatteryCallback event);

    UnRegister();

    ChangePath([in] String path);

    GetCapacity([out] int capacity);

    GetVoltage([out] int voltage);

    GetTemperature([out] int temperature);

    //... ...

}
  • 如果接口中用到了自定义数据类型,将自定义类型定义定义到一个单独的.idl文件,如Types.idl

package ohos.hdi.battery.v2_0;

enum BatteryHealthState
{
    BATTERY_HEALTH_UNKNOWN = 0,
    BATTERY_HEALTH_GOOD,
    BATTERY_HEALTH_OVERHEAT,
    BATTERY_HEALTH_OVERVOLTAGE,
    BATTERY_HEALTH_COLD,
    BATTERY_HEALTH_DEAD,
    BATTERY_HEALTH_RESERVED,
};

enum BatteryChargeState
{
    CHARGE_STATE_NONE = 0,
    CHARGE_STATE_ENABLE,
    CHARGE_STATE_DISABLE,
    CHARGE_STATE_FULL,
    CHARGE_STATE_RESERVED,
};

//... ...
  • 如果需要从服务端回调,可以定义callback接口类,如IBatteryCallback.idl

package ohos.hdi.battery.v2_0;

import ohos.hdi.battery.v2_0.Types;

[callback] interface IBatteryCallback {
    Update([in] struct BatteryInfo event);
}

2、.idl文件编译

.idl文件的编译脚本BUILD.gn:

import("../../../hdf_core/adapter/uhdf2/hdi.gni")
if (defined(ohos_lite)) {
  group("libbattery_proxy_2.0") {
    deps = []
    public_configs = []
  }
} else {
  hdi("battery") {
    module_name = "battery_interface_service"

    sources = [
      "IBatteryCallback.idl",
      "IBatteryInterface.idl",
      "Types.idl",
    ]

    language = "cpp"
    subsystem_name = "hdf"
    part_name = "drivers_interface_battery"
  }
}

在上述步骤中idl编译后将在out/[product_name]/gen/drivers/interface/battery/v2_0目录生成中间代码,如 图 3中间部分所示。

.idl文件在编译过程中会转化成C/C++语言的函数接口声明、客户端与服务端IPC相关过程代码,并编译成库文件,其中:

  • libbattery_proxy_2.0.z.so提供给系统服务层使用

  • libbattery_stub_2.0.z.so供HDI服务使用

图 4 IPC过程代码编译成库文件

3、HDI 服务实现

    .idl文件在编译过程中除了生成C/C++语言的函数接口声明、客户端与服务端IPC相关过程代码,还会生成驱动入口文件和驱动服务实现文件的模板(如 图 3中间部分所示),实际开发中我们需要做的就是参照这两个模板根据实际业务需求将文件重新实现即可(如 图 3右侧目录结构所示)。

  • 实现驱动入口

    HDI服务发布是基于用户态HDF驱动框架,所以需要实现一个驱动入口。驱动实现代码参考已经在out目录中生成,可以根据业务需要直接使用该文件或参考该文件按业务需要重新实现, 然后将驱动入口源码编译为libbattery_driver.z.so

//drivers/peripheral/battery/interfaces/hdi_service/src/battery_interface_driver.cpp
static int32_t BatteryInterfaceDriverDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data,
    struct HdfSBuf *reply)
{
	//... ...

    return hdfBatteryInterfaceHost->stub->SendRequest(cmdId, *dataParcel, *replyParcel, option);
}

static int32_t HdfBatteryInterfaceDriverBind(struct HdfDeviceObject *deviceObject)
{
    auto *hdfBatteryInterfaceHost = new (std::nothrow) HdfBatteryInterfaceHost;
	//... ...

    hdfBatteryInterfaceHost->ioService.Dispatch = BatteryInterfaceDriverDispatch;

    auto serviceImpl = IBatteryInterface::Get(true);
	//... ...
    hdfBatteryInterfaceHost->stub = OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl,
        IBatteryInterface::GetDescriptor());
	//... ...
    deviceObject->service = &hdfBatteryInterfaceHost->ioService;
    return HDF_SUCCESS;
}

static struct HdfDriverEntry g_batteryInterfaceDriverEntry = {
    .moduleVersion = 1,
    .moduleName = "battery_interface_service",
    .Bind = HdfBatteryInterfaceDriverBind,
    .Init = HdfBatteryInterfaceDriverInit,
    .Release = HdfBatteryInterfaceDriverRelease,
};
  • 实现HDI服务接口

    基于工具自动生成的battery_interface_service.h,实现其中的服务接口,并将相关源码编译为libbattery_interface_service_2.0.z.so。

//drivers/peripheral/battery/interfaces/hdi_service/src/battery_interface_impl.cpp
#include "battery_interface_impl.h"
#include "hdf_base.h"
#include "battery_config.h"
#include "battery_log.h"

namespace OHOS {
namespace HDI {
namespace Battery {
namespace V2_0 {
namespace {
sptr<BatteryInterfaceImpl::BatteryDeathRecipient> g_deathRecipient = nullptr;
bool g_isHdiStart = false;
}

//... ...
    
//具体接口功能实现
int32_t BatteryInterfaceImpl::Register(const sptr<IBatteryCallback>& callback)
{
    if (callback == nullptr) {
        BATTERY_HILOGW(FEATURE_BATT_INFO, "callback is nullptr");
        return HDF_ERR_INVALID_PARAM;
    }
    if (!g_isHdiStart) {
        batteryCallback_ = callback;
        loop_->InitCallback(batteryCallback_);

        g_deathRecipient = new BatteryInterfaceImpl::BatteryDeathRecipient(this);
        if (g_deathRecipient == nullptr) {
            BATTERY_HILOGE(COMP_HDI, "Failed to allocate BatteryDeathRecipient");
            return HDF_ERR_MALLOC_FAIL;
        }
        AddBatteryDeathRecipient(batteryCallback_);
        g_isHdiStart = true;
    }
    return HDF_SUCCESS;
}

//... ...
    
int32_t BatteryInterfaceImpl::ChangePath(const std::string& path)
{
    powerSupplyProvider_->SetSysFilePath(path);
    powerSupplyProvider_->InitPowerSupplySysfs();
    return HDF_SUCCESS;
}

int32_t BatteryInterfaceImpl::GetCapacity(int32_t& capacity)
{
    return powerSupplyProvider_->ParseCapacity(&capacity);
}

//... ...

三、HDI使用

1、在需要使用HDI服务的客户端BUILD.gn中增加依赖: "drivers_interface_battery:libbattery_proxy_2.0"

//base/powermgr/battery_manager/services/BUILD.gn
ohos_shared_library("batteryservice") {
  //... ...
  sources = [
    "native/src/battery_callback.cpp",
    "native/src/battery_config.cpp",
    "native/src/battery_dump.cpp",
    "native/src/battery_light.cpp",
    "native/src/battery_notify.cpp",
    "native/src/battery_service.cpp",
  ]
  //... ...
  deps = [
    "${battery_service_zidl}:batterysrv_stub",
    "//third_party/jsoncpp:jsoncpp",
  ]

  external_deps = [ "power_manager:power_permission" ]
  external_deps += [
	//... ...
    "drivers_interface_battery:libbattery_proxy_2.0",
	//... ...
  ]

  subsystem_name = "powermgr"
  part_name = "battery_manager"
}

2、在代码中调用HDI接口

//base/powermgr/battery_manager/services/native/src/battery_service.cpp
#include "v2_0/ibattery_interface.h"
using namespace OHOS::HDI::Battery;

bool BatteryService::RegisterBatteryHdiCallback()
{
    std::lock_guard<std::shared_mutex> lock(mutex_);
    if (iBatteryInterface_ == nullptr) {
        iBatteryInterface_ = V2_0::IBatteryInterface::Get();//获取客户端实例
        BATTERY_HILOGE(COMP_SVC, "failed to get battery hdi interface");
        RETURN_IF_WITH_RET(iBatteryInterface_ == nullptr, false);
    }
    sptr<V2_0::IBatteryCallback> callback = new BatteryCallback();
    ErrCode ret = iBatteryInterface_->Register(callback);//调用服务接口
	//... ...
    return true;
}

 

Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐