openharmony 3.2 Release HDF的IDL文件初探(上) 原创

motilyfor
发布于 2022-10-24 02:31
浏览
1收藏

1.IDL

安卓上我们熟知的aidl能够帮我们快速生成binder的代码,openharmony上也提供了此功能,用法与aidl相似.与安卓不同的地方以及和openharmony 3.1不同的是:

  1. 不再需要在代码中分别引入proxy和sub,只需要在deps中是加入不同的包

  2. idl文件也与服务端解耦,需要单独编写bundle.json.

1. IDL 声明和引入.

1.IDL的bundle.json: drivers\interface\location\gnss\bundle.json

        "inner_kits": [
          {
            "name": "//drivers/interface/location/gnss/v1_0:liblocation_gnss_proxy_1.0",
            "header": {
              "header_files": [
              ],
              "header_base": "//drivers/interface/location/gnss"
            }
          },
          {
            "name": "//drivers/interface/location/gnss/v1_0:location_gnss_idl_headers",
            "header": {
              "header_files": [
              ],
              "header_base": "//drivers/interface/location/gnss"
            }
          }
        ]

2.proxy端引入:base\location\services\location_gnss\gnss\BUILD.gn

  external_deps = [
    ...
    "drivers_interface_location_agnss:liblocation_agnss_proxy_1.0",
    "drivers_interface_location_gnss:liblocation_gnss_proxy_1.0",
    ...
  ]

3.service端引入:drivers\peripheral\location\gnss\hdi_service\BUILD.gn

    external_deps = [
      "drivers_interface_location_agnss:location_gnss_idl_headers",
      ...
    ] 

2.IDL 文件编写

先看readme.md,可以简单了解一下idl文件规则 OpenHarmony IDL工具规格及使用说明书.目前openharmony文档内容有点少,但是hdf中已经在使用,可能还没给上层开放.这里用的是harmonyOS的介绍:

IDL文件编写规范

一个 HarmonyOS IDL 文件只能定义一个接口类,接口定义的形式使用 BNF 范式描述,示例如下:

<*interface_attributes_declaration*> ? interface <*interface_name_with_namespace*> { <*method_declaration*> ? }

<u><interface_attributes_declaration>是接口属性声明,当前支持 oneway、callback、full、lite 属性:</u>(openharmony的文档中只有oneway)

  1. oneway:表示该接口中的方法都是单向方法,即调用方法后不用等待该方法执行即可返回,该属性为可选项,如果无声明,则默认为同步调用方法
  2. callback:表示该接口为callback接口,即从下层实现中回调到上层服务中;
  3. full、lite:表示该接口在重量级部署或轻量级部署中使用。如果无声明,则默认为重量级、轻量级部署中都会使用。

<u><interface_name_with_namespace>是接口名声明,接口名需包含完整的命名空间,且必须包含方法声明,不允许出现空接口。接口示例:</u>

[oneway] interface ohos.app.IAbilityManager {
   	    ……
};

<u><method_declaration>是方法声明,形式为:</u>

<*method_attributes_declaration*> ? <*result type*> <*method declarator*>

<u><method_attributes_declaration>是方法属性声明,当前支持 oneway 、full、lite 属性:</u>

  1. oneway:表示该方法是单向方法,即调用方法后不用等待该方法执行即可返回;
  2. full、lite:表示该方法在重量级部署或轻量级部署中使用。如果无声明,则默认为重量级、轻量级部署中都会使用。

<u><result type>是返回类型,<method declarator>是方法名和各个参数声明,参数声明的形式为:</u>

\[ <*formal_parameter_attribute*> \] <*type*> <*identifier*>

<u><formal_parameter_attribute>的值为“in”、“out”或“inout”,分别表示该参数是输入参数、输出参数或输入输出参数。oneway 方法不允许有输出参数(包含输入输出参数)和返回值。方法示例:</u>

   	void SetBundles([in] Map<String, BundleInfo> bundleInfos,  [in, out] int number);
   	[oneway] void Dump([in] ParcelableFileDescriptor fd,  [in] long flags);

IDL主要三个内容:数据类型,callback,接口
├── bundle.json
└── v1_0
├── BUILD.gn # idl文件编译脚本
├── GnssTypes.idl # 数据类型定义idl文件
├── IGnssCallback.idl # callback 接口定义idl文件
└── IGnssInterface.idl # interface 接口定义idl文件

1. 数据类型定义 GnssTypes.idl

这里仅简单列举一些:

package ohos.hdi.location.gnss.v1_0;

enum GnssWorkingMode	// 枚举类型
{
    GNSS_WORKING_MODE_STANDALONE = 1,
    ...
};

struct SatelliteStatusInfo {	// 结构体
    unsigned int satellitesNumber;	
    short[] satelliteIds;
    enum GnssConstellationType[] constellation;
    float[] carrierToNoiseDensitys;
	// ...
};

// ...

struct GnssRefInfo {
    enum GnssRefInfoType type;
    struct GnssRefTime time;
    struct GnssRefLocation location;
    struct LocationInfo best_location;
};

2. callback定义IGnssCallback.idl

[callback] 表示该接口为callback接口,即从下层实现中回调到上层服务中;

package ohos.hdi.location.gnss.v1_0;

import ohos.hdi.location.gnss.v1_0.GnssTypes;

[callback] interface IGnssCallback {
    ReportLocation([in] struct LocationInfo location);
    ReportGnssWorkingStatus([in] enum GnssWorkingStatus status);
    ReportNmea([in] long timestamp, [in] String nmea, [in] int length);
    ReportGnssCapabilities([in] enum GnssCapabilities capabilities);
    ReportSatelliteStatusInfo([in] struct SatelliteStatusInfo info);
    RequestGnssReferenceInfo([in] enum GnssRefInfoType type);
    RequestPredictGnssData();
    ReportCachedLocation([in] struct LocationInfo[] gnssLocations);
}

3. interface定义

package ohos.hdi.location.gnss.v1_0;

import ohos.hdi.location.gnss.v1_0.IGnssCallback;
import ohos.hdi.location.gnss.v1_0.GnssTypes;

interface IGnssInterface {
    SetGnssConfigPara([in] struct GnssConfigPara para);
    EnableGnss([in] IGnssCallback callbackObj);
    DisableGnss();
    StartGnss([in] enum GnssStartType type);
    StopGnss([in] enum GnssStartType type);
    SetGnssReferenceInfo([in] struct GnssRefInfo refInfo);
    DeleteAuxiliaryData([in] enum GnssAuxiliaryData data);
    SetPredictGnssData([in] String data);
    GetCachedGnssLocationsSize([out] int size);
    GetCachedGnssLocations();
}

4. BUILD.gn编译文件编写

import("//drivers/hdf_core/adapter/uhdf2/hdi.gni")
hdi("location_gnss") {
  module_name = "location_gnss"
  sources = [
    "GnssTypes.idl",
    "IGnssCallback.idl",
    "IGnssInterface.idl",
  ]

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

3. IDL服务端实现

drivers\peripheral\location\gnss\hdi_service\gnss_interface_impl.h

客户端服务端头文件现在统一到一个ixxx_interface.h头文件中,在openharmony 3.1客户端是xxx_proxy.h,服务端是xxx_stub.h

#include "v1_0/ignss_interface.h"

namespace OHOS {
namespace HDI {
namespace Location {
namespace Gnss {
namespace V1_0 {
class GnssInterfaceImpl : public IGnssInterface {
public:
    GnssInterfaceImpl();
    virtual ~GnssInterfaceImpl();
    int32_t SetGnssConfigPara(const GnssConfigPara& para) override;
    int32_t EnableGnss(const sptr<IGnssCallback>& callbackObj) override;
    int32_t DisableGnss() override;
    int32_t StartGnss(GnssStartType type) override;
    int32_t StopGnss(GnssStartType type) override;
    int32_t SetGnssReferenceInfo(const GnssRefInfo& refInfo) override;
    int32_t DeleteAuxiliaryData(GnssAuxiliaryData data) override;
    int32_t SetPredictGnssData(const std::string& data) override;
    int32_t GetCachedGnssLocationsSize(int32_t& size) override;
    int32_t GetCachedGnssLocations() override;
};
} // V1_0
} // Gnss
} // Location
} // HDI
} // OHOS

在HDF_INIT的地方还是要使用

drivers\peripheral\location\gnss\hdi_service\gnss_interface_driver.cpp

#include "v1_0/gnss_interface_stub.h"

<details> <summary>3.1和3.2头文件对比</summary>
这里对比一下thermal<br>
drivers\peripheral\thermal\interfaces\hdi_service\include\thermal_interface_impl.h<br>
3.2<br>
#include “v1_0/ithermal_interface.h”<br>
namespace OHOS {<br>
namespace HDI {<br>
namespace Thermal {<br>
namespace V1_0 {<br>
class ThermalInterfaceImpl : public IThermalInterface {<br><br>
3.1<br>
#include “v1_0/thermal_interface_stub.h”<br>
namespace OHOS {<br>
namespace HDI {<br>
namespace Thermal {<br>
namespace V1_0 {<br>
class ThermalInterfaceImpl : public ThermalInterfaceStub { <br>
</details>

具体实现在 drivers\peripheral\location\gnss\hdi_service\gnss_interface_impl.cpp,本文只看idl,所以不涉及细节了

4. IDL客户端

#include <v1_0/ignss_interface.h>
gnssInterface_ = IGnssInterface::Get();

下一篇聊聊idl生成的文件,其实跟aidl生成的东西差不多,都是封装binder

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2022-10-24 10:17:53修改
3
收藏 1
回复
举报
2条回复
按时间正序
/
按时间倒序
Haoc_小源同学
Haoc_小源同学

请问一下IDL的作用是什么?在什么场景需要用到

回复
2023-3-31 09:42:40
motilyfor
motilyfor 回复了 Haoc_小源同学
请问一下IDL的作用是什么?在什么场景需要用到

目前只看到framework层和hdf driver的service进行ipc通信的时候用

跟android的hidl是差不多的东西

1
回复
2023-4-18 12:17:45
回复
    相关推荐