欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android P HIDL demo代码编写 (原创)

程序员文章站 2022-03-18 16:57:47
之前的文章已经分析了HIDL服务的注册和调用,这篇文章来总结下一个HIDL的服务如何编写。 缩写HAL文件 首先要确认放置文件夹和接口的包名,因为这跟后面使用脚本生成一部分代码有关,一般默认的放在hardware/interfaces目录下,我们写一个简单的IDemo.hal (hardware/i ......

之前的文章已经分析了hidl服务的注册和调用,这篇文章来总结下一个hidl的服务如何编写。

缩写hal文件

 首先要确认放置文件夹和接口的包名,因为这跟后面使用脚本生成一部分代码有关,一般默认的放在hardware/interfaces目录下,我们写一个简单的idemo.hal (hardware/interface/demo/1.0/idemo.hal)

package android.hardware.demo@1.0;

interface idemo {
    init(int32_t level) generates (int32_t initret);

    getproperty(string key) generates (int32_t getresult, string value);
};

 生成接口的执行代码

使用如下命令生成执行文件:

hidl-gen -o hardware/interfaces/demo/1.0/default -lc++-impl -randroid.hardware:hardware/intefaces -randroid.hidl:system/libhidl/transport android.hardware.demo@1.0

这个命令会在hardware/interfaces/demo/1.0/default 下生成demo.cpp 和 demo.h两个文件,上面那个接口文件里,getproperty里有两个返回值,一般函数都只有一个返回值,那这个两个返回值是回事呢?那我们看看生成的执行代码是怎么样的?

#include "demo.h"

namespace android {
namespace hardware {
namespace demo {
namespace v1_0 {
namespace implementation {

return<int32_t> demo::init(int32_t level) {
//这种返回一个参数就按普通函数的做法,返回值就ok return int32_t{}; } return<void> demo::getproperty(const hidl_string& key, getproperty_cb _hidl_cb ) { //这里将两个返回值封装到一个回调函数里,然后传给调用者,使用如下 int result = 0; //使用map 里值来返回
  std::map<hidl_string, hidl_string> demomap = {
    {"one", "first"},
    {"two", "second"},
    {"three", "third"}
  };

  int result = -1;
  hidl_string value = "";
  auto findret = demomap.find(key);
  if(findret != demomap.end()){
    result = 0;
    value = findret->second;
  }
  //这里就将result 和 value 作为参数直接回调给调用者
  _hidl_cb(result, value); return void(); } } } } }

生成android.bp

方法实现完了之后,就需要用命令再生成一个android.bp

hidl-gen -o hardware/interfaces/demo/1.0/default -landroidbp-impl -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.demo@1.0

执行命令之后,就会在hardeare/interfaces/demo/1.0/default/android.bp

进入hardware/interface目录下,执行./update-makefiles.sh之后,会生成demo/1.0/android.bp 文件

现在有了两个android.bp之后,需要采用绑定模式来创建一个demo服务,在demo/1.0/default下创建一个service.cpp

添加绑定模式的服务代码

#include <android-base/logging.h>
#include <hidl/hidltransportsupport.h>
#include <android/hardware/demo/1.0/idemo.h>

#undef log_tag
#define log_tag "android.hardware.demo@1.0-service"

#include <hidl/legacysupport.h>
#include "demo.h"
using android::hardware::configurerpcthreadpool;
using android::hardware::joinrpcthreadpool;
using android::hardware::demo::v1.0::implementation::demo;

int main(){
    configurerpcthreadpool(4, true);
    demo demo = new demo();
    auto status = demo.registerasservice();
    if(status != android::ok){
        aloge("register demo as service failed");
        return -1;
    }
    joinrpcthreadpool();
}

 然后再在demo/1.0/default下创建android.hardware.demo@1.0-service.rc

service demo_hal_service /vendor/bin/hw/android.hardware.demo@1.0-service
    class hal
    user  system
    group  system

在demo/1.0/default/android.bp中增加 init_rc和 service.cpp的编译项,并将cc_library_shared 改为 cc_binary ,具体如下:

cc_binary {
    name: "android.hardware.demo@1.0-service",
    relative_install_path: "hw",
    proprietary: true,
    init_rc: ["android.hardware.demo@1.0-service.rc"],
    srcs: [
        "demo.cpp",
        "service.cpp"
    ],  
    shared_libs: [
        "libhidlbase",
        "libhidltransport",
        "libutils",
     "liblog", "android.hardware.demo@1.0", ], }

 然后通过mmm 或 mm 的方式 就可以编译出android.hardware.demo@1.0-service 和 android.hardware.demo@1.0-service.rc的服务了。

如果要自运行,添加上selinux 的相关权限,可以参考其它hidl 服务的selinux。

关于调用hidl的接口,之前文章分析过,下面我们写核心的几句代码:

#include <android/hardware/demo/1.0/idemo.h>
sp<idemo> mdemo = idemo::getservice();
mdemo->init(1);
string mvalue;
mdemo->getproperty("two", [&](int result, string value) {
       if(result == 0)
             mvaule = value;
});

到这里,hidl的demo服务代码可以结束了,后面可以增加复杂的icallback hidl接口相关的代码。